diff options
156 files changed, 6696 insertions, 1208 deletions
diff --git a/Documentation/devicetree/bindings/sound/soc/codecs/fsl-sgtl5000.txt b/Documentation/devicetree/bindings/sound/soc/codecs/fsl-sgtl5000.txt new file mode 100644 index 000000000000..2c3cd413f042 --- /dev/null +++ b/Documentation/devicetree/bindings/sound/soc/codecs/fsl-sgtl5000.txt | |||
@@ -0,0 +1,11 @@ | |||
1 | * Freescale SGTL5000 Stereo Codec | ||
2 | |||
3 | Required properties: | ||
4 | - compatible : "fsl,sgtl5000". | ||
5 | |||
6 | Example: | ||
7 | |||
8 | codec: sgtl5000@0a { | ||
9 | compatible = "fsl,sgtl5000"; | ||
10 | reg = <0x0a>; | ||
11 | }; | ||
diff --git a/Documentation/devicetree/bindings/sound/wm8510.txt b/Documentation/devicetree/bindings/sound/wm8510.txt new file mode 100644 index 000000000000..fa1a32b85577 --- /dev/null +++ b/Documentation/devicetree/bindings/sound/wm8510.txt | |||
@@ -0,0 +1,18 @@ | |||
1 | WM8510 audio CODEC | ||
2 | |||
3 | This device supports both I2C and SPI (configured with pin strapping | ||
4 | on the board). | ||
5 | |||
6 | Required properties: | ||
7 | |||
8 | - compatible : "wlf,wm8510" | ||
9 | |||
10 | - reg : the I2C address of the device for I2C, the chip select | ||
11 | number for SPI. | ||
12 | |||
13 | Example: | ||
14 | |||
15 | codec: wm8510@1a { | ||
16 | compatible = "wlf,wm8510"; | ||
17 | reg = <0x1a>; | ||
18 | }; | ||
diff --git a/Documentation/devicetree/bindings/sound/wm8523.txt b/Documentation/devicetree/bindings/sound/wm8523.txt new file mode 100644 index 000000000000..04746186b283 --- /dev/null +++ b/Documentation/devicetree/bindings/sound/wm8523.txt | |||
@@ -0,0 +1,16 @@ | |||
1 | WM8523 audio CODEC | ||
2 | |||
3 | This device supports I2C only. | ||
4 | |||
5 | Required properties: | ||
6 | |||
7 | - compatible : "wlf,wm8523" | ||
8 | |||
9 | - reg : the I2C address of the device. | ||
10 | |||
11 | Example: | ||
12 | |||
13 | codec: wm8523@1a { | ||
14 | compatible = "wlf,wm8523"; | ||
15 | reg = <0x1a>; | ||
16 | }; | ||
diff --git a/Documentation/devicetree/bindings/sound/wm8580.txt b/Documentation/devicetree/bindings/sound/wm8580.txt new file mode 100644 index 000000000000..7d9821f348da --- /dev/null +++ b/Documentation/devicetree/bindings/sound/wm8580.txt | |||
@@ -0,0 +1,16 @@ | |||
1 | WM8580 audio CODEC | ||
2 | |||
3 | This device supports I2C only. | ||
4 | |||
5 | Required properties: | ||
6 | |||
7 | - compatible : "wlf,wm8580" | ||
8 | |||
9 | - reg : the I2C address of the device. | ||
10 | |||
11 | Example: | ||
12 | |||
13 | codec: wm8580@1a { | ||
14 | compatible = "wlf,wm8580"; | ||
15 | reg = <0x1a>; | ||
16 | }; | ||
diff --git a/Documentation/devicetree/bindings/sound/wm8711.txt b/Documentation/devicetree/bindings/sound/wm8711.txt new file mode 100644 index 000000000000..8ed9998cd23c --- /dev/null +++ b/Documentation/devicetree/bindings/sound/wm8711.txt | |||
@@ -0,0 +1,18 @@ | |||
1 | WM8711 audio CODEC | ||
2 | |||
3 | This device supports both I2C and SPI (configured with pin strapping | ||
4 | on the board). | ||
5 | |||
6 | Required properties: | ||
7 | |||
8 | - compatible : "wlf,wm8711" | ||
9 | |||
10 | - reg : the I2C address of the device for I2C, the chip select | ||
11 | number for SPI. | ||
12 | |||
13 | Example: | ||
14 | |||
15 | codec: wm8711@1a { | ||
16 | compatible = "wlf,wm8711"; | ||
17 | reg = <0x1a>; | ||
18 | }; | ||
diff --git a/Documentation/devicetree/bindings/sound/wm8728.txt b/Documentation/devicetree/bindings/sound/wm8728.txt new file mode 100644 index 000000000000..a8b5c3668e60 --- /dev/null +++ b/Documentation/devicetree/bindings/sound/wm8728.txt | |||
@@ -0,0 +1,18 @@ | |||
1 | WM8728 audio CODEC | ||
2 | |||
3 | This device supports both I2C and SPI (configured with pin strapping | ||
4 | on the board). | ||
5 | |||
6 | Required properties: | ||
7 | |||
8 | - compatible : "wlf,wm8728" | ||
9 | |||
10 | - reg : the I2C address of the device for I2C, the chip select | ||
11 | number for SPI. | ||
12 | |||
13 | Example: | ||
14 | |||
15 | codec: wm8728@1a { | ||
16 | compatible = "wlf,wm8728"; | ||
17 | reg = <0x1a>; | ||
18 | }; | ||
diff --git a/Documentation/devicetree/bindings/sound/wm8731.txt b/Documentation/devicetree/bindings/sound/wm8731.txt new file mode 100644 index 000000000000..15f70048469b --- /dev/null +++ b/Documentation/devicetree/bindings/sound/wm8731.txt | |||
@@ -0,0 +1,18 @@ | |||
1 | WM8731 audio CODEC | ||
2 | |||
3 | This device supports both I2C and SPI (configured with pin strapping | ||
4 | on the board). | ||
5 | |||
6 | Required properties: | ||
7 | |||
8 | - compatible : "wlf,wm8731" | ||
9 | |||
10 | - reg : the I2C address of the device for I2C, the chip select | ||
11 | number for SPI. | ||
12 | |||
13 | Example: | ||
14 | |||
15 | codec: wm8731@1a { | ||
16 | compatible = "wlf,wm8731"; | ||
17 | reg = <0x1a>; | ||
18 | }; | ||
diff --git a/Documentation/devicetree/bindings/sound/wm8737.txt b/Documentation/devicetree/bindings/sound/wm8737.txt new file mode 100644 index 000000000000..4bc2cea3b140 --- /dev/null +++ b/Documentation/devicetree/bindings/sound/wm8737.txt | |||
@@ -0,0 +1,18 @@ | |||
1 | WM8737 audio CODEC | ||
2 | |||
3 | This device supports both I2C and SPI (configured with pin strapping | ||
4 | on the board). | ||
5 | |||
6 | Required properties: | ||
7 | |||
8 | - compatible : "wlf,wm8737" | ||
9 | |||
10 | - reg : the I2C address of the device for I2C, the chip select | ||
11 | number for SPI. | ||
12 | |||
13 | Example: | ||
14 | |||
15 | codec: wm8737@1a { | ||
16 | compatible = "wlf,wm8737"; | ||
17 | reg = <0x1a>; | ||
18 | }; | ||
diff --git a/Documentation/devicetree/bindings/sound/wm8741.txt b/Documentation/devicetree/bindings/sound/wm8741.txt new file mode 100644 index 000000000000..74bda58c1bcf --- /dev/null +++ b/Documentation/devicetree/bindings/sound/wm8741.txt | |||
@@ -0,0 +1,18 @@ | |||
1 | WM8741 audio CODEC | ||
2 | |||
3 | This device supports both I2C and SPI (configured with pin strapping | ||
4 | on the board). | ||
5 | |||
6 | Required properties: | ||
7 | |||
8 | - compatible : "wlf,wm8741" | ||
9 | |||
10 | - reg : the I2C address of the device for I2C, the chip select | ||
11 | number for SPI. | ||
12 | |||
13 | Example: | ||
14 | |||
15 | codec: wm8741@1a { | ||
16 | compatible = "wlf,wm8741"; | ||
17 | reg = <0x1a>; | ||
18 | }; | ||
diff --git a/Documentation/devicetree/bindings/sound/wm8750.txt b/Documentation/devicetree/bindings/sound/wm8750.txt new file mode 100644 index 000000000000..8db239fd5ecd --- /dev/null +++ b/Documentation/devicetree/bindings/sound/wm8750.txt | |||
@@ -0,0 +1,18 @@ | |||
1 | WM8750 and WM8987 audio CODECs | ||
2 | |||
3 | These devices support both I2C and SPI (configured with pin strapping | ||
4 | on the board). | ||
5 | |||
6 | Required properties: | ||
7 | |||
8 | - compatible : "wlf,wm8750" or "wlf,wm8987" | ||
9 | |||
10 | - reg : the I2C address of the device for I2C, the chip select | ||
11 | number for SPI. | ||
12 | |||
13 | Example: | ||
14 | |||
15 | codec: wm8750@1a { | ||
16 | compatible = "wlf,wm8750"; | ||
17 | reg = <0x1a>; | ||
18 | }; | ||
diff --git a/Documentation/devicetree/bindings/sound/wm8753.txt b/Documentation/devicetree/bindings/sound/wm8753.txt new file mode 100644 index 000000000000..e65277a0fb60 --- /dev/null +++ b/Documentation/devicetree/bindings/sound/wm8753.txt | |||
@@ -0,0 +1,18 @@ | |||
1 | WM8753 audio CODEC | ||
2 | |||
3 | This device supports both I2C and SPI (configured with pin strapping | ||
4 | on the board). | ||
5 | |||
6 | Required properties: | ||
7 | |||
8 | - compatible : "wlf,wm8753" | ||
9 | |||
10 | - reg : the I2C address of the device for I2C, the chip select | ||
11 | number for SPI. | ||
12 | |||
13 | Example: | ||
14 | |||
15 | codec: wm8737@1a { | ||
16 | compatible = "wlf,wm8753"; | ||
17 | reg = <0x1a>; | ||
18 | }; | ||
diff --git a/Documentation/devicetree/bindings/sound/wm8770.txt b/Documentation/devicetree/bindings/sound/wm8770.txt new file mode 100644 index 000000000000..866e00ca150b --- /dev/null +++ b/Documentation/devicetree/bindings/sound/wm8770.txt | |||
@@ -0,0 +1,16 @@ | |||
1 | WM8770 audio CODEC | ||
2 | |||
3 | This device supports SPI. | ||
4 | |||
5 | Required properties: | ||
6 | |||
7 | - compatible : "wlf,wm8770" | ||
8 | |||
9 | - reg : the chip select number. | ||
10 | |||
11 | Example: | ||
12 | |||
13 | codec: wm8770@1 { | ||
14 | compatible = "wlf,wm8770"; | ||
15 | reg = <1>; | ||
16 | }; | ||
diff --git a/Documentation/devicetree/bindings/sound/wm8776.txt b/Documentation/devicetree/bindings/sound/wm8776.txt new file mode 100644 index 000000000000..3b9ca49abc2b --- /dev/null +++ b/Documentation/devicetree/bindings/sound/wm8776.txt | |||
@@ -0,0 +1,18 @@ | |||
1 | WM8776 audio CODEC | ||
2 | |||
3 | This device supports both I2C and SPI (configured with pin strapping | ||
4 | on the board). | ||
5 | |||
6 | Required properties: | ||
7 | |||
8 | - compatible : "wlf,wm8776" | ||
9 | |||
10 | - reg : the I2C address of the device for I2C, the chip select | ||
11 | number for SPI. | ||
12 | |||
13 | Example: | ||
14 | |||
15 | codec: wm8776@1a { | ||
16 | compatible = "wlf,wm8776"; | ||
17 | reg = <0x1a>; | ||
18 | }; | ||
diff --git a/Documentation/devicetree/bindings/sound/wm8804.txt b/Documentation/devicetree/bindings/sound/wm8804.txt new file mode 100644 index 000000000000..4d3a56f38adc --- /dev/null +++ b/Documentation/devicetree/bindings/sound/wm8804.txt | |||
@@ -0,0 +1,18 @@ | |||
1 | WM8804 audio CODEC | ||
2 | |||
3 | This device supports both I2C and SPI (configured with pin strapping | ||
4 | on the board). | ||
5 | |||
6 | Required properties: | ||
7 | |||
8 | - compatible : "wlf,wm8804" | ||
9 | |||
10 | - reg : the I2C address of the device for I2C, the chip select | ||
11 | number for SPI. | ||
12 | |||
13 | Example: | ||
14 | |||
15 | codec: wm8804@1a { | ||
16 | compatible = "wlf,wm8804"; | ||
17 | reg = <0x1a>; | ||
18 | }; | ||
diff --git a/arch/arm/mach-ep93xx/edb93xx.c b/arch/arm/mach-ep93xx/edb93xx.c index 9969bb115f60..8dc51e464a4e 100644 --- a/arch/arm/mach-ep93xx/edb93xx.c +++ b/arch/arm/mach-ep93xx/edb93xx.c | |||
@@ -159,6 +159,11 @@ static void __init edb93xx_register_spi(void) | |||
159 | /************************************************************************* | 159 | /************************************************************************* |
160 | * EDB93xx I2S | 160 | * EDB93xx I2S |
161 | *************************************************************************/ | 161 | *************************************************************************/ |
162 | static struct platform_device edb93xx_audio_device = { | ||
163 | .name = "edb93xx-audio", | ||
164 | .id = -1, | ||
165 | }; | ||
166 | |||
162 | static int __init edb93xx_has_audio(void) | 167 | static int __init edb93xx_has_audio(void) |
163 | { | 168 | { |
164 | return (machine_is_edb9301() || machine_is_edb9302() || | 169 | return (machine_is_edb9301() || machine_is_edb9302() || |
@@ -170,6 +175,7 @@ static void __init edb93xx_register_i2s(void) | |||
170 | { | 175 | { |
171 | if (edb93xx_has_audio()) { | 176 | if (edb93xx_has_audio()) { |
172 | ep93xx_register_i2s(); | 177 | ep93xx_register_i2s(); |
178 | platform_device_register(&edb93xx_audio_device); | ||
173 | } | 179 | } |
174 | } | 180 | } |
175 | 181 | ||
diff --git a/arch/arm/mach-ep93xx/simone.c b/arch/arm/mach-ep93xx/simone.c index 8392e95d7cea..1445ce568cae 100644 --- a/arch/arm/mach-ep93xx/simone.c +++ b/arch/arm/mach-ep93xx/simone.c | |||
@@ -53,6 +53,17 @@ static struct i2c_board_info __initdata simone_i2c_board_info[] = { | |||
53 | }, | 53 | }, |
54 | }; | 54 | }; |
55 | 55 | ||
56 | static struct platform_device simone_audio_device = { | ||
57 | .name = "simone-audio", | ||
58 | .id = -1, | ||
59 | }; | ||
60 | |||
61 | static void __init simone_register_audio(void) | ||
62 | { | ||
63 | ep93xx_register_ac97(); | ||
64 | platform_device_register(&simone_audio_device); | ||
65 | } | ||
66 | |||
56 | static void __init simone_init_machine(void) | 67 | static void __init simone_init_machine(void) |
57 | { | 68 | { |
58 | ep93xx_init_devices(); | 69 | ep93xx_init_devices(); |
@@ -61,7 +72,7 @@ static void __init simone_init_machine(void) | |||
61 | ep93xx_register_fb(&simone_fb_info); | 72 | ep93xx_register_fb(&simone_fb_info); |
62 | ep93xx_register_i2c(&simone_i2c_gpio_data, simone_i2c_board_info, | 73 | ep93xx_register_i2c(&simone_i2c_gpio_data, simone_i2c_board_info, |
63 | ARRAY_SIZE(simone_i2c_board_info)); | 74 | ARRAY_SIZE(simone_i2c_board_info)); |
64 | ep93xx_register_ac97(); | 75 | simone_register_audio(); |
65 | } | 76 | } |
66 | 77 | ||
67 | MACHINE_START(SIM_ONE, "Simplemachines Sim.One Board") | 78 | MACHINE_START(SIM_ONE, "Simplemachines Sim.One Board") |
diff --git a/arch/arm/mach-ep93xx/snappercl15.c b/arch/arm/mach-ep93xx/snappercl15.c index 2e9c614757e4..edd75e37f4de 100644 --- a/arch/arm/mach-ep93xx/snappercl15.c +++ b/arch/arm/mach-ep93xx/snappercl15.c | |||
@@ -150,6 +150,17 @@ static struct ep93xxfb_mach_info __initdata snappercl15_fb_info = { | |||
150 | .bpp = 16, | 150 | .bpp = 16, |
151 | }; | 151 | }; |
152 | 152 | ||
153 | static struct platform_device snappercl15_audio_device = { | ||
154 | .name = "snappercl15-audio", | ||
155 | .id = -1, | ||
156 | }; | ||
157 | |||
158 | static void __init snappercl15_register_audio(void) | ||
159 | { | ||
160 | ep93xx_register_i2s(); | ||
161 | platform_device_register(&snappercl15_audio_device); | ||
162 | } | ||
163 | |||
153 | static void __init snappercl15_init_machine(void) | 164 | static void __init snappercl15_init_machine(void) |
154 | { | 165 | { |
155 | ep93xx_init_devices(); | 166 | ep93xx_init_devices(); |
@@ -157,7 +168,7 @@ static void __init snappercl15_init_machine(void) | |||
157 | ep93xx_register_i2c(&snappercl15_i2c_gpio_data, snappercl15_i2c_data, | 168 | ep93xx_register_i2c(&snappercl15_i2c_gpio_data, snappercl15_i2c_data, |
158 | ARRAY_SIZE(snappercl15_i2c_data)); | 169 | ARRAY_SIZE(snappercl15_i2c_data)); |
159 | ep93xx_register_fb(&snappercl15_fb_info); | 170 | ep93xx_register_fb(&snappercl15_fb_info); |
160 | ep93xx_register_i2s(); | 171 | snappercl15_register_audio(); |
161 | platform_device_register(&snappercl15_nand_device); | 172 | platform_device_register(&snappercl15_nand_device); |
162 | } | 173 | } |
163 | 174 | ||
diff --git a/arch/mips/alchemy/devboards/db1200/platform.c b/arch/mips/alchemy/devboards/db1200/platform.c index fbb55935b99e..dda090bf74e6 100644 --- a/arch/mips/alchemy/devboards/db1200/platform.c +++ b/arch/mips/alchemy/devboards/db1200/platform.c | |||
@@ -422,6 +422,7 @@ static struct resource au1200_psc1_res[] = { | |||
422 | }, | 422 | }, |
423 | }; | 423 | }; |
424 | 424 | ||
425 | /* AC97 or I2S device */ | ||
425 | static struct platform_device db1200_audio_dev = { | 426 | static struct platform_device db1200_audio_dev = { |
426 | /* name assigned later based on switch setting */ | 427 | /* name assigned later based on switch setting */ |
427 | .id = 1, /* PSC ID */ | 428 | .id = 1, /* PSC ID */ |
@@ -429,19 +430,32 @@ static struct platform_device db1200_audio_dev = { | |||
429 | .resource = au1200_psc1_res, | 430 | .resource = au1200_psc1_res, |
430 | }; | 431 | }; |
431 | 432 | ||
433 | /* DB1200 ASoC card device */ | ||
434 | static struct platform_device db1200_sound_dev = { | ||
435 | /* name assigned later based on switch setting */ | ||
436 | .id = 1, /* PSC ID */ | ||
437 | }; | ||
438 | |||
432 | static struct platform_device db1200_stac_dev = { | 439 | static struct platform_device db1200_stac_dev = { |
433 | .name = "ac97-codec", | 440 | .name = "ac97-codec", |
434 | .id = 1, /* on PSC1 */ | 441 | .id = 1, /* on PSC1 */ |
435 | }; | 442 | }; |
436 | 443 | ||
444 | static struct platform_device db1200_audiodma_dev = { | ||
445 | .name = "au1xpsc-pcm", | ||
446 | .id = 1, /* PSC ID */ | ||
447 | }; | ||
448 | |||
437 | static struct platform_device *db1200_devs[] __initdata = { | 449 | static struct platform_device *db1200_devs[] __initdata = { |
438 | NULL, /* PSC0, selected by S6.8 */ | 450 | NULL, /* PSC0, selected by S6.8 */ |
439 | &db1200_ide_dev, | 451 | &db1200_ide_dev, |
440 | &db1200_eth_dev, | 452 | &db1200_eth_dev, |
441 | &db1200_rtc_dev, | 453 | &db1200_rtc_dev, |
442 | &db1200_nand_dev, | 454 | &db1200_nand_dev, |
455 | &db1200_audiodma_dev, | ||
443 | &db1200_audio_dev, | 456 | &db1200_audio_dev, |
444 | &db1200_stac_dev, | 457 | &db1200_stac_dev, |
458 | &db1200_sound_dev, | ||
445 | }; | 459 | }; |
446 | 460 | ||
447 | static int __init db1200_dev_init(void) | 461 | static int __init db1200_dev_init(void) |
@@ -501,10 +515,12 @@ static int __init db1200_dev_init(void) | |||
501 | if (sw == BCSR_SWITCHES_DIP_8) { | 515 | if (sw == BCSR_SWITCHES_DIP_8) { |
502 | bcsr_mod(BCSR_RESETS, 0, BCSR_RESETS_PSC1MUX); | 516 | bcsr_mod(BCSR_RESETS, 0, BCSR_RESETS_PSC1MUX); |
503 | db1200_audio_dev.name = "au1xpsc_i2s"; | 517 | db1200_audio_dev.name = "au1xpsc_i2s"; |
518 | db1200_sound_dev.name = "db1200-i2s"; | ||
504 | printk(KERN_INFO " S6.7 ON : PSC1 mode I2S\n"); | 519 | printk(KERN_INFO " S6.7 ON : PSC1 mode I2S\n"); |
505 | } else { | 520 | } else { |
506 | bcsr_mod(BCSR_RESETS, BCSR_RESETS_PSC1MUX, 0); | 521 | bcsr_mod(BCSR_RESETS, BCSR_RESETS_PSC1MUX, 0); |
507 | db1200_audio_dev.name = "au1xpsc_ac97"; | 522 | db1200_audio_dev.name = "au1xpsc_ac97"; |
523 | db1200_sound_dev.name = "db1200-ac97"; | ||
508 | printk(KERN_INFO " S6.7 OFF: PSC1 mode AC97\n"); | 524 | printk(KERN_INFO " S6.7 OFF: PSC1 mode AC97\n"); |
509 | } | 525 | } |
510 | 526 | ||
diff --git a/arch/mips/alchemy/devboards/db1x00/platform.c b/arch/mips/alchemy/devboards/db1x00/platform.c index 978d5ab3d678..7057d28f7301 100644 --- a/arch/mips/alchemy/devboards/db1x00/platform.c +++ b/arch/mips/alchemy/devboards/db1x00/platform.c | |||
@@ -19,8 +19,11 @@ | |||
19 | */ | 19 | */ |
20 | 20 | ||
21 | #include <linux/init.h> | 21 | #include <linux/init.h> |
22 | #include <linux/interrupt.h> | ||
22 | #include <linux/platform_device.h> | 23 | #include <linux/platform_device.h> |
23 | 24 | ||
25 | #include <asm/mach-au1x00/au1000.h> | ||
26 | #include <asm/mach-au1x00/au1000_dma.h> | ||
24 | #include <asm/mach-au1x00/au1xxx.h> | 27 | #include <asm/mach-au1x00/au1xxx.h> |
25 | #include <asm/mach-db1x00/bcsr.h> | 28 | #include <asm/mach-db1x00/bcsr.h> |
26 | #include "../platform.h" | 29 | #include "../platform.h" |
@@ -85,6 +88,45 @@ | |||
85 | #endif | 88 | #endif |
86 | #endif | 89 | #endif |
87 | 90 | ||
91 | static struct resource alchemy_ac97c_res[] = { | ||
92 | [0] = { | ||
93 | .start = AU1000_AC97_PHYS_ADDR, | ||
94 | .end = AU1000_AC97_PHYS_ADDR + 0xfff, | ||
95 | .flags = IORESOURCE_MEM, | ||
96 | }, | ||
97 | [1] = { | ||
98 | .start = DMA_ID_AC97C_TX, | ||
99 | .end = DMA_ID_AC97C_TX, | ||
100 | .flags = IORESOURCE_DMA, | ||
101 | }, | ||
102 | [2] = { | ||
103 | .start = DMA_ID_AC97C_RX, | ||
104 | .end = DMA_ID_AC97C_RX, | ||
105 | .flags = IORESOURCE_DMA, | ||
106 | }, | ||
107 | }; | ||
108 | |||
109 | static struct platform_device alchemy_ac97c_dev = { | ||
110 | .name = "alchemy-ac97c", | ||
111 | .id = -1, | ||
112 | .resource = alchemy_ac97c_res, | ||
113 | .num_resources = ARRAY_SIZE(alchemy_ac97c_res), | ||
114 | }; | ||
115 | |||
116 | static struct platform_device alchemy_ac97c_dma_dev = { | ||
117 | .name = "alchemy-pcm-dma", | ||
118 | .id = 0, | ||
119 | }; | ||
120 | |||
121 | static struct platform_device db1x00_codec_dev = { | ||
122 | .name = "ac97-codec", | ||
123 | .id = -1, | ||
124 | }; | ||
125 | |||
126 | static struct platform_device db1x00_audio_dev = { | ||
127 | .name = "db1000-audio", | ||
128 | }; | ||
129 | |||
88 | static int __init db1xxx_dev_init(void) | 130 | static int __init db1xxx_dev_init(void) |
89 | { | 131 | { |
90 | #ifdef DB1XXX_HAS_PCMCIA | 132 | #ifdef DB1XXX_HAS_PCMCIA |
@@ -113,6 +155,12 @@ static int __init db1xxx_dev_init(void) | |||
113 | 1); | 155 | 1); |
114 | #endif | 156 | #endif |
115 | db1x_register_norflash(BOARD_FLASH_SIZE, BOARD_FLASH_WIDTH, F_SWAPPED); | 157 | db1x_register_norflash(BOARD_FLASH_SIZE, BOARD_FLASH_WIDTH, F_SWAPPED); |
158 | |||
159 | platform_device_register(&db1x00_codec_dev); | ||
160 | platform_device_register(&alchemy_ac97c_dma_dev); | ||
161 | platform_device_register(&alchemy_ac97c_dev); | ||
162 | platform_device_register(&db1x00_audio_dev); | ||
163 | |||
116 | return 0; | 164 | return 0; |
117 | } | 165 | } |
118 | device_initcall(db1xxx_dev_init); | 166 | device_initcall(db1xxx_dev_init); |
diff --git a/drivers/base/regmap/regmap.c b/drivers/base/regmap/regmap.c index cf3565cae93d..2fa55c56897a 100644 --- a/drivers/base/regmap/regmap.c +++ b/drivers/base/regmap/regmap.c | |||
@@ -37,6 +37,11 @@ struct regmap { | |||
37 | void *work_buf; /* Scratch buffer used to format I/O */ | 37 | void *work_buf; /* Scratch buffer used to format I/O */ |
38 | struct regmap_format format; /* Buffer format */ | 38 | struct regmap_format format; /* Buffer format */ |
39 | const struct regmap_bus *bus; | 39 | const struct regmap_bus *bus; |
40 | |||
41 | unsigned int max_register; | ||
42 | bool (*writeable_reg)(struct device *dev, unsigned int reg); | ||
43 | bool (*readable_reg)(struct device *dev, unsigned int reg); | ||
44 | bool (*volatile_reg)(struct device *dev, unsigned int reg); | ||
40 | }; | 45 | }; |
41 | 46 | ||
42 | static void regmap_format_4_12_write(struct regmap *map, | 47 | static void regmap_format_4_12_write(struct regmap *map, |
@@ -116,6 +121,10 @@ struct regmap *regmap_init(struct device *dev, | |||
116 | map->format.val_bytes = config->val_bits / 8; | 121 | map->format.val_bytes = config->val_bits / 8; |
117 | map->dev = dev; | 122 | map->dev = dev; |
118 | map->bus = bus; | 123 | map->bus = bus; |
124 | map->max_register = config->max_register; | ||
125 | map->writeable_reg = config->writeable_reg; | ||
126 | map->readable_reg = config->readable_reg; | ||
127 | map->volatile_reg = config->volatile_reg; | ||
119 | 128 | ||
120 | switch (config->reg_bits) { | 129 | switch (config->reg_bits) { |
121 | case 4: | 130 | case 4: |
diff --git a/drivers/input/misc/twl6040-vibra.c b/drivers/input/misc/twl6040-vibra.c index c43002e7ec72..154b7a324d67 100644 --- a/drivers/input/misc/twl6040-vibra.c +++ b/drivers/input/misc/twl6040-vibra.c | |||
@@ -97,7 +97,7 @@ static void twl6040_vibra_enable(struct vibra_info *info) | |||
97 | } | 97 | } |
98 | 98 | ||
99 | twl6040_power(info->twl6040, 1); | 99 | twl6040_power(info->twl6040, 1); |
100 | if (twl6040->rev <= TWL6040_REV_ES1_1) { | 100 | if (twl6040_get_revid(twl6040) <= TWL6040_REV_ES1_1) { |
101 | /* | 101 | /* |
102 | * ERRATA: Disable overcurrent protection for at least | 102 | * ERRATA: Disable overcurrent protection for at least |
103 | * 3ms when enabling vibrator drivers to avoid false | 103 | * 3ms when enabling vibrator drivers to avoid false |
diff --git a/drivers/mfd/twl6040-core.c b/drivers/mfd/twl6040-core.c index 24d436c2fe4a..7dc8c4715001 100644 --- a/drivers/mfd/twl6040-core.c +++ b/drivers/mfd/twl6040-core.c | |||
@@ -34,8 +34,6 @@ | |||
34 | #include <linux/mfd/core.h> | 34 | #include <linux/mfd/core.h> |
35 | #include <linux/mfd/twl6040.h> | 35 | #include <linux/mfd/twl6040.h> |
36 | 36 | ||
37 | static struct platform_device *twl6040_dev; | ||
38 | |||
39 | int twl6040_reg_read(struct twl6040 *twl6040, unsigned int reg) | 37 | int twl6040_reg_read(struct twl6040 *twl6040, unsigned int reg) |
40 | { | 38 | { |
41 | int ret; | 39 | int ret; |
@@ -203,11 +201,11 @@ static irqreturn_t twl6040_naudint_handler(int irq, void *data) | |||
203 | if (intid & TWL6040_THINT) { | 201 | if (intid & TWL6040_THINT) { |
204 | status = twl6040_reg_read(twl6040, TWL6040_REG_STATUS); | 202 | status = twl6040_reg_read(twl6040, TWL6040_REG_STATUS); |
205 | if (status & TWL6040_TSHUTDET) { | 203 | if (status & TWL6040_TSHUTDET) { |
206 | dev_warn(&twl6040_dev->dev, | 204 | dev_warn(twl6040->dev, |
207 | "Thermal shutdown, powering-off"); | 205 | "Thermal shutdown, powering-off"); |
208 | twl6040_power(twl6040, 0); | 206 | twl6040_power(twl6040, 0); |
209 | } else { | 207 | } else { |
210 | dev_warn(&twl6040_dev->dev, | 208 | dev_warn(twl6040->dev, |
211 | "Leaving thermal shutdown, powering-on"); | 209 | "Leaving thermal shutdown, powering-on"); |
212 | twl6040_power(twl6040, 1); | 210 | twl6040_power(twl6040, 1); |
213 | } | 211 | } |
@@ -227,7 +225,7 @@ static int twl6040_power_up_completion(struct twl6040 *twl6040, | |||
227 | if (!time_left) { | 225 | if (!time_left) { |
228 | intid = twl6040_reg_read(twl6040, TWL6040_REG_INTID); | 226 | intid = twl6040_reg_read(twl6040, TWL6040_REG_INTID); |
229 | if (!(intid & TWL6040_READYINT)) { | 227 | if (!(intid & TWL6040_READYINT)) { |
230 | dev_err(&twl6040_dev->dev, | 228 | dev_err(twl6040->dev, |
231 | "timeout waiting for READYINT\n"); | 229 | "timeout waiting for READYINT\n"); |
232 | return -ETIMEDOUT; | 230 | return -ETIMEDOUT; |
233 | } | 231 | } |
@@ -255,7 +253,7 @@ int twl6040_power(struct twl6040 *twl6040, int on) | |||
255 | /* wait for power-up completion */ | 253 | /* wait for power-up completion */ |
256 | ret = twl6040_power_up_completion(twl6040, naudint); | 254 | ret = twl6040_power_up_completion(twl6040, naudint); |
257 | if (ret) { | 255 | if (ret) { |
258 | dev_err(&twl6040_dev->dev, | 256 | dev_err(twl6040->dev, |
259 | "automatic power-down failed\n"); | 257 | "automatic power-down failed\n"); |
260 | twl6040->power_count = 0; | 258 | twl6040->power_count = 0; |
261 | goto out; | 259 | goto out; |
@@ -264,7 +262,7 @@ int twl6040_power(struct twl6040 *twl6040, int on) | |||
264 | /* use manual power-up sequence */ | 262 | /* use manual power-up sequence */ |
265 | ret = twl6040_power_up(twl6040); | 263 | ret = twl6040_power_up(twl6040); |
266 | if (ret) { | 264 | if (ret) { |
267 | dev_err(&twl6040_dev->dev, | 265 | dev_err(twl6040->dev, |
268 | "manual power-up failed\n"); | 266 | "manual power-up failed\n"); |
269 | twl6040->power_count = 0; | 267 | twl6040->power_count = 0; |
270 | goto out; | 268 | goto out; |
@@ -276,7 +274,7 @@ int twl6040_power(struct twl6040 *twl6040, int on) | |||
276 | } else { | 274 | } else { |
277 | /* already powered-down */ | 275 | /* already powered-down */ |
278 | if (!twl6040->power_count) { | 276 | if (!twl6040->power_count) { |
279 | dev_err(&twl6040_dev->dev, | 277 | dev_err(twl6040->dev, |
280 | "device is already powered-off\n"); | 278 | "device is already powered-off\n"); |
281 | ret = -EPERM; | 279 | ret = -EPERM; |
282 | goto out; | 280 | goto out; |
@@ -326,7 +324,7 @@ int twl6040_set_pll(struct twl6040 *twl6040, int pll_id, | |||
326 | lppllctl &= ~TWL6040_LPLLFIN; | 324 | lppllctl &= ~TWL6040_LPLLFIN; |
327 | break; | 325 | break; |
328 | default: | 326 | default: |
329 | dev_err(&twl6040_dev->dev, | 327 | dev_err(twl6040->dev, |
330 | "freq_out %d not supported\n", freq_out); | 328 | "freq_out %d not supported\n", freq_out); |
331 | ret = -EINVAL; | 329 | ret = -EINVAL; |
332 | goto pll_out; | 330 | goto pll_out; |
@@ -347,7 +345,7 @@ int twl6040_set_pll(struct twl6040 *twl6040, int pll_id, | |||
347 | hppllctl); | 345 | hppllctl); |
348 | break; | 346 | break; |
349 | default: | 347 | default: |
350 | dev_err(&twl6040_dev->dev, | 348 | dev_err(twl6040->dev, |
351 | "freq_in %d not supported\n", freq_in); | 349 | "freq_in %d not supported\n", freq_in); |
352 | ret = -EINVAL; | 350 | ret = -EINVAL; |
353 | goto pll_out; | 351 | goto pll_out; |
@@ -356,7 +354,7 @@ int twl6040_set_pll(struct twl6040 *twl6040, int pll_id, | |||
356 | case TWL6040_SYSCLK_SEL_HPPLL: | 354 | case TWL6040_SYSCLK_SEL_HPPLL: |
357 | /* high-performance PLL can provide only 19.2 MHz */ | 355 | /* high-performance PLL can provide only 19.2 MHz */ |
358 | if (freq_out != 19200000) { | 356 | if (freq_out != 19200000) { |
359 | dev_err(&twl6040_dev->dev, | 357 | dev_err(twl6040->dev, |
360 | "freq_out %d not supported\n", freq_out); | 358 | "freq_out %d not supported\n", freq_out); |
361 | ret = -EINVAL; | 359 | ret = -EINVAL; |
362 | goto pll_out; | 360 | goto pll_out; |
@@ -389,7 +387,7 @@ int twl6040_set_pll(struct twl6040 *twl6040, int pll_id, | |||
389 | TWL6040_HPLLENA; | 387 | TWL6040_HPLLENA; |
390 | break; | 388 | break; |
391 | default: | 389 | default: |
392 | dev_err(&twl6040_dev->dev, | 390 | dev_err(twl6040->dev, |
393 | "freq_in %d not supported\n", freq_in); | 391 | "freq_in %d not supported\n", freq_in); |
394 | ret = -EINVAL; | 392 | ret = -EINVAL; |
395 | goto pll_out; | 393 | goto pll_out; |
@@ -406,7 +404,7 @@ int twl6040_set_pll(struct twl6040 *twl6040, int pll_id, | |||
406 | twl6040_reg_write(twl6040, TWL6040_REG_LPPLLCTL, lppllctl); | 404 | twl6040_reg_write(twl6040, TWL6040_REG_LPPLLCTL, lppllctl); |
407 | break; | 405 | break; |
408 | default: | 406 | default: |
409 | dev_err(&twl6040_dev->dev, "unknown pll id %d\n", pll_id); | 407 | dev_err(twl6040->dev, "unknown pll id %d\n", pll_id); |
410 | ret = -EINVAL; | 408 | ret = -EINVAL; |
411 | goto pll_out; | 409 | goto pll_out; |
412 | } | 410 | } |
@@ -471,9 +469,7 @@ static int __devinit twl6040_probe(struct platform_device *pdev) | |||
471 | 469 | ||
472 | platform_set_drvdata(pdev, twl6040); | 470 | platform_set_drvdata(pdev, twl6040); |
473 | 471 | ||
474 | twl6040_dev = pdev; | ||
475 | twl6040->dev = &pdev->dev; | 472 | twl6040->dev = &pdev->dev; |
476 | twl6040->audpwron = pdata->audpwron_gpio; | ||
477 | twl6040->irq = pdata->naudint_irq; | 473 | twl6040->irq = pdata->naudint_irq; |
478 | twl6040->irq_base = pdata->irq_base; | 474 | twl6040->irq_base = pdata->irq_base; |
479 | 475 | ||
@@ -483,6 +479,12 @@ static int __devinit twl6040_probe(struct platform_device *pdev) | |||
483 | 479 | ||
484 | twl6040->rev = twl6040_reg_read(twl6040, TWL6040_REG_ASICREV); | 480 | twl6040->rev = twl6040_reg_read(twl6040, TWL6040_REG_ASICREV); |
485 | 481 | ||
482 | /* ERRATA: Automatic power-up is not possible in ES1.0 */ | ||
483 | if (twl6040_get_revid(twl6040) > TWL6040_REV_ES1_0) | ||
484 | twl6040->audpwron = pdata->audpwron_gpio; | ||
485 | else | ||
486 | twl6040->audpwron = -EINVAL; | ||
487 | |||
486 | if (gpio_is_valid(twl6040->audpwron)) { | 488 | if (gpio_is_valid(twl6040->audpwron)) { |
487 | ret = gpio_request(twl6040->audpwron, "audpwron"); | 489 | ret = gpio_request(twl6040->audpwron, "audpwron"); |
488 | if (ret) | 490 | if (ret) |
@@ -493,10 +495,6 @@ static int __devinit twl6040_probe(struct platform_device *pdev) | |||
493 | goto gpio2_err; | 495 | goto gpio2_err; |
494 | } | 496 | } |
495 | 497 | ||
496 | /* ERRATA: Automatic power-up is not possible in ES1.0 */ | ||
497 | if (twl6040->rev == TWL6040_REV_ES1_0) | ||
498 | twl6040->audpwron = -EINVAL; | ||
499 | |||
500 | /* codec interrupt */ | 498 | /* codec interrupt */ |
501 | ret = twl6040_irq_init(twl6040); | 499 | ret = twl6040_irq_init(twl6040); |
502 | if (ret) | 500 | if (ret) |
@@ -566,7 +564,6 @@ gpio2_err: | |||
566 | gpio1_err: | 564 | gpio1_err: |
567 | platform_set_drvdata(pdev, NULL); | 565 | platform_set_drvdata(pdev, NULL); |
568 | kfree(twl6040); | 566 | kfree(twl6040); |
569 | twl6040_dev = NULL; | ||
570 | return ret; | 567 | return ret; |
571 | } | 568 | } |
572 | 569 | ||
@@ -586,7 +583,6 @@ static int __devexit twl6040_remove(struct platform_device *pdev) | |||
586 | mfd_remove_devices(&pdev->dev); | 583 | mfd_remove_devices(&pdev->dev); |
587 | platform_set_drvdata(pdev, NULL); | 584 | platform_set_drvdata(pdev, NULL); |
588 | kfree(twl6040); | 585 | kfree(twl6040); |
589 | twl6040_dev = NULL; | ||
590 | 586 | ||
591 | return 0; | 587 | return 0; |
592 | } | 588 | } |
diff --git a/drivers/regulator/core.c b/drivers/regulator/core.c index d8e6a429e8ba..d0bde70f3466 100644 --- a/drivers/regulator/core.c +++ b/drivers/regulator/core.c | |||
@@ -1552,6 +1552,63 @@ int regulator_force_disable(struct regulator *regulator) | |||
1552 | } | 1552 | } |
1553 | EXPORT_SYMBOL_GPL(regulator_force_disable); | 1553 | EXPORT_SYMBOL_GPL(regulator_force_disable); |
1554 | 1554 | ||
1555 | static void regulator_disable_work(struct work_struct *work) | ||
1556 | { | ||
1557 | struct regulator_dev *rdev = container_of(work, struct regulator_dev, | ||
1558 | disable_work.work); | ||
1559 | int count, i, ret; | ||
1560 | |||
1561 | mutex_lock(&rdev->mutex); | ||
1562 | |||
1563 | BUG_ON(!rdev->deferred_disables); | ||
1564 | |||
1565 | count = rdev->deferred_disables; | ||
1566 | rdev->deferred_disables = 0; | ||
1567 | |||
1568 | for (i = 0; i < count; i++) { | ||
1569 | ret = _regulator_disable(rdev); | ||
1570 | if (ret != 0) | ||
1571 | rdev_err(rdev, "Deferred disable failed: %d\n", ret); | ||
1572 | } | ||
1573 | |||
1574 | mutex_unlock(&rdev->mutex); | ||
1575 | |||
1576 | if (rdev->supply) { | ||
1577 | for (i = 0; i < count; i++) { | ||
1578 | ret = regulator_disable(rdev->supply); | ||
1579 | if (ret != 0) { | ||
1580 | rdev_err(rdev, | ||
1581 | "Supply disable failed: %d\n", ret); | ||
1582 | } | ||
1583 | } | ||
1584 | } | ||
1585 | } | ||
1586 | |||
1587 | /** | ||
1588 | * regulator_disable_deferred - disable regulator output with delay | ||
1589 | * @regulator: regulator source | ||
1590 | * @ms: miliseconds until the regulator is disabled | ||
1591 | * | ||
1592 | * Execute regulator_disable() on the regulator after a delay. This | ||
1593 | * is intended for use with devices that require some time to quiesce. | ||
1594 | * | ||
1595 | * NOTE: this will only disable the regulator output if no other consumer | ||
1596 | * devices have it enabled, the regulator device supports disabling and | ||
1597 | * machine constraints permit this operation. | ||
1598 | */ | ||
1599 | int regulator_disable_deferred(struct regulator *regulator, int ms) | ||
1600 | { | ||
1601 | struct regulator_dev *rdev = regulator->rdev; | ||
1602 | |||
1603 | mutex_lock(&rdev->mutex); | ||
1604 | rdev->deferred_disables++; | ||
1605 | mutex_unlock(&rdev->mutex); | ||
1606 | |||
1607 | return schedule_delayed_work(&rdev->disable_work, | ||
1608 | msecs_to_jiffies(ms)); | ||
1609 | } | ||
1610 | EXPORT_SYMBOL_GPL(regulator_disable_deferred); | ||
1611 | |||
1555 | static int _regulator_is_enabled(struct regulator_dev *rdev) | 1612 | static int _regulator_is_enabled(struct regulator_dev *rdev) |
1556 | { | 1613 | { |
1557 | /* If we don't know then assume that the regulator is always on */ | 1614 | /* If we don't know then assume that the regulator is always on */ |
@@ -2622,6 +2679,7 @@ struct regulator_dev *regulator_register(struct regulator_desc *regulator_desc, | |||
2622 | INIT_LIST_HEAD(&rdev->consumer_list); | 2679 | INIT_LIST_HEAD(&rdev->consumer_list); |
2623 | INIT_LIST_HEAD(&rdev->list); | 2680 | INIT_LIST_HEAD(&rdev->list); |
2624 | BLOCKING_INIT_NOTIFIER_HEAD(&rdev->notifier); | 2681 | BLOCKING_INIT_NOTIFIER_HEAD(&rdev->notifier); |
2682 | INIT_DELAYED_WORK(&rdev->disable_work, regulator_disable_work); | ||
2625 | 2683 | ||
2626 | /* preform any regulator specific init */ | 2684 | /* preform any regulator specific init */ |
2627 | if (init_data->regulator_init) { | 2685 | if (init_data->regulator_init) { |
@@ -2729,6 +2787,7 @@ void regulator_unregister(struct regulator_dev *rdev) | |||
2729 | #ifdef CONFIG_DEBUG_FS | 2787 | #ifdef CONFIG_DEBUG_FS |
2730 | debugfs_remove_recursive(rdev->debugfs); | 2788 | debugfs_remove_recursive(rdev->debugfs); |
2731 | #endif | 2789 | #endif |
2790 | flush_work_sync(&rdev->disable_work.work); | ||
2732 | WARN_ON(rdev->open_count); | 2791 | WARN_ON(rdev->open_count); |
2733 | unset_regulator_supplies(rdev); | 2792 | unset_regulator_supplies(rdev); |
2734 | list_del(&rdev->list); | 2793 | list_del(&rdev->list); |
diff --git a/include/linux/mfd/twl6040.h b/include/linux/mfd/twl6040.h index 4c806f6d663e..ec1ec794fa23 100644 --- a/include/linux/mfd/twl6040.h +++ b/include/linux/mfd/twl6040.h | |||
@@ -70,9 +70,6 @@ | |||
70 | 70 | ||
71 | #define TWL6040_CACHEREGNUM (TWL6040_REG_STATUS + 1) | 71 | #define TWL6040_CACHEREGNUM (TWL6040_REG_STATUS + 1) |
72 | 72 | ||
73 | #define TWL6040_VIOREGNUM 18 | ||
74 | #define TWL6040_VDDREGNUM 21 | ||
75 | |||
76 | /* INTID (0x03) fields */ | 73 | /* INTID (0x03) fields */ |
77 | 74 | ||
78 | #define TWL6040_THINT 0x01 | 75 | #define TWL6040_THINT 0x01 |
@@ -225,4 +222,9 @@ unsigned int twl6040_get_sysclk(struct twl6040 *twl6040); | |||
225 | int twl6040_irq_init(struct twl6040 *twl6040); | 222 | int twl6040_irq_init(struct twl6040 *twl6040); |
226 | void twl6040_irq_exit(struct twl6040 *twl6040); | 223 | void twl6040_irq_exit(struct twl6040 *twl6040); |
227 | 224 | ||
225 | static inline int twl6040_get_revid(struct twl6040 *twl6040) | ||
226 | { | ||
227 | return twl6040->rev; | ||
228 | } | ||
229 | |||
228 | #endif /* End of __TWL6040_CODEC_H__ */ | 230 | #endif /* End of __TWL6040_CODEC_H__ */ |
diff --git a/include/linux/mfd/wm8994/registers.h b/include/linux/mfd/wm8994/registers.h index f3ee84284670..83ecdcd8aaf9 100644 --- a/include/linux/mfd/wm8994/registers.h +++ b/include/linux/mfd/wm8994/registers.h | |||
@@ -72,6 +72,7 @@ | |||
72 | #define WM8994_DC_SERVO_2 0x55 | 72 | #define WM8994_DC_SERVO_2 0x55 |
73 | #define WM8994_DC_SERVO_4 0x57 | 73 | #define WM8994_DC_SERVO_4 0x57 |
74 | #define WM8994_DC_SERVO_READBACK 0x58 | 74 | #define WM8994_DC_SERVO_READBACK 0x58 |
75 | #define WM8994_DC_SERVO_4E 0x59 | ||
75 | #define WM8994_ANALOGUE_HP_1 0x60 | 76 | #define WM8994_ANALOGUE_HP_1 0x60 |
76 | #define WM8958_MIC_DETECT_1 0xD0 | 77 | #define WM8958_MIC_DETECT_1 0xD0 |
77 | #define WM8958_MIC_DETECT_2 0xD1 | 78 | #define WM8958_MIC_DETECT_2 0xD1 |
@@ -133,6 +134,8 @@ | |||
133 | #define WM8994_AIF1_DAC1_FILTERS_2 0x421 | 134 | #define WM8994_AIF1_DAC1_FILTERS_2 0x421 |
134 | #define WM8994_AIF1_DAC2_FILTERS_1 0x422 | 135 | #define WM8994_AIF1_DAC2_FILTERS_1 0x422 |
135 | #define WM8994_AIF1_DAC2_FILTERS_2 0x423 | 136 | #define WM8994_AIF1_DAC2_FILTERS_2 0x423 |
137 | #define WM8958_AIF1_DAC1_NOISE_GATE 0x430 | ||
138 | #define WM8958_AIF1_DAC2_NOISE_GATE 0x431 | ||
136 | #define WM8994_AIF1_DRC1_1 0x440 | 139 | #define WM8994_AIF1_DRC1_1 0x440 |
137 | #define WM8994_AIF1_DRC1_2 0x441 | 140 | #define WM8994_AIF1_DRC1_2 0x441 |
138 | #define WM8994_AIF1_DRC1_3 0x442 | 141 | #define WM8994_AIF1_DRC1_3 0x442 |
@@ -190,6 +193,7 @@ | |||
190 | #define WM8994_AIF2_ADC_FILTERS 0x510 | 193 | #define WM8994_AIF2_ADC_FILTERS 0x510 |
191 | #define WM8994_AIF2_DAC_FILTERS_1 0x520 | 194 | #define WM8994_AIF2_DAC_FILTERS_1 0x520 |
192 | #define WM8994_AIF2_DAC_FILTERS_2 0x521 | 195 | #define WM8994_AIF2_DAC_FILTERS_2 0x521 |
196 | #define WM8958_AIF2_DAC_NOISE_GATE 0x530 | ||
193 | #define WM8994_AIF2_DRC_1 0x540 | 197 | #define WM8994_AIF2_DRC_1 0x540 |
194 | #define WM8994_AIF2_DRC_2 0x541 | 198 | #define WM8994_AIF2_DRC_2 0x541 |
195 | #define WM8994_AIF2_DRC_3 0x542 | 199 | #define WM8994_AIF2_DRC_3 0x542 |
@@ -1921,6 +1925,44 @@ | |||
1921 | #define WM8994_LDO2_DISCH_WIDTH 1 /* LDO2_DISCH */ | 1925 | #define WM8994_LDO2_DISCH_WIDTH 1 /* LDO2_DISCH */ |
1922 | 1926 | ||
1923 | /* | 1927 | /* |
1928 | * R61 (0x3D) - MICBIAS1 | ||
1929 | */ | ||
1930 | #define WM8958_MICB1_RATE 0x0020 /* MICB1_RATE */ | ||
1931 | #define WM8958_MICB1_RATE_MASK 0x0020 /* MICB1_RATE */ | ||
1932 | #define WM8958_MICB1_RATE_SHIFT 5 /* MICB1_RATE */ | ||
1933 | #define WM8958_MICB1_RATE_WIDTH 1 /* MICB1_RATE */ | ||
1934 | #define WM8958_MICB1_MODE 0x0010 /* MICB1_MODE */ | ||
1935 | #define WM8958_MICB1_MODE_MASK 0x0010 /* MICB1_MODE */ | ||
1936 | #define WM8958_MICB1_MODE_SHIFT 4 /* MICB1_MODE */ | ||
1937 | #define WM8958_MICB1_MODE_WIDTH 1 /* MICB1_MODE */ | ||
1938 | #define WM8958_MICB1_LVL_MASK 0x000E /* MICB1_LVL - [3:1] */ | ||
1939 | #define WM8958_MICB1_LVL_SHIFT 1 /* MICB1_LVL - [3:1] */ | ||
1940 | #define WM8958_MICB1_LVL_WIDTH 3 /* MICB1_LVL - [3:1] */ | ||
1941 | #define WM8958_MICB1_DISCH 0x0001 /* MICB1_DISCH */ | ||
1942 | #define WM8958_MICB1_DISCH_MASK 0x0001 /* MICB1_DISCH */ | ||
1943 | #define WM8958_MICB1_DISCH_SHIFT 0 /* MICB1_DISCH */ | ||
1944 | #define WM8958_MICB1_DISCH_WIDTH 1 /* MICB1_DISCH */ | ||
1945 | |||
1946 | /* | ||
1947 | * R62 (0x3E) - MICBIAS2 | ||
1948 | */ | ||
1949 | #define WM8958_MICB2_RATE 0x0020 /* MICB2_RATE */ | ||
1950 | #define WM8958_MICB2_RATE_MASK 0x0020 /* MICB2_RATE */ | ||
1951 | #define WM8958_MICB2_RATE_SHIFT 5 /* MICB2_RATE */ | ||
1952 | #define WM8958_MICB2_RATE_WIDTH 1 /* MICB2_RATE */ | ||
1953 | #define WM8958_MICB2_MODE 0x0010 /* MICB2_MODE */ | ||
1954 | #define WM8958_MICB2_MODE_MASK 0x0010 /* MICB2_MODE */ | ||
1955 | #define WM8958_MICB2_MODE_SHIFT 4 /* MICB2_MODE */ | ||
1956 | #define WM8958_MICB2_MODE_WIDTH 1 /* MICB2_MODE */ | ||
1957 | #define WM8958_MICB2_LVL_MASK 0x000E /* MICB2_LVL - [3:1] */ | ||
1958 | #define WM8958_MICB2_LVL_SHIFT 1 /* MICB2_LVL - [3:1] */ | ||
1959 | #define WM8958_MICB2_LVL_WIDTH 3 /* MICB2_LVL - [3:1] */ | ||
1960 | #define WM8958_MICB2_DISCH 0x0001 /* MICB2_DISCH */ | ||
1961 | #define WM8958_MICB2_DISCH_MASK 0x0001 /* MICB2_DISCH */ | ||
1962 | #define WM8958_MICB2_DISCH_SHIFT 0 /* MICB2_DISCH */ | ||
1963 | #define WM8958_MICB2_DISCH_WIDTH 1 /* MICB2_DISCH */ | ||
1964 | |||
1965 | /* | ||
1924 | * R76 (0x4C) - Charge Pump (1) | 1966 | * R76 (0x4C) - Charge Pump (1) |
1925 | */ | 1967 | */ |
1926 | #define WM8994_CP_ENA 0x8000 /* CP_ENA */ | 1968 | #define WM8994_CP_ENA 0x8000 /* CP_ENA */ |
@@ -2949,6 +2991,34 @@ | |||
2949 | #define WM8994_AIF1DAC2_3D_ENA_WIDTH 1 /* AIF1DAC2_3D_ENA */ | 2991 | #define WM8994_AIF1DAC2_3D_ENA_WIDTH 1 /* AIF1DAC2_3D_ENA */ |
2950 | 2992 | ||
2951 | /* | 2993 | /* |
2994 | * R1072 (0x430) - AIF1 DAC1 Noise Gate | ||
2995 | */ | ||
2996 | #define WM8958_AIF1DAC1_NG_HLD_MASK 0x0060 /* AIF1DAC1_NG_HLD - [6:5] */ | ||
2997 | #define WM8958_AIF1DAC1_NG_HLD_SHIFT 5 /* AIF1DAC1_NG_HLD - [6:5] */ | ||
2998 | #define WM8958_AIF1DAC1_NG_HLD_WIDTH 2 /* AIF1DAC1_NG_HLD - [6:5] */ | ||
2999 | #define WM8958_AIF1DAC1_NG_THR_MASK 0x000E /* AIF1DAC1_NG_THR - [3:1] */ | ||
3000 | #define WM8958_AIF1DAC1_NG_THR_SHIFT 1 /* AIF1DAC1_NG_THR - [3:1] */ | ||
3001 | #define WM8958_AIF1DAC1_NG_THR_WIDTH 3 /* AIF1DAC1_NG_THR - [3:1] */ | ||
3002 | #define WM8958_AIF1DAC1_NG_ENA 0x0001 /* AIF1DAC1_NG_ENA */ | ||
3003 | #define WM8958_AIF1DAC1_NG_ENA_MASK 0x0001 /* AIF1DAC1_NG_ENA */ | ||
3004 | #define WM8958_AIF1DAC1_NG_ENA_SHIFT 0 /* AIF1DAC1_NG_ENA */ | ||
3005 | #define WM8958_AIF1DAC1_NG_ENA_WIDTH 1 /* AIF1DAC1_NG_ENA */ | ||
3006 | |||
3007 | /* | ||
3008 | * R1073 (0x431) - AIF1 DAC2 Noise Gate | ||
3009 | */ | ||
3010 | #define WM8958_AIF1DAC2_NG_HLD_MASK 0x0060 /* AIF1DAC2_NG_HLD - [6:5] */ | ||
3011 | #define WM8958_AIF1DAC2_NG_HLD_SHIFT 5 /* AIF1DAC2_NG_HLD - [6:5] */ | ||
3012 | #define WM8958_AIF1DAC2_NG_HLD_WIDTH 2 /* AIF1DAC2_NG_HLD - [6:5] */ | ||
3013 | #define WM8958_AIF1DAC2_NG_THR_MASK 0x000E /* AIF1DAC2_NG_THR - [3:1] */ | ||
3014 | #define WM8958_AIF1DAC2_NG_THR_SHIFT 1 /* AIF1DAC2_NG_THR - [3:1] */ | ||
3015 | #define WM8958_AIF1DAC2_NG_THR_WIDTH 3 /* AIF1DAC2_NG_THR - [3:1] */ | ||
3016 | #define WM8958_AIF1DAC2_NG_ENA 0x0001 /* AIF1DAC2_NG_ENA */ | ||
3017 | #define WM8958_AIF1DAC2_NG_ENA_MASK 0x0001 /* AIF1DAC2_NG_ENA */ | ||
3018 | #define WM8958_AIF1DAC2_NG_ENA_SHIFT 0 /* AIF1DAC2_NG_ENA */ | ||
3019 | #define WM8958_AIF1DAC2_NG_ENA_WIDTH 1 /* AIF1DAC2_NG_ENA */ | ||
3020 | |||
3021 | /* | ||
2952 | * R1088 (0x440) - AIF1 DRC1 (1) | 3022 | * R1088 (0x440) - AIF1 DRC1 (1) |
2953 | */ | 3023 | */ |
2954 | #define WM8994_AIF1DRC1_SIG_DET_RMS_MASK 0xF800 /* AIF1DRC1_SIG_DET_RMS - [15:11] */ | 3024 | #define WM8994_AIF1DRC1_SIG_DET_RMS_MASK 0xF800 /* AIF1DRC1_SIG_DET_RMS - [15:11] */ |
@@ -3560,6 +3630,20 @@ | |||
3560 | #define WM8994_AIF2DAC_3D_ENA_WIDTH 1 /* AIF2DAC_3D_ENA */ | 3630 | #define WM8994_AIF2DAC_3D_ENA_WIDTH 1 /* AIF2DAC_3D_ENA */ |
3561 | 3631 | ||
3562 | /* | 3632 | /* |
3633 | * R1328 (0x530) - AIF2 DAC Noise Gate | ||
3634 | */ | ||
3635 | #define WM8958_AIF2DAC_NG_HLD_MASK 0x0060 /* AIF2DAC_NG_HLD - [6:5] */ | ||
3636 | #define WM8958_AIF2DAC_NG_HLD_SHIFT 5 /* AIF2DAC_NG_HLD - [6:5] */ | ||
3637 | #define WM8958_AIF2DAC_NG_HLD_WIDTH 2 /* AIF2DAC_NG_HLD - [6:5] */ | ||
3638 | #define WM8958_AIF2DAC_NG_THR_MASK 0x000E /* AIF2DAC_NG_THR - [3:1] */ | ||
3639 | #define WM8958_AIF2DAC_NG_THR_SHIFT 1 /* AIF2DAC_NG_THR - [3:1] */ | ||
3640 | #define WM8958_AIF2DAC_NG_THR_WIDTH 3 /* AIF2DAC_NG_THR - [3:1] */ | ||
3641 | #define WM8958_AIF2DAC_NG_ENA 0x0001 /* AIF2DAC_NG_ENA */ | ||
3642 | #define WM8958_AIF2DAC_NG_ENA_MASK 0x0001 /* AIF2DAC_NG_ENA */ | ||
3643 | #define WM8958_AIF2DAC_NG_ENA_SHIFT 0 /* AIF2DAC_NG_ENA */ | ||
3644 | #define WM8958_AIF2DAC_NG_ENA_WIDTH 1 /* AIF2DAC_NG_ENA */ | ||
3645 | |||
3646 | /* | ||
3563 | * R1344 (0x540) - AIF2 DRC (1) | 3647 | * R1344 (0x540) - AIF2 DRC (1) |
3564 | */ | 3648 | */ |
3565 | #define WM8994_AIF2DRC_SIG_DET_RMS_MASK 0xF800 /* AIF2DRC_SIG_DET_RMS - [15:11] */ | 3649 | #define WM8994_AIF2DRC_SIG_DET_RMS_MASK 0xF800 /* AIF2DRC_SIG_DET_RMS - [15:11] */ |
diff --git a/include/linux/regmap.h b/include/linux/regmap.h index 60a65cd7e1a0..003c05349ae5 100644 --- a/include/linux/regmap.h +++ b/include/linux/regmap.h | |||
@@ -20,9 +20,61 @@ | |||
20 | struct i2c_client; | 20 | struct i2c_client; |
21 | struct spi_device; | 21 | struct spi_device; |
22 | 22 | ||
23 | /** | ||
24 | * Default value for a register. We use an array of structs rather | ||
25 | * than a simple array as many modern devices have very sparse | ||
26 | * register maps. | ||
27 | * | ||
28 | * @reg: Register address. | ||
29 | * @def: Register default value. | ||
30 | */ | ||
31 | struct reg_default { | ||
32 | unsigned int reg; | ||
33 | unsigned int def; | ||
34 | }; | ||
35 | |||
36 | /** | ||
37 | * Configuration for the register map of a device. | ||
38 | * | ||
39 | * @reg_bits: Number of bits in a register address, mandatory. | ||
40 | * @val_bits: Number of bits in a register value, mandatory. | ||
41 | * | ||
42 | * @writeable_reg: Optional callback returning true if the register | ||
43 | * can be written to. | ||
44 | * @readable_reg: Optional callback returning true if the register | ||
45 | * can be read from. | ||
46 | * @volatile_reg: Optional callback returning true if the register | ||
47 | * value can't be cached. | ||
48 | * @precious_reg: Optional callback returning true if the rgister | ||
49 | * should not be read outside of a call from the driver | ||
50 | * (eg, a clear on read interrupt status register). | ||
51 | * | ||
52 | * @max_register: Optional, specifies the maximum valid register index. | ||
53 | * @reg_defaults: Power on reset values for registers (for use with | ||
54 | * register cache support). | ||
55 | * @num_reg_defaults: Number of elements in reg_defaults. | ||
56 | * | ||
57 | * @read_flag_mask: Mask to be set in the top byte of the register when doing | ||
58 | * a read. | ||
59 | * @write_flag_mask: Mask to be set in the top byte of the register when doing | ||
60 | * a write. If both read_flag_mask and write_flag_mask are | ||
61 | * empty the regmap_bus default masks are used. | ||
62 | */ | ||
23 | struct regmap_config { | 63 | struct regmap_config { |
24 | int reg_bits; | 64 | int reg_bits; |
25 | int val_bits; | 65 | int val_bits; |
66 | |||
67 | bool (*writeable_reg)(struct device *dev, unsigned int reg); | ||
68 | bool (*readable_reg)(struct device *dev, unsigned int reg); | ||
69 | bool (*volatile_reg)(struct device *dev, unsigned int reg); | ||
70 | bool (*precious_reg)(struct device *dev, unsigned int reg); | ||
71 | |||
72 | unsigned int max_register; | ||
73 | struct reg_default *reg_defaults; | ||
74 | int num_reg_defaults; | ||
75 | |||
76 | u8 read_flag_mask; | ||
77 | u8 write_flag_mask; | ||
26 | }; | 78 | }; |
27 | 79 | ||
28 | typedef int (*regmap_hw_write)(struct device *dev, const void *data, | 80 | typedef int (*regmap_hw_write)(struct device *dev, const void *data, |
diff --git a/include/linux/regulator/consumer.h b/include/linux/regulator/consumer.h index 26f6ea4444e3..6fae97a6ce7d 100644 --- a/include/linux/regulator/consumer.h +++ b/include/linux/regulator/consumer.h | |||
@@ -141,6 +141,7 @@ int regulator_enable(struct regulator *regulator); | |||
141 | int regulator_disable(struct regulator *regulator); | 141 | int regulator_disable(struct regulator *regulator); |
142 | int regulator_force_disable(struct regulator *regulator); | 142 | int regulator_force_disable(struct regulator *regulator); |
143 | int regulator_is_enabled(struct regulator *regulator); | 143 | int regulator_is_enabled(struct regulator *regulator); |
144 | int regulator_disable_deferred(struct regulator *regulator, int ms); | ||
144 | 145 | ||
145 | int regulator_bulk_get(struct device *dev, int num_consumers, | 146 | int regulator_bulk_get(struct device *dev, int num_consumers, |
146 | struct regulator_bulk_data *consumers); | 147 | struct regulator_bulk_data *consumers); |
@@ -211,6 +212,12 @@ static inline int regulator_disable(struct regulator *regulator) | |||
211 | return 0; | 212 | return 0; |
212 | } | 213 | } |
213 | 214 | ||
215 | static inline int regulator_disable_deferred(struct regulator *regulator, | ||
216 | int ms) | ||
217 | { | ||
218 | return 0; | ||
219 | } | ||
220 | |||
214 | static inline int regulator_is_enabled(struct regulator *regulator) | 221 | static inline int regulator_is_enabled(struct regulator *regulator) |
215 | { | 222 | { |
216 | return 1; | 223 | return 1; |
diff --git a/include/linux/regulator/driver.h b/include/linux/regulator/driver.h index 1a80bc77517d..12a1aa04b720 100644 --- a/include/linux/regulator/driver.h +++ b/include/linux/regulator/driver.h | |||
@@ -199,6 +199,9 @@ struct regulator_dev { | |||
199 | struct regulation_constraints *constraints; | 199 | struct regulation_constraints *constraints; |
200 | struct regulator *supply; /* for tree */ | 200 | struct regulator *supply; /* for tree */ |
201 | 201 | ||
202 | struct delayed_work disable_work; | ||
203 | int deferred_disables; | ||
204 | |||
202 | void *reg_data; /* regulator_dev data */ | 205 | void *reg_data; /* regulator_dev data */ |
203 | 206 | ||
204 | #ifdef CONFIG_DEBUG_FS | 207 | #ifdef CONFIG_DEBUG_FS |
diff --git a/include/sound/adau1373.h b/include/sound/adau1373.h new file mode 100644 index 000000000000..1b19c7666574 --- /dev/null +++ b/include/sound/adau1373.h | |||
@@ -0,0 +1,34 @@ | |||
1 | /* | ||
2 | * Analog Devices ADAU1373 Audio Codec drive | ||
3 | * | ||
4 | * Copyright 2011 Analog Devices Inc. | ||
5 | * Author: Lars-Peter Clausen <lars@metafoo.de> | ||
6 | * | ||
7 | * Licensed under the GPL-2 or later. | ||
8 | */ | ||
9 | |||
10 | #ifndef __SOUND_ADAU1373_H__ | ||
11 | #define __SOUND_ADAU1373_H__ | ||
12 | |||
13 | enum adau1373_micbias_voltage { | ||
14 | ADAU1373_MICBIAS_2_9V = 0, | ||
15 | ADAU1373_MICBIAS_2_2V = 1, | ||
16 | ADAU1373_MICBIAS_2_6V = 2, | ||
17 | ADAU1373_MICBIAS_1_8V = 3, | ||
18 | }; | ||
19 | |||
20 | #define ADAU1373_DRC_SIZE 13 | ||
21 | |||
22 | struct adau1373_platform_data { | ||
23 | bool input_differential[4]; | ||
24 | bool lineout_differential; | ||
25 | bool lineout_ground_sense; | ||
26 | |||
27 | unsigned int num_drc; | ||
28 | uint8_t drc_setting[3][ADAU1373_DRC_SIZE]; | ||
29 | |||
30 | enum adau1373_micbias_voltage micbias1; | ||
31 | enum adau1373_micbias_voltage micbias2; | ||
32 | }; | ||
33 | |||
34 | #endif | ||
diff --git a/include/sound/initval.h b/include/sound/initval.h index 1daa6dff8297..f99a0d2ddfe7 100644 --- a/include/sound/initval.h +++ b/include/sound/initval.h | |||
@@ -62,7 +62,7 @@ static int snd_legacy_find_free_irq(int *irq_table) | |||
62 | { | 62 | { |
63 | while (*irq_table != -1) { | 63 | while (*irq_table != -1) { |
64 | if (!request_irq(*irq_table, snd_legacy_empty_irq_handler, | 64 | if (!request_irq(*irq_table, snd_legacy_empty_irq_handler, |
65 | IRQF_DISABLED | IRQF_PROBE_SHARED, "ALSA Test IRQ", | 65 | IRQF_PROBE_SHARED, "ALSA Test IRQ", |
66 | (void *) irq_table)) { | 66 | (void *) irq_table)) { |
67 | free_irq(*irq_table, (void *) irq_table); | 67 | free_irq(*irq_table, (void *) irq_table); |
68 | return *irq_table; | 68 | return *irq_table; |
diff --git a/include/sound/saif.h b/include/sound/saif.h new file mode 100644 index 000000000000..d0e0de7984ec --- /dev/null +++ b/include/sound/saif.h | |||
@@ -0,0 +1,16 @@ | |||
1 | /* | ||
2 | * Copyright 2011 Freescale Semiconductor, Inc. All Rights Reserved. | ||
3 | * | ||
4 | * This program is free software; you can redistribute it and/or modify | ||
5 | * it under the terms of the GNU General Public License version 2 as | ||
6 | * published by the Free Software Foundation. | ||
7 | */ | ||
8 | |||
9 | #ifndef __SOUND_SAIF_H__ | ||
10 | #define __SOUND_SAIF_H__ | ||
11 | |||
12 | struct mxs_saif_platform_data { | ||
13 | int (*init) (void); | ||
14 | int (*get_master_id) (unsigned int saif_id); | ||
15 | }; | ||
16 | #endif | ||
diff --git a/include/sound/soc-dapm.h b/include/sound/soc-dapm.h index e0583b7769cb..350b1b395cac 100644 --- a/include/sound/soc-dapm.h +++ b/include/sound/soc-dapm.h | |||
@@ -524,6 +524,8 @@ struct snd_soc_dapm_context { | |||
524 | enum snd_soc_bias_level target_bias_level; | 524 | enum snd_soc_bias_level target_bias_level; |
525 | struct list_head list; | 525 | struct list_head list; |
526 | 526 | ||
527 | int (*stream_event)(struct snd_soc_dapm_context *dapm, int event); | ||
528 | |||
527 | #ifdef CONFIG_DEBUG_FS | 529 | #ifdef CONFIG_DEBUG_FS |
528 | struct dentry *debugfs_dapm; | 530 | struct dentry *debugfs_dapm; |
529 | #endif | 531 | #endif |
diff --git a/include/sound/soc.h b/include/sound/soc.h index aa19f5a32ba8..24e17be38c19 100644 --- a/include/sound/soc.h +++ b/include/sound/soc.h | |||
@@ -19,6 +19,7 @@ | |||
19 | #include <linux/workqueue.h> | 19 | #include <linux/workqueue.h> |
20 | #include <linux/interrupt.h> | 20 | #include <linux/interrupt.h> |
21 | #include <linux/kernel.h> | 21 | #include <linux/kernel.h> |
22 | #include <linux/regmap.h> | ||
22 | #include <sound/core.h> | 23 | #include <sound/core.h> |
23 | #include <sound/pcm.h> | 24 | #include <sound/pcm.h> |
24 | #include <sound/control.h> | 25 | #include <sound/control.h> |
@@ -260,6 +261,7 @@ extern struct snd_ac97_bus_ops soc_ac97_ops; | |||
260 | enum snd_soc_control_type { | 261 | enum snd_soc_control_type { |
261 | SND_SOC_I2C = 1, | 262 | SND_SOC_I2C = 1, |
262 | SND_SOC_SPI, | 263 | SND_SOC_SPI, |
264 | SND_SOC_REGMAP, | ||
263 | }; | 265 | }; |
264 | 266 | ||
265 | enum snd_soc_compress_type { | 267 | enum snd_soc_compress_type { |
@@ -274,7 +276,7 @@ enum snd_soc_pcm_subclass { | |||
274 | }; | 276 | }; |
275 | 277 | ||
276 | int snd_soc_codec_set_sysclk(struct snd_soc_codec *codec, int clk_id, | 278 | int snd_soc_codec_set_sysclk(struct snd_soc_codec *codec, int clk_id, |
277 | unsigned int freq, int dir); | 279 | int source, unsigned int freq, int dir); |
278 | int snd_soc_codec_set_pll(struct snd_soc_codec *codec, int pll_id, int source, | 280 | int snd_soc_codec_set_pll(struct snd_soc_codec *codec, int pll_id, int source, |
279 | unsigned int freq_in, unsigned int freq_out); | 281 | unsigned int freq_in, unsigned int freq_out); |
280 | 282 | ||
@@ -576,6 +578,7 @@ struct snd_soc_codec { | |||
576 | const void *reg_def_copy; | 578 | const void *reg_def_copy; |
577 | const struct snd_soc_cache_ops *cache_ops; | 579 | const struct snd_soc_cache_ops *cache_ops; |
578 | struct mutex cache_rw_mutex; | 580 | struct mutex cache_rw_mutex; |
581 | int val_bytes; | ||
579 | 582 | ||
580 | /* dapm */ | 583 | /* dapm */ |
581 | struct snd_soc_dapm_context dapm; | 584 | struct snd_soc_dapm_context dapm; |
@@ -607,7 +610,7 @@ struct snd_soc_codec_driver { | |||
607 | 610 | ||
608 | /* codec wide operations */ | 611 | /* codec wide operations */ |
609 | int (*set_sysclk)(struct snd_soc_codec *codec, | 612 | int (*set_sysclk)(struct snd_soc_codec *codec, |
610 | int clk_id, unsigned int freq, int dir); | 613 | int clk_id, int source, unsigned int freq, int dir); |
611 | int (*set_pll)(struct snd_soc_codec *codec, int pll_id, int source, | 614 | int (*set_pll)(struct snd_soc_codec *codec, int pll_id, int source, |
612 | unsigned int freq_in, unsigned int freq_out); | 615 | unsigned int freq_in, unsigned int freq_out); |
613 | 616 | ||
@@ -619,7 +622,7 @@ struct snd_soc_codec_driver { | |||
619 | int (*volatile_register)(struct snd_soc_codec *, unsigned int); | 622 | int (*volatile_register)(struct snd_soc_codec *, unsigned int); |
620 | int (*readable_register)(struct snd_soc_codec *, unsigned int); | 623 | int (*readable_register)(struct snd_soc_codec *, unsigned int); |
621 | int (*writable_register)(struct snd_soc_codec *, unsigned int); | 624 | int (*writable_register)(struct snd_soc_codec *, unsigned int); |
622 | short reg_cache_size; | 625 | unsigned int reg_cache_size; |
623 | short reg_cache_step; | 626 | short reg_cache_step; |
624 | short reg_word_size; | 627 | short reg_word_size; |
625 | const void *reg_cache_default; | 628 | const void *reg_cache_default; |
@@ -630,10 +633,14 @@ struct snd_soc_codec_driver { | |||
630 | /* codec bias level */ | 633 | /* codec bias level */ |
631 | int (*set_bias_level)(struct snd_soc_codec *, | 634 | int (*set_bias_level)(struct snd_soc_codec *, |
632 | enum snd_soc_bias_level level); | 635 | enum snd_soc_bias_level level); |
636 | bool idle_bias_off; | ||
633 | 637 | ||
634 | void (*seq_notifier)(struct snd_soc_dapm_context *, | 638 | void (*seq_notifier)(struct snd_soc_dapm_context *, |
635 | enum snd_soc_dapm_type, int); | 639 | enum snd_soc_dapm_type, int); |
636 | 640 | ||
641 | /* codec stream completion event */ | ||
642 | int (*stream_event)(struct snd_soc_dapm_context *dapm, int event); | ||
643 | |||
637 | /* probe ordering - for components with runtime dependencies */ | 644 | /* probe ordering - for components with runtime dependencies */ |
638 | int probe_order; | 645 | int probe_order; |
639 | int remove_order; | 646 | int remove_order; |
@@ -669,6 +676,9 @@ struct snd_soc_platform_driver { | |||
669 | /* platform stream ops */ | 676 | /* platform stream ops */ |
670 | struct snd_pcm_ops *ops; | 677 | struct snd_pcm_ops *ops; |
671 | 678 | ||
679 | /* platform stream completion event */ | ||
680 | int (*stream_event)(struct snd_soc_dapm_context *dapm, int event); | ||
681 | |||
672 | /* probe ordering - for components with runtime dependencies */ | 682 | /* probe ordering - for components with runtime dependencies */ |
673 | int probe_order; | 683 | int probe_order; |
674 | int remove_order; | 684 | int remove_order; |
diff --git a/sound/arm/aaci.c b/sound/arm/aaci.c index d0cead38d5fb..e518d38b1c74 100644 --- a/sound/arm/aaci.c +++ b/sound/arm/aaci.c | |||
@@ -443,7 +443,7 @@ static int aaci_pcm_open(struct snd_pcm_substream *substream) | |||
443 | mutex_lock(&aaci->irq_lock); | 443 | mutex_lock(&aaci->irq_lock); |
444 | if (!aaci->users++) { | 444 | if (!aaci->users++) { |
445 | ret = request_irq(aaci->dev->irq[0], aaci_irq, | 445 | ret = request_irq(aaci->dev->irq[0], aaci_irq, |
446 | IRQF_SHARED | IRQF_DISABLED, DRIVER_NAME, aaci); | 446 | IRQF_SHARED, DRIVER_NAME, aaci); |
447 | if (ret != 0) | 447 | if (ret != 0) |
448 | aaci->users--; | 448 | aaci->users--; |
449 | } | 449 | } |
diff --git a/sound/arm/pxa2xx-ac97-lib.c b/sound/arm/pxa2xx-ac97-lib.c index 88eec3847df2..8ad65352bf91 100644 --- a/sound/arm/pxa2xx-ac97-lib.c +++ b/sound/arm/pxa2xx-ac97-lib.c | |||
@@ -359,7 +359,7 @@ int __devinit pxa2xx_ac97_hw_probe(struct platform_device *dev) | |||
359 | if (ret) | 359 | if (ret) |
360 | goto err_clk2; | 360 | goto err_clk2; |
361 | 361 | ||
362 | ret = request_irq(IRQ_AC97, pxa2xx_ac97_irq, IRQF_DISABLED, "AC97", NULL); | 362 | ret = request_irq(IRQ_AC97, pxa2xx_ac97_irq, 0, "AC97", NULL); |
363 | if (ret < 0) | 363 | if (ret < 0) |
364 | goto err_irq; | 364 | goto err_irq; |
365 | 365 | ||
diff --git a/sound/drivers/ml403-ac97cr.c b/sound/drivers/ml403-ac97cr.c index 5cfcb908c430..2c7a7636f472 100644 --- a/sound/drivers/ml403-ac97cr.c +++ b/sound/drivers/ml403-ac97cr.c | |||
@@ -1153,7 +1153,7 @@ snd_ml403_ac97cr_create(struct snd_card *card, struct platform_device *pfdev, | |||
1153 | "0x%x done\n", (unsigned int)ml403_ac97cr->port); | 1153 | "0x%x done\n", (unsigned int)ml403_ac97cr->port); |
1154 | /* get irq */ | 1154 | /* get irq */ |
1155 | irq = platform_get_irq(pfdev, 0); | 1155 | irq = platform_get_irq(pfdev, 0); |
1156 | if (request_irq(irq, snd_ml403_ac97cr_irq, IRQF_DISABLED, | 1156 | if (request_irq(irq, snd_ml403_ac97cr_irq, 0, |
1157 | dev_name(&pfdev->dev), (void *)ml403_ac97cr)) { | 1157 | dev_name(&pfdev->dev), (void *)ml403_ac97cr)) { |
1158 | snd_printk(KERN_ERR SND_ML403_AC97CR_DRIVER ": " | 1158 | snd_printk(KERN_ERR SND_ML403_AC97CR_DRIVER ": " |
1159 | "unable to grab IRQ %d\n", | 1159 | "unable to grab IRQ %d\n", |
@@ -1166,7 +1166,7 @@ snd_ml403_ac97cr_create(struct snd_card *card, struct platform_device *pfdev, | |||
1166 | "request (playback) irq %d done\n", | 1166 | "request (playback) irq %d done\n", |
1167 | ml403_ac97cr->irq); | 1167 | ml403_ac97cr->irq); |
1168 | irq = platform_get_irq(pfdev, 1); | 1168 | irq = platform_get_irq(pfdev, 1); |
1169 | if (request_irq(irq, snd_ml403_ac97cr_irq, IRQF_DISABLED, | 1169 | if (request_irq(irq, snd_ml403_ac97cr_irq, 0, |
1170 | dev_name(&pfdev->dev), (void *)ml403_ac97cr)) { | 1170 | dev_name(&pfdev->dev), (void *)ml403_ac97cr)) { |
1171 | snd_printk(KERN_ERR SND_ML403_AC97CR_DRIVER ": " | 1171 | snd_printk(KERN_ERR SND_ML403_AC97CR_DRIVER ": " |
1172 | "unable to grab IRQ %d\n", | 1172 | "unable to grab IRQ %d\n", |
diff --git a/sound/drivers/mpu401/mpu401_uart.c b/sound/drivers/mpu401/mpu401_uart.c index 9d01c181feca..e91698a634b2 100644 --- a/sound/drivers/mpu401/mpu401_uart.c +++ b/sound/drivers/mpu401/mpu401_uart.c | |||
@@ -577,7 +577,7 @@ int snd_mpu401_uart_new(struct snd_card *card, int device, | |||
577 | else | 577 | else |
578 | mpu->cport = port + 1; | 578 | mpu->cport = port + 1; |
579 | if (irq >= 0) { | 579 | if (irq >= 0) { |
580 | if (request_irq(irq, snd_mpu401_uart_interrupt, IRQF_DISABLED, | 580 | if (request_irq(irq, snd_mpu401_uart_interrupt, 0, |
581 | "MPU401 UART", (void *) mpu)) { | 581 | "MPU401 UART", (void *) mpu)) { |
582 | snd_printk(KERN_ERR "mpu401_uart: " | 582 | snd_printk(KERN_ERR "mpu401_uart: " |
583 | "unable to grab IRQ %d\n", irq); | 583 | "unable to grab IRQ %d\n", irq); |
diff --git a/sound/drivers/mtpav.c b/sound/drivers/mtpav.c index 5c426df87678..1eef4ccebe4b 100644 --- a/sound/drivers/mtpav.c +++ b/sound/drivers/mtpav.c | |||
@@ -589,7 +589,7 @@ static int __devinit snd_mtpav_get_ISA(struct mtpav * mcard) | |||
589 | return -EBUSY; | 589 | return -EBUSY; |
590 | } | 590 | } |
591 | mcard->port = port; | 591 | mcard->port = port; |
592 | if (request_irq(irq, snd_mtpav_irqh, IRQF_DISABLED, "MOTU MTPAV", mcard)) { | 592 | if (request_irq(irq, snd_mtpav_irqh, 0, "MOTU MTPAV", mcard)) { |
593 | snd_printk(KERN_ERR "MTVAP IRQ %d busy\n", irq); | 593 | snd_printk(KERN_ERR "MTVAP IRQ %d busy\n", irq); |
594 | return -EBUSY; | 594 | return -EBUSY; |
595 | } | 595 | } |
diff --git a/sound/drivers/serial-u16550.c b/sound/drivers/serial-u16550.c index a25fb7b1f441..fc1d822802c3 100644 --- a/sound/drivers/serial-u16550.c +++ b/sound/drivers/serial-u16550.c | |||
@@ -816,7 +816,7 @@ static int __devinit snd_uart16550_create(struct snd_card *card, | |||
816 | 816 | ||
817 | if (irq >= 0 && irq != SNDRV_AUTO_IRQ) { | 817 | if (irq >= 0 && irq != SNDRV_AUTO_IRQ) { |
818 | if (request_irq(irq, snd_uart16550_interrupt, | 818 | if (request_irq(irq, snd_uart16550_interrupt, |
819 | IRQF_DISABLED, "Serial MIDI", uart)) { | 819 | 0, "Serial MIDI", uart)) { |
820 | snd_printk(KERN_WARNING | 820 | snd_printk(KERN_WARNING |
821 | "irq %d busy. Using Polling.\n", irq); | 821 | "irq %d busy. Using Polling.\n", irq); |
822 | } else { | 822 | } else { |
diff --git a/sound/isa/ad1816a/ad1816a_lib.c b/sound/isa/ad1816a/ad1816a_lib.c index 05aef8b97e96..177eed3271bc 100644 --- a/sound/isa/ad1816a/ad1816a_lib.c +++ b/sound/isa/ad1816a/ad1816a_lib.c | |||
@@ -595,7 +595,7 @@ int __devinit snd_ad1816a_create(struct snd_card *card, | |||
595 | snd_ad1816a_free(chip); | 595 | snd_ad1816a_free(chip); |
596 | return -EBUSY; | 596 | return -EBUSY; |
597 | } | 597 | } |
598 | if (request_irq(irq, snd_ad1816a_interrupt, IRQF_DISABLED, "AD1816A", (void *) chip)) { | 598 | if (request_irq(irq, snd_ad1816a_interrupt, 0, "AD1816A", (void *) chip)) { |
599 | snd_printk(KERN_ERR "ad1816a: can't grab IRQ %d\n", irq); | 599 | snd_printk(KERN_ERR "ad1816a: can't grab IRQ %d\n", irq); |
600 | snd_ad1816a_free(chip); | 600 | snd_ad1816a_free(chip); |
601 | return -EBUSY; | 601 | return -EBUSY; |
diff --git a/sound/isa/es1688/es1688_lib.c b/sound/isa/es1688/es1688_lib.c index 07676200496a..d3eab6fb0866 100644 --- a/sound/isa/es1688/es1688_lib.c +++ b/sound/isa/es1688/es1688_lib.c | |||
@@ -661,7 +661,7 @@ int snd_es1688_create(struct snd_card *card, | |||
661 | snd_printk(KERN_ERR "es1688: can't grab port 0x%lx\n", port + 4); | 661 | snd_printk(KERN_ERR "es1688: can't grab port 0x%lx\n", port + 4); |
662 | return -EBUSY; | 662 | return -EBUSY; |
663 | } | 663 | } |
664 | if (request_irq(irq, snd_es1688_interrupt, IRQF_DISABLED, "ES1688", (void *) chip)) { | 664 | if (request_irq(irq, snd_es1688_interrupt, 0, "ES1688", (void *) chip)) { |
665 | snd_printk(KERN_ERR "es1688: can't grab IRQ %d\n", irq); | 665 | snd_printk(KERN_ERR "es1688: can't grab IRQ %d\n", irq); |
666 | return -EBUSY; | 666 | return -EBUSY; |
667 | } | 667 | } |
diff --git a/sound/isa/es18xx.c b/sound/isa/es18xx.c index aeee8f8bf5e9..bf6ad0bf51c6 100644 --- a/sound/isa/es18xx.c +++ b/sound/isa/es18xx.c | |||
@@ -1805,7 +1805,7 @@ static int __devinit snd_es18xx_new_device(struct snd_card *card, | |||
1805 | return -EBUSY; | 1805 | return -EBUSY; |
1806 | } | 1806 | } |
1807 | 1807 | ||
1808 | if (request_irq(irq, snd_es18xx_interrupt, IRQF_DISABLED, "ES18xx", | 1808 | if (request_irq(irq, snd_es18xx_interrupt, 0, "ES18xx", |
1809 | (void *) card)) { | 1809 | (void *) card)) { |
1810 | snd_es18xx_free(card); | 1810 | snd_es18xx_free(card); |
1811 | snd_printk(KERN_ERR PFX "unable to grap IRQ %d\n", irq); | 1811 | snd_printk(KERN_ERR PFX "unable to grap IRQ %d\n", irq); |
diff --git a/sound/isa/gus/gus_main.c b/sound/isa/gus/gus_main.c index 12eb98f2f931..3167e5ac3699 100644 --- a/sound/isa/gus/gus_main.c +++ b/sound/isa/gus/gus_main.c | |||
@@ -180,7 +180,7 @@ int snd_gus_create(struct snd_card *card, | |||
180 | snd_gus_free(gus); | 180 | snd_gus_free(gus); |
181 | return -EBUSY; | 181 | return -EBUSY; |
182 | } | 182 | } |
183 | if (irq >= 0 && request_irq(irq, snd_gus_interrupt, IRQF_DISABLED, "GUS GF1", (void *) gus)) { | 183 | if (irq >= 0 && request_irq(irq, snd_gus_interrupt, 0, "GUS GF1", (void *) gus)) { |
184 | snd_printk(KERN_ERR "gus: can't grab irq %d\n", irq); | 184 | snd_printk(KERN_ERR "gus: can't grab irq %d\n", irq); |
185 | snd_gus_free(gus); | 185 | snd_gus_free(gus); |
186 | return -EBUSY; | 186 | return -EBUSY; |
diff --git a/sound/isa/gus/gusmax.c b/sound/isa/gus/gusmax.c index 3e4a58b72913..c43faa057ff6 100644 --- a/sound/isa/gus/gusmax.c +++ b/sound/isa/gus/gusmax.c | |||
@@ -291,7 +291,7 @@ static int __devinit snd_gusmax_probe(struct device *pdev, unsigned int dev) | |||
291 | goto _err; | 291 | goto _err; |
292 | } | 292 | } |
293 | 293 | ||
294 | if (request_irq(xirq, snd_gusmax_interrupt, IRQF_DISABLED, "GUS MAX", (void *)maxcard)) { | 294 | if (request_irq(xirq, snd_gusmax_interrupt, 0, "GUS MAX", (void *)maxcard)) { |
295 | snd_printk(KERN_ERR PFX "unable to grab IRQ %d\n", xirq); | 295 | snd_printk(KERN_ERR PFX "unable to grab IRQ %d\n", xirq); |
296 | err = -EBUSY; | 296 | err = -EBUSY; |
297 | goto _err; | 297 | goto _err; |
diff --git a/sound/isa/gus/interwave.c b/sound/isa/gus/interwave.c index c7b80e4730fc..5f869a32b48c 100644 --- a/sound/isa/gus/interwave.c +++ b/sound/isa/gus/interwave.c | |||
@@ -684,7 +684,7 @@ static int __devinit snd_interwave_probe(struct snd_card *card, int dev) | |||
684 | if ((err = snd_gus_initialize(gus)) < 0) | 684 | if ((err = snd_gus_initialize(gus)) < 0) |
685 | return err; | 685 | return err; |
686 | 686 | ||
687 | if (request_irq(xirq, snd_interwave_interrupt, IRQF_DISABLED, | 687 | if (request_irq(xirq, snd_interwave_interrupt, 0, |
688 | "InterWave", iwcard)) { | 688 | "InterWave", iwcard)) { |
689 | snd_printk(KERN_ERR PFX "unable to grab IRQ %d\n", xirq); | 689 | snd_printk(KERN_ERR PFX "unable to grab IRQ %d\n", xirq); |
690 | return -EBUSY; | 690 | return -EBUSY; |
diff --git a/sound/isa/opl3sa2.c b/sound/isa/opl3sa2.c index de99f47770bf..bbafb0b543ea 100644 --- a/sound/isa/opl3sa2.c +++ b/sound/isa/opl3sa2.c | |||
@@ -667,7 +667,7 @@ static int __devinit snd_opl3sa2_probe(struct snd_card *card, int dev) | |||
667 | err = snd_opl3sa2_detect(card); | 667 | err = snd_opl3sa2_detect(card); |
668 | if (err < 0) | 668 | if (err < 0) |
669 | return err; | 669 | return err; |
670 | err = request_irq(xirq, snd_opl3sa2_interrupt, IRQF_DISABLED, | 670 | err = request_irq(xirq, snd_opl3sa2_interrupt, 0, |
671 | "OPL3-SA2", card); | 671 | "OPL3-SA2", card); |
672 | if (err) { | 672 | if (err) { |
673 | snd_printk(KERN_ERR PFX "can't grab IRQ %d\n", xirq); | 673 | snd_printk(KERN_ERR PFX "can't grab IRQ %d\n", xirq); |
diff --git a/sound/isa/opti9xx/opti92x-ad1848.c b/sound/isa/opti9xx/opti92x-ad1848.c index 346e12baa98e..6dbbfa76b440 100644 --- a/sound/isa/opti9xx/opti92x-ad1848.c +++ b/sound/isa/opti9xx/opti92x-ad1848.c | |||
@@ -892,7 +892,7 @@ static int __devinit snd_opti9xx_probe(struct snd_card *card) | |||
892 | #endif | 892 | #endif |
893 | #ifdef OPTi93X | 893 | #ifdef OPTi93X |
894 | error = request_irq(irq, snd_opti93x_interrupt, | 894 | error = request_irq(irq, snd_opti93x_interrupt, |
895 | IRQF_DISABLED, DEV_NAME" - WSS", chip); | 895 | 0, DEV_NAME" - WSS", chip); |
896 | if (error < 0) { | 896 | if (error < 0) { |
897 | snd_printk(KERN_ERR "opti9xx: can't grab IRQ %d\n", irq); | 897 | snd_printk(KERN_ERR "opti9xx: can't grab IRQ %d\n", irq); |
898 | return error; | 898 | return error; |
diff --git a/sound/isa/sb/sb_common.c b/sound/isa/sb/sb_common.c index eae6c1c0eff9..d2e19215813e 100644 --- a/sound/isa/sb/sb_common.c +++ b/sound/isa/sb/sb_common.c | |||
@@ -240,7 +240,7 @@ int snd_sbdsp_create(struct snd_card *card, | |||
240 | if (request_irq(irq, irq_handler, | 240 | if (request_irq(irq, irq_handler, |
241 | (hardware == SB_HW_ALS4000 || | 241 | (hardware == SB_HW_ALS4000 || |
242 | hardware == SB_HW_CS5530) ? | 242 | hardware == SB_HW_CS5530) ? |
243 | IRQF_SHARED : IRQF_DISABLED, | 243 | IRQF_SHARED : 0, |
244 | "SoundBlaster", (void *) chip)) { | 244 | "SoundBlaster", (void *) chip)) { |
245 | snd_printk(KERN_ERR "sb: can't grab irq %d\n", irq); | 245 | snd_printk(KERN_ERR "sb: can't grab irq %d\n", irq); |
246 | snd_sbdsp_free(chip); | 246 | snd_sbdsp_free(chip); |
diff --git a/sound/isa/wavefront/wavefront.c b/sound/isa/wavefront/wavefront.c index 83f291d89a95..87142977335a 100644 --- a/sound/isa/wavefront/wavefront.c +++ b/sound/isa/wavefront/wavefront.c | |||
@@ -418,7 +418,7 @@ snd_wavefront_probe (struct snd_card *card, int dev) | |||
418 | return -EBUSY; | 418 | return -EBUSY; |
419 | } | 419 | } |
420 | if (request_irq(ics2115_irq[dev], snd_wavefront_ics2115_interrupt, | 420 | if (request_irq(ics2115_irq[dev], snd_wavefront_ics2115_interrupt, |
421 | IRQF_DISABLED, "ICS2115", acard)) { | 421 | 0, "ICS2115", acard)) { |
422 | snd_printk(KERN_ERR "unable to use ICS2115 IRQ %d\n", ics2115_irq[dev]); | 422 | snd_printk(KERN_ERR "unable to use ICS2115 IRQ %d\n", ics2115_irq[dev]); |
423 | return -EBUSY; | 423 | return -EBUSY; |
424 | } | 424 | } |
diff --git a/sound/isa/wss/wss_lib.c b/sound/isa/wss/wss_lib.c index 2a42cc377957..7277c5b7df6c 100644 --- a/sound/isa/wss/wss_lib.c +++ b/sound/isa/wss/wss_lib.c | |||
@@ -1833,7 +1833,7 @@ int snd_wss_create(struct snd_card *card, | |||
1833 | } | 1833 | } |
1834 | chip->cport = cport; | 1834 | chip->cport = cport; |
1835 | if (!(hwshare & WSS_HWSHARE_IRQ)) | 1835 | if (!(hwshare & WSS_HWSHARE_IRQ)) |
1836 | if (request_irq(irq, snd_wss_interrupt, IRQF_DISABLED, | 1836 | if (request_irq(irq, snd_wss_interrupt, 0, |
1837 | "WSS", (void *) chip)) { | 1837 | "WSS", (void *) chip)) { |
1838 | snd_printk(KERN_ERR "wss: can't grab IRQ %d\n", irq); | 1838 | snd_printk(KERN_ERR "wss: can't grab IRQ %d\n", irq); |
1839 | snd_wss_free(chip); | 1839 | snd_wss_free(chip); |
diff --git a/sound/mips/Kconfig b/sound/mips/Kconfig index a9823fad85c2..77dd0a13aecc 100644 --- a/sound/mips/Kconfig +++ b/sound/mips/Kconfig | |||
@@ -23,12 +23,15 @@ config SND_SGI_HAL2 | |||
23 | 23 | ||
24 | 24 | ||
25 | config SND_AU1X00 | 25 | config SND_AU1X00 |
26 | tristate "Au1x00 AC97 Port Driver" | 26 | tristate "Au1x00 AC97 Port Driver (DEPRECATED)" |
27 | depends on SOC_AU1000 || SOC_AU1100 || SOC_AU1500 | 27 | depends on SOC_AU1000 || SOC_AU1100 || SOC_AU1500 |
28 | select SND_PCM | 28 | select SND_PCM |
29 | select SND_AC97_CODEC | 29 | select SND_AC97_CODEC |
30 | help | 30 | help |
31 | ALSA Sound driver for the Au1x00's AC97 port. | 31 | ALSA Sound driver for the Au1x00's AC97 port. |
32 | 32 | ||
33 | Newer drivers for ASoC are available, please do not use | ||
34 | this driver as it will be removed in the future. | ||
35 | |||
33 | endif # SND_MIPS | 36 | endif # SND_MIPS |
34 | 37 | ||
diff --git a/sound/mips/au1x00.c b/sound/mips/au1x00.c index 446cf9748664..7567ebd71913 100644 --- a/sound/mips/au1x00.c +++ b/sound/mips/au1x00.c | |||
@@ -465,13 +465,13 @@ snd_au1000_pcm_new(struct snd_au1000 *au1000) | |||
465 | 465 | ||
466 | flags = claim_dma_lock(); | 466 | flags = claim_dma_lock(); |
467 | if ((au1000->stream[PLAYBACK]->dma = request_au1000_dma(DMA_ID_AC97C_TX, | 467 | if ((au1000->stream[PLAYBACK]->dma = request_au1000_dma(DMA_ID_AC97C_TX, |
468 | "AC97 TX", au1000_dma_interrupt, IRQF_DISABLED, | 468 | "AC97 TX", au1000_dma_interrupt, 0, |
469 | au1000->stream[PLAYBACK])) < 0) { | 469 | au1000->stream[PLAYBACK])) < 0) { |
470 | release_dma_lock(flags); | 470 | release_dma_lock(flags); |
471 | return -EBUSY; | 471 | return -EBUSY; |
472 | } | 472 | } |
473 | if ((au1000->stream[CAPTURE]->dma = request_au1000_dma(DMA_ID_AC97C_RX, | 473 | if ((au1000->stream[CAPTURE]->dma = request_au1000_dma(DMA_ID_AC97C_RX, |
474 | "AC97 RX", au1000_dma_interrupt, IRQF_DISABLED, | 474 | "AC97 RX", au1000_dma_interrupt, 0, |
475 | au1000->stream[CAPTURE])) < 0){ | 475 | au1000->stream[CAPTURE])) < 0){ |
476 | release_dma_lock(flags); | 476 | release_dma_lock(flags); |
477 | return -EBUSY; | 477 | return -EBUSY; |
diff --git a/sound/pci/sis7019.c b/sound/pci/sis7019.c index bcf61524a13f..5ffb20b18786 100644 --- a/sound/pci/sis7019.c +++ b/sound/pci/sis7019.c | |||
@@ -1234,7 +1234,7 @@ static int sis_resume(struct pci_dev *pci) | |||
1234 | goto error; | 1234 | goto error; |
1235 | } | 1235 | } |
1236 | 1236 | ||
1237 | if (request_irq(pci->irq, sis_interrupt, IRQF_DISABLED|IRQF_SHARED, | 1237 | if (request_irq(pci->irq, sis_interrupt, IRQF_SHARED, |
1238 | KBUILD_MODNAME, sis)) { | 1238 | KBUILD_MODNAME, sis)) { |
1239 | printk(KERN_ERR "sis7019: unable to regain IRQ %d\n", pci->irq); | 1239 | printk(KERN_ERR "sis7019: unable to regain IRQ %d\n", pci->irq); |
1240 | goto error; | 1240 | goto error; |
@@ -1340,7 +1340,7 @@ static int __devinit sis_chip_create(struct snd_card *card, | |||
1340 | if (rc) | 1340 | if (rc) |
1341 | goto error_out_cleanup; | 1341 | goto error_out_cleanup; |
1342 | 1342 | ||
1343 | if (request_irq(pci->irq, sis_interrupt, IRQF_DISABLED|IRQF_SHARED, | 1343 | if (request_irq(pci->irq, sis_interrupt, IRQF_SHARED, |
1344 | KBUILD_MODNAME, sis)) { | 1344 | KBUILD_MODNAME, sis)) { |
1345 | printk(KERN_ERR "unable to allocate irq %d\n", sis->irq); | 1345 | printk(KERN_ERR "unable to allocate irq %d\n", sis->irq); |
1346 | goto error_out_cleanup; | 1346 | goto error_out_cleanup; |
diff --git a/sound/ppc/snd_ps3.c b/sound/ppc/snd_ps3.c index bc823a547550..775bd95d4be6 100644 --- a/sound/ppc/snd_ps3.c +++ b/sound/ppc/snd_ps3.c | |||
@@ -845,7 +845,7 @@ static int __devinit snd_ps3_allocate_irq(void) | |||
845 | return ret; | 845 | return ret; |
846 | } | 846 | } |
847 | 847 | ||
848 | ret = request_irq(the_card.irq_no, snd_ps3_interrupt, IRQF_DISABLED, | 848 | ret = request_irq(the_card.irq_no, snd_ps3_interrupt, 0, |
849 | SND_PS3_DRIVER_NAME, &the_card); | 849 | SND_PS3_DRIVER_NAME, &the_card); |
850 | if (ret) { | 850 | if (ret) { |
851 | pr_info("%s: request_irq failed (%d)\n", __func__, ret); | 851 | pr_info("%s: request_irq failed (%d)\n", __func__, ret); |
diff --git a/sound/soc/Kconfig b/sound/soc/Kconfig index 8224db5f0434..1381db853ef0 100644 --- a/sound/soc/Kconfig +++ b/sound/soc/Kconfig | |||
@@ -7,6 +7,8 @@ menuconfig SND_SOC | |||
7 | select SND_PCM | 7 | select SND_PCM |
8 | select AC97_BUS if SND_SOC_AC97_BUS | 8 | select AC97_BUS if SND_SOC_AC97_BUS |
9 | select SND_JACK if INPUT=y || INPUT=SND | 9 | select SND_JACK if INPUT=y || INPUT=SND |
10 | select REGMAP_I2C if I2C | ||
11 | select REGMAP_SPI if SPI_MASTER | ||
10 | ---help--- | 12 | ---help--- |
11 | 13 | ||
12 | If you want ASoC support, you should say Y here and also to the | 14 | If you want ASoC support, you should say Y here and also to the |
@@ -51,6 +53,7 @@ source "sound/soc/nuc900/Kconfig" | |||
51 | source "sound/soc/omap/Kconfig" | 53 | source "sound/soc/omap/Kconfig" |
52 | source "sound/soc/kirkwood/Kconfig" | 54 | source "sound/soc/kirkwood/Kconfig" |
53 | source "sound/soc/mid-x86/Kconfig" | 55 | source "sound/soc/mid-x86/Kconfig" |
56 | source "sound/soc/mxs/Kconfig" | ||
54 | source "sound/soc/pxa/Kconfig" | 57 | source "sound/soc/pxa/Kconfig" |
55 | source "sound/soc/samsung/Kconfig" | 58 | source "sound/soc/samsung/Kconfig" |
56 | source "sound/soc/s6000/Kconfig" | 59 | source "sound/soc/s6000/Kconfig" |
diff --git a/sound/soc/Makefile b/sound/soc/Makefile index 4f913876f332..9ea8ac827adc 100644 --- a/sound/soc/Makefile +++ b/sound/soc/Makefile | |||
@@ -12,6 +12,7 @@ obj-$(CONFIG_SND_SOC) += fsl/ | |||
12 | obj-$(CONFIG_SND_SOC) += imx/ | 12 | obj-$(CONFIG_SND_SOC) += imx/ |
13 | obj-$(CONFIG_SND_SOC) += jz4740/ | 13 | obj-$(CONFIG_SND_SOC) += jz4740/ |
14 | obj-$(CONFIG_SND_SOC) += mid-x86/ | 14 | obj-$(CONFIG_SND_SOC) += mid-x86/ |
15 | obj-$(CONFIG_SND_SOC) += mxs/ | ||
15 | obj-$(CONFIG_SND_SOC) += nuc900/ | 16 | obj-$(CONFIG_SND_SOC) += nuc900/ |
16 | obj-$(CONFIG_SND_SOC) += omap/ | 17 | obj-$(CONFIG_SND_SOC) += omap/ |
17 | obj-$(CONFIG_SND_SOC) += kirkwood/ | 18 | obj-$(CONFIG_SND_SOC) += kirkwood/ |
diff --git a/sound/soc/atmel/playpaq_wm8510.c b/sound/soc/atmel/playpaq_wm8510.c index 1aac2f4dbcf6..2909bfaed265 100644 --- a/sound/soc/atmel/playpaq_wm8510.c +++ b/sound/soc/atmel/playpaq_wm8510.c | |||
@@ -383,14 +383,17 @@ static int __init playpaq_asoc_init(void) | |||
383 | _gclk0 = clk_get(NULL, "gclk0"); | 383 | _gclk0 = clk_get(NULL, "gclk0"); |
384 | if (IS_ERR(_gclk0)) { | 384 | if (IS_ERR(_gclk0)) { |
385 | _gclk0 = NULL; | 385 | _gclk0 = NULL; |
386 | ret = PTR_ERR(_gclk0); | ||
386 | goto err_gclk0; | 387 | goto err_gclk0; |
387 | } | 388 | } |
388 | _pll0 = clk_get(NULL, "pll0"); | 389 | _pll0 = clk_get(NULL, "pll0"); |
389 | if (IS_ERR(_pll0)) { | 390 | if (IS_ERR(_pll0)) { |
390 | _pll0 = NULL; | 391 | _pll0 = NULL; |
392 | ret = PTR_ERR(_pll0); | ||
391 | goto err_pll0; | 393 | goto err_pll0; |
392 | } | 394 | } |
393 | if (clk_set_parent(_gclk0, _pll0)) { | 395 | ret = clk_set_parent(_gclk0, _pll0); |
396 | if (ret) { | ||
394 | pr_warning("snd-soc-playpaq: " | 397 | pr_warning("snd-soc-playpaq: " |
395 | "Failed to set PLL0 as parent for DAC clock\n"); | 398 | "Failed to set PLL0 as parent for DAC clock\n"); |
396 | goto err_set_clk; | 399 | goto err_set_clk; |
diff --git a/sound/soc/au1x/Kconfig b/sound/soc/au1x/Kconfig index 4b67140fdec3..6d592546e8fc 100644 --- a/sound/soc/au1x/Kconfig +++ b/sound/soc/au1x/Kconfig | |||
@@ -18,10 +18,38 @@ config SND_SOC_AU1XPSC_AC97 | |||
18 | select SND_AC97_CODEC | 18 | select SND_AC97_CODEC |
19 | select SND_SOC_AC97_BUS | 19 | select SND_SOC_AC97_BUS |
20 | 20 | ||
21 | ## | ||
22 | ## Au1000/1500/1100 DMA + AC97C/I2SC | ||
23 | ## | ||
24 | config SND_SOC_AU1XAUDIO | ||
25 | tristate "SoC Audio for Au1000/Au1500/Au1100" | ||
26 | depends on MIPS_ALCHEMY | ||
27 | help | ||
28 | This is a driver set for the AC97 unit and the | ||
29 | old DMA controller as found on the Au1000/Au1500/Au1100 chips. | ||
30 | |||
31 | config SND_SOC_AU1XAC97C | ||
32 | tristate | ||
33 | select AC97_BUS | ||
34 | select SND_AC97_CODEC | ||
35 | select SND_SOC_AC97_BUS | ||
36 | |||
37 | config SND_SOC_AU1XI2SC | ||
38 | tristate | ||
39 | |||
21 | 40 | ||
22 | ## | 41 | ## |
23 | ## Boards | 42 | ## Boards |
24 | ## | 43 | ## |
44 | config SND_SOC_DB1000 | ||
45 | tristate "DB1000 Audio support" | ||
46 | depends on SND_SOC_AU1XAUDIO | ||
47 | select SND_SOC_AU1XAC97C | ||
48 | select SND_SOC_AC97_CODEC | ||
49 | help | ||
50 | Select this option to enable AC97 audio on the early DB1x00 series | ||
51 | of boards (DB1000/DB1500/DB1100). | ||
52 | |||
25 | config SND_SOC_DB1200 | 53 | config SND_SOC_DB1200 |
26 | tristate "DB1200 AC97+I2S audio support" | 54 | tristate "DB1200 AC97+I2S audio support" |
27 | depends on SND_SOC_AU1XPSC | 55 | depends on SND_SOC_AU1XPSC |
diff --git a/sound/soc/au1x/Makefile b/sound/soc/au1x/Makefile index 16873076e8c4..920710514ea0 100644 --- a/sound/soc/au1x/Makefile +++ b/sound/soc/au1x/Makefile | |||
@@ -3,11 +3,21 @@ snd-soc-au1xpsc-dbdma-objs := dbdma2.o | |||
3 | snd-soc-au1xpsc-i2s-objs := psc-i2s.o | 3 | snd-soc-au1xpsc-i2s-objs := psc-i2s.o |
4 | snd-soc-au1xpsc-ac97-objs := psc-ac97.o | 4 | snd-soc-au1xpsc-ac97-objs := psc-ac97.o |
5 | 5 | ||
6 | # Au1000/1500/1100 Audio units | ||
7 | snd-soc-au1x-dma-objs := dma.o | ||
8 | snd-soc-au1x-ac97c-objs := ac97c.o | ||
9 | snd-soc-au1x-i2sc-objs := i2sc.o | ||
10 | |||
6 | obj-$(CONFIG_SND_SOC_AU1XPSC) += snd-soc-au1xpsc-dbdma.o | 11 | obj-$(CONFIG_SND_SOC_AU1XPSC) += snd-soc-au1xpsc-dbdma.o |
7 | obj-$(CONFIG_SND_SOC_AU1XPSC_I2S) += snd-soc-au1xpsc-i2s.o | 12 | obj-$(CONFIG_SND_SOC_AU1XPSC_I2S) += snd-soc-au1xpsc-i2s.o |
8 | obj-$(CONFIG_SND_SOC_AU1XPSC_AC97) += snd-soc-au1xpsc-ac97.o | 13 | obj-$(CONFIG_SND_SOC_AU1XPSC_AC97) += snd-soc-au1xpsc-ac97.o |
14 | obj-$(CONFIG_SND_SOC_AU1XAUDIO) += snd-soc-au1x-dma.o | ||
15 | obj-$(CONFIG_SND_SOC_AU1XAC97C) += snd-soc-au1x-ac97c.o | ||
16 | obj-$(CONFIG_SND_SOC_AU1XI2SC) += snd-soc-au1x-i2sc.o | ||
9 | 17 | ||
10 | # Boards | 18 | # Boards |
19 | snd-soc-db1000-objs := db1000.o | ||
11 | snd-soc-db1200-objs := db1200.o | 20 | snd-soc-db1200-objs := db1200.o |
12 | 21 | ||
22 | obj-$(CONFIG_SND_SOC_DB1000) += snd-soc-db1000.o | ||
13 | obj-$(CONFIG_SND_SOC_DB1200) += snd-soc-db1200.o | 23 | obj-$(CONFIG_SND_SOC_DB1200) += snd-soc-db1200.o |
diff --git a/sound/soc/au1x/ac97c.c b/sound/soc/au1x/ac97c.c new file mode 100644 index 000000000000..13802ff7cf05 --- /dev/null +++ b/sound/soc/au1x/ac97c.c | |||
@@ -0,0 +1,363 @@ | |||
1 | /* | ||
2 | * Au1000/Au1500/Au1100 AC97C controller driver for ASoC | ||
3 | * | ||
4 | * (c) 2011 Manuel Lauss <manuel.lauss@googlemail.com> | ||
5 | * | ||
6 | * based on the old ALSA driver originally written by | ||
7 | * Charles Eidsness <charles@cooper-street.com> | ||
8 | */ | ||
9 | |||
10 | #include <linux/init.h> | ||
11 | #include <linux/module.h> | ||
12 | #include <linux/slab.h> | ||
13 | #include <linux/device.h> | ||
14 | #include <linux/delay.h> | ||
15 | #include <linux/mutex.h> | ||
16 | #include <linux/platform_device.h> | ||
17 | #include <linux/suspend.h> | ||
18 | #include <sound/core.h> | ||
19 | #include <sound/pcm.h> | ||
20 | #include <sound/initval.h> | ||
21 | #include <sound/soc.h> | ||
22 | #include <asm/mach-au1x00/au1000.h> | ||
23 | |||
24 | #include "psc.h" | ||
25 | |||
26 | /* register offsets and bits */ | ||
27 | #define AC97_CONFIG 0x00 | ||
28 | #define AC97_STATUS 0x04 | ||
29 | #define AC97_DATA 0x08 | ||
30 | #define AC97_CMDRESP 0x0c | ||
31 | #define AC97_ENABLE 0x10 | ||
32 | |||
33 | #define CFG_RC(x) (((x) & 0x3ff) << 13) /* valid rx slots mask */ | ||
34 | #define CFG_XS(x) (((x) & 0x3ff) << 3) /* valid tx slots mask */ | ||
35 | #define CFG_SG (1 << 2) /* sync gate */ | ||
36 | #define CFG_SN (1 << 1) /* sync control */ | ||
37 | #define CFG_RS (1 << 0) /* acrst# control */ | ||
38 | #define STAT_XU (1 << 11) /* tx underflow */ | ||
39 | #define STAT_XO (1 << 10) /* tx overflow */ | ||
40 | #define STAT_RU (1 << 9) /* rx underflow */ | ||
41 | #define STAT_RO (1 << 8) /* rx overflow */ | ||
42 | #define STAT_RD (1 << 7) /* codec ready */ | ||
43 | #define STAT_CP (1 << 6) /* command pending */ | ||
44 | #define STAT_TE (1 << 4) /* tx fifo empty */ | ||
45 | #define STAT_TF (1 << 3) /* tx fifo full */ | ||
46 | #define STAT_RE (1 << 1) /* rx fifo empty */ | ||
47 | #define STAT_RF (1 << 0) /* rx fifo full */ | ||
48 | #define CMD_SET_DATA(x) (((x) & 0xffff) << 16) | ||
49 | #define CMD_GET_DATA(x) ((x) & 0xffff) | ||
50 | #define CMD_READ (1 << 7) | ||
51 | #define CMD_WRITE (0 << 7) | ||
52 | #define CMD_IDX(x) ((x) & 0x7f) | ||
53 | #define EN_D (1 << 1) /* DISable bit */ | ||
54 | #define EN_CE (1 << 0) /* clock enable bit */ | ||
55 | |||
56 | /* how often to retry failed codec register reads/writes */ | ||
57 | #define AC97_RW_RETRIES 5 | ||
58 | |||
59 | #define AC97_RATES \ | ||
60 | SNDRV_PCM_RATE_CONTINUOUS | ||
61 | |||
62 | #define AC97_FMTS \ | ||
63 | (SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S16_BE) | ||
64 | |||
65 | /* instance data. There can be only one, MacLeod!!!!, fortunately there IS only | ||
66 | * once AC97C on early Alchemy chips. The newer ones aren't so lucky. | ||
67 | */ | ||
68 | static struct au1xpsc_audio_data *ac97c_workdata; | ||
69 | #define ac97_to_ctx(x) ac97c_workdata | ||
70 | |||
71 | static inline unsigned long RD(struct au1xpsc_audio_data *ctx, int reg) | ||
72 | { | ||
73 | return __raw_readl(ctx->mmio + reg); | ||
74 | } | ||
75 | |||
76 | static inline void WR(struct au1xpsc_audio_data *ctx, int reg, unsigned long v) | ||
77 | { | ||
78 | __raw_writel(v, ctx->mmio + reg); | ||
79 | wmb(); | ||
80 | } | ||
81 | |||
82 | static unsigned short au1xac97c_ac97_read(struct snd_ac97 *ac97, | ||
83 | unsigned short r) | ||
84 | { | ||
85 | struct au1xpsc_audio_data *ctx = ac97_to_ctx(ac97); | ||
86 | unsigned int tmo, retry; | ||
87 | unsigned long data; | ||
88 | |||
89 | data = ~0; | ||
90 | retry = AC97_RW_RETRIES; | ||
91 | do { | ||
92 | mutex_lock(&ctx->lock); | ||
93 | |||
94 | tmo = 5; | ||
95 | while ((RD(ctx, AC97_STATUS) & STAT_CP) && tmo--) | ||
96 | udelay(21); /* wait an ac97 frame time */ | ||
97 | if (!tmo) { | ||
98 | pr_debug("ac97rd timeout #1\n"); | ||
99 | goto next; | ||
100 | } | ||
101 | |||
102 | WR(ctx, AC97_CMDRESP, CMD_IDX(r) | CMD_READ); | ||
103 | |||
104 | /* stupid errata: data is only valid for 21us, so | ||
105 | * poll, Forrest, poll... | ||
106 | */ | ||
107 | tmo = 0x10000; | ||
108 | while ((RD(ctx, AC97_STATUS) & STAT_CP) && tmo--) | ||
109 | asm volatile ("nop"); | ||
110 | data = RD(ctx, AC97_CMDRESP); | ||
111 | |||
112 | if (!tmo) | ||
113 | pr_debug("ac97rd timeout #2\n"); | ||
114 | |||
115 | next: | ||
116 | mutex_unlock(&ctx->lock); | ||
117 | } while (--retry && !tmo); | ||
118 | |||
119 | pr_debug("AC97RD %04x %04lx %d\n", r, data, retry); | ||
120 | |||
121 | return retry ? data & 0xffff : 0xffff; | ||
122 | } | ||
123 | |||
124 | static void au1xac97c_ac97_write(struct snd_ac97 *ac97, unsigned short r, | ||
125 | unsigned short v) | ||
126 | { | ||
127 | struct au1xpsc_audio_data *ctx = ac97_to_ctx(ac97); | ||
128 | unsigned int tmo, retry; | ||
129 | |||
130 | retry = AC97_RW_RETRIES; | ||
131 | do { | ||
132 | mutex_lock(&ctx->lock); | ||
133 | |||
134 | for (tmo = 5; (RD(ctx, AC97_STATUS) & STAT_CP) && tmo; tmo--) | ||
135 | udelay(21); | ||
136 | if (!tmo) { | ||
137 | pr_debug("ac97wr timeout #1\n"); | ||
138 | goto next; | ||
139 | } | ||
140 | |||
141 | WR(ctx, AC97_CMDRESP, CMD_WRITE | CMD_IDX(r) | CMD_SET_DATA(v)); | ||
142 | |||
143 | for (tmo = 10; (RD(ctx, AC97_STATUS) & STAT_CP) && tmo; tmo--) | ||
144 | udelay(21); | ||
145 | if (!tmo) | ||
146 | pr_debug("ac97wr timeout #2\n"); | ||
147 | next: | ||
148 | mutex_unlock(&ctx->lock); | ||
149 | } while (--retry && !tmo); | ||
150 | |||
151 | pr_debug("AC97WR %04x %04x %d\n", r, v, retry); | ||
152 | } | ||
153 | |||
154 | static void au1xac97c_ac97_warm_reset(struct snd_ac97 *ac97) | ||
155 | { | ||
156 | struct au1xpsc_audio_data *ctx = ac97_to_ctx(ac97); | ||
157 | |||
158 | WR(ctx, AC97_CONFIG, ctx->cfg | CFG_SG | CFG_SN); | ||
159 | msleep(20); | ||
160 | WR(ctx, AC97_CONFIG, ctx->cfg | CFG_SG); | ||
161 | WR(ctx, AC97_CONFIG, ctx->cfg); | ||
162 | } | ||
163 | |||
164 | static void au1xac97c_ac97_cold_reset(struct snd_ac97 *ac97) | ||
165 | { | ||
166 | struct au1xpsc_audio_data *ctx = ac97_to_ctx(ac97); | ||
167 | int i; | ||
168 | |||
169 | WR(ctx, AC97_CONFIG, ctx->cfg | CFG_RS); | ||
170 | msleep(500); | ||
171 | WR(ctx, AC97_CONFIG, ctx->cfg); | ||
172 | |||
173 | /* wait for codec ready */ | ||
174 | i = 50; | ||
175 | while (((RD(ctx, AC97_STATUS) & STAT_RD) == 0) && --i) | ||
176 | msleep(20); | ||
177 | if (!i) | ||
178 | printk(KERN_ERR "ac97c: codec not ready after cold reset\n"); | ||
179 | } | ||
180 | |||
181 | /* AC97 controller operations */ | ||
182 | struct snd_ac97_bus_ops soc_ac97_ops = { | ||
183 | .read = au1xac97c_ac97_read, | ||
184 | .write = au1xac97c_ac97_write, | ||
185 | .reset = au1xac97c_ac97_cold_reset, | ||
186 | .warm_reset = au1xac97c_ac97_warm_reset, | ||
187 | }; | ||
188 | EXPORT_SYMBOL_GPL(soc_ac97_ops); /* globals be gone! */ | ||
189 | |||
190 | static int alchemy_ac97c_startup(struct snd_pcm_substream *substream, | ||
191 | struct snd_soc_dai *dai) | ||
192 | { | ||
193 | struct au1xpsc_audio_data *ctx = snd_soc_dai_get_drvdata(dai); | ||
194 | snd_soc_dai_set_dma_data(dai, substream, &ctx->dmaids[0]); | ||
195 | return 0; | ||
196 | } | ||
197 | |||
198 | static struct snd_soc_dai_ops alchemy_ac97c_ops = { | ||
199 | .startup = alchemy_ac97c_startup, | ||
200 | }; | ||
201 | |||
202 | static int au1xac97c_dai_probe(struct snd_soc_dai *dai) | ||
203 | { | ||
204 | return ac97c_workdata ? 0 : -ENODEV; | ||
205 | } | ||
206 | |||
207 | static struct snd_soc_dai_driver au1xac97c_dai_driver = { | ||
208 | .name = "alchemy-ac97c", | ||
209 | .ac97_control = 1, | ||
210 | .probe = au1xac97c_dai_probe, | ||
211 | .playback = { | ||
212 | .rates = AC97_RATES, | ||
213 | .formats = AC97_FMTS, | ||
214 | .channels_min = 2, | ||
215 | .channels_max = 2, | ||
216 | }, | ||
217 | .capture = { | ||
218 | .rates = AC97_RATES, | ||
219 | .formats = AC97_FMTS, | ||
220 | .channels_min = 2, | ||
221 | .channels_max = 2, | ||
222 | }, | ||
223 | .ops = &alchemy_ac97c_ops, | ||
224 | }; | ||
225 | |||
226 | static int __devinit au1xac97c_drvprobe(struct platform_device *pdev) | ||
227 | { | ||
228 | int ret; | ||
229 | struct resource *r; | ||
230 | struct au1xpsc_audio_data *ctx; | ||
231 | |||
232 | ctx = kzalloc(sizeof(*ctx), GFP_KERNEL); | ||
233 | if (!ctx) | ||
234 | return -ENOMEM; | ||
235 | |||
236 | mutex_init(&ctx->lock); | ||
237 | |||
238 | r = platform_get_resource(pdev, IORESOURCE_MEM, 0); | ||
239 | if (!r) { | ||
240 | ret = -ENODEV; | ||
241 | goto out0; | ||
242 | } | ||
243 | |||
244 | ret = -EBUSY; | ||
245 | if (!request_mem_region(r->start, resource_size(r), pdev->name)) | ||
246 | goto out0; | ||
247 | |||
248 | ctx->mmio = ioremap_nocache(r->start, resource_size(r)); | ||
249 | if (!ctx->mmio) | ||
250 | goto out1; | ||
251 | |||
252 | r = platform_get_resource(pdev, IORESOURCE_DMA, 0); | ||
253 | if (!r) | ||
254 | goto out1; | ||
255 | ctx->dmaids[SNDRV_PCM_STREAM_PLAYBACK] = r->start; | ||
256 | |||
257 | r = platform_get_resource(pdev, IORESOURCE_DMA, 1); | ||
258 | if (!r) | ||
259 | goto out1; | ||
260 | ctx->dmaids[SNDRV_PCM_STREAM_CAPTURE] = r->start; | ||
261 | |||
262 | /* switch it on */ | ||
263 | WR(ctx, AC97_ENABLE, EN_D | EN_CE); | ||
264 | WR(ctx, AC97_ENABLE, EN_CE); | ||
265 | |||
266 | ctx->cfg = CFG_RC(3) | CFG_XS(3); | ||
267 | WR(ctx, AC97_CONFIG, ctx->cfg); | ||
268 | |||
269 | platform_set_drvdata(pdev, ctx); | ||
270 | |||
271 | ret = snd_soc_register_dai(&pdev->dev, &au1xac97c_dai_driver); | ||
272 | if (ret) | ||
273 | goto out1; | ||
274 | |||
275 | ac97c_workdata = ctx; | ||
276 | return 0; | ||
277 | |||
278 | out1: | ||
279 | release_mem_region(r->start, resource_size(r)); | ||
280 | out0: | ||
281 | kfree(ctx); | ||
282 | return ret; | ||
283 | } | ||
284 | |||
285 | static int __devexit au1xac97c_drvremove(struct platform_device *pdev) | ||
286 | { | ||
287 | struct au1xpsc_audio_data *ctx = platform_get_drvdata(pdev); | ||
288 | struct resource *r = platform_get_resource(pdev, IORESOURCE_MEM, 0); | ||
289 | |||
290 | snd_soc_unregister_dai(&pdev->dev); | ||
291 | |||
292 | WR(ctx, AC97_ENABLE, EN_D); /* clock off, disable */ | ||
293 | |||
294 | iounmap(ctx->mmio); | ||
295 | release_mem_region(r->start, resource_size(r)); | ||
296 | kfree(ctx); | ||
297 | |||
298 | ac97c_workdata = NULL; /* MDEV */ | ||
299 | |||
300 | return 0; | ||
301 | } | ||
302 | |||
303 | #ifdef CONFIG_PM | ||
304 | static int au1xac97c_drvsuspend(struct device *dev) | ||
305 | { | ||
306 | struct au1xpsc_audio_data *ctx = dev_get_drvdata(dev); | ||
307 | |||
308 | WR(ctx, AC97_ENABLE, EN_D); /* clock off, disable */ | ||
309 | |||
310 | return 0; | ||
311 | } | ||
312 | |||
313 | static int au1xac97c_drvresume(struct device *dev) | ||
314 | { | ||
315 | struct au1xpsc_audio_data *ctx = dev_get_drvdata(dev); | ||
316 | |||
317 | WR(ctx, AC97_ENABLE, EN_D | EN_CE); | ||
318 | WR(ctx, AC97_ENABLE, EN_CE); | ||
319 | WR(ctx, AC97_CONFIG, ctx->cfg); | ||
320 | |||
321 | return 0; | ||
322 | } | ||
323 | |||
324 | static const struct dev_pm_ops au1xpscac97_pmops = { | ||
325 | .suspend = au1xac97c_drvsuspend, | ||
326 | .resume = au1xac97c_drvresume, | ||
327 | }; | ||
328 | |||
329 | #define AU1XPSCAC97_PMOPS (&au1xpscac97_pmops) | ||
330 | |||
331 | #else | ||
332 | |||
333 | #define AU1XPSCAC97_PMOPS NULL | ||
334 | |||
335 | #endif | ||
336 | |||
337 | static struct platform_driver au1xac97c_driver = { | ||
338 | .driver = { | ||
339 | .name = "alchemy-ac97c", | ||
340 | .owner = THIS_MODULE, | ||
341 | .pm = AU1XPSCAC97_PMOPS, | ||
342 | }, | ||
343 | .probe = au1xac97c_drvprobe, | ||
344 | .remove = __devexit_p(au1xac97c_drvremove), | ||
345 | }; | ||
346 | |||
347 | static int __init au1xac97c_load(void) | ||
348 | { | ||
349 | ac97c_workdata = NULL; | ||
350 | return platform_driver_register(&au1xac97c_driver); | ||
351 | } | ||
352 | |||
353 | static void __exit au1xac97c_unload(void) | ||
354 | { | ||
355 | platform_driver_unregister(&au1xac97c_driver); | ||
356 | } | ||
357 | |||
358 | module_init(au1xac97c_load); | ||
359 | module_exit(au1xac97c_unload); | ||
360 | |||
361 | MODULE_LICENSE("GPL"); | ||
362 | MODULE_DESCRIPTION("Au1000/1500/1100 AC97C ASoC driver"); | ||
363 | MODULE_AUTHOR("Manuel Lauss"); | ||
diff --git a/sound/soc/au1x/db1000.c b/sound/soc/au1x/db1000.c new file mode 100644 index 000000000000..127477a5e0c7 --- /dev/null +++ b/sound/soc/au1x/db1000.c | |||
@@ -0,0 +1,75 @@ | |||
1 | /* | ||
2 | * DB1000/DB1500/DB1100 ASoC audio fabric support code. | ||
3 | * | ||
4 | * (c) 2011 Manuel Lauss <manuel.lauss@googlemail.com> | ||
5 | * | ||
6 | */ | ||
7 | |||
8 | #include <linux/module.h> | ||
9 | #include <linux/moduleparam.h> | ||
10 | #include <linux/timer.h> | ||
11 | #include <linux/interrupt.h> | ||
12 | #include <linux/platform_device.h> | ||
13 | #include <sound/core.h> | ||
14 | #include <sound/pcm.h> | ||
15 | #include <sound/soc.h> | ||
16 | #include <asm/mach-au1x00/au1000.h> | ||
17 | #include <asm/mach-db1x00/bcsr.h> | ||
18 | |||
19 | #include "psc.h" | ||
20 | |||
21 | static struct snd_soc_dai_link db1000_ac97_dai = { | ||
22 | .name = "AC97", | ||
23 | .stream_name = "AC97 HiFi", | ||
24 | .codec_dai_name = "ac97-hifi", | ||
25 | .cpu_dai_name = "alchemy-ac97c", | ||
26 | .platform_name = "alchemy-pcm-dma.0", | ||
27 | .codec_name = "ac97-codec", | ||
28 | }; | ||
29 | |||
30 | static struct snd_soc_card db1000_ac97 = { | ||
31 | .name = "DB1000_AC97", | ||
32 | .dai_link = &db1000_ac97_dai, | ||
33 | .num_links = 1, | ||
34 | }; | ||
35 | |||
36 | static int __devinit db1000_audio_probe(struct platform_device *pdev) | ||
37 | { | ||
38 | struct snd_soc_card *card = &db1000_ac97; | ||
39 | card->dev = &pdev->dev; | ||
40 | return snd_soc_register_card(card); | ||
41 | } | ||
42 | |||
43 | static int __devexit db1000_audio_remove(struct platform_device *pdev) | ||
44 | { | ||
45 | struct snd_soc_card *card = platform_get_drvdata(pdev); | ||
46 | snd_soc_unregister_card(card); | ||
47 | return 0; | ||
48 | } | ||
49 | |||
50 | static struct platform_driver db1000_audio_driver = { | ||
51 | .driver = { | ||
52 | .name = "db1000-audio", | ||
53 | .owner = THIS_MODULE, | ||
54 | .pm = &snd_soc_pm_ops, | ||
55 | }, | ||
56 | .probe = db1000_audio_probe, | ||
57 | .remove = __devexit_p(db1000_audio_remove), | ||
58 | }; | ||
59 | |||
60 | static int __init db1000_audio_load(void) | ||
61 | { | ||
62 | return platform_driver_register(&db1000_audio_driver); | ||
63 | } | ||
64 | |||
65 | static void __exit db1000_audio_unload(void) | ||
66 | { | ||
67 | platform_driver_unregister(&db1000_audio_driver); | ||
68 | } | ||
69 | |||
70 | module_init(db1000_audio_load); | ||
71 | module_exit(db1000_audio_unload); | ||
72 | |||
73 | MODULE_LICENSE("GPL"); | ||
74 | MODULE_DESCRIPTION("DB1000/DB1500/DB1100 ASoC audio"); | ||
75 | MODULE_AUTHOR("Manuel Lauss"); | ||
diff --git a/sound/soc/au1x/db1200.c b/sound/soc/au1x/db1200.c index 1d3e258c9ea8..289312c14b99 100644 --- a/sound/soc/au1x/db1200.c +++ b/sound/soc/au1x/db1200.c | |||
@@ -1,7 +1,7 @@ | |||
1 | /* | 1 | /* |
2 | * DB1200 ASoC audio fabric support code. | 2 | * DB1200 ASoC audio fabric support code. |
3 | * | 3 | * |
4 | * (c) 2008-9 Manuel Lauss <manuel.lauss@gmail.com> | 4 | * (c) 2008-2011 Manuel Lauss <manuel.lauss@googlemail.com> |
5 | * | 5 | * |
6 | */ | 6 | */ |
7 | 7 | ||
@@ -21,6 +21,17 @@ | |||
21 | #include "../codecs/wm8731.h" | 21 | #include "../codecs/wm8731.h" |
22 | #include "psc.h" | 22 | #include "psc.h" |
23 | 23 | ||
24 | static struct platform_device_id db1200_pids[] = { | ||
25 | { | ||
26 | .name = "db1200-ac97", | ||
27 | .driver_data = 0, | ||
28 | }, { | ||
29 | .name = "db1200-i2s", | ||
30 | .driver_data = 1, | ||
31 | }, | ||
32 | {}, | ||
33 | }; | ||
34 | |||
24 | /*------------------------- AC97 PART ---------------------------*/ | 35 | /*------------------------- AC97 PART ---------------------------*/ |
25 | 36 | ||
26 | static struct snd_soc_dai_link db1200_ac97_dai = { | 37 | static struct snd_soc_dai_link db1200_ac97_dai = { |
@@ -89,36 +100,47 @@ static struct snd_soc_card db1200_i2s_machine = { | |||
89 | 100 | ||
90 | /*------------------------- COMMON PART ---------------------------*/ | 101 | /*------------------------- COMMON PART ---------------------------*/ |
91 | 102 | ||
92 | static struct platform_device *db1200_asoc_dev; | 103 | static struct snd_soc_card *db1200_cards[] __devinitdata = { |
104 | &db1200_ac97_machine, | ||
105 | &db1200_i2s_machine, | ||
106 | }; | ||
93 | 107 | ||
94 | static int __init db1200_audio_load(void) | 108 | static int __devinit db1200_audio_probe(struct platform_device *pdev) |
95 | { | 109 | { |
96 | int ret; | 110 | const struct platform_device_id *pid = platform_get_device_id(pdev); |
111 | struct snd_soc_card *card; | ||
97 | 112 | ||
98 | ret = -ENOMEM; | 113 | card = db1200_cards[pid->driver_data]; |
99 | db1200_asoc_dev = platform_device_alloc("soc-audio", 1); /* PSC1 */ | 114 | card->dev = &pdev->dev; |
100 | if (!db1200_asoc_dev) | 115 | return snd_soc_register_card(card); |
101 | goto out; | 116 | } |
102 | 117 | ||
103 | /* DB1200 board setup set PSC1MUX to preferred audio device */ | 118 | static int __devexit db1200_audio_remove(struct platform_device *pdev) |
104 | if (bcsr_read(BCSR_RESETS) & BCSR_RESETS_PSC1MUX) | 119 | { |
105 | platform_set_drvdata(db1200_asoc_dev, &db1200_i2s_machine); | 120 | struct snd_soc_card *card = platform_get_drvdata(pdev); |
106 | else | 121 | snd_soc_unregister_card(card); |
107 | platform_set_drvdata(db1200_asoc_dev, &db1200_ac97_machine); | 122 | return 0; |
123 | } | ||
108 | 124 | ||
109 | ret = platform_device_add(db1200_asoc_dev); | 125 | static struct platform_driver db1200_audio_driver = { |
126 | .driver = { | ||
127 | .name = "db1200-ac97", | ||
128 | .owner = THIS_MODULE, | ||
129 | .pm = &snd_soc_pm_ops, | ||
130 | }, | ||
131 | .id_table = db1200_pids, | ||
132 | .probe = db1200_audio_probe, | ||
133 | .remove = __devexit_p(db1200_audio_remove), | ||
134 | }; | ||
110 | 135 | ||
111 | if (ret) { | 136 | static int __init db1200_audio_load(void) |
112 | platform_device_put(db1200_asoc_dev); | 137 | { |
113 | db1200_asoc_dev = NULL; | 138 | return platform_driver_register(&db1200_audio_driver); |
114 | } | ||
115 | out: | ||
116 | return ret; | ||
117 | } | 139 | } |
118 | 140 | ||
119 | static void __exit db1200_audio_unload(void) | 141 | static void __exit db1200_audio_unload(void) |
120 | { | 142 | { |
121 | platform_device_unregister(db1200_asoc_dev); | 143 | platform_driver_unregister(&db1200_audio_driver); |
122 | } | 144 | } |
123 | 145 | ||
124 | module_init(db1200_audio_load); | 146 | module_init(db1200_audio_load); |
diff --git a/sound/soc/au1x/dbdma2.c b/sound/soc/au1x/dbdma2.c index 20bb53a837b1..d7d04e26eee5 100644 --- a/sound/soc/au1x/dbdma2.c +++ b/sound/soc/au1x/dbdma2.c | |||
@@ -169,7 +169,7 @@ static int au1x_pcm_dbdma_realloc(struct au1xpsc_audio_dmadata *pcd, | |||
169 | 169 | ||
170 | au1x_pcm_dbdma_free(pcd); | 170 | au1x_pcm_dbdma_free(pcd); |
171 | 171 | ||
172 | if (stype == PCM_RX) | 172 | if (stype == SNDRV_PCM_STREAM_CAPTURE) |
173 | pcd->ddma_chan = au1xxx_dbdma_chan_alloc(pcd->ddma_id, | 173 | pcd->ddma_chan = au1xxx_dbdma_chan_alloc(pcd->ddma_id, |
174 | DSCR_CMD0_ALWAYS, | 174 | DSCR_CMD0_ALWAYS, |
175 | au1x_pcm_dmarx_cb, (void *)pcd); | 175 | au1x_pcm_dmarx_cb, (void *)pcd); |
@@ -198,7 +198,7 @@ static inline struct au1xpsc_audio_dmadata *to_dmadata(struct snd_pcm_substream | |||
198 | struct snd_soc_pcm_runtime *rtd = ss->private_data; | 198 | struct snd_soc_pcm_runtime *rtd = ss->private_data; |
199 | struct au1xpsc_audio_dmadata *pcd = | 199 | struct au1xpsc_audio_dmadata *pcd = |
200 | snd_soc_platform_get_drvdata(rtd->platform); | 200 | snd_soc_platform_get_drvdata(rtd->platform); |
201 | return &pcd[SUBSTREAM_TYPE(ss)]; | 201 | return &pcd[ss->stream]; |
202 | } | 202 | } |
203 | 203 | ||
204 | static int au1xpsc_pcm_hw_params(struct snd_pcm_substream *substream, | 204 | static int au1xpsc_pcm_hw_params(struct snd_pcm_substream *substream, |
@@ -212,7 +212,7 @@ static int au1xpsc_pcm_hw_params(struct snd_pcm_substream *substream, | |||
212 | if (ret < 0) | 212 | if (ret < 0) |
213 | goto out; | 213 | goto out; |
214 | 214 | ||
215 | stype = SUBSTREAM_TYPE(substream); | 215 | stype = substream->stream; |
216 | pcd = to_dmadata(substream); | 216 | pcd = to_dmadata(substream); |
217 | 217 | ||
218 | DBG("runtime->dma_area = 0x%08lx dma_addr_t = 0x%08lx dma_size = %d " | 218 | DBG("runtime->dma_area = 0x%08lx dma_addr_t = 0x%08lx dma_size = %d " |
@@ -255,7 +255,7 @@ static int au1xpsc_pcm_prepare(struct snd_pcm_substream *substream) | |||
255 | 255 | ||
256 | au1xxx_dbdma_reset(pcd->ddma_chan); | 256 | au1xxx_dbdma_reset(pcd->ddma_chan); |
257 | 257 | ||
258 | if (SUBSTREAM_TYPE(substream) == PCM_RX) { | 258 | if (substream->stream == SNDRV_PCM_STREAM_CAPTURE) { |
259 | au1x_pcm_queue_rx(pcd); | 259 | au1x_pcm_queue_rx(pcd); |
260 | au1x_pcm_queue_rx(pcd); | 260 | au1x_pcm_queue_rx(pcd); |
261 | } else { | 261 | } else { |
@@ -293,6 +293,16 @@ au1xpsc_pcm_pointer(struct snd_pcm_substream *substream) | |||
293 | 293 | ||
294 | static int au1xpsc_pcm_open(struct snd_pcm_substream *substream) | 294 | static int au1xpsc_pcm_open(struct snd_pcm_substream *substream) |
295 | { | 295 | { |
296 | struct au1xpsc_audio_dmadata *pcd = to_dmadata(substream); | ||
297 | struct snd_soc_pcm_runtime *rtd = substream->private_data; | ||
298 | int stype = substream->stream, *dmaids; | ||
299 | |||
300 | dmaids = snd_soc_dai_get_dma_data(rtd->cpu_dai, substream); | ||
301 | if (!dmaids) | ||
302 | return -ENODEV; /* whoa, has ordering changed? */ | ||
303 | |||
304 | pcd->ddma_id = dmaids[stype]; | ||
305 | |||
296 | snd_soc_set_runtime_hwparams(substream, &au1xpsc_pcm_hardware); | 306 | snd_soc_set_runtime_hwparams(substream, &au1xpsc_pcm_hardware); |
297 | return 0; | 307 | return 0; |
298 | } | 308 | } |
@@ -340,36 +350,18 @@ struct snd_soc_platform_driver au1xpsc_soc_platform = { | |||
340 | static int __devinit au1xpsc_pcm_drvprobe(struct platform_device *pdev) | 350 | static int __devinit au1xpsc_pcm_drvprobe(struct platform_device *pdev) |
341 | { | 351 | { |
342 | struct au1xpsc_audio_dmadata *dmadata; | 352 | struct au1xpsc_audio_dmadata *dmadata; |
343 | struct resource *r; | ||
344 | int ret; | 353 | int ret; |
345 | 354 | ||
346 | dmadata = kzalloc(2 * sizeof(struct au1xpsc_audio_dmadata), GFP_KERNEL); | 355 | dmadata = kzalloc(2 * sizeof(struct au1xpsc_audio_dmadata), GFP_KERNEL); |
347 | if (!dmadata) | 356 | if (!dmadata) |
348 | return -ENOMEM; | 357 | return -ENOMEM; |
349 | 358 | ||
350 | r = platform_get_resource(pdev, IORESOURCE_DMA, 0); | ||
351 | if (!r) { | ||
352 | ret = -ENODEV; | ||
353 | goto out1; | ||
354 | } | ||
355 | dmadata[PCM_TX].ddma_id = r->start; | ||
356 | |||
357 | /* RX DMA */ | ||
358 | r = platform_get_resource(pdev, IORESOURCE_DMA, 1); | ||
359 | if (!r) { | ||
360 | ret = -ENODEV; | ||
361 | goto out1; | ||
362 | } | ||
363 | dmadata[PCM_RX].ddma_id = r->start; | ||
364 | |||
365 | platform_set_drvdata(pdev, dmadata); | 359 | platform_set_drvdata(pdev, dmadata); |
366 | 360 | ||
367 | ret = snd_soc_register_platform(&pdev->dev, &au1xpsc_soc_platform); | 361 | ret = snd_soc_register_platform(&pdev->dev, &au1xpsc_soc_platform); |
368 | if (!ret) | 362 | if (ret) |
369 | return ret; | 363 | kfree(dmadata); |
370 | 364 | ||
371 | out1: | ||
372 | kfree(dmadata); | ||
373 | return ret; | 365 | return ret; |
374 | } | 366 | } |
375 | 367 | ||
@@ -405,57 +397,6 @@ static void __exit au1xpsc_audio_dbdma_unload(void) | |||
405 | module_init(au1xpsc_audio_dbdma_load); | 397 | module_init(au1xpsc_audio_dbdma_load); |
406 | module_exit(au1xpsc_audio_dbdma_unload); | 398 | module_exit(au1xpsc_audio_dbdma_unload); |
407 | 399 | ||
408 | |||
409 | struct platform_device *au1xpsc_pcm_add(struct platform_device *pdev) | ||
410 | { | ||
411 | struct resource *res, *r; | ||
412 | struct platform_device *pd; | ||
413 | int id[2]; | ||
414 | int ret; | ||
415 | |||
416 | r = platform_get_resource(pdev, IORESOURCE_DMA, 0); | ||
417 | if (!r) | ||
418 | return NULL; | ||
419 | id[0] = r->start; | ||
420 | |||
421 | r = platform_get_resource(pdev, IORESOURCE_DMA, 1); | ||
422 | if (!r) | ||
423 | return NULL; | ||
424 | id[1] = r->start; | ||
425 | |||
426 | res = kzalloc(sizeof(struct resource) * 2, GFP_KERNEL); | ||
427 | if (!res) | ||
428 | return NULL; | ||
429 | |||
430 | res[0].start = res[0].end = id[0]; | ||
431 | res[1].start = res[1].end = id[1]; | ||
432 | res[0].flags = res[1].flags = IORESOURCE_DMA; | ||
433 | |||
434 | pd = platform_device_alloc("au1xpsc-pcm", pdev->id); | ||
435 | if (!pd) | ||
436 | goto out; | ||
437 | |||
438 | pd->resource = res; | ||
439 | pd->num_resources = 2; | ||
440 | |||
441 | ret = platform_device_add(pd); | ||
442 | if (!ret) | ||
443 | return pd; | ||
444 | |||
445 | platform_device_put(pd); | ||
446 | out: | ||
447 | kfree(res); | ||
448 | return NULL; | ||
449 | } | ||
450 | EXPORT_SYMBOL_GPL(au1xpsc_pcm_add); | ||
451 | |||
452 | void au1xpsc_pcm_destroy(struct platform_device *dmapd) | ||
453 | { | ||
454 | if (dmapd) | ||
455 | platform_device_unregister(dmapd); | ||
456 | } | ||
457 | EXPORT_SYMBOL_GPL(au1xpsc_pcm_destroy); | ||
458 | |||
459 | MODULE_LICENSE("GPL"); | 400 | MODULE_LICENSE("GPL"); |
460 | MODULE_DESCRIPTION("Au12x0/Au1550 PSC Audio DMA driver"); | 401 | MODULE_DESCRIPTION("Au12x0/Au1550 PSC Audio DMA driver"); |
461 | MODULE_AUTHOR("Manuel Lauss"); | 402 | MODULE_AUTHOR("Manuel Lauss"); |
diff --git a/sound/soc/au1x/dma.c b/sound/soc/au1x/dma.c new file mode 100644 index 000000000000..177f7137a9c8 --- /dev/null +++ b/sound/soc/au1x/dma.c | |||
@@ -0,0 +1,377 @@ | |||
1 | /* | ||
2 | * Au1000/Au1500/Au1100 Audio DMA support. | ||
3 | * | ||
4 | * (c) 2011 Manuel Lauss <manuel.lauss@googlemail.com> | ||
5 | * | ||
6 | * copied almost verbatim from the old ALSA driver, written by | ||
7 | * Charles Eidsness <charles@cooper-street.com> | ||
8 | */ | ||
9 | |||
10 | #include <linux/module.h> | ||
11 | #include <linux/init.h> | ||
12 | #include <linux/platform_device.h> | ||
13 | #include <linux/slab.h> | ||
14 | #include <linux/dma-mapping.h> | ||
15 | #include <sound/core.h> | ||
16 | #include <sound/pcm.h> | ||
17 | #include <sound/pcm_params.h> | ||
18 | #include <sound/soc.h> | ||
19 | #include <asm/mach-au1x00/au1000.h> | ||
20 | #include <asm/mach-au1x00/au1000_dma.h> | ||
21 | |||
22 | #include "psc.h" | ||
23 | |||
24 | #define ALCHEMY_PCM_FMTS \ | ||
25 | (SNDRV_PCM_FMTBIT_S8 | SNDRV_PCM_FMTBIT_U8 | \ | ||
26 | SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S16_BE | \ | ||
27 | SNDRV_PCM_FMTBIT_U16_LE | SNDRV_PCM_FMTBIT_U16_BE | \ | ||
28 | SNDRV_PCM_FMTBIT_S32_LE | SNDRV_PCM_FMTBIT_S32_BE | \ | ||
29 | SNDRV_PCM_FMTBIT_U32_LE | SNDRV_PCM_FMTBIT_U32_BE | \ | ||
30 | 0) | ||
31 | |||
32 | struct pcm_period { | ||
33 | u32 start; | ||
34 | u32 relative_end; /* relative to start of buffer */ | ||
35 | struct pcm_period *next; | ||
36 | }; | ||
37 | |||
38 | struct audio_stream { | ||
39 | struct snd_pcm_substream *substream; | ||
40 | int dma; | ||
41 | struct pcm_period *buffer; | ||
42 | unsigned int period_size; | ||
43 | unsigned int periods; | ||
44 | }; | ||
45 | |||
46 | struct alchemy_pcm_ctx { | ||
47 | struct audio_stream stream[2]; /* playback & capture */ | ||
48 | }; | ||
49 | |||
50 | static void au1000_release_dma_link(struct audio_stream *stream) | ||
51 | { | ||
52 | struct pcm_period *pointer; | ||
53 | struct pcm_period *pointer_next; | ||
54 | |||
55 | stream->period_size = 0; | ||
56 | stream->periods = 0; | ||
57 | pointer = stream->buffer; | ||
58 | if (!pointer) | ||
59 | return; | ||
60 | do { | ||
61 | pointer_next = pointer->next; | ||
62 | kfree(pointer); | ||
63 | pointer = pointer_next; | ||
64 | } while (pointer != stream->buffer); | ||
65 | stream->buffer = NULL; | ||
66 | } | ||
67 | |||
68 | static int au1000_setup_dma_link(struct audio_stream *stream, | ||
69 | unsigned int period_bytes, | ||
70 | unsigned int periods) | ||
71 | { | ||
72 | struct snd_pcm_substream *substream = stream->substream; | ||
73 | struct snd_pcm_runtime *runtime = substream->runtime; | ||
74 | struct pcm_period *pointer; | ||
75 | unsigned long dma_start; | ||
76 | int i; | ||
77 | |||
78 | dma_start = virt_to_phys(runtime->dma_area); | ||
79 | |||
80 | if (stream->period_size == period_bytes && | ||
81 | stream->periods == periods) | ||
82 | return 0; /* not changed */ | ||
83 | |||
84 | au1000_release_dma_link(stream); | ||
85 | |||
86 | stream->period_size = period_bytes; | ||
87 | stream->periods = periods; | ||
88 | |||
89 | stream->buffer = kmalloc(sizeof(struct pcm_period), GFP_KERNEL); | ||
90 | if (!stream->buffer) | ||
91 | return -ENOMEM; | ||
92 | pointer = stream->buffer; | ||
93 | for (i = 0; i < periods; i++) { | ||
94 | pointer->start = (u32)(dma_start + (i * period_bytes)); | ||
95 | pointer->relative_end = (u32) (((i+1) * period_bytes) - 0x1); | ||
96 | if (i < periods - 1) { | ||
97 | pointer->next = kmalloc(sizeof(struct pcm_period), | ||
98 | GFP_KERNEL); | ||
99 | if (!pointer->next) { | ||
100 | au1000_release_dma_link(stream); | ||
101 | return -ENOMEM; | ||
102 | } | ||
103 | pointer = pointer->next; | ||
104 | } | ||
105 | } | ||
106 | pointer->next = stream->buffer; | ||
107 | return 0; | ||
108 | } | ||
109 | |||
110 | static void au1000_dma_stop(struct audio_stream *stream) | ||
111 | { | ||
112 | if (stream->buffer) | ||
113 | disable_dma(stream->dma); | ||
114 | } | ||
115 | |||
116 | static void au1000_dma_start(struct audio_stream *stream) | ||
117 | { | ||
118 | if (!stream->buffer) | ||
119 | return; | ||
120 | |||
121 | init_dma(stream->dma); | ||
122 | if (get_dma_active_buffer(stream->dma) == 0) { | ||
123 | clear_dma_done0(stream->dma); | ||
124 | set_dma_addr0(stream->dma, stream->buffer->start); | ||
125 | set_dma_count0(stream->dma, stream->period_size >> 1); | ||
126 | set_dma_addr1(stream->dma, stream->buffer->next->start); | ||
127 | set_dma_count1(stream->dma, stream->period_size >> 1); | ||
128 | } else { | ||
129 | clear_dma_done1(stream->dma); | ||
130 | set_dma_addr1(stream->dma, stream->buffer->start); | ||
131 | set_dma_count1(stream->dma, stream->period_size >> 1); | ||
132 | set_dma_addr0(stream->dma, stream->buffer->next->start); | ||
133 | set_dma_count0(stream->dma, stream->period_size >> 1); | ||
134 | } | ||
135 | enable_dma_buffers(stream->dma); | ||
136 | start_dma(stream->dma); | ||
137 | } | ||
138 | |||
139 | static irqreturn_t au1000_dma_interrupt(int irq, void *ptr) | ||
140 | { | ||
141 | struct audio_stream *stream = (struct audio_stream *)ptr; | ||
142 | struct snd_pcm_substream *substream = stream->substream; | ||
143 | |||
144 | switch (get_dma_buffer_done(stream->dma)) { | ||
145 | case DMA_D0: | ||
146 | stream->buffer = stream->buffer->next; | ||
147 | clear_dma_done0(stream->dma); | ||
148 | set_dma_addr0(stream->dma, stream->buffer->next->start); | ||
149 | set_dma_count0(stream->dma, stream->period_size >> 1); | ||
150 | enable_dma_buffer0(stream->dma); | ||
151 | break; | ||
152 | case DMA_D1: | ||
153 | stream->buffer = stream->buffer->next; | ||
154 | clear_dma_done1(stream->dma); | ||
155 | set_dma_addr1(stream->dma, stream->buffer->next->start); | ||
156 | set_dma_count1(stream->dma, stream->period_size >> 1); | ||
157 | enable_dma_buffer1(stream->dma); | ||
158 | break; | ||
159 | case (DMA_D0 | DMA_D1): | ||
160 | pr_debug("DMA %d missed interrupt.\n", stream->dma); | ||
161 | au1000_dma_stop(stream); | ||
162 | au1000_dma_start(stream); | ||
163 | break; | ||
164 | case (~DMA_D0 & ~DMA_D1): | ||
165 | pr_debug("DMA %d empty irq.\n", stream->dma); | ||
166 | } | ||
167 | snd_pcm_period_elapsed(substream); | ||
168 | return IRQ_HANDLED; | ||
169 | } | ||
170 | |||
171 | static const struct snd_pcm_hardware alchemy_pcm_hardware = { | ||
172 | .info = SNDRV_PCM_INFO_MMAP | SNDRV_PCM_INFO_MMAP_VALID | | ||
173 | SNDRV_PCM_INFO_INTERLEAVED | SNDRV_PCM_INFO_BATCH, | ||
174 | .formats = ALCHEMY_PCM_FMTS, | ||
175 | .rates = SNDRV_PCM_RATE_8000_192000, | ||
176 | .rate_min = SNDRV_PCM_RATE_8000, | ||
177 | .rate_max = SNDRV_PCM_RATE_192000, | ||
178 | .channels_min = 2, | ||
179 | .channels_max = 2, | ||
180 | .period_bytes_min = 1024, | ||
181 | .period_bytes_max = 16 * 1024 - 1, | ||
182 | .periods_min = 4, | ||
183 | .periods_max = 255, | ||
184 | .buffer_bytes_max = 128 * 1024, | ||
185 | .fifo_size = 16, | ||
186 | }; | ||
187 | |||
188 | static inline struct alchemy_pcm_ctx *ss_to_ctx(struct snd_pcm_substream *ss) | ||
189 | { | ||
190 | struct snd_soc_pcm_runtime *rtd = ss->private_data; | ||
191 | return snd_soc_platform_get_drvdata(rtd->platform); | ||
192 | } | ||
193 | |||
194 | static inline struct audio_stream *ss_to_as(struct snd_pcm_substream *ss) | ||
195 | { | ||
196 | struct alchemy_pcm_ctx *ctx = ss_to_ctx(ss); | ||
197 | return &(ctx->stream[ss->stream]); | ||
198 | } | ||
199 | |||
200 | static int alchemy_pcm_open(struct snd_pcm_substream *substream) | ||
201 | { | ||
202 | struct alchemy_pcm_ctx *ctx = ss_to_ctx(substream); | ||
203 | struct snd_soc_pcm_runtime *rtd = substream->private_data; | ||
204 | int *dmaids, s = substream->stream; | ||
205 | char *name; | ||
206 | |||
207 | dmaids = snd_soc_dai_get_dma_data(rtd->cpu_dai, substream); | ||
208 | if (!dmaids) | ||
209 | return -ENODEV; /* whoa, has ordering changed? */ | ||
210 | |||
211 | /* DMA setup */ | ||
212 | name = (s == SNDRV_PCM_STREAM_PLAYBACK) ? "audio-tx" : "audio-rx"; | ||
213 | ctx->stream[s].dma = request_au1000_dma(dmaids[s], name, | ||
214 | au1000_dma_interrupt, 0, | ||
215 | &ctx->stream[s]); | ||
216 | set_dma_mode(ctx->stream[s].dma, | ||
217 | get_dma_mode(ctx->stream[s].dma) & ~DMA_NC); | ||
218 | |||
219 | ctx->stream[s].substream = substream; | ||
220 | ctx->stream[s].buffer = NULL; | ||
221 | snd_soc_set_runtime_hwparams(substream, &alchemy_pcm_hardware); | ||
222 | |||
223 | return 0; | ||
224 | } | ||
225 | |||
226 | static int alchemy_pcm_close(struct snd_pcm_substream *substream) | ||
227 | { | ||
228 | struct alchemy_pcm_ctx *ctx = ss_to_ctx(substream); | ||
229 | int stype = substream->stream; | ||
230 | |||
231 | ctx->stream[stype].substream = NULL; | ||
232 | free_au1000_dma(ctx->stream[stype].dma); | ||
233 | |||
234 | return 0; | ||
235 | } | ||
236 | |||
237 | static int alchemy_pcm_hw_params(struct snd_pcm_substream *substream, | ||
238 | struct snd_pcm_hw_params *hw_params) | ||
239 | { | ||
240 | struct audio_stream *stream = ss_to_as(substream); | ||
241 | int err; | ||
242 | |||
243 | err = snd_pcm_lib_malloc_pages(substream, | ||
244 | params_buffer_bytes(hw_params)); | ||
245 | if (err < 0) | ||
246 | return err; | ||
247 | err = au1000_setup_dma_link(stream, | ||
248 | params_period_bytes(hw_params), | ||
249 | params_periods(hw_params)); | ||
250 | if (err) | ||
251 | snd_pcm_lib_free_pages(substream); | ||
252 | |||
253 | return err; | ||
254 | } | ||
255 | |||
256 | static int alchemy_pcm_hw_free(struct snd_pcm_substream *substream) | ||
257 | { | ||
258 | struct audio_stream *stream = ss_to_as(substream); | ||
259 | au1000_release_dma_link(stream); | ||
260 | return snd_pcm_lib_free_pages(substream); | ||
261 | } | ||
262 | |||
263 | static int alchemy_pcm_trigger(struct snd_pcm_substream *substream, int cmd) | ||
264 | { | ||
265 | struct audio_stream *stream = ss_to_as(substream); | ||
266 | int err = 0; | ||
267 | |||
268 | switch (cmd) { | ||
269 | case SNDRV_PCM_TRIGGER_START: | ||
270 | au1000_dma_start(stream); | ||
271 | break; | ||
272 | case SNDRV_PCM_TRIGGER_STOP: | ||
273 | au1000_dma_stop(stream); | ||
274 | break; | ||
275 | default: | ||
276 | err = -EINVAL; | ||
277 | break; | ||
278 | } | ||
279 | return err; | ||
280 | } | ||
281 | |||
282 | static snd_pcm_uframes_t alchemy_pcm_pointer(struct snd_pcm_substream *ss) | ||
283 | { | ||
284 | struct audio_stream *stream = ss_to_as(ss); | ||
285 | long location; | ||
286 | |||
287 | location = get_dma_residue(stream->dma); | ||
288 | location = stream->buffer->relative_end - location; | ||
289 | if (location == -1) | ||
290 | location = 0; | ||
291 | return bytes_to_frames(ss->runtime, location); | ||
292 | } | ||
293 | |||
294 | static struct snd_pcm_ops alchemy_pcm_ops = { | ||
295 | .open = alchemy_pcm_open, | ||
296 | .close = alchemy_pcm_close, | ||
297 | .ioctl = snd_pcm_lib_ioctl, | ||
298 | .hw_params = alchemy_pcm_hw_params, | ||
299 | .hw_free = alchemy_pcm_hw_free, | ||
300 | .trigger = alchemy_pcm_trigger, | ||
301 | .pointer = alchemy_pcm_pointer, | ||
302 | }; | ||
303 | |||
304 | static void alchemy_pcm_free_dma_buffers(struct snd_pcm *pcm) | ||
305 | { | ||
306 | snd_pcm_lib_preallocate_free_for_all(pcm); | ||
307 | } | ||
308 | |||
309 | static int alchemy_pcm_new(struct snd_soc_pcm_runtime *rtd) | ||
310 | { | ||
311 | struct snd_pcm *pcm = rtd->pcm; | ||
312 | |||
313 | snd_pcm_lib_preallocate_pages_for_all(pcm, SNDRV_DMA_TYPE_CONTINUOUS, | ||
314 | snd_dma_continuous_data(GFP_KERNEL), 65536, (4096 * 1024) - 1); | ||
315 | |||
316 | return 0; | ||
317 | } | ||
318 | |||
319 | struct snd_soc_platform_driver alchemy_pcm_soc_platform = { | ||
320 | .ops = &alchemy_pcm_ops, | ||
321 | .pcm_new = alchemy_pcm_new, | ||
322 | .pcm_free = alchemy_pcm_free_dma_buffers, | ||
323 | }; | ||
324 | |||
325 | static int __devinit alchemy_pcm_drvprobe(struct platform_device *pdev) | ||
326 | { | ||
327 | struct alchemy_pcm_ctx *ctx; | ||
328 | int ret; | ||
329 | |||
330 | ctx = kzalloc(sizeof(*ctx), GFP_KERNEL); | ||
331 | if (!ctx) | ||
332 | return -ENOMEM; | ||
333 | |||
334 | platform_set_drvdata(pdev, ctx); | ||
335 | |||
336 | ret = snd_soc_register_platform(&pdev->dev, &alchemy_pcm_soc_platform); | ||
337 | if (ret) | ||
338 | kfree(ctx); | ||
339 | |||
340 | return ret; | ||
341 | } | ||
342 | |||
343 | static int __devexit alchemy_pcm_drvremove(struct platform_device *pdev) | ||
344 | { | ||
345 | struct alchemy_pcm_ctx *ctx = platform_get_drvdata(pdev); | ||
346 | |||
347 | snd_soc_unregister_platform(&pdev->dev); | ||
348 | kfree(ctx); | ||
349 | |||
350 | return 0; | ||
351 | } | ||
352 | |||
353 | static struct platform_driver alchemy_pcmdma_driver = { | ||
354 | .driver = { | ||
355 | .name = "alchemy-pcm-dma", | ||
356 | .owner = THIS_MODULE, | ||
357 | }, | ||
358 | .probe = alchemy_pcm_drvprobe, | ||
359 | .remove = __devexit_p(alchemy_pcm_drvremove), | ||
360 | }; | ||
361 | |||
362 | static int __init alchemy_pcmdma_load(void) | ||
363 | { | ||
364 | return platform_driver_register(&alchemy_pcmdma_driver); | ||
365 | } | ||
366 | |||
367 | static void __exit alchemy_pcmdma_unload(void) | ||
368 | { | ||
369 | platform_driver_unregister(&alchemy_pcmdma_driver); | ||
370 | } | ||
371 | |||
372 | module_init(alchemy_pcmdma_load); | ||
373 | module_exit(alchemy_pcmdma_unload); | ||
374 | |||
375 | MODULE_LICENSE("GPL"); | ||
376 | MODULE_DESCRIPTION("Au1000/Au1500/Au1100 Audio DMA driver"); | ||
377 | MODULE_AUTHOR("Manuel Lauss"); | ||
diff --git a/sound/soc/au1x/i2sc.c b/sound/soc/au1x/i2sc.c new file mode 100644 index 000000000000..19e0d2a9c828 --- /dev/null +++ b/sound/soc/au1x/i2sc.c | |||
@@ -0,0 +1,346 @@ | |||
1 | /* | ||
2 | * Au1000/Au1500/Au1100 I2S controller driver for ASoC | ||
3 | * | ||
4 | * (c) 2011 Manuel Lauss <manuel.lauss@googlemail.com> | ||
5 | * | ||
6 | * Note: clock supplied to the I2S controller must be 256x samplerate. | ||
7 | */ | ||
8 | |||
9 | #include <linux/init.h> | ||
10 | #include <linux/module.h> | ||
11 | #include <linux/slab.h> | ||
12 | #include <linux/suspend.h> | ||
13 | #include <sound/core.h> | ||
14 | #include <sound/pcm.h> | ||
15 | #include <sound/initval.h> | ||
16 | #include <sound/soc.h> | ||
17 | #include <asm/mach-au1x00/au1000.h> | ||
18 | |||
19 | #include "psc.h" | ||
20 | |||
21 | #define I2S_RXTX 0x00 | ||
22 | #define I2S_CFG 0x04 | ||
23 | #define I2S_ENABLE 0x08 | ||
24 | |||
25 | #define CFG_XU (1 << 25) /* tx underflow */ | ||
26 | #define CFG_XO (1 << 24) | ||
27 | #define CFG_RU (1 << 23) | ||
28 | #define CFG_RO (1 << 22) | ||
29 | #define CFG_TR (1 << 21) | ||
30 | #define CFG_TE (1 << 20) | ||
31 | #define CFG_TF (1 << 19) | ||
32 | #define CFG_RR (1 << 18) | ||
33 | #define CFG_RF (1 << 17) | ||
34 | #define CFG_ICK (1 << 12) /* clock invert */ | ||
35 | #define CFG_PD (1 << 11) /* set to make I2SDIO INPUT */ | ||
36 | #define CFG_LB (1 << 10) /* loopback */ | ||
37 | #define CFG_IC (1 << 9) /* word select invert */ | ||
38 | #define CFG_FM_I2S (0 << 7) /* I2S format */ | ||
39 | #define CFG_FM_LJ (1 << 7) /* left-justified */ | ||
40 | #define CFG_FM_RJ (2 << 7) /* right-justified */ | ||
41 | #define CFG_FM_MASK (3 << 7) | ||
42 | #define CFG_TN (1 << 6) /* tx fifo en */ | ||
43 | #define CFG_RN (1 << 5) /* rx fifo en */ | ||
44 | #define CFG_SZ_8 (0x08) | ||
45 | #define CFG_SZ_16 (0x10) | ||
46 | #define CFG_SZ_18 (0x12) | ||
47 | #define CFG_SZ_20 (0x14) | ||
48 | #define CFG_SZ_24 (0x18) | ||
49 | #define CFG_SZ_MASK (0x1f) | ||
50 | #define EN_D (1 << 1) /* DISable */ | ||
51 | #define EN_CE (1 << 0) /* clock enable */ | ||
52 | |||
53 | /* only limited by clock generator and board design */ | ||
54 | #define AU1XI2SC_RATES \ | ||
55 | SNDRV_PCM_RATE_CONTINUOUS | ||
56 | |||
57 | #define AU1XI2SC_FMTS \ | ||
58 | (SNDRV_PCM_FMTBIT_S8 | SNDRV_PCM_FMTBIT_U8 | \ | ||
59 | SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S16_BE | \ | ||
60 | SNDRV_PCM_FMTBIT_U16_LE | SNDRV_PCM_FMTBIT_U16_BE | \ | ||
61 | SNDRV_PCM_FMTBIT_S18_3LE | SNDRV_PCM_FMTBIT_U18_3LE | \ | ||
62 | SNDRV_PCM_FMTBIT_S18_3BE | SNDRV_PCM_FMTBIT_U18_3BE | \ | ||
63 | SNDRV_PCM_FMTBIT_S20_3LE | SNDRV_PCM_FMTBIT_U20_3LE | \ | ||
64 | SNDRV_PCM_FMTBIT_S20_3BE | SNDRV_PCM_FMTBIT_U20_3BE | \ | ||
65 | SNDRV_PCM_FMTBIT_S24_LE | SNDRV_PCM_FMTBIT_S24_BE | \ | ||
66 | SNDRV_PCM_FMTBIT_U24_LE | SNDRV_PCM_FMTBIT_U24_BE | \ | ||
67 | 0) | ||
68 | |||
69 | static inline unsigned long RD(struct au1xpsc_audio_data *ctx, int reg) | ||
70 | { | ||
71 | return __raw_readl(ctx->mmio + reg); | ||
72 | } | ||
73 | |||
74 | static inline void WR(struct au1xpsc_audio_data *ctx, int reg, unsigned long v) | ||
75 | { | ||
76 | __raw_writel(v, ctx->mmio + reg); | ||
77 | wmb(); | ||
78 | } | ||
79 | |||
80 | static int au1xi2s_set_fmt(struct snd_soc_dai *cpu_dai, unsigned int fmt) | ||
81 | { | ||
82 | struct au1xpsc_audio_data *ctx = snd_soc_dai_get_drvdata(cpu_dai); | ||
83 | unsigned long c; | ||
84 | int ret; | ||
85 | |||
86 | ret = -EINVAL; | ||
87 | c = ctx->cfg; | ||
88 | |||
89 | c &= ~CFG_FM_MASK; | ||
90 | switch (fmt & SND_SOC_DAIFMT_FORMAT_MASK) { | ||
91 | case SND_SOC_DAIFMT_I2S: | ||
92 | c |= CFG_FM_I2S; | ||
93 | break; | ||
94 | case SND_SOC_DAIFMT_MSB: | ||
95 | c |= CFG_FM_RJ; | ||
96 | break; | ||
97 | case SND_SOC_DAIFMT_LSB: | ||
98 | c |= CFG_FM_LJ; | ||
99 | break; | ||
100 | default: | ||
101 | goto out; | ||
102 | } | ||
103 | |||
104 | c &= ~(CFG_IC | CFG_ICK); /* IB-IF */ | ||
105 | switch (fmt & SND_SOC_DAIFMT_INV_MASK) { | ||
106 | case SND_SOC_DAIFMT_NB_NF: | ||
107 | c |= CFG_IC | CFG_ICK; | ||
108 | break; | ||
109 | case SND_SOC_DAIFMT_NB_IF: | ||
110 | c |= CFG_IC; | ||
111 | break; | ||
112 | case SND_SOC_DAIFMT_IB_NF: | ||
113 | c |= CFG_ICK; | ||
114 | break; | ||
115 | case SND_SOC_DAIFMT_IB_IF: | ||
116 | break; | ||
117 | default: | ||
118 | goto out; | ||
119 | } | ||
120 | |||
121 | /* I2S controller only supports master */ | ||
122 | switch (fmt & SND_SOC_DAIFMT_MASTER_MASK) { | ||
123 | case SND_SOC_DAIFMT_CBS_CFS: /* CODEC slave */ | ||
124 | break; | ||
125 | default: | ||
126 | goto out; | ||
127 | } | ||
128 | |||
129 | ret = 0; | ||
130 | ctx->cfg = c; | ||
131 | out: | ||
132 | return ret; | ||
133 | } | ||
134 | |||
135 | static int au1xi2s_trigger(struct snd_pcm_substream *substream, | ||
136 | int cmd, struct snd_soc_dai *dai) | ||
137 | { | ||
138 | struct au1xpsc_audio_data *ctx = snd_soc_dai_get_drvdata(dai); | ||
139 | int stype = SUBSTREAM_TYPE(substream); | ||
140 | |||
141 | switch (cmd) { | ||
142 | case SNDRV_PCM_TRIGGER_START: | ||
143 | case SNDRV_PCM_TRIGGER_RESUME: | ||
144 | /* power up */ | ||
145 | WR(ctx, I2S_ENABLE, EN_D | EN_CE); | ||
146 | WR(ctx, I2S_ENABLE, EN_CE); | ||
147 | ctx->cfg |= (stype == PCM_TX) ? CFG_TN : CFG_RN; | ||
148 | WR(ctx, I2S_CFG, ctx->cfg); | ||
149 | break; | ||
150 | case SNDRV_PCM_TRIGGER_STOP: | ||
151 | case SNDRV_PCM_TRIGGER_SUSPEND: | ||
152 | ctx->cfg &= ~((stype == PCM_TX) ? CFG_TN : CFG_RN); | ||
153 | WR(ctx, I2S_CFG, ctx->cfg); | ||
154 | WR(ctx, I2S_ENABLE, EN_D); /* power off */ | ||
155 | break; | ||
156 | default: | ||
157 | return -EINVAL; | ||
158 | } | ||
159 | |||
160 | return 0; | ||
161 | } | ||
162 | |||
163 | static unsigned long msbits_to_reg(int msbits) | ||
164 | { | ||
165 | switch (msbits) { | ||
166 | case 8: | ||
167 | return CFG_SZ_8; | ||
168 | case 16: | ||
169 | return CFG_SZ_16; | ||
170 | case 18: | ||
171 | return CFG_SZ_18; | ||
172 | case 20: | ||
173 | return CFG_SZ_20; | ||
174 | case 24: | ||
175 | return CFG_SZ_24; | ||
176 | } | ||
177 | return 0; | ||
178 | } | ||
179 | |||
180 | static int au1xi2s_hw_params(struct snd_pcm_substream *substream, | ||
181 | struct snd_pcm_hw_params *params, | ||
182 | struct snd_soc_dai *dai) | ||
183 | { | ||
184 | struct au1xpsc_audio_data *ctx = snd_soc_dai_get_drvdata(dai); | ||
185 | unsigned long v; | ||
186 | |||
187 | v = msbits_to_reg(params->msbits); | ||
188 | if (!v) | ||
189 | return -EINVAL; | ||
190 | |||
191 | ctx->cfg &= ~CFG_SZ_MASK; | ||
192 | ctx->cfg |= v; | ||
193 | return 0; | ||
194 | } | ||
195 | |||
196 | static int au1xi2s_startup(struct snd_pcm_substream *substream, | ||
197 | struct snd_soc_dai *dai) | ||
198 | { | ||
199 | struct au1xpsc_audio_data *ctx = snd_soc_dai_get_drvdata(dai); | ||
200 | snd_soc_dai_set_dma_data(dai, substream, &ctx->dmaids[0]); | ||
201 | return 0; | ||
202 | } | ||
203 | |||
204 | static const struct snd_soc_dai_ops au1xi2s_dai_ops = { | ||
205 | .startup = au1xi2s_startup, | ||
206 | .trigger = au1xi2s_trigger, | ||
207 | .hw_params = au1xi2s_hw_params, | ||
208 | .set_fmt = au1xi2s_set_fmt, | ||
209 | }; | ||
210 | |||
211 | static struct snd_soc_dai_driver au1xi2s_dai_driver = { | ||
212 | .symmetric_rates = 1, | ||
213 | .playback = { | ||
214 | .rates = AU1XI2SC_RATES, | ||
215 | .formats = AU1XI2SC_FMTS, | ||
216 | .channels_min = 2, | ||
217 | .channels_max = 2, | ||
218 | }, | ||
219 | .capture = { | ||
220 | .rates = AU1XI2SC_RATES, | ||
221 | .formats = AU1XI2SC_FMTS, | ||
222 | .channels_min = 2, | ||
223 | .channels_max = 2, | ||
224 | }, | ||
225 | .ops = &au1xi2s_dai_ops, | ||
226 | }; | ||
227 | |||
228 | static int __devinit au1xi2s_drvprobe(struct platform_device *pdev) | ||
229 | { | ||
230 | int ret; | ||
231 | struct resource *r; | ||
232 | struct au1xpsc_audio_data *ctx; | ||
233 | |||
234 | ctx = kzalloc(sizeof(*ctx), GFP_KERNEL); | ||
235 | if (!ctx) | ||
236 | return -ENOMEM; | ||
237 | |||
238 | r = platform_get_resource(pdev, IORESOURCE_MEM, 0); | ||
239 | if (!r) { | ||
240 | ret = -ENODEV; | ||
241 | goto out0; | ||
242 | } | ||
243 | |||
244 | ret = -EBUSY; | ||
245 | if (!request_mem_region(r->start, resource_size(r), pdev->name)) | ||
246 | goto out0; | ||
247 | |||
248 | ctx->mmio = ioremap_nocache(r->start, resource_size(r)); | ||
249 | if (!ctx->mmio) | ||
250 | goto out1; | ||
251 | |||
252 | r = platform_get_resource(pdev, IORESOURCE_DMA, 0); | ||
253 | if (!r) | ||
254 | goto out1; | ||
255 | ctx->dmaids[SNDRV_PCM_STREAM_PLAYBACK] = r->start; | ||
256 | |||
257 | r = platform_get_resource(pdev, IORESOURCE_DMA, 1); | ||
258 | if (!r) | ||
259 | goto out1; | ||
260 | ctx->dmaids[SNDRV_PCM_STREAM_CAPTURE] = r->start; | ||
261 | |||
262 | platform_set_drvdata(pdev, ctx); | ||
263 | |||
264 | ret = snd_soc_register_dai(&pdev->dev, &au1xi2s_dai_driver); | ||
265 | if (ret) | ||
266 | goto out1; | ||
267 | |||
268 | return 0; | ||
269 | |||
270 | out1: | ||
271 | release_mem_region(r->start, resource_size(r)); | ||
272 | out0: | ||
273 | kfree(ctx); | ||
274 | return ret; | ||
275 | } | ||
276 | |||
277 | static int __devexit au1xi2s_drvremove(struct platform_device *pdev) | ||
278 | { | ||
279 | struct au1xpsc_audio_data *ctx = platform_get_drvdata(pdev); | ||
280 | struct resource *r = platform_get_resource(pdev, IORESOURCE_MEM, 0); | ||
281 | |||
282 | snd_soc_unregister_dai(&pdev->dev); | ||
283 | |||
284 | WR(ctx, I2S_ENABLE, EN_D); /* clock off, disable */ | ||
285 | |||
286 | iounmap(ctx->mmio); | ||
287 | release_mem_region(r->start, resource_size(r)); | ||
288 | kfree(ctx); | ||
289 | |||
290 | return 0; | ||
291 | } | ||
292 | |||
293 | #ifdef CONFIG_PM | ||
294 | static int au1xi2s_drvsuspend(struct device *dev) | ||
295 | { | ||
296 | struct au1xpsc_audio_data *ctx = dev_get_drvdata(dev); | ||
297 | |||
298 | WR(ctx, I2S_ENABLE, EN_D); /* clock off, disable */ | ||
299 | |||
300 | return 0; | ||
301 | } | ||
302 | |||
303 | static int au1xi2s_drvresume(struct device *dev) | ||
304 | { | ||
305 | return 0; | ||
306 | } | ||
307 | |||
308 | static const struct dev_pm_ops au1xi2sc_pmops = { | ||
309 | .suspend = au1xi2s_drvsuspend, | ||
310 | .resume = au1xi2s_drvresume, | ||
311 | }; | ||
312 | |||
313 | #define AU1XI2SC_PMOPS (&au1xi2sc_pmops) | ||
314 | |||
315 | #else | ||
316 | |||
317 | #define AU1XI2SC_PMOPS NULL | ||
318 | |||
319 | #endif | ||
320 | |||
321 | static struct platform_driver au1xi2s_driver = { | ||
322 | .driver = { | ||
323 | .name = "alchemy-i2sc", | ||
324 | .owner = THIS_MODULE, | ||
325 | .pm = AU1XI2SC_PMOPS, | ||
326 | }, | ||
327 | .probe = au1xi2s_drvprobe, | ||
328 | .remove = __devexit_p(au1xi2s_drvremove), | ||
329 | }; | ||
330 | |||
331 | static int __init au1xi2s_load(void) | ||
332 | { | ||
333 | return platform_driver_register(&au1xi2s_driver); | ||
334 | } | ||
335 | |||
336 | static void __exit au1xi2s_unload(void) | ||
337 | { | ||
338 | platform_driver_unregister(&au1xi2s_driver); | ||
339 | } | ||
340 | |||
341 | module_init(au1xi2s_load); | ||
342 | module_exit(au1xi2s_unload); | ||
343 | |||
344 | MODULE_LICENSE("GPL"); | ||
345 | MODULE_DESCRIPTION("Au1000/1500/1100 I2S ASoC driver"); | ||
346 | MODULE_AUTHOR("Manuel Lauss"); | ||
diff --git a/sound/soc/au1x/psc-ac97.c b/sound/soc/au1x/psc-ac97.c index d0db66f24a00..172eefd38b2d 100644 --- a/sound/soc/au1x/psc-ac97.c +++ b/sound/soc/au1x/psc-ac97.c | |||
@@ -41,14 +41,14 @@ | |||
41 | (SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S20_3BE) | 41 | (SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S20_3BE) |
42 | 42 | ||
43 | #define AC97PCR_START(stype) \ | 43 | #define AC97PCR_START(stype) \ |
44 | ((stype) == PCM_TX ? PSC_AC97PCR_TS : PSC_AC97PCR_RS) | 44 | ((stype) == SNDRV_PCM_STREAM_PLAYBACK ? PSC_AC97PCR_TS : PSC_AC97PCR_RS) |
45 | #define AC97PCR_STOP(stype) \ | 45 | #define AC97PCR_STOP(stype) \ |
46 | ((stype) == PCM_TX ? PSC_AC97PCR_TP : PSC_AC97PCR_RP) | 46 | ((stype) == SNDRV_PCM_STREAM_PLAYBACK ? PSC_AC97PCR_TP : PSC_AC97PCR_RP) |
47 | #define AC97PCR_CLRFIFO(stype) \ | 47 | #define AC97PCR_CLRFIFO(stype) \ |
48 | ((stype) == PCM_TX ? PSC_AC97PCR_TC : PSC_AC97PCR_RC) | 48 | ((stype) == SNDRV_PCM_STREAM_PLAYBACK ? PSC_AC97PCR_TC : PSC_AC97PCR_RC) |
49 | 49 | ||
50 | #define AC97STAT_BUSY(stype) \ | 50 | #define AC97STAT_BUSY(stype) \ |
51 | ((stype) == PCM_TX ? PSC_AC97STAT_TB : PSC_AC97STAT_RB) | 51 | ((stype) == SNDRV_PCM_STREAM_PLAYBACK ? PSC_AC97STAT_TB : PSC_AC97STAT_RB) |
52 | 52 | ||
53 | /* instance data. There can be only one, MacLeod!!!! */ | 53 | /* instance data. There can be only one, MacLeod!!!! */ |
54 | static struct au1xpsc_audio_data *au1xpsc_ac97_workdata; | 54 | static struct au1xpsc_audio_data *au1xpsc_ac97_workdata; |
@@ -215,7 +215,7 @@ static int au1xpsc_ac97_hw_params(struct snd_pcm_substream *substream, | |||
215 | { | 215 | { |
216 | struct au1xpsc_audio_data *pscdata = snd_soc_dai_get_drvdata(dai); | 216 | struct au1xpsc_audio_data *pscdata = snd_soc_dai_get_drvdata(dai); |
217 | unsigned long r, ro, stat; | 217 | unsigned long r, ro, stat; |
218 | int chans, t, stype = SUBSTREAM_TYPE(substream); | 218 | int chans, t, stype = substream->stream; |
219 | 219 | ||
220 | chans = params_channels(params); | 220 | chans = params_channels(params); |
221 | 221 | ||
@@ -235,7 +235,7 @@ static int au1xpsc_ac97_hw_params(struct snd_pcm_substream *substream, | |||
235 | r |= PSC_AC97CFG_SET_LEN(params->msbits); | 235 | r |= PSC_AC97CFG_SET_LEN(params->msbits); |
236 | 236 | ||
237 | /* channels: enable slots for front L/R channel */ | 237 | /* channels: enable slots for front L/R channel */ |
238 | if (stype == PCM_TX) { | 238 | if (stype == SNDRV_PCM_STREAM_PLAYBACK) { |
239 | r &= ~PSC_AC97CFG_TXSLOT_MASK; | 239 | r &= ~PSC_AC97CFG_TXSLOT_MASK; |
240 | r |= PSC_AC97CFG_TXSLOT_ENA(3); | 240 | r |= PSC_AC97CFG_TXSLOT_ENA(3); |
241 | r |= PSC_AC97CFG_TXSLOT_ENA(4); | 241 | r |= PSC_AC97CFG_TXSLOT_ENA(4); |
@@ -294,7 +294,7 @@ static int au1xpsc_ac97_trigger(struct snd_pcm_substream *substream, | |||
294 | int cmd, struct snd_soc_dai *dai) | 294 | int cmd, struct snd_soc_dai *dai) |
295 | { | 295 | { |
296 | struct au1xpsc_audio_data *pscdata = snd_soc_dai_get_drvdata(dai); | 296 | struct au1xpsc_audio_data *pscdata = snd_soc_dai_get_drvdata(dai); |
297 | int ret, stype = SUBSTREAM_TYPE(substream); | 297 | int ret, stype = substream->stream; |
298 | 298 | ||
299 | ret = 0; | 299 | ret = 0; |
300 | 300 | ||
@@ -324,12 +324,21 @@ static int au1xpsc_ac97_trigger(struct snd_pcm_substream *substream, | |||
324 | return ret; | 324 | return ret; |
325 | } | 325 | } |
326 | 326 | ||
327 | static int au1xpsc_ac97_startup(struct snd_pcm_substream *substream, | ||
328 | struct snd_soc_dai *dai) | ||
329 | { | ||
330 | struct au1xpsc_audio_data *pscdata = snd_soc_dai_get_drvdata(dai); | ||
331 | snd_soc_dai_set_dma_data(dai, substream, &pscdata->dmaids[0]); | ||
332 | return 0; | ||
333 | } | ||
334 | |||
327 | static int au1xpsc_ac97_probe(struct snd_soc_dai *dai) | 335 | static int au1xpsc_ac97_probe(struct snd_soc_dai *dai) |
328 | { | 336 | { |
329 | return au1xpsc_ac97_workdata ? 0 : -ENODEV; | 337 | return au1xpsc_ac97_workdata ? 0 : -ENODEV; |
330 | } | 338 | } |
331 | 339 | ||
332 | static struct snd_soc_dai_ops au1xpsc_ac97_dai_ops = { | 340 | static struct snd_soc_dai_ops au1xpsc_ac97_dai_ops = { |
341 | .startup = au1xpsc_ac97_startup, | ||
333 | .trigger = au1xpsc_ac97_trigger, | 342 | .trigger = au1xpsc_ac97_trigger, |
334 | .hw_params = au1xpsc_ac97_hw_params, | 343 | .hw_params = au1xpsc_ac97_hw_params, |
335 | }; | 344 | }; |
@@ -379,6 +388,16 @@ static int __devinit au1xpsc_ac97_drvprobe(struct platform_device *pdev) | |||
379 | if (!wd->mmio) | 388 | if (!wd->mmio) |
380 | goto out1; | 389 | goto out1; |
381 | 390 | ||
391 | r = platform_get_resource(pdev, IORESOURCE_DMA, 0); | ||
392 | if (!r) | ||
393 | goto out2; | ||
394 | wd->dmaids[SNDRV_PCM_STREAM_PLAYBACK] = r->start; | ||
395 | |||
396 | r = platform_get_resource(pdev, IORESOURCE_DMA, 1); | ||
397 | if (!r) | ||
398 | goto out2; | ||
399 | wd->dmaids[SNDRV_PCM_STREAM_CAPTURE] = r->start; | ||
400 | |||
382 | /* configuration: max dma trigger threshold, enable ac97 */ | 401 | /* configuration: max dma trigger threshold, enable ac97 */ |
383 | wd->cfg = PSC_AC97CFG_RT_FIFO8 | PSC_AC97CFG_TT_FIFO8 | | 402 | wd->cfg = PSC_AC97CFG_RT_FIFO8 | PSC_AC97CFG_TT_FIFO8 | |
384 | PSC_AC97CFG_DE_ENABLE; | 403 | PSC_AC97CFG_DE_ENABLE; |
@@ -401,15 +420,13 @@ static int __devinit au1xpsc_ac97_drvprobe(struct platform_device *pdev) | |||
401 | 420 | ||
402 | ret = snd_soc_register_dai(&pdev->dev, &wd->dai_drv); | 421 | ret = snd_soc_register_dai(&pdev->dev, &wd->dai_drv); |
403 | if (ret) | 422 | if (ret) |
404 | goto out1; | 423 | goto out2; |
405 | 424 | ||
406 | wd->dmapd = au1xpsc_pcm_add(pdev); | 425 | au1xpsc_ac97_workdata = wd; |
407 | if (wd->dmapd) { | 426 | return 0; |
408 | au1xpsc_ac97_workdata = wd; | ||
409 | return 0; | ||
410 | } | ||
411 | 427 | ||
412 | snd_soc_unregister_dai(&pdev->dev); | 428 | out2: |
429 | iounmap(wd->mmio); | ||
413 | out1: | 430 | out1: |
414 | release_mem_region(r->start, resource_size(r)); | 431 | release_mem_region(r->start, resource_size(r)); |
415 | out0: | 432 | out0: |
@@ -422,9 +439,6 @@ static int __devexit au1xpsc_ac97_drvremove(struct platform_device *pdev) | |||
422 | struct au1xpsc_audio_data *wd = platform_get_drvdata(pdev); | 439 | struct au1xpsc_audio_data *wd = platform_get_drvdata(pdev); |
423 | struct resource *r = platform_get_resource(pdev, IORESOURCE_MEM, 0); | 440 | struct resource *r = platform_get_resource(pdev, IORESOURCE_MEM, 0); |
424 | 441 | ||
425 | if (wd->dmapd) | ||
426 | au1xpsc_pcm_destroy(wd->dmapd); | ||
427 | |||
428 | snd_soc_unregister_dai(&pdev->dev); | 442 | snd_soc_unregister_dai(&pdev->dev); |
429 | 443 | ||
430 | /* disable PSC completely */ | 444 | /* disable PSC completely */ |
diff --git a/sound/soc/au1x/psc-i2s.c b/sound/soc/au1x/psc-i2s.c index fca091276320..7c5ae920544f 100644 --- a/sound/soc/au1x/psc-i2s.c +++ b/sound/soc/au1x/psc-i2s.c | |||
@@ -42,13 +42,13 @@ | |||
42 | (SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S24_LE) | 42 | (SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S24_LE) |
43 | 43 | ||
44 | #define I2SSTAT_BUSY(stype) \ | 44 | #define I2SSTAT_BUSY(stype) \ |
45 | ((stype) == PCM_TX ? PSC_I2SSTAT_TB : PSC_I2SSTAT_RB) | 45 | ((stype) == SNDRV_PCM_STREAM_PLAYBACK ? PSC_I2SSTAT_TB : PSC_I2SSTAT_RB) |
46 | #define I2SPCR_START(stype) \ | 46 | #define I2SPCR_START(stype) \ |
47 | ((stype) == PCM_TX ? PSC_I2SPCR_TS : PSC_I2SPCR_RS) | 47 | ((stype) == SNDRV_PCM_STREAM_PLAYBACK ? PSC_I2SPCR_TS : PSC_I2SPCR_RS) |
48 | #define I2SPCR_STOP(stype) \ | 48 | #define I2SPCR_STOP(stype) \ |
49 | ((stype) == PCM_TX ? PSC_I2SPCR_TP : PSC_I2SPCR_RP) | 49 | ((stype) == SNDRV_PCM_STREAM_PLAYBACK ? PSC_I2SPCR_TP : PSC_I2SPCR_RP) |
50 | #define I2SPCR_CLRFIFO(stype) \ | 50 | #define I2SPCR_CLRFIFO(stype) \ |
51 | ((stype) == PCM_TX ? PSC_I2SPCR_TC : PSC_I2SPCR_RC) | 51 | ((stype) == SNDRV_PCM_STREAM_PLAYBACK ? PSC_I2SPCR_TC : PSC_I2SPCR_RC) |
52 | 52 | ||
53 | 53 | ||
54 | static int au1xpsc_i2s_set_fmt(struct snd_soc_dai *cpu_dai, | 54 | static int au1xpsc_i2s_set_fmt(struct snd_soc_dai *cpu_dai, |
@@ -240,7 +240,7 @@ static int au1xpsc_i2s_trigger(struct snd_pcm_substream *substream, int cmd, | |||
240 | struct snd_soc_dai *dai) | 240 | struct snd_soc_dai *dai) |
241 | { | 241 | { |
242 | struct au1xpsc_audio_data *pscdata = snd_soc_dai_get_drvdata(dai); | 242 | struct au1xpsc_audio_data *pscdata = snd_soc_dai_get_drvdata(dai); |
243 | int ret, stype = SUBSTREAM_TYPE(substream); | 243 | int ret, stype = substream->stream; |
244 | 244 | ||
245 | switch (cmd) { | 245 | switch (cmd) { |
246 | case SNDRV_PCM_TRIGGER_START: | 246 | case SNDRV_PCM_TRIGGER_START: |
@@ -257,7 +257,16 @@ static int au1xpsc_i2s_trigger(struct snd_pcm_substream *substream, int cmd, | |||
257 | return ret; | 257 | return ret; |
258 | } | 258 | } |
259 | 259 | ||
260 | static int au1xpsc_i2s_startup(struct snd_pcm_substream *substream, | ||
261 | struct snd_soc_dai *dai) | ||
262 | { | ||
263 | struct au1xpsc_audio_data *pscdata = snd_soc_dai_get_drvdata(dai); | ||
264 | snd_soc_dai_set_dma_data(dai, substream, &pscdata->dmaids[0]); | ||
265 | return 0; | ||
266 | } | ||
267 | |||
260 | static struct snd_soc_dai_ops au1xpsc_i2s_dai_ops = { | 268 | static struct snd_soc_dai_ops au1xpsc_i2s_dai_ops = { |
269 | .startup = au1xpsc_i2s_startup, | ||
261 | .trigger = au1xpsc_i2s_trigger, | 270 | .trigger = au1xpsc_i2s_trigger, |
262 | .hw_params = au1xpsc_i2s_hw_params, | 271 | .hw_params = au1xpsc_i2s_hw_params, |
263 | .set_fmt = au1xpsc_i2s_set_fmt, | 272 | .set_fmt = au1xpsc_i2s_set_fmt, |
@@ -304,6 +313,16 @@ static int __devinit au1xpsc_i2s_drvprobe(struct platform_device *pdev) | |||
304 | if (!wd->mmio) | 313 | if (!wd->mmio) |
305 | goto out1; | 314 | goto out1; |
306 | 315 | ||
316 | r = platform_get_resource(pdev, IORESOURCE_DMA, 0); | ||
317 | if (!r) | ||
318 | goto out2; | ||
319 | wd->dmaids[SNDRV_PCM_STREAM_PLAYBACK] = r->start; | ||
320 | |||
321 | r = platform_get_resource(pdev, IORESOURCE_DMA, 1); | ||
322 | if (!r) | ||
323 | goto out2; | ||
324 | wd->dmaids[SNDRV_PCM_STREAM_CAPTURE] = r->start; | ||
325 | |||
307 | /* preserve PSC clock source set up by platform (dev.platform_data | 326 | /* preserve PSC clock source set up by platform (dev.platform_data |
308 | * is already occupied by soc layer) | 327 | * is already occupied by soc layer) |
309 | */ | 328 | */ |
@@ -330,15 +349,11 @@ static int __devinit au1xpsc_i2s_drvprobe(struct platform_device *pdev) | |||
330 | platform_set_drvdata(pdev, wd); | 349 | platform_set_drvdata(pdev, wd); |
331 | 350 | ||
332 | ret = snd_soc_register_dai(&pdev->dev, &wd->dai_drv); | 351 | ret = snd_soc_register_dai(&pdev->dev, &wd->dai_drv); |
333 | if (ret) | 352 | if (!ret) |
334 | goto out1; | ||
335 | |||
336 | /* finally add the DMA device for this PSC */ | ||
337 | wd->dmapd = au1xpsc_pcm_add(pdev); | ||
338 | if (wd->dmapd) | ||
339 | return 0; | 353 | return 0; |
340 | 354 | ||
341 | snd_soc_unregister_dai(&pdev->dev); | 355 | out2: |
356 | iounmap(wd->mmio); | ||
342 | out1: | 357 | out1: |
343 | release_mem_region(r->start, resource_size(r)); | 358 | release_mem_region(r->start, resource_size(r)); |
344 | out0: | 359 | out0: |
@@ -351,9 +366,6 @@ static int __devexit au1xpsc_i2s_drvremove(struct platform_device *pdev) | |||
351 | struct au1xpsc_audio_data *wd = platform_get_drvdata(pdev); | 366 | struct au1xpsc_audio_data *wd = platform_get_drvdata(pdev); |
352 | struct resource *r = platform_get_resource(pdev, IORESOURCE_MEM, 0); | 367 | struct resource *r = platform_get_resource(pdev, IORESOURCE_MEM, 0); |
353 | 368 | ||
354 | if (wd->dmapd) | ||
355 | au1xpsc_pcm_destroy(wd->dmapd); | ||
356 | |||
357 | snd_soc_unregister_dai(&pdev->dev); | 369 | snd_soc_unregister_dai(&pdev->dev); |
358 | 370 | ||
359 | au_writel(0, I2S_CFG(wd)); | 371 | au_writel(0, I2S_CFG(wd)); |
diff --git a/sound/soc/au1x/psc.h b/sound/soc/au1x/psc.h index b30eadd422a7..b16b2e02e0c9 100644 --- a/sound/soc/au1x/psc.h +++ b/sound/soc/au1x/psc.h | |||
@@ -1,7 +1,7 @@ | |||
1 | /* | 1 | /* |
2 | * Au12x0/Au1550 PSC ALSA ASoC audio support. | 2 | * Alchemy ALSA ASoC audio support. |
3 | * | 3 | * |
4 | * (c) 2007-2008 MSC Vertriebsges.m.b.H., | 4 | * (c) 2007-2011 MSC Vertriebsges.m.b.H., |
5 | * Manuel Lauss <manuel.lauss@gmail.com> | 5 | * Manuel Lauss <manuel.lauss@gmail.com> |
6 | * | 6 | * |
7 | * This program is free software; you can redistribute it and/or modify | 7 | * This program is free software; you can redistribute it and/or modify |
@@ -13,10 +13,6 @@ | |||
13 | #ifndef _AU1X_PCM_H | 13 | #ifndef _AU1X_PCM_H |
14 | #define _AU1X_PCM_H | 14 | #define _AU1X_PCM_H |
15 | 15 | ||
16 | /* DBDMA helpers */ | ||
17 | extern struct platform_device *au1xpsc_pcm_add(struct platform_device *pdev); | ||
18 | extern void au1xpsc_pcm_destroy(struct platform_device *dmapd); | ||
19 | |||
20 | struct au1xpsc_audio_data { | 16 | struct au1xpsc_audio_data { |
21 | void __iomem *mmio; | 17 | void __iomem *mmio; |
22 | 18 | ||
@@ -27,15 +23,9 @@ struct au1xpsc_audio_data { | |||
27 | 23 | ||
28 | unsigned long pm[2]; | 24 | unsigned long pm[2]; |
29 | struct mutex lock; | 25 | struct mutex lock; |
30 | struct platform_device *dmapd; | 26 | int dmaids[2]; |
31 | }; | 27 | }; |
32 | 28 | ||
33 | #define PCM_TX 0 | ||
34 | #define PCM_RX 1 | ||
35 | |||
36 | #define SUBSTREAM_TYPE(substream) \ | ||
37 | ((substream)->stream == SNDRV_PCM_STREAM_PLAYBACK ? PCM_TX : PCM_RX) | ||
38 | |||
39 | /* easy access macros */ | 29 | /* easy access macros */ |
40 | #define PSC_CTRL(x) ((unsigned long)((x)->mmio) + PSC_CTRL_OFFSET) | 30 | #define PSC_CTRL(x) ((unsigned long)((x)->mmio) + PSC_CTRL_OFFSET) |
41 | #define PSC_SEL(x) ((unsigned long)((x)->mmio) + PSC_SEL_OFFSET) | 31 | #define PSC_SEL(x) ((unsigned long)((x)->mmio) + PSC_SEL_OFFSET) |
diff --git a/sound/soc/blackfin/Kconfig b/sound/soc/blackfin/Kconfig index fe9d548a6837..9f6bc55fc399 100644 --- a/sound/soc/blackfin/Kconfig +++ b/sound/soc/blackfin/Kconfig | |||
@@ -27,6 +27,19 @@ config SND_SOC_BFIN_EVAL_ADAU1701 | |||
27 | board connected to one of the Blackfin evaluation boards like the | 27 | board connected to one of the Blackfin evaluation boards like the |
28 | BF5XX-STAMP or BF5XX-EZKIT. | 28 | BF5XX-STAMP or BF5XX-EZKIT. |
29 | 29 | ||
30 | config SND_SOC_BFIN_EVAL_ADAU1373 | ||
31 | tristate "Support for the EVAL-ADAU1373 board on Blackfin eval boards" | ||
32 | depends on SND_BF5XX_I2S && I2C | ||
33 | select SND_BF5XX_SOC_I2S | ||
34 | select SND_SOC_ADAU1373 | ||
35 | help | ||
36 | Say Y if you want to add support for the Analog Devices EVAL-ADAU1373 | ||
37 | board connected to one of the Blackfin evaluation boards like the | ||
38 | BF5XX-STAMP or BF5XX-EZKIT. | ||
39 | |||
40 | Note: This driver assumes that first ADAU1373 DAI is connected to the | ||
41 | first SPORT port on the BF5XX board. | ||
42 | |||
30 | config SND_SOC_BFIN_EVAL_ADAV80X | 43 | config SND_SOC_BFIN_EVAL_ADAV80X |
31 | tristate "Support for the EVAL-ADAV80X boards on Blackfin eval boards" | 44 | tristate "Support for the EVAL-ADAV80X boards on Blackfin eval boards" |
32 | depends on SND_BF5XX_I2S && (SPI_MASTER || I2C) | 45 | depends on SND_BF5XX_I2S && (SPI_MASTER || I2C) |
diff --git a/sound/soc/blackfin/Makefile b/sound/soc/blackfin/Makefile index 6018bf52a234..1bf86ccaa8de 100644 --- a/sound/soc/blackfin/Makefile +++ b/sound/soc/blackfin/Makefile | |||
@@ -21,6 +21,7 @@ snd-ad1980-objs := bf5xx-ad1980.o | |||
21 | snd-ssm2602-objs := bf5xx-ssm2602.o | 21 | snd-ssm2602-objs := bf5xx-ssm2602.o |
22 | snd-ad73311-objs := bf5xx-ad73311.o | 22 | snd-ad73311-objs := bf5xx-ad73311.o |
23 | snd-ad193x-objs := bf5xx-ad193x.o | 23 | snd-ad193x-objs := bf5xx-ad193x.o |
24 | snd-soc-bfin-eval-adau1373-objs := bfin-eval-adau1373.o | ||
24 | snd-soc-bfin-eval-adau1701-objs := bfin-eval-adau1701.o | 25 | snd-soc-bfin-eval-adau1701-objs := bfin-eval-adau1701.o |
25 | snd-soc-bfin-eval-adav80x-objs := bfin-eval-adav80x.o | 26 | snd-soc-bfin-eval-adav80x-objs := bfin-eval-adav80x.o |
26 | 27 | ||
@@ -29,5 +30,6 @@ obj-$(CONFIG_SND_BF5XX_SOC_AD1980) += snd-ad1980.o | |||
29 | obj-$(CONFIG_SND_BF5XX_SOC_SSM2602) += snd-ssm2602.o | 30 | obj-$(CONFIG_SND_BF5XX_SOC_SSM2602) += snd-ssm2602.o |
30 | obj-$(CONFIG_SND_BF5XX_SOC_AD73311) += snd-ad73311.o | 31 | obj-$(CONFIG_SND_BF5XX_SOC_AD73311) += snd-ad73311.o |
31 | obj-$(CONFIG_SND_BF5XX_SOC_AD193X) += snd-ad193x.o | 32 | obj-$(CONFIG_SND_BF5XX_SOC_AD193X) += snd-ad193x.o |
33 | obj-$(CONFIG_SND_SOC_BFIN_EVAL_ADAU1373) += snd-soc-bfin-eval-adau1373.o | ||
32 | obj-$(CONFIG_SND_SOC_BFIN_EVAL_ADAU1701) += snd-soc-bfin-eval-adau1701.o | 34 | obj-$(CONFIG_SND_SOC_BFIN_EVAL_ADAU1701) += snd-soc-bfin-eval-adau1701.o |
33 | obj-$(CONFIG_SND_SOC_BFIN_EVAL_ADAV80X) += snd-soc-bfin-eval-adav80x.o | 35 | obj-$(CONFIG_SND_SOC_BFIN_EVAL_ADAV80X) += snd-soc-bfin-eval-adav80x.o |
diff --git a/sound/soc/blackfin/bfin-eval-adau1373.c b/sound/soc/blackfin/bfin-eval-adau1373.c new file mode 100644 index 000000000000..8df2a3b0cb36 --- /dev/null +++ b/sound/soc/blackfin/bfin-eval-adau1373.c | |||
@@ -0,0 +1,202 @@ | |||
1 | /* | ||
2 | * Machine driver for EVAL-ADAU1373 on Analog Devices bfin | ||
3 | * evaluation boards. | ||
4 | * | ||
5 | * Copyright 2011 Analog Devices Inc. | ||
6 | * Author: Lars-Peter Clausen <lars@metafoo.de> | ||
7 | * | ||
8 | * Licensed under the GPL-2 or later. | ||
9 | */ | ||
10 | |||
11 | #include <linux/module.h> | ||
12 | #include <linux/device.h> | ||
13 | #include <sound/core.h> | ||
14 | #include <sound/pcm.h> | ||
15 | #include <sound/soc.h> | ||
16 | #include <sound/pcm_params.h> | ||
17 | |||
18 | #include "../codecs/adau1373.h" | ||
19 | |||
20 | static const struct snd_soc_dapm_widget bfin_eval_adau1373_dapm_widgets[] = { | ||
21 | SND_SOC_DAPM_LINE("Line In1", NULL), | ||
22 | SND_SOC_DAPM_LINE("Line In2", NULL), | ||
23 | SND_SOC_DAPM_LINE("Line In3", NULL), | ||
24 | SND_SOC_DAPM_LINE("Line In4", NULL), | ||
25 | |||
26 | SND_SOC_DAPM_LINE("Line Out1", NULL), | ||
27 | SND_SOC_DAPM_LINE("Line Out2", NULL), | ||
28 | SND_SOC_DAPM_LINE("Stereo Out", NULL), | ||
29 | SND_SOC_DAPM_HP("Headphone", NULL), | ||
30 | SND_SOC_DAPM_HP("Earpiece", NULL), | ||
31 | SND_SOC_DAPM_SPK("Speaker", NULL), | ||
32 | }; | ||
33 | |||
34 | static const struct snd_soc_dapm_route bfin_eval_adau1373_dapm_routes[] = { | ||
35 | { "AIN1L", NULL, "Line In1" }, | ||
36 | { "AIN1R", NULL, "Line In1" }, | ||
37 | { "AIN2L", NULL, "Line In2" }, | ||
38 | { "AIN2R", NULL, "Line In2" }, | ||
39 | { "AIN3L", NULL, "Line In3" }, | ||
40 | { "AIN3R", NULL, "Line In3" }, | ||
41 | { "AIN4L", NULL, "Line In4" }, | ||
42 | { "AIN4R", NULL, "Line In4" }, | ||
43 | |||
44 | /* MICBIAS can be connected via a jumper to the line-in jack, since w | ||
45 | don't know which one is going to be used, just power both. */ | ||
46 | { "Line In1", NULL, "MICBIAS1" }, | ||
47 | { "Line In2", NULL, "MICBIAS1" }, | ||
48 | { "Line In3", NULL, "MICBIAS1" }, | ||
49 | { "Line In4", NULL, "MICBIAS1" }, | ||
50 | { "Line In1", NULL, "MICBIAS2" }, | ||
51 | { "Line In2", NULL, "MICBIAS2" }, | ||
52 | { "Line In3", NULL, "MICBIAS2" }, | ||
53 | { "Line In4", NULL, "MICBIAS2" }, | ||
54 | |||
55 | { "Line Out1", NULL, "LOUT1L" }, | ||
56 | { "Line Out1", NULL, "LOUT1R" }, | ||
57 | { "Line Out2", NULL, "LOUT2L" }, | ||
58 | { "Line Out2", NULL, "LOUT2R" }, | ||
59 | { "Headphone", NULL, "HPL" }, | ||
60 | { "Headphone", NULL, "HPR" }, | ||
61 | { "Earpiece", NULL, "EP" }, | ||
62 | { "Speaker", NULL, "SPKL" }, | ||
63 | { "Stereo Out", NULL, "SPKR" }, | ||
64 | }; | ||
65 | |||
66 | static int bfin_eval_adau1373_hw_params(struct snd_pcm_substream *substream, | ||
67 | struct snd_pcm_hw_params *params) | ||
68 | { | ||
69 | struct snd_soc_pcm_runtime *rtd = substream->private_data; | ||
70 | struct snd_soc_dai *cpu_dai = rtd->cpu_dai; | ||
71 | struct snd_soc_dai *codec_dai = rtd->codec_dai; | ||
72 | int ret; | ||
73 | int pll_rate; | ||
74 | |||
75 | ret = snd_soc_dai_set_fmt(cpu_dai, SND_SOC_DAIFMT_I2S | | ||
76 | SND_SOC_DAIFMT_NB_NF | SND_SOC_DAIFMT_CBM_CFM); | ||
77 | if (ret) | ||
78 | return ret; | ||
79 | |||
80 | ret = snd_soc_dai_set_fmt(codec_dai, SND_SOC_DAIFMT_I2S | | ||
81 | SND_SOC_DAIFMT_NB_NF | SND_SOC_DAIFMT_CBM_CFM); | ||
82 | if (ret) | ||
83 | return ret; | ||
84 | |||
85 | switch (params_rate(params)) { | ||
86 | case 48000: | ||
87 | case 8000: | ||
88 | case 12000: | ||
89 | case 16000: | ||
90 | case 24000: | ||
91 | case 32000: | ||
92 | pll_rate = 48000 * 1024; | ||
93 | break; | ||
94 | case 44100: | ||
95 | case 7350: | ||
96 | case 11025: | ||
97 | case 14700: | ||
98 | case 22050: | ||
99 | case 29400: | ||
100 | pll_rate = 44100 * 1024; | ||
101 | break; | ||
102 | default: | ||
103 | return -EINVAL; | ||
104 | } | ||
105 | |||
106 | ret = snd_soc_dai_set_pll(codec_dai, ADAU1373_PLL1, | ||
107 | ADAU1373_PLL_SRC_MCLK1, 12288000, pll_rate); | ||
108 | if (ret) | ||
109 | return ret; | ||
110 | |||
111 | ret = snd_soc_dai_set_sysclk(codec_dai, ADAU1373_CLK_SRC_PLL1, pll_rate, | ||
112 | SND_SOC_CLOCK_IN); | ||
113 | |||
114 | return ret; | ||
115 | } | ||
116 | |||
117 | static int bfin_eval_adau1373_codec_init(struct snd_soc_pcm_runtime *rtd) | ||
118 | { | ||
119 | struct snd_soc_dai *codec_dai = rtd->codec_dai; | ||
120 | unsigned int pll_rate = 48000 * 1024; | ||
121 | int ret; | ||
122 | |||
123 | ret = snd_soc_dai_set_pll(codec_dai, ADAU1373_PLL1, | ||
124 | ADAU1373_PLL_SRC_MCLK1, 12288000, pll_rate); | ||
125 | if (ret) | ||
126 | return ret; | ||
127 | |||
128 | ret = snd_soc_dai_set_sysclk(codec_dai, ADAU1373_CLK_SRC_PLL1, pll_rate, | ||
129 | SND_SOC_CLOCK_IN); | ||
130 | |||
131 | return ret; | ||
132 | } | ||
133 | static struct snd_soc_ops bfin_eval_adau1373_ops = { | ||
134 | .hw_params = bfin_eval_adau1373_hw_params, | ||
135 | }; | ||
136 | |||
137 | static struct snd_soc_dai_link bfin_eval_adau1373_dai = { | ||
138 | .name = "adau1373", | ||
139 | .stream_name = "adau1373", | ||
140 | .cpu_dai_name = "bfin-i2s.0", | ||
141 | .codec_dai_name = "adau1373-aif1", | ||
142 | .platform_name = "bfin-i2s-pcm-audio", | ||
143 | .codec_name = "adau1373.0-001a", | ||
144 | .ops = &bfin_eval_adau1373_ops, | ||
145 | .init = bfin_eval_adau1373_codec_init, | ||
146 | }; | ||
147 | |||
148 | static struct snd_soc_card bfin_eval_adau1373 = { | ||
149 | .name = "bfin-eval-adau1373", | ||
150 | .dai_link = &bfin_eval_adau1373_dai, | ||
151 | .num_links = 1, | ||
152 | |||
153 | .dapm_widgets = bfin_eval_adau1373_dapm_widgets, | ||
154 | .num_dapm_widgets = ARRAY_SIZE(bfin_eval_adau1373_dapm_widgets), | ||
155 | .dapm_routes = bfin_eval_adau1373_dapm_routes, | ||
156 | .num_dapm_routes = ARRAY_SIZE(bfin_eval_adau1373_dapm_routes), | ||
157 | }; | ||
158 | |||
159 | static int bfin_eval_adau1373_probe(struct platform_device *pdev) | ||
160 | { | ||
161 | struct snd_soc_card *card = &bfin_eval_adau1373; | ||
162 | |||
163 | card->dev = &pdev->dev; | ||
164 | |||
165 | return snd_soc_register_card(&bfin_eval_adau1373); | ||
166 | } | ||
167 | |||
168 | static int __devexit bfin_eval_adau1373_remove(struct platform_device *pdev) | ||
169 | { | ||
170 | struct snd_soc_card *card = platform_get_drvdata(pdev); | ||
171 | |||
172 | snd_soc_unregister_card(card); | ||
173 | |||
174 | return 0; | ||
175 | } | ||
176 | |||
177 | static struct platform_driver bfin_eval_adau1373_driver = { | ||
178 | .driver = { | ||
179 | .name = "bfin-eval-adau1373", | ||
180 | .owner = THIS_MODULE, | ||
181 | .pm = &snd_soc_pm_ops, | ||
182 | }, | ||
183 | .probe = bfin_eval_adau1373_probe, | ||
184 | .remove = __devexit_p(bfin_eval_adau1373_remove), | ||
185 | }; | ||
186 | |||
187 | static int __init bfin_eval_adau1373_init(void) | ||
188 | { | ||
189 | return platform_driver_register(&bfin_eval_adau1373_driver); | ||
190 | } | ||
191 | module_init(bfin_eval_adau1373_init); | ||
192 | |||
193 | static void __exit bfin_eval_adau1373_exit(void) | ||
194 | { | ||
195 | platform_driver_unregister(&bfin_eval_adau1373_driver); | ||
196 | } | ||
197 | module_exit(bfin_eval_adau1373_exit); | ||
198 | |||
199 | MODULE_AUTHOR("Lars-Peter Clausen <lars@metafoo.de>"); | ||
200 | MODULE_DESCRIPTION("ALSA SoC bfin adau1373 driver"); | ||
201 | MODULE_LICENSE("GPL"); | ||
202 | MODULE_ALIAS("platform:bfin-eval-adau1373"); | ||
diff --git a/sound/soc/codecs/Kconfig b/sound/soc/codecs/Kconfig index 665d9240c4ae..71b46c8f70d7 100644 --- a/sound/soc/codecs/Kconfig +++ b/sound/soc/codecs/Kconfig | |||
@@ -17,6 +17,7 @@ config SND_SOC_ALL_CODECS | |||
17 | select SND_SOC_AD193X if SND_SOC_I2C_AND_SPI | 17 | select SND_SOC_AD193X if SND_SOC_I2C_AND_SPI |
18 | select SND_SOC_AD1980 if SND_SOC_AC97_BUS | 18 | select SND_SOC_AD1980 if SND_SOC_AC97_BUS |
19 | select SND_SOC_AD73311 | 19 | select SND_SOC_AD73311 |
20 | select SND_SOC_ADAU1373 if I2C | ||
20 | select SND_SOC_ADAV80X | 21 | select SND_SOC_ADAV80X |
21 | select SND_SOC_ADS117X | 22 | select SND_SOC_ADS117X |
22 | select SND_SOC_AK4104 if SPI_MASTER | 23 | select SND_SOC_AK4104 if SPI_MASTER |
@@ -139,6 +140,9 @@ config SND_SOC_ADAU1701 | |||
139 | select SIGMA | 140 | select SIGMA |
140 | tristate | 141 | tristate |
141 | 142 | ||
143 | config SND_SOC_ADAU1373 | ||
144 | tristate | ||
145 | |||
142 | config SND_SOC_ADAV80X | 146 | config SND_SOC_ADAV80X |
143 | tristate | 147 | tristate |
144 | 148 | ||
diff --git a/sound/soc/codecs/Makefile b/sound/soc/codecs/Makefile index 5119a7e2c1a8..70c1769acd15 100644 --- a/sound/soc/codecs/Makefile +++ b/sound/soc/codecs/Makefile | |||
@@ -5,6 +5,7 @@ snd-soc-ad193x-objs := ad193x.o | |||
5 | snd-soc-ad1980-objs := ad1980.o | 5 | snd-soc-ad1980-objs := ad1980.o |
6 | snd-soc-ad73311-objs := ad73311.o | 6 | snd-soc-ad73311-objs := ad73311.o |
7 | snd-soc-adau1701-objs := adau1701.o | 7 | snd-soc-adau1701-objs := adau1701.o |
8 | snd-soc-adau1373-objs := adau1373.o | ||
8 | snd-soc-adav80x-objs := adav80x.o | 9 | snd-soc-adav80x-objs := adav80x.o |
9 | snd-soc-ads117x-objs := ads117x.o | 10 | snd-soc-ads117x-objs := ads117x.o |
10 | snd-soc-ak4104-objs := ak4104.o | 11 | snd-soc-ak4104-objs := ak4104.o |
@@ -100,6 +101,7 @@ obj-$(CONFIG_SND_SOC_AD1836) += snd-soc-ad1836.o | |||
100 | obj-$(CONFIG_SND_SOC_AD193X) += snd-soc-ad193x.o | 101 | obj-$(CONFIG_SND_SOC_AD193X) += snd-soc-ad193x.o |
101 | obj-$(CONFIG_SND_SOC_AD1980) += snd-soc-ad1980.o | 102 | obj-$(CONFIG_SND_SOC_AD1980) += snd-soc-ad1980.o |
102 | obj-$(CONFIG_SND_SOC_AD73311) += snd-soc-ad73311.o | 103 | obj-$(CONFIG_SND_SOC_AD73311) += snd-soc-ad73311.o |
104 | obj-$(CONFIG_SND_SOC_ADAU1373) += snd-soc-adau1373.o | ||
103 | obj-$(CONFIG_SND_SOC_ADAU1701) += snd-soc-adau1701.o | 105 | obj-$(CONFIG_SND_SOC_ADAU1701) += snd-soc-adau1701.o |
104 | obj-$(CONFIG_SND_SOC_ADAV80X) += snd-soc-adav80x.o | 106 | obj-$(CONFIG_SND_SOC_ADAV80X) += snd-soc-adav80x.o |
105 | obj-$(CONFIG_SND_SOC_ADS117X) += snd-soc-ads117x.o | 107 | obj-$(CONFIG_SND_SOC_ADS117X) += snd-soc-ads117x.o |
diff --git a/sound/soc/codecs/ad193x.c b/sound/soc/codecs/ad193x.c index eedb6f5e5823..f934670199a5 100644 --- a/sound/soc/codecs/ad193x.c +++ b/sound/soc/codecs/ad193x.c | |||
@@ -23,7 +23,7 @@ | |||
23 | 23 | ||
24 | /* codec private data */ | 24 | /* codec private data */ |
25 | struct ad193x_priv { | 25 | struct ad193x_priv { |
26 | enum snd_soc_control_type control_type; | 26 | struct regmap *regmap; |
27 | int sysclk; | 27 | int sysclk; |
28 | }; | 28 | }; |
29 | 29 | ||
@@ -349,10 +349,8 @@ static int ad193x_probe(struct snd_soc_codec *codec) | |||
349 | struct snd_soc_dapm_context *dapm = &codec->dapm; | 349 | struct snd_soc_dapm_context *dapm = &codec->dapm; |
350 | int ret; | 350 | int ret; |
351 | 351 | ||
352 | if (ad193x->control_type == SND_SOC_I2C) | 352 | codec->control_data = ad193x->regmap; |
353 | ret = snd_soc_codec_set_cache_io(codec, 8, 8, ad193x->control_type); | 353 | ret = snd_soc_codec_set_cache_io(codec, 0, 0, SND_SOC_REGMAP); |
354 | else | ||
355 | ret = snd_soc_codec_set_cache_io(codec, 16, 8, ad193x->control_type); | ||
356 | if (ret < 0) { | 354 | if (ret < 0) { |
357 | dev_err(codec->dev, "failed to set cache I/O: %d\n", ret); | 355 | dev_err(codec->dev, "failed to set cache I/O: %d\n", ret); |
358 | return ret; | 356 | return ret; |
@@ -388,6 +386,14 @@ static struct snd_soc_codec_driver soc_codec_dev_ad193x = { | |||
388 | }; | 386 | }; |
389 | 387 | ||
390 | #if defined(CONFIG_SPI_MASTER) | 388 | #if defined(CONFIG_SPI_MASTER) |
389 | |||
390 | static const struct regmap_config ad193x_spi_regmap_config = { | ||
391 | .val_bits = 8, | ||
392 | .reg_bits = 16, | ||
393 | .read_flag_mask = 0x09, | ||
394 | .write_flag_mask = 0x08, | ||
395 | }; | ||
396 | |||
391 | static int __devinit ad193x_spi_probe(struct spi_device *spi) | 397 | static int __devinit ad193x_spi_probe(struct spi_device *spi) |
392 | { | 398 | { |
393 | struct ad193x_priv *ad193x; | 399 | struct ad193x_priv *ad193x; |
@@ -397,20 +403,36 @@ static int __devinit ad193x_spi_probe(struct spi_device *spi) | |||
397 | if (ad193x == NULL) | 403 | if (ad193x == NULL) |
398 | return -ENOMEM; | 404 | return -ENOMEM; |
399 | 405 | ||
406 | ad193x->regmap = regmap_init_spi(spi, &ad193x_spi_regmap_config); | ||
407 | if (IS_ERR(ad193x->regmap)) { | ||
408 | ret = PTR_ERR(ad193x->regmap); | ||
409 | goto err_free; | ||
410 | } | ||
411 | |||
400 | spi_set_drvdata(spi, ad193x); | 412 | spi_set_drvdata(spi, ad193x); |
401 | ad193x->control_type = SND_SOC_SPI; | ||
402 | 413 | ||
403 | ret = snd_soc_register_codec(&spi->dev, | 414 | ret = snd_soc_register_codec(&spi->dev, |
404 | &soc_codec_dev_ad193x, &ad193x_dai, 1); | 415 | &soc_codec_dev_ad193x, &ad193x_dai, 1); |
405 | if (ret < 0) | 416 | if (ret < 0) |
406 | kfree(ad193x); | 417 | goto err_regmap_exit; |
418 | |||
419 | return 0; | ||
420 | |||
421 | err_regmap_exit: | ||
422 | regmap_exit(ad193x->regmap); | ||
423 | err_free: | ||
424 | kfree(ad193x); | ||
425 | |||
407 | return ret; | 426 | return ret; |
408 | } | 427 | } |
409 | 428 | ||
410 | static int __devexit ad193x_spi_remove(struct spi_device *spi) | 429 | static int __devexit ad193x_spi_remove(struct spi_device *spi) |
411 | { | 430 | { |
431 | struct ad193x_priv *ad193x = spi_get_drvdata(spi); | ||
432 | |||
412 | snd_soc_unregister_codec(&spi->dev); | 433 | snd_soc_unregister_codec(&spi->dev); |
413 | kfree(spi_get_drvdata(spi)); | 434 | regmap_exit(ad193x->regmap); |
435 | kfree(ad193x); | ||
414 | return 0; | 436 | return 0; |
415 | } | 437 | } |
416 | 438 | ||
@@ -425,6 +447,12 @@ static struct spi_driver ad193x_spi_driver = { | |||
425 | #endif | 447 | #endif |
426 | 448 | ||
427 | #if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE) | 449 | #if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE) |
450 | |||
451 | static const struct regmap_config ad193x_i2c_regmap_config = { | ||
452 | .val_bits = 8, | ||
453 | .reg_bits = 8, | ||
454 | }; | ||
455 | |||
428 | static const struct i2c_device_id ad193x_id[] = { | 456 | static const struct i2c_device_id ad193x_id[] = { |
429 | { "ad1936", 0 }, | 457 | { "ad1936", 0 }, |
430 | { "ad1937", 0 }, | 458 | { "ad1937", 0 }, |
@@ -442,20 +470,35 @@ static int __devinit ad193x_i2c_probe(struct i2c_client *client, | |||
442 | if (ad193x == NULL) | 470 | if (ad193x == NULL) |
443 | return -ENOMEM; | 471 | return -ENOMEM; |
444 | 472 | ||
473 | ad193x->regmap = regmap_init_i2c(client, &ad193x_i2c_regmap_config); | ||
474 | if (IS_ERR(ad193x->regmap)) { | ||
475 | ret = PTR_ERR(ad193x->regmap); | ||
476 | goto err_free; | ||
477 | } | ||
478 | |||
445 | i2c_set_clientdata(client, ad193x); | 479 | i2c_set_clientdata(client, ad193x); |
446 | ad193x->control_type = SND_SOC_I2C; | ||
447 | 480 | ||
448 | ret = snd_soc_register_codec(&client->dev, | 481 | ret = snd_soc_register_codec(&client->dev, |
449 | &soc_codec_dev_ad193x, &ad193x_dai, 1); | 482 | &soc_codec_dev_ad193x, &ad193x_dai, 1); |
450 | if (ret < 0) | 483 | if (ret < 0) |
451 | kfree(ad193x); | 484 | goto err_regmap_exit; |
485 | |||
486 | return 0; | ||
487 | |||
488 | err_regmap_exit: | ||
489 | regmap_exit(ad193x->regmap); | ||
490 | err_free: | ||
491 | kfree(ad193x); | ||
452 | return ret; | 492 | return ret; |
453 | } | 493 | } |
454 | 494 | ||
455 | static int __devexit ad193x_i2c_remove(struct i2c_client *client) | 495 | static int __devexit ad193x_i2c_remove(struct i2c_client *client) |
456 | { | 496 | { |
497 | struct ad193x_priv *ad193x = i2c_get_clientdata(client); | ||
498 | |||
457 | snd_soc_unregister_codec(&client->dev); | 499 | snd_soc_unregister_codec(&client->dev); |
458 | kfree(i2c_get_clientdata(client)); | 500 | regmap_exit(ad193x->regmap); |
501 | kfree(ad193x); | ||
459 | return 0; | 502 | return 0; |
460 | } | 503 | } |
461 | 504 | ||
diff --git a/sound/soc/codecs/ad193x.h b/sound/soc/codecs/ad193x.h index cccc2e8e5fbd..536e5f2b136e 100644 --- a/sound/soc/codecs/ad193x.h +++ b/sound/soc/codecs/ad193x.h | |||
@@ -9,20 +9,20 @@ | |||
9 | #ifndef __AD193X_H__ | 9 | #ifndef __AD193X_H__ |
10 | #define __AD193X_H__ | 10 | #define __AD193X_H__ |
11 | 11 | ||
12 | #define AD193X_PLL_CLK_CTRL0 0x800 | 12 | #define AD193X_PLL_CLK_CTRL0 0x00 |
13 | #define AD193X_PLL_POWERDOWN 0x01 | 13 | #define AD193X_PLL_POWERDOWN 0x01 |
14 | #define AD193X_PLL_INPUT_MASK (~0x6) | 14 | #define AD193X_PLL_INPUT_MASK (~0x6) |
15 | #define AD193X_PLL_INPUT_256 (0 << 1) | 15 | #define AD193X_PLL_INPUT_256 (0 << 1) |
16 | #define AD193X_PLL_INPUT_384 (1 << 1) | 16 | #define AD193X_PLL_INPUT_384 (1 << 1) |
17 | #define AD193X_PLL_INPUT_512 (2 << 1) | 17 | #define AD193X_PLL_INPUT_512 (2 << 1) |
18 | #define AD193X_PLL_INPUT_768 (3 << 1) | 18 | #define AD193X_PLL_INPUT_768 (3 << 1) |
19 | #define AD193X_PLL_CLK_CTRL1 0x801 | 19 | #define AD193X_PLL_CLK_CTRL1 0x01 |
20 | #define AD193X_DAC_CTRL0 0x802 | 20 | #define AD193X_DAC_CTRL0 0x02 |
21 | #define AD193X_DAC_POWERDOWN 0x01 | 21 | #define AD193X_DAC_POWERDOWN 0x01 |
22 | #define AD193X_DAC_SERFMT_MASK 0xC0 | 22 | #define AD193X_DAC_SERFMT_MASK 0xC0 |
23 | #define AD193X_DAC_SERFMT_STEREO (0 << 6) | 23 | #define AD193X_DAC_SERFMT_STEREO (0 << 6) |
24 | #define AD193X_DAC_SERFMT_TDM (1 << 6) | 24 | #define AD193X_DAC_SERFMT_TDM (1 << 6) |
25 | #define AD193X_DAC_CTRL1 0x803 | 25 | #define AD193X_DAC_CTRL1 0x03 |
26 | #define AD193X_DAC_2_CHANNELS 0 | 26 | #define AD193X_DAC_2_CHANNELS 0 |
27 | #define AD193X_DAC_4_CHANNELS 1 | 27 | #define AD193X_DAC_4_CHANNELS 1 |
28 | #define AD193X_DAC_8_CHANNELS 2 | 28 | #define AD193X_DAC_8_CHANNELS 2 |
@@ -33,11 +33,11 @@ | |||
33 | #define AD193X_DAC_BCLK_MASTER (1 << 5) | 33 | #define AD193X_DAC_BCLK_MASTER (1 << 5) |
34 | #define AD193X_DAC_LEFT_HIGH (1 << 3) | 34 | #define AD193X_DAC_LEFT_HIGH (1 << 3) |
35 | #define AD193X_DAC_BCLK_INV (1 << 7) | 35 | #define AD193X_DAC_BCLK_INV (1 << 7) |
36 | #define AD193X_DAC_CTRL2 0x804 | 36 | #define AD193X_DAC_CTRL2 0x04 |
37 | #define AD193X_DAC_WORD_LEN_SHFT 3 | 37 | #define AD193X_DAC_WORD_LEN_SHFT 3 |
38 | #define AD193X_DAC_WORD_LEN_MASK 0x18 | 38 | #define AD193X_DAC_WORD_LEN_MASK 0x18 |
39 | #define AD193X_DAC_MASTER_MUTE 1 | 39 | #define AD193X_DAC_MASTER_MUTE 1 |
40 | #define AD193X_DAC_CHNL_MUTE 0x805 | 40 | #define AD193X_DAC_CHNL_MUTE 0x05 |
41 | #define AD193X_DACL1_MUTE 0 | 41 | #define AD193X_DACL1_MUTE 0 |
42 | #define AD193X_DACR1_MUTE 1 | 42 | #define AD193X_DACR1_MUTE 1 |
43 | #define AD193X_DACL2_MUTE 2 | 43 | #define AD193X_DACL2_MUTE 2 |
@@ -46,28 +46,28 @@ | |||
46 | #define AD193X_DACR3_MUTE 5 | 46 | #define AD193X_DACR3_MUTE 5 |
47 | #define AD193X_DACL4_MUTE 6 | 47 | #define AD193X_DACL4_MUTE 6 |
48 | #define AD193X_DACR4_MUTE 7 | 48 | #define AD193X_DACR4_MUTE 7 |
49 | #define AD193X_DAC_L1_VOL 0x806 | 49 | #define AD193X_DAC_L1_VOL 0x06 |
50 | #define AD193X_DAC_R1_VOL 0x807 | 50 | #define AD193X_DAC_R1_VOL 0x07 |
51 | #define AD193X_DAC_L2_VOL 0x808 | 51 | #define AD193X_DAC_L2_VOL 0x08 |
52 | #define AD193X_DAC_R2_VOL 0x809 | 52 | #define AD193X_DAC_R2_VOL 0x09 |
53 | #define AD193X_DAC_L3_VOL 0x80a | 53 | #define AD193X_DAC_L3_VOL 0x0a |
54 | #define AD193X_DAC_R3_VOL 0x80b | 54 | #define AD193X_DAC_R3_VOL 0x0b |
55 | #define AD193X_DAC_L4_VOL 0x80c | 55 | #define AD193X_DAC_L4_VOL 0x0c |
56 | #define AD193X_DAC_R4_VOL 0x80d | 56 | #define AD193X_DAC_R4_VOL 0x0d |
57 | #define AD193X_ADC_CTRL0 0x80e | 57 | #define AD193X_ADC_CTRL0 0x0e |
58 | #define AD193X_ADC_POWERDOWN 0x01 | 58 | #define AD193X_ADC_POWERDOWN 0x01 |
59 | #define AD193X_ADC_HIGHPASS_FILTER 1 | 59 | #define AD193X_ADC_HIGHPASS_FILTER 1 |
60 | #define AD193X_ADCL1_MUTE 2 | 60 | #define AD193X_ADCL1_MUTE 2 |
61 | #define AD193X_ADCR1_MUTE 3 | 61 | #define AD193X_ADCR1_MUTE 3 |
62 | #define AD193X_ADCL2_MUTE 4 | 62 | #define AD193X_ADCL2_MUTE 4 |
63 | #define AD193X_ADCR2_MUTE 5 | 63 | #define AD193X_ADCR2_MUTE 5 |
64 | #define AD193X_ADC_CTRL1 0x80f | 64 | #define AD193X_ADC_CTRL1 0x0f |
65 | #define AD193X_ADC_SERFMT_MASK 0x60 | 65 | #define AD193X_ADC_SERFMT_MASK 0x60 |
66 | #define AD193X_ADC_SERFMT_STEREO (0 << 5) | 66 | #define AD193X_ADC_SERFMT_STEREO (0 << 5) |
67 | #define AD193X_ADC_SERFMT_TDM (1 << 5) | 67 | #define AD193X_ADC_SERFMT_TDM (1 << 5) |
68 | #define AD193X_ADC_SERFMT_AUX (2 << 5) | 68 | #define AD193X_ADC_SERFMT_AUX (2 << 5) |
69 | #define AD193X_ADC_WORD_LEN_MASK 0x3 | 69 | #define AD193X_ADC_WORD_LEN_MASK 0x3 |
70 | #define AD193X_ADC_CTRL2 0x810 | 70 | #define AD193X_ADC_CTRL2 0x10 |
71 | #define AD193X_ADC_2_CHANNELS 0 | 71 | #define AD193X_ADC_2_CHANNELS 0 |
72 | #define AD193X_ADC_4_CHANNELS 1 | 72 | #define AD193X_ADC_4_CHANNELS 1 |
73 | #define AD193X_ADC_8_CHANNELS 2 | 73 | #define AD193X_ADC_8_CHANNELS 2 |
diff --git a/sound/soc/codecs/ad1980.c b/sound/soc/codecs/ad1980.c index 923b364a3e41..4c0fc30a4ccb 100644 --- a/sound/soc/codecs/ad1980.c +++ b/sound/soc/codecs/ad1980.c | |||
@@ -200,18 +200,22 @@ static int ad1980_soc_probe(struct snd_soc_codec *codec) | |||
200 | } | 200 | } |
201 | 201 | ||
202 | /* Read out vendor ID to make sure it is ad1980 */ | 202 | /* Read out vendor ID to make sure it is ad1980 */ |
203 | if (ac97_read(codec, AC97_VENDOR_ID1) != 0x4144) | 203 | if (ac97_read(codec, AC97_VENDOR_ID1) != 0x4144) { |
204 | ret = -ENODEV; | ||
204 | goto reset_err; | 205 | goto reset_err; |
206 | } | ||
205 | 207 | ||
206 | vendor_id2 = ac97_read(codec, AC97_VENDOR_ID2); | 208 | vendor_id2 = ac97_read(codec, AC97_VENDOR_ID2); |
207 | 209 | ||
208 | if (vendor_id2 != 0x5370) { | 210 | if (vendor_id2 != 0x5370) { |
209 | if (vendor_id2 != 0x5374) | 211 | if (vendor_id2 != 0x5374) { |
212 | ret = -ENODEV; | ||
210 | goto reset_err; | 213 | goto reset_err; |
211 | else | 214 | } else { |
212 | printk(KERN_WARNING "ad1980: " | 215 | printk(KERN_WARNING "ad1980: " |
213 | "Found AD1981 - only 2/2 IN/OUT Channels " | 216 | "Found AD1981 - only 2/2 IN/OUT Channels " |
214 | "supported\n"); | 217 | "supported\n"); |
218 | } | ||
215 | } | 219 | } |
216 | 220 | ||
217 | /* unmute captures and playbacks volume */ | 221 | /* unmute captures and playbacks volume */ |
diff --git a/sound/soc/codecs/adau1373.c b/sound/soc/codecs/adau1373.c new file mode 100644 index 000000000000..2aa40c3731d0 --- /dev/null +++ b/sound/soc/codecs/adau1373.c | |||
@@ -0,0 +1,1414 @@ | |||
1 | /* | ||
2 | * Analog Devices ADAU1373 Audio Codec drive | ||
3 | * | ||
4 | * Copyright 2011 Analog Devices Inc. | ||
5 | * Author: Lars-Peter Clausen <lars@metafoo.de> | ||
6 | * | ||
7 | * Licensed under the GPL-2 or later. | ||
8 | */ | ||
9 | |||
10 | #include <linux/module.h> | ||
11 | #include <linux/init.h> | ||
12 | #include <linux/delay.h> | ||
13 | #include <linux/pm.h> | ||
14 | #include <linux/i2c.h> | ||
15 | #include <linux/slab.h> | ||
16 | #include <linux/gcd.h> | ||
17 | |||
18 | #include <sound/core.h> | ||
19 | #include <sound/pcm.h> | ||
20 | #include <sound/pcm_params.h> | ||
21 | #include <sound/tlv.h> | ||
22 | #include <sound/soc.h> | ||
23 | #include <sound/adau1373.h> | ||
24 | |||
25 | #include "adau1373.h" | ||
26 | |||
27 | struct adau1373_dai { | ||
28 | unsigned int clk_src; | ||
29 | unsigned int sysclk; | ||
30 | bool enable_src; | ||
31 | bool master; | ||
32 | }; | ||
33 | |||
34 | struct adau1373 { | ||
35 | struct adau1373_dai dais[3]; | ||
36 | }; | ||
37 | |||
38 | #define ADAU1373_INPUT_MODE 0x00 | ||
39 | #define ADAU1373_AINL_CTRL(x) (0x01 + (x) * 2) | ||
40 | #define ADAU1373_AINR_CTRL(x) (0x02 + (x) * 2) | ||
41 | #define ADAU1373_LLINE_OUT(x) (0x9 + (x) * 2) | ||
42 | #define ADAU1373_RLINE_OUT(x) (0xa + (x) * 2) | ||
43 | #define ADAU1373_LSPK_OUT 0x0d | ||
44 | #define ADAU1373_RSPK_OUT 0x0e | ||
45 | #define ADAU1373_LHP_OUT 0x0f | ||
46 | #define ADAU1373_RHP_OUT 0x10 | ||
47 | #define ADAU1373_ADC_GAIN 0x11 | ||
48 | #define ADAU1373_LADC_MIXER 0x12 | ||
49 | #define ADAU1373_RADC_MIXER 0x13 | ||
50 | #define ADAU1373_LLINE1_MIX 0x14 | ||
51 | #define ADAU1373_RLINE1_MIX 0x15 | ||
52 | #define ADAU1373_LLINE2_MIX 0x16 | ||
53 | #define ADAU1373_RLINE2_MIX 0x17 | ||
54 | #define ADAU1373_LSPK_MIX 0x18 | ||
55 | #define ADAU1373_RSPK_MIX 0x19 | ||
56 | #define ADAU1373_LHP_MIX 0x1a | ||
57 | #define ADAU1373_RHP_MIX 0x1b | ||
58 | #define ADAU1373_EP_MIX 0x1c | ||
59 | #define ADAU1373_HP_CTRL 0x1d | ||
60 | #define ADAU1373_HP_CTRL2 0x1e | ||
61 | #define ADAU1373_LS_CTRL 0x1f | ||
62 | #define ADAU1373_EP_CTRL 0x21 | ||
63 | #define ADAU1373_MICBIAS_CTRL1 0x22 | ||
64 | #define ADAU1373_MICBIAS_CTRL2 0x23 | ||
65 | #define ADAU1373_OUTPUT_CTRL 0x24 | ||
66 | #define ADAU1373_PWDN_CTRL1 0x25 | ||
67 | #define ADAU1373_PWDN_CTRL2 0x26 | ||
68 | #define ADAU1373_PWDN_CTRL3 0x27 | ||
69 | #define ADAU1373_DPLL_CTRL(x) (0x28 + (x) * 7) | ||
70 | #define ADAU1373_PLL_CTRL1(x) (0x29 + (x) * 7) | ||
71 | #define ADAU1373_PLL_CTRL2(x) (0x2a + (x) * 7) | ||
72 | #define ADAU1373_PLL_CTRL3(x) (0x2b + (x) * 7) | ||
73 | #define ADAU1373_PLL_CTRL4(x) (0x2c + (x) * 7) | ||
74 | #define ADAU1373_PLL_CTRL5(x) (0x2d + (x) * 7) | ||
75 | #define ADAU1373_PLL_CTRL6(x) (0x2e + (x) * 7) | ||
76 | #define ADAU1373_PLL_CTRL7(x) (0x2f + (x) * 7) | ||
77 | #define ADAU1373_HEADDECT 0x36 | ||
78 | #define ADAU1373_ADC_DAC_STATUS 0x37 | ||
79 | #define ADAU1373_ADC_CTRL 0x3c | ||
80 | #define ADAU1373_DAI(x) (0x44 + (x)) | ||
81 | #define ADAU1373_CLK_SRC_DIV(x) (0x40 + (x) * 2) | ||
82 | #define ADAU1373_BCLKDIV(x) (0x47 + (x)) | ||
83 | #define ADAU1373_SRC_RATIOA(x) (0x4a + (x) * 2) | ||
84 | #define ADAU1373_SRC_RATIOB(x) (0x4b + (x) * 2) | ||
85 | #define ADAU1373_DEEMP_CTRL 0x50 | ||
86 | #define ADAU1373_SRC_DAI_CTRL(x) (0x51 + (x)) | ||
87 | #define ADAU1373_DIN_MIX_CTRL(x) (0x56 + (x)) | ||
88 | #define ADAU1373_DOUT_MIX_CTRL(x) (0x5b + (x)) | ||
89 | #define ADAU1373_DAI_PBL_VOL(x) (0x62 + (x) * 2) | ||
90 | #define ADAU1373_DAI_PBR_VOL(x) (0x63 + (x) * 2) | ||
91 | #define ADAU1373_DAI_RECL_VOL(x) (0x68 + (x) * 2) | ||
92 | #define ADAU1373_DAI_RECR_VOL(x) (0x69 + (x) * 2) | ||
93 | #define ADAU1373_DAC1_PBL_VOL 0x6e | ||
94 | #define ADAU1373_DAC1_PBR_VOL 0x6f | ||
95 | #define ADAU1373_DAC2_PBL_VOL 0x70 | ||
96 | #define ADAU1373_DAC2_PBR_VOL 0x71 | ||
97 | #define ADAU1373_ADC_RECL_VOL 0x72 | ||
98 | #define ADAU1373_ADC_RECR_VOL 0x73 | ||
99 | #define ADAU1373_DMIC_RECL_VOL 0x74 | ||
100 | #define ADAU1373_DMIC_RECR_VOL 0x75 | ||
101 | #define ADAU1373_VOL_GAIN1 0x76 | ||
102 | #define ADAU1373_VOL_GAIN2 0x77 | ||
103 | #define ADAU1373_VOL_GAIN3 0x78 | ||
104 | #define ADAU1373_HPF_CTRL 0x7d | ||
105 | #define ADAU1373_BASS1 0x7e | ||
106 | #define ADAU1373_BASS2 0x7f | ||
107 | #define ADAU1373_DRC(x) (0x80 + (x) * 0x10) | ||
108 | #define ADAU1373_3D_CTRL1 0xc0 | ||
109 | #define ADAU1373_3D_CTRL2 0xc1 | ||
110 | #define ADAU1373_FDSP_SEL1 0xdc | ||
111 | #define ADAU1373_FDSP_SEL2 0xdd | ||
112 | #define ADAU1373_FDSP_SEL3 0xde | ||
113 | #define ADAU1373_FDSP_SEL4 0xdf | ||
114 | #define ADAU1373_DIGMICCTRL 0xe2 | ||
115 | #define ADAU1373_DIGEN 0xeb | ||
116 | #define ADAU1373_SOFT_RESET 0xff | ||
117 | |||
118 | |||
119 | #define ADAU1373_PLL_CTRL6_DPLL_BYPASS BIT(1) | ||
120 | #define ADAU1373_PLL_CTRL6_PLL_EN BIT(0) | ||
121 | |||
122 | #define ADAU1373_DAI_INVERT_BCLK BIT(7) | ||
123 | #define ADAU1373_DAI_MASTER BIT(6) | ||
124 | #define ADAU1373_DAI_INVERT_LRCLK BIT(4) | ||
125 | #define ADAU1373_DAI_WLEN_16 0x0 | ||
126 | #define ADAU1373_DAI_WLEN_20 0x4 | ||
127 | #define ADAU1373_DAI_WLEN_24 0x8 | ||
128 | #define ADAU1373_DAI_WLEN_32 0xc | ||
129 | #define ADAU1373_DAI_WLEN_MASK 0xc | ||
130 | #define ADAU1373_DAI_FORMAT_RIGHT_J 0x0 | ||
131 | #define ADAU1373_DAI_FORMAT_LEFT_J 0x1 | ||
132 | #define ADAU1373_DAI_FORMAT_I2S 0x2 | ||
133 | #define ADAU1373_DAI_FORMAT_DSP 0x3 | ||
134 | |||
135 | #define ADAU1373_BCLKDIV_SOURCE BIT(5) | ||
136 | #define ADAU1373_BCLKDIV_32 0x03 | ||
137 | #define ADAU1373_BCLKDIV_64 0x02 | ||
138 | #define ADAU1373_BCLKDIV_128 0x01 | ||
139 | #define ADAU1373_BCLKDIV_256 0x00 | ||
140 | |||
141 | #define ADAU1373_ADC_CTRL_PEAK_DETECT BIT(0) | ||
142 | #define ADAU1373_ADC_CTRL_RESET BIT(1) | ||
143 | #define ADAU1373_ADC_CTRL_RESET_FORCE BIT(2) | ||
144 | |||
145 | #define ADAU1373_OUTPUT_CTRL_LDIFF BIT(3) | ||
146 | #define ADAU1373_OUTPUT_CTRL_LNFBEN BIT(2) | ||
147 | |||
148 | #define ADAU1373_PWDN_CTRL3_PWR_EN BIT(0) | ||
149 | |||
150 | #define ADAU1373_EP_CTRL_MICBIAS1_OFFSET 4 | ||
151 | #define ADAU1373_EP_CTRL_MICBIAS2_OFFSET 2 | ||
152 | |||
153 | static const uint8_t adau1373_default_regs[] = { | ||
154 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x00 */ | ||
155 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, | ||
156 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x10 */ | ||
157 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, | ||
158 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x20 */ | ||
159 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, | ||
160 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, /* 0x30 */ | ||
161 | 0x00, 0x00, 0x00, 0x80, 0x00, 0x01, 0x00, 0x00, | ||
162 | 0x00, 0x00, 0x00, 0x00, 0x0a, 0x0a, 0x0a, 0x00, /* 0x40 */ | ||
163 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, | ||
164 | 0x00, 0x08, 0x08, 0x08, 0x00, 0x00, 0x00, 0x00, /* 0x50 */ | ||
165 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, | ||
166 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x60 */ | ||
167 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, | ||
168 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x70 */ | ||
169 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, | ||
170 | 0x78, 0x18, 0x00, 0x00, 0x00, 0xc0, 0x00, 0x00, /* 0x80 */ | ||
171 | 0x00, 0xc0, 0x88, 0x7a, 0xdf, 0x20, 0x00, 0x00, | ||
172 | 0x78, 0x18, 0x00, 0x00, 0x00, 0xc0, 0x00, 0x00, /* 0x90 */ | ||
173 | 0x00, 0xc0, 0x88, 0x7a, 0xdf, 0x20, 0x00, 0x00, | ||
174 | 0x78, 0x18, 0x00, 0x00, 0x00, 0xc0, 0x00, 0x00, /* 0xa0 */ | ||
175 | 0x00, 0xc0, 0x88, 0x7a, 0xdf, 0x20, 0x00, 0x00, | ||
176 | 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0xff, /* 0xb0 */ | ||
177 | 0xff, 0xff, 0xff, 0xff, 0xff, 0x1f, 0x00, 0x00, | ||
178 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xc0 */ | ||
179 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, | ||
180 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xd0 */ | ||
181 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, | ||
182 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, /* 0xe0 */ | ||
183 | 0x00, 0x1f, 0x0f, 0x00, 0x00, | ||
184 | }; | ||
185 | |||
186 | static const unsigned int adau1373_out_tlv[] = { | ||
187 | TLV_DB_RANGE_HEAD(4), | ||
188 | 0, 7, TLV_DB_SCALE_ITEM(-7900, 400, 1), | ||
189 | 8, 15, TLV_DB_SCALE_ITEM(-4700, 300, 0), | ||
190 | 16, 23, TLV_DB_SCALE_ITEM(-2300, 200, 0), | ||
191 | 24, 31, TLV_DB_SCALE_ITEM(-700, 100, 0), | ||
192 | }; | ||
193 | |||
194 | static const DECLARE_TLV_DB_MINMAX(adau1373_digital_tlv, -9563, 0); | ||
195 | static const DECLARE_TLV_DB_SCALE(adau1373_in_pga_tlv, -1300, 100, 1); | ||
196 | static const DECLARE_TLV_DB_SCALE(adau1373_ep_tlv, -600, 600, 1); | ||
197 | |||
198 | static const DECLARE_TLV_DB_SCALE(adau1373_input_boost_tlv, 0, 2000, 0); | ||
199 | static const DECLARE_TLV_DB_SCALE(adau1373_gain_boost_tlv, 0, 600, 0); | ||
200 | static const DECLARE_TLV_DB_SCALE(adau1373_speaker_boost_tlv, 1200, 600, 0); | ||
201 | |||
202 | static const char *adau1373_fdsp_sel_text[] = { | ||
203 | "None", | ||
204 | "Channel 1", | ||
205 | "Channel 2", | ||
206 | "Channel 3", | ||
207 | "Channel 4", | ||
208 | "Channel 5", | ||
209 | }; | ||
210 | |||
211 | static const SOC_ENUM_SINGLE_DECL(adau1373_drc1_channel_enum, | ||
212 | ADAU1373_FDSP_SEL1, 4, adau1373_fdsp_sel_text); | ||
213 | static const SOC_ENUM_SINGLE_DECL(adau1373_drc2_channel_enum, | ||
214 | ADAU1373_FDSP_SEL1, 0, adau1373_fdsp_sel_text); | ||
215 | static const SOC_ENUM_SINGLE_DECL(adau1373_drc3_channel_enum, | ||
216 | ADAU1373_FDSP_SEL2, 0, adau1373_fdsp_sel_text); | ||
217 | static const SOC_ENUM_SINGLE_DECL(adau1373_hpf_channel_enum, | ||
218 | ADAU1373_FDSP_SEL3, 0, adau1373_fdsp_sel_text); | ||
219 | static const SOC_ENUM_SINGLE_DECL(adau1373_bass_channel_enum, | ||
220 | ADAU1373_FDSP_SEL4, 4, adau1373_fdsp_sel_text); | ||
221 | |||
222 | static const char *adau1373_hpf_cutoff_text[] = { | ||
223 | "3.7Hz", "50Hz", "100Hz", "150Hz", "200Hz", "250Hz", "300Hz", "350Hz", | ||
224 | "400Hz", "450Hz", "500Hz", "550Hz", "600Hz", "650Hz", "700Hz", "750Hz", | ||
225 | "800Hz", | ||
226 | }; | ||
227 | |||
228 | static const SOC_ENUM_SINGLE_DECL(adau1373_hpf_cutoff_enum, | ||
229 | ADAU1373_HPF_CTRL, 3, adau1373_hpf_cutoff_text); | ||
230 | |||
231 | static const char *adau1373_bass_lpf_cutoff_text[] = { | ||
232 | "801Hz", "1001Hz", | ||
233 | }; | ||
234 | |||
235 | static const char *adau1373_bass_clip_level_text[] = { | ||
236 | "0.125", "0.250", "0.370", "0.500", "0.625", "0.750", "0.875", | ||
237 | }; | ||
238 | |||
239 | static const unsigned int adau1373_bass_clip_level_values[] = { | ||
240 | 1, 2, 3, 4, 5, 6, 7, | ||
241 | }; | ||
242 | |||
243 | static const char *adau1373_bass_hpf_cutoff_text[] = { | ||
244 | "158Hz", "232Hz", "347Hz", "520Hz", | ||
245 | }; | ||
246 | |||
247 | static const unsigned int adau1373_bass_tlv[] = { | ||
248 | TLV_DB_RANGE_HEAD(4), | ||
249 | 0, 2, TLV_DB_SCALE_ITEM(-600, 600, 1), | ||
250 | 3, 4, TLV_DB_SCALE_ITEM(950, 250, 0), | ||
251 | 5, 7, TLV_DB_SCALE_ITEM(1400, 150, 0), | ||
252 | }; | ||
253 | |||
254 | static const SOC_ENUM_SINGLE_DECL(adau1373_bass_lpf_cutoff_enum, | ||
255 | ADAU1373_BASS1, 5, adau1373_bass_lpf_cutoff_text); | ||
256 | |||
257 | static const SOC_VALUE_ENUM_SINGLE_DECL(adau1373_bass_clip_level_enum, | ||
258 | ADAU1373_BASS1, 2, 7, adau1373_bass_clip_level_text, | ||
259 | adau1373_bass_clip_level_values); | ||
260 | |||
261 | static const SOC_ENUM_SINGLE_DECL(adau1373_bass_hpf_cutoff_enum, | ||
262 | ADAU1373_BASS1, 0, adau1373_bass_hpf_cutoff_text); | ||
263 | |||
264 | static const char *adau1373_3d_level_text[] = { | ||
265 | "0%", "6.67%", "13.33%", "20%", "26.67%", "33.33%", | ||
266 | "40%", "46.67%", "53.33%", "60%", "66.67%", "73.33%", | ||
267 | "80%", "86.67", "99.33%", "100%" | ||
268 | }; | ||
269 | |||
270 | static const char *adau1373_3d_cutoff_text[] = { | ||
271 | "No 3D", "0.03125 fs", "0.04583 fs", "0.075 fs", "0.11458 fs", | ||
272 | "0.16875 fs", "0.27083 fs" | ||
273 | }; | ||
274 | |||
275 | static const SOC_ENUM_SINGLE_DECL(adau1373_3d_level_enum, | ||
276 | ADAU1373_3D_CTRL1, 4, adau1373_3d_level_text); | ||
277 | static const SOC_ENUM_SINGLE_DECL(adau1373_3d_cutoff_enum, | ||
278 | ADAU1373_3D_CTRL1, 0, adau1373_3d_cutoff_text); | ||
279 | |||
280 | static const unsigned int adau1373_3d_tlv[] = { | ||
281 | TLV_DB_RANGE_HEAD(2), | ||
282 | 0, 0, TLV_DB_SCALE_ITEM(0, 0, 0), | ||
283 | 1, 7, TLV_DB_LINEAR_ITEM(-1800, -120), | ||
284 | }; | ||
285 | |||
286 | static const char *adau1373_lr_mux_text[] = { | ||
287 | "Mute", | ||
288 | "Right Channel (L+R)", | ||
289 | "Left Channel (L+R)", | ||
290 | "Stereo", | ||
291 | }; | ||
292 | |||
293 | static const SOC_ENUM_SINGLE_DECL(adau1373_lineout1_lr_mux_enum, | ||
294 | ADAU1373_OUTPUT_CTRL, 4, adau1373_lr_mux_text); | ||
295 | static const SOC_ENUM_SINGLE_DECL(adau1373_lineout2_lr_mux_enum, | ||
296 | ADAU1373_OUTPUT_CTRL, 6, adau1373_lr_mux_text); | ||
297 | static const SOC_ENUM_SINGLE_DECL(adau1373_speaker_lr_mux_enum, | ||
298 | ADAU1373_LS_CTRL, 4, adau1373_lr_mux_text); | ||
299 | |||
300 | static const struct snd_kcontrol_new adau1373_controls[] = { | ||
301 | SOC_DOUBLE_R_TLV("AIF1 Capture Volume", ADAU1373_DAI_RECL_VOL(0), | ||
302 | ADAU1373_DAI_RECR_VOL(0), 0, 0xff, 1, adau1373_digital_tlv), | ||
303 | SOC_DOUBLE_R_TLV("AIF2 Capture Volume", ADAU1373_DAI_RECL_VOL(1), | ||
304 | ADAU1373_DAI_RECR_VOL(1), 0, 0xff, 1, adau1373_digital_tlv), | ||
305 | SOC_DOUBLE_R_TLV("AIF3 Capture Volume", ADAU1373_DAI_RECL_VOL(2), | ||
306 | ADAU1373_DAI_RECR_VOL(2), 0, 0xff, 1, adau1373_digital_tlv), | ||
307 | |||
308 | SOC_DOUBLE_R_TLV("ADC Capture Volume", ADAU1373_ADC_RECL_VOL, | ||
309 | ADAU1373_ADC_RECR_VOL, 0, 0xff, 1, adau1373_digital_tlv), | ||
310 | SOC_DOUBLE_R_TLV("DMIC Capture Volume", ADAU1373_DMIC_RECL_VOL, | ||
311 | ADAU1373_DMIC_RECR_VOL, 0, 0xff, 1, adau1373_digital_tlv), | ||
312 | |||
313 | SOC_DOUBLE_R_TLV("AIF1 Playback Volume", ADAU1373_DAI_PBL_VOL(0), | ||
314 | ADAU1373_DAI_PBR_VOL(0), 0, 0xff, 1, adau1373_digital_tlv), | ||
315 | SOC_DOUBLE_R_TLV("AIF2 Playback Volume", ADAU1373_DAI_PBL_VOL(1), | ||
316 | ADAU1373_DAI_PBR_VOL(1), 0, 0xff, 1, adau1373_digital_tlv), | ||
317 | SOC_DOUBLE_R_TLV("AIF3 Playback Volume", ADAU1373_DAI_PBL_VOL(2), | ||
318 | ADAU1373_DAI_PBR_VOL(2), 0, 0xff, 1, adau1373_digital_tlv), | ||
319 | |||
320 | SOC_DOUBLE_R_TLV("DAC1 Playback Volume", ADAU1373_DAC1_PBL_VOL, | ||
321 | ADAU1373_DAC1_PBR_VOL, 0, 0xff, 1, adau1373_digital_tlv), | ||
322 | SOC_DOUBLE_R_TLV("DAC2 Playback Volume", ADAU1373_DAC2_PBL_VOL, | ||
323 | ADAU1373_DAC2_PBR_VOL, 0, 0xff, 1, adau1373_digital_tlv), | ||
324 | |||
325 | SOC_DOUBLE_R_TLV("Lineout1 Playback Volume", ADAU1373_LLINE_OUT(0), | ||
326 | ADAU1373_RLINE_OUT(0), 0, 0x1f, 0, adau1373_out_tlv), | ||
327 | SOC_DOUBLE_R_TLV("Speaker Playback Volume", ADAU1373_LSPK_OUT, | ||
328 | ADAU1373_RSPK_OUT, 0, 0x1f, 0, adau1373_out_tlv), | ||
329 | SOC_DOUBLE_R_TLV("Headphone Playback Volume", ADAU1373_LHP_OUT, | ||
330 | ADAU1373_RHP_OUT, 0, 0x1f, 0, adau1373_out_tlv), | ||
331 | |||
332 | SOC_DOUBLE_R_TLV("Input 1 Capture Volume", ADAU1373_AINL_CTRL(0), | ||
333 | ADAU1373_AINR_CTRL(0), 0, 0x1f, 0, adau1373_in_pga_tlv), | ||
334 | SOC_DOUBLE_R_TLV("Input 2 Capture Volume", ADAU1373_AINL_CTRL(1), | ||
335 | ADAU1373_AINR_CTRL(1), 0, 0x1f, 0, adau1373_in_pga_tlv), | ||
336 | SOC_DOUBLE_R_TLV("Input 3 Capture Volume", ADAU1373_AINL_CTRL(2), | ||
337 | ADAU1373_AINR_CTRL(2), 0, 0x1f, 0, adau1373_in_pga_tlv), | ||
338 | SOC_DOUBLE_R_TLV("Input 4 Capture Volume", ADAU1373_AINL_CTRL(3), | ||
339 | ADAU1373_AINR_CTRL(3), 0, 0x1f, 0, adau1373_in_pga_tlv), | ||
340 | |||
341 | SOC_SINGLE_TLV("Earpiece Playback Volume", ADAU1373_EP_CTRL, 0, 3, 0, | ||
342 | adau1373_ep_tlv), | ||
343 | |||
344 | SOC_DOUBLE_TLV("AIF3 Boost Playback Volume", ADAU1373_VOL_GAIN1, 4, 5, | ||
345 | 1, 0, adau1373_gain_boost_tlv), | ||
346 | SOC_DOUBLE_TLV("AIF2 Boost Playback Volume", ADAU1373_VOL_GAIN1, 2, 3, | ||
347 | 1, 0, adau1373_gain_boost_tlv), | ||
348 | SOC_DOUBLE_TLV("AIF1 Boost Playback Volume", ADAU1373_VOL_GAIN1, 0, 1, | ||
349 | 1, 0, adau1373_gain_boost_tlv), | ||
350 | SOC_DOUBLE_TLV("AIF3 Boost Capture Volume", ADAU1373_VOL_GAIN2, 4, 5, | ||
351 | 1, 0, adau1373_gain_boost_tlv), | ||
352 | SOC_DOUBLE_TLV("AIF2 Boost Capture Volume", ADAU1373_VOL_GAIN2, 2, 3, | ||
353 | 1, 0, adau1373_gain_boost_tlv), | ||
354 | SOC_DOUBLE_TLV("AIF1 Boost Capture Volume", ADAU1373_VOL_GAIN2, 0, 1, | ||
355 | 1, 0, adau1373_gain_boost_tlv), | ||
356 | SOC_DOUBLE_TLV("DMIC Boost Capture Volume", ADAU1373_VOL_GAIN3, 6, 7, | ||
357 | 1, 0, adau1373_gain_boost_tlv), | ||
358 | SOC_DOUBLE_TLV("ADC Boost Capture Volume", ADAU1373_VOL_GAIN3, 4, 5, | ||
359 | 1, 0, adau1373_gain_boost_tlv), | ||
360 | SOC_DOUBLE_TLV("DAC2 Boost Playback Volume", ADAU1373_VOL_GAIN3, 2, 3, | ||
361 | 1, 0, adau1373_gain_boost_tlv), | ||
362 | SOC_DOUBLE_TLV("DAC1 Boost Playback Volume", ADAU1373_VOL_GAIN3, 0, 1, | ||
363 | 1, 0, adau1373_gain_boost_tlv), | ||
364 | |||
365 | SOC_DOUBLE_TLV("Input 1 Boost Capture Volume", ADAU1373_ADC_GAIN, 0, 4, | ||
366 | 1, 0, adau1373_input_boost_tlv), | ||
367 | SOC_DOUBLE_TLV("Input 2 Boost Capture Volume", ADAU1373_ADC_GAIN, 1, 5, | ||
368 | 1, 0, adau1373_input_boost_tlv), | ||
369 | SOC_DOUBLE_TLV("Input 3 Boost Capture Volume", ADAU1373_ADC_GAIN, 2, 6, | ||
370 | 1, 0, adau1373_input_boost_tlv), | ||
371 | SOC_DOUBLE_TLV("Input 4 Boost Capture Volume", ADAU1373_ADC_GAIN, 3, 7, | ||
372 | 1, 0, adau1373_input_boost_tlv), | ||
373 | |||
374 | SOC_DOUBLE_TLV("Speaker Boost Playback Volume", ADAU1373_LS_CTRL, 2, 3, | ||
375 | 1, 0, adau1373_speaker_boost_tlv), | ||
376 | |||
377 | SOC_ENUM("Lineout1 LR Mux", adau1373_lineout1_lr_mux_enum), | ||
378 | SOC_ENUM("Speaker LR Mux", adau1373_speaker_lr_mux_enum), | ||
379 | |||
380 | SOC_ENUM("HPF Cutoff", adau1373_hpf_cutoff_enum), | ||
381 | SOC_DOUBLE("HPF Switch", ADAU1373_HPF_CTRL, 1, 0, 1, 0), | ||
382 | SOC_ENUM("HPF Channel", adau1373_hpf_channel_enum), | ||
383 | |||
384 | SOC_ENUM("Bass HPF Cutoff", adau1373_bass_hpf_cutoff_enum), | ||
385 | SOC_VALUE_ENUM("Bass Clip Level Threshold", | ||
386 | adau1373_bass_clip_level_enum), | ||
387 | SOC_ENUM("Bass LPF Cutoff", adau1373_bass_lpf_cutoff_enum), | ||
388 | SOC_DOUBLE("Bass Playback Switch", ADAU1373_BASS2, 0, 1, 1, 0), | ||
389 | SOC_SINGLE_TLV("Bass Playback Volume", ADAU1373_BASS2, 2, 7, 0, | ||
390 | adau1373_bass_tlv), | ||
391 | SOC_ENUM("Bass Channel", adau1373_bass_channel_enum), | ||
392 | |||
393 | SOC_ENUM("3D Freq", adau1373_3d_cutoff_enum), | ||
394 | SOC_ENUM("3D Level", adau1373_3d_level_enum), | ||
395 | SOC_SINGLE("3D Playback Switch", ADAU1373_3D_CTRL2, 0, 1, 0), | ||
396 | SOC_SINGLE_TLV("3D Playback Volume", ADAU1373_3D_CTRL2, 2, 7, 0, | ||
397 | adau1373_3d_tlv), | ||
398 | SOC_ENUM("3D Channel", adau1373_bass_channel_enum), | ||
399 | |||
400 | SOC_SINGLE("Zero Cross Switch", ADAU1373_PWDN_CTRL3, 7, 1, 0), | ||
401 | }; | ||
402 | |||
403 | static const struct snd_kcontrol_new adau1373_lineout2_controls[] = { | ||
404 | SOC_DOUBLE_R_TLV("Lineout2 Playback Volume", ADAU1373_LLINE_OUT(1), | ||
405 | ADAU1373_RLINE_OUT(1), 0, 0x1f, 0, adau1373_out_tlv), | ||
406 | SOC_ENUM("Lineout2 LR Mux", adau1373_lineout2_lr_mux_enum), | ||
407 | }; | ||
408 | |||
409 | static const struct snd_kcontrol_new adau1373_drc_controls[] = { | ||
410 | SOC_ENUM("DRC1 Channel", adau1373_drc1_channel_enum), | ||
411 | SOC_ENUM("DRC2 Channel", adau1373_drc2_channel_enum), | ||
412 | SOC_ENUM("DRC3 Channel", adau1373_drc3_channel_enum), | ||
413 | }; | ||
414 | |||
415 | static int adau1373_pll_event(struct snd_soc_dapm_widget *w, | ||
416 | struct snd_kcontrol *kcontrol, int event) | ||
417 | { | ||
418 | struct snd_soc_codec *codec = w->codec; | ||
419 | unsigned int pll_id = w->name[3] - '1'; | ||
420 | unsigned int val; | ||
421 | |||
422 | if (SND_SOC_DAPM_EVENT_ON(event)) | ||
423 | val = ADAU1373_PLL_CTRL6_PLL_EN; | ||
424 | else | ||
425 | val = 0; | ||
426 | |||
427 | snd_soc_update_bits(codec, ADAU1373_PLL_CTRL6(pll_id), | ||
428 | ADAU1373_PLL_CTRL6_PLL_EN, val); | ||
429 | |||
430 | if (SND_SOC_DAPM_EVENT_ON(event)) | ||
431 | mdelay(5); | ||
432 | |||
433 | return 0; | ||
434 | } | ||
435 | |||
436 | static const char *adau1373_decimator_text[] = { | ||
437 | "ADC", | ||
438 | "DMIC1", | ||
439 | }; | ||
440 | |||
441 | static const struct soc_enum adau1373_decimator_enum = | ||
442 | SOC_ENUM_SINGLE(0, 0, 2, adau1373_decimator_text); | ||
443 | |||
444 | static const struct snd_kcontrol_new adau1373_decimator_mux = | ||
445 | SOC_DAPM_ENUM_VIRT("Decimator Mux", adau1373_decimator_enum); | ||
446 | |||
447 | static const struct snd_kcontrol_new adau1373_left_adc_mixer_controls[] = { | ||
448 | SOC_DAPM_SINGLE("DAC1 Switch", ADAU1373_LADC_MIXER, 4, 1, 0), | ||
449 | SOC_DAPM_SINGLE("Input 4 Switch", ADAU1373_LADC_MIXER, 3, 1, 0), | ||
450 | SOC_DAPM_SINGLE("Input 3 Switch", ADAU1373_LADC_MIXER, 2, 1, 0), | ||
451 | SOC_DAPM_SINGLE("Input 2 Switch", ADAU1373_LADC_MIXER, 1, 1, 0), | ||
452 | SOC_DAPM_SINGLE("Input 1 Switch", ADAU1373_LADC_MIXER, 0, 1, 0), | ||
453 | }; | ||
454 | |||
455 | static const struct snd_kcontrol_new adau1373_right_adc_mixer_controls[] = { | ||
456 | SOC_DAPM_SINGLE("DAC1 Switch", ADAU1373_RADC_MIXER, 4, 1, 0), | ||
457 | SOC_DAPM_SINGLE("Input 4 Switch", ADAU1373_RADC_MIXER, 3, 1, 0), | ||
458 | SOC_DAPM_SINGLE("Input 3 Switch", ADAU1373_RADC_MIXER, 2, 1, 0), | ||
459 | SOC_DAPM_SINGLE("Input 2 Switch", ADAU1373_RADC_MIXER, 1, 1, 0), | ||
460 | SOC_DAPM_SINGLE("Input 1 Switch", ADAU1373_RADC_MIXER, 0, 1, 0), | ||
461 | }; | ||
462 | |||
463 | #define DECLARE_ADAU1373_OUTPUT_MIXER_CTRLS(_name, _reg) \ | ||
464 | const struct snd_kcontrol_new _name[] = { \ | ||
465 | SOC_DAPM_SINGLE("Left DAC2 Switch", _reg, 7, 1, 0), \ | ||
466 | SOC_DAPM_SINGLE("Right DAC2 Switch", _reg, 6, 1, 0), \ | ||
467 | SOC_DAPM_SINGLE("Left DAC1 Switch", _reg, 5, 1, 0), \ | ||
468 | SOC_DAPM_SINGLE("Right DAC1 Switch", _reg, 4, 1, 0), \ | ||
469 | SOC_DAPM_SINGLE("Input 4 Bypass Switch", _reg, 3, 1, 0), \ | ||
470 | SOC_DAPM_SINGLE("Input 3 Bypass Switch", _reg, 2, 1, 0), \ | ||
471 | SOC_DAPM_SINGLE("Input 2 Bypass Switch", _reg, 1, 1, 0), \ | ||
472 | SOC_DAPM_SINGLE("Input 1 Bypass Switch", _reg, 0, 1, 0), \ | ||
473 | } | ||
474 | |||
475 | static DECLARE_ADAU1373_OUTPUT_MIXER_CTRLS(adau1373_left_line1_mixer_controls, | ||
476 | ADAU1373_LLINE1_MIX); | ||
477 | static DECLARE_ADAU1373_OUTPUT_MIXER_CTRLS(adau1373_right_line1_mixer_controls, | ||
478 | ADAU1373_RLINE1_MIX); | ||
479 | static DECLARE_ADAU1373_OUTPUT_MIXER_CTRLS(adau1373_left_line2_mixer_controls, | ||
480 | ADAU1373_LLINE2_MIX); | ||
481 | static DECLARE_ADAU1373_OUTPUT_MIXER_CTRLS(adau1373_right_line2_mixer_controls, | ||
482 | ADAU1373_RLINE2_MIX); | ||
483 | static DECLARE_ADAU1373_OUTPUT_MIXER_CTRLS(adau1373_left_spk_mixer_controls, | ||
484 | ADAU1373_LSPK_MIX); | ||
485 | static DECLARE_ADAU1373_OUTPUT_MIXER_CTRLS(adau1373_right_spk_mixer_controls, | ||
486 | ADAU1373_RSPK_MIX); | ||
487 | static DECLARE_ADAU1373_OUTPUT_MIXER_CTRLS(adau1373_ep_mixer_controls, | ||
488 | ADAU1373_EP_MIX); | ||
489 | |||
490 | static const struct snd_kcontrol_new adau1373_left_hp_mixer_controls[] = { | ||
491 | SOC_DAPM_SINGLE("Left DAC1 Switch", ADAU1373_LHP_MIX, 5, 1, 0), | ||
492 | SOC_DAPM_SINGLE("Left DAC2 Switch", ADAU1373_LHP_MIX, 4, 1, 0), | ||
493 | SOC_DAPM_SINGLE("Input 4 Bypass Switch", ADAU1373_LHP_MIX, 3, 1, 0), | ||
494 | SOC_DAPM_SINGLE("Input 3 Bypass Switch", ADAU1373_LHP_MIX, 2, 1, 0), | ||
495 | SOC_DAPM_SINGLE("Input 2 Bypass Switch", ADAU1373_LHP_MIX, 1, 1, 0), | ||
496 | SOC_DAPM_SINGLE("Input 1 Bypass Switch", ADAU1373_LHP_MIX, 0, 1, 0), | ||
497 | }; | ||
498 | |||
499 | static const struct snd_kcontrol_new adau1373_right_hp_mixer_controls[] = { | ||
500 | SOC_DAPM_SINGLE("Right DAC1 Switch", ADAU1373_RHP_MIX, 5, 1, 0), | ||
501 | SOC_DAPM_SINGLE("Right DAC2 Switch", ADAU1373_RHP_MIX, 4, 1, 0), | ||
502 | SOC_DAPM_SINGLE("Input 4 Bypass Switch", ADAU1373_RHP_MIX, 3, 1, 0), | ||
503 | SOC_DAPM_SINGLE("Input 3 Bypass Switch", ADAU1373_RHP_MIX, 2, 1, 0), | ||
504 | SOC_DAPM_SINGLE("Input 2 Bypass Switch", ADAU1373_RHP_MIX, 1, 1, 0), | ||
505 | SOC_DAPM_SINGLE("Input 1 Bypass Switch", ADAU1373_RHP_MIX, 0, 1, 0), | ||
506 | }; | ||
507 | |||
508 | #define DECLARE_ADAU1373_DSP_CHANNEL_MIXER_CTRLS(_name, _reg) \ | ||
509 | const struct snd_kcontrol_new _name[] = { \ | ||
510 | SOC_DAPM_SINGLE("DMIC2 Swapped Switch", _reg, 6, 1, 0), \ | ||
511 | SOC_DAPM_SINGLE("DMIC2 Switch", _reg, 5, 1, 0), \ | ||
512 | SOC_DAPM_SINGLE("ADC/DMIC1 Swapped Switch", _reg, 4, 1, 0), \ | ||
513 | SOC_DAPM_SINGLE("ADC/DMIC1 Switch", _reg, 3, 1, 0), \ | ||
514 | SOC_DAPM_SINGLE("AIF3 Switch", _reg, 2, 1, 0), \ | ||
515 | SOC_DAPM_SINGLE("AIF2 Switch", _reg, 1, 1, 0), \ | ||
516 | SOC_DAPM_SINGLE("AIF1 Switch", _reg, 0, 1, 0), \ | ||
517 | } | ||
518 | |||
519 | static DECLARE_ADAU1373_DSP_CHANNEL_MIXER_CTRLS(adau1373_dsp_channel1_mixer_controls, | ||
520 | ADAU1373_DIN_MIX_CTRL(0)); | ||
521 | static DECLARE_ADAU1373_DSP_CHANNEL_MIXER_CTRLS(adau1373_dsp_channel2_mixer_controls, | ||
522 | ADAU1373_DIN_MIX_CTRL(1)); | ||
523 | static DECLARE_ADAU1373_DSP_CHANNEL_MIXER_CTRLS(adau1373_dsp_channel3_mixer_controls, | ||
524 | ADAU1373_DIN_MIX_CTRL(2)); | ||
525 | static DECLARE_ADAU1373_DSP_CHANNEL_MIXER_CTRLS(adau1373_dsp_channel4_mixer_controls, | ||
526 | ADAU1373_DIN_MIX_CTRL(3)); | ||
527 | static DECLARE_ADAU1373_DSP_CHANNEL_MIXER_CTRLS(adau1373_dsp_channel5_mixer_controls, | ||
528 | ADAU1373_DIN_MIX_CTRL(4)); | ||
529 | |||
530 | #define DECLARE_ADAU1373_DSP_OUTPUT_MIXER_CTRLS(_name, _reg) \ | ||
531 | const struct snd_kcontrol_new _name[] = { \ | ||
532 | SOC_DAPM_SINGLE("DSP Channel5 Switch", _reg, 4, 1, 0), \ | ||
533 | SOC_DAPM_SINGLE("DSP Channel4 Switch", _reg, 3, 1, 0), \ | ||
534 | SOC_DAPM_SINGLE("DSP Channel3 Switch", _reg, 2, 1, 0), \ | ||
535 | SOC_DAPM_SINGLE("DSP Channel2 Switch", _reg, 1, 1, 0), \ | ||
536 | SOC_DAPM_SINGLE("DSP Channel1 Switch", _reg, 0, 1, 0), \ | ||
537 | } | ||
538 | |||
539 | static DECLARE_ADAU1373_DSP_OUTPUT_MIXER_CTRLS(adau1373_aif1_mixer_controls, | ||
540 | ADAU1373_DOUT_MIX_CTRL(0)); | ||
541 | static DECLARE_ADAU1373_DSP_OUTPUT_MIXER_CTRLS(adau1373_aif2_mixer_controls, | ||
542 | ADAU1373_DOUT_MIX_CTRL(1)); | ||
543 | static DECLARE_ADAU1373_DSP_OUTPUT_MIXER_CTRLS(adau1373_aif3_mixer_controls, | ||
544 | ADAU1373_DOUT_MIX_CTRL(2)); | ||
545 | static DECLARE_ADAU1373_DSP_OUTPUT_MIXER_CTRLS(adau1373_dac1_mixer_controls, | ||
546 | ADAU1373_DOUT_MIX_CTRL(3)); | ||
547 | static DECLARE_ADAU1373_DSP_OUTPUT_MIXER_CTRLS(adau1373_dac2_mixer_controls, | ||
548 | ADAU1373_DOUT_MIX_CTRL(4)); | ||
549 | |||
550 | static const struct snd_soc_dapm_widget adau1373_dapm_widgets[] = { | ||
551 | /* Datasheet claims Left ADC is bit 6 and Right ADC is bit 7, but that | ||
552 | * doesn't seem to be the case. */ | ||
553 | SND_SOC_DAPM_ADC("Left ADC", NULL, ADAU1373_PWDN_CTRL1, 7, 0), | ||
554 | SND_SOC_DAPM_ADC("Right ADC", NULL, ADAU1373_PWDN_CTRL1, 6, 0), | ||
555 | |||
556 | SND_SOC_DAPM_ADC("DMIC1", NULL, ADAU1373_DIGMICCTRL, 0, 0), | ||
557 | SND_SOC_DAPM_ADC("DMIC2", NULL, ADAU1373_DIGMICCTRL, 2, 0), | ||
558 | |||
559 | SND_SOC_DAPM_VIRT_MUX("Decimator Mux", SND_SOC_NOPM, 0, 0, | ||
560 | &adau1373_decimator_mux), | ||
561 | |||
562 | SND_SOC_DAPM_SUPPLY("MICBIAS2", ADAU1373_PWDN_CTRL1, 5, 0, NULL, 0), | ||
563 | SND_SOC_DAPM_SUPPLY("MICBIAS1", ADAU1373_PWDN_CTRL1, 4, 0, NULL, 0), | ||
564 | |||
565 | SND_SOC_DAPM_PGA("IN4PGA", ADAU1373_PWDN_CTRL1, 3, 0, NULL, 0), | ||
566 | SND_SOC_DAPM_PGA("IN3PGA", ADAU1373_PWDN_CTRL1, 2, 0, NULL, 0), | ||
567 | SND_SOC_DAPM_PGA("IN2PGA", ADAU1373_PWDN_CTRL1, 1, 0, NULL, 0), | ||
568 | SND_SOC_DAPM_PGA("IN1PGA", ADAU1373_PWDN_CTRL1, 0, 0, NULL, 0), | ||
569 | |||
570 | SND_SOC_DAPM_DAC("Left DAC2", NULL, ADAU1373_PWDN_CTRL2, 7, 0), | ||
571 | SND_SOC_DAPM_DAC("Right DAC2", NULL, ADAU1373_PWDN_CTRL2, 6, 0), | ||
572 | SND_SOC_DAPM_DAC("Left DAC1", NULL, ADAU1373_PWDN_CTRL2, 5, 0), | ||
573 | SND_SOC_DAPM_DAC("Right DAC1", NULL, ADAU1373_PWDN_CTRL2, 4, 0), | ||
574 | |||
575 | SOC_MIXER_ARRAY("Left ADC Mixer", SND_SOC_NOPM, 0, 0, | ||
576 | adau1373_left_adc_mixer_controls), | ||
577 | SOC_MIXER_ARRAY("Right ADC Mixer", SND_SOC_NOPM, 0, 0, | ||
578 | adau1373_right_adc_mixer_controls), | ||
579 | |||
580 | SOC_MIXER_ARRAY("Left Lineout2 Mixer", ADAU1373_PWDN_CTRL2, 3, 0, | ||
581 | adau1373_left_line2_mixer_controls), | ||
582 | SOC_MIXER_ARRAY("Right Lineout2 Mixer", ADAU1373_PWDN_CTRL2, 2, 0, | ||
583 | adau1373_right_line2_mixer_controls), | ||
584 | SOC_MIXER_ARRAY("Left Lineout1 Mixer", ADAU1373_PWDN_CTRL2, 1, 0, | ||
585 | adau1373_left_line1_mixer_controls), | ||
586 | SOC_MIXER_ARRAY("Right Lineout1 Mixer", ADAU1373_PWDN_CTRL2, 0, 0, | ||
587 | adau1373_right_line1_mixer_controls), | ||
588 | |||
589 | SOC_MIXER_ARRAY("Earpiece Mixer", ADAU1373_PWDN_CTRL3, 4, 0, | ||
590 | adau1373_ep_mixer_controls), | ||
591 | SOC_MIXER_ARRAY("Left Speaker Mixer", ADAU1373_PWDN_CTRL3, 3, 0, | ||
592 | adau1373_left_spk_mixer_controls), | ||
593 | SOC_MIXER_ARRAY("Right Speaker Mixer", ADAU1373_PWDN_CTRL3, 2, 0, | ||
594 | adau1373_right_spk_mixer_controls), | ||
595 | SOC_MIXER_ARRAY("Left Headphone Mixer", SND_SOC_NOPM, 0, 0, | ||
596 | adau1373_left_hp_mixer_controls), | ||
597 | SOC_MIXER_ARRAY("Right Headphone Mixer", SND_SOC_NOPM, 0, 0, | ||
598 | adau1373_right_hp_mixer_controls), | ||
599 | SND_SOC_DAPM_SUPPLY("Headphone Enable", ADAU1373_PWDN_CTRL3, 1, 0, | ||
600 | NULL, 0), | ||
601 | |||
602 | SND_SOC_DAPM_SUPPLY("AIF1 CLK", ADAU1373_SRC_DAI_CTRL(0), 0, 0, | ||
603 | NULL, 0), | ||
604 | SND_SOC_DAPM_SUPPLY("AIF2 CLK", ADAU1373_SRC_DAI_CTRL(1), 0, 0, | ||
605 | NULL, 0), | ||
606 | SND_SOC_DAPM_SUPPLY("AIF3 CLK", ADAU1373_SRC_DAI_CTRL(2), 0, 0, | ||
607 | NULL, 0), | ||
608 | SND_SOC_DAPM_SUPPLY("AIF1 IN SRC", ADAU1373_SRC_DAI_CTRL(0), 2, 0, | ||
609 | NULL, 0), | ||
610 | SND_SOC_DAPM_SUPPLY("AIF1 OUT SRC", ADAU1373_SRC_DAI_CTRL(0), 1, 0, | ||
611 | NULL, 0), | ||
612 | SND_SOC_DAPM_SUPPLY("AIF2 IN SRC", ADAU1373_SRC_DAI_CTRL(1), 2, 0, | ||
613 | NULL, 0), | ||
614 | SND_SOC_DAPM_SUPPLY("AIF2 OUT SRC", ADAU1373_SRC_DAI_CTRL(1), 1, 0, | ||
615 | NULL, 0), | ||
616 | SND_SOC_DAPM_SUPPLY("AIF3 IN SRC", ADAU1373_SRC_DAI_CTRL(2), 2, 0, | ||
617 | NULL, 0), | ||
618 | SND_SOC_DAPM_SUPPLY("AIF3 OUT SRC", ADAU1373_SRC_DAI_CTRL(2), 1, 0, | ||
619 | NULL, 0), | ||
620 | |||
621 | SND_SOC_DAPM_AIF_IN("AIF1 IN", "AIF1 Playback", 0, SND_SOC_NOPM, 0, 0), | ||
622 | SND_SOC_DAPM_AIF_OUT("AIF1 OUT", "AIF1 Capture", 0, SND_SOC_NOPM, 0, 0), | ||
623 | SND_SOC_DAPM_AIF_IN("AIF2 IN", "AIF2 Playback", 0, SND_SOC_NOPM, 0, 0), | ||
624 | SND_SOC_DAPM_AIF_OUT("AIF2 OUT", "AIF2 Capture", 0, SND_SOC_NOPM, 0, 0), | ||
625 | SND_SOC_DAPM_AIF_IN("AIF3 IN", "AIF3 Playback", 0, SND_SOC_NOPM, 0, 0), | ||
626 | SND_SOC_DAPM_AIF_OUT("AIF3 OUT", "AIF3 Capture", 0, SND_SOC_NOPM, 0, 0), | ||
627 | |||
628 | SOC_MIXER_ARRAY("DSP Channel1 Mixer", SND_SOC_NOPM, 0, 0, | ||
629 | adau1373_dsp_channel1_mixer_controls), | ||
630 | SOC_MIXER_ARRAY("DSP Channel2 Mixer", SND_SOC_NOPM, 0, 0, | ||
631 | adau1373_dsp_channel2_mixer_controls), | ||
632 | SOC_MIXER_ARRAY("DSP Channel3 Mixer", SND_SOC_NOPM, 0, 0, | ||
633 | adau1373_dsp_channel3_mixer_controls), | ||
634 | SOC_MIXER_ARRAY("DSP Channel4 Mixer", SND_SOC_NOPM, 0, 0, | ||
635 | adau1373_dsp_channel4_mixer_controls), | ||
636 | SOC_MIXER_ARRAY("DSP Channel5 Mixer", SND_SOC_NOPM, 0, 0, | ||
637 | adau1373_dsp_channel5_mixer_controls), | ||
638 | |||
639 | SOC_MIXER_ARRAY("AIF1 Mixer", SND_SOC_NOPM, 0, 0, | ||
640 | adau1373_aif1_mixer_controls), | ||
641 | SOC_MIXER_ARRAY("AIF2 Mixer", SND_SOC_NOPM, 0, 0, | ||
642 | adau1373_aif2_mixer_controls), | ||
643 | SOC_MIXER_ARRAY("AIF3 Mixer", SND_SOC_NOPM, 0, 0, | ||
644 | adau1373_aif3_mixer_controls), | ||
645 | SOC_MIXER_ARRAY("DAC1 Mixer", SND_SOC_NOPM, 0, 0, | ||
646 | adau1373_dac1_mixer_controls), | ||
647 | SOC_MIXER_ARRAY("DAC2 Mixer", SND_SOC_NOPM, 0, 0, | ||
648 | adau1373_dac2_mixer_controls), | ||
649 | |||
650 | SND_SOC_DAPM_SUPPLY("DSP", ADAU1373_DIGEN, 4, 0, NULL, 0), | ||
651 | SND_SOC_DAPM_SUPPLY("Recording Engine B", ADAU1373_DIGEN, 3, 0, NULL, 0), | ||
652 | SND_SOC_DAPM_SUPPLY("Recording Engine A", ADAU1373_DIGEN, 2, 0, NULL, 0), | ||
653 | SND_SOC_DAPM_SUPPLY("Playback Engine B", ADAU1373_DIGEN, 1, 0, NULL, 0), | ||
654 | SND_SOC_DAPM_SUPPLY("Playback Engine A", ADAU1373_DIGEN, 0, 0, NULL, 0), | ||
655 | |||
656 | SND_SOC_DAPM_SUPPLY("PLL1", SND_SOC_NOPM, 0, 0, adau1373_pll_event, | ||
657 | SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD), | ||
658 | SND_SOC_DAPM_SUPPLY("PLL2", SND_SOC_NOPM, 0, 0, adau1373_pll_event, | ||
659 | SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD), | ||
660 | SND_SOC_DAPM_SUPPLY("SYSCLK1", ADAU1373_CLK_SRC_DIV(0), 7, 0, NULL, 0), | ||
661 | SND_SOC_DAPM_SUPPLY("SYSCLK2", ADAU1373_CLK_SRC_DIV(1), 7, 0, NULL, 0), | ||
662 | |||
663 | SND_SOC_DAPM_INPUT("AIN1L"), | ||
664 | SND_SOC_DAPM_INPUT("AIN1R"), | ||
665 | SND_SOC_DAPM_INPUT("AIN2L"), | ||
666 | SND_SOC_DAPM_INPUT("AIN2R"), | ||
667 | SND_SOC_DAPM_INPUT("AIN3L"), | ||
668 | SND_SOC_DAPM_INPUT("AIN3R"), | ||
669 | SND_SOC_DAPM_INPUT("AIN4L"), | ||
670 | SND_SOC_DAPM_INPUT("AIN4R"), | ||
671 | |||
672 | SND_SOC_DAPM_INPUT("DMIC1DAT"), | ||
673 | SND_SOC_DAPM_INPUT("DMIC2DAT"), | ||
674 | |||
675 | SND_SOC_DAPM_OUTPUT("LOUT1L"), | ||
676 | SND_SOC_DAPM_OUTPUT("LOUT1R"), | ||
677 | SND_SOC_DAPM_OUTPUT("LOUT2L"), | ||
678 | SND_SOC_DAPM_OUTPUT("LOUT2R"), | ||
679 | SND_SOC_DAPM_OUTPUT("HPL"), | ||
680 | SND_SOC_DAPM_OUTPUT("HPR"), | ||
681 | SND_SOC_DAPM_OUTPUT("SPKL"), | ||
682 | SND_SOC_DAPM_OUTPUT("SPKR"), | ||
683 | SND_SOC_DAPM_OUTPUT("EP"), | ||
684 | }; | ||
685 | |||
686 | static int adau1373_check_aif_clk(struct snd_soc_dapm_widget *source, | ||
687 | struct snd_soc_dapm_widget *sink) | ||
688 | { | ||
689 | struct snd_soc_codec *codec = source->codec; | ||
690 | struct adau1373 *adau1373 = snd_soc_codec_get_drvdata(codec); | ||
691 | unsigned int dai; | ||
692 | const char *clk; | ||
693 | |||
694 | dai = sink->name[3] - '1'; | ||
695 | |||
696 | if (!adau1373->dais[dai].master) | ||
697 | return 0; | ||
698 | |||
699 | if (adau1373->dais[dai].clk_src == ADAU1373_CLK_SRC_PLL1) | ||
700 | clk = "SYSCLK1"; | ||
701 | else | ||
702 | clk = "SYSCLK2"; | ||
703 | |||
704 | return strcmp(source->name, clk) == 0; | ||
705 | } | ||
706 | |||
707 | static int adau1373_check_src(struct snd_soc_dapm_widget *source, | ||
708 | struct snd_soc_dapm_widget *sink) | ||
709 | { | ||
710 | struct snd_soc_codec *codec = source->codec; | ||
711 | struct adau1373 *adau1373 = snd_soc_codec_get_drvdata(codec); | ||
712 | unsigned int dai; | ||
713 | |||
714 | dai = sink->name[3] - '1'; | ||
715 | |||
716 | return adau1373->dais[dai].enable_src; | ||
717 | } | ||
718 | |||
719 | #define DSP_CHANNEL_MIXER_ROUTES(_sink) \ | ||
720 | { _sink, "DMIC2 Swapped Switch", "DMIC2" }, \ | ||
721 | { _sink, "DMIC2 Switch", "DMIC2" }, \ | ||
722 | { _sink, "ADC/DMIC1 Swapped Switch", "Decimator Mux" }, \ | ||
723 | { _sink, "ADC/DMIC1 Switch", "Decimator Mux" }, \ | ||
724 | { _sink, "AIF1 Switch", "AIF1 IN" }, \ | ||
725 | { _sink, "AIF2 Switch", "AIF2 IN" }, \ | ||
726 | { _sink, "AIF3 Switch", "AIF3 IN" } | ||
727 | |||
728 | #define DSP_OUTPUT_MIXER_ROUTES(_sink) \ | ||
729 | { _sink, "DSP Channel1 Switch", "DSP Channel1 Mixer" }, \ | ||
730 | { _sink, "DSP Channel2 Switch", "DSP Channel2 Mixer" }, \ | ||
731 | { _sink, "DSP Channel3 Switch", "DSP Channel3 Mixer" }, \ | ||
732 | { _sink, "DSP Channel4 Switch", "DSP Channel4 Mixer" }, \ | ||
733 | { _sink, "DSP Channel5 Switch", "DSP Channel5 Mixer" } | ||
734 | |||
735 | #define LEFT_OUTPUT_MIXER_ROUTES(_sink) \ | ||
736 | { _sink, "Right DAC2 Switch", "Right DAC2" }, \ | ||
737 | { _sink, "Left DAC2 Switch", "Left DAC2" }, \ | ||
738 | { _sink, "Right DAC1 Switch", "Right DAC1" }, \ | ||
739 | { _sink, "Left DAC1 Switch", "Left DAC1" }, \ | ||
740 | { _sink, "Input 1 Bypass Switch", "IN1PGA" }, \ | ||
741 | { _sink, "Input 2 Bypass Switch", "IN2PGA" }, \ | ||
742 | { _sink, "Input 3 Bypass Switch", "IN3PGA" }, \ | ||
743 | { _sink, "Input 4 Bypass Switch", "IN4PGA" } | ||
744 | |||
745 | #define RIGHT_OUTPUT_MIXER_ROUTES(_sink) \ | ||
746 | { _sink, "Right DAC2 Switch", "Right DAC2" }, \ | ||
747 | { _sink, "Left DAC2 Switch", "Left DAC2" }, \ | ||
748 | { _sink, "Right DAC1 Switch", "Right DAC1" }, \ | ||
749 | { _sink, "Left DAC1 Switch", "Left DAC1" }, \ | ||
750 | { _sink, "Input 1 Bypass Switch", "IN1PGA" }, \ | ||
751 | { _sink, "Input 2 Bypass Switch", "IN2PGA" }, \ | ||
752 | { _sink, "Input 3 Bypass Switch", "IN3PGA" }, \ | ||
753 | { _sink, "Input 4 Bypass Switch", "IN4PGA" } | ||
754 | |||
755 | static const struct snd_soc_dapm_route adau1373_dapm_routes[] = { | ||
756 | { "Left ADC Mixer", "DAC1 Switch", "Left DAC1" }, | ||
757 | { "Left ADC Mixer", "Input 1 Switch", "IN1PGA" }, | ||
758 | { "Left ADC Mixer", "Input 2 Switch", "IN2PGA" }, | ||
759 | { "Left ADC Mixer", "Input 3 Switch", "IN3PGA" }, | ||
760 | { "Left ADC Mixer", "Input 4 Switch", "IN4PGA" }, | ||
761 | |||
762 | { "Right ADC Mixer", "DAC1 Switch", "Right DAC1" }, | ||
763 | { "Right ADC Mixer", "Input 1 Switch", "IN1PGA" }, | ||
764 | { "Right ADC Mixer", "Input 2 Switch", "IN2PGA" }, | ||
765 | { "Right ADC Mixer", "Input 3 Switch", "IN3PGA" }, | ||
766 | { "Right ADC Mixer", "Input 4 Switch", "IN4PGA" }, | ||
767 | |||
768 | { "Left ADC", NULL, "Left ADC Mixer" }, | ||
769 | { "Right ADC", NULL, "Right ADC Mixer" }, | ||
770 | |||
771 | { "Decimator Mux", "ADC", "Left ADC" }, | ||
772 | { "Decimator Mux", "ADC", "Right ADC" }, | ||
773 | { "Decimator Mux", "DMIC1", "DMIC1" }, | ||
774 | |||
775 | DSP_CHANNEL_MIXER_ROUTES("DSP Channel1 Mixer"), | ||
776 | DSP_CHANNEL_MIXER_ROUTES("DSP Channel2 Mixer"), | ||
777 | DSP_CHANNEL_MIXER_ROUTES("DSP Channel3 Mixer"), | ||
778 | DSP_CHANNEL_MIXER_ROUTES("DSP Channel4 Mixer"), | ||
779 | DSP_CHANNEL_MIXER_ROUTES("DSP Channel5 Mixer"), | ||
780 | |||
781 | DSP_OUTPUT_MIXER_ROUTES("AIF1 Mixer"), | ||
782 | DSP_OUTPUT_MIXER_ROUTES("AIF2 Mixer"), | ||
783 | DSP_OUTPUT_MIXER_ROUTES("AIF3 Mixer"), | ||
784 | DSP_OUTPUT_MIXER_ROUTES("DAC1 Mixer"), | ||
785 | DSP_OUTPUT_MIXER_ROUTES("DAC2 Mixer"), | ||
786 | |||
787 | { "AIF1 OUT", NULL, "AIF1 Mixer" }, | ||
788 | { "AIF2 OUT", NULL, "AIF2 Mixer" }, | ||
789 | { "AIF3 OUT", NULL, "AIF3 Mixer" }, | ||
790 | { "Left DAC1", NULL, "DAC1 Mixer" }, | ||
791 | { "Right DAC1", NULL, "DAC1 Mixer" }, | ||
792 | { "Left DAC2", NULL, "DAC2 Mixer" }, | ||
793 | { "Right DAC2", NULL, "DAC2 Mixer" }, | ||
794 | |||
795 | LEFT_OUTPUT_MIXER_ROUTES("Left Lineout1 Mixer"), | ||
796 | RIGHT_OUTPUT_MIXER_ROUTES("Right Lineout1 Mixer"), | ||
797 | LEFT_OUTPUT_MIXER_ROUTES("Left Lineout2 Mixer"), | ||
798 | RIGHT_OUTPUT_MIXER_ROUTES("Right Lineout2 Mixer"), | ||
799 | LEFT_OUTPUT_MIXER_ROUTES("Left Speaker Mixer"), | ||
800 | RIGHT_OUTPUT_MIXER_ROUTES("Right Speaker Mixer"), | ||
801 | |||
802 | { "Left Headphone Mixer", "Left DAC2 Switch", "Left DAC2" }, | ||
803 | { "Left Headphone Mixer", "Left DAC1 Switch", "Left DAC1" }, | ||
804 | { "Left Headphone Mixer", "Input 1 Bypass Switch", "IN1PGA" }, | ||
805 | { "Left Headphone Mixer", "Input 2 Bypass Switch", "IN2PGA" }, | ||
806 | { "Left Headphone Mixer", "Input 3 Bypass Switch", "IN3PGA" }, | ||
807 | { "Left Headphone Mixer", "Input 4 Bypass Switch", "IN4PGA" }, | ||
808 | { "Right Headphone Mixer", "Right DAC2 Switch", "Right DAC2" }, | ||
809 | { "Right Headphone Mixer", "Right DAC1 Switch", "Right DAC1" }, | ||
810 | { "Right Headphone Mixer", "Input 1 Bypass Switch", "IN1PGA" }, | ||
811 | { "Right Headphone Mixer", "Input 2 Bypass Switch", "IN2PGA" }, | ||
812 | { "Right Headphone Mixer", "Input 3 Bypass Switch", "IN3PGA" }, | ||
813 | { "Right Headphone Mixer", "Input 4 Bypass Switch", "IN4PGA" }, | ||
814 | |||
815 | { "Left Headphone Mixer", NULL, "Headphone Enable" }, | ||
816 | { "Right Headphone Mixer", NULL, "Headphone Enable" }, | ||
817 | |||
818 | { "Earpiece Mixer", "Right DAC2 Switch", "Right DAC2" }, | ||
819 | { "Earpiece Mixer", "Left DAC2 Switch", "Left DAC2" }, | ||
820 | { "Earpiece Mixer", "Right DAC1 Switch", "Right DAC1" }, | ||
821 | { "Earpiece Mixer", "Left DAC1 Switch", "Left DAC1" }, | ||
822 | { "Earpiece Mixer", "Input 1 Bypass Switch", "IN1PGA" }, | ||
823 | { "Earpiece Mixer", "Input 2 Bypass Switch", "IN2PGA" }, | ||
824 | { "Earpiece Mixer", "Input 3 Bypass Switch", "IN3PGA" }, | ||
825 | { "Earpiece Mixer", "Input 4 Bypass Switch", "IN4PGA" }, | ||
826 | |||
827 | { "LOUT1L", NULL, "Left Lineout1 Mixer" }, | ||
828 | { "LOUT1R", NULL, "Right Lineout1 Mixer" }, | ||
829 | { "LOUT2L", NULL, "Left Lineout2 Mixer" }, | ||
830 | { "LOUT2R", NULL, "Right Lineout2 Mixer" }, | ||
831 | { "SPKL", NULL, "Left Speaker Mixer" }, | ||
832 | { "SPKR", NULL, "Right Speaker Mixer" }, | ||
833 | { "HPL", NULL, "Left Headphone Mixer" }, | ||
834 | { "HPR", NULL, "Right Headphone Mixer" }, | ||
835 | { "EP", NULL, "Earpiece Mixer" }, | ||
836 | |||
837 | { "IN1PGA", NULL, "AIN1L" }, | ||
838 | { "IN2PGA", NULL, "AIN2L" }, | ||
839 | { "IN3PGA", NULL, "AIN3L" }, | ||
840 | { "IN4PGA", NULL, "AIN4L" }, | ||
841 | { "IN1PGA", NULL, "AIN1R" }, | ||
842 | { "IN2PGA", NULL, "AIN2R" }, | ||
843 | { "IN3PGA", NULL, "AIN3R" }, | ||
844 | { "IN4PGA", NULL, "AIN4R" }, | ||
845 | |||
846 | { "SYSCLK1", NULL, "PLL1" }, | ||
847 | { "SYSCLK2", NULL, "PLL2" }, | ||
848 | |||
849 | { "Left DAC1", NULL, "SYSCLK1" }, | ||
850 | { "Right DAC1", NULL, "SYSCLK1" }, | ||
851 | { "Left DAC2", NULL, "SYSCLK1" }, | ||
852 | { "Right DAC2", NULL, "SYSCLK1" }, | ||
853 | { "Left ADC", NULL, "SYSCLK1" }, | ||
854 | { "Right ADC", NULL, "SYSCLK1" }, | ||
855 | |||
856 | { "DSP", NULL, "SYSCLK1" }, | ||
857 | |||
858 | { "AIF1 Mixer", NULL, "DSP" }, | ||
859 | { "AIF2 Mixer", NULL, "DSP" }, | ||
860 | { "AIF3 Mixer", NULL, "DSP" }, | ||
861 | { "DAC1 Mixer", NULL, "DSP" }, | ||
862 | { "DAC2 Mixer", NULL, "DSP" }, | ||
863 | { "DAC1 Mixer", NULL, "Playback Engine A" }, | ||
864 | { "DAC2 Mixer", NULL, "Playback Engine B" }, | ||
865 | { "Left ADC Mixer", NULL, "Recording Engine A" }, | ||
866 | { "Right ADC Mixer", NULL, "Recording Engine A" }, | ||
867 | |||
868 | { "AIF1 CLK", NULL, "SYSCLK1", adau1373_check_aif_clk }, | ||
869 | { "AIF2 CLK", NULL, "SYSCLK1", adau1373_check_aif_clk }, | ||
870 | { "AIF3 CLK", NULL, "SYSCLK1", adau1373_check_aif_clk }, | ||
871 | { "AIF1 CLK", NULL, "SYSCLK2", adau1373_check_aif_clk }, | ||
872 | { "AIF2 CLK", NULL, "SYSCLK2", adau1373_check_aif_clk }, | ||
873 | { "AIF3 CLK", NULL, "SYSCLK2", adau1373_check_aif_clk }, | ||
874 | |||
875 | { "AIF1 IN", NULL, "AIF1 CLK" }, | ||
876 | { "AIF1 OUT", NULL, "AIF1 CLK" }, | ||
877 | { "AIF2 IN", NULL, "AIF2 CLK" }, | ||
878 | { "AIF2 OUT", NULL, "AIF2 CLK" }, | ||
879 | { "AIF3 IN", NULL, "AIF3 CLK" }, | ||
880 | { "AIF3 OUT", NULL, "AIF3 CLK" }, | ||
881 | { "AIF1 IN", NULL, "AIF1 IN SRC", adau1373_check_src }, | ||
882 | { "AIF1 OUT", NULL, "AIF1 OUT SRC", adau1373_check_src }, | ||
883 | { "AIF2 IN", NULL, "AIF2 IN SRC", adau1373_check_src }, | ||
884 | { "AIF2 OUT", NULL, "AIF2 OUT SRC", adau1373_check_src }, | ||
885 | { "AIF3 IN", NULL, "AIF3 IN SRC", adau1373_check_src }, | ||
886 | { "AIF3 OUT", NULL, "AIF3 OUT SRC", adau1373_check_src }, | ||
887 | |||
888 | { "DMIC1", NULL, "DMIC1DAT" }, | ||
889 | { "DMIC1", NULL, "SYSCLK1" }, | ||
890 | { "DMIC1", NULL, "Recording Engine A" }, | ||
891 | { "DMIC2", NULL, "DMIC2DAT" }, | ||
892 | { "DMIC2", NULL, "SYSCLK1" }, | ||
893 | { "DMIC2", NULL, "Recording Engine B" }, | ||
894 | }; | ||
895 | |||
896 | static int adau1373_hw_params(struct snd_pcm_substream *substream, | ||
897 | struct snd_pcm_hw_params *params, struct snd_soc_dai *dai) | ||
898 | { | ||
899 | struct snd_soc_codec *codec = dai->codec; | ||
900 | struct adau1373 *adau1373 = snd_soc_codec_get_drvdata(codec); | ||
901 | struct adau1373_dai *adau1373_dai = &adau1373->dais[dai->id]; | ||
902 | unsigned int div; | ||
903 | unsigned int freq; | ||
904 | unsigned int ctrl; | ||
905 | |||
906 | freq = adau1373_dai->sysclk; | ||
907 | |||
908 | if (freq % params_rate(params) != 0) | ||
909 | return -EINVAL; | ||
910 | |||
911 | switch (freq / params_rate(params)) { | ||
912 | case 1024: /* sysclk / 256 */ | ||
913 | div = 0; | ||
914 | break; | ||
915 | case 1536: /* 2/3 sysclk / 256 */ | ||
916 | div = 1; | ||
917 | break; | ||
918 | case 2048: /* 1/2 sysclk / 256 */ | ||
919 | div = 2; | ||
920 | break; | ||
921 | case 3072: /* 1/3 sysclk / 256 */ | ||
922 | div = 3; | ||
923 | break; | ||
924 | case 4096: /* 1/4 sysclk / 256 */ | ||
925 | div = 4; | ||
926 | break; | ||
927 | case 6144: /* 1/6 sysclk / 256 */ | ||
928 | div = 5; | ||
929 | break; | ||
930 | case 5632: /* 2/11 sysclk / 256 */ | ||
931 | div = 6; | ||
932 | break; | ||
933 | default: | ||
934 | return -EINVAL; | ||
935 | } | ||
936 | |||
937 | adau1373_dai->enable_src = (div != 0); | ||
938 | |||
939 | snd_soc_update_bits(codec, ADAU1373_BCLKDIV(dai->id), | ||
940 | ~ADAU1373_BCLKDIV_SOURCE, (div << 2) | ADAU1373_BCLKDIV_64); | ||
941 | |||
942 | switch (params_format(params)) { | ||
943 | case SNDRV_PCM_FORMAT_S16_LE: | ||
944 | ctrl = ADAU1373_DAI_WLEN_16; | ||
945 | break; | ||
946 | case SNDRV_PCM_FORMAT_S20_3LE: | ||
947 | ctrl = ADAU1373_DAI_WLEN_20; | ||
948 | break; | ||
949 | case SNDRV_PCM_FORMAT_S24_LE: | ||
950 | ctrl = ADAU1373_DAI_WLEN_24; | ||
951 | break; | ||
952 | case SNDRV_PCM_FORMAT_S32_LE: | ||
953 | ctrl = ADAU1373_DAI_WLEN_32; | ||
954 | break; | ||
955 | default: | ||
956 | return -EINVAL; | ||
957 | } | ||
958 | |||
959 | return snd_soc_update_bits(codec, ADAU1373_DAI(dai->id), | ||
960 | ADAU1373_DAI_WLEN_MASK, ctrl); | ||
961 | } | ||
962 | |||
963 | static int adau1373_set_dai_fmt(struct snd_soc_dai *dai, unsigned int fmt) | ||
964 | { | ||
965 | struct snd_soc_codec *codec = dai->codec; | ||
966 | struct adau1373 *adau1373 = snd_soc_codec_get_drvdata(codec); | ||
967 | struct adau1373_dai *adau1373_dai = &adau1373->dais[dai->id]; | ||
968 | unsigned int ctrl; | ||
969 | |||
970 | switch (fmt & SND_SOC_DAIFMT_MASTER_MASK) { | ||
971 | case SND_SOC_DAIFMT_CBM_CFM: | ||
972 | ctrl = ADAU1373_DAI_MASTER; | ||
973 | adau1373_dai->master = true; | ||
974 | break; | ||
975 | case SND_SOC_DAIFMT_CBS_CFS: | ||
976 | ctrl = 0; | ||
977 | adau1373_dai->master = true; | ||
978 | break; | ||
979 | default: | ||
980 | return -EINVAL; | ||
981 | } | ||
982 | |||
983 | switch (fmt & SND_SOC_DAIFMT_FORMAT_MASK) { | ||
984 | case SND_SOC_DAIFMT_I2S: | ||
985 | ctrl |= ADAU1373_DAI_FORMAT_I2S; | ||
986 | break; | ||
987 | case SND_SOC_DAIFMT_LEFT_J: | ||
988 | ctrl |= ADAU1373_DAI_FORMAT_LEFT_J; | ||
989 | break; | ||
990 | case SND_SOC_DAIFMT_RIGHT_J: | ||
991 | ctrl |= ADAU1373_DAI_FORMAT_RIGHT_J; | ||
992 | break; | ||
993 | case SND_SOC_DAIFMT_DSP_B: | ||
994 | ctrl |= ADAU1373_DAI_FORMAT_DSP; | ||
995 | break; | ||
996 | default: | ||
997 | return -EINVAL; | ||
998 | } | ||
999 | |||
1000 | switch (fmt & SND_SOC_DAIFMT_INV_MASK) { | ||
1001 | case SND_SOC_DAIFMT_NB_NF: | ||
1002 | break; | ||
1003 | case SND_SOC_DAIFMT_IB_NF: | ||
1004 | ctrl |= ADAU1373_DAI_INVERT_BCLK; | ||
1005 | break; | ||
1006 | case SND_SOC_DAIFMT_NB_IF: | ||
1007 | ctrl |= ADAU1373_DAI_INVERT_LRCLK; | ||
1008 | break; | ||
1009 | case SND_SOC_DAIFMT_IB_IF: | ||
1010 | ctrl |= ADAU1373_DAI_INVERT_LRCLK | ADAU1373_DAI_INVERT_BCLK; | ||
1011 | break; | ||
1012 | default: | ||
1013 | return -EINVAL; | ||
1014 | } | ||
1015 | |||
1016 | snd_soc_update_bits(codec, ADAU1373_DAI(dai->id), | ||
1017 | ~ADAU1373_DAI_WLEN_MASK, ctrl); | ||
1018 | |||
1019 | return 0; | ||
1020 | } | ||
1021 | |||
1022 | static int adau1373_set_dai_sysclk(struct snd_soc_dai *dai, | ||
1023 | int clk_id, unsigned int freq, int dir) | ||
1024 | { | ||
1025 | struct adau1373 *adau1373 = snd_soc_codec_get_drvdata(dai->codec); | ||
1026 | struct adau1373_dai *adau1373_dai = &adau1373->dais[dai->id]; | ||
1027 | |||
1028 | switch (clk_id) { | ||
1029 | case ADAU1373_CLK_SRC_PLL1: | ||
1030 | case ADAU1373_CLK_SRC_PLL2: | ||
1031 | break; | ||
1032 | default: | ||
1033 | return -EINVAL; | ||
1034 | } | ||
1035 | |||
1036 | adau1373_dai->sysclk = freq; | ||
1037 | adau1373_dai->clk_src = clk_id; | ||
1038 | |||
1039 | snd_soc_update_bits(dai->codec, ADAU1373_BCLKDIV(dai->id), | ||
1040 | ADAU1373_BCLKDIV_SOURCE, clk_id << 5); | ||
1041 | |||
1042 | return 0; | ||
1043 | } | ||
1044 | |||
1045 | static const struct snd_soc_dai_ops adau1373_dai_ops = { | ||
1046 | .hw_params = adau1373_hw_params, | ||
1047 | .set_sysclk = adau1373_set_dai_sysclk, | ||
1048 | .set_fmt = adau1373_set_dai_fmt, | ||
1049 | }; | ||
1050 | |||
1051 | #define ADAU1373_FORMATS (SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S20_3LE | \ | ||
1052 | SNDRV_PCM_FMTBIT_S24_LE | SNDRV_PCM_FMTBIT_S32_LE) | ||
1053 | |||
1054 | static struct snd_soc_dai_driver adau1373_dai_driver[] = { | ||
1055 | { | ||
1056 | .id = 0, | ||
1057 | .name = "adau1373-aif1", | ||
1058 | .playback = { | ||
1059 | .stream_name = "AIF1 Playback", | ||
1060 | .channels_min = 2, | ||
1061 | .channels_max = 2, | ||
1062 | .rates = SNDRV_PCM_RATE_8000_48000, | ||
1063 | .formats = ADAU1373_FORMATS, | ||
1064 | }, | ||
1065 | .capture = { | ||
1066 | .stream_name = "AIF1 Capture", | ||
1067 | .channels_min = 2, | ||
1068 | .channels_max = 2, | ||
1069 | .rates = SNDRV_PCM_RATE_8000_48000, | ||
1070 | .formats = ADAU1373_FORMATS, | ||
1071 | }, | ||
1072 | .ops = &adau1373_dai_ops, | ||
1073 | .symmetric_rates = 1, | ||
1074 | }, | ||
1075 | { | ||
1076 | .id = 1, | ||
1077 | .name = "adau1373-aif2", | ||
1078 | .playback = { | ||
1079 | .stream_name = "AIF2 Playback", | ||
1080 | .channels_min = 2, | ||
1081 | .channels_max = 2, | ||
1082 | .rates = SNDRV_PCM_RATE_8000_48000, | ||
1083 | .formats = ADAU1373_FORMATS, | ||
1084 | }, | ||
1085 | .capture = { | ||
1086 | .stream_name = "AIF2 Capture", | ||
1087 | .channels_min = 2, | ||
1088 | .channels_max = 2, | ||
1089 | .rates = SNDRV_PCM_RATE_8000_48000, | ||
1090 | .formats = ADAU1373_FORMATS, | ||
1091 | }, | ||
1092 | .ops = &adau1373_dai_ops, | ||
1093 | .symmetric_rates = 1, | ||
1094 | }, | ||
1095 | { | ||
1096 | .id = 2, | ||
1097 | .name = "adau1373-aif3", | ||
1098 | .playback = { | ||
1099 | .stream_name = "AIF3 Playback", | ||
1100 | .channels_min = 2, | ||
1101 | .channels_max = 2, | ||
1102 | .rates = SNDRV_PCM_RATE_8000_48000, | ||
1103 | .formats = ADAU1373_FORMATS, | ||
1104 | }, | ||
1105 | .capture = { | ||
1106 | .stream_name = "AIF3 Capture", | ||
1107 | .channels_min = 2, | ||
1108 | .channels_max = 2, | ||
1109 | .rates = SNDRV_PCM_RATE_8000_48000, | ||
1110 | .formats = ADAU1373_FORMATS, | ||
1111 | }, | ||
1112 | .ops = &adau1373_dai_ops, | ||
1113 | .symmetric_rates = 1, | ||
1114 | }, | ||
1115 | }; | ||
1116 | |||
1117 | static int adau1373_set_pll(struct snd_soc_codec *codec, int pll_id, | ||
1118 | int source, unsigned int freq_in, unsigned int freq_out) | ||
1119 | { | ||
1120 | unsigned int dpll_div = 0; | ||
1121 | unsigned int x, r, n, m, i, j, mode; | ||
1122 | |||
1123 | switch (pll_id) { | ||
1124 | case ADAU1373_PLL1: | ||
1125 | case ADAU1373_PLL2: | ||
1126 | break; | ||
1127 | default: | ||
1128 | return -EINVAL; | ||
1129 | } | ||
1130 | |||
1131 | switch (source) { | ||
1132 | case ADAU1373_PLL_SRC_BCLK1: | ||
1133 | case ADAU1373_PLL_SRC_BCLK2: | ||
1134 | case ADAU1373_PLL_SRC_BCLK3: | ||
1135 | case ADAU1373_PLL_SRC_LRCLK1: | ||
1136 | case ADAU1373_PLL_SRC_LRCLK2: | ||
1137 | case ADAU1373_PLL_SRC_LRCLK3: | ||
1138 | case ADAU1373_PLL_SRC_MCLK1: | ||
1139 | case ADAU1373_PLL_SRC_MCLK2: | ||
1140 | case ADAU1373_PLL_SRC_GPIO1: | ||
1141 | case ADAU1373_PLL_SRC_GPIO2: | ||
1142 | case ADAU1373_PLL_SRC_GPIO3: | ||
1143 | case ADAU1373_PLL_SRC_GPIO4: | ||
1144 | break; | ||
1145 | default: | ||
1146 | return -EINVAL; | ||
1147 | } | ||
1148 | |||
1149 | if (freq_in < 7813 || freq_in > 27000000) | ||
1150 | return -EINVAL; | ||
1151 | |||
1152 | if (freq_out < 45158000 || freq_out > 49152000) | ||
1153 | return -EINVAL; | ||
1154 | |||
1155 | /* APLL input needs to be >= 8Mhz, so in case freq_in is less we use the | ||
1156 | * DPLL to get it there. DPLL_out = (DPLL_in / div) * 1024 */ | ||
1157 | while (freq_in < 8000000) { | ||
1158 | freq_in *= 2; | ||
1159 | dpll_div++; | ||
1160 | } | ||
1161 | |||
1162 | if (freq_out % freq_in != 0) { | ||
1163 | /* fout = fin * (r + (n/m)) / x */ | ||
1164 | x = DIV_ROUND_UP(freq_in, 13500000); | ||
1165 | freq_in /= x; | ||
1166 | r = freq_out / freq_in; | ||
1167 | i = freq_out % freq_in; | ||
1168 | j = gcd(i, freq_in); | ||
1169 | n = i / j; | ||
1170 | m = freq_in / j; | ||
1171 | x--; | ||
1172 | mode = 1; | ||
1173 | } else { | ||
1174 | /* fout = fin / r */ | ||
1175 | r = freq_out / freq_in; | ||
1176 | n = 0; | ||
1177 | m = 0; | ||
1178 | x = 0; | ||
1179 | mode = 0; | ||
1180 | } | ||
1181 | |||
1182 | if (r < 2 || r > 8 || x > 3 || m > 0xffff || n > 0xffff) | ||
1183 | return -EINVAL; | ||
1184 | |||
1185 | if (dpll_div) { | ||
1186 | dpll_div = 11 - dpll_div; | ||
1187 | snd_soc_update_bits(codec, ADAU1373_PLL_CTRL6(pll_id), | ||
1188 | ADAU1373_PLL_CTRL6_DPLL_BYPASS, 0); | ||
1189 | } else { | ||
1190 | snd_soc_update_bits(codec, ADAU1373_PLL_CTRL6(pll_id), | ||
1191 | ADAU1373_PLL_CTRL6_DPLL_BYPASS, | ||
1192 | ADAU1373_PLL_CTRL6_DPLL_BYPASS); | ||
1193 | } | ||
1194 | |||
1195 | snd_soc_write(codec, ADAU1373_DPLL_CTRL(pll_id), | ||
1196 | (source << 4) | dpll_div); | ||
1197 | snd_soc_write(codec, ADAU1373_PLL_CTRL1(pll_id), (m >> 8) & 0xff); | ||
1198 | snd_soc_write(codec, ADAU1373_PLL_CTRL2(pll_id), m & 0xff); | ||
1199 | snd_soc_write(codec, ADAU1373_PLL_CTRL3(pll_id), (n >> 8) & 0xff); | ||
1200 | snd_soc_write(codec, ADAU1373_PLL_CTRL4(pll_id), n & 0xff); | ||
1201 | snd_soc_write(codec, ADAU1373_PLL_CTRL5(pll_id), | ||
1202 | (r << 3) | (x << 1) | mode); | ||
1203 | |||
1204 | /* Set sysclk to pll_rate / 4 */ | ||
1205 | snd_soc_update_bits(codec, ADAU1373_CLK_SRC_DIV(pll_id), 0x3f, 0x09); | ||
1206 | |||
1207 | return 0; | ||
1208 | } | ||
1209 | |||
1210 | static void adau1373_load_drc_settings(struct snd_soc_codec *codec, | ||
1211 | unsigned int nr, uint8_t *drc) | ||
1212 | { | ||
1213 | unsigned int i; | ||
1214 | |||
1215 | for (i = 0; i < ADAU1373_DRC_SIZE; ++i) | ||
1216 | snd_soc_write(codec, ADAU1373_DRC(nr) + i, drc[i]); | ||
1217 | } | ||
1218 | |||
1219 | static bool adau1373_valid_micbias(enum adau1373_micbias_voltage micbias) | ||
1220 | { | ||
1221 | switch (micbias) { | ||
1222 | case ADAU1373_MICBIAS_2_9V: | ||
1223 | case ADAU1373_MICBIAS_2_2V: | ||
1224 | case ADAU1373_MICBIAS_2_6V: | ||
1225 | case ADAU1373_MICBIAS_1_8V: | ||
1226 | return true; | ||
1227 | default: | ||
1228 | break; | ||
1229 | } | ||
1230 | return false; | ||
1231 | } | ||
1232 | |||
1233 | static int adau1373_probe(struct snd_soc_codec *codec) | ||
1234 | { | ||
1235 | struct adau1373_platform_data *pdata = codec->dev->platform_data; | ||
1236 | bool lineout_differential = false; | ||
1237 | unsigned int val; | ||
1238 | int ret; | ||
1239 | int i; | ||
1240 | |||
1241 | ret = snd_soc_codec_set_cache_io(codec, 8, 8, SND_SOC_I2C); | ||
1242 | if (ret) { | ||
1243 | dev_err(codec->dev, "failed to set cache I/O: %d\n", ret); | ||
1244 | return ret; | ||
1245 | } | ||
1246 | |||
1247 | codec->dapm.idle_bias_off = true; | ||
1248 | |||
1249 | if (pdata) { | ||
1250 | if (pdata->num_drc > ARRAY_SIZE(pdata->drc_setting)) | ||
1251 | return -EINVAL; | ||
1252 | |||
1253 | if (!adau1373_valid_micbias(pdata->micbias1) || | ||
1254 | !adau1373_valid_micbias(pdata->micbias2)) | ||
1255 | return -EINVAL; | ||
1256 | |||
1257 | for (i = 0; i < pdata->num_drc; ++i) { | ||
1258 | adau1373_load_drc_settings(codec, i, | ||
1259 | pdata->drc_setting[i]); | ||
1260 | } | ||
1261 | |||
1262 | snd_soc_add_controls(codec, adau1373_drc_controls, | ||
1263 | pdata->num_drc); | ||
1264 | |||
1265 | val = 0; | ||
1266 | for (i = 0; i < 4; ++i) { | ||
1267 | if (pdata->input_differential[i]) | ||
1268 | val |= BIT(i); | ||
1269 | } | ||
1270 | snd_soc_write(codec, ADAU1373_INPUT_MODE, val); | ||
1271 | |||
1272 | val = 0; | ||
1273 | if (pdata->lineout_differential) | ||
1274 | val |= ADAU1373_OUTPUT_CTRL_LDIFF; | ||
1275 | if (pdata->lineout_ground_sense) | ||
1276 | val |= ADAU1373_OUTPUT_CTRL_LNFBEN; | ||
1277 | snd_soc_write(codec, ADAU1373_OUTPUT_CTRL, val); | ||
1278 | |||
1279 | lineout_differential = pdata->lineout_differential; | ||
1280 | |||
1281 | snd_soc_write(codec, ADAU1373_EP_CTRL, | ||
1282 | (pdata->micbias1 << ADAU1373_EP_CTRL_MICBIAS1_OFFSET) | | ||
1283 | (pdata->micbias2 << ADAU1373_EP_CTRL_MICBIAS2_OFFSET)); | ||
1284 | } | ||
1285 | |||
1286 | if (!lineout_differential) { | ||
1287 | snd_soc_add_controls(codec, adau1373_lineout2_controls, | ||
1288 | ARRAY_SIZE(adau1373_lineout2_controls)); | ||
1289 | } | ||
1290 | |||
1291 | snd_soc_write(codec, ADAU1373_ADC_CTRL, | ||
1292 | ADAU1373_ADC_CTRL_RESET_FORCE | ADAU1373_ADC_CTRL_PEAK_DETECT); | ||
1293 | |||
1294 | return 0; | ||
1295 | } | ||
1296 | |||
1297 | static int adau1373_set_bias_level(struct snd_soc_codec *codec, | ||
1298 | enum snd_soc_bias_level level) | ||
1299 | { | ||
1300 | switch (level) { | ||
1301 | case SND_SOC_BIAS_ON: | ||
1302 | break; | ||
1303 | case SND_SOC_BIAS_PREPARE: | ||
1304 | break; | ||
1305 | case SND_SOC_BIAS_STANDBY: | ||
1306 | snd_soc_update_bits(codec, ADAU1373_PWDN_CTRL3, | ||
1307 | ADAU1373_PWDN_CTRL3_PWR_EN, ADAU1373_PWDN_CTRL3_PWR_EN); | ||
1308 | break; | ||
1309 | case SND_SOC_BIAS_OFF: | ||
1310 | snd_soc_update_bits(codec, ADAU1373_PWDN_CTRL3, | ||
1311 | ADAU1373_PWDN_CTRL3_PWR_EN, 0); | ||
1312 | break; | ||
1313 | } | ||
1314 | codec->dapm.bias_level = level; | ||
1315 | return 0; | ||
1316 | } | ||
1317 | |||
1318 | static int adau1373_remove(struct snd_soc_codec *codec) | ||
1319 | { | ||
1320 | adau1373_set_bias_level(codec, SND_SOC_BIAS_OFF); | ||
1321 | return 0; | ||
1322 | } | ||
1323 | |||
1324 | static int adau1373_suspend(struct snd_soc_codec *codec, pm_message_t state) | ||
1325 | { | ||
1326 | return adau1373_set_bias_level(codec, SND_SOC_BIAS_OFF); | ||
1327 | } | ||
1328 | |||
1329 | static int adau1373_resume(struct snd_soc_codec *codec) | ||
1330 | { | ||
1331 | adau1373_set_bias_level(codec, SND_SOC_BIAS_STANDBY); | ||
1332 | snd_soc_cache_sync(codec); | ||
1333 | |||
1334 | return 0; | ||
1335 | } | ||
1336 | |||
1337 | static struct snd_soc_codec_driver adau1373_codec_driver = { | ||
1338 | .probe = adau1373_probe, | ||
1339 | .remove = adau1373_remove, | ||
1340 | .suspend = adau1373_suspend, | ||
1341 | .resume = adau1373_resume, | ||
1342 | .set_bias_level = adau1373_set_bias_level, | ||
1343 | .reg_cache_size = ARRAY_SIZE(adau1373_default_regs), | ||
1344 | .reg_cache_default = adau1373_default_regs, | ||
1345 | .reg_word_size = sizeof(uint8_t), | ||
1346 | |||
1347 | .set_pll = adau1373_set_pll, | ||
1348 | |||
1349 | .controls = adau1373_controls, | ||
1350 | .num_controls = ARRAY_SIZE(adau1373_controls), | ||
1351 | .dapm_widgets = adau1373_dapm_widgets, | ||
1352 | .num_dapm_widgets = ARRAY_SIZE(adau1373_dapm_widgets), | ||
1353 | .dapm_routes = adau1373_dapm_routes, | ||
1354 | .num_dapm_routes = ARRAY_SIZE(adau1373_dapm_routes), | ||
1355 | }; | ||
1356 | |||
1357 | static int __devinit adau1373_i2c_probe(struct i2c_client *client, | ||
1358 | const struct i2c_device_id *id) | ||
1359 | { | ||
1360 | struct adau1373 *adau1373; | ||
1361 | int ret; | ||
1362 | |||
1363 | adau1373 = kzalloc(sizeof(*adau1373), GFP_KERNEL); | ||
1364 | if (!adau1373) | ||
1365 | return -ENOMEM; | ||
1366 | |||
1367 | dev_set_drvdata(&client->dev, adau1373); | ||
1368 | |||
1369 | ret = snd_soc_register_codec(&client->dev, &adau1373_codec_driver, | ||
1370 | adau1373_dai_driver, ARRAY_SIZE(adau1373_dai_driver)); | ||
1371 | if (ret < 0) | ||
1372 | kfree(adau1373); | ||
1373 | |||
1374 | return ret; | ||
1375 | } | ||
1376 | |||
1377 | static int __devexit adau1373_i2c_remove(struct i2c_client *client) | ||
1378 | { | ||
1379 | snd_soc_unregister_codec(&client->dev); | ||
1380 | kfree(dev_get_drvdata(&client->dev)); | ||
1381 | return 0; | ||
1382 | } | ||
1383 | |||
1384 | static const struct i2c_device_id adau1373_i2c_id[] = { | ||
1385 | { "adau1373", 0 }, | ||
1386 | { } | ||
1387 | }; | ||
1388 | MODULE_DEVICE_TABLE(i2c, adau1373_i2c_id); | ||
1389 | |||
1390 | static struct i2c_driver adau1373_i2c_driver = { | ||
1391 | .driver = { | ||
1392 | .name = "adau1373", | ||
1393 | .owner = THIS_MODULE, | ||
1394 | }, | ||
1395 | .probe = adau1373_i2c_probe, | ||
1396 | .remove = __devexit_p(adau1373_i2c_remove), | ||
1397 | .id_table = adau1373_i2c_id, | ||
1398 | }; | ||
1399 | |||
1400 | static int __init adau1373_init(void) | ||
1401 | { | ||
1402 | return i2c_add_driver(&adau1373_i2c_driver); | ||
1403 | } | ||
1404 | module_init(adau1373_init); | ||
1405 | |||
1406 | static void __exit adau1373_exit(void) | ||
1407 | { | ||
1408 | i2c_del_driver(&adau1373_i2c_driver); | ||
1409 | } | ||
1410 | module_exit(adau1373_exit); | ||
1411 | |||
1412 | MODULE_DESCRIPTION("ASoC ADAU1373 driver"); | ||
1413 | MODULE_AUTHOR("Lars-Peter Clausen <lars@metafoo.de>"); | ||
1414 | MODULE_LICENSE("GPL"); | ||
diff --git a/sound/soc/codecs/adau1373.h b/sound/soc/codecs/adau1373.h new file mode 100644 index 000000000000..c6ab5530760c --- /dev/null +++ b/sound/soc/codecs/adau1373.h | |||
@@ -0,0 +1,29 @@ | |||
1 | #ifndef __ADAU1373_H__ | ||
2 | #define __ADAU1373_H__ | ||
3 | |||
4 | enum adau1373_pll_src { | ||
5 | ADAU1373_PLL_SRC_MCLK1 = 0, | ||
6 | ADAU1373_PLL_SRC_BCLK1 = 1, | ||
7 | ADAU1373_PLL_SRC_BCLK2 = 2, | ||
8 | ADAU1373_PLL_SRC_BCLK3 = 3, | ||
9 | ADAU1373_PLL_SRC_LRCLK1 = 4, | ||
10 | ADAU1373_PLL_SRC_LRCLK2 = 5, | ||
11 | ADAU1373_PLL_SRC_LRCLK3 = 6, | ||
12 | ADAU1373_PLL_SRC_GPIO1 = 7, | ||
13 | ADAU1373_PLL_SRC_GPIO2 = 8, | ||
14 | ADAU1373_PLL_SRC_GPIO3 = 9, | ||
15 | ADAU1373_PLL_SRC_GPIO4 = 10, | ||
16 | ADAU1373_PLL_SRC_MCLK2 = 11, | ||
17 | }; | ||
18 | |||
19 | enum adau1373_pll { | ||
20 | ADAU1373_PLL1 = 0, | ||
21 | ADAU1373_PLL2 = 1, | ||
22 | }; | ||
23 | |||
24 | enum adau1373_clk_src { | ||
25 | ADAU1373_CLK_SRC_PLL1 = 0, | ||
26 | ADAU1373_CLK_SRC_PLL2 = 1, | ||
27 | }; | ||
28 | |||
29 | #endif | ||
diff --git a/sound/soc/codecs/adav80x.c b/sound/soc/codecs/adav80x.c index 300c04b70e71..f9f08948e5e8 100644 --- a/sound/soc/codecs/adav80x.c +++ b/sound/soc/codecs/adav80x.c | |||
@@ -523,7 +523,8 @@ static int adav80x_hw_params(struct snd_pcm_substream *substream, | |||
523 | } | 523 | } |
524 | 524 | ||
525 | static int adav80x_set_sysclk(struct snd_soc_codec *codec, | 525 | static int adav80x_set_sysclk(struct snd_soc_codec *codec, |
526 | int clk_id, unsigned int freq, int dir) | 526 | int clk_id, int source, |
527 | unsigned int freq, int dir) | ||
527 | { | 528 | { |
528 | struct adav80x *adav80x = snd_soc_codec_get_drvdata(codec); | 529 | struct adav80x *adav80x = snd_soc_codec_get_drvdata(codec); |
529 | 530 | ||
diff --git a/sound/soc/codecs/alc5623.c b/sound/soc/codecs/alc5623.c index eecffb548947..05173159507e 100644 --- a/sound/soc/codecs/alc5623.c +++ b/sound/soc/codecs/alc5623.c | |||
@@ -41,7 +41,6 @@ MODULE_PARM_DESC(caps_charge, "ALC5623 cap charge time (msecs)"); | |||
41 | struct alc5623_priv { | 41 | struct alc5623_priv { |
42 | enum snd_soc_control_type control_type; | 42 | enum snd_soc_control_type control_type; |
43 | void *control_data; | 43 | void *control_data; |
44 | struct mutex mutex; | ||
45 | u8 id; | 44 | u8 id; |
46 | unsigned int sysclk; | 45 | unsigned int sysclk; |
47 | u16 reg_cache[ALC5623_VENDOR_ID2+2]; | 46 | u16 reg_cache[ALC5623_VENDOR_ID2+2]; |
@@ -1052,7 +1051,6 @@ static int alc5623_i2c_probe(struct i2c_client *client, | |||
1052 | i2c_set_clientdata(client, alc5623); | 1051 | i2c_set_clientdata(client, alc5623); |
1053 | alc5623->control_data = client; | 1052 | alc5623->control_data = client; |
1054 | alc5623->control_type = SND_SOC_I2C; | 1053 | alc5623->control_type = SND_SOC_I2C; |
1055 | mutex_init(&alc5623->mutex); | ||
1056 | 1054 | ||
1057 | ret = snd_soc_register_codec(&client->dev, | 1055 | ret = snd_soc_register_codec(&client->dev, |
1058 | &soc_codec_device_alc5623, &alc5623_dai, 1); | 1056 | &soc_codec_device_alc5623, &alc5623_dai, 1); |
diff --git a/sound/soc/codecs/sgtl5000.c b/sound/soc/codecs/sgtl5000.c index 7e4066e131e6..91130fbc6913 100644 --- a/sound/soc/codecs/sgtl5000.c +++ b/sound/soc/codecs/sgtl5000.c | |||
@@ -20,6 +20,7 @@ | |||
20 | #include <linux/regulator/driver.h> | 20 | #include <linux/regulator/driver.h> |
21 | #include <linux/regulator/machine.h> | 21 | #include <linux/regulator/machine.h> |
22 | #include <linux/regulator/consumer.h> | 22 | #include <linux/regulator/consumer.h> |
23 | #include <linux/of_device.h> | ||
23 | #include <sound/core.h> | 24 | #include <sound/core.h> |
24 | #include <sound/tlv.h> | 25 | #include <sound/tlv.h> |
25 | #include <sound/pcm.h> | 26 | #include <sound/pcm.h> |
@@ -1436,10 +1437,17 @@ static const struct i2c_device_id sgtl5000_id[] = { | |||
1436 | 1437 | ||
1437 | MODULE_DEVICE_TABLE(i2c, sgtl5000_id); | 1438 | MODULE_DEVICE_TABLE(i2c, sgtl5000_id); |
1438 | 1439 | ||
1440 | static const struct of_device_id sgtl5000_dt_ids[] = { | ||
1441 | { .compatible = "fsl,sgtl5000", }, | ||
1442 | { /* sentinel */ } | ||
1443 | }; | ||
1444 | MODULE_DEVICE_TABLE(of, sgtl5000_dt_ids); | ||
1445 | |||
1439 | static struct i2c_driver sgtl5000_i2c_driver = { | 1446 | static struct i2c_driver sgtl5000_i2c_driver = { |
1440 | .driver = { | 1447 | .driver = { |
1441 | .name = "sgtl5000", | 1448 | .name = "sgtl5000", |
1442 | .owner = THIS_MODULE, | 1449 | .owner = THIS_MODULE, |
1450 | .of_match_table = sgtl5000_dt_ids, | ||
1443 | }, | 1451 | }, |
1444 | .probe = sgtl5000_i2c_probe, | 1452 | .probe = sgtl5000_i2c_probe, |
1445 | .remove = __devexit_p(sgtl5000_i2c_remove), | 1453 | .remove = __devexit_p(sgtl5000_i2c_remove), |
diff --git a/sound/soc/codecs/sn95031.c b/sound/soc/codecs/sn95031.c index 84ffdebb8a8b..29945b004135 100644 --- a/sound/soc/codecs/sn95031.c +++ b/sound/soc/codecs/sn95031.c | |||
@@ -79,7 +79,7 @@ static void configure_adc(struct snd_soc_codec *sn95031_codec, int val) | |||
79 | */ | 79 | */ |
80 | static int find_free_channel(struct snd_soc_codec *sn95031_codec) | 80 | static int find_free_channel(struct snd_soc_codec *sn95031_codec) |
81 | { | 81 | { |
82 | int ret = 0, i, value; | 82 | int i, value; |
83 | 83 | ||
84 | /* check whether ADC is enabled */ | 84 | /* check whether ADC is enabled */ |
85 | value = snd_soc_read(sn95031_codec, SN95031_ADC1CNTL1); | 85 | value = snd_soc_read(sn95031_codec, SN95031_ADC1CNTL1); |
@@ -91,12 +91,10 @@ static int find_free_channel(struct snd_soc_codec *sn95031_codec) | |||
91 | for (i = 0; i < SN95031_ADC_CHANLS_MAX; i++) { | 91 | for (i = 0; i < SN95031_ADC_CHANLS_MAX; i++) { |
92 | value = snd_soc_read(sn95031_codec, | 92 | value = snd_soc_read(sn95031_codec, |
93 | SN95031_ADC_CHNL_START_ADDR + i); | 93 | SN95031_ADC_CHNL_START_ADDR + i); |
94 | if (value & SN95031_STOPBIT_MASK) { | 94 | if (value & SN95031_STOPBIT_MASK) |
95 | ret = i; | ||
96 | break; | 95 | break; |
97 | } | ||
98 | } | 96 | } |
99 | return (ret > SN95031_ADC_LOOP_MAX) ? (-EINVAL) : ret; | 97 | return (i == SN95031_ADC_CHANLS_MAX) ? (-EINVAL) : i; |
100 | } | 98 | } |
101 | 99 | ||
102 | /* Initialize the ADC for reading micbias values. Can sleep. */ | 100 | /* Initialize the ADC for reading micbias values. Can sleep. */ |
@@ -660,7 +658,7 @@ static int sn95031_pcm_spkr_mute(struct snd_soc_dai *dai, int mute) | |||
660 | return 0; | 658 | return 0; |
661 | } | 659 | } |
662 | 660 | ||
663 | int sn95031_pcm_hw_params(struct snd_pcm_substream *substream, | 661 | static int sn95031_pcm_hw_params(struct snd_pcm_substream *substream, |
664 | struct snd_pcm_hw_params *params, struct snd_soc_dai *dai) | 662 | struct snd_pcm_hw_params *params, struct snd_soc_dai *dai) |
665 | { | 663 | { |
666 | unsigned int format, rate; | 664 | unsigned int format, rate; |
diff --git a/sound/soc/codecs/ssm2602.c b/sound/soc/codecs/ssm2602.c index 9801cd7cfcb5..32d6c5141860 100644 --- a/sound/soc/codecs/ssm2602.c +++ b/sound/soc/codecs/ssm2602.c | |||
@@ -294,7 +294,6 @@ static int ssm2602_startup(struct snd_pcm_substream *substream, | |||
294 | struct snd_soc_pcm_runtime *rtd = substream->private_data; | 294 | struct snd_soc_pcm_runtime *rtd = substream->private_data; |
295 | struct snd_soc_codec *codec = rtd->codec; | 295 | struct snd_soc_codec *codec = rtd->codec; |
296 | struct ssm2602_priv *ssm2602 = snd_soc_codec_get_drvdata(codec); | 296 | struct ssm2602_priv *ssm2602 = snd_soc_codec_get_drvdata(codec); |
297 | struct i2c_client *i2c = codec->control_data; | ||
298 | struct snd_pcm_runtime *master_runtime; | 297 | struct snd_pcm_runtime *master_runtime; |
299 | 298 | ||
300 | /* The DAI has shared clocks so if we already have a playback or | 299 | /* The DAI has shared clocks so if we already have a playback or |
@@ -303,7 +302,7 @@ static int ssm2602_startup(struct snd_pcm_substream *substream, | |||
303 | */ | 302 | */ |
304 | if (ssm2602->master_substream) { | 303 | if (ssm2602->master_substream) { |
305 | master_runtime = ssm2602->master_substream->runtime; | 304 | master_runtime = ssm2602->master_substream->runtime; |
306 | dev_dbg(&i2c->dev, "Constraining to %d bits at %dHz\n", | 305 | dev_dbg(codec->dev, "Constraining to %d bits at %dHz\n", |
307 | master_runtime->sample_bits, | 306 | master_runtime->sample_bits, |
308 | master_runtime->rate); | 307 | master_runtime->rate); |
309 | 308 | ||
diff --git a/sound/soc/codecs/sta32x.c b/sound/soc/codecs/sta32x.c index fbd7eb9e61ce..5c7def3979c0 100644 --- a/sound/soc/codecs/sta32x.c +++ b/sound/soc/codecs/sta32x.c | |||
@@ -524,13 +524,17 @@ static int sta32x_hw_params(struct snd_pcm_substream *substream, | |||
524 | rate = params_rate(params); | 524 | rate = params_rate(params); |
525 | pr_debug("rate: %u\n", rate); | 525 | pr_debug("rate: %u\n", rate); |
526 | for (i = 0; i < ARRAY_SIZE(interpolation_ratios); i++) | 526 | for (i = 0; i < ARRAY_SIZE(interpolation_ratios); i++) |
527 | if (interpolation_ratios[i].fs == rate) | 527 | if (interpolation_ratios[i].fs == rate) { |
528 | ir = interpolation_ratios[i].ir; | 528 | ir = interpolation_ratios[i].ir; |
529 | break; | ||
530 | } | ||
529 | if (ir < 0) | 531 | if (ir < 0) |
530 | return -EINVAL; | 532 | return -EINVAL; |
531 | for (i = 0; mclk_ratios[ir][i].ratio; i++) | 533 | for (i = 0; mclk_ratios[ir][i].ratio; i++) |
532 | if (mclk_ratios[ir][i].ratio * rate == sta32x->mclk) | 534 | if (mclk_ratios[ir][i].ratio * rate == sta32x->mclk) { |
533 | mcs = mclk_ratios[ir][i].mcs; | 535 | mcs = mclk_ratios[ir][i].mcs; |
536 | break; | ||
537 | } | ||
534 | if (mcs < 0) | 538 | if (mcs < 0) |
535 | return -EINVAL; | 539 | return -EINVAL; |
536 | 540 | ||
@@ -808,6 +812,7 @@ static int sta32x_remove(struct snd_soc_codec *codec) | |||
808 | { | 812 | { |
809 | struct sta32x_priv *sta32x = snd_soc_codec_get_drvdata(codec); | 813 | struct sta32x_priv *sta32x = snd_soc_codec_get_drvdata(codec); |
810 | 814 | ||
815 | sta32x_set_bias_level(codec, SND_SOC_BIAS_OFF); | ||
811 | regulator_bulk_disable(ARRAY_SIZE(sta32x->supplies), sta32x->supplies); | 816 | regulator_bulk_disable(ARRAY_SIZE(sta32x->supplies), sta32x->supplies); |
812 | regulator_bulk_free(ARRAY_SIZE(sta32x->supplies), sta32x->supplies); | 817 | regulator_bulk_free(ARRAY_SIZE(sta32x->supplies), sta32x->supplies); |
813 | 818 | ||
@@ -867,18 +872,8 @@ static __devinit int sta32x_i2c_probe(struct i2c_client *i2c, | |||
867 | static __devexit int sta32x_i2c_remove(struct i2c_client *client) | 872 | static __devexit int sta32x_i2c_remove(struct i2c_client *client) |
868 | { | 873 | { |
869 | struct sta32x_priv *sta32x = i2c_get_clientdata(client); | 874 | struct sta32x_priv *sta32x = i2c_get_clientdata(client); |
870 | struct snd_soc_codec *codec = sta32x->codec; | ||
871 | |||
872 | if (codec) | ||
873 | sta32x_set_bias_level(codec, SND_SOC_BIAS_OFF); | ||
874 | |||
875 | regulator_bulk_free(ARRAY_SIZE(sta32x->supplies), sta32x->supplies); | ||
876 | |||
877 | if (codec) { | ||
878 | snd_soc_unregister_codec(&client->dev); | ||
879 | snd_soc_codec_set_drvdata(codec, NULL); | ||
880 | } | ||
881 | 875 | ||
876 | snd_soc_unregister_codec(&client->dev); | ||
882 | kfree(sta32x); | 877 | kfree(sta32x); |
883 | return 0; | 878 | return 0; |
884 | } | 879 | } |
diff --git a/sound/soc/codecs/tlv320dac33.c b/sound/soc/codecs/tlv320dac33.c index faa5e9fb1471..243d17711211 100644 --- a/sound/soc/codecs/tlv320dac33.c +++ b/sound/soc/codecs/tlv320dac33.c | |||
@@ -1431,7 +1431,7 @@ static int dac33_soc_probe(struct snd_soc_codec *codec) | |||
1431 | /* Check if the IRQ number is valid and request it */ | 1431 | /* Check if the IRQ number is valid and request it */ |
1432 | if (dac33->irq >= 0) { | 1432 | if (dac33->irq >= 0) { |
1433 | ret = request_irq(dac33->irq, dac33_interrupt_handler, | 1433 | ret = request_irq(dac33->irq, dac33_interrupt_handler, |
1434 | IRQF_TRIGGER_RISING | IRQF_DISABLED, | 1434 | IRQF_TRIGGER_RISING, |
1435 | codec->name, codec); | 1435 | codec->name, codec); |
1436 | if (ret < 0) { | 1436 | if (ret < 0) { |
1437 | dev_err(codec->dev, "Could not request IRQ%d (%d)\n", | 1437 | dev_err(codec->dev, "Could not request IRQ%d (%d)\n", |
diff --git a/sound/soc/codecs/tpa6130a2.c b/sound/soc/codecs/tpa6130a2.c index 239e0c461068..b2572c451c35 100644 --- a/sound/soc/codecs/tpa6130a2.c +++ b/sound/soc/codecs/tpa6130a2.c | |||
@@ -446,7 +446,6 @@ err_regulator: | |||
446 | gpio_free(data->power_gpio); | 446 | gpio_free(data->power_gpio); |
447 | err_gpio: | 447 | err_gpio: |
448 | kfree(data); | 448 | kfree(data); |
449 | i2c_set_clientdata(tpa6130a2_client, NULL); | ||
450 | tpa6130a2_client = NULL; | 449 | tpa6130a2_client = NULL; |
451 | 450 | ||
452 | return ret; | 451 | return ret; |
diff --git a/sound/soc/codecs/twl6040.c b/sound/soc/codecs/twl6040.c index 443032b3b329..81645c632447 100644 --- a/sound/soc/codecs/twl6040.c +++ b/sound/soc/codecs/twl6040.c | |||
@@ -118,8 +118,8 @@ static const u8 twl6040_reg[TWL6040_CACHEREGNUM] = { | |||
118 | 0x4A, /* TWL6040_LPPLLDIV 0x09 */ | 118 | 0x4A, /* TWL6040_LPPLLDIV 0x09 */ |
119 | 0x00, /* TWL6040_AMICBCTL 0x0A */ | 119 | 0x00, /* TWL6040_AMICBCTL 0x0A */ |
120 | 0x00, /* TWL6040_DMICBCTL 0x0B */ | 120 | 0x00, /* TWL6040_DMICBCTL 0x0B */ |
121 | 0x18, /* TWL6040_MICLCTL 0x0C - No input selected on Left Mic */ | 121 | 0x00, /* TWL6040_MICLCTL 0x0C */ |
122 | 0x18, /* TWL6040_MICRCTL 0x0D - No input selected on Right Mic */ | 122 | 0x00, /* TWL6040_MICRCTL 0x0D */ |
123 | 0x00, /* TWL6040_MICGAIN 0x0E */ | 123 | 0x00, /* TWL6040_MICGAIN 0x0E */ |
124 | 0x1B, /* TWL6040_LINEGAIN 0x0F */ | 124 | 0x1B, /* TWL6040_LINEGAIN 0x0F */ |
125 | 0x00, /* TWL6040_HSLCTL 0x10 */ | 125 | 0x00, /* TWL6040_HSLCTL 0x10 */ |
@@ -155,41 +155,8 @@ static const u8 twl6040_reg[TWL6040_CACHEREGNUM] = { | |||
155 | 0x00, /* TWL6040_STATUS (ro) 0x2E */ | 155 | 0x00, /* TWL6040_STATUS (ro) 0x2E */ |
156 | }; | 156 | }; |
157 | 157 | ||
158 | /* | 158 | /* List of registers to be restored after power up */ |
159 | * twl6040 vio/gnd registers: | 159 | static const int twl6040_restore_list[] = { |
160 | * registers under vio/gnd supply can be accessed | ||
161 | * before the power-up sequence, after NRESPWRON goes high | ||
162 | */ | ||
163 | static const int twl6040_vio_reg[TWL6040_VIOREGNUM] = { | ||
164 | TWL6040_REG_ASICID, | ||
165 | TWL6040_REG_ASICREV, | ||
166 | TWL6040_REG_INTID, | ||
167 | TWL6040_REG_INTMR, | ||
168 | TWL6040_REG_NCPCTL, | ||
169 | TWL6040_REG_LDOCTL, | ||
170 | TWL6040_REG_AMICBCTL, | ||
171 | TWL6040_REG_DMICBCTL, | ||
172 | TWL6040_REG_HKCTL1, | ||
173 | TWL6040_REG_HKCTL2, | ||
174 | TWL6040_REG_GPOCTL, | ||
175 | TWL6040_REG_TRIM1, | ||
176 | TWL6040_REG_TRIM2, | ||
177 | TWL6040_REG_TRIM3, | ||
178 | TWL6040_REG_HSOTRIM, | ||
179 | TWL6040_REG_HFOTRIM, | ||
180 | TWL6040_REG_ACCCTL, | ||
181 | TWL6040_REG_STATUS, | ||
182 | }; | ||
183 | |||
184 | /* | ||
185 | * twl6040 vdd/vss registers: | ||
186 | * registers under vdd/vss supplies can only be accessed | ||
187 | * after the power-up sequence | ||
188 | */ | ||
189 | static const int twl6040_vdd_reg[TWL6040_VDDREGNUM] = { | ||
190 | TWL6040_REG_HPPLLCTL, | ||
191 | TWL6040_REG_LPPLLCTL, | ||
192 | TWL6040_REG_LPPLLDIV, | ||
193 | TWL6040_REG_MICLCTL, | 160 | TWL6040_REG_MICLCTL, |
194 | TWL6040_REG_MICRCTL, | 161 | TWL6040_REG_MICRCTL, |
195 | TWL6040_REG_MICGAIN, | 162 | TWL6040_REG_MICGAIN, |
@@ -202,12 +169,6 @@ static const int twl6040_vdd_reg[TWL6040_VDDREGNUM] = { | |||
202 | TWL6040_REG_HFLGAIN, | 169 | TWL6040_REG_HFLGAIN, |
203 | TWL6040_REG_HFRCTL, | 170 | TWL6040_REG_HFRCTL, |
204 | TWL6040_REG_HFRGAIN, | 171 | TWL6040_REG_HFRGAIN, |
205 | TWL6040_REG_VIBCTLL, | ||
206 | TWL6040_REG_VIBDATL, | ||
207 | TWL6040_REG_VIBCTLR, | ||
208 | TWL6040_REG_VIBDATR, | ||
209 | TWL6040_REG_ALB, | ||
210 | TWL6040_REG_DLB, | ||
211 | }; | 172 | }; |
212 | 173 | ||
213 | /* set of rates for each pll: low-power and high-performance */ | 174 | /* set of rates for each pll: low-power and high-performance */ |
@@ -296,56 +257,27 @@ static int twl6040_write(struct snd_soc_codec *codec, | |||
296 | return twl6040_reg_write(twl6040, reg, value); | 257 | return twl6040_reg_write(twl6040, reg, value); |
297 | } | 258 | } |
298 | 259 | ||
299 | static void twl6040_init_vio_regs(struct snd_soc_codec *codec) | 260 | static void twl6040_init_chip(struct snd_soc_codec *codec) |
300 | { | 261 | { |
301 | u8 *cache = codec->reg_cache; | 262 | struct twl6040 *twl6040 = codec->control_data; |
302 | int reg, i; | 263 | u8 val; |
303 | 264 | ||
304 | for (i = 0; i < TWL6040_VIOREGNUM; i++) { | 265 | val = twl6040_get_revid(twl6040); |
305 | reg = twl6040_vio_reg[i]; | 266 | twl6040_write_reg_cache(codec, TWL6040_REG_ASICREV, val); |
306 | /* | 267 | |
307 | * skip read-only registers (ASICID, ASICREV, STATUS) | 268 | /* Change chip defaults */ |
308 | * and registers shared among MFD children | 269 | /* No imput selected for microphone amplifiers */ |
309 | */ | 270 | twl6040_write_reg_cache(codec, TWL6040_REG_MICLCTL, 0x18); |
310 | switch (reg) { | 271 | twl6040_write_reg_cache(codec, TWL6040_REG_MICRCTL, 0x18); |
311 | case TWL6040_REG_ASICID: | ||
312 | case TWL6040_REG_ASICREV: | ||
313 | case TWL6040_REG_INTID: | ||
314 | case TWL6040_REG_INTMR: | ||
315 | case TWL6040_REG_NCPCTL: | ||
316 | case TWL6040_REG_LDOCTL: | ||
317 | case TWL6040_REG_GPOCTL: | ||
318 | case TWL6040_REG_ACCCTL: | ||
319 | case TWL6040_REG_STATUS: | ||
320 | continue; | ||
321 | default: | ||
322 | break; | ||
323 | } | ||
324 | twl6040_write(codec, reg, cache[reg]); | ||
325 | } | ||
326 | } | 272 | } |
327 | 273 | ||
328 | static void twl6040_init_vdd_regs(struct snd_soc_codec *codec) | 274 | static void twl6040_restore_regs(struct snd_soc_codec *codec) |
329 | { | 275 | { |
330 | u8 *cache = codec->reg_cache; | 276 | u8 *cache = codec->reg_cache; |
331 | int reg, i; | 277 | int reg, i; |
332 | 278 | ||
333 | for (i = 0; i < TWL6040_VDDREGNUM; i++) { | 279 | for (i = 0; i < ARRAY_SIZE(twl6040_restore_list); i++) { |
334 | reg = twl6040_vdd_reg[i]; | 280 | reg = twl6040_restore_list[i]; |
335 | /* skip vibra and PLL registers */ | ||
336 | switch (reg) { | ||
337 | case TWL6040_REG_VIBCTLL: | ||
338 | case TWL6040_REG_VIBDATL: | ||
339 | case TWL6040_REG_VIBCTLR: | ||
340 | case TWL6040_REG_VIBDATR: | ||
341 | case TWL6040_REG_HPPLLCTL: | ||
342 | case TWL6040_REG_LPPLLCTL: | ||
343 | case TWL6040_REG_LPPLLDIV: | ||
344 | continue; | ||
345 | default: | ||
346 | break; | ||
347 | } | ||
348 | |||
349 | twl6040_write(codec, reg, cache[reg]); | 281 | twl6040_write(codec, reg, cache[reg]); |
350 | } | 282 | } |
351 | } | 283 | } |
@@ -1325,8 +1257,7 @@ static int twl6040_set_bias_level(struct snd_soc_codec *codec, | |||
1325 | 1257 | ||
1326 | priv->codec_powered = 1; | 1258 | priv->codec_powered = 1; |
1327 | 1259 | ||
1328 | /* initialize vdd/vss registers with reg_cache */ | 1260 | twl6040_restore_regs(codec); |
1329 | twl6040_init_vdd_regs(codec); | ||
1330 | 1261 | ||
1331 | /* Set external boost GPO */ | 1262 | /* Set external boost GPO */ |
1332 | twl6040_write(codec, TWL6040_REG_GPOCTL, 0x02); | 1263 | twl6040_write(codec, TWL6040_REG_GPOCTL, 0x02); |
@@ -1468,7 +1399,7 @@ static struct snd_soc_dai_driver twl6040_dai[] = { | |||
1468 | .playback = { | 1399 | .playback = { |
1469 | .stream_name = "Playback", | 1400 | .stream_name = "Playback", |
1470 | .channels_min = 1, | 1401 | .channels_min = 1, |
1471 | .channels_max = 2, | 1402 | .channels_max = 5, |
1472 | .rates = TWL6040_RATES, | 1403 | .rates = TWL6040_RATES, |
1473 | .formats = TWL6040_FORMATS, | 1404 | .formats = TWL6040_FORMATS, |
1474 | }, | 1405 | }, |
@@ -1518,8 +1449,8 @@ static struct snd_soc_dai_driver twl6040_dai[] = { | |||
1518 | .name = "twl6040-vib", | 1449 | .name = "twl6040-vib", |
1519 | .playback = { | 1450 | .playback = { |
1520 | .stream_name = "Vibra Playback", | 1451 | .stream_name = "Vibra Playback", |
1521 | .channels_min = 2, | 1452 | .channels_min = 1, |
1522 | .channels_max = 2, | 1453 | .channels_max = 1, |
1523 | .rates = SNDRV_PCM_RATE_CONTINUOUS, | 1454 | .rates = SNDRV_PCM_RATE_CONTINUOUS, |
1524 | .formats = TWL6040_FORMATS, | 1455 | .formats = TWL6040_FORMATS, |
1525 | }, | 1456 | }, |
@@ -1620,8 +1551,7 @@ static int twl6040_probe(struct snd_soc_codec *codec) | |||
1620 | goto plugirq_err; | 1551 | goto plugirq_err; |
1621 | } | 1552 | } |
1622 | 1553 | ||
1623 | /* init vio registers */ | 1554 | twl6040_init_chip(codec); |
1624 | twl6040_init_vio_regs(codec); | ||
1625 | 1555 | ||
1626 | /* power on device */ | 1556 | /* power on device */ |
1627 | ret = twl6040_set_bias_level(codec, SND_SOC_BIAS_STANDBY); | 1557 | ret = twl6040_set_bias_level(codec, SND_SOC_BIAS_STANDBY); |
diff --git a/sound/soc/codecs/wm1250-ev1.c b/sound/soc/codecs/wm1250-ev1.c index bcc208967917..4523c4cec02b 100644 --- a/sound/soc/codecs/wm1250-ev1.c +++ b/sound/soc/codecs/wm1250-ev1.c | |||
@@ -56,8 +56,26 @@ static struct snd_soc_codec_driver soc_codec_dev_wm1250_ev1 = { | |||
56 | }; | 56 | }; |
57 | 57 | ||
58 | static int __devinit wm1250_ev1_probe(struct i2c_client *i2c, | 58 | static int __devinit wm1250_ev1_probe(struct i2c_client *i2c, |
59 | const struct i2c_device_id *id) | 59 | const struct i2c_device_id *i2c_id) |
60 | { | 60 | { |
61 | int id, board, rev; | ||
62 | |||
63 | board = i2c_smbus_read_byte_data(i2c, 0); | ||
64 | if (board < 0) { | ||
65 | dev_err(&i2c->dev, "Failed to read ID: %d\n", board); | ||
66 | return board; | ||
67 | } | ||
68 | |||
69 | id = (board & 0xfe) >> 2; | ||
70 | rev = board & 0x3; | ||
71 | |||
72 | if (id != 1) { | ||
73 | dev_err(&i2c->dev, "Unknown board ID %d\n", id); | ||
74 | return -ENODEV; | ||
75 | } | ||
76 | |||
77 | dev_info(&i2c->dev, "revision %d\n", rev + 1); | ||
78 | |||
61 | return snd_soc_register_codec(&i2c->dev, &soc_codec_dev_wm1250_ev1, | 79 | return snd_soc_register_codec(&i2c->dev, &soc_codec_dev_wm1250_ev1, |
62 | &wm1250_ev1_dai, 1); | 80 | &wm1250_ev1_dai, 1); |
63 | } | 81 | } |
diff --git a/sound/soc/codecs/wm8510.c b/sound/soc/codecs/wm8510.c index db0dced74843..55a4c830e111 100644 --- a/sound/soc/codecs/wm8510.c +++ b/sound/soc/codecs/wm8510.c | |||
@@ -20,6 +20,7 @@ | |||
20 | #include <linux/platform_device.h> | 20 | #include <linux/platform_device.h> |
21 | #include <linux/spi/spi.h> | 21 | #include <linux/spi/spi.h> |
22 | #include <linux/slab.h> | 22 | #include <linux/slab.h> |
23 | #include <linux/of_device.h> | ||
23 | #include <sound/core.h> | 24 | #include <sound/core.h> |
24 | #include <sound/pcm.h> | 25 | #include <sound/pcm.h> |
25 | #include <sound/pcm_params.h> | 26 | #include <sound/pcm_params.h> |
@@ -598,6 +599,11 @@ static struct snd_soc_codec_driver soc_codec_dev_wm8510 = { | |||
598 | .reg_cache_default =wm8510_reg, | 599 | .reg_cache_default =wm8510_reg, |
599 | }; | 600 | }; |
600 | 601 | ||
602 | static const struct of_device_id wm8510_of_match[] = { | ||
603 | { .compatible = "wlf,wm8510" }, | ||
604 | { }, | ||
605 | }; | ||
606 | |||
601 | #if defined(CONFIG_SPI_MASTER) | 607 | #if defined(CONFIG_SPI_MASTER) |
602 | static int __devinit wm8510_spi_probe(struct spi_device *spi) | 608 | static int __devinit wm8510_spi_probe(struct spi_device *spi) |
603 | { | 609 | { |
@@ -628,6 +634,7 @@ static struct spi_driver wm8510_spi_driver = { | |||
628 | .driver = { | 634 | .driver = { |
629 | .name = "wm8510", | 635 | .name = "wm8510", |
630 | .owner = THIS_MODULE, | 636 | .owner = THIS_MODULE, |
637 | .of_match_table = wm8510_of_match, | ||
631 | }, | 638 | }, |
632 | .probe = wm8510_spi_probe, | 639 | .probe = wm8510_spi_probe, |
633 | .remove = __devexit_p(wm8510_spi_remove), | 640 | .remove = __devexit_p(wm8510_spi_remove), |
@@ -671,6 +678,7 @@ static struct i2c_driver wm8510_i2c_driver = { | |||
671 | .driver = { | 678 | .driver = { |
672 | .name = "wm8510-codec", | 679 | .name = "wm8510-codec", |
673 | .owner = THIS_MODULE, | 680 | .owner = THIS_MODULE, |
681 | .of_match_table = wm8510_of_match, | ||
674 | }, | 682 | }, |
675 | .probe = wm8510_i2c_probe, | 683 | .probe = wm8510_i2c_probe, |
676 | .remove = __devexit_p(wm8510_i2c_remove), | 684 | .remove = __devexit_p(wm8510_i2c_remove), |
diff --git a/sound/soc/codecs/wm8523.c b/sound/soc/codecs/wm8523.c index 4fd4d8dca0fc..5355a7a944f7 100644 --- a/sound/soc/codecs/wm8523.c +++ b/sound/soc/codecs/wm8523.c | |||
@@ -20,6 +20,7 @@ | |||
20 | #include <linux/platform_device.h> | 20 | #include <linux/platform_device.h> |
21 | #include <linux/regulator/consumer.h> | 21 | #include <linux/regulator/consumer.h> |
22 | #include <linux/slab.h> | 22 | #include <linux/slab.h> |
23 | #include <linux/of_device.h> | ||
23 | #include <sound/core.h> | 24 | #include <sound/core.h> |
24 | #include <sound/pcm.h> | 25 | #include <sound/pcm.h> |
25 | #include <sound/pcm_params.h> | 26 | #include <sound/pcm_params.h> |
@@ -84,7 +85,7 @@ static const char *wm8523_zd_count_text[] = { | |||
84 | static const struct soc_enum wm8523_zc_count = | 85 | static const struct soc_enum wm8523_zc_count = |
85 | SOC_ENUM_SINGLE(WM8523_ZERO_DETECT, 0, 2, wm8523_zd_count_text); | 86 | SOC_ENUM_SINGLE(WM8523_ZERO_DETECT, 0, 2, wm8523_zd_count_text); |
86 | 87 | ||
87 | static const struct snd_kcontrol_new wm8523_snd_controls[] = { | 88 | static const struct snd_kcontrol_new wm8523_controls[] = { |
88 | SOC_DOUBLE_R_TLV("Playback Volume", WM8523_DAC_GAINL, WM8523_DAC_GAINR, | 89 | SOC_DOUBLE_R_TLV("Playback Volume", WM8523_DAC_GAINL, WM8523_DAC_GAINR, |
89 | 0, 448, 0, dac_tlv), | 90 | 0, 448, 0, dac_tlv), |
90 | SOC_SINGLE("ZC Switch", WM8523_DAC_CTRL3, 4, 1, 0), | 91 | SOC_SINGLE("ZC Switch", WM8523_DAC_CTRL3, 4, 1, 0), |
@@ -101,22 +102,11 @@ SND_SOC_DAPM_OUTPUT("LINEVOUTL"), | |||
101 | SND_SOC_DAPM_OUTPUT("LINEVOUTR"), | 102 | SND_SOC_DAPM_OUTPUT("LINEVOUTR"), |
102 | }; | 103 | }; |
103 | 104 | ||
104 | static const struct snd_soc_dapm_route intercon[] = { | 105 | static const struct snd_soc_dapm_route wm8523_dapm_routes[] = { |
105 | { "LINEVOUTL", NULL, "DAC" }, | 106 | { "LINEVOUTL", NULL, "DAC" }, |
106 | { "LINEVOUTR", NULL, "DAC" }, | 107 | { "LINEVOUTR", NULL, "DAC" }, |
107 | }; | 108 | }; |
108 | 109 | ||
109 | static int wm8523_add_widgets(struct snd_soc_codec *codec) | ||
110 | { | ||
111 | struct snd_soc_dapm_context *dapm = &codec->dapm; | ||
112 | |||
113 | snd_soc_dapm_new_controls(dapm, wm8523_dapm_widgets, | ||
114 | ARRAY_SIZE(wm8523_dapm_widgets)); | ||
115 | snd_soc_dapm_add_routes(dapm, intercon, ARRAY_SIZE(intercon)); | ||
116 | |||
117 | return 0; | ||
118 | } | ||
119 | |||
120 | static struct { | 110 | static struct { |
121 | int value; | 111 | int value; |
122 | int ratio; | 112 | int ratio; |
@@ -479,10 +469,6 @@ static int wm8523_probe(struct snd_soc_codec *codec) | |||
479 | /* Bias level configuration will have done an extra enable */ | 469 | /* Bias level configuration will have done an extra enable */ |
480 | regulator_bulk_disable(ARRAY_SIZE(wm8523->supplies), wm8523->supplies); | 470 | regulator_bulk_disable(ARRAY_SIZE(wm8523->supplies), wm8523->supplies); |
481 | 471 | ||
482 | snd_soc_add_controls(codec, wm8523_snd_controls, | ||
483 | ARRAY_SIZE(wm8523_snd_controls)); | ||
484 | wm8523_add_widgets(codec); | ||
485 | |||
486 | return 0; | 472 | return 0; |
487 | 473 | ||
488 | err_enable: | 474 | err_enable: |
@@ -512,6 +498,18 @@ static struct snd_soc_codec_driver soc_codec_dev_wm8523 = { | |||
512 | .reg_word_size = sizeof(u16), | 498 | .reg_word_size = sizeof(u16), |
513 | .reg_cache_default = wm8523_reg, | 499 | .reg_cache_default = wm8523_reg, |
514 | .volatile_register = wm8523_volatile_register, | 500 | .volatile_register = wm8523_volatile_register, |
501 | |||
502 | .controls = wm8523_controls, | ||
503 | .num_controls = ARRAY_SIZE(wm8523_controls), | ||
504 | .dapm_widgets = wm8523_dapm_widgets, | ||
505 | .num_dapm_widgets = ARRAY_SIZE(wm8523_dapm_widgets), | ||
506 | .dapm_routes = wm8523_dapm_routes, | ||
507 | .num_dapm_routes = ARRAY_SIZE(wm8523_dapm_routes), | ||
508 | }; | ||
509 | |||
510 | static const struct of_device_id wm8523_of_match[] = { | ||
511 | { .compatible = "wlf,wm8523" }, | ||
512 | { }, | ||
515 | }; | 513 | }; |
516 | 514 | ||
517 | #if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE) | 515 | #if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE) |
@@ -551,8 +549,9 @@ MODULE_DEVICE_TABLE(i2c, wm8523_i2c_id); | |||
551 | 549 | ||
552 | static struct i2c_driver wm8523_i2c_driver = { | 550 | static struct i2c_driver wm8523_i2c_driver = { |
553 | .driver = { | 551 | .driver = { |
554 | .name = "wm8523-codec", | 552 | .name = "wm8523", |
555 | .owner = THIS_MODULE, | 553 | .owner = THIS_MODULE, |
554 | .of_match_table = wm8523_of_match, | ||
556 | }, | 555 | }, |
557 | .probe = wm8523_i2c_probe, | 556 | .probe = wm8523_i2c_probe, |
558 | .remove = __devexit_p(wm8523_i2c_remove), | 557 | .remove = __devexit_p(wm8523_i2c_remove), |
diff --git a/sound/soc/codecs/wm8580.c b/sound/soc/codecs/wm8580.c index 4bbc0a79f01e..4664c3a76c78 100644 --- a/sound/soc/codecs/wm8580.c +++ b/sound/soc/codecs/wm8580.c | |||
@@ -26,6 +26,7 @@ | |||
26 | #include <linux/platform_device.h> | 26 | #include <linux/platform_device.h> |
27 | #include <linux/regulator/consumer.h> | 27 | #include <linux/regulator/consumer.h> |
28 | #include <linux/slab.h> | 28 | #include <linux/slab.h> |
29 | #include <linux/of_device.h> | ||
29 | 30 | ||
30 | #include <sound/core.h> | 31 | #include <sound/core.h> |
31 | #include <sound/pcm.h> | 32 | #include <sound/pcm.h> |
@@ -907,6 +908,11 @@ static struct snd_soc_codec_driver soc_codec_dev_wm8580 = { | |||
907 | .reg_cache_default = wm8580_reg, | 908 | .reg_cache_default = wm8580_reg, |
908 | }; | 909 | }; |
909 | 910 | ||
911 | static const struct of_device_id wm8580_of_match[] = { | ||
912 | { .compatible = "wlf,wm8580" }, | ||
913 | { }, | ||
914 | }; | ||
915 | |||
910 | #if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE) | 916 | #if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE) |
911 | static int wm8580_i2c_probe(struct i2c_client *i2c, | 917 | static int wm8580_i2c_probe(struct i2c_client *i2c, |
912 | const struct i2c_device_id *id) | 918 | const struct i2c_device_id *id) |
@@ -943,8 +949,9 @@ MODULE_DEVICE_TABLE(i2c, wm8580_i2c_id); | |||
943 | 949 | ||
944 | static struct i2c_driver wm8580_i2c_driver = { | 950 | static struct i2c_driver wm8580_i2c_driver = { |
945 | .driver = { | 951 | .driver = { |
946 | .name = "wm8580-codec", | 952 | .name = "wm8580", |
947 | .owner = THIS_MODULE, | 953 | .owner = THIS_MODULE, |
954 | .of_match_table = wm8580_of_match, | ||
948 | }, | 955 | }, |
949 | .probe = wm8580_i2c_probe, | 956 | .probe = wm8580_i2c_probe, |
950 | .remove = wm8580_i2c_remove, | 957 | .remove = wm8580_i2c_remove, |
diff --git a/sound/soc/codecs/wm8711.c b/sound/soc/codecs/wm8711.c index a537e4af6ae7..8457d3cb5962 100644 --- a/sound/soc/codecs/wm8711.c +++ b/sound/soc/codecs/wm8711.c | |||
@@ -21,6 +21,7 @@ | |||
21 | #include <linux/platform_device.h> | 21 | #include <linux/platform_device.h> |
22 | #include <linux/spi/spi.h> | 22 | #include <linux/spi/spi.h> |
23 | #include <linux/slab.h> | 23 | #include <linux/slab.h> |
24 | #include <linux/of_device.h> | ||
24 | #include <sound/core.h> | 25 | #include <sound/core.h> |
25 | #include <sound/pcm.h> | 26 | #include <sound/pcm.h> |
26 | #include <sound/pcm_params.h> | 27 | #include <sound/pcm_params.h> |
@@ -414,6 +415,12 @@ static struct snd_soc_codec_driver soc_codec_dev_wm8711 = { | |||
414 | .num_dapm_routes = ARRAY_SIZE(wm8711_intercon), | 415 | .num_dapm_routes = ARRAY_SIZE(wm8711_intercon), |
415 | }; | 416 | }; |
416 | 417 | ||
418 | static const struct of_device_id wm8711_of_match[] = { | ||
419 | { .compatible = "wlf,wm8711", }, | ||
420 | { } | ||
421 | }; | ||
422 | MODULE_DEVICE_TABLE(of, wm8711_of_match); | ||
423 | |||
417 | #if defined(CONFIG_SPI_MASTER) | 424 | #if defined(CONFIG_SPI_MASTER) |
418 | static int __devinit wm8711_spi_probe(struct spi_device *spi) | 425 | static int __devinit wm8711_spi_probe(struct spi_device *spi) |
419 | { | 426 | { |
@@ -443,8 +450,9 @@ static int __devexit wm8711_spi_remove(struct spi_device *spi) | |||
443 | 450 | ||
444 | static struct spi_driver wm8711_spi_driver = { | 451 | static struct spi_driver wm8711_spi_driver = { |
445 | .driver = { | 452 | .driver = { |
446 | .name = "wm8711-codec", | 453 | .name = "wm8711", |
447 | .owner = THIS_MODULE, | 454 | .owner = THIS_MODULE, |
455 | .of_match_table = wm8711_of_match, | ||
448 | }, | 456 | }, |
449 | .probe = wm8711_spi_probe, | 457 | .probe = wm8711_spi_probe, |
450 | .remove = __devexit_p(wm8711_spi_remove), | 458 | .remove = __devexit_p(wm8711_spi_remove), |
@@ -487,8 +495,9 @@ MODULE_DEVICE_TABLE(i2c, wm8711_i2c_id); | |||
487 | 495 | ||
488 | static struct i2c_driver wm8711_i2c_driver = { | 496 | static struct i2c_driver wm8711_i2c_driver = { |
489 | .driver = { | 497 | .driver = { |
490 | .name = "wm8711-codec", | 498 | .name = "wm8711", |
491 | .owner = THIS_MODULE, | 499 | .owner = THIS_MODULE, |
500 | .of_match_table = wm8711_of_match, | ||
492 | }, | 501 | }, |
493 | .probe = wm8711_i2c_probe, | 502 | .probe = wm8711_i2c_probe, |
494 | .remove = __devexit_p(wm8711_i2c_remove), | 503 | .remove = __devexit_p(wm8711_i2c_remove), |
diff --git a/sound/soc/codecs/wm8728.c b/sound/soc/codecs/wm8728.c index 86d4718d3a76..04b027efd5c0 100644 --- a/sound/soc/codecs/wm8728.c +++ b/sound/soc/codecs/wm8728.c | |||
@@ -19,6 +19,7 @@ | |||
19 | #include <linux/platform_device.h> | 19 | #include <linux/platform_device.h> |
20 | #include <linux/spi/spi.h> | 20 | #include <linux/spi/spi.h> |
21 | #include <linux/slab.h> | 21 | #include <linux/slab.h> |
22 | #include <linux/of_device.h> | ||
22 | #include <sound/core.h> | 23 | #include <sound/core.h> |
23 | #include <sound/pcm.h> | 24 | #include <sound/pcm.h> |
24 | #include <sound/pcm_params.h> | 25 | #include <sound/pcm_params.h> |
@@ -269,6 +270,12 @@ static struct snd_soc_codec_driver soc_codec_dev_wm8728 = { | |||
269 | .num_dapm_routes = ARRAY_SIZE(wm8728_intercon), | 270 | .num_dapm_routes = ARRAY_SIZE(wm8728_intercon), |
270 | }; | 271 | }; |
271 | 272 | ||
273 | static const struct of_device_id wm8728_of_match[] = { | ||
274 | { .compatible = "wlf,wm8728", }, | ||
275 | { } | ||
276 | }; | ||
277 | MODULE_DEVICE_TABLE(of, wm8728_of_match); | ||
278 | |||
272 | #if defined(CONFIG_SPI_MASTER) | 279 | #if defined(CONFIG_SPI_MASTER) |
273 | static int __devinit wm8728_spi_probe(struct spi_device *spi) | 280 | static int __devinit wm8728_spi_probe(struct spi_device *spi) |
274 | { | 281 | { |
@@ -298,8 +305,9 @@ static int __devexit wm8728_spi_remove(struct spi_device *spi) | |||
298 | 305 | ||
299 | static struct spi_driver wm8728_spi_driver = { | 306 | static struct spi_driver wm8728_spi_driver = { |
300 | .driver = { | 307 | .driver = { |
301 | .name = "wm8728-codec", | 308 | .name = "wm8728", |
302 | .owner = THIS_MODULE, | 309 | .owner = THIS_MODULE, |
310 | .of_match_table = wm8728_of_match, | ||
303 | }, | 311 | }, |
304 | .probe = wm8728_spi_probe, | 312 | .probe = wm8728_spi_probe, |
305 | .remove = __devexit_p(wm8728_spi_remove), | 313 | .remove = __devexit_p(wm8728_spi_remove), |
@@ -342,8 +350,9 @@ MODULE_DEVICE_TABLE(i2c, wm8728_i2c_id); | |||
342 | 350 | ||
343 | static struct i2c_driver wm8728_i2c_driver = { | 351 | static struct i2c_driver wm8728_i2c_driver = { |
344 | .driver = { | 352 | .driver = { |
345 | .name = "wm8728-codec", | 353 | .name = "wm8728", |
346 | .owner = THIS_MODULE, | 354 | .owner = THIS_MODULE, |
355 | .of_match_table = wm8728_of_match, | ||
347 | }, | 356 | }, |
348 | .probe = wm8728_i2c_probe, | 357 | .probe = wm8728_i2c_probe, |
349 | .remove = __devexit_p(wm8728_i2c_remove), | 358 | .remove = __devexit_p(wm8728_i2c_remove), |
diff --git a/sound/soc/codecs/wm8731.c b/sound/soc/codecs/wm8731.c index 76b4361e9b80..f76b6fc6766a 100644 --- a/sound/soc/codecs/wm8731.c +++ b/sound/soc/codecs/wm8731.c | |||
@@ -22,6 +22,7 @@ | |||
22 | #include <linux/platform_device.h> | 22 | #include <linux/platform_device.h> |
23 | #include <linux/regulator/consumer.h> | 23 | #include <linux/regulator/consumer.h> |
24 | #include <linux/spi/spi.h> | 24 | #include <linux/spi/spi.h> |
25 | #include <linux/of_device.h> | ||
25 | #include <sound/core.h> | 26 | #include <sound/core.h> |
26 | #include <sound/pcm.h> | 27 | #include <sound/pcm.h> |
27 | #include <sound/pcm_params.h> | 28 | #include <sound/pcm_params.h> |
@@ -607,6 +608,13 @@ static struct snd_soc_codec_driver soc_codec_dev_wm8731 = { | |||
607 | .num_dapm_routes = ARRAY_SIZE(wm8731_intercon), | 608 | .num_dapm_routes = ARRAY_SIZE(wm8731_intercon), |
608 | }; | 609 | }; |
609 | 610 | ||
611 | static const struct of_device_id wm8731_of_match[] = { | ||
612 | { .compatible = "wlf,wm8731", }, | ||
613 | { } | ||
614 | }; | ||
615 | |||
616 | MODULE_DEVICE_TABLE(of, wm8731_of_match); | ||
617 | |||
610 | #if defined(CONFIG_SPI_MASTER) | 618 | #if defined(CONFIG_SPI_MASTER) |
611 | static int __devinit wm8731_spi_probe(struct spi_device *spi) | 619 | static int __devinit wm8731_spi_probe(struct spi_device *spi) |
612 | { | 620 | { |
@@ -638,6 +646,7 @@ static struct spi_driver wm8731_spi_driver = { | |||
638 | .driver = { | 646 | .driver = { |
639 | .name = "wm8731", | 647 | .name = "wm8731", |
640 | .owner = THIS_MODULE, | 648 | .owner = THIS_MODULE, |
649 | .of_match_table = wm8731_of_match, | ||
641 | }, | 650 | }, |
642 | .probe = wm8731_spi_probe, | 651 | .probe = wm8731_spi_probe, |
643 | .remove = __devexit_p(wm8731_spi_remove), | 652 | .remove = __devexit_p(wm8731_spi_remove), |
@@ -682,6 +691,7 @@ static struct i2c_driver wm8731_i2c_driver = { | |||
682 | .driver = { | 691 | .driver = { |
683 | .name = "wm8731", | 692 | .name = "wm8731", |
684 | .owner = THIS_MODULE, | 693 | .owner = THIS_MODULE, |
694 | .of_match_table = wm8731_of_match, | ||
685 | }, | 695 | }, |
686 | .probe = wm8731_i2c_probe, | 696 | .probe = wm8731_i2c_probe, |
687 | .remove = __devexit_p(wm8731_i2c_remove), | 697 | .remove = __devexit_p(wm8731_i2c_remove), |
diff --git a/sound/soc/codecs/wm8737.c b/sound/soc/codecs/wm8737.c index 30c67d06a904..f6aef58845c2 100644 --- a/sound/soc/codecs/wm8737.c +++ b/sound/soc/codecs/wm8737.c | |||
@@ -20,6 +20,7 @@ | |||
20 | #include <linux/regulator/consumer.h> | 20 | #include <linux/regulator/consumer.h> |
21 | #include <linux/spi/spi.h> | 21 | #include <linux/spi/spi.h> |
22 | #include <linux/slab.h> | 22 | #include <linux/slab.h> |
23 | #include <linux/of_device.h> | ||
23 | #include <sound/core.h> | 24 | #include <sound/core.h> |
24 | #include <sound/pcm.h> | 25 | #include <sound/pcm.h> |
25 | #include <sound/pcm_params.h> | 26 | #include <sound/pcm_params.h> |
@@ -634,6 +635,13 @@ static struct snd_soc_codec_driver soc_codec_dev_wm8737 = { | |||
634 | .reg_cache_default = wm8737_reg, | 635 | .reg_cache_default = wm8737_reg, |
635 | }; | 636 | }; |
636 | 637 | ||
638 | static const struct of_device_id wm8737_of_match[] = { | ||
639 | { .compatible = "wlf,wm8737", }, | ||
640 | { } | ||
641 | }; | ||
642 | |||
643 | MODULE_DEVICE_TABLE(of, wm8737_of_match); | ||
644 | |||
637 | #if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE) | 645 | #if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE) |
638 | static __devinit int wm8737_i2c_probe(struct i2c_client *i2c, | 646 | static __devinit int wm8737_i2c_probe(struct i2c_client *i2c, |
639 | const struct i2c_device_id *id) | 647 | const struct i2c_device_id *id) |
@@ -673,6 +681,7 @@ static struct i2c_driver wm8737_i2c_driver = { | |||
673 | .driver = { | 681 | .driver = { |
674 | .name = "wm8737", | 682 | .name = "wm8737", |
675 | .owner = THIS_MODULE, | 683 | .owner = THIS_MODULE, |
684 | .of_match_table = wm8737_of_match, | ||
676 | }, | 685 | }, |
677 | .probe = wm8737_i2c_probe, | 686 | .probe = wm8737_i2c_probe, |
678 | .remove = __devexit_p(wm8737_i2c_remove), | 687 | .remove = __devexit_p(wm8737_i2c_remove), |
@@ -711,6 +720,7 @@ static struct spi_driver wm8737_spi_driver = { | |||
711 | .driver = { | 720 | .driver = { |
712 | .name = "wm8737", | 721 | .name = "wm8737", |
713 | .owner = THIS_MODULE, | 722 | .owner = THIS_MODULE, |
723 | .of_match_table = wm8737_of_match, | ||
714 | }, | 724 | }, |
715 | .probe = wm8737_spi_probe, | 725 | .probe = wm8737_spi_probe, |
716 | .remove = __devexit_p(wm8737_spi_remove), | 726 | .remove = __devexit_p(wm8737_spi_remove), |
diff --git a/sound/soc/codecs/wm8741.c b/sound/soc/codecs/wm8741.c index 25af901fe813..78c9e5ab3fa5 100644 --- a/sound/soc/codecs/wm8741.c +++ b/sound/soc/codecs/wm8741.c | |||
@@ -17,9 +17,11 @@ | |||
17 | #include <linux/delay.h> | 17 | #include <linux/delay.h> |
18 | #include <linux/pm.h> | 18 | #include <linux/pm.h> |
19 | #include <linux/i2c.h> | 19 | #include <linux/i2c.h> |
20 | #include <linux/spi/spi.h> | ||
20 | #include <linux/platform_device.h> | 21 | #include <linux/platform_device.h> |
21 | #include <linux/regulator/consumer.h> | 22 | #include <linux/regulator/consumer.h> |
22 | #include <linux/slab.h> | 23 | #include <linux/slab.h> |
24 | #include <linux/of_device.h> | ||
23 | #include <sound/core.h> | 25 | #include <sound/core.h> |
24 | #include <sound/pcm.h> | 26 | #include <sound/pcm.h> |
25 | #include <sound/pcm_params.h> | 27 | #include <sound/pcm_params.h> |
@@ -422,17 +424,35 @@ static int wm8741_probe(struct snd_soc_codec *codec) | |||
422 | { | 424 | { |
423 | struct wm8741_priv *wm8741 = snd_soc_codec_get_drvdata(codec); | 425 | struct wm8741_priv *wm8741 = snd_soc_codec_get_drvdata(codec); |
424 | int ret = 0; | 426 | int ret = 0; |
427 | int i; | ||
428 | |||
429 | for (i = 0; i < ARRAY_SIZE(wm8741->supplies); i++) | ||
430 | wm8741->supplies[i].supply = wm8741_supply_names[i]; | ||
431 | |||
432 | ret = regulator_bulk_get(codec->dev, ARRAY_SIZE(wm8741->supplies), | ||
433 | wm8741->supplies); | ||
434 | if (ret != 0) { | ||
435 | dev_err(codec->dev, "Failed to request supplies: %d\n", ret); | ||
436 | goto err; | ||
437 | } | ||
438 | |||
439 | ret = regulator_bulk_enable(ARRAY_SIZE(wm8741->supplies), | ||
440 | wm8741->supplies); | ||
441 | if (ret != 0) { | ||
442 | dev_err(codec->dev, "Failed to enable supplies: %d\n", ret); | ||
443 | goto err_get; | ||
444 | } | ||
425 | 445 | ||
426 | ret = snd_soc_codec_set_cache_io(codec, 7, 9, wm8741->control_type); | 446 | ret = snd_soc_codec_set_cache_io(codec, 7, 9, wm8741->control_type); |
427 | if (ret != 0) { | 447 | if (ret != 0) { |
428 | dev_err(codec->dev, "Failed to set cache I/O: %d\n", ret); | 448 | dev_err(codec->dev, "Failed to set cache I/O: %d\n", ret); |
429 | return ret; | 449 | goto err_enable; |
430 | } | 450 | } |
431 | 451 | ||
432 | ret = wm8741_reset(codec); | 452 | ret = wm8741_reset(codec); |
433 | if (ret < 0) { | 453 | if (ret < 0) { |
434 | dev_err(codec->dev, "Failed to issue reset\n"); | 454 | dev_err(codec->dev, "Failed to issue reset\n"); |
435 | return ret; | 455 | goto err_enable; |
436 | } | 456 | } |
437 | 457 | ||
438 | /* Change some default settings - latch VU */ | 458 | /* Change some default settings - latch VU */ |
@@ -451,58 +471,61 @@ static int wm8741_probe(struct snd_soc_codec *codec) | |||
451 | 471 | ||
452 | dev_dbg(codec->dev, "Successful registration\n"); | 472 | dev_dbg(codec->dev, "Successful registration\n"); |
453 | return ret; | 473 | return ret; |
474 | |||
475 | err_enable: | ||
476 | regulator_bulk_disable(ARRAY_SIZE(wm8741->supplies), wm8741->supplies); | ||
477 | err_get: | ||
478 | regulator_bulk_free(ARRAY_SIZE(wm8741->supplies), wm8741->supplies); | ||
479 | err: | ||
480 | return ret; | ||
481 | } | ||
482 | |||
483 | static int wm8741_remove(struct snd_soc_codec *codec) | ||
484 | { | ||
485 | struct wm8741_priv *wm8741 = snd_soc_codec_get_drvdata(codec); | ||
486 | |||
487 | regulator_bulk_disable(ARRAY_SIZE(wm8741->supplies), wm8741->supplies); | ||
488 | regulator_bulk_free(ARRAY_SIZE(wm8741->supplies), wm8741->supplies); | ||
489 | |||
490 | return 0; | ||
454 | } | 491 | } |
455 | 492 | ||
456 | static struct snd_soc_codec_driver soc_codec_dev_wm8741 = { | 493 | static struct snd_soc_codec_driver soc_codec_dev_wm8741 = { |
457 | .probe = wm8741_probe, | 494 | .probe = wm8741_probe, |
495 | .remove = wm8741_remove, | ||
458 | .resume = wm8741_resume, | 496 | .resume = wm8741_resume, |
459 | .reg_cache_size = ARRAY_SIZE(wm8741_reg_defaults), | 497 | .reg_cache_size = ARRAY_SIZE(wm8741_reg_defaults), |
460 | .reg_word_size = sizeof(u16), | 498 | .reg_word_size = sizeof(u16), |
461 | .reg_cache_default = wm8741_reg_defaults, | 499 | .reg_cache_default = wm8741_reg_defaults, |
462 | }; | 500 | }; |
463 | 501 | ||
502 | static const struct of_device_id wm8741_of_match[] = { | ||
503 | { .compatible = "wlf,wm8741", }, | ||
504 | { } | ||
505 | }; | ||
506 | MODULE_DEVICE_TABLE(of, wm8741_of_match); | ||
507 | |||
464 | #if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE) | 508 | #if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE) |
465 | static int wm8741_i2c_probe(struct i2c_client *i2c, | 509 | static int wm8741_i2c_probe(struct i2c_client *i2c, |
466 | const struct i2c_device_id *id) | 510 | const struct i2c_device_id *id) |
467 | { | 511 | { |
468 | struct wm8741_priv *wm8741; | 512 | struct wm8741_priv *wm8741; |
469 | int ret, i; | 513 | int ret; |
470 | 514 | ||
471 | wm8741 = kzalloc(sizeof(struct wm8741_priv), GFP_KERNEL); | 515 | wm8741 = kzalloc(sizeof(struct wm8741_priv), GFP_KERNEL); |
472 | if (wm8741 == NULL) | 516 | if (wm8741 == NULL) |
473 | return -ENOMEM; | 517 | return -ENOMEM; |
474 | 518 | ||
475 | for (i = 0; i < ARRAY_SIZE(wm8741->supplies); i++) | ||
476 | wm8741->supplies[i].supply = wm8741_supply_names[i]; | ||
477 | |||
478 | ret = regulator_bulk_get(&i2c->dev, ARRAY_SIZE(wm8741->supplies), | ||
479 | wm8741->supplies); | ||
480 | if (ret != 0) { | ||
481 | dev_err(&i2c->dev, "Failed to request supplies: %d\n", ret); | ||
482 | goto err; | ||
483 | } | ||
484 | |||
485 | ret = regulator_bulk_enable(ARRAY_SIZE(wm8741->supplies), | ||
486 | wm8741->supplies); | ||
487 | if (ret != 0) { | ||
488 | dev_err(&i2c->dev, "Failed to enable supplies: %d\n", ret); | ||
489 | goto err_get; | ||
490 | } | ||
491 | |||
492 | i2c_set_clientdata(i2c, wm8741); | 519 | i2c_set_clientdata(i2c, wm8741); |
493 | wm8741->control_type = SND_SOC_I2C; | 520 | wm8741->control_type = SND_SOC_I2C; |
494 | 521 | ||
495 | ret = snd_soc_register_codec(&i2c->dev, | 522 | ret = snd_soc_register_codec(&i2c->dev, |
496 | &soc_codec_dev_wm8741, &wm8741_dai, 1); | 523 | &soc_codec_dev_wm8741, &wm8741_dai, 1); |
497 | if (ret < 0) | 524 | if (ret != 0) |
498 | goto err_enable; | 525 | goto err; |
499 | return ret; | ||
500 | 526 | ||
501 | err_enable: | 527 | return ret; |
502 | regulator_bulk_disable(ARRAY_SIZE(wm8741->supplies), wm8741->supplies); | ||
503 | 528 | ||
504 | err_get: | ||
505 | regulator_bulk_free(ARRAY_SIZE(wm8741->supplies), wm8741->supplies); | ||
506 | err: | 529 | err: |
507 | kfree(wm8741); | 530 | kfree(wm8741); |
508 | return ret; | 531 | return ret; |
@@ -510,10 +533,7 @@ err: | |||
510 | 533 | ||
511 | static int wm8741_i2c_remove(struct i2c_client *client) | 534 | static int wm8741_i2c_remove(struct i2c_client *client) |
512 | { | 535 | { |
513 | struct wm8741_priv *wm8741 = i2c_get_clientdata(client); | ||
514 | |||
515 | snd_soc_unregister_codec(&client->dev); | 536 | snd_soc_unregister_codec(&client->dev); |
516 | regulator_bulk_free(ARRAY_SIZE(wm8741->supplies), wm8741->supplies); | ||
517 | kfree(i2c_get_clientdata(client)); | 537 | kfree(i2c_get_clientdata(client)); |
518 | return 0; | 538 | return 0; |
519 | } | 539 | } |
@@ -526,8 +546,9 @@ MODULE_DEVICE_TABLE(i2c, wm8741_i2c_id); | |||
526 | 546 | ||
527 | static struct i2c_driver wm8741_i2c_driver = { | 547 | static struct i2c_driver wm8741_i2c_driver = { |
528 | .driver = { | 548 | .driver = { |
529 | .name = "wm8741-codec", | 549 | .name = "wm8741", |
530 | .owner = THIS_MODULE, | 550 | .owner = THIS_MODULE, |
551 | .of_match_table = wm8741_of_match, | ||
531 | }, | 552 | }, |
532 | .probe = wm8741_i2c_probe, | 553 | .probe = wm8741_i2c_probe, |
533 | .remove = wm8741_i2c_remove, | 554 | .remove = wm8741_i2c_remove, |
@@ -535,6 +556,44 @@ static struct i2c_driver wm8741_i2c_driver = { | |||
535 | }; | 556 | }; |
536 | #endif | 557 | #endif |
537 | 558 | ||
559 | #if defined(CONFIG_SPI_MASTER) | ||
560 | static int __devinit wm8741_spi_probe(struct spi_device *spi) | ||
561 | { | ||
562 | struct wm8741_priv *wm8741; | ||
563 | int ret; | ||
564 | |||
565 | wm8741 = kzalloc(sizeof(struct wm8741_priv), GFP_KERNEL); | ||
566 | if (wm8741 == NULL) | ||
567 | return -ENOMEM; | ||
568 | |||
569 | wm8741->control_type = SND_SOC_SPI; | ||
570 | spi_set_drvdata(spi, wm8741); | ||
571 | |||
572 | ret = snd_soc_register_codec(&spi->dev, | ||
573 | &soc_codec_dev_wm8741, &wm8741_dai, 1); | ||
574 | if (ret < 0) | ||
575 | kfree(wm8741); | ||
576 | return ret; | ||
577 | } | ||
578 | |||
579 | static int __devexit wm8741_spi_remove(struct spi_device *spi) | ||
580 | { | ||
581 | snd_soc_unregister_codec(&spi->dev); | ||
582 | kfree(spi_get_drvdata(spi)); | ||
583 | return 0; | ||
584 | } | ||
585 | |||
586 | static struct spi_driver wm8741_spi_driver = { | ||
587 | .driver = { | ||
588 | .name = "wm8741", | ||
589 | .owner = THIS_MODULE, | ||
590 | .of_match_table = wm8741_of_match, | ||
591 | }, | ||
592 | .probe = wm8741_spi_probe, | ||
593 | .remove = __devexit_p(wm8741_spi_remove), | ||
594 | }; | ||
595 | #endif /* CONFIG_SPI_MASTER */ | ||
596 | |||
538 | static int __init wm8741_modinit(void) | 597 | static int __init wm8741_modinit(void) |
539 | { | 598 | { |
540 | int ret = 0; | 599 | int ret = 0; |
@@ -544,6 +603,13 @@ static int __init wm8741_modinit(void) | |||
544 | if (ret != 0) | 603 | if (ret != 0) |
545 | pr_err("Failed to register WM8741 I2C driver: %d\n", ret); | 604 | pr_err("Failed to register WM8741 I2C driver: %d\n", ret); |
546 | #endif | 605 | #endif |
606 | #if defined(CONFIG_SPI_MASTER) | ||
607 | ret = spi_register_driver(&wm8741_spi_driver); | ||
608 | if (ret != 0) { | ||
609 | printk(KERN_ERR "Failed to register wm8741 SPI driver: %d\n", | ||
610 | ret); | ||
611 | } | ||
612 | #endif | ||
547 | 613 | ||
548 | return ret; | 614 | return ret; |
549 | } | 615 | } |
@@ -551,6 +617,9 @@ module_init(wm8741_modinit); | |||
551 | 617 | ||
552 | static void __exit wm8741_exit(void) | 618 | static void __exit wm8741_exit(void) |
553 | { | 619 | { |
620 | #if defined(CONFIG_SPI_MASTER) | ||
621 | spi_unregister_driver(&wm8741_spi_driver); | ||
622 | #endif | ||
554 | #if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE) | 623 | #if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE) |
555 | i2c_del_driver(&wm8741_i2c_driver); | 624 | i2c_del_driver(&wm8741_i2c_driver); |
556 | #endif | 625 | #endif |
diff --git a/sound/soc/codecs/wm8750.c b/sound/soc/codecs/wm8750.c index d0003cc3bcd6..15f03721ec6f 100644 --- a/sound/soc/codecs/wm8750.c +++ b/sound/soc/codecs/wm8750.c | |||
@@ -21,6 +21,7 @@ | |||
21 | #include <linux/platform_device.h> | 21 | #include <linux/platform_device.h> |
22 | #include <linux/spi/spi.h> | 22 | #include <linux/spi/spi.h> |
23 | #include <linux/slab.h> | 23 | #include <linux/slab.h> |
24 | #include <linux/of_device.h> | ||
24 | #include <sound/core.h> | 25 | #include <sound/core.h> |
25 | #include <sound/pcm.h> | 26 | #include <sound/pcm.h> |
26 | #include <sound/pcm_params.h> | 27 | #include <sound/pcm_params.h> |
@@ -751,6 +752,13 @@ static struct snd_soc_codec_driver soc_codec_dev_wm8750 = { | |||
751 | .reg_cache_default = wm8750_reg, | 752 | .reg_cache_default = wm8750_reg, |
752 | }; | 753 | }; |
753 | 754 | ||
755 | static const struct of_device_id wm8750_of_match[] = { | ||
756 | { .compatible = "wlf,wm8750", }, | ||
757 | { .compatible = "wlf,wm8987", }, | ||
758 | { } | ||
759 | }; | ||
760 | MODULE_DEVICE_TABLE(of, wm8750_of_match); | ||
761 | |||
754 | #if defined(CONFIG_SPI_MASTER) | 762 | #if defined(CONFIG_SPI_MASTER) |
755 | static int __devinit wm8750_spi_probe(struct spi_device *spi) | 763 | static int __devinit wm8750_spi_probe(struct spi_device *spi) |
756 | { | 764 | { |
@@ -787,8 +795,9 @@ MODULE_DEVICE_TABLE(spi, wm8750_spi_ids); | |||
787 | 795 | ||
788 | static struct spi_driver wm8750_spi_driver = { | 796 | static struct spi_driver wm8750_spi_driver = { |
789 | .driver = { | 797 | .driver = { |
790 | .name = "wm8750-codec", | 798 | .name = "wm8750", |
791 | .owner = THIS_MODULE, | 799 | .owner = THIS_MODULE, |
800 | .of_match_table = wm8750_of_match, | ||
792 | }, | 801 | }, |
793 | .id_table = wm8750_spi_ids, | 802 | .id_table = wm8750_spi_ids, |
794 | .probe = wm8750_spi_probe, | 803 | .probe = wm8750_spi_probe, |
@@ -833,8 +842,9 @@ MODULE_DEVICE_TABLE(i2c, wm8750_i2c_id); | |||
833 | 842 | ||
834 | static struct i2c_driver wm8750_i2c_driver = { | 843 | static struct i2c_driver wm8750_i2c_driver = { |
835 | .driver = { | 844 | .driver = { |
836 | .name = "wm8750-codec", | 845 | .name = "wm8750", |
837 | .owner = THIS_MODULE, | 846 | .owner = THIS_MODULE, |
847 | .of_match_table = wm8750_of_match, | ||
838 | }, | 848 | }, |
839 | .probe = wm8750_i2c_probe, | 849 | .probe = wm8750_i2c_probe, |
840 | .remove = __devexit_p(wm8750_i2c_remove), | 850 | .remove = __devexit_p(wm8750_i2c_remove), |
diff --git a/sound/soc/codecs/wm8753.c b/sound/soc/codecs/wm8753.c index ffa2ffe5ec11..fe04a101d657 100644 --- a/sound/soc/codecs/wm8753.c +++ b/sound/soc/codecs/wm8753.c | |||
@@ -38,6 +38,7 @@ | |||
38 | #include <linux/delay.h> | 38 | #include <linux/delay.h> |
39 | #include <linux/pm.h> | 39 | #include <linux/pm.h> |
40 | #include <linux/i2c.h> | 40 | #include <linux/i2c.h> |
41 | #include <linux/of_device.h> | ||
41 | #include <linux/platform_device.h> | 42 | #include <linux/platform_device.h> |
42 | #include <linux/spi/spi.h> | 43 | #include <linux/spi/spi.h> |
43 | #include <linux/slab.h> | 44 | #include <linux/slab.h> |
@@ -1490,6 +1491,12 @@ static struct snd_soc_codec_driver soc_codec_dev_wm8753 = { | |||
1490 | .reg_cache_default = wm8753_reg, | 1491 | .reg_cache_default = wm8753_reg, |
1491 | }; | 1492 | }; |
1492 | 1493 | ||
1494 | static const struct of_device_id wm8753_of_match[] = { | ||
1495 | { .compatible = "wlf,wm8753", }, | ||
1496 | { } | ||
1497 | }; | ||
1498 | MODULE_DEVICE_TABLE(of, wm8753_of_match); | ||
1499 | |||
1493 | #if defined(CONFIG_SPI_MASTER) | 1500 | #if defined(CONFIG_SPI_MASTER) |
1494 | static int __devinit wm8753_spi_probe(struct spi_device *spi) | 1501 | static int __devinit wm8753_spi_probe(struct spi_device *spi) |
1495 | { | 1502 | { |
@@ -1519,8 +1526,9 @@ static int __devexit wm8753_spi_remove(struct spi_device *spi) | |||
1519 | 1526 | ||
1520 | static struct spi_driver wm8753_spi_driver = { | 1527 | static struct spi_driver wm8753_spi_driver = { |
1521 | .driver = { | 1528 | .driver = { |
1522 | .name = "wm8753-codec", | 1529 | .name = "wm8753", |
1523 | .owner = THIS_MODULE, | 1530 | .owner = THIS_MODULE, |
1531 | .of_match_table = wm8753_of_match, | ||
1524 | }, | 1532 | }, |
1525 | .probe = wm8753_spi_probe, | 1533 | .probe = wm8753_spi_probe, |
1526 | .remove = __devexit_p(wm8753_spi_remove), | 1534 | .remove = __devexit_p(wm8753_spi_remove), |
@@ -1563,8 +1571,9 @@ MODULE_DEVICE_TABLE(i2c, wm8753_i2c_id); | |||
1563 | 1571 | ||
1564 | static struct i2c_driver wm8753_i2c_driver = { | 1572 | static struct i2c_driver wm8753_i2c_driver = { |
1565 | .driver = { | 1573 | .driver = { |
1566 | .name = "wm8753-codec", | 1574 | .name = "wm8753", |
1567 | .owner = THIS_MODULE, | 1575 | .owner = THIS_MODULE, |
1576 | .of_match_table = wm8753_of_match, | ||
1568 | }, | 1577 | }, |
1569 | .probe = wm8753_i2c_probe, | 1578 | .probe = wm8753_i2c_probe, |
1570 | .remove = __devexit_p(wm8753_i2c_remove), | 1579 | .remove = __devexit_p(wm8753_i2c_remove), |
diff --git a/sound/soc/codecs/wm8770.c b/sound/soc/codecs/wm8770.c index 19b92baa9e8c..aa05e6507f84 100644 --- a/sound/soc/codecs/wm8770.c +++ b/sound/soc/codecs/wm8770.c | |||
@@ -14,6 +14,7 @@ | |||
14 | #include <linux/moduleparam.h> | 14 | #include <linux/moduleparam.h> |
15 | #include <linux/init.h> | 15 | #include <linux/init.h> |
16 | #include <linux/delay.h> | 16 | #include <linux/delay.h> |
17 | #include <linux/of_device.h> | ||
17 | #include <linux/pm.h> | 18 | #include <linux/pm.h> |
18 | #include <linux/platform_device.h> | 19 | #include <linux/platform_device.h> |
19 | #include <linux/spi/spi.h> | 20 | #include <linux/spi/spi.h> |
@@ -684,6 +685,12 @@ static struct snd_soc_codec_driver soc_codec_dev_wm8770 = { | |||
684 | .reg_cache_default = wm8770_reg_defs | 685 | .reg_cache_default = wm8770_reg_defs |
685 | }; | 686 | }; |
686 | 687 | ||
688 | static const struct of_device_id wm8770_of_match[] = { | ||
689 | { .compatible = "wlf,wm8770", }, | ||
690 | { } | ||
691 | }; | ||
692 | MODULE_DEVICE_TABLE(of, wm8770_of_match); | ||
693 | |||
687 | #if defined(CONFIG_SPI_MASTER) | 694 | #if defined(CONFIG_SPI_MASTER) |
688 | static int __devinit wm8770_spi_probe(struct spi_device *spi) | 695 | static int __devinit wm8770_spi_probe(struct spi_device *spi) |
689 | { | 696 | { |
@@ -715,6 +722,7 @@ static struct spi_driver wm8770_spi_driver = { | |||
715 | .driver = { | 722 | .driver = { |
716 | .name = "wm8770", | 723 | .name = "wm8770", |
717 | .owner = THIS_MODULE, | 724 | .owner = THIS_MODULE, |
725 | .of_match_table = wm8770_of_match, | ||
718 | }, | 726 | }, |
719 | .probe = wm8770_spi_probe, | 727 | .probe = wm8770_spi_probe, |
720 | .remove = __devexit_p(wm8770_spi_remove) | 728 | .remove = __devexit_p(wm8770_spi_remove) |
diff --git a/sound/soc/codecs/wm8776.c b/sound/soc/codecs/wm8776.c index 8e7953b1b790..00d8846fae8a 100644 --- a/sound/soc/codecs/wm8776.c +++ b/sound/soc/codecs/wm8776.c | |||
@@ -18,6 +18,7 @@ | |||
18 | #include <linux/delay.h> | 18 | #include <linux/delay.h> |
19 | #include <linux/pm.h> | 19 | #include <linux/pm.h> |
20 | #include <linux/i2c.h> | 20 | #include <linux/i2c.h> |
21 | #include <linux/of_device.h> | ||
21 | #include <linux/platform_device.h> | 22 | #include <linux/platform_device.h> |
22 | #include <linux/spi/spi.h> | 23 | #include <linux/spi/spi.h> |
23 | #include <linux/slab.h> | 24 | #include <linux/slab.h> |
@@ -215,8 +216,6 @@ static int wm8776_hw_params(struct snd_pcm_substream *substream, | |||
215 | int ratio_shift, master; | 216 | int ratio_shift, master; |
216 | int i; | 217 | int i; |
217 | 218 | ||
218 | iface = 0; | ||
219 | |||
220 | switch (dai->driver->id) { | 219 | switch (dai->driver->id) { |
221 | case WM8776_DAI_DAC: | 220 | case WM8776_DAI_DAC: |
222 | iface_reg = WM8776_DACIFCTRL; | 221 | iface_reg = WM8776_DACIFCTRL; |
@@ -232,20 +231,23 @@ static int wm8776_hw_params(struct snd_pcm_substream *substream, | |||
232 | return -EINVAL; | 231 | return -EINVAL; |
233 | } | 232 | } |
234 | 233 | ||
235 | |||
236 | /* Set word length */ | 234 | /* Set word length */ |
237 | switch (params_format(params)) { | 235 | switch (snd_pcm_format_width(params_format(params))) { |
238 | case SNDRV_PCM_FORMAT_S16_LE: | 236 | case 16: |
237 | iface = 0; | ||
238 | case 20: | ||
239 | iface = 0x10; | ||
239 | break; | 240 | break; |
240 | case SNDRV_PCM_FORMAT_S20_3LE: | 241 | case 24: |
241 | iface |= 0x10; | 242 | iface = 0x20; |
242 | break; | 243 | break; |
243 | case SNDRV_PCM_FORMAT_S24_LE: | 244 | case 32: |
244 | iface |= 0x20; | 245 | iface = 0x30; |
245 | break; | ||
246 | case SNDRV_PCM_FORMAT_S32_LE: | ||
247 | iface |= 0x30; | ||
248 | break; | 246 | break; |
247 | default: | ||
248 | dev_err(codec->dev, "Unsupported sample size: %i\n", | ||
249 | snd_pcm_format_width(params_format(params))); | ||
250 | return -EINVAL; | ||
249 | } | 251 | } |
250 | 252 | ||
251 | /* Only need to set MCLK/LRCLK ratio if we're master */ | 253 | /* Only need to set MCLK/LRCLK ratio if we're master */ |
@@ -320,11 +322,6 @@ static int wm8776_set_bias_level(struct snd_soc_codec *codec, | |||
320 | return 0; | 322 | return 0; |
321 | } | 323 | } |
322 | 324 | ||
323 | #define WM8776_RATES (SNDRV_PCM_RATE_32000 | SNDRV_PCM_RATE_44100 |\ | ||
324 | SNDRV_PCM_RATE_48000 | SNDRV_PCM_RATE_88200 |\ | ||
325 | SNDRV_PCM_RATE_96000) | ||
326 | |||
327 | |||
328 | #define WM8776_FORMATS (SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S20_3LE |\ | 325 | #define WM8776_FORMATS (SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S20_3LE |\ |
329 | SNDRV_PCM_FMTBIT_S24_LE | SNDRV_PCM_FMTBIT_S32_LE) | 326 | SNDRV_PCM_FMTBIT_S24_LE | SNDRV_PCM_FMTBIT_S32_LE) |
330 | 327 | ||
@@ -349,7 +346,9 @@ static struct snd_soc_dai_driver wm8776_dai[] = { | |||
349 | .stream_name = "Playback", | 346 | .stream_name = "Playback", |
350 | .channels_min = 2, | 347 | .channels_min = 2, |
351 | .channels_max = 2, | 348 | .channels_max = 2, |
352 | .rates = WM8776_RATES, | 349 | .rates = SNDRV_PCM_RATE_CONTINUOUS, |
350 | .rate_min = 32000, | ||
351 | .rate_max = 192000, | ||
353 | .formats = WM8776_FORMATS, | 352 | .formats = WM8776_FORMATS, |
354 | }, | 353 | }, |
355 | .ops = &wm8776_dac_ops, | 354 | .ops = &wm8776_dac_ops, |
@@ -361,7 +360,9 @@ static struct snd_soc_dai_driver wm8776_dai[] = { | |||
361 | .stream_name = "Capture", | 360 | .stream_name = "Capture", |
362 | .channels_min = 2, | 361 | .channels_min = 2, |
363 | .channels_max = 2, | 362 | .channels_max = 2, |
364 | .rates = WM8776_RATES, | 363 | .rates = SNDRV_PCM_RATE_CONTINUOUS, |
364 | .rate_min = 32000, | ||
365 | .rate_max = 96000, | ||
365 | .formats = WM8776_FORMATS, | 366 | .formats = WM8776_FORMATS, |
366 | }, | 367 | }, |
367 | .ops = &wm8776_adc_ops, | 368 | .ops = &wm8776_adc_ops, |
@@ -452,6 +453,12 @@ static struct snd_soc_codec_driver soc_codec_dev_wm8776 = { | |||
452 | .reg_cache_default = wm8776_reg, | 453 | .reg_cache_default = wm8776_reg, |
453 | }; | 454 | }; |
454 | 455 | ||
456 | static const struct of_device_id wm8776_of_match[] = { | ||
457 | { .compatible = "wlf,wm8776", }, | ||
458 | { } | ||
459 | }; | ||
460 | MODULE_DEVICE_TABLE(of, wm8776_of_match); | ||
461 | |||
455 | #if defined(CONFIG_SPI_MASTER) | 462 | #if defined(CONFIG_SPI_MASTER) |
456 | static int __devinit wm8776_spi_probe(struct spi_device *spi) | 463 | static int __devinit wm8776_spi_probe(struct spi_device *spi) |
457 | { | 464 | { |
@@ -481,8 +488,9 @@ static int __devexit wm8776_spi_remove(struct spi_device *spi) | |||
481 | 488 | ||
482 | static struct spi_driver wm8776_spi_driver = { | 489 | static struct spi_driver wm8776_spi_driver = { |
483 | .driver = { | 490 | .driver = { |
484 | .name = "wm8776-codec", | 491 | .name = "wm8776", |
485 | .owner = THIS_MODULE, | 492 | .owner = THIS_MODULE, |
493 | .of_match_table = wm8776_of_match, | ||
486 | }, | 494 | }, |
487 | .probe = wm8776_spi_probe, | 495 | .probe = wm8776_spi_probe, |
488 | .remove = __devexit_p(wm8776_spi_remove), | 496 | .remove = __devexit_p(wm8776_spi_remove), |
@@ -525,8 +533,9 @@ MODULE_DEVICE_TABLE(i2c, wm8776_i2c_id); | |||
525 | 533 | ||
526 | static struct i2c_driver wm8776_i2c_driver = { | 534 | static struct i2c_driver wm8776_i2c_driver = { |
527 | .driver = { | 535 | .driver = { |
528 | .name = "wm8776-codec", | 536 | .name = "wm8776", |
529 | .owner = THIS_MODULE, | 537 | .owner = THIS_MODULE, |
538 | .of_match_table = wm8776_of_match, | ||
530 | }, | 539 | }, |
531 | .probe = wm8776_i2c_probe, | 540 | .probe = wm8776_i2c_probe, |
532 | .remove = __devexit_p(wm8776_i2c_remove), | 541 | .remove = __devexit_p(wm8776_i2c_remove), |
diff --git a/sound/soc/codecs/wm8804.c b/sound/soc/codecs/wm8804.c index 9a5e67c5a6bd..9ee072b85975 100644 --- a/sound/soc/codecs/wm8804.c +++ b/sound/soc/codecs/wm8804.c | |||
@@ -16,6 +16,7 @@ | |||
16 | #include <linux/delay.h> | 16 | #include <linux/delay.h> |
17 | #include <linux/pm.h> | 17 | #include <linux/pm.h> |
18 | #include <linux/i2c.h> | 18 | #include <linux/i2c.h> |
19 | #include <linux/of_device.h> | ||
19 | #include <linux/spi/spi.h> | 20 | #include <linux/spi/spi.h> |
20 | #include <linux/regulator/consumer.h> | 21 | #include <linux/regulator/consumer.h> |
21 | #include <linux/slab.h> | 22 | #include <linux/slab.h> |
@@ -717,6 +718,12 @@ static struct snd_soc_codec_driver soc_codec_dev_wm8804 = { | |||
717 | .volatile_register = wm8804_volatile | 718 | .volatile_register = wm8804_volatile |
718 | }; | 719 | }; |
719 | 720 | ||
721 | static const struct of_device_id wm8804_of_match[] = { | ||
722 | { .compatible = "wlf,wm8804", }, | ||
723 | { } | ||
724 | }; | ||
725 | MODULE_DEVICE_TABLE(of, wm8804_of_match); | ||
726 | |||
720 | #if defined(CONFIG_SPI_MASTER) | 727 | #if defined(CONFIG_SPI_MASTER) |
721 | static int __devinit wm8804_spi_probe(struct spi_device *spi) | 728 | static int __devinit wm8804_spi_probe(struct spi_device *spi) |
722 | { | 729 | { |
@@ -748,6 +755,7 @@ static struct spi_driver wm8804_spi_driver = { | |||
748 | .driver = { | 755 | .driver = { |
749 | .name = "wm8804", | 756 | .name = "wm8804", |
750 | .owner = THIS_MODULE, | 757 | .owner = THIS_MODULE, |
758 | .of_match_table = wm8804_of_match, | ||
751 | }, | 759 | }, |
752 | .probe = wm8804_spi_probe, | 760 | .probe = wm8804_spi_probe, |
753 | .remove = __devexit_p(wm8804_spi_remove) | 761 | .remove = __devexit_p(wm8804_spi_remove) |
@@ -792,6 +800,7 @@ static struct i2c_driver wm8804_i2c_driver = { | |||
792 | .driver = { | 800 | .driver = { |
793 | .name = "wm8804", | 801 | .name = "wm8804", |
794 | .owner = THIS_MODULE, | 802 | .owner = THIS_MODULE, |
803 | .of_match_table = wm8804_of_match, | ||
795 | }, | 804 | }, |
796 | .probe = wm8804_i2c_probe, | 805 | .probe = wm8804_i2c_probe, |
797 | .remove = __devexit_p(wm8804_i2c_remove), | 806 | .remove = __devexit_p(wm8804_i2c_remove), |
diff --git a/sound/soc/codecs/wm8962.c b/sound/soc/codecs/wm8962.c index d2c315fa1b9b..3676b38838d8 100644 --- a/sound/soc/codecs/wm8962.c +++ b/sound/soc/codecs/wm8962.c | |||
@@ -63,6 +63,8 @@ struct wm8962_priv { | |||
63 | int fll_fref; | 63 | int fll_fref; |
64 | int fll_fout; | 64 | int fll_fout; |
65 | 65 | ||
66 | u16 dsp2_ena; | ||
67 | |||
66 | struct delayed_work mic_work; | 68 | struct delayed_work mic_work; |
67 | struct snd_soc_jack *jack; | 69 | struct snd_soc_jack *jack; |
68 | 70 | ||
@@ -837,7 +839,7 @@ static const struct wm8962_reg_access { | |||
837 | [40] = { 0x00FF, 0x01FF, 0x0000 }, /* R40 - SPKOUTL volume */ | 839 | [40] = { 0x00FF, 0x01FF, 0x0000 }, /* R40 - SPKOUTL volume */ |
838 | [41] = { 0x00FF, 0x01FF, 0x0000 }, /* R41 - SPKOUTR volume */ | 840 | [41] = { 0x00FF, 0x01FF, 0x0000 }, /* R41 - SPKOUTR volume */ |
839 | 841 | ||
840 | [47] = { 0x000F, 0x0000, 0x0000 }, /* R47 - Thermal Shutdown Status */ | 842 | [47] = { 0x000F, 0x0000, 0xFFFF }, /* R47 - Thermal Shutdown Status */ |
841 | [48] = { 0x7EC7, 0x7E07, 0xFFFF }, /* R48 - Additional Control (4) */ | 843 | [48] = { 0x7EC7, 0x7E07, 0xFFFF }, /* R48 - Additional Control (4) */ |
842 | [49] = { 0x00D3, 0x00D7, 0xFFFF }, /* R49 - Class D Control 1 */ | 844 | [49] = { 0x00D3, 0x00D7, 0xFFFF }, /* R49 - Class D Control 1 */ |
843 | [51] = { 0x0047, 0x0047, 0x0000 }, /* R51 - Class D Control 2 */ | 845 | [51] = { 0x0047, 0x0047, 0x0000 }, /* R51 - Class D Control 2 */ |
@@ -965,7 +967,7 @@ static const struct wm8962_reg_access { | |||
965 | [584] = { 0x002D, 0x002D, 0x0000 }, /* R584 - IRQ Debounce */ | 967 | [584] = { 0x002D, 0x002D, 0x0000 }, /* R584 - IRQ Debounce */ |
966 | [586] = { 0xC000, 0xC000, 0x0000 }, /* R586 - MICINT Source Pol */ | 968 | [586] = { 0xC000, 0xC000, 0x0000 }, /* R586 - MICINT Source Pol */ |
967 | [768] = { 0x0001, 0x0001, 0x0000 }, /* R768 - DSP2 Power Management */ | 969 | [768] = { 0x0001, 0x0001, 0x0000 }, /* R768 - DSP2 Power Management */ |
968 | [1037] = { 0x0000, 0x003F, 0x0000 }, /* R1037 - DSP2_ExecControl */ | 970 | [1037] = { 0x0000, 0x003F, 0xFFFF }, /* R1037 - DSP2_ExecControl */ |
969 | [4096] = { 0x3FFF, 0x3FFF, 0x0000 }, /* R4096 - Write Sequencer 0 */ | 971 | [4096] = { 0x3FFF, 0x3FFF, 0x0000 }, /* R4096 - Write Sequencer 0 */ |
970 | [4097] = { 0x00FF, 0x00FF, 0x0000 }, /* R4097 - Write Sequencer 1 */ | 972 | [4097] = { 0x00FF, 0x00FF, 0x0000 }, /* R4097 - Write Sequencer 1 */ |
971 | [4098] = { 0x070F, 0x070F, 0x0000 }, /* R4098 - Write Sequencer 2 */ | 973 | [4098] = { 0x070F, 0x070F, 0x0000 }, /* R4098 - Write Sequencer 2 */ |
@@ -1986,6 +1988,122 @@ static const unsigned int classd_tlv[] = { | |||
1986 | }; | 1988 | }; |
1987 | static const DECLARE_TLV_DB_SCALE(eq_tlv, -1200, 100, 0); | 1989 | static const DECLARE_TLV_DB_SCALE(eq_tlv, -1200, 100, 0); |
1988 | 1990 | ||
1991 | static int wm8962_dsp2_write_config(struct snd_soc_codec *codec) | ||
1992 | { | ||
1993 | return 0; | ||
1994 | } | ||
1995 | |||
1996 | static int wm8962_dsp2_set_enable(struct snd_soc_codec *codec, u16 val) | ||
1997 | { | ||
1998 | u16 adcl = snd_soc_read(codec, WM8962_LEFT_ADC_VOLUME); | ||
1999 | u16 adcr = snd_soc_read(codec, WM8962_RIGHT_ADC_VOLUME); | ||
2000 | u16 dac = snd_soc_read(codec, WM8962_ADC_DAC_CONTROL_1); | ||
2001 | |||
2002 | /* Mute the ADCs and DACs */ | ||
2003 | snd_soc_write(codec, WM8962_LEFT_ADC_VOLUME, 0); | ||
2004 | snd_soc_write(codec, WM8962_RIGHT_ADC_VOLUME, WM8962_ADC_VU); | ||
2005 | snd_soc_update_bits(codec, WM8962_ADC_DAC_CONTROL_1, | ||
2006 | WM8962_DAC_MUTE, WM8962_DAC_MUTE); | ||
2007 | |||
2008 | snd_soc_write(codec, WM8962_SOUNDSTAGE_ENABLES_0, val); | ||
2009 | |||
2010 | /* Restore the ADCs and DACs */ | ||
2011 | snd_soc_write(codec, WM8962_LEFT_ADC_VOLUME, adcl); | ||
2012 | snd_soc_write(codec, WM8962_RIGHT_ADC_VOLUME, adcr); | ||
2013 | snd_soc_update_bits(codec, WM8962_ADC_DAC_CONTROL_1, | ||
2014 | WM8962_DAC_MUTE, dac); | ||
2015 | |||
2016 | return 0; | ||
2017 | } | ||
2018 | |||
2019 | static int wm8962_dsp2_start(struct snd_soc_codec *codec) | ||
2020 | { | ||
2021 | struct wm8962_priv *wm8962 = snd_soc_codec_get_drvdata(codec); | ||
2022 | |||
2023 | wm8962_dsp2_write_config(codec); | ||
2024 | |||
2025 | snd_soc_write(codec, WM8962_DSP2_EXECCONTROL, WM8962_DSP2_RUNR); | ||
2026 | |||
2027 | wm8962_dsp2_set_enable(codec, wm8962->dsp2_ena); | ||
2028 | |||
2029 | return 0; | ||
2030 | } | ||
2031 | |||
2032 | static int wm8962_dsp2_stop(struct snd_soc_codec *codec) | ||
2033 | { | ||
2034 | wm8962_dsp2_set_enable(codec, 0); | ||
2035 | |||
2036 | snd_soc_write(codec, WM8962_DSP2_EXECCONTROL, WM8962_DSP2_STOP); | ||
2037 | |||
2038 | return 0; | ||
2039 | } | ||
2040 | |||
2041 | #define WM8962_DSP2_ENABLE(xname, xshift) \ | ||
2042 | { .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = xname, \ | ||
2043 | .info = wm8962_dsp2_ena_info, \ | ||
2044 | .get = wm8962_dsp2_ena_get, .put = wm8962_dsp2_ena_put, \ | ||
2045 | .private_value = xshift } | ||
2046 | |||
2047 | static int wm8962_dsp2_ena_info(struct snd_kcontrol *kcontrol, | ||
2048 | struct snd_ctl_elem_info *uinfo) | ||
2049 | { | ||
2050 | uinfo->type = SNDRV_CTL_ELEM_TYPE_BOOLEAN; | ||
2051 | |||
2052 | uinfo->count = 1; | ||
2053 | uinfo->value.integer.min = 0; | ||
2054 | uinfo->value.integer.max = 1; | ||
2055 | |||
2056 | return 0; | ||
2057 | } | ||
2058 | |||
2059 | static int wm8962_dsp2_ena_get(struct snd_kcontrol *kcontrol, | ||
2060 | struct snd_ctl_elem_value *ucontrol) | ||
2061 | { | ||
2062 | int shift = kcontrol->private_value; | ||
2063 | struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol); | ||
2064 | struct wm8962_priv *wm8962 = snd_soc_codec_get_drvdata(codec); | ||
2065 | |||
2066 | ucontrol->value.integer.value[0] = !!(wm8962->dsp2_ena & 1 << shift); | ||
2067 | |||
2068 | return 0; | ||
2069 | } | ||
2070 | |||
2071 | static int wm8962_dsp2_ena_put(struct snd_kcontrol *kcontrol, | ||
2072 | struct snd_ctl_elem_value *ucontrol) | ||
2073 | { | ||
2074 | int shift = kcontrol->private_value; | ||
2075 | struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol); | ||
2076 | struct wm8962_priv *wm8962 = snd_soc_codec_get_drvdata(codec); | ||
2077 | int old = wm8962->dsp2_ena; | ||
2078 | int ret = 0; | ||
2079 | int dsp2_running = snd_soc_read(codec, WM8962_DSP2_POWER_MANAGEMENT) & | ||
2080 | WM8962_DSP2_ENA; | ||
2081 | |||
2082 | mutex_lock(&codec->mutex); | ||
2083 | |||
2084 | if (ucontrol->value.integer.value[0]) | ||
2085 | wm8962->dsp2_ena |= 1 << shift; | ||
2086 | else | ||
2087 | wm8962->dsp2_ena &= ~(1 << shift); | ||
2088 | |||
2089 | if (wm8962->dsp2_ena == old) | ||
2090 | goto out; | ||
2091 | |||
2092 | ret = 1; | ||
2093 | |||
2094 | if (dsp2_running) { | ||
2095 | if (wm8962->dsp2_ena) | ||
2096 | wm8962_dsp2_set_enable(codec, wm8962->dsp2_ena); | ||
2097 | else | ||
2098 | wm8962_dsp2_stop(codec); | ||
2099 | } | ||
2100 | |||
2101 | out: | ||
2102 | mutex_unlock(&codec->mutex); | ||
2103 | |||
2104 | return ret; | ||
2105 | } | ||
2106 | |||
1989 | /* The VU bits for the headphones are in a different register to the mute | 2107 | /* The VU bits for the headphones are in a different register to the mute |
1990 | * bits and only take effect on the PGA if it is actually powered. | 2108 | * bits and only take effect on the PGA if it is actually powered. |
1991 | */ | 2109 | */ |
@@ -2049,6 +2167,14 @@ static const char *cap_hpf_mode_text[] = { | |||
2049 | static const struct soc_enum cap_hpf_mode = | 2167 | static const struct soc_enum cap_hpf_mode = |
2050 | SOC_ENUM_SINGLE(WM8962_ADC_DAC_CONTROL_2, 10, 2, cap_hpf_mode_text); | 2168 | SOC_ENUM_SINGLE(WM8962_ADC_DAC_CONTROL_2, 10, 2, cap_hpf_mode_text); |
2051 | 2169 | ||
2170 | |||
2171 | static const char *cap_lhpf_mode_text[] = { | ||
2172 | "LPF", "HPF" | ||
2173 | }; | ||
2174 | |||
2175 | static const struct soc_enum cap_lhpf_mode = | ||
2176 | SOC_ENUM_SINGLE(WM8962_LHPF1, 1, 2, cap_lhpf_mode_text); | ||
2177 | |||
2052 | static const struct snd_kcontrol_new wm8962_snd_controls[] = { | 2178 | static const struct snd_kcontrol_new wm8962_snd_controls[] = { |
2053 | SOC_DOUBLE("Input Mixer Switch", WM8962_INPUT_MIXER_CONTROL_1, 3, 2, 1, 1), | 2179 | SOC_DOUBLE("Input Mixer Switch", WM8962_INPUT_MIXER_CONTROL_1, 3, 2, 1, 1), |
2054 | 2180 | ||
@@ -2077,6 +2203,8 @@ SOC_DOUBLE_R("Capture ZC Switch", WM8962_LEFT_INPUT_VOLUME, | |||
2077 | SOC_SINGLE("Capture HPF Switch", WM8962_ADC_DAC_CONTROL_1, 0, 1, 1), | 2203 | SOC_SINGLE("Capture HPF Switch", WM8962_ADC_DAC_CONTROL_1, 0, 1, 1), |
2078 | SOC_ENUM("Capture HPF Mode", cap_hpf_mode), | 2204 | SOC_ENUM("Capture HPF Mode", cap_hpf_mode), |
2079 | SOC_SINGLE("Capture HPF Cutoff", WM8962_ADC_DAC_CONTROL_2, 7, 7, 0), | 2205 | SOC_SINGLE("Capture HPF Cutoff", WM8962_ADC_DAC_CONTROL_2, 7, 7, 0), |
2206 | SOC_SINGLE("Capture LHPF Switch", WM8962_LHPF1, 0, 1, 0), | ||
2207 | SOC_ENUM("Capture LHPF Mode", cap_lhpf_mode), | ||
2080 | 2208 | ||
2081 | SOC_DOUBLE_R_TLV("Sidetone Volume", WM8962_DAC_DSP_MIXING_1, | 2209 | SOC_DOUBLE_R_TLV("Sidetone Volume", WM8962_DAC_DSP_MIXING_1, |
2082 | WM8962_DAC_DSP_MIXING_2, 4, 12, 0, st_tlv), | 2210 | WM8962_DAC_DSP_MIXING_2, 4, 12, 0, st_tlv), |
@@ -2134,6 +2262,11 @@ SOC_DOUBLE_R_TLV("EQ4 Volume", WM8962_EQ3, WM8962_EQ23, | |||
2134 | WM8962_EQL_B4_GAIN_SHIFT, 31, 0, eq_tlv), | 2262 | WM8962_EQL_B4_GAIN_SHIFT, 31, 0, eq_tlv), |
2135 | SOC_DOUBLE_R_TLV("EQ5 Volume", WM8962_EQ3, WM8962_EQ23, | 2263 | SOC_DOUBLE_R_TLV("EQ5 Volume", WM8962_EQ3, WM8962_EQ23, |
2136 | WM8962_EQL_B5_GAIN_SHIFT, 31, 0, eq_tlv), | 2264 | WM8962_EQL_B5_GAIN_SHIFT, 31, 0, eq_tlv), |
2265 | |||
2266 | WM8962_DSP2_ENABLE("VSS Switch", WM8962_VSS_ENA_SHIFT), | ||
2267 | WM8962_DSP2_ENABLE("HPF1 Switch", WM8962_HPF1_ENA_SHIFT), | ||
2268 | WM8962_DSP2_ENABLE("HPF2 Switch", WM8962_HPF2_ENA_SHIFT), | ||
2269 | WM8962_DSP2_ENABLE("HD Bass Switch", WM8962_HDBASS_ENA_SHIFT), | ||
2137 | }; | 2270 | }; |
2138 | 2271 | ||
2139 | static const struct snd_kcontrol_new wm8962_spk_mono_controls[] = { | 2272 | static const struct snd_kcontrol_new wm8962_spk_mono_controls[] = { |
@@ -2395,6 +2528,31 @@ static int out_pga_event(struct snd_soc_dapm_widget *w, | |||
2395 | } | 2528 | } |
2396 | } | 2529 | } |
2397 | 2530 | ||
2531 | static int dsp2_event(struct snd_soc_dapm_widget *w, | ||
2532 | struct snd_kcontrol *kcontrol, int event) | ||
2533 | { | ||
2534 | struct snd_soc_codec *codec = w->codec; | ||
2535 | struct wm8962_priv *wm8962 = snd_soc_codec_get_drvdata(codec); | ||
2536 | |||
2537 | switch (event) { | ||
2538 | case SND_SOC_DAPM_POST_PMU: | ||
2539 | if (wm8962->dsp2_ena) | ||
2540 | wm8962_dsp2_start(codec); | ||
2541 | break; | ||
2542 | |||
2543 | case SND_SOC_DAPM_PRE_PMD: | ||
2544 | if (wm8962->dsp2_ena) | ||
2545 | wm8962_dsp2_stop(codec); | ||
2546 | break; | ||
2547 | |||
2548 | default: | ||
2549 | BUG(); | ||
2550 | return -EINVAL; | ||
2551 | } | ||
2552 | |||
2553 | return 0; | ||
2554 | } | ||
2555 | |||
2398 | static const char *st_text[] = { "None", "Right", "Left" }; | 2556 | static const char *st_text[] = { "None", "Right", "Left" }; |
2399 | 2557 | ||
2400 | static const struct soc_enum str_enum = | 2558 | static const struct soc_enum str_enum = |
@@ -2517,6 +2675,9 @@ SND_SOC_DAPM_SUPPLY("SYSCLK", WM8962_CLOCKING2, 5, 0, sysclk_event, | |||
2517 | SND_SOC_DAPM_SUPPLY("Charge Pump", WM8962_CHARGE_PUMP_1, 0, 0, cp_event, | 2675 | SND_SOC_DAPM_SUPPLY("Charge Pump", WM8962_CHARGE_PUMP_1, 0, 0, cp_event, |
2518 | SND_SOC_DAPM_POST_PMU), | 2676 | SND_SOC_DAPM_POST_PMU), |
2519 | SND_SOC_DAPM_SUPPLY("TOCLK", WM8962_ADDITIONAL_CONTROL_1, 0, 0, NULL, 0), | 2677 | SND_SOC_DAPM_SUPPLY("TOCLK", WM8962_ADDITIONAL_CONTROL_1, 0, 0, NULL, 0), |
2678 | SND_SOC_DAPM_SUPPLY_S("DSP2", 1, WM8962_DSP2_POWER_MANAGEMENT, | ||
2679 | WM8962_DSP2_ENA_SHIFT, 0, dsp2_event, | ||
2680 | SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_PRE_PMD), | ||
2520 | 2681 | ||
2521 | SND_SOC_DAPM_MIXER("INPGAL", WM8962_LEFT_INPUT_PGA_CONTROL, 4, 0, | 2682 | SND_SOC_DAPM_MIXER("INPGAL", WM8962_LEFT_INPUT_PGA_CONTROL, 4, 0, |
2522 | inpgal, ARRAY_SIZE(inpgal)), | 2683 | inpgal, ARRAY_SIZE(inpgal)), |
@@ -2612,11 +2773,13 @@ static const struct snd_soc_dapm_route wm8962_intercon[] = { | |||
2612 | { "ADCL", NULL, "TOCLK" }, | 2773 | { "ADCL", NULL, "TOCLK" }, |
2613 | { "ADCL", NULL, "MIXINL" }, | 2774 | { "ADCL", NULL, "MIXINL" }, |
2614 | { "ADCL", NULL, "DMIC" }, | 2775 | { "ADCL", NULL, "DMIC" }, |
2776 | { "ADCL", NULL, "DSP2" }, | ||
2615 | 2777 | ||
2616 | { "ADCR", NULL, "SYSCLK" }, | 2778 | { "ADCR", NULL, "SYSCLK" }, |
2617 | { "ADCR", NULL, "TOCLK" }, | 2779 | { "ADCR", NULL, "TOCLK" }, |
2618 | { "ADCR", NULL, "MIXINR" }, | 2780 | { "ADCR", NULL, "MIXINR" }, |
2619 | { "ADCR", NULL, "DMIC" }, | 2781 | { "ADCR", NULL, "DMIC" }, |
2782 | { "ADCR", NULL, "DSP2" }, | ||
2620 | 2783 | ||
2621 | { "STL", "Left", "ADCL" }, | 2784 | { "STL", "Left", "ADCL" }, |
2622 | { "STL", "Right", "ADCR" }, | 2785 | { "STL", "Right", "ADCR" }, |
@@ -2628,11 +2791,13 @@ static const struct snd_soc_dapm_route wm8962_intercon[] = { | |||
2628 | { "DACL", NULL, "TOCLK" }, | 2791 | { "DACL", NULL, "TOCLK" }, |
2629 | { "DACL", NULL, "Beep" }, | 2792 | { "DACL", NULL, "Beep" }, |
2630 | { "DACL", NULL, "STL" }, | 2793 | { "DACL", NULL, "STL" }, |
2794 | { "DACL", NULL, "DSP2" }, | ||
2631 | 2795 | ||
2632 | { "DACR", NULL, "SYSCLK" }, | 2796 | { "DACR", NULL, "SYSCLK" }, |
2633 | { "DACR", NULL, "TOCLK" }, | 2797 | { "DACR", NULL, "TOCLK" }, |
2634 | { "DACR", NULL, "Beep" }, | 2798 | { "DACR", NULL, "Beep" }, |
2635 | { "DACR", NULL, "STR" }, | 2799 | { "DACR", NULL, "STR" }, |
2800 | { "DACR", NULL, "DSP2" }, | ||
2636 | 2801 | ||
2637 | { "HPMIXL", "IN4L Switch", "IN4L" }, | 2802 | { "HPMIXL", "IN4L Switch", "IN4L" }, |
2638 | { "HPMIXL", "IN4R Switch", "IN4R" }, | 2803 | { "HPMIXL", "IN4R Switch", "IN4R" }, |
@@ -3403,12 +3568,16 @@ static irqreturn_t wm8962_irq(int irq, void *data) | |||
3403 | struct wm8962_priv *wm8962 = snd_soc_codec_get_drvdata(codec); | 3568 | struct wm8962_priv *wm8962 = snd_soc_codec_get_drvdata(codec); |
3404 | int mask; | 3569 | int mask; |
3405 | int active; | 3570 | int active; |
3571 | int reg; | ||
3406 | 3572 | ||
3407 | mask = snd_soc_read(codec, WM8962_INTERRUPT_STATUS_2_MASK); | 3573 | mask = snd_soc_read(codec, WM8962_INTERRUPT_STATUS_2_MASK); |
3408 | 3574 | ||
3409 | active = snd_soc_read(codec, WM8962_INTERRUPT_STATUS_2); | 3575 | active = snd_soc_read(codec, WM8962_INTERRUPT_STATUS_2); |
3410 | active &= ~mask; | 3576 | active &= ~mask; |
3411 | 3577 | ||
3578 | if (!active) | ||
3579 | return IRQ_NONE; | ||
3580 | |||
3412 | /* Acknowledge the interrupts */ | 3581 | /* Acknowledge the interrupts */ |
3413 | snd_soc_write(codec, WM8962_INTERRUPT_STATUS_2, active); | 3582 | snd_soc_write(codec, WM8962_INTERRUPT_STATUS_2, active); |
3414 | 3583 | ||
@@ -3420,9 +3589,21 @@ static irqreturn_t wm8962_irq(int irq, void *data) | |||
3420 | if (active & WM8962_FIFOS_ERR_EINT) | 3589 | if (active & WM8962_FIFOS_ERR_EINT) |
3421 | dev_err(codec->dev, "FIFO error\n"); | 3590 | dev_err(codec->dev, "FIFO error\n"); |
3422 | 3591 | ||
3423 | if (active & WM8962_TEMP_SHUT_EINT) | 3592 | if (active & WM8962_TEMP_SHUT_EINT) { |
3424 | dev_crit(codec->dev, "Thermal shutdown\n"); | 3593 | dev_crit(codec->dev, "Thermal shutdown\n"); |
3425 | 3594 | ||
3595 | reg = snd_soc_read(codec, WM8962_THERMAL_SHUTDOWN_STATUS); | ||
3596 | |||
3597 | if (reg & WM8962_TEMP_ERR_HP) | ||
3598 | dev_crit(codec->dev, "Headphone thermal error\n"); | ||
3599 | if (reg & WM8962_TEMP_WARN_HP) | ||
3600 | dev_crit(codec->dev, "Headphone thermal warning\n"); | ||
3601 | if (reg & WM8962_TEMP_ERR_SPK) | ||
3602 | dev_crit(codec->dev, "Speaker thermal error\n"); | ||
3603 | if (reg & WM8962_TEMP_WARN_SPK) | ||
3604 | dev_crit(codec->dev, "Speaker thermal warning\n"); | ||
3605 | } | ||
3606 | |||
3426 | if (active & (WM8962_MICSCD_EINT | WM8962_MICD_EINT)) { | 3607 | if (active & (WM8962_MICSCD_EINT | WM8962_MICD_EINT)) { |
3427 | dev_dbg(codec->dev, "Microphone event detected\n"); | 3608 | dev_dbg(codec->dev, "Microphone event detected\n"); |
3428 | 3609 | ||
diff --git a/sound/soc/codecs/wm8993.c b/sound/soc/codecs/wm8993.c index 6e85b8869af7..eec8e1435116 100644 --- a/sound/soc/codecs/wm8993.c +++ b/sound/soc/codecs/wm8993.c | |||
@@ -847,6 +847,7 @@ SND_SOC_DAPM_SUPPLY("CLK_SYS", WM8993_BUS_CONTROL_1, 1, 0, clk_sys_event, | |||
847 | SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD), | 847 | SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD), |
848 | SND_SOC_DAPM_SUPPLY("TOCLK", WM8993_CLOCKING_1, 14, 0, NULL, 0), | 848 | SND_SOC_DAPM_SUPPLY("TOCLK", WM8993_CLOCKING_1, 14, 0, NULL, 0), |
849 | SND_SOC_DAPM_SUPPLY("CLK_DSP", WM8993_CLOCKING_3, 0, 0, NULL, 0), | 849 | SND_SOC_DAPM_SUPPLY("CLK_DSP", WM8993_CLOCKING_3, 0, 0, NULL, 0), |
850 | SND_SOC_DAPM_SUPPLY("VMID", SND_SOC_NOPM, 0, 0, NULL, 0), | ||
850 | 851 | ||
851 | SND_SOC_DAPM_ADC("ADCL", NULL, WM8993_POWER_MANAGEMENT_2, 1, 0), | 852 | SND_SOC_DAPM_ADC("ADCL", NULL, WM8993_POWER_MANAGEMENT_2, 1, 0), |
852 | SND_SOC_DAPM_ADC("ADCR", NULL, WM8993_POWER_MANAGEMENT_2, 0, 0), | 853 | SND_SOC_DAPM_ADC("ADCR", NULL, WM8993_POWER_MANAGEMENT_2, 0, 0), |
@@ -880,6 +881,9 @@ SND_SOC_DAPM_PGA("Direct Voice", SND_SOC_NOPM, 0, 0, NULL, 0), | |||
880 | }; | 881 | }; |
881 | 882 | ||
882 | static const struct snd_soc_dapm_route routes[] = { | 883 | static const struct snd_soc_dapm_route routes[] = { |
884 | { "MICBIAS1", NULL, "VMID" }, | ||
885 | { "MICBIAS2", NULL, "VMID" }, | ||
886 | |||
883 | { "ADCL", NULL, "CLK_SYS" }, | 887 | { "ADCL", NULL, "CLK_SYS" }, |
884 | { "ADCL", NULL, "CLK_DSP" }, | 888 | { "ADCL", NULL, "CLK_DSP" }, |
885 | { "ADCR", NULL, "CLK_SYS" }, | 889 | { "ADCR", NULL, "CLK_SYS" }, |
@@ -1433,7 +1437,8 @@ static int wm8993_probe(struct snd_soc_codec *codec) | |||
1433 | int ret, i, val; | 1437 | int ret, i, val; |
1434 | 1438 | ||
1435 | wm8993->hubs_data.hp_startup_mode = 1; | 1439 | wm8993->hubs_data.hp_startup_mode = 1; |
1436 | wm8993->hubs_data.dcs_codes = -2; | 1440 | wm8993->hubs_data.dcs_codes_l = -2; |
1441 | wm8993->hubs_data.dcs_codes_r = -2; | ||
1437 | wm8993->hubs_data.series_startup = 1; | 1442 | wm8993->hubs_data.series_startup = 1; |
1438 | 1443 | ||
1439 | ret = snd_soc_codec_set_cache_io(codec, 8, 16, SND_SOC_I2C); | 1444 | ret = snd_soc_codec_set_cache_io(codec, 8, 16, SND_SOC_I2C); |
diff --git a/sound/soc/codecs/wm8994-tables.c b/sound/soc/codecs/wm8994-tables.c index a87adbd05ee1..df5a8b9a250f 100644 --- a/sound/soc/codecs/wm8994-tables.c +++ b/sound/soc/codecs/wm8994-tables.c | |||
@@ -1073,8 +1073,8 @@ const struct wm8994_access_mask wm8994_access_masks[WM8994_CACHE_SIZE] = { | |||
1073 | { 0x0000, 0x0000 }, /* R1069 */ | 1073 | { 0x0000, 0x0000 }, /* R1069 */ |
1074 | { 0x0000, 0x0000 }, /* R1070 */ | 1074 | { 0x0000, 0x0000 }, /* R1070 */ |
1075 | { 0x0000, 0x0000 }, /* R1071 */ | 1075 | { 0x0000, 0x0000 }, /* R1071 */ |
1076 | { 0x0000, 0x0000 }, /* R1072 */ | 1076 | { 0x006F, 0x006F }, /* R1072 - AIF1 DAC1 Noise Gate */ |
1077 | { 0x0000, 0x0000 }, /* R1073 */ | 1077 | { 0x006F, 0x006F }, /* R1073 - AIF1 DAC2 Noise Gate */ |
1078 | { 0x0000, 0x0000 }, /* R1074 */ | 1078 | { 0x0000, 0x0000 }, /* R1074 */ |
1079 | { 0x0000, 0x0000 }, /* R1075 */ | 1079 | { 0x0000, 0x0000 }, /* R1075 */ |
1080 | { 0x0000, 0x0000 }, /* R1076 */ | 1080 | { 0x0000, 0x0000 }, /* R1076 */ |
@@ -1329,7 +1329,7 @@ const struct wm8994_access_mask wm8994_access_masks[WM8994_CACHE_SIZE] = { | |||
1329 | { 0x0000, 0x0000 }, /* R1325 */ | 1329 | { 0x0000, 0x0000 }, /* R1325 */ |
1330 | { 0x0000, 0x0000 }, /* R1326 */ | 1330 | { 0x0000, 0x0000 }, /* R1326 */ |
1331 | { 0x0000, 0x0000 }, /* R1327 */ | 1331 | { 0x0000, 0x0000 }, /* R1327 */ |
1332 | { 0x0000, 0x0000 }, /* R1328 */ | 1332 | { 0x006F, 0x006F }, /* R1328 - AIF2 DAC Noise Gate */ |
1333 | { 0x0000, 0x0000 }, /* R1329 */ | 1333 | { 0x0000, 0x0000 }, /* R1329 */ |
1334 | { 0x0000, 0x0000 }, /* R1330 */ | 1334 | { 0x0000, 0x0000 }, /* R1330 */ |
1335 | { 0x0000, 0x0000 }, /* R1331 */ | 1335 | { 0x0000, 0x0000 }, /* R1331 */ |
@@ -1635,8 +1635,8 @@ const u16 wm8994_reg_defaults[WM8994_CACHE_SIZE] = { | |||
1635 | 0x0000, /* R58 - MICBIAS */ | 1635 | 0x0000, /* R58 - MICBIAS */ |
1636 | 0x000D, /* R59 - LDO 1 */ | 1636 | 0x000D, /* R59 - LDO 1 */ |
1637 | 0x0003, /* R60 - LDO 2 */ | 1637 | 0x0003, /* R60 - LDO 2 */ |
1638 | 0x0000, /* R61 */ | 1638 | 0x0039, /* R61 - MICBIAS1 */ |
1639 | 0x0000, /* R62 */ | 1639 | 0x0039, /* R62 - MICBIAS2 */ |
1640 | 0x0000, /* R63 */ | 1640 | 0x0000, /* R63 */ |
1641 | 0x0000, /* R64 */ | 1641 | 0x0000, /* R64 */ |
1642 | 0x0000, /* R65 */ | 1642 | 0x0000, /* R65 */ |
@@ -2646,8 +2646,8 @@ const u16 wm8994_reg_defaults[WM8994_CACHE_SIZE] = { | |||
2646 | 0x0000, /* R1069 */ | 2646 | 0x0000, /* R1069 */ |
2647 | 0x0000, /* R1070 */ | 2647 | 0x0000, /* R1070 */ |
2648 | 0x0000, /* R1071 */ | 2648 | 0x0000, /* R1071 */ |
2649 | 0x0000, /* R1072 */ | 2649 | 0x0068, /* R1072 - AIF1 DAC1 Noise Gate */ |
2650 | 0x0000, /* R1073 */ | 2650 | 0x0068, /* R1073 - AIF1 DAC2 Noise Gate */ |
2651 | 0x0000, /* R1074 */ | 2651 | 0x0000, /* R1074 */ |
2652 | 0x0000, /* R1075 */ | 2652 | 0x0000, /* R1075 */ |
2653 | 0x0000, /* R1076 */ | 2653 | 0x0000, /* R1076 */ |
@@ -2902,7 +2902,7 @@ const u16 wm8994_reg_defaults[WM8994_CACHE_SIZE] = { | |||
2902 | 0x0000, /* R1325 */ | 2902 | 0x0000, /* R1325 */ |
2903 | 0x0000, /* R1326 */ | 2903 | 0x0000, /* R1326 */ |
2904 | 0x0000, /* R1327 */ | 2904 | 0x0000, /* R1327 */ |
2905 | 0x0000, /* R1328 */ | 2905 | 0x0068, /* R1328 - AIF2 DAC Noise Gate */ |
2906 | 0x0000, /* R1329 */ | 2906 | 0x0000, /* R1329 */ |
2907 | 0x0000, /* R1330 */ | 2907 | 0x0000, /* R1330 */ |
2908 | 0x0000, /* R1331 */ | 2908 | 0x0000, /* R1331 */ |
diff --git a/sound/soc/codecs/wm8994.c b/sound/soc/codecs/wm8994.c index b393f9fac97a..e5372675123d 100644 --- a/sound/soc/codecs/wm8994.c +++ b/sound/soc/codecs/wm8994.c | |||
@@ -107,6 +107,7 @@ static int wm8994_volatile(struct snd_soc_codec *codec, unsigned int reg) | |||
107 | case WM8994_LDO_2: | 107 | case WM8994_LDO_2: |
108 | case WM8958_DSP2_EXECCONTROL: | 108 | case WM8958_DSP2_EXECCONTROL: |
109 | case WM8958_MIC_DETECT_3: | 109 | case WM8958_MIC_DETECT_3: |
110 | case WM8994_DC_SERVO_4E: | ||
110 | return 1; | 111 | return 1; |
111 | default: | 112 | default: |
112 | return 0; | 113 | return 0; |
@@ -281,6 +282,7 @@ static const DECLARE_TLV_DB_SCALE(digital_tlv, -7200, 75, 1); | |||
281 | static const DECLARE_TLV_DB_SCALE(st_tlv, -3600, 300, 0); | 282 | static const DECLARE_TLV_DB_SCALE(st_tlv, -3600, 300, 0); |
282 | static const DECLARE_TLV_DB_SCALE(wm8994_3d_tlv, -1600, 183, 0); | 283 | static const DECLARE_TLV_DB_SCALE(wm8994_3d_tlv, -1600, 183, 0); |
283 | static const DECLARE_TLV_DB_SCALE(eq_tlv, -1200, 100, 0); | 284 | static const DECLARE_TLV_DB_SCALE(eq_tlv, -1200, 100, 0); |
285 | static const DECLARE_TLV_DB_SCALE(ng_tlv, -10200, 600, 0); | ||
284 | 286 | ||
285 | #define WM8994_DRC_SWITCH(xname, reg, shift) \ | 287 | #define WM8994_DRC_SWITCH(xname, reg, shift) \ |
286 | { .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = xname, \ | 288 | { .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = xname, \ |
@@ -660,8 +662,45 @@ SOC_SINGLE_TLV("AIF2 EQ5 Volume", WM8994_AIF2_EQ_GAINS_2, 6, 31, 0, | |||
660 | eq_tlv), | 662 | eq_tlv), |
661 | }; | 663 | }; |
662 | 664 | ||
665 | static const char *wm8958_ng_text[] = { | ||
666 | "30ms", "125ms", "250ms", "500ms", | ||
667 | }; | ||
668 | |||
669 | static const struct soc_enum wm8958_aif1dac1_ng_hold = | ||
670 | SOC_ENUM_SINGLE(WM8958_AIF1_DAC1_NOISE_GATE, | ||
671 | WM8958_AIF1DAC1_NG_THR_SHIFT, 4, wm8958_ng_text); | ||
672 | |||
673 | static const struct soc_enum wm8958_aif1dac2_ng_hold = | ||
674 | SOC_ENUM_SINGLE(WM8958_AIF1_DAC2_NOISE_GATE, | ||
675 | WM8958_AIF1DAC2_NG_THR_SHIFT, 4, wm8958_ng_text); | ||
676 | |||
677 | static const struct soc_enum wm8958_aif2dac_ng_hold = | ||
678 | SOC_ENUM_SINGLE(WM8958_AIF2_DAC_NOISE_GATE, | ||
679 | WM8958_AIF2DAC_NG_THR_SHIFT, 4, wm8958_ng_text); | ||
680 | |||
663 | static const struct snd_kcontrol_new wm8958_snd_controls[] = { | 681 | static const struct snd_kcontrol_new wm8958_snd_controls[] = { |
664 | SOC_SINGLE_TLV("AIF3 Boost Volume", WM8958_AIF3_CONTROL_2, 10, 3, 0, aif_tlv), | 682 | SOC_SINGLE_TLV("AIF3 Boost Volume", WM8958_AIF3_CONTROL_2, 10, 3, 0, aif_tlv), |
683 | |||
684 | SOC_SINGLE("AIF1DAC1 Noise Gate Switch", WM8958_AIF1_DAC1_NOISE_GATE, | ||
685 | WM8958_AIF1DAC1_NG_ENA_SHIFT, 1, 0), | ||
686 | SOC_ENUM("AIF1DAC1 Noise Gate Hold Time", wm8958_aif1dac1_ng_hold), | ||
687 | SOC_SINGLE_TLV("AIF1DAC1 Noise Gate Threshold Volume", | ||
688 | WM8958_AIF1_DAC1_NOISE_GATE, WM8958_AIF1DAC1_NG_THR_SHIFT, | ||
689 | 7, 1, ng_tlv), | ||
690 | |||
691 | SOC_SINGLE("AIF1DAC2 Noise Gate Switch", WM8958_AIF1_DAC2_NOISE_GATE, | ||
692 | WM8958_AIF1DAC2_NG_ENA_SHIFT, 1, 0), | ||
693 | SOC_ENUM("AIF1DAC2 Noise Gate Hold Time", wm8958_aif1dac2_ng_hold), | ||
694 | SOC_SINGLE_TLV("AIF1DAC2 Noise Gate Threshold Volume", | ||
695 | WM8958_AIF1_DAC2_NOISE_GATE, WM8958_AIF1DAC2_NG_THR_SHIFT, | ||
696 | 7, 1, ng_tlv), | ||
697 | |||
698 | SOC_SINGLE("AIF2DAC Noise Gate Switch", WM8958_AIF2_DAC_NOISE_GATE, | ||
699 | WM8958_AIF2DAC_NG_ENA_SHIFT, 1, 0), | ||
700 | SOC_ENUM("AIF2DAC Noise Gate Hold Time", wm8958_aif2dac_ng_hold), | ||
701 | SOC_SINGLE_TLV("AIF2DAC Noise Gate Threshold Volume", | ||
702 | WM8958_AIF2_DAC_NOISE_GATE, WM8958_AIF2DAC_NG_THR_SHIFT, | ||
703 | 7, 1, ng_tlv), | ||
665 | }; | 704 | }; |
666 | 705 | ||
667 | static int clk_sys_event(struct snd_soc_dapm_widget *w, | 706 | static int clk_sys_event(struct snd_soc_dapm_widget *w, |
@@ -681,6 +720,97 @@ static int clk_sys_event(struct snd_soc_dapm_widget *w, | |||
681 | return 0; | 720 | return 0; |
682 | } | 721 | } |
683 | 722 | ||
723 | static void vmid_reference(struct snd_soc_codec *codec) | ||
724 | { | ||
725 | struct wm8994_priv *wm8994 = snd_soc_codec_get_drvdata(codec); | ||
726 | |||
727 | wm8994->vmid_refcount++; | ||
728 | |||
729 | dev_dbg(codec->dev, "Referencing VMID, refcount is now %d\n", | ||
730 | wm8994->vmid_refcount); | ||
731 | |||
732 | if (wm8994->vmid_refcount == 1) { | ||
733 | /* Startup bias, VMID ramp & buffer */ | ||
734 | snd_soc_update_bits(codec, WM8994_ANTIPOP_2, | ||
735 | WM8994_STARTUP_BIAS_ENA | | ||
736 | WM8994_VMID_BUF_ENA | | ||
737 | WM8994_VMID_RAMP_MASK, | ||
738 | WM8994_STARTUP_BIAS_ENA | | ||
739 | WM8994_VMID_BUF_ENA | | ||
740 | (0x11 << WM8994_VMID_RAMP_SHIFT)); | ||
741 | |||
742 | /* Main bias enable, VMID=2x40k */ | ||
743 | snd_soc_update_bits(codec, WM8994_POWER_MANAGEMENT_1, | ||
744 | WM8994_BIAS_ENA | | ||
745 | WM8994_VMID_SEL_MASK, | ||
746 | WM8994_BIAS_ENA | 0x2); | ||
747 | |||
748 | msleep(20); | ||
749 | } | ||
750 | } | ||
751 | |||
752 | static void vmid_dereference(struct snd_soc_codec *codec) | ||
753 | { | ||
754 | struct wm8994_priv *wm8994 = snd_soc_codec_get_drvdata(codec); | ||
755 | |||
756 | wm8994->vmid_refcount--; | ||
757 | |||
758 | dev_dbg(codec->dev, "Dereferencing VMID, refcount is now %d\n", | ||
759 | wm8994->vmid_refcount); | ||
760 | |||
761 | if (wm8994->vmid_refcount == 0) { | ||
762 | /* Switch over to startup biases */ | ||
763 | snd_soc_update_bits(codec, WM8994_ANTIPOP_2, | ||
764 | WM8994_BIAS_SRC | | ||
765 | WM8994_STARTUP_BIAS_ENA | | ||
766 | WM8994_VMID_BUF_ENA | | ||
767 | WM8994_VMID_RAMP_MASK, | ||
768 | WM8994_BIAS_SRC | | ||
769 | WM8994_STARTUP_BIAS_ENA | | ||
770 | WM8994_VMID_BUF_ENA | | ||
771 | (1 << WM8994_VMID_RAMP_SHIFT)); | ||
772 | |||
773 | /* Disable main biases */ | ||
774 | snd_soc_update_bits(codec, WM8994_POWER_MANAGEMENT_1, | ||
775 | WM8994_BIAS_ENA | | ||
776 | WM8994_VMID_SEL_MASK, 0); | ||
777 | |||
778 | /* Discharge line */ | ||
779 | snd_soc_update_bits(codec, WM8994_ANTIPOP_1, | ||
780 | WM8994_LINEOUT1_DISCH | | ||
781 | WM8994_LINEOUT2_DISCH, | ||
782 | WM8994_LINEOUT1_DISCH | | ||
783 | WM8994_LINEOUT2_DISCH); | ||
784 | |||
785 | msleep(5); | ||
786 | |||
787 | /* Switch off startup biases */ | ||
788 | snd_soc_update_bits(codec, WM8994_ANTIPOP_2, | ||
789 | WM8994_BIAS_SRC | | ||
790 | WM8994_STARTUP_BIAS_ENA | | ||
791 | WM8994_VMID_BUF_ENA | | ||
792 | WM8994_VMID_RAMP_MASK, 0); | ||
793 | } | ||
794 | } | ||
795 | |||
796 | static int vmid_event(struct snd_soc_dapm_widget *w, | ||
797 | struct snd_kcontrol *kcontrol, int event) | ||
798 | { | ||
799 | struct snd_soc_codec *codec = w->codec; | ||
800 | |||
801 | switch (event) { | ||
802 | case SND_SOC_DAPM_PRE_PMU: | ||
803 | vmid_reference(codec); | ||
804 | break; | ||
805 | |||
806 | case SND_SOC_DAPM_POST_PMD: | ||
807 | vmid_dereference(codec); | ||
808 | break; | ||
809 | } | ||
810 | |||
811 | return 0; | ||
812 | } | ||
813 | |||
684 | static void wm8994_update_class_w(struct snd_soc_codec *codec) | 814 | static void wm8994_update_class_w(struct snd_soc_codec *codec) |
685 | { | 815 | { |
686 | struct wm8994_priv *wm8994 = snd_soc_codec_get_drvdata(codec); | 816 | struct wm8994_priv *wm8994 = snd_soc_codec_get_drvdata(codec); |
@@ -1208,6 +1338,8 @@ SND_SOC_DAPM_INPUT("Clock"), | |||
1208 | 1338 | ||
1209 | SND_SOC_DAPM_SUPPLY_S("MICBIAS Supply", 1, SND_SOC_NOPM, 0, 0, micbias_ev, | 1339 | SND_SOC_DAPM_SUPPLY_S("MICBIAS Supply", 1, SND_SOC_NOPM, 0, 0, micbias_ev, |
1210 | SND_SOC_DAPM_PRE_PMU), | 1340 | SND_SOC_DAPM_PRE_PMU), |
1341 | SND_SOC_DAPM_SUPPLY("VMID", SND_SOC_NOPM, 0, 0, vmid_event, | ||
1342 | SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD), | ||
1211 | 1343 | ||
1212 | SND_SOC_DAPM_SUPPLY("CLK_SYS", SND_SOC_NOPM, 0, 0, clk_sys_event, | 1344 | SND_SOC_DAPM_SUPPLY("CLK_SYS", SND_SOC_NOPM, 0, 0, clk_sys_event, |
1213 | SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_PRE_PMD), | 1345 | SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_PRE_PMD), |
@@ -1525,6 +1657,8 @@ static const struct snd_soc_dapm_route wm8994_revd_intercon[] = { | |||
1525 | static const struct snd_soc_dapm_route wm8994_intercon[] = { | 1657 | static const struct snd_soc_dapm_route wm8994_intercon[] = { |
1526 | { "AIF2DACL", NULL, "AIF2DAC Mux" }, | 1658 | { "AIF2DACL", NULL, "AIF2DAC Mux" }, |
1527 | { "AIF2DACR", NULL, "AIF2DAC Mux" }, | 1659 | { "AIF2DACR", NULL, "AIF2DAC Mux" }, |
1660 | { "MICBIAS1", NULL, "VMID" }, | ||
1661 | { "MICBIAS2", NULL, "VMID" }, | ||
1528 | }; | 1662 | }; |
1529 | 1663 | ||
1530 | static const struct snd_soc_dapm_route wm8958_intercon[] = { | 1664 | static const struct snd_soc_dapm_route wm8958_intercon[] = { |
@@ -1629,10 +1763,12 @@ static int _wm8994_set_fll(struct snd_soc_codec *codec, int id, int src, | |||
1629 | unsigned int freq_in, unsigned int freq_out) | 1763 | unsigned int freq_in, unsigned int freq_out) |
1630 | { | 1764 | { |
1631 | struct wm8994_priv *wm8994 = snd_soc_codec_get_drvdata(codec); | 1765 | struct wm8994_priv *wm8994 = snd_soc_codec_get_drvdata(codec); |
1766 | struct wm8994 *control = codec->control_data; | ||
1632 | int reg_offset, ret; | 1767 | int reg_offset, ret; |
1633 | struct fll_div fll; | 1768 | struct fll_div fll; |
1634 | u16 reg, aif1, aif2; | 1769 | u16 reg, aif1, aif2; |
1635 | unsigned long timeout; | 1770 | unsigned long timeout; |
1771 | bool was_enabled; | ||
1636 | 1772 | ||
1637 | aif1 = snd_soc_read(codec, WM8994_AIF1_CLOCKING_1) | 1773 | aif1 = snd_soc_read(codec, WM8994_AIF1_CLOCKING_1) |
1638 | & WM8994_AIF1CLK_ENA; | 1774 | & WM8994_AIF1CLK_ENA; |
@@ -1653,6 +1789,9 @@ static int _wm8994_set_fll(struct snd_soc_codec *codec, int id, int src, | |||
1653 | return -EINVAL; | 1789 | return -EINVAL; |
1654 | } | 1790 | } |
1655 | 1791 | ||
1792 | reg = snd_soc_read(codec, WM8994_FLL1_CONTROL_1 + reg_offset); | ||
1793 | was_enabled = reg & WM8994_FLL1_ENA; | ||
1794 | |||
1656 | switch (src) { | 1795 | switch (src) { |
1657 | case 0: | 1796 | case 0: |
1658 | /* Allow no source specification when stopping */ | 1797 | /* Allow no source specification when stopping */ |
@@ -1719,6 +1858,21 @@ static int _wm8994_set_fll(struct snd_soc_codec *codec, int id, int src, | |||
1719 | 1858 | ||
1720 | /* Enable (with fractional mode if required) */ | 1859 | /* Enable (with fractional mode if required) */ |
1721 | if (freq_out) { | 1860 | if (freq_out) { |
1861 | /* Enable VMID if we need it */ | ||
1862 | if (!was_enabled) { | ||
1863 | switch (control->type) { | ||
1864 | case WM8994: | ||
1865 | vmid_reference(codec); | ||
1866 | break; | ||
1867 | case WM8958: | ||
1868 | if (wm8994->revision < 1) | ||
1869 | vmid_reference(codec); | ||
1870 | break; | ||
1871 | default: | ||
1872 | break; | ||
1873 | } | ||
1874 | } | ||
1875 | |||
1722 | if (fll.k) | 1876 | if (fll.k) |
1723 | reg = WM8994_FLL1_ENA | WM8994_FLL1_FRAC; | 1877 | reg = WM8994_FLL1_ENA | WM8994_FLL1_FRAC; |
1724 | else | 1878 | else |
@@ -1736,6 +1890,20 @@ static int _wm8994_set_fll(struct snd_soc_codec *codec, int id, int src, | |||
1736 | } else { | 1890 | } else { |
1737 | msleep(5); | 1891 | msleep(5); |
1738 | } | 1892 | } |
1893 | } else { | ||
1894 | if (was_enabled) { | ||
1895 | switch (control->type) { | ||
1896 | case WM8994: | ||
1897 | vmid_dereference(codec); | ||
1898 | break; | ||
1899 | case WM8958: | ||
1900 | if (wm8994->revision < 1) | ||
1901 | vmid_dereference(codec); | ||
1902 | break; | ||
1903 | default: | ||
1904 | break; | ||
1905 | } | ||
1906 | } | ||
1739 | } | 1907 | } |
1740 | 1908 | ||
1741 | wm8994->fll[id].in = freq_in; | 1909 | wm8994->fll[id].in = freq_in; |
@@ -1852,9 +2020,6 @@ static int wm8994_set_bias_level(struct snd_soc_codec *codec, | |||
1852 | break; | 2020 | break; |
1853 | 2021 | ||
1854 | case SND_SOC_BIAS_PREPARE: | 2022 | case SND_SOC_BIAS_PREPARE: |
1855 | /* VMID=2x40k */ | ||
1856 | snd_soc_update_bits(codec, WM8994_POWER_MANAGEMENT_1, | ||
1857 | WM8994_VMID_SEL_MASK, 0x2); | ||
1858 | break; | 2023 | break; |
1859 | 2024 | ||
1860 | case SND_SOC_BIAS_STANDBY: | 2025 | case SND_SOC_BIAS_STANDBY: |
@@ -1896,65 +2061,13 @@ static int wm8994_set_bias_level(struct snd_soc_codec *codec, | |||
1896 | WM8994_LINEOUT2_DISCH, | 2061 | WM8994_LINEOUT2_DISCH, |
1897 | WM8994_LINEOUT1_DISCH | | 2062 | WM8994_LINEOUT1_DISCH | |
1898 | WM8994_LINEOUT2_DISCH); | 2063 | WM8994_LINEOUT2_DISCH); |
1899 | |||
1900 | /* Startup bias, VMID ramp & buffer */ | ||
1901 | snd_soc_update_bits(codec, WM8994_ANTIPOP_2, | ||
1902 | WM8994_STARTUP_BIAS_ENA | | ||
1903 | WM8994_VMID_BUF_ENA | | ||
1904 | WM8994_VMID_RAMP_MASK, | ||
1905 | WM8994_STARTUP_BIAS_ENA | | ||
1906 | WM8994_VMID_BUF_ENA | | ||
1907 | (0x11 << WM8994_VMID_RAMP_SHIFT)); | ||
1908 | |||
1909 | /* Main bias enable, VMID=2x40k */ | ||
1910 | snd_soc_update_bits(codec, WM8994_POWER_MANAGEMENT_1, | ||
1911 | WM8994_BIAS_ENA | | ||
1912 | WM8994_VMID_SEL_MASK, | ||
1913 | WM8994_BIAS_ENA | 0x2); | ||
1914 | |||
1915 | msleep(20); | ||
1916 | } | 2064 | } |
1917 | 2065 | ||
1918 | /* VMID=2x500k */ | ||
1919 | snd_soc_update_bits(codec, WM8994_POWER_MANAGEMENT_1, | ||
1920 | WM8994_VMID_SEL_MASK, 0x4); | ||
1921 | 2066 | ||
1922 | break; | 2067 | break; |
1923 | 2068 | ||
1924 | case SND_SOC_BIAS_OFF: | 2069 | case SND_SOC_BIAS_OFF: |
1925 | if (codec->dapm.bias_level == SND_SOC_BIAS_STANDBY) { | 2070 | if (codec->dapm.bias_level == SND_SOC_BIAS_STANDBY) { |
1926 | /* Switch over to startup biases */ | ||
1927 | snd_soc_update_bits(codec, WM8994_ANTIPOP_2, | ||
1928 | WM8994_BIAS_SRC | | ||
1929 | WM8994_STARTUP_BIAS_ENA | | ||
1930 | WM8994_VMID_BUF_ENA | | ||
1931 | WM8994_VMID_RAMP_MASK, | ||
1932 | WM8994_BIAS_SRC | | ||
1933 | WM8994_STARTUP_BIAS_ENA | | ||
1934 | WM8994_VMID_BUF_ENA | | ||
1935 | (1 << WM8994_VMID_RAMP_SHIFT)); | ||
1936 | |||
1937 | /* Disable main biases */ | ||
1938 | snd_soc_update_bits(codec, WM8994_POWER_MANAGEMENT_1, | ||
1939 | WM8994_BIAS_ENA | | ||
1940 | WM8994_VMID_SEL_MASK, 0); | ||
1941 | |||
1942 | /* Discharge line */ | ||
1943 | snd_soc_update_bits(codec, WM8994_ANTIPOP_1, | ||
1944 | WM8994_LINEOUT1_DISCH | | ||
1945 | WM8994_LINEOUT2_DISCH, | ||
1946 | WM8994_LINEOUT1_DISCH | | ||
1947 | WM8994_LINEOUT2_DISCH); | ||
1948 | |||
1949 | msleep(5); | ||
1950 | |||
1951 | /* Switch off startup biases */ | ||
1952 | snd_soc_update_bits(codec, WM8994_ANTIPOP_2, | ||
1953 | WM8994_BIAS_SRC | | ||
1954 | WM8994_STARTUP_BIAS_ENA | | ||
1955 | WM8994_VMID_BUF_ENA | | ||
1956 | WM8994_VMID_RAMP_MASK, 0); | ||
1957 | |||
1958 | wm8994->cur_fw = NULL; | 2071 | wm8994->cur_fw = NULL; |
1959 | 2072 | ||
1960 | pm_runtime_put(codec->dev); | 2073 | pm_runtime_put(codec->dev); |
@@ -2384,6 +2497,21 @@ static int wm8994_set_tristate(struct snd_soc_dai *codec_dai, int tristate) | |||
2384 | return snd_soc_update_bits(codec, reg, mask, val); | 2497 | return snd_soc_update_bits(codec, reg, mask, val); |
2385 | } | 2498 | } |
2386 | 2499 | ||
2500 | static int wm8994_aif2_probe(struct snd_soc_dai *dai) | ||
2501 | { | ||
2502 | struct snd_soc_codec *codec = dai->codec; | ||
2503 | |||
2504 | /* Disable the pulls on the AIF if we're using it to save power. */ | ||
2505 | snd_soc_update_bits(codec, WM8994_GPIO_3, | ||
2506 | WM8994_GPN_PU | WM8994_GPN_PD, 0); | ||
2507 | snd_soc_update_bits(codec, WM8994_GPIO_4, | ||
2508 | WM8994_GPN_PU | WM8994_GPN_PD, 0); | ||
2509 | snd_soc_update_bits(codec, WM8994_GPIO_5, | ||
2510 | WM8994_GPN_PU | WM8994_GPN_PD, 0); | ||
2511 | |||
2512 | return 0; | ||
2513 | } | ||
2514 | |||
2387 | #define WM8994_RATES SNDRV_PCM_RATE_8000_96000 | 2515 | #define WM8994_RATES SNDRV_PCM_RATE_8000_96000 |
2388 | 2516 | ||
2389 | #define WM8994_FORMATS (SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S20_3LE |\ | 2517 | #define WM8994_FORMATS (SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S20_3LE |\ |
@@ -2451,6 +2579,7 @@ static struct snd_soc_dai_driver wm8994_dai[] = { | |||
2451 | .rates = WM8994_RATES, | 2579 | .rates = WM8994_RATES, |
2452 | .formats = WM8994_FORMATS, | 2580 | .formats = WM8994_FORMATS, |
2453 | }, | 2581 | }, |
2582 | .probe = wm8994_aif2_probe, | ||
2454 | .ops = &wm8994_aif2_dai_ops, | 2583 | .ops = &wm8994_aif2_dai_ops, |
2455 | }, | 2584 | }, |
2456 | { | 2585 | { |
@@ -2916,6 +3045,24 @@ static irqreturn_t wm8994_fifo_error(int irq, void *data) | |||
2916 | return IRQ_HANDLED; | 3045 | return IRQ_HANDLED; |
2917 | } | 3046 | } |
2918 | 3047 | ||
3048 | static irqreturn_t wm8994_temp_warn(int irq, void *data) | ||
3049 | { | ||
3050 | struct snd_soc_codec *codec = data; | ||
3051 | |||
3052 | dev_err(codec->dev, "Thermal warning\n"); | ||
3053 | |||
3054 | return IRQ_HANDLED; | ||
3055 | } | ||
3056 | |||
3057 | static irqreturn_t wm8994_temp_shut(int irq, void *data) | ||
3058 | { | ||
3059 | struct snd_soc_codec *codec = data; | ||
3060 | |||
3061 | dev_crit(codec->dev, "Thermal shutdown\n"); | ||
3062 | |||
3063 | return IRQ_HANDLED; | ||
3064 | } | ||
3065 | |||
2919 | static int wm8994_codec_probe(struct snd_soc_codec *codec) | 3066 | static int wm8994_codec_probe(struct snd_soc_codec *codec) |
2920 | { | 3067 | { |
2921 | struct wm8994 *control; | 3068 | struct wm8994 *control; |
@@ -2972,13 +3119,14 @@ static int wm8994_codec_probe(struct snd_soc_codec *codec) | |||
2972 | switch (wm8994->revision) { | 3119 | switch (wm8994->revision) { |
2973 | case 2: | 3120 | case 2: |
2974 | case 3: | 3121 | case 3: |
2975 | wm8994->hubs.dcs_codes = -5; | 3122 | wm8994->hubs.dcs_codes_l = -5; |
3123 | wm8994->hubs.dcs_codes_r = -5; | ||
2976 | wm8994->hubs.hp_startup_mode = 1; | 3124 | wm8994->hubs.hp_startup_mode = 1; |
2977 | wm8994->hubs.dcs_readback_mode = 1; | 3125 | wm8994->hubs.dcs_readback_mode = 1; |
2978 | wm8994->hubs.series_startup = 1; | 3126 | wm8994->hubs.series_startup = 1; |
2979 | break; | 3127 | break; |
2980 | default: | 3128 | default: |
2981 | wm8994->hubs.dcs_readback_mode = 1; | 3129 | wm8994->hubs.dcs_readback_mode = 2; |
2982 | break; | 3130 | break; |
2983 | } | 3131 | } |
2984 | break; | 3132 | break; |
@@ -2993,6 +3141,10 @@ static int wm8994_codec_probe(struct snd_soc_codec *codec) | |||
2993 | 3141 | ||
2994 | wm8994_request_irq(codec->control_data, WM8994_IRQ_FIFOS_ERR, | 3142 | wm8994_request_irq(codec->control_data, WM8994_IRQ_FIFOS_ERR, |
2995 | wm8994_fifo_error, "FIFO error", codec); | 3143 | wm8994_fifo_error, "FIFO error", codec); |
3144 | wm8994_request_irq(wm8994->control_data, WM8994_IRQ_TEMP_WARN, | ||
3145 | wm8994_temp_warn, "Thermal warning", codec); | ||
3146 | wm8994_request_irq(wm8994->control_data, WM8994_IRQ_TEMP_SHUT, | ||
3147 | wm8994_temp_shut, "Thermal shutdown", codec); | ||
2996 | 3148 | ||
2997 | ret = wm8994_request_irq(codec->control_data, WM8994_IRQ_DCS_DONE, | 3149 | ret = wm8994_request_irq(codec->control_data, WM8994_IRQ_DCS_DONE, |
2998 | wm_hubs_dcs_done, "DC servo done", | 3150 | wm_hubs_dcs_done, "DC servo done", |
@@ -3257,6 +3409,8 @@ err_irq: | |||
3257 | wm8994_free_irq(codec->control_data, WM8994_IRQ_DCS_DONE, | 3409 | wm8994_free_irq(codec->control_data, WM8994_IRQ_DCS_DONE, |
3258 | &wm8994->hubs); | 3410 | &wm8994->hubs); |
3259 | wm8994_free_irq(codec->control_data, WM8994_IRQ_FIFOS_ERR, codec); | 3411 | wm8994_free_irq(codec->control_data, WM8994_IRQ_FIFOS_ERR, codec); |
3412 | wm8994_free_irq(codec->control_data, WM8994_IRQ_TEMP_SHUT, codec); | ||
3413 | wm8994_free_irq(codec->control_data, WM8994_IRQ_TEMP_WARN, codec); | ||
3260 | err: | 3414 | err: |
3261 | kfree(wm8994); | 3415 | kfree(wm8994); |
3262 | return ret; | 3416 | return ret; |
@@ -3279,6 +3433,8 @@ static int wm8994_codec_remove(struct snd_soc_codec *codec) | |||
3279 | wm8994_free_irq(codec->control_data, WM8994_IRQ_DCS_DONE, | 3433 | wm8994_free_irq(codec->control_data, WM8994_IRQ_DCS_DONE, |
3280 | &wm8994->hubs); | 3434 | &wm8994->hubs); |
3281 | wm8994_free_irq(codec->control_data, WM8994_IRQ_FIFOS_ERR, codec); | 3435 | wm8994_free_irq(codec->control_data, WM8994_IRQ_FIFOS_ERR, codec); |
3436 | wm8994_free_irq(codec->control_data, WM8994_IRQ_TEMP_SHUT, codec); | ||
3437 | wm8994_free_irq(codec->control_data, WM8994_IRQ_TEMP_WARN, codec); | ||
3282 | 3438 | ||
3283 | switch (control->type) { | 3439 | switch (control->type) { |
3284 | case WM8994: | 3440 | case WM8994: |
diff --git a/sound/soc/codecs/wm8994.h b/sound/soc/codecs/wm8994.h index 1ab2266039f7..f4f1355efc82 100644 --- a/sound/soc/codecs/wm8994.h +++ b/sound/soc/codecs/wm8994.h | |||
@@ -83,6 +83,8 @@ struct wm8994_priv { | |||
83 | struct completion fll_locked[2]; | 83 | struct completion fll_locked[2]; |
84 | bool fll_locked_irq; | 84 | bool fll_locked_irq; |
85 | 85 | ||
86 | int vmid_refcount; | ||
87 | |||
86 | int dac_rates[2]; | 88 | int dac_rates[2]; |
87 | int lrclk_shared[2]; | 89 | int lrclk_shared[2]; |
88 | 90 | ||
diff --git a/sound/soc/codecs/wm8995.c b/sound/soc/codecs/wm8995.c index 5ad873fda814..74ae5995a786 100644 --- a/sound/soc/codecs/wm8995.c +++ b/sound/soc/codecs/wm8995.c | |||
@@ -1573,9 +1573,7 @@ static int wm8995_resume(struct snd_soc_codec *codec) | |||
1573 | static int wm8995_remove(struct snd_soc_codec *codec) | 1573 | static int wm8995_remove(struct snd_soc_codec *codec) |
1574 | { | 1574 | { |
1575 | struct wm8995_priv *wm8995; | 1575 | struct wm8995_priv *wm8995; |
1576 | struct i2c_client *i2c; | ||
1577 | 1576 | ||
1578 | i2c = container_of(codec->dev, struct i2c_client, dev); | ||
1579 | wm8995 = snd_soc_codec_get_drvdata(codec); | 1577 | wm8995 = snd_soc_codec_get_drvdata(codec); |
1580 | wm8995_set_bias_level(codec, SND_SOC_BIAS_OFF); | 1578 | wm8995_set_bias_level(codec, SND_SOC_BIAS_OFF); |
1581 | return 0; | 1579 | return 0; |
@@ -1642,6 +1640,7 @@ static int wm8995_probe(struct snd_soc_codec *codec) | |||
1642 | 1640 | ||
1643 | if (ret != 0x8995) { | 1641 | if (ret != 0x8995) { |
1644 | dev_err(codec->dev, "Invalid device ID: %#x\n", ret); | 1642 | dev_err(codec->dev, "Invalid device ID: %#x\n", ret); |
1643 | ret = -EINVAL; | ||
1645 | goto err_reg_enable; | 1644 | goto err_reg_enable; |
1646 | } | 1645 | } |
1647 | 1646 | ||
diff --git a/sound/soc/codecs/wm8996.c b/sound/soc/codecs/wm8996.c index 0cdb9d105671..833df74c5584 100644 --- a/sound/soc/codecs/wm8996.c +++ b/sound/soc/codecs/wm8996.c | |||
@@ -41,12 +41,11 @@ | |||
41 | #define HPOUT2L 4 | 41 | #define HPOUT2L 4 |
42 | #define HPOUT2R 8 | 42 | #define HPOUT2R 8 |
43 | 43 | ||
44 | #define WM8996_NUM_SUPPLIES 4 | 44 | #define WM8996_NUM_SUPPLIES 3 |
45 | static const char *wm8996_supply_names[WM8996_NUM_SUPPLIES] = { | 45 | static const char *wm8996_supply_names[WM8996_NUM_SUPPLIES] = { |
46 | "DBVDD", | 46 | "DBVDD", |
47 | "AVDD1", | 47 | "AVDD1", |
48 | "AVDD2", | 48 | "AVDD2", |
49 | "CPVDD", | ||
50 | }; | 49 | }; |
51 | 50 | ||
52 | struct wm8996_priv { | 51 | struct wm8996_priv { |
@@ -71,6 +70,8 @@ struct wm8996_priv { | |||
71 | 70 | ||
72 | struct regulator_bulk_data supplies[WM8996_NUM_SUPPLIES]; | 71 | struct regulator_bulk_data supplies[WM8996_NUM_SUPPLIES]; |
73 | struct notifier_block disable_nb[WM8996_NUM_SUPPLIES]; | 72 | struct notifier_block disable_nb[WM8996_NUM_SUPPLIES]; |
73 | struct regulator *cpvdd; | ||
74 | int bg_ena; | ||
74 | 75 | ||
75 | struct wm8996_pdata pdata; | 76 | struct wm8996_pdata pdata; |
76 | 77 | ||
@@ -112,7 +113,6 @@ static int wm8996_regulator_event_##n(struct notifier_block *nb, \ | |||
112 | WM8996_REGULATOR_EVENT(0) | 113 | WM8996_REGULATOR_EVENT(0) |
113 | WM8996_REGULATOR_EVENT(1) | 114 | WM8996_REGULATOR_EVENT(1) |
114 | WM8996_REGULATOR_EVENT(2) | 115 | WM8996_REGULATOR_EVENT(2) |
115 | WM8996_REGULATOR_EVENT(3) | ||
116 | 116 | ||
117 | static const u16 wm8996_reg[WM8996_MAX_REGISTER] = { | 117 | static const u16 wm8996_reg[WM8996_MAX_REGISTER] = { |
118 | [WM8996_SOFTWARE_RESET] = 0x8996, | 118 | [WM8996_SOFTWARE_RESET] = 0x8996, |
@@ -414,6 +414,7 @@ static const DECLARE_TLV_DB_SCALE(out_digital_tlv, -1200, 150, 0); | |||
414 | static const DECLARE_TLV_DB_SCALE(out_tlv, -900, 75, 0); | 414 | static const DECLARE_TLV_DB_SCALE(out_tlv, -900, 75, 0); |
415 | static const DECLARE_TLV_DB_SCALE(spk_tlv, -900, 150, 0); | 415 | static const DECLARE_TLV_DB_SCALE(spk_tlv, -900, 150, 0); |
416 | static const DECLARE_TLV_DB_SCALE(eq_tlv, -1200, 100, 0); | 416 | static const DECLARE_TLV_DB_SCALE(eq_tlv, -1200, 100, 0); |
417 | static const DECLARE_TLV_DB_SCALE(threedstereo_tlv, -1600, 183, 1); | ||
417 | 418 | ||
418 | static const char *sidetone_hpf_text[] = { | 419 | static const char *sidetone_hpf_text[] = { |
419 | "2.9kHz", "1.5kHz", "735Hz", "403Hz", "196Hz", "98Hz", "49Hz" | 420 | "2.9kHz", "1.5kHz", "735Hz", "403Hz", "196Hz", "98Hz", "49Hz" |
@@ -608,6 +609,14 @@ SOC_SINGLE("DAC High Performance Switch", WM8996_OVERSAMPLING, 0, 1, 0), | |||
608 | SOC_SINGLE("DAC Soft Mute Switch", WM8996_DAC_SOFTMUTE, 1, 1, 0), | 609 | SOC_SINGLE("DAC Soft Mute Switch", WM8996_DAC_SOFTMUTE, 1, 1, 0), |
609 | SOC_SINGLE("DAC Slow Soft Mute Switch", WM8996_DAC_SOFTMUTE, 0, 1, 0), | 610 | SOC_SINGLE("DAC Slow Soft Mute Switch", WM8996_DAC_SOFTMUTE, 0, 1, 0), |
610 | 611 | ||
612 | SOC_SINGLE("DSP1 3D Stereo Switch", WM8996_DSP1_RX_FILTERS_2, 8, 1, 0), | ||
613 | SOC_SINGLE("DSP2 3D Stereo Switch", WM8996_DSP2_RX_FILTERS_2, 8, 1, 0), | ||
614 | |||
615 | SOC_SINGLE_TLV("DSP1 3D Stereo Volume", WM8996_DSP1_RX_FILTERS_2, 10, 15, | ||
616 | 0, threedstereo_tlv), | ||
617 | SOC_SINGLE_TLV("DSP2 3D Stereo Volume", WM8996_DSP2_RX_FILTERS_2, 10, 15, | ||
618 | 0, threedstereo_tlv), | ||
619 | |||
611 | SOC_DOUBLE_TLV("Digital Output 1 Volume", WM8996_DAC1_HPOUT1_VOLUME, 0, 4, | 620 | SOC_DOUBLE_TLV("Digital Output 1 Volume", WM8996_DAC1_HPOUT1_VOLUME, 0, 4, |
612 | 8, 0, out_digital_tlv), | 621 | 8, 0, out_digital_tlv), |
613 | SOC_DOUBLE_TLV("Digital Output 2 Volume", WM8996_DAC2_HPOUT2_VOLUME, 0, 4, | 622 | SOC_DOUBLE_TLV("Digital Output 2 Volume", WM8996_DAC2_HPOUT2_VOLUME, 0, 4, |
@@ -658,19 +667,75 @@ SOC_SINGLE_TLV("DSP2 EQ B5 Volume", WM8996_DSP2_RX_EQ_GAINS_2, 6, 31, 0, | |||
658 | eq_tlv), | 667 | eq_tlv), |
659 | }; | 668 | }; |
660 | 669 | ||
670 | static void wm8996_bg_enable(struct snd_soc_codec *codec) | ||
671 | { | ||
672 | struct wm8996_priv *wm8996 = snd_soc_codec_get_drvdata(codec); | ||
673 | |||
674 | wm8996->bg_ena++; | ||
675 | if (wm8996->bg_ena == 1) { | ||
676 | snd_soc_update_bits(codec, WM8996_POWER_MANAGEMENT_1, | ||
677 | WM8996_BG_ENA, WM8996_BG_ENA); | ||
678 | msleep(2); | ||
679 | } | ||
680 | } | ||
681 | |||
682 | static void wm8996_bg_disable(struct snd_soc_codec *codec) | ||
683 | { | ||
684 | struct wm8996_priv *wm8996 = snd_soc_codec_get_drvdata(codec); | ||
685 | |||
686 | wm8996->bg_ena--; | ||
687 | if (!wm8996->bg_ena) | ||
688 | snd_soc_update_bits(codec, WM8996_POWER_MANAGEMENT_1, | ||
689 | WM8996_BG_ENA, 0); | ||
690 | } | ||
691 | |||
692 | static int bg_event(struct snd_soc_dapm_widget *w, | ||
693 | struct snd_kcontrol *kcontrol, int event) | ||
694 | { | ||
695 | struct snd_soc_codec *codec = w->codec; | ||
696 | int ret = 0; | ||
697 | |||
698 | switch (event) { | ||
699 | case SND_SOC_DAPM_PRE_PMU: | ||
700 | wm8996_bg_enable(codec); | ||
701 | break; | ||
702 | case SND_SOC_DAPM_POST_PMD: | ||
703 | wm8996_bg_disable(codec); | ||
704 | break; | ||
705 | default: | ||
706 | BUG(); | ||
707 | ret = -EINVAL; | ||
708 | } | ||
709 | |||
710 | return ret; | ||
711 | } | ||
712 | |||
661 | static int cp_event(struct snd_soc_dapm_widget *w, | 713 | static int cp_event(struct snd_soc_dapm_widget *w, |
662 | struct snd_kcontrol *kcontrol, int event) | 714 | struct snd_kcontrol *kcontrol, int event) |
663 | { | 715 | { |
716 | struct snd_soc_codec *codec = w->codec; | ||
717 | struct wm8996_priv *wm8996 = snd_soc_codec_get_drvdata(codec); | ||
718 | int ret = 0; | ||
719 | |||
664 | switch (event) { | 720 | switch (event) { |
721 | case SND_SOC_DAPM_PRE_PMU: | ||
722 | ret = regulator_enable(wm8996->cpvdd); | ||
723 | if (ret != 0) | ||
724 | dev_err(codec->dev, "Failed to enable CPVDD: %d\n", | ||
725 | ret); | ||
726 | break; | ||
665 | case SND_SOC_DAPM_POST_PMU: | 727 | case SND_SOC_DAPM_POST_PMU: |
666 | msleep(5); | 728 | msleep(5); |
667 | break; | 729 | break; |
730 | case SND_SOC_DAPM_POST_PMD: | ||
731 | regulator_disable_deferred(wm8996->cpvdd, 20); | ||
732 | break; | ||
668 | default: | 733 | default: |
669 | BUG(); | 734 | BUG(); |
670 | return -EINVAL; | 735 | ret = -EINVAL; |
671 | } | 736 | } |
672 | 737 | ||
673 | return 0; | 738 | return ret; |
674 | } | 739 | } |
675 | 740 | ||
676 | static int rmv_short_event(struct snd_soc_dapm_widget *w, | 741 | static int rmv_short_event(struct snd_soc_dapm_widget *w, |
@@ -698,7 +763,7 @@ static void wait_for_dc_servo(struct snd_soc_codec *codec, u16 mask) | |||
698 | { | 763 | { |
699 | struct i2c_client *i2c = to_i2c_client(codec->dev); | 764 | struct i2c_client *i2c = to_i2c_client(codec->dev); |
700 | struct wm8996_priv *wm8996 = snd_soc_codec_get_drvdata(codec); | 765 | struct wm8996_priv *wm8996 = snd_soc_codec_get_drvdata(codec); |
701 | int i, ret; | 766 | int ret; |
702 | unsigned long timeout = 200; | 767 | unsigned long timeout = 200; |
703 | 768 | ||
704 | snd_soc_write(codec, WM8996_DC_SERVO_2, mask); | 769 | snd_soc_write(codec, WM8996_DC_SERVO_2, mask); |
@@ -713,15 +778,12 @@ static void wait_for_dc_servo(struct snd_soc_codec *codec, u16 mask) | |||
713 | 778 | ||
714 | } else { | 779 | } else { |
715 | msleep(1); | 780 | msleep(1); |
716 | if (--i) { | 781 | timeout--; |
717 | timeout = 0; | ||
718 | break; | ||
719 | } | ||
720 | } | 782 | } |
721 | 783 | ||
722 | ret = snd_soc_read(codec, WM8996_DC_SERVO_2); | 784 | ret = snd_soc_read(codec, WM8996_DC_SERVO_2); |
723 | dev_dbg(codec->dev, "DC servo state: %x\n", ret); | 785 | dev_dbg(codec->dev, "DC servo state: %x\n", ret); |
724 | } while (ret & mask); | 786 | } while (timeout && ret & mask); |
725 | 787 | ||
726 | if (timeout == 0) | 788 | if (timeout == 0) |
727 | dev_err(codec->dev, "DC servo timed out for %x\n", mask); | 789 | dev_err(codec->dev, "DC servo timed out for %x\n", mask); |
@@ -979,9 +1041,12 @@ SND_SOC_DAPM_SUPPLY_S("SYSCLK", 1, WM8996_AIF_CLOCKING_1, 0, 0, NULL, 0), | |||
979 | SND_SOC_DAPM_SUPPLY_S("SYSDSPCLK", 2, WM8996_CLOCKING_1, 1, 0, NULL, 0), | 1041 | SND_SOC_DAPM_SUPPLY_S("SYSDSPCLK", 2, WM8996_CLOCKING_1, 1, 0, NULL, 0), |
980 | SND_SOC_DAPM_SUPPLY_S("AIFCLK", 2, WM8996_CLOCKING_1, 2, 0, NULL, 0), | 1042 | SND_SOC_DAPM_SUPPLY_S("AIFCLK", 2, WM8996_CLOCKING_1, 2, 0, NULL, 0), |
981 | SND_SOC_DAPM_SUPPLY_S("Charge Pump", 2, WM8996_CHARGE_PUMP_1, 15, 0, cp_event, | 1043 | SND_SOC_DAPM_SUPPLY_S("Charge Pump", 2, WM8996_CHARGE_PUMP_1, 15, 0, cp_event, |
982 | SND_SOC_DAPM_POST_PMU), | 1044 | SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD), |
983 | 1045 | SND_SOC_DAPM_SUPPLY("Bandgap", SND_SOC_NOPM, 0, 0, bg_event, | |
1046 | SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD), | ||
984 | SND_SOC_DAPM_SUPPLY("LDO2", WM8996_POWER_MANAGEMENT_2, 1, 0, NULL, 0), | 1047 | SND_SOC_DAPM_SUPPLY("LDO2", WM8996_POWER_MANAGEMENT_2, 1, 0, NULL, 0), |
1048 | SND_SOC_DAPM_SUPPLY("MICB1 Audio", WM8996_MICBIAS_1, 4, 1, NULL, 0), | ||
1049 | SND_SOC_DAPM_SUPPLY("MICB2 Audio", WM8996_MICBIAS_2, 4, 1, NULL, 0), | ||
985 | SND_SOC_DAPM_MICBIAS("MICB2", WM8996_POWER_MANAGEMENT_1, 9, 0), | 1050 | SND_SOC_DAPM_MICBIAS("MICB2", WM8996_POWER_MANAGEMENT_1, 9, 0), |
986 | SND_SOC_DAPM_MICBIAS("MICB1", WM8996_POWER_MANAGEMENT_1, 8, 0), | 1051 | SND_SOC_DAPM_MICBIAS("MICB1", WM8996_POWER_MANAGEMENT_1, 8, 0), |
987 | 1052 | ||
@@ -1035,14 +1100,14 @@ SND_SOC_DAPM_DAC("DAC2R", NULL, WM8996_POWER_MANAGEMENT_5, 2, 0), | |||
1035 | SND_SOC_DAPM_DAC("DAC1L", NULL, WM8996_POWER_MANAGEMENT_5, 1, 0), | 1100 | SND_SOC_DAPM_DAC("DAC1L", NULL, WM8996_POWER_MANAGEMENT_5, 1, 0), |
1036 | SND_SOC_DAPM_DAC("DAC1R", NULL, WM8996_POWER_MANAGEMENT_5, 0, 0), | 1101 | SND_SOC_DAPM_DAC("DAC1R", NULL, WM8996_POWER_MANAGEMENT_5, 0, 0), |
1037 | 1102 | ||
1038 | SND_SOC_DAPM_AIF_IN("AIF2RX1", "AIF2 Playback", 1, | 1103 | SND_SOC_DAPM_AIF_IN("AIF2RX1", "AIF2 Playback", 0, |
1039 | WM8996_POWER_MANAGEMENT_4, 9, 0), | 1104 | WM8996_POWER_MANAGEMENT_4, 9, 0), |
1040 | SND_SOC_DAPM_AIF_IN("AIF2RX0", "AIF2 Playback", 2, | 1105 | SND_SOC_DAPM_AIF_IN("AIF2RX0", "AIF2 Playback", 1, |
1041 | WM8996_POWER_MANAGEMENT_4, 8, 0), | 1106 | WM8996_POWER_MANAGEMENT_4, 8, 0), |
1042 | 1107 | ||
1043 | SND_SOC_DAPM_AIF_IN("AIF2TX1", "AIF2 Capture", 1, | 1108 | SND_SOC_DAPM_AIF_IN("AIF2TX1", "AIF2 Capture", 0, |
1044 | WM8996_POWER_MANAGEMENT_6, 9, 0), | 1109 | WM8996_POWER_MANAGEMENT_6, 9, 0), |
1045 | SND_SOC_DAPM_AIF_IN("AIF2TX0", "AIF2 Capture", 2, | 1110 | SND_SOC_DAPM_AIF_IN("AIF2TX0", "AIF2 Capture", 1, |
1046 | WM8996_POWER_MANAGEMENT_6, 8, 0), | 1111 | WM8996_POWER_MANAGEMENT_6, 8, 0), |
1047 | 1112 | ||
1048 | SND_SOC_DAPM_AIF_IN("AIF1RX5", "AIF1 Playback", 5, | 1113 | SND_SOC_DAPM_AIF_IN("AIF1RX5", "AIF1 Playback", 5, |
@@ -1137,17 +1202,23 @@ static const struct snd_soc_dapm_route wm8996_dapm_routes[] = { | |||
1137 | { "Charge Pump", NULL, "SYSCLK" }, | 1202 | { "Charge Pump", NULL, "SYSCLK" }, |
1138 | 1203 | ||
1139 | { "MICB1", NULL, "LDO2" }, | 1204 | { "MICB1", NULL, "LDO2" }, |
1205 | { "MICB1", NULL, "MICB1 Audio" }, | ||
1206 | { "MICB1", NULL, "Bandgap" }, | ||
1140 | { "MICB2", NULL, "LDO2" }, | 1207 | { "MICB2", NULL, "LDO2" }, |
1208 | { "MICB2", NULL, "MICB2 Audio" }, | ||
1209 | { "MICB2", NULL, "Bandgap" }, | ||
1141 | 1210 | ||
1142 | { "IN1L PGA", NULL, "IN2LN" }, | 1211 | { "IN1L PGA", NULL, "IN2LN" }, |
1143 | { "IN1L PGA", NULL, "IN2LP" }, | 1212 | { "IN1L PGA", NULL, "IN2LP" }, |
1144 | { "IN1L PGA", NULL, "IN1LN" }, | 1213 | { "IN1L PGA", NULL, "IN1LN" }, |
1145 | { "IN1L PGA", NULL, "IN1LP" }, | 1214 | { "IN1L PGA", NULL, "IN1LP" }, |
1215 | { "IN1L PGA", NULL, "Bandgap" }, | ||
1146 | 1216 | ||
1147 | { "IN1R PGA", NULL, "IN2RN" }, | 1217 | { "IN1R PGA", NULL, "IN2RN" }, |
1148 | { "IN1R PGA", NULL, "IN2RP" }, | 1218 | { "IN1R PGA", NULL, "IN2RP" }, |
1149 | { "IN1R PGA", NULL, "IN1RN" }, | 1219 | { "IN1R PGA", NULL, "IN1RN" }, |
1150 | { "IN1R PGA", NULL, "IN1RP" }, | 1220 | { "IN1R PGA", NULL, "IN1RP" }, |
1221 | { "IN1R PGA", NULL, "Bandgap" }, | ||
1151 | 1222 | ||
1152 | { "ADCL", NULL, "IN1L PGA" }, | 1223 | { "ADCL", NULL, "IN1L PGA" }, |
1153 | 1224 | ||
@@ -1281,6 +1352,7 @@ static const struct snd_soc_dapm_route wm8996_dapm_routes[] = { | |||
1281 | { "DAC2R", NULL, "DAC2R Mixer" }, | 1352 | { "DAC2R", NULL, "DAC2R Mixer" }, |
1282 | 1353 | ||
1283 | { "HPOUT2L PGA", NULL, "Charge Pump" }, | 1354 | { "HPOUT2L PGA", NULL, "Charge Pump" }, |
1355 | { "HPOUT2L PGA", NULL, "Bandgap" }, | ||
1284 | { "HPOUT2L PGA", NULL, "DAC2L" }, | 1356 | { "HPOUT2L PGA", NULL, "DAC2L" }, |
1285 | { "HPOUT2L_DLY", NULL, "HPOUT2L PGA" }, | 1357 | { "HPOUT2L_DLY", NULL, "HPOUT2L PGA" }, |
1286 | { "HPOUT2L_DCS", NULL, "HPOUT2L_DLY" }, | 1358 | { "HPOUT2L_DCS", NULL, "HPOUT2L_DLY" }, |
@@ -1288,6 +1360,7 @@ static const struct snd_soc_dapm_route wm8996_dapm_routes[] = { | |||
1288 | { "HPOUT2L_RMV_SHORT", NULL, "HPOUT2L_OUTP" }, | 1360 | { "HPOUT2L_RMV_SHORT", NULL, "HPOUT2L_OUTP" }, |
1289 | 1361 | ||
1290 | { "HPOUT2R PGA", NULL, "Charge Pump" }, | 1362 | { "HPOUT2R PGA", NULL, "Charge Pump" }, |
1363 | { "HPOUT2R PGA", NULL, "Bandgap" }, | ||
1291 | { "HPOUT2R PGA", NULL, "DAC2R" }, | 1364 | { "HPOUT2R PGA", NULL, "DAC2R" }, |
1292 | { "HPOUT2R_DLY", NULL, "HPOUT2R PGA" }, | 1365 | { "HPOUT2R_DLY", NULL, "HPOUT2R PGA" }, |
1293 | { "HPOUT2R_DCS", NULL, "HPOUT2R_DLY" }, | 1366 | { "HPOUT2R_DCS", NULL, "HPOUT2R_DLY" }, |
@@ -1295,6 +1368,7 @@ static const struct snd_soc_dapm_route wm8996_dapm_routes[] = { | |||
1295 | { "HPOUT2R_RMV_SHORT", NULL, "HPOUT2R_OUTP" }, | 1368 | { "HPOUT2R_RMV_SHORT", NULL, "HPOUT2R_OUTP" }, |
1296 | 1369 | ||
1297 | { "HPOUT1L PGA", NULL, "Charge Pump" }, | 1370 | { "HPOUT1L PGA", NULL, "Charge Pump" }, |
1371 | { "HPOUT1L PGA", NULL, "Bandgap" }, | ||
1298 | { "HPOUT1L PGA", NULL, "DAC1L" }, | 1372 | { "HPOUT1L PGA", NULL, "DAC1L" }, |
1299 | { "HPOUT1L_DLY", NULL, "HPOUT1L PGA" }, | 1373 | { "HPOUT1L_DLY", NULL, "HPOUT1L PGA" }, |
1300 | { "HPOUT1L_DCS", NULL, "HPOUT1L_DLY" }, | 1374 | { "HPOUT1L_DCS", NULL, "HPOUT1L_DLY" }, |
@@ -1302,6 +1376,7 @@ static const struct snd_soc_dapm_route wm8996_dapm_routes[] = { | |||
1302 | { "HPOUT1L_RMV_SHORT", NULL, "HPOUT1L_OUTP" }, | 1376 | { "HPOUT1L_RMV_SHORT", NULL, "HPOUT1L_OUTP" }, |
1303 | 1377 | ||
1304 | { "HPOUT1R PGA", NULL, "Charge Pump" }, | 1378 | { "HPOUT1R PGA", NULL, "Charge Pump" }, |
1379 | { "HPOUT1R PGA", NULL, "Bandgap" }, | ||
1305 | { "HPOUT1R PGA", NULL, "DAC1R" }, | 1380 | { "HPOUT1R PGA", NULL, "DAC1R" }, |
1306 | { "HPOUT1R_DLY", NULL, "HPOUT1R PGA" }, | 1381 | { "HPOUT1R_DLY", NULL, "HPOUT1R PGA" }, |
1307 | { "HPOUT1R_DCS", NULL, "HPOUT1R_DLY" }, | 1382 | { "HPOUT1R_DCS", NULL, "HPOUT1R_DLY" }, |
@@ -1620,14 +1695,7 @@ static int wm8996_set_bias_level(struct snd_soc_codec *codec, | |||
1620 | 1695 | ||
1621 | switch (level) { | 1696 | switch (level) { |
1622 | case SND_SOC_BIAS_ON: | 1697 | case SND_SOC_BIAS_ON: |
1623 | break; | ||
1624 | |||
1625 | case SND_SOC_BIAS_PREPARE: | 1698 | case SND_SOC_BIAS_PREPARE: |
1626 | if (codec->dapm.bias_level == SND_SOC_BIAS_STANDBY) { | ||
1627 | snd_soc_update_bits(codec, WM8996_POWER_MANAGEMENT_1, | ||
1628 | WM8996_BG_ENA, WM8996_BG_ENA); | ||
1629 | msleep(2); | ||
1630 | } | ||
1631 | break; | 1699 | break; |
1632 | 1700 | ||
1633 | case SND_SOC_BIAS_STANDBY: | 1701 | case SND_SOC_BIAS_STANDBY: |
@@ -1650,9 +1718,6 @@ static int wm8996_set_bias_level(struct snd_soc_codec *codec, | |||
1650 | codec->cache_only = false; | 1718 | codec->cache_only = false; |
1651 | snd_soc_cache_sync(codec); | 1719 | snd_soc_cache_sync(codec); |
1652 | } | 1720 | } |
1653 | |||
1654 | snd_soc_update_bits(codec, WM8996_POWER_MANAGEMENT_1, | ||
1655 | WM8996_BG_ENA, 0); | ||
1656 | break; | 1721 | break; |
1657 | 1722 | ||
1658 | case SND_SOC_BIAS_OFF: | 1723 | case SND_SOC_BIAS_OFF: |
@@ -2041,7 +2106,7 @@ static int wm8996_set_fll(struct snd_soc_codec *codec, int fll_id, int source, | |||
2041 | struct i2c_client *i2c = to_i2c_client(codec->dev); | 2106 | struct i2c_client *i2c = to_i2c_client(codec->dev); |
2042 | struct _fll_div fll_div; | 2107 | struct _fll_div fll_div; |
2043 | unsigned long timeout; | 2108 | unsigned long timeout; |
2044 | int ret, reg; | 2109 | int ret, reg, retry; |
2045 | 2110 | ||
2046 | /* Any change? */ | 2111 | /* Any change? */ |
2047 | if (source == wm8996->fll_src && Fref == wm8996->fll_fref && | 2112 | if (source == wm8996->fll_src && Fref == wm8996->fll_fref && |
@@ -2057,6 +2122,8 @@ static int wm8996_set_fll(struct snd_soc_codec *codec, int fll_id, int source, | |||
2057 | snd_soc_update_bits(codec, WM8996_FLL_CONTROL_1, | 2122 | snd_soc_update_bits(codec, WM8996_FLL_CONTROL_1, |
2058 | WM8996_FLL_ENA, 0); | 2123 | WM8996_FLL_ENA, 0); |
2059 | 2124 | ||
2125 | wm8996_bg_disable(codec); | ||
2126 | |||
2060 | return 0; | 2127 | return 0; |
2061 | } | 2128 | } |
2062 | 2129 | ||
@@ -2111,6 +2178,11 @@ static int wm8996_set_fll(struct snd_soc_codec *codec, int fll_id, int source, | |||
2111 | 2178 | ||
2112 | snd_soc_write(codec, WM8996_FLL_EFS_1, fll_div.lambda); | 2179 | snd_soc_write(codec, WM8996_FLL_EFS_1, fll_div.lambda); |
2113 | 2180 | ||
2181 | /* Enable the bandgap if it's not already enabled */ | ||
2182 | ret = snd_soc_read(codec, WM8996_FLL_CONTROL_1); | ||
2183 | if (!(ret & WM8996_FLL_ENA)) | ||
2184 | wm8996_bg_enable(codec); | ||
2185 | |||
2114 | /* Clear any pending completions (eg, from failed startups) */ | 2186 | /* Clear any pending completions (eg, from failed startups) */ |
2115 | try_wait_for_completion(&wm8996->fll_lock); | 2187 | try_wait_for_completion(&wm8996->fll_lock); |
2116 | 2188 | ||
@@ -2128,17 +2200,29 @@ static int wm8996_set_fll(struct snd_soc_codec *codec, int fll_id, int source, | |||
2128 | else | 2200 | else |
2129 | timeout = msecs_to_jiffies(2); | 2201 | timeout = msecs_to_jiffies(2); |
2130 | 2202 | ||
2131 | /* Allow substantially longer if we've actually got the IRQ */ | 2203 | /* Allow substantially longer if we've actually got the IRQ, poll |
2204 | * at a slightly higher rate if we don't. | ||
2205 | */ | ||
2132 | if (i2c->irq) | 2206 | if (i2c->irq) |
2133 | timeout *= 1000; | 2207 | timeout *= 10; |
2208 | else | ||
2209 | timeout /= 2; | ||
2134 | 2210 | ||
2135 | ret = wait_for_completion_timeout(&wm8996->fll_lock, timeout); | 2211 | for (retry = 0; retry < 10; retry++) { |
2212 | ret = wait_for_completion_timeout(&wm8996->fll_lock, | ||
2213 | timeout); | ||
2214 | if (ret != 0) { | ||
2215 | WARN_ON(!i2c->irq); | ||
2216 | break; | ||
2217 | } | ||
2136 | 2218 | ||
2137 | if (ret == 0 && i2c->irq) { | 2219 | ret = snd_soc_read(codec, WM8996_INTERRUPT_RAW_STATUS_2); |
2220 | if (ret & WM8996_FLL_LOCK_STS) | ||
2221 | break; | ||
2222 | } | ||
2223 | if (retry == 10) { | ||
2138 | dev_err(codec->dev, "Timed out waiting for FLL\n"); | 2224 | dev_err(codec->dev, "Timed out waiting for FLL\n"); |
2139 | ret = -ETIMEDOUT; | 2225 | ret = -ETIMEDOUT; |
2140 | } else { | ||
2141 | ret = 0; | ||
2142 | } | 2226 | } |
2143 | 2227 | ||
2144 | dev_dbg(codec->dev, "FLL configured for %dHz->%dHz\n", Fref, Fout); | 2228 | dev_dbg(codec->dev, "FLL configured for %dHz->%dHz\n", Fref, Fout); |
@@ -2297,12 +2381,94 @@ int wm8996_detect(struct snd_soc_codec *codec, struct snd_soc_jack *jack, | |||
2297 | 2381 | ||
2298 | /* Enable interrupts and we're off */ | 2382 | /* Enable interrupts and we're off */ |
2299 | snd_soc_update_bits(codec, WM8996_INTERRUPT_STATUS_2_MASK, | 2383 | snd_soc_update_bits(codec, WM8996_INTERRUPT_STATUS_2_MASK, |
2300 | WM8996_IM_MICD_EINT, 0); | 2384 | WM8996_IM_MICD_EINT | WM8996_HP_DONE_EINT, 0); |
2301 | 2385 | ||
2302 | return 0; | 2386 | return 0; |
2303 | } | 2387 | } |
2304 | EXPORT_SYMBOL_GPL(wm8996_detect); | 2388 | EXPORT_SYMBOL_GPL(wm8996_detect); |
2305 | 2389 | ||
2390 | static void wm8996_hpdet_irq(struct snd_soc_codec *codec) | ||
2391 | { | ||
2392 | struct wm8996_priv *wm8996 = snd_soc_codec_get_drvdata(codec); | ||
2393 | int val, reg, report; | ||
2394 | |||
2395 | /* Assume headphone in error conditions; we need to report | ||
2396 | * something or we stall our state machine. | ||
2397 | */ | ||
2398 | report = SND_JACK_HEADPHONE; | ||
2399 | |||
2400 | reg = snd_soc_read(codec, WM8996_HEADPHONE_DETECT_2); | ||
2401 | if (reg < 0) { | ||
2402 | dev_err(codec->dev, "Failed to read HPDET status\n"); | ||
2403 | goto out; | ||
2404 | } | ||
2405 | |||
2406 | if (!(reg & WM8996_HP_DONE)) { | ||
2407 | dev_err(codec->dev, "Got HPDET IRQ but HPDET is busy\n"); | ||
2408 | goto out; | ||
2409 | } | ||
2410 | |||
2411 | val = reg & WM8996_HP_LVL_MASK; | ||
2412 | |||
2413 | dev_dbg(codec->dev, "HPDET measured %d ohms\n", val); | ||
2414 | |||
2415 | /* If we've got high enough impedence then report as line, | ||
2416 | * otherwise assume headphone. | ||
2417 | */ | ||
2418 | if (val >= 126) | ||
2419 | report = SND_JACK_LINEOUT; | ||
2420 | else | ||
2421 | report = SND_JACK_HEADPHONE; | ||
2422 | |||
2423 | out: | ||
2424 | if (wm8996->jack_mic) | ||
2425 | report |= SND_JACK_MICROPHONE; | ||
2426 | |||
2427 | snd_soc_jack_report(wm8996->jack, report, | ||
2428 | SND_JACK_LINEOUT | SND_JACK_HEADSET); | ||
2429 | |||
2430 | wm8996->detecting = false; | ||
2431 | |||
2432 | /* If the output isn't running re-clamp it */ | ||
2433 | if (!(snd_soc_read(codec, WM8996_POWER_MANAGEMENT_1) & | ||
2434 | (WM8996_HPOUT1L_ENA | WM8996_HPOUT1R_RMV_SHORT))) | ||
2435 | snd_soc_update_bits(codec, WM8996_ANALOGUE_HP_1, | ||
2436 | WM8996_HPOUT1L_RMV_SHORT | | ||
2437 | WM8996_HPOUT1R_RMV_SHORT, 0); | ||
2438 | |||
2439 | /* Go back to looking at the microphone */ | ||
2440 | snd_soc_update_bits(codec, WM8996_ACCESSORY_DETECT_MODE_1, | ||
2441 | WM8996_JD_MODE_MASK, 0); | ||
2442 | snd_soc_update_bits(codec, WM8996_MIC_DETECT_1, WM8996_MICD_ENA, | ||
2443 | WM8996_MICD_ENA); | ||
2444 | |||
2445 | snd_soc_dapm_disable_pin(&codec->dapm, "Bandgap"); | ||
2446 | snd_soc_dapm_sync(&codec->dapm); | ||
2447 | } | ||
2448 | |||
2449 | static void wm8996_hpdet_start(struct snd_soc_codec *codec) | ||
2450 | { | ||
2451 | /* Unclamp the output, we can't measure while we're shorting it */ | ||
2452 | snd_soc_update_bits(codec, WM8996_ANALOGUE_HP_1, | ||
2453 | WM8996_HPOUT1L_RMV_SHORT | | ||
2454 | WM8996_HPOUT1R_RMV_SHORT, | ||
2455 | WM8996_HPOUT1L_RMV_SHORT | | ||
2456 | WM8996_HPOUT1R_RMV_SHORT); | ||
2457 | |||
2458 | /* We need bandgap for HPDET */ | ||
2459 | snd_soc_dapm_force_enable_pin(&codec->dapm, "Bandgap"); | ||
2460 | snd_soc_dapm_sync(&codec->dapm); | ||
2461 | |||
2462 | /* Go into headphone detect left mode */ | ||
2463 | snd_soc_update_bits(codec, WM8996_MIC_DETECT_1, WM8996_MICD_ENA, 0); | ||
2464 | snd_soc_update_bits(codec, WM8996_ACCESSORY_DETECT_MODE_1, | ||
2465 | WM8996_JD_MODE_MASK, 1); | ||
2466 | |||
2467 | /* Trigger a measurement */ | ||
2468 | snd_soc_update_bits(codec, WM8996_HEADPHONE_DETECT_1, | ||
2469 | WM8996_HP_POLL, WM8996_HP_POLL); | ||
2470 | } | ||
2471 | |||
2306 | static void wm8996_micd(struct snd_soc_codec *codec) | 2472 | static void wm8996_micd(struct snd_soc_codec *codec) |
2307 | { | 2473 | { |
2308 | struct wm8996_priv *wm8996 = snd_soc_codec_get_drvdata(codec); | 2474 | struct wm8996_priv *wm8996 = snd_soc_codec_get_drvdata(codec); |
@@ -2323,28 +2489,36 @@ static void wm8996_micd(struct snd_soc_codec *codec) | |||
2323 | wm8996->jack_mic = false; | 2489 | wm8996->jack_mic = false; |
2324 | wm8996->detecting = true; | 2490 | wm8996->detecting = true; |
2325 | snd_soc_jack_report(wm8996->jack, 0, | 2491 | snd_soc_jack_report(wm8996->jack, 0, |
2326 | SND_JACK_HEADSET | SND_JACK_BTN_0); | 2492 | SND_JACK_LINEOUT | SND_JACK_HEADSET | |
2493 | SND_JACK_BTN_0); | ||
2494 | |||
2327 | snd_soc_update_bits(codec, WM8996_MIC_DETECT_1, | 2495 | snd_soc_update_bits(codec, WM8996_MIC_DETECT_1, |
2328 | WM8996_MICD_RATE_MASK, | 2496 | WM8996_MICD_RATE_MASK, |
2329 | WM8996_MICD_RATE_MASK); | 2497 | WM8996_MICD_RATE_MASK); |
2330 | return; | 2498 | return; |
2331 | } | 2499 | } |
2332 | 2500 | ||
2333 | /* If the measurement is very high we've got a microphone but | 2501 | /* If the measurement is very high we've got a microphone, |
2334 | * do a little debounce to account for mechanical issues. | 2502 | * either we just detected one or if we already reported then |
2503 | * we've got a button release event. | ||
2335 | */ | 2504 | */ |
2336 | if (val & 0x400) { | 2505 | if (val & 0x400) { |
2337 | dev_dbg(codec->dev, "Microphone detected\n"); | 2506 | if (wm8996->detecting) { |
2338 | snd_soc_jack_report(wm8996->jack, SND_JACK_HEADSET, | 2507 | dev_dbg(codec->dev, "Microphone detected\n"); |
2339 | SND_JACK_HEADSET | SND_JACK_BTN_0); | 2508 | wm8996->jack_mic = true; |
2340 | wm8996->jack_mic = true; | 2509 | wm8996_hpdet_start(codec); |
2341 | wm8996->detecting = false; | 2510 | |
2342 | 2511 | /* Increase poll rate to give better responsiveness | |
2343 | /* Increase poll rate to give better responsiveness | 2512 | * for buttons */ |
2344 | * for buttons */ | 2513 | snd_soc_update_bits(codec, WM8996_MIC_DETECT_1, |
2345 | snd_soc_update_bits(codec, WM8996_MIC_DETECT_1, | 2514 | WM8996_MICD_RATE_MASK, |
2346 | WM8996_MICD_RATE_MASK, | 2515 | 5 << WM8996_MICD_RATE_SHIFT); |
2347 | 5 << WM8996_MICD_RATE_SHIFT); | 2516 | } else { |
2517 | dev_dbg(codec->dev, "Mic button up\n"); | ||
2518 | snd_soc_jack_report(wm8996->jack, 0, SND_JACK_BTN_0); | ||
2519 | } | ||
2520 | |||
2521 | return; | ||
2348 | } | 2522 | } |
2349 | 2523 | ||
2350 | /* If we detected a lower impedence during initial startup | 2524 | /* If we detected a lower impedence during initial startup |
@@ -2376,15 +2550,11 @@ static void wm8996_micd(struct snd_soc_codec *codec) | |||
2376 | if (val & 0x3fc) { | 2550 | if (val & 0x3fc) { |
2377 | if (wm8996->jack_mic) { | 2551 | if (wm8996->jack_mic) { |
2378 | dev_dbg(codec->dev, "Mic button detected\n"); | 2552 | dev_dbg(codec->dev, "Mic button detected\n"); |
2379 | snd_soc_jack_report(wm8996->jack, | 2553 | snd_soc_jack_report(wm8996->jack, SND_JACK_BTN_0, |
2380 | SND_JACK_HEADSET | SND_JACK_BTN_0, | ||
2381 | SND_JACK_HEADSET | SND_JACK_BTN_0); | ||
2382 | } else { | ||
2383 | dev_dbg(codec->dev, "Headphone detected\n"); | ||
2384 | snd_soc_jack_report(wm8996->jack, | ||
2385 | SND_JACK_HEADPHONE, | ||
2386 | SND_JACK_HEADSET | | ||
2387 | SND_JACK_BTN_0); | 2554 | SND_JACK_BTN_0); |
2555 | } else if (wm8996->detecting) { | ||
2556 | dev_dbg(codec->dev, "Headphone detected\n"); | ||
2557 | wm8996_hpdet_start(codec); | ||
2388 | 2558 | ||
2389 | /* Increase the detection rate a bit for | 2559 | /* Increase the detection rate a bit for |
2390 | * responsiveness. | 2560 | * responsiveness. |
@@ -2392,8 +2562,6 @@ static void wm8996_micd(struct snd_soc_codec *codec) | |||
2392 | snd_soc_update_bits(codec, WM8996_MIC_DETECT_1, | 2562 | snd_soc_update_bits(codec, WM8996_MIC_DETECT_1, |
2393 | WM8996_MICD_RATE_MASK, | 2563 | WM8996_MICD_RATE_MASK, |
2394 | 7 << WM8996_MICD_RATE_SHIFT); | 2564 | 7 << WM8996_MICD_RATE_SHIFT); |
2395 | |||
2396 | wm8996->detecting = false; | ||
2397 | } | 2565 | } |
2398 | } | 2566 | } |
2399 | } | 2567 | } |
@@ -2412,6 +2580,9 @@ static irqreturn_t wm8996_irq(int irq, void *data) | |||
2412 | } | 2580 | } |
2413 | irq_val &= ~snd_soc_read(codec, WM8996_INTERRUPT_STATUS_2_MASK); | 2581 | irq_val &= ~snd_soc_read(codec, WM8996_INTERRUPT_STATUS_2_MASK); |
2414 | 2582 | ||
2583 | if (!irq_val) | ||
2584 | return IRQ_NONE; | ||
2585 | |||
2415 | snd_soc_write(codec, WM8996_INTERRUPT_STATUS_2, irq_val); | 2586 | snd_soc_write(codec, WM8996_INTERRUPT_STATUS_2, irq_val); |
2416 | 2587 | ||
2417 | if (irq_val & (WM8996_DCS_DONE_01_EINT | WM8996_DCS_DONE_23_EINT)) { | 2588 | if (irq_val & (WM8996_DCS_DONE_01_EINT | WM8996_DCS_DONE_23_EINT)) { |
@@ -2430,10 +2601,10 @@ static irqreturn_t wm8996_irq(int irq, void *data) | |||
2430 | if (irq_val & WM8996_MICD_EINT) | 2601 | if (irq_val & WM8996_MICD_EINT) |
2431 | wm8996_micd(codec); | 2602 | wm8996_micd(codec); |
2432 | 2603 | ||
2433 | if (irq_val) | 2604 | if (irq_val & WM8996_HP_DONE_EINT) |
2434 | return IRQ_HANDLED; | 2605 | wm8996_hpdet_irq(codec); |
2435 | else | 2606 | |
2436 | return IRQ_NONE; | 2607 | return IRQ_HANDLED; |
2437 | } | 2608 | } |
2438 | 2609 | ||
2439 | static irqreturn_t wm8996_edge_irq(int irq, void *data) | 2610 | static irqreturn_t wm8996_edge_irq(int irq, void *data) |
@@ -2548,7 +2719,13 @@ static int wm8996_probe(struct snd_soc_codec *codec) | |||
2548 | wm8996->disable_nb[0].notifier_call = wm8996_regulator_event_0; | 2719 | wm8996->disable_nb[0].notifier_call = wm8996_regulator_event_0; |
2549 | wm8996->disable_nb[1].notifier_call = wm8996_regulator_event_1; | 2720 | wm8996->disable_nb[1].notifier_call = wm8996_regulator_event_1; |
2550 | wm8996->disable_nb[2].notifier_call = wm8996_regulator_event_2; | 2721 | wm8996->disable_nb[2].notifier_call = wm8996_regulator_event_2; |
2551 | wm8996->disable_nb[3].notifier_call = wm8996_regulator_event_3; | 2722 | |
2723 | wm8996->cpvdd = regulator_get(&i2c->dev, "CPVDD"); | ||
2724 | if (IS_ERR(wm8996->cpvdd)) { | ||
2725 | ret = PTR_ERR(wm8996->cpvdd); | ||
2726 | dev_err(&i2c->dev, "Failed to get CPVDD: %d\n", ret); | ||
2727 | goto err_get; | ||
2728 | } | ||
2552 | 2729 | ||
2553 | /* This should really be moved into the regulator core */ | 2730 | /* This should really be moved into the regulator core */ |
2554 | for (i = 0; i < ARRAY_SIZE(wm8996->supplies); i++) { | 2731 | for (i = 0; i < ARRAY_SIZE(wm8996->supplies); i++) { |
@@ -2565,7 +2742,7 @@ static int wm8996_probe(struct snd_soc_codec *codec) | |||
2565 | wm8996->supplies); | 2742 | wm8996->supplies); |
2566 | if (ret != 0) { | 2743 | if (ret != 0) { |
2567 | dev_err(codec->dev, "Failed to enable supplies: %d\n", ret); | 2744 | dev_err(codec->dev, "Failed to enable supplies: %d\n", ret); |
2568 | goto err_get; | 2745 | goto err_cpvdd; |
2569 | } | 2746 | } |
2570 | 2747 | ||
2571 | if (wm8996->pdata.ldo_ena >= 0) { | 2748 | if (wm8996->pdata.ldo_ena >= 0) { |
@@ -2808,6 +2985,8 @@ err_enable: | |||
2808 | gpio_set_value_cansleep(wm8996->pdata.ldo_ena, 0); | 2985 | gpio_set_value_cansleep(wm8996->pdata.ldo_ena, 0); |
2809 | 2986 | ||
2810 | regulator_bulk_disable(ARRAY_SIZE(wm8996->supplies), wm8996->supplies); | 2987 | regulator_bulk_disable(ARRAY_SIZE(wm8996->supplies), wm8996->supplies); |
2988 | err_cpvdd: | ||
2989 | regulator_put(wm8996->cpvdd); | ||
2811 | err_get: | 2990 | err_get: |
2812 | regulator_bulk_free(ARRAY_SIZE(wm8996->supplies), wm8996->supplies); | 2991 | regulator_bulk_free(ARRAY_SIZE(wm8996->supplies), wm8996->supplies); |
2813 | err: | 2992 | err: |
@@ -2831,6 +3010,7 @@ static int wm8996_remove(struct snd_soc_codec *codec) | |||
2831 | for (i = 0; i < ARRAY_SIZE(wm8996->supplies); i++) | 3010 | for (i = 0; i < ARRAY_SIZE(wm8996->supplies); i++) |
2832 | regulator_unregister_notifier(wm8996->supplies[i].consumer, | 3011 | regulator_unregister_notifier(wm8996->supplies[i].consumer, |
2833 | &wm8996->disable_nb[i]); | 3012 | &wm8996->disable_nb[i]); |
3013 | regulator_put(wm8996->cpvdd); | ||
2834 | regulator_bulk_free(ARRAY_SIZE(wm8996->supplies), wm8996->supplies); | 3014 | regulator_bulk_free(ARRAY_SIZE(wm8996->supplies), wm8996->supplies); |
2835 | 3015 | ||
2836 | return 0; | 3016 | return 0; |
diff --git a/sound/soc/codecs/wm9081.c b/sound/soc/codecs/wm9081.c index a4691321f9b3..f32ab1ee9647 100644 --- a/sound/soc/codecs/wm9081.c +++ b/sound/soc/codecs/wm9081.c | |||
@@ -1120,8 +1120,8 @@ static int wm9081_digital_mute(struct snd_soc_dai *codec_dai, int mute) | |||
1120 | return 0; | 1120 | return 0; |
1121 | } | 1121 | } |
1122 | 1122 | ||
1123 | static int wm9081_set_sysclk(struct snd_soc_codec *codec, | 1123 | static int wm9081_set_sysclk(struct snd_soc_codec *codec, int clk_id, |
1124 | int clk_id, unsigned int freq, int dir) | 1124 | int source, unsigned int freq, int dir) |
1125 | { | 1125 | { |
1126 | struct wm9081_priv *wm9081 = snd_soc_codec_get_drvdata(codec); | 1126 | struct wm9081_priv *wm9081 = snd_soc_codec_get_drvdata(codec); |
1127 | 1127 | ||
diff --git a/sound/soc/codecs/wm9090.c b/sound/soc/codecs/wm9090.c index 4de12203e611..f2f3077928da 100644 --- a/sound/soc/codecs/wm9090.c +++ b/sound/soc/codecs/wm9090.c | |||
@@ -139,7 +139,6 @@ static const u16 wm9090_reg_defaults[] = { | |||
139 | 139 | ||
140 | /* This struct is used to save the context */ | 140 | /* This struct is used to save the context */ |
141 | struct wm9090_priv { | 141 | struct wm9090_priv { |
142 | struct mutex mutex; | ||
143 | struct wm9090_platform_data pdata; | 142 | struct wm9090_platform_data pdata; |
144 | void *control_data; | 143 | void *control_data; |
145 | }; | 144 | }; |
@@ -663,7 +662,6 @@ static int wm9090_i2c_probe(struct i2c_client *i2c, | |||
663 | 662 | ||
664 | i2c_set_clientdata(i2c, wm9090); | 663 | i2c_set_clientdata(i2c, wm9090); |
665 | wm9090->control_data = i2c; | 664 | wm9090->control_data = i2c; |
666 | mutex_init(&wm9090->mutex); | ||
667 | 665 | ||
668 | ret = snd_soc_register_codec(&i2c->dev, | 666 | ret = snd_soc_register_codec(&i2c->dev, |
669 | &soc_codec_dev_wm9090, NULL, 0); | 667 | &soc_codec_dev_wm9090, NULL, 0); |
diff --git a/sound/soc/codecs/wm_hubs.c b/sound/soc/codecs/wm_hubs.c index e763c54c55dc..ca8ce03510f4 100644 --- a/sound/soc/codecs/wm_hubs.c +++ b/sound/soc/codecs/wm_hubs.c | |||
@@ -18,6 +18,7 @@ | |||
18 | #include <linux/pm.h> | 18 | #include <linux/pm.h> |
19 | #include <linux/i2c.h> | 19 | #include <linux/i2c.h> |
20 | #include <linux/platform_device.h> | 20 | #include <linux/platform_device.h> |
21 | #include <linux/mfd/wm8994/registers.h> | ||
21 | #include <sound/core.h> | 22 | #include <sound/core.h> |
22 | #include <sound/pcm.h> | 23 | #include <sound/pcm.h> |
23 | #include <sound/pcm_params.h> | 24 | #include <sound/pcm_params.h> |
@@ -116,14 +117,23 @@ static void calibrate_dc_servo(struct snd_soc_codec *codec) | |||
116 | { | 117 | { |
117 | struct wm_hubs_data *hubs = snd_soc_codec_get_drvdata(codec); | 118 | struct wm_hubs_data *hubs = snd_soc_codec_get_drvdata(codec); |
118 | s8 offset; | 119 | s8 offset; |
119 | u16 reg, reg_l, reg_r, dcs_cfg; | 120 | u16 reg, reg_l, reg_r, dcs_cfg, dcs_reg; |
121 | |||
122 | switch (hubs->dcs_readback_mode) { | ||
123 | case 2: | ||
124 | dcs_reg = WM8994_DC_SERVO_4E; | ||
125 | break; | ||
126 | default: | ||
127 | dcs_reg = WM8993_DC_SERVO_3; | ||
128 | break; | ||
129 | } | ||
120 | 130 | ||
121 | /* If we're using a digital only path and have a previously | 131 | /* If we're using a digital only path and have a previously |
122 | * callibrated DC servo offset stored then use that. */ | 132 | * callibrated DC servo offset stored then use that. */ |
123 | if (hubs->class_w && hubs->class_w_dcs) { | 133 | if (hubs->class_w && hubs->class_w_dcs) { |
124 | dev_dbg(codec->dev, "Using cached DC servo offset %x\n", | 134 | dev_dbg(codec->dev, "Using cached DC servo offset %x\n", |
125 | hubs->class_w_dcs); | 135 | hubs->class_w_dcs); |
126 | snd_soc_write(codec, WM8993_DC_SERVO_3, hubs->class_w_dcs); | 136 | snd_soc_write(codec, dcs_reg, hubs->class_w_dcs); |
127 | wait_for_dc_servo(codec, | 137 | wait_for_dc_servo(codec, |
128 | WM8993_DCS_TRIG_DAC_WR_0 | | 138 | WM8993_DCS_TRIG_DAC_WR_0 | |
129 | WM8993_DCS_TRIG_DAC_WR_1); | 139 | WM8993_DCS_TRIG_DAC_WR_1); |
@@ -154,8 +164,9 @@ static void calibrate_dc_servo(struct snd_soc_codec *codec) | |||
154 | reg_r = snd_soc_read(codec, WM8993_DC_SERVO_READBACK_2) | 164 | reg_r = snd_soc_read(codec, WM8993_DC_SERVO_READBACK_2) |
155 | & WM8993_DCS_INTEG_CHAN_1_MASK; | 165 | & WM8993_DCS_INTEG_CHAN_1_MASK; |
156 | break; | 166 | break; |
167 | case 2: | ||
157 | case 1: | 168 | case 1: |
158 | reg = snd_soc_read(codec, WM8993_DC_SERVO_3); | 169 | reg = snd_soc_read(codec, dcs_reg); |
159 | reg_r = (reg & WM8993_DCS_DAC_WR_VAL_1_MASK) | 170 | reg_r = (reg & WM8993_DCS_DAC_WR_VAL_1_MASK) |
160 | >> WM8993_DCS_DAC_WR_VAL_1_SHIFT; | 171 | >> WM8993_DCS_DAC_WR_VAL_1_SHIFT; |
161 | reg_l = reg & WM8993_DCS_DAC_WR_VAL_0_MASK; | 172 | reg_l = reg & WM8993_DCS_DAC_WR_VAL_0_MASK; |
@@ -168,24 +179,25 @@ static void calibrate_dc_servo(struct snd_soc_codec *codec) | |||
168 | dev_dbg(codec->dev, "DCS input: %x %x\n", reg_l, reg_r); | 179 | dev_dbg(codec->dev, "DCS input: %x %x\n", reg_l, reg_r); |
169 | 180 | ||
170 | /* Apply correction to DC servo result */ | 181 | /* Apply correction to DC servo result */ |
171 | if (hubs->dcs_codes) { | 182 | if (hubs->dcs_codes_l || hubs->dcs_codes_r) { |
172 | dev_dbg(codec->dev, "Applying %d code DC servo correction\n", | 183 | dev_dbg(codec->dev, |
173 | hubs->dcs_codes); | 184 | "Applying %d/%d code DC servo correction\n", |
185 | hubs->dcs_codes_l, hubs->dcs_codes_r); | ||
174 | 186 | ||
175 | /* HPOUT1R */ | 187 | /* HPOUT1R */ |
176 | offset = reg_r; | 188 | offset = reg_r; |
177 | offset += hubs->dcs_codes; | 189 | offset += hubs->dcs_codes_r; |
178 | dcs_cfg = (u8)offset << WM8993_DCS_DAC_WR_VAL_1_SHIFT; | 190 | dcs_cfg = (u8)offset << WM8993_DCS_DAC_WR_VAL_1_SHIFT; |
179 | 191 | ||
180 | /* HPOUT1L */ | 192 | /* HPOUT1L */ |
181 | offset = reg_l; | 193 | offset = reg_l; |
182 | offset += hubs->dcs_codes; | 194 | offset += hubs->dcs_codes_l; |
183 | dcs_cfg |= (u8)offset; | 195 | dcs_cfg |= (u8)offset; |
184 | 196 | ||
185 | dev_dbg(codec->dev, "DCS result: %x\n", dcs_cfg); | 197 | dev_dbg(codec->dev, "DCS result: %x\n", dcs_cfg); |
186 | 198 | ||
187 | /* Do it */ | 199 | /* Do it */ |
188 | snd_soc_write(codec, WM8993_DC_SERVO_3, dcs_cfg); | 200 | snd_soc_write(codec, dcs_reg, dcs_cfg); |
189 | wait_for_dc_servo(codec, | 201 | wait_for_dc_servo(codec, |
190 | WM8993_DCS_TRIG_DAC_WR_0 | | 202 | WM8993_DCS_TRIG_DAC_WR_0 | |
191 | WM8993_DCS_TRIG_DAC_WR_1); | 203 | WM8993_DCS_TRIG_DAC_WR_1); |
@@ -217,7 +229,7 @@ static int wm8993_put_dc_servo(struct snd_kcontrol *kcontrol, | |||
217 | 229 | ||
218 | /* If we're applying an offset correction then updating the | 230 | /* If we're applying an offset correction then updating the |
219 | * callibration would be likely to introduce further offsets. */ | 231 | * callibration would be likely to introduce further offsets. */ |
220 | if (hubs->dcs_codes || hubs->no_series_update) | 232 | if (hubs->dcs_codes_l || hubs->dcs_codes_r || hubs->no_series_update) |
221 | return ret; | 233 | return ret; |
222 | 234 | ||
223 | /* Only need to do this if the outputs are active */ | 235 | /* Only need to do this if the outputs are active */ |
@@ -699,6 +711,11 @@ static const struct snd_soc_dapm_route analogue_routes[] = { | |||
699 | { "IN1L PGA", "IN1LP Switch", "IN1LP" }, | 711 | { "IN1L PGA", "IN1LP Switch", "IN1LP" }, |
700 | { "IN1L PGA", "IN1LN Switch", "IN1LN" }, | 712 | { "IN1L PGA", "IN1LN Switch", "IN1LN" }, |
701 | 713 | ||
714 | { "IN1L PGA", NULL, "VMID" }, | ||
715 | { "IN1R PGA", NULL, "VMID" }, | ||
716 | { "IN2L PGA", NULL, "VMID" }, | ||
717 | { "IN2R PGA", NULL, "VMID" }, | ||
718 | |||
702 | { "IN1R PGA", "IN1RP Switch", "IN1RP" }, | 719 | { "IN1R PGA", "IN1RP Switch", "IN1RP" }, |
703 | { "IN1R PGA", "IN1RN Switch", "IN1RN" }, | 720 | { "IN1R PGA", "IN1RN Switch", "IN1RN" }, |
704 | 721 | ||
@@ -716,12 +733,14 @@ static const struct snd_soc_dapm_route analogue_routes[] = { | |||
716 | { "MIXINL", NULL, "Direct Voice" }, | 733 | { "MIXINL", NULL, "Direct Voice" }, |
717 | { "MIXINL", NULL, "IN1LP" }, | 734 | { "MIXINL", NULL, "IN1LP" }, |
718 | { "MIXINL", NULL, "Left Output Mixer" }, | 735 | { "MIXINL", NULL, "Left Output Mixer" }, |
736 | { "MIXINL", NULL, "VMID" }, | ||
719 | 737 | ||
720 | { "MIXINR", "IN1R Switch", "IN1R PGA" }, | 738 | { "MIXINR", "IN1R Switch", "IN1R PGA" }, |
721 | { "MIXINR", "IN2R Switch", "IN2R PGA" }, | 739 | { "MIXINR", "IN2R Switch", "IN2R PGA" }, |
722 | { "MIXINR", NULL, "Direct Voice" }, | 740 | { "MIXINR", NULL, "Direct Voice" }, |
723 | { "MIXINR", NULL, "IN1RP" }, | 741 | { "MIXINR", NULL, "IN1RP" }, |
724 | { "MIXINR", NULL, "Right Output Mixer" }, | 742 | { "MIXINR", NULL, "Right Output Mixer" }, |
743 | { "MIXINR", NULL, "VMID" }, | ||
725 | 744 | ||
726 | { "ADCL", NULL, "MIXINL" }, | 745 | { "ADCL", NULL, "MIXINL" }, |
727 | { "ADCR", NULL, "MIXINR" }, | 746 | { "ADCR", NULL, "MIXINR" }, |
@@ -752,6 +771,7 @@ static const struct snd_soc_dapm_route analogue_routes[] = { | |||
752 | { "Earpiece Mixer", "Left Output Switch", "Left Output PGA" }, | 771 | { "Earpiece Mixer", "Left Output Switch", "Left Output PGA" }, |
753 | { "Earpiece Mixer", "Right Output Switch", "Right Output PGA" }, | 772 | { "Earpiece Mixer", "Right Output Switch", "Right Output PGA" }, |
754 | 773 | ||
774 | { "Earpiece Driver", NULL, "VMID" }, | ||
755 | { "Earpiece Driver", NULL, "Earpiece Mixer" }, | 775 | { "Earpiece Driver", NULL, "Earpiece Mixer" }, |
756 | { "HPOUT2N", NULL, "Earpiece Driver" }, | 776 | { "HPOUT2N", NULL, "Earpiece Driver" }, |
757 | { "HPOUT2P", NULL, "Earpiece Driver" }, | 777 | { "HPOUT2P", NULL, "Earpiece Driver" }, |
@@ -774,9 +794,11 @@ static const struct snd_soc_dapm_route analogue_routes[] = { | |||
774 | { "SPKR Boost", "SPKR Switch", "SPKR" }, | 794 | { "SPKR Boost", "SPKR Switch", "SPKR" }, |
775 | { "SPKR Boost", "SPKL Switch", "SPKL" }, | 795 | { "SPKR Boost", "SPKL Switch", "SPKL" }, |
776 | 796 | ||
797 | { "SPKL Driver", NULL, "VMID" }, | ||
777 | { "SPKL Driver", NULL, "SPKL Boost" }, | 798 | { "SPKL Driver", NULL, "SPKL Boost" }, |
778 | { "SPKL Driver", NULL, "CLK_SYS" }, | 799 | { "SPKL Driver", NULL, "CLK_SYS" }, |
779 | 800 | ||
801 | { "SPKR Driver", NULL, "VMID" }, | ||
780 | { "SPKR Driver", NULL, "SPKR Boost" }, | 802 | { "SPKR Driver", NULL, "SPKR Boost" }, |
781 | { "SPKR Driver", NULL, "CLK_SYS" }, | 803 | { "SPKR Driver", NULL, "CLK_SYS" }, |
782 | 804 | ||
@@ -790,12 +812,18 @@ static const struct snd_soc_dapm_route analogue_routes[] = { | |||
790 | 812 | ||
791 | { "Headphone PGA", NULL, "Left Headphone Mux" }, | 813 | { "Headphone PGA", NULL, "Left Headphone Mux" }, |
792 | { "Headphone PGA", NULL, "Right Headphone Mux" }, | 814 | { "Headphone PGA", NULL, "Right Headphone Mux" }, |
815 | { "Headphone PGA", NULL, "VMID" }, | ||
793 | { "Headphone PGA", NULL, "CLK_SYS" }, | 816 | { "Headphone PGA", NULL, "CLK_SYS" }, |
794 | { "Headphone PGA", NULL, "Headphone Supply" }, | 817 | { "Headphone PGA", NULL, "Headphone Supply" }, |
795 | 818 | ||
796 | { "HPOUT1L", NULL, "Headphone PGA" }, | 819 | { "HPOUT1L", NULL, "Headphone PGA" }, |
797 | { "HPOUT1R", NULL, "Headphone PGA" }, | 820 | { "HPOUT1R", NULL, "Headphone PGA" }, |
798 | 821 | ||
822 | { "LINEOUT1N Driver", NULL, "VMID" }, | ||
823 | { "LINEOUT1P Driver", NULL, "VMID" }, | ||
824 | { "LINEOUT2N Driver", NULL, "VMID" }, | ||
825 | { "LINEOUT2P Driver", NULL, "VMID" }, | ||
826 | |||
799 | { "LINEOUT1N", NULL, "LINEOUT1N Driver" }, | 827 | { "LINEOUT1N", NULL, "LINEOUT1N Driver" }, |
800 | { "LINEOUT1P", NULL, "LINEOUT1P Driver" }, | 828 | { "LINEOUT1P", NULL, "LINEOUT1P Driver" }, |
801 | { "LINEOUT2N", NULL, "LINEOUT2N Driver" }, | 829 | { "LINEOUT2N", NULL, "LINEOUT2N Driver" }, |
diff --git a/sound/soc/codecs/wm_hubs.h b/sound/soc/codecs/wm_hubs.h index 676b1252ab91..c674c7a502a6 100644 --- a/sound/soc/codecs/wm_hubs.h +++ b/sound/soc/codecs/wm_hubs.h | |||
@@ -23,7 +23,8 @@ extern const unsigned int wm_hubs_spkmix_tlv[]; | |||
23 | 23 | ||
24 | /* This *must* be the first element of the codec->private_data struct */ | 24 | /* This *must* be the first element of the codec->private_data struct */ |
25 | struct wm_hubs_data { | 25 | struct wm_hubs_data { |
26 | int dcs_codes; | 26 | int dcs_codes_l; |
27 | int dcs_codes_r; | ||
27 | int dcs_readback_mode; | 28 | int dcs_readback_mode; |
28 | int hp_startup_mode; | 29 | int hp_startup_mode; |
29 | int series_startup; | 30 | int series_startup; |
diff --git a/sound/soc/davinci/davinci-mcasp.c b/sound/soc/davinci/davinci-mcasp.c index 8566238db2a5..7173df254a91 100644 --- a/sound/soc/davinci/davinci-mcasp.c +++ b/sound/soc/davinci/davinci-mcasp.c | |||
@@ -732,16 +732,19 @@ static int davinci_mcasp_hw_params(struct snd_pcm_substream *substream, | |||
732 | davinci_hw_param(dev, substream->stream); | 732 | davinci_hw_param(dev, substream->stream); |
733 | 733 | ||
734 | switch (params_format(params)) { | 734 | switch (params_format(params)) { |
735 | case SNDRV_PCM_FORMAT_U8: | ||
735 | case SNDRV_PCM_FORMAT_S8: | 736 | case SNDRV_PCM_FORMAT_S8: |
736 | dma_params->data_type = 1; | 737 | dma_params->data_type = 1; |
737 | word_length = DAVINCI_AUDIO_WORD_8; | 738 | word_length = DAVINCI_AUDIO_WORD_8; |
738 | break; | 739 | break; |
739 | 740 | ||
741 | case SNDRV_PCM_FORMAT_U16_LE: | ||
740 | case SNDRV_PCM_FORMAT_S16_LE: | 742 | case SNDRV_PCM_FORMAT_S16_LE: |
741 | dma_params->data_type = 2; | 743 | dma_params->data_type = 2; |
742 | word_length = DAVINCI_AUDIO_WORD_16; | 744 | word_length = DAVINCI_AUDIO_WORD_16; |
743 | break; | 745 | break; |
744 | 746 | ||
747 | case SNDRV_PCM_FORMAT_U32_LE: | ||
745 | case SNDRV_PCM_FORMAT_S32_LE: | 748 | case SNDRV_PCM_FORMAT_S32_LE: |
746 | dma_params->data_type = 4; | 749 | dma_params->data_type = 4; |
747 | word_length = DAVINCI_AUDIO_WORD_32; | 750 | word_length = DAVINCI_AUDIO_WORD_32; |
@@ -818,6 +821,13 @@ static struct snd_soc_dai_ops davinci_mcasp_dai_ops = { | |||
818 | 821 | ||
819 | }; | 822 | }; |
820 | 823 | ||
824 | #define DAVINCI_MCASP_PCM_FMTS (SNDRV_PCM_FMTBIT_S8 | \ | ||
825 | SNDRV_PCM_FMTBIT_U8 | \ | ||
826 | SNDRV_PCM_FMTBIT_S16_LE | \ | ||
827 | SNDRV_PCM_FMTBIT_U16_LE | \ | ||
828 | SNDRV_PCM_FMTBIT_S32_LE | \ | ||
829 | SNDRV_PCM_FMTBIT_U32_LE) | ||
830 | |||
821 | static struct snd_soc_dai_driver davinci_mcasp_dai[] = { | 831 | static struct snd_soc_dai_driver davinci_mcasp_dai[] = { |
822 | { | 832 | { |
823 | .name = "davinci-mcasp.0", | 833 | .name = "davinci-mcasp.0", |
@@ -825,17 +835,13 @@ static struct snd_soc_dai_driver davinci_mcasp_dai[] = { | |||
825 | .channels_min = 2, | 835 | .channels_min = 2, |
826 | .channels_max = 2, | 836 | .channels_max = 2, |
827 | .rates = DAVINCI_MCASP_RATES, | 837 | .rates = DAVINCI_MCASP_RATES, |
828 | .formats = SNDRV_PCM_FMTBIT_S8 | | 838 | .formats = DAVINCI_MCASP_PCM_FMTS, |
829 | SNDRV_PCM_FMTBIT_S16_LE | | ||
830 | SNDRV_PCM_FMTBIT_S32_LE, | ||
831 | }, | 839 | }, |
832 | .capture = { | 840 | .capture = { |
833 | .channels_min = 2, | 841 | .channels_min = 2, |
834 | .channels_max = 2, | 842 | .channels_max = 2, |
835 | .rates = DAVINCI_MCASP_RATES, | 843 | .rates = DAVINCI_MCASP_RATES, |
836 | .formats = SNDRV_PCM_FMTBIT_S8 | | 844 | .formats = DAVINCI_MCASP_PCM_FMTS, |
837 | SNDRV_PCM_FMTBIT_S16_LE | | ||
838 | SNDRV_PCM_FMTBIT_S32_LE, | ||
839 | }, | 845 | }, |
840 | .ops = &davinci_mcasp_dai_ops, | 846 | .ops = &davinci_mcasp_dai_ops, |
841 | 847 | ||
@@ -846,7 +852,7 @@ static struct snd_soc_dai_driver davinci_mcasp_dai[] = { | |||
846 | .channels_min = 1, | 852 | .channels_min = 1, |
847 | .channels_max = 384, | 853 | .channels_max = 384, |
848 | .rates = DAVINCI_MCASP_RATES, | 854 | .rates = DAVINCI_MCASP_RATES, |
849 | .formats = SNDRV_PCM_FMTBIT_S16_LE, | 855 | .formats = DAVINCI_MCASP_PCM_FMTS, |
850 | }, | 856 | }, |
851 | .ops = &davinci_mcasp_dai_ops, | 857 | .ops = &davinci_mcasp_dai_ops, |
852 | }, | 858 | }, |
diff --git a/sound/soc/davinci/davinci-pcm.c b/sound/soc/davinci/davinci-pcm.c index a49e667373bc..d5fe08cc5db7 100644 --- a/sound/soc/davinci/davinci-pcm.c +++ b/sound/soc/davinci/davinci-pcm.c | |||
@@ -180,7 +180,6 @@ static void davinci_pcm_enqueue_dma(struct snd_pcm_substream *substream) | |||
180 | { | 180 | { |
181 | struct davinci_runtime_data *prtd = substream->runtime->private_data; | 181 | struct davinci_runtime_data *prtd = substream->runtime->private_data; |
182 | struct snd_pcm_runtime *runtime = substream->runtime; | 182 | struct snd_pcm_runtime *runtime = substream->runtime; |
183 | int link = prtd->asp_link[0]; | ||
184 | unsigned int period_size; | 183 | unsigned int period_size; |
185 | unsigned int dma_offset; | 184 | unsigned int dma_offset; |
186 | dma_addr_t dma_pos; | 185 | dma_addr_t dma_pos; |
@@ -198,7 +197,8 @@ static void davinci_pcm_enqueue_dma(struct snd_pcm_substream *substream) | |||
198 | fifo_level = prtd->params->fifo_level; | 197 | fifo_level = prtd->params->fifo_level; |
199 | 198 | ||
200 | pr_debug("davinci_pcm: audio_set_dma_params_play channel = %d " | 199 | pr_debug("davinci_pcm: audio_set_dma_params_play channel = %d " |
201 | "dma_ptr = %x period_size=%x\n", link, dma_pos, period_size); | 200 | "dma_ptr = %x period_size=%x\n", prtd->asp_link[0], dma_pos, |
201 | period_size); | ||
202 | 202 | ||
203 | data_type = prtd->params->data_type; | 203 | data_type = prtd->params->data_type; |
204 | count = period_size / data_type; | 204 | count = period_size / data_type; |
@@ -222,17 +222,19 @@ static void davinci_pcm_enqueue_dma(struct snd_pcm_substream *substream) | |||
222 | } | 222 | } |
223 | 223 | ||
224 | acnt = prtd->params->acnt; | 224 | acnt = prtd->params->acnt; |
225 | edma_set_src(link, src, INCR, W8BIT); | 225 | edma_set_src(prtd->asp_link[0], src, INCR, W8BIT); |
226 | edma_set_dest(link, dst, INCR, W8BIT); | 226 | edma_set_dest(prtd->asp_link[0], dst, INCR, W8BIT); |
227 | 227 | ||
228 | edma_set_src_index(link, src_bidx, src_cidx); | 228 | edma_set_src_index(prtd->asp_link[0], src_bidx, src_cidx); |
229 | edma_set_dest_index(link, dst_bidx, dst_cidx); | 229 | edma_set_dest_index(prtd->asp_link[0], dst_bidx, dst_cidx); |
230 | 230 | ||
231 | if (!fifo_level) | 231 | if (!fifo_level) |
232 | edma_set_transfer_params(link, acnt, count, 1, 0, ASYNC); | 232 | edma_set_transfer_params(prtd->asp_link[0], acnt, count, 1, 0, |
233 | ASYNC); | ||
233 | else | 234 | else |
234 | edma_set_transfer_params(link, acnt, fifo_level, count, | 235 | edma_set_transfer_params(prtd->asp_link[0], acnt, fifo_level, |
235 | fifo_level, ABSYNC); | 236 | count, fifo_level, |
237 | ABSYNC); | ||
236 | } | 238 | } |
237 | 239 | ||
238 | static void davinci_pcm_dma_irq(unsigned link, u16 ch_status, void *data) | 240 | static void davinci_pcm_dma_irq(unsigned link, u16 ch_status, void *data) |
@@ -305,7 +307,6 @@ static int ping_pong_dma_setup(struct snd_pcm_substream *substream) | |||
305 | unsigned int acnt = params->acnt; | 307 | unsigned int acnt = params->acnt; |
306 | /* divide by 2 for ping/pong */ | 308 | /* divide by 2 for ping/pong */ |
307 | unsigned int ping_size = snd_pcm_lib_period_bytes(substream) >> 1; | 309 | unsigned int ping_size = snd_pcm_lib_period_bytes(substream) >> 1; |
308 | int link = prtd->asp_link[1]; | ||
309 | unsigned int fifo_level = prtd->params->fifo_level; | 310 | unsigned int fifo_level = prtd->params->fifo_level; |
310 | unsigned int count; | 311 | unsigned int count; |
311 | if ((data_type == 0) || (data_type > 4)) { | 312 | if ((data_type == 0) || (data_type > 4)) { |
@@ -316,28 +317,26 @@ static int ping_pong_dma_setup(struct snd_pcm_substream *substream) | |||
316 | dma_addr_t asp_src_pong = iram_dma->addr + ping_size; | 317 | dma_addr_t asp_src_pong = iram_dma->addr + ping_size; |
317 | ram_src_cidx = ping_size; | 318 | ram_src_cidx = ping_size; |
318 | ram_dst_cidx = -ping_size; | 319 | ram_dst_cidx = -ping_size; |
319 | edma_set_src(link, asp_src_pong, INCR, W8BIT); | 320 | edma_set_src(prtd->asp_link[1], asp_src_pong, INCR, W8BIT); |
320 | 321 | ||
321 | link = prtd->asp_link[0]; | 322 | edma_set_src_index(prtd->asp_link[0], data_type, |
322 | edma_set_src_index(link, data_type, data_type * fifo_level); | 323 | data_type * fifo_level); |
323 | link = prtd->asp_link[1]; | 324 | edma_set_src_index(prtd->asp_link[1], data_type, |
324 | edma_set_src_index(link, data_type, data_type * fifo_level); | 325 | data_type * fifo_level); |
325 | 326 | ||
326 | link = prtd->ram_link; | 327 | edma_set_src(prtd->ram_link, runtime->dma_addr, INCR, W32BIT); |
327 | edma_set_src(link, runtime->dma_addr, INCR, W32BIT); | ||
328 | } else { | 328 | } else { |
329 | dma_addr_t asp_dst_pong = iram_dma->addr + ping_size; | 329 | dma_addr_t asp_dst_pong = iram_dma->addr + ping_size; |
330 | ram_src_cidx = -ping_size; | 330 | ram_src_cidx = -ping_size; |
331 | ram_dst_cidx = ping_size; | 331 | ram_dst_cidx = ping_size; |
332 | edma_set_dest(link, asp_dst_pong, INCR, W8BIT); | 332 | edma_set_dest(prtd->asp_link[1], asp_dst_pong, INCR, W8BIT); |
333 | 333 | ||
334 | link = prtd->asp_link[0]; | 334 | edma_set_dest_index(prtd->asp_link[0], data_type, |
335 | edma_set_dest_index(link, data_type, data_type * fifo_level); | 335 | data_type * fifo_level); |
336 | link = prtd->asp_link[1]; | 336 | edma_set_dest_index(prtd->asp_link[1], data_type, |
337 | edma_set_dest_index(link, data_type, data_type * fifo_level); | 337 | data_type * fifo_level); |
338 | 338 | ||
339 | link = prtd->ram_link; | 339 | edma_set_dest(prtd->ram_link, runtime->dma_addr, INCR, W32BIT); |
340 | edma_set_dest(link, runtime->dma_addr, INCR, W32BIT); | ||
341 | } | 340 | } |
342 | 341 | ||
343 | if (!fifo_level) { | 342 | if (!fifo_level) { |
@@ -354,10 +353,9 @@ static int ping_pong_dma_setup(struct snd_pcm_substream *substream) | |||
354 | count, fifo_level, ABSYNC); | 353 | count, fifo_level, ABSYNC); |
355 | } | 354 | } |
356 | 355 | ||
357 | link = prtd->ram_link; | 356 | edma_set_src_index(prtd->ram_link, ping_size, ram_src_cidx); |
358 | edma_set_src_index(link, ping_size, ram_src_cidx); | 357 | edma_set_dest_index(prtd->ram_link, ping_size, ram_dst_cidx); |
359 | edma_set_dest_index(link, ping_size, ram_dst_cidx); | 358 | edma_set_transfer_params(prtd->ram_link, ping_size, 2, |
360 | edma_set_transfer_params(link, ping_size, 2, | ||
361 | runtime->periods, 2, ASYNC); | 359 | runtime->periods, 2, ASYNC); |
362 | 360 | ||
363 | /* init master params */ | 361 | /* init master params */ |
@@ -406,32 +404,32 @@ static int request_ping_pong(struct snd_pcm_substream *substream, | |||
406 | { | 404 | { |
407 | dma_addr_t asp_src_ping; | 405 | dma_addr_t asp_src_ping; |
408 | dma_addr_t asp_dst_ping; | 406 | dma_addr_t asp_dst_ping; |
409 | int link; | 407 | int ret; |
410 | struct davinci_pcm_dma_params *params = prtd->params; | 408 | struct davinci_pcm_dma_params *params = prtd->params; |
411 | 409 | ||
412 | /* Request ram master channel */ | 410 | /* Request ram master channel */ |
413 | link = prtd->ram_channel = edma_alloc_channel(EDMA_CHANNEL_ANY, | 411 | ret = prtd->ram_channel = edma_alloc_channel(EDMA_CHANNEL_ANY, |
414 | davinci_pcm_dma_irq, substream, | 412 | davinci_pcm_dma_irq, substream, |
415 | prtd->params->ram_chan_q); | 413 | prtd->params->ram_chan_q); |
416 | if (link < 0) | 414 | if (ret < 0) |
417 | goto exit1; | 415 | goto exit1; |
418 | 416 | ||
419 | /* Request ram link channel */ | 417 | /* Request ram link channel */ |
420 | link = prtd->ram_link = edma_alloc_slot( | 418 | ret = prtd->ram_link = edma_alloc_slot( |
421 | EDMA_CTLR(prtd->ram_channel), EDMA_SLOT_ANY); | 419 | EDMA_CTLR(prtd->ram_channel), EDMA_SLOT_ANY); |
422 | if (link < 0) | 420 | if (ret < 0) |
423 | goto exit2; | 421 | goto exit2; |
424 | 422 | ||
425 | link = prtd->asp_link[1] = edma_alloc_slot( | 423 | ret = prtd->asp_link[1] = edma_alloc_slot( |
426 | EDMA_CTLR(prtd->asp_channel), EDMA_SLOT_ANY); | 424 | EDMA_CTLR(prtd->asp_channel), EDMA_SLOT_ANY); |
427 | if (link < 0) | 425 | if (ret < 0) |
428 | goto exit3; | 426 | goto exit3; |
429 | 427 | ||
430 | prtd->ram_link2 = -1; | 428 | prtd->ram_link2 = -1; |
431 | if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) { | 429 | if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) { |
432 | link = prtd->ram_link2 = edma_alloc_slot( | 430 | ret = prtd->ram_link2 = edma_alloc_slot( |
433 | EDMA_CTLR(prtd->ram_channel), EDMA_SLOT_ANY); | 431 | EDMA_CTLR(prtd->ram_channel), EDMA_SLOT_ANY); |
434 | if (link < 0) | 432 | if (ret < 0) |
435 | goto exit4; | 433 | goto exit4; |
436 | } | 434 | } |
437 | /* circle ping-pong buffers */ | 435 | /* circle ping-pong buffers */ |
@@ -448,36 +446,33 @@ static int request_ping_pong(struct snd_pcm_substream *substream, | |||
448 | asp_dst_ping = iram_dma->addr; | 446 | asp_dst_ping = iram_dma->addr; |
449 | } | 447 | } |
450 | /* ping */ | 448 | /* ping */ |
451 | link = prtd->asp_link[0]; | 449 | edma_set_src(prtd->asp_link[0], asp_src_ping, INCR, W16BIT); |
452 | edma_set_src(link, asp_src_ping, INCR, W16BIT); | 450 | edma_set_dest(prtd->asp_link[0], asp_dst_ping, INCR, W16BIT); |
453 | edma_set_dest(link, asp_dst_ping, INCR, W16BIT); | 451 | edma_set_src_index(prtd->asp_link[0], 0, 0); |
454 | edma_set_src_index(link, 0, 0); | 452 | edma_set_dest_index(prtd->asp_link[0], 0, 0); |
455 | edma_set_dest_index(link, 0, 0); | ||
456 | 453 | ||
457 | edma_read_slot(link, &prtd->asp_params); | 454 | edma_read_slot(prtd->asp_link[0], &prtd->asp_params); |
458 | prtd->asp_params.opt &= ~(TCCMODE | EDMA_TCC(0x3f) | TCINTEN); | 455 | prtd->asp_params.opt &= ~(TCCMODE | EDMA_TCC(0x3f) | TCINTEN); |
459 | prtd->asp_params.opt |= TCCHEN | | 456 | prtd->asp_params.opt |= TCCHEN | |
460 | EDMA_TCC(prtd->ram_channel & 0x3f); | 457 | EDMA_TCC(prtd->ram_channel & 0x3f); |
461 | edma_write_slot(link, &prtd->asp_params); | 458 | edma_write_slot(prtd->asp_link[0], &prtd->asp_params); |
462 | 459 | ||
463 | /* pong */ | 460 | /* pong */ |
464 | link = prtd->asp_link[1]; | 461 | edma_set_src(prtd->asp_link[1], asp_src_ping, INCR, W16BIT); |
465 | edma_set_src(link, asp_src_ping, INCR, W16BIT); | 462 | edma_set_dest(prtd->asp_link[1], asp_dst_ping, INCR, W16BIT); |
466 | edma_set_dest(link, asp_dst_ping, INCR, W16BIT); | 463 | edma_set_src_index(prtd->asp_link[1], 0, 0); |
467 | edma_set_src_index(link, 0, 0); | 464 | edma_set_dest_index(prtd->asp_link[1], 0, 0); |
468 | edma_set_dest_index(link, 0, 0); | ||
469 | 465 | ||
470 | edma_read_slot(link, &prtd->asp_params); | 466 | edma_read_slot(prtd->asp_link[1], &prtd->asp_params); |
471 | prtd->asp_params.opt &= ~(TCCMODE | EDMA_TCC(0x3f)); | 467 | prtd->asp_params.opt &= ~(TCCMODE | EDMA_TCC(0x3f)); |
472 | /* interrupt after every pong completion */ | 468 | /* interrupt after every pong completion */ |
473 | prtd->asp_params.opt |= TCINTEN | TCCHEN | | 469 | prtd->asp_params.opt |= TCINTEN | TCCHEN | |
474 | EDMA_TCC(prtd->ram_channel & 0x3f); | 470 | EDMA_TCC(prtd->ram_channel & 0x3f); |
475 | edma_write_slot(link, &prtd->asp_params); | 471 | edma_write_slot(prtd->asp_link[1], &prtd->asp_params); |
476 | 472 | ||
477 | /* ram */ | 473 | /* ram */ |
478 | link = prtd->ram_link; | 474 | edma_set_src(prtd->ram_link, iram_dma->addr, INCR, W32BIT); |
479 | edma_set_src(link, iram_dma->addr, INCR, W32BIT); | 475 | edma_set_dest(prtd->ram_link, iram_dma->addr, INCR, W32BIT); |
480 | edma_set_dest(link, iram_dma->addr, INCR, W32BIT); | ||
481 | pr_debug("%s: audio dma channels/slots in use for ram:%u %u %u," | 476 | pr_debug("%s: audio dma channels/slots in use for ram:%u %u %u," |
482 | "for asp:%u %u %u\n", __func__, | 477 | "for asp:%u %u %u\n", __func__, |
483 | prtd->ram_channel, prtd->ram_link, prtd->ram_link2, | 478 | prtd->ram_channel, prtd->ram_link, prtd->ram_link2, |
@@ -494,7 +489,7 @@ exit2: | |||
494 | edma_free_channel(prtd->ram_channel); | 489 | edma_free_channel(prtd->ram_channel); |
495 | prtd->ram_channel = -1; | 490 | prtd->ram_channel = -1; |
496 | exit1: | 491 | exit1: |
497 | return link; | 492 | return ret; |
498 | } | 493 | } |
499 | 494 | ||
500 | static int davinci_pcm_dma_request(struct snd_pcm_substream *substream) | 495 | static int davinci_pcm_dma_request(struct snd_pcm_substream *substream) |
@@ -502,22 +497,22 @@ static int davinci_pcm_dma_request(struct snd_pcm_substream *substream) | |||
502 | struct snd_dma_buffer *iram_dma; | 497 | struct snd_dma_buffer *iram_dma; |
503 | struct davinci_runtime_data *prtd = substream->runtime->private_data; | 498 | struct davinci_runtime_data *prtd = substream->runtime->private_data; |
504 | struct davinci_pcm_dma_params *params = prtd->params; | 499 | struct davinci_pcm_dma_params *params = prtd->params; |
505 | int link; | 500 | int ret; |
506 | 501 | ||
507 | if (!params) | 502 | if (!params) |
508 | return -ENODEV; | 503 | return -ENODEV; |
509 | 504 | ||
510 | /* Request asp master DMA channel */ | 505 | /* Request asp master DMA channel */ |
511 | link = prtd->asp_channel = edma_alloc_channel(params->channel, | 506 | ret = prtd->asp_channel = edma_alloc_channel(params->channel, |
512 | davinci_pcm_dma_irq, substream, | 507 | davinci_pcm_dma_irq, substream, |
513 | prtd->params->asp_chan_q); | 508 | prtd->params->asp_chan_q); |
514 | if (link < 0) | 509 | if (ret < 0) |
515 | goto exit1; | 510 | goto exit1; |
516 | 511 | ||
517 | /* Request asp link channels */ | 512 | /* Request asp link channels */ |
518 | link = prtd->asp_link[0] = edma_alloc_slot( | 513 | ret = prtd->asp_link[0] = edma_alloc_slot( |
519 | EDMA_CTLR(prtd->asp_channel), EDMA_SLOT_ANY); | 514 | EDMA_CTLR(prtd->asp_channel), EDMA_SLOT_ANY); |
520 | if (link < 0) | 515 | if (ret < 0) |
521 | goto exit2; | 516 | goto exit2; |
522 | 517 | ||
523 | iram_dma = (struct snd_dma_buffer *)substream->dma_buffer.private_data; | 518 | iram_dma = (struct snd_dma_buffer *)substream->dma_buffer.private_data; |
@@ -537,17 +532,17 @@ static int davinci_pcm_dma_request(struct snd_pcm_substream *substream) | |||
537 | * the buffer and its length (ccnt) ... use it as a template | 532 | * the buffer and its length (ccnt) ... use it as a template |
538 | * so davinci_pcm_enqueue_dma() takes less time in IRQ. | 533 | * so davinci_pcm_enqueue_dma() takes less time in IRQ. |
539 | */ | 534 | */ |
540 | edma_read_slot(link, &prtd->asp_params); | 535 | edma_read_slot(prtd->asp_link[0], &prtd->asp_params); |
541 | prtd->asp_params.opt |= TCINTEN | | 536 | prtd->asp_params.opt |= TCINTEN | |
542 | EDMA_TCC(EDMA_CHAN_SLOT(prtd->asp_channel)); | 537 | EDMA_TCC(EDMA_CHAN_SLOT(prtd->asp_channel)); |
543 | prtd->asp_params.link_bcntrld = EDMA_CHAN_SLOT(link) << 5; | 538 | prtd->asp_params.link_bcntrld = EDMA_CHAN_SLOT(prtd->asp_link[0]) << 5; |
544 | edma_write_slot(link, &prtd->asp_params); | 539 | edma_write_slot(prtd->asp_link[0], &prtd->asp_params); |
545 | return 0; | 540 | return 0; |
546 | exit2: | 541 | exit2: |
547 | edma_free_channel(prtd->asp_channel); | 542 | edma_free_channel(prtd->asp_channel); |
548 | prtd->asp_channel = -1; | 543 | prtd->asp_channel = -1; |
549 | exit1: | 544 | exit1: |
550 | return link; | 545 | return ret; |
551 | } | 546 | } |
552 | 547 | ||
553 | static int davinci_pcm_trigger(struct snd_pcm_substream *substream, int cmd) | 548 | static int davinci_pcm_trigger(struct snd_pcm_substream *substream, int cmd) |
diff --git a/sound/soc/ep93xx/edb93xx.c b/sound/soc/ep93xx/edb93xx.c index d3aa15119d26..0134d4e9131c 100644 --- a/sound/soc/ep93xx/edb93xx.c +++ b/sound/soc/ep93xx/edb93xx.c | |||
@@ -28,12 +28,6 @@ | |||
28 | #include <mach/hardware.h> | 28 | #include <mach/hardware.h> |
29 | #include "ep93xx-pcm.h" | 29 | #include "ep93xx-pcm.h" |
30 | 30 | ||
31 | #define edb93xx_has_audio() (machine_is_edb9301() || \ | ||
32 | machine_is_edb9302() || \ | ||
33 | machine_is_edb9302a() || \ | ||
34 | machine_is_edb9307a() || \ | ||
35 | machine_is_edb9315a()) | ||
36 | |||
37 | static int edb93xx_hw_params(struct snd_pcm_substream *substream, | 31 | static int edb93xx_hw_params(struct snd_pcm_substream *substream, |
38 | struct snd_pcm_hw_params *params) | 32 | struct snd_pcm_hw_params *params) |
39 | { | 33 | { |
@@ -94,49 +88,61 @@ static struct snd_soc_card snd_soc_edb93xx = { | |||
94 | .num_links = 1, | 88 | .num_links = 1, |
95 | }; | 89 | }; |
96 | 90 | ||
97 | static struct platform_device *edb93xx_snd_device; | 91 | static int __devinit edb93xx_probe(struct platform_device *pdev) |
98 | |||
99 | static int __init edb93xx_init(void) | ||
100 | { | 92 | { |
93 | struct snd_soc_card *card = &snd_soc_edb93xx; | ||
101 | int ret; | 94 | int ret; |
102 | 95 | ||
103 | if (!edb93xx_has_audio()) | ||
104 | return -ENODEV; | ||
105 | |||
106 | ret = ep93xx_i2s_acquire(EP93XX_SYSCON_DEVCFG_I2SONAC97, | 96 | ret = ep93xx_i2s_acquire(EP93XX_SYSCON_DEVCFG_I2SONAC97, |
107 | EP93XX_SYSCON_I2SCLKDIV_ORIDE | | 97 | EP93XX_SYSCON_I2SCLKDIV_ORIDE | |
108 | EP93XX_SYSCON_I2SCLKDIV_SPOL); | 98 | EP93XX_SYSCON_I2SCLKDIV_SPOL); |
109 | if (ret) | 99 | if (ret) |
110 | return ret; | 100 | return ret; |
111 | 101 | ||
112 | edb93xx_snd_device = platform_device_alloc("soc-audio", -1); | 102 | card->dev = &pdev->dev; |
113 | if (!edb93xx_snd_device) { | 103 | |
114 | ret = -ENOMEM; | 104 | ret = snd_soc_register_card(card); |
115 | goto free_i2s; | 105 | if (ret) { |
106 | dev_err(&pdev->dev, "snd_soc_register_card() failed: %d\n", | ||
107 | ret); | ||
108 | ep93xx_i2s_release(); | ||
116 | } | 109 | } |
117 | 110 | ||
118 | platform_set_drvdata(edb93xx_snd_device, &snd_soc_edb93xx); | 111 | return ret; |
119 | ret = platform_device_add(edb93xx_snd_device); | 112 | } |
120 | if (ret) | ||
121 | goto device_put; | ||
122 | 113 | ||
123 | return 0; | 114 | static int __devexit edb93xx_remove(struct platform_device *pdev) |
115 | { | ||
116 | struct snd_soc_card *card = platform_get_drvdata(pdev); | ||
124 | 117 | ||
125 | device_put: | 118 | snd_soc_unregister_card(card); |
126 | platform_device_put(edb93xx_snd_device); | ||
127 | free_i2s: | ||
128 | ep93xx_i2s_release(); | 119 | ep93xx_i2s_release(); |
129 | return ret; | 120 | |
121 | return 0; | ||
122 | } | ||
123 | |||
124 | static struct platform_driver edb93xx_driver = { | ||
125 | .driver = { | ||
126 | .name = "edb93xx-audio", | ||
127 | .owner = THIS_MODULE, | ||
128 | }, | ||
129 | .probe = edb93xx_probe, | ||
130 | .remove = __devexit_p(edb93xx_remove), | ||
131 | }; | ||
132 | |||
133 | static int __init edb93xx_init(void) | ||
134 | { | ||
135 | return platform_driver_register(&edb93xx_driver); | ||
130 | } | 136 | } |
131 | module_init(edb93xx_init); | 137 | module_init(edb93xx_init); |
132 | 138 | ||
133 | static void __exit edb93xx_exit(void) | 139 | static void __exit edb93xx_exit(void) |
134 | { | 140 | { |
135 | platform_device_unregister(edb93xx_snd_device); | 141 | platform_driver_unregister(&edb93xx_driver); |
136 | ep93xx_i2s_release(); | ||
137 | } | 142 | } |
138 | module_exit(edb93xx_exit); | 143 | module_exit(edb93xx_exit); |
139 | 144 | ||
140 | MODULE_AUTHOR("Alexander Sverdlin <subaparts@yandex.ru>"); | 145 | MODULE_AUTHOR("Alexander Sverdlin <subaparts@yandex.ru>"); |
141 | MODULE_DESCRIPTION("ALSA SoC EDB93xx"); | 146 | MODULE_DESCRIPTION("ALSA SoC EDB93xx"); |
142 | MODULE_LICENSE("GPL"); | 147 | MODULE_LICENSE("GPL"); |
148 | MODULE_ALIAS("platform:edb93xx-audio"); | ||
diff --git a/sound/soc/ep93xx/ep93xx-pcm.c b/sound/soc/ep93xx/ep93xx-pcm.c index 8dfd3ad84b19..d00230a591b1 100644 --- a/sound/soc/ep93xx/ep93xx-pcm.c +++ b/sound/soc/ep93xx/ep93xx-pcm.c | |||
@@ -355,3 +355,4 @@ module_exit(ep93xx_soc_platform_exit); | |||
355 | MODULE_AUTHOR("Ryan Mallon"); | 355 | MODULE_AUTHOR("Ryan Mallon"); |
356 | MODULE_DESCRIPTION("EP93xx ALSA PCM interface"); | 356 | MODULE_DESCRIPTION("EP93xx ALSA PCM interface"); |
357 | MODULE_LICENSE("GPL"); | 357 | MODULE_LICENSE("GPL"); |
358 | MODULE_ALIAS("platform:ep93xx-pcm-audio"); | ||
diff --git a/sound/soc/ep93xx/simone.c b/sound/soc/ep93xx/simone.c index 286817946c56..968cb316d511 100644 --- a/sound/soc/ep93xx/simone.c +++ b/sound/soc/ep93xx/simone.c | |||
@@ -39,53 +39,61 @@ static struct snd_soc_card snd_soc_simone = { | |||
39 | }; | 39 | }; |
40 | 40 | ||
41 | static struct platform_device *simone_snd_ac97_device; | 41 | static struct platform_device *simone_snd_ac97_device; |
42 | static struct platform_device *simone_snd_device; | ||
43 | 42 | ||
44 | static int __init simone_init(void) | 43 | static int __devinit simone_probe(struct platform_device *pdev) |
45 | { | 44 | { |
45 | struct snd_soc_card *card = &snd_soc_simone; | ||
46 | int ret; | 46 | int ret; |
47 | 47 | ||
48 | if (!machine_is_sim_one()) | 48 | simone_snd_ac97_device = platform_device_register_simple("ac97-codec", |
49 | return -ENODEV; | 49 | -1, NULL, 0); |
50 | 50 | if (IS_ERR(simone_snd_ac97_device)) | |
51 | simone_snd_ac97_device = platform_device_alloc("ac97-codec", -1); | 51 | return PTR_ERR(simone_snd_ac97_device); |
52 | if (!simone_snd_ac97_device) | ||
53 | return -ENOMEM; | ||
54 | 52 | ||
55 | ret = platform_device_add(simone_snd_ac97_device); | 53 | card->dev = &pdev->dev; |
56 | if (ret) | ||
57 | goto fail1; | ||
58 | 54 | ||
59 | simone_snd_device = platform_device_alloc("soc-audio", -1); | 55 | ret = snd_soc_register_card(card); |
60 | if (!simone_snd_device) { | 56 | if (ret) { |
61 | ret = -ENOMEM; | 57 | dev_err(&pdev->dev, "snd_soc_register_card() failed: %d\n", |
62 | goto fail2; | 58 | ret); |
59 | platform_device_unregister(simone_snd_ac97_device); | ||
63 | } | 60 | } |
64 | 61 | ||
65 | platform_set_drvdata(simone_snd_device, &snd_soc_simone); | 62 | return ret; |
66 | ret = platform_device_add(simone_snd_device); | 63 | } |
67 | if (ret) | 64 | |
68 | goto fail3; | 65 | static int __devexit simone_remove(struct platform_device *pdev) |
66 | { | ||
67 | struct snd_soc_card *card = platform_get_drvdata(pdev); | ||
68 | |||
69 | snd_soc_unregister_card(card); | ||
70 | platform_device_unregister(simone_snd_ac97_device); | ||
69 | 71 | ||
70 | return 0; | 72 | return 0; |
73 | } | ||
71 | 74 | ||
72 | fail3: | 75 | static struct platform_driver simone_driver = { |
73 | platform_device_put(simone_snd_device); | 76 | .driver = { |
74 | fail2: | 77 | .name = "simone-audio", |
75 | platform_device_del(simone_snd_ac97_device); | 78 | .owner = THIS_MODULE, |
76 | fail1: | 79 | }, |
77 | platform_device_put(simone_snd_ac97_device); | 80 | .probe = simone_probe, |
78 | return ret; | 81 | .remove = __devexit_p(simone_remove), |
82 | }; | ||
83 | |||
84 | static int __init simone_init(void) | ||
85 | { | ||
86 | return platform_driver_register(&simone_driver); | ||
79 | } | 87 | } |
80 | module_init(simone_init); | 88 | module_init(simone_init); |
81 | 89 | ||
82 | static void __exit simone_exit(void) | 90 | static void __exit simone_exit(void) |
83 | { | 91 | { |
84 | platform_device_unregister(simone_snd_device); | 92 | platform_driver_unregister(&simone_driver); |
85 | platform_device_unregister(simone_snd_ac97_device); | ||
86 | } | 93 | } |
87 | module_exit(simone_exit); | 94 | module_exit(simone_exit); |
88 | 95 | ||
89 | MODULE_DESCRIPTION("ALSA SoC Simplemachines Sim.One"); | 96 | MODULE_DESCRIPTION("ALSA SoC Simplemachines Sim.One"); |
90 | MODULE_AUTHOR("Mika Westerberg <mika.westerberg@iki.fi>"); | 97 | MODULE_AUTHOR("Mika Westerberg <mika.westerberg@iki.fi>"); |
91 | MODULE_LICENSE("GPL"); | 98 | MODULE_LICENSE("GPL"); |
99 | MODULE_ALIAS("platform:simone-audio"); | ||
diff --git a/sound/soc/ep93xx/snappercl15.c b/sound/soc/ep93xx/snappercl15.c index c8aa8a5003ca..f74ac54c285a 100644 --- a/sound/soc/ep93xx/snappercl15.c +++ b/sound/soc/ep93xx/snappercl15.c | |||
@@ -104,37 +104,56 @@ static struct snd_soc_card snd_soc_snappercl15 = { | |||
104 | .num_links = 1, | 104 | .num_links = 1, |
105 | }; | 105 | }; |
106 | 106 | ||
107 | static struct platform_device *snappercl15_snd_device; | 107 | static int __devinit snappercl15_probe(struct platform_device *pdev) |
108 | |||
109 | static int __init snappercl15_init(void) | ||
110 | { | 108 | { |
109 | struct snd_soc_card *card = &snd_soc_snappercl15; | ||
111 | int ret; | 110 | int ret; |
112 | 111 | ||
113 | if (!machine_is_snapper_cl15()) | ||
114 | return -ENODEV; | ||
115 | |||
116 | ret = ep93xx_i2s_acquire(EP93XX_SYSCON_DEVCFG_I2SONAC97, | 112 | ret = ep93xx_i2s_acquire(EP93XX_SYSCON_DEVCFG_I2SONAC97, |
117 | EP93XX_SYSCON_I2SCLKDIV_ORIDE | | 113 | EP93XX_SYSCON_I2SCLKDIV_ORIDE | |
118 | EP93XX_SYSCON_I2SCLKDIV_SPOL); | 114 | EP93XX_SYSCON_I2SCLKDIV_SPOL); |
119 | if (ret) | 115 | if (ret) |
120 | return ret; | 116 | return ret; |
121 | 117 | ||
122 | snappercl15_snd_device = platform_device_alloc("soc-audio", -1); | 118 | card->dev = &pdev->dev; |
123 | if (!snappercl15_snd_device) | 119 | |
124 | return -ENOMEM; | 120 | ret = snd_soc_register_card(card); |
125 | 121 | if (ret) { | |
126 | platform_set_drvdata(snappercl15_snd_device, &snd_soc_snappercl15); | 122 | dev_err(&pdev->dev, "snd_soc_register_card() failed: %d\n", |
127 | ret = platform_device_add(snappercl15_snd_device); | 123 | ret); |
128 | if (ret) | 124 | ep93xx_i2s_release(); |
129 | platform_device_put(snappercl15_snd_device); | 125 | } |
130 | 126 | ||
131 | return ret; | 127 | return ret; |
132 | } | 128 | } |
133 | 129 | ||
134 | static void __exit snappercl15_exit(void) | 130 | static int __devexit snappercl15_remove(struct platform_device *pdev) |
135 | { | 131 | { |
136 | platform_device_unregister(snappercl15_snd_device); | 132 | struct snd_soc_card *card = platform_get_drvdata(pdev); |
133 | |||
134 | snd_soc_unregister_card(card); | ||
137 | ep93xx_i2s_release(); | 135 | ep93xx_i2s_release(); |
136 | |||
137 | return 0; | ||
138 | } | ||
139 | |||
140 | static struct platform_driver snappercl15_driver = { | ||
141 | .driver = { | ||
142 | .name = "snappercl15-audio", | ||
143 | .owner = THIS_MODULE, | ||
144 | }, | ||
145 | .probe = snappercl15_probe, | ||
146 | .remove = __devexit_p(snappercl15_remove), | ||
147 | }; | ||
148 | |||
149 | static int __init snappercl15_init(void) | ||
150 | { | ||
151 | return platform_driver_register(&snappercl15_driver); | ||
152 | } | ||
153 | |||
154 | static void __exit snappercl15_exit(void) | ||
155 | { | ||
156 | platform_driver_unregister(&snappercl15_driver); | ||
138 | } | 157 | } |
139 | 158 | ||
140 | module_init(snappercl15_init); | 159 | module_init(snappercl15_init); |
@@ -143,4 +162,4 @@ module_exit(snappercl15_exit); | |||
143 | MODULE_AUTHOR("Ryan Mallon"); | 162 | MODULE_AUTHOR("Ryan Mallon"); |
144 | MODULE_DESCRIPTION("ALSA SoC Snapper CL15"); | 163 | MODULE_DESCRIPTION("ALSA SoC Snapper CL15"); |
145 | MODULE_LICENSE("GPL"); | 164 | MODULE_LICENSE("GPL"); |
146 | 165 | MODULE_ALIAS("platform:snappercl15-audio"); | |
diff --git a/sound/soc/fsl/fsl_dma.c b/sound/soc/fsl/fsl_dma.c index cb50598338e9..ef15402a3bc4 100644 --- a/sound/soc/fsl/fsl_dma.c +++ b/sound/soc/fsl/fsl_dma.c | |||
@@ -297,7 +297,6 @@ static irqreturn_t fsl_dma_isr(int irq, void *dev_id) | |||
297 | static int fsl_dma_new(struct snd_soc_pcm_runtime *rtd) | 297 | static int fsl_dma_new(struct snd_soc_pcm_runtime *rtd) |
298 | { | 298 | { |
299 | struct snd_card *card = rtd->card->snd_card; | 299 | struct snd_card *card = rtd->card->snd_card; |
300 | struct snd_soc_dai *dai = rtd->cpu_dai; | ||
301 | struct snd_pcm *pcm = rtd->pcm; | 300 | struct snd_pcm *pcm = rtd->pcm; |
302 | static u64 fsl_dma_dmamask = DMA_BIT_MASK(36); | 301 | static u64 fsl_dma_dmamask = DMA_BIT_MASK(36); |
303 | int ret; | 302 | int ret; |
diff --git a/sound/soc/fsl/fsl_ssi.c b/sound/soc/fsl/fsl_ssi.c index d48afea5d93d..0268cf989736 100644 --- a/sound/soc/fsl/fsl_ssi.c +++ b/sound/soc/fsl/fsl_ssi.c | |||
@@ -78,7 +78,6 @@ | |||
78 | * @second_stream: pointer to second stream | 78 | * @second_stream: pointer to second stream |
79 | * @playback: the number of playback streams opened | 79 | * @playback: the number of playback streams opened |
80 | * @capture: the number of capture streams opened | 80 | * @capture: the number of capture streams opened |
81 | * @asynchronous: 0=synchronous mode, 1=asynchronous mode | ||
82 | * @cpu_dai: the CPU DAI for this device | 81 | * @cpu_dai: the CPU DAI for this device |
83 | * @dev_attr: the sysfs device attribute structure | 82 | * @dev_attr: the sysfs device attribute structure |
84 | * @stats: SSI statistics | 83 | * @stats: SSI statistics |
@@ -90,9 +89,6 @@ struct fsl_ssi_private { | |||
90 | unsigned int irq; | 89 | unsigned int irq; |
91 | struct snd_pcm_substream *first_stream; | 90 | struct snd_pcm_substream *first_stream; |
92 | struct snd_pcm_substream *second_stream; | 91 | struct snd_pcm_substream *second_stream; |
93 | unsigned int playback; | ||
94 | unsigned int capture; | ||
95 | int asynchronous; | ||
96 | unsigned int fifo_depth; | 92 | unsigned int fifo_depth; |
97 | struct snd_soc_dai_driver cpu_dai_drv; | 93 | struct snd_soc_dai_driver cpu_dai_drv; |
98 | struct device_attribute dev_attr; | 94 | struct device_attribute dev_attr; |
@@ -281,24 +277,18 @@ static int fsl_ssi_startup(struct snd_pcm_substream *substream, | |||
281 | struct snd_soc_dai *dai) | 277 | struct snd_soc_dai *dai) |
282 | { | 278 | { |
283 | struct snd_soc_pcm_runtime *rtd = substream->private_data; | 279 | struct snd_soc_pcm_runtime *rtd = substream->private_data; |
284 | struct fsl_ssi_private *ssi_private = snd_soc_dai_get_drvdata(rtd->cpu_dai); | 280 | struct fsl_ssi_private *ssi_private = |
281 | snd_soc_dai_get_drvdata(rtd->cpu_dai); | ||
282 | int synchronous = ssi_private->cpu_dai_drv.symmetric_rates; | ||
285 | 283 | ||
286 | /* | 284 | /* |
287 | * If this is the first stream opened, then request the IRQ | 285 | * If this is the first stream opened, then request the IRQ |
288 | * and initialize the SSI registers. | 286 | * and initialize the SSI registers. |
289 | */ | 287 | */ |
290 | if (!ssi_private->playback && !ssi_private->capture) { | 288 | if (!ssi_private->first_stream) { |
291 | struct ccsr_ssi __iomem *ssi = ssi_private->ssi; | 289 | struct ccsr_ssi __iomem *ssi = ssi_private->ssi; |
292 | int ret; | 290 | |
293 | 291 | ssi_private->first_stream = substream; | |
294 | /* The 'name' should not have any slashes in it. */ | ||
295 | ret = request_irq(ssi_private->irq, fsl_ssi_isr, 0, | ||
296 | ssi_private->name, ssi_private); | ||
297 | if (ret < 0) { | ||
298 | dev_err(substream->pcm->card->dev, | ||
299 | "could not claim irq %u\n", ssi_private->irq); | ||
300 | return ret; | ||
301 | } | ||
302 | 292 | ||
303 | /* | 293 | /* |
304 | * Section 16.5 of the MPC8610 reference manual says that the | 294 | * Section 16.5 of the MPC8610 reference manual says that the |
@@ -316,7 +306,7 @@ static int fsl_ssi_startup(struct snd_pcm_substream *substream, | |||
316 | clrsetbits_be32(&ssi->scr, | 306 | clrsetbits_be32(&ssi->scr, |
317 | CCSR_SSI_SCR_I2S_MODE_MASK | CCSR_SSI_SCR_SYN, | 307 | CCSR_SSI_SCR_I2S_MODE_MASK | CCSR_SSI_SCR_SYN, |
318 | CCSR_SSI_SCR_TFR_CLK_DIS | CCSR_SSI_SCR_I2S_MODE_SLAVE | 308 | CCSR_SSI_SCR_TFR_CLK_DIS | CCSR_SSI_SCR_I2S_MODE_SLAVE |
319 | | (ssi_private->asynchronous ? 0 : CCSR_SSI_SCR_SYN)); | 309 | | (synchronous ? CCSR_SSI_SCR_SYN : 0)); |
320 | 310 | ||
321 | out_be32(&ssi->stcr, | 311 | out_be32(&ssi->stcr, |
322 | CCSR_SSI_STCR_TXBIT0 | CCSR_SSI_STCR_TFEN0 | | 312 | CCSR_SSI_STCR_TXBIT0 | CCSR_SSI_STCR_TFEN0 | |
@@ -333,7 +323,7 @@ static int fsl_ssi_startup(struct snd_pcm_substream *substream, | |||
333 | * master. | 323 | * master. |
334 | */ | 324 | */ |
335 | 325 | ||
336 | /* 4. Enable the interrupts and DMA requests */ | 326 | /* Enable the interrupts and DMA requests */ |
337 | out_be32(&ssi->sier, SIER_FLAGS); | 327 | out_be32(&ssi->sier, SIER_FLAGS); |
338 | 328 | ||
339 | /* | 329 | /* |
@@ -362,58 +352,47 @@ static int fsl_ssi_startup(struct snd_pcm_substream *substream, | |||
362 | * this is bad is because at this point, the PCM driver has not | 352 | * this is bad is because at this point, the PCM driver has not |
363 | * finished initializing the DMA controller. | 353 | * finished initializing the DMA controller. |
364 | */ | 354 | */ |
365 | } | 355 | } else { |
356 | if (synchronous) { | ||
357 | struct snd_pcm_runtime *first_runtime = | ||
358 | ssi_private->first_stream->runtime; | ||
359 | /* | ||
360 | * This is the second stream open, and we're in | ||
361 | * synchronous mode, so we need to impose sample | ||
362 | * sample size constraints. This is because STCCR is | ||
363 | * used for playback and capture in synchronous mode, | ||
364 | * so there's no way to specify different word | ||
365 | * lengths. | ||
366 | * | ||
367 | * Note that this can cause a race condition if the | ||
368 | * second stream is opened before the first stream is | ||
369 | * fully initialized. We provide some protection by | ||
370 | * checking to make sure the first stream is | ||
371 | * initialized, but it's not perfect. ALSA sometimes | ||
372 | * re-initializes the driver with a different sample | ||
373 | * rate or size. If the second stream is opened | ||
374 | * before the first stream has received its final | ||
375 | * parameters, then the second stream may be | ||
376 | * constrained to the wrong sample rate or size. | ||
377 | */ | ||
378 | if (!first_runtime->sample_bits) { | ||
379 | dev_err(substream->pcm->card->dev, | ||
380 | "set sample size in %s stream first\n", | ||
381 | substream->stream == | ||
382 | SNDRV_PCM_STREAM_PLAYBACK | ||
383 | ? "capture" : "playback"); | ||
384 | return -EAGAIN; | ||
385 | } | ||
366 | 386 | ||
367 | if (!ssi_private->first_stream) | ||
368 | ssi_private->first_stream = substream; | ||
369 | else { | ||
370 | /* This is the second stream open, so we need to impose sample | ||
371 | * rate and maybe sample size constraints. Note that this can | ||
372 | * cause a race condition if the second stream is opened before | ||
373 | * the first stream is fully initialized. | ||
374 | * | ||
375 | * We provide some protection by checking to make sure the first | ||
376 | * stream is initialized, but it's not perfect. ALSA sometimes | ||
377 | * re-initializes the driver with a different sample rate or | ||
378 | * size. If the second stream is opened before the first stream | ||
379 | * has received its final parameters, then the second stream may | ||
380 | * be constrained to the wrong sample rate or size. | ||
381 | * | ||
382 | * FIXME: This code does not handle opening and closing streams | ||
383 | * repeatedly. If you open two streams and then close the first | ||
384 | * one, you may not be able to open another stream until you | ||
385 | * close the second one as well. | ||
386 | */ | ||
387 | struct snd_pcm_runtime *first_runtime = | ||
388 | ssi_private->first_stream->runtime; | ||
389 | |||
390 | if (!first_runtime->sample_bits) { | ||
391 | dev_err(substream->pcm->card->dev, | ||
392 | "set sample size in %s stream first\n", | ||
393 | substream->stream == SNDRV_PCM_STREAM_PLAYBACK | ||
394 | ? "capture" : "playback"); | ||
395 | return -EAGAIN; | ||
396 | } | ||
397 | |||
398 | /* If we're in synchronous mode, then we need to constrain | ||
399 | * the sample size as well. We don't support independent sample | ||
400 | * rates in asynchronous mode. | ||
401 | */ | ||
402 | if (!ssi_private->asynchronous) | ||
403 | snd_pcm_hw_constraint_minmax(substream->runtime, | 387 | snd_pcm_hw_constraint_minmax(substream->runtime, |
404 | SNDRV_PCM_HW_PARAM_SAMPLE_BITS, | 388 | SNDRV_PCM_HW_PARAM_SAMPLE_BITS, |
405 | first_runtime->sample_bits, | 389 | first_runtime->sample_bits, |
406 | first_runtime->sample_bits); | 390 | first_runtime->sample_bits); |
391 | } | ||
407 | 392 | ||
408 | ssi_private->second_stream = substream; | 393 | ssi_private->second_stream = substream; |
409 | } | 394 | } |
410 | 395 | ||
411 | if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) | ||
412 | ssi_private->playback++; | ||
413 | |||
414 | if (substream->stream == SNDRV_PCM_STREAM_CAPTURE) | ||
415 | ssi_private->capture++; | ||
416 | |||
417 | return 0; | 396 | return 0; |
418 | } | 397 | } |
419 | 398 | ||
@@ -434,24 +413,35 @@ static int fsl_ssi_hw_params(struct snd_pcm_substream *substream, | |||
434 | struct snd_pcm_hw_params *hw_params, struct snd_soc_dai *cpu_dai) | 413 | struct snd_pcm_hw_params *hw_params, struct snd_soc_dai *cpu_dai) |
435 | { | 414 | { |
436 | struct fsl_ssi_private *ssi_private = snd_soc_dai_get_drvdata(cpu_dai); | 415 | struct fsl_ssi_private *ssi_private = snd_soc_dai_get_drvdata(cpu_dai); |
416 | struct ccsr_ssi __iomem *ssi = ssi_private->ssi; | ||
417 | unsigned int sample_size = | ||
418 | snd_pcm_format_width(params_format(hw_params)); | ||
419 | u32 wl = CCSR_SSI_SxCCR_WL(sample_size); | ||
420 | int enabled = in_be32(&ssi->scr) & CCSR_SSI_SCR_SSIEN; | ||
437 | 421 | ||
438 | if (substream == ssi_private->first_stream) { | 422 | /* |
439 | struct ccsr_ssi __iomem *ssi = ssi_private->ssi; | 423 | * If we're in synchronous mode, and the SSI is already enabled, |
440 | unsigned int sample_size = | 424 | * then STCCR is already set properly. |
441 | snd_pcm_format_width(params_format(hw_params)); | 425 | */ |
442 | u32 wl = CCSR_SSI_SxCCR_WL(sample_size); | 426 | if (enabled && ssi_private->cpu_dai_drv.symmetric_rates) |
427 | return 0; | ||
443 | 428 | ||
444 | /* The SSI should always be disabled at this points (SSIEN=0) */ | 429 | /* |
430 | * FIXME: The documentation says that SxCCR[WL] should not be | ||
431 | * modified while the SSI is enabled. The only time this can | ||
432 | * happen is if we're trying to do simultaneous playback and | ||
433 | * capture in asynchronous mode. Unfortunately, I have been enable | ||
434 | * to get that to work at all on the P1022DS. Therefore, we don't | ||
435 | * bother to disable/enable the SSI when setting SxCCR[WL], because | ||
436 | * the SSI will stop anyway. Maybe one day, this will get fixed. | ||
437 | */ | ||
445 | 438 | ||
446 | /* In synchronous mode, the SSI uses STCCR for capture */ | 439 | /* In synchronous mode, the SSI uses STCCR for capture */ |
447 | if ((substream->stream == SNDRV_PCM_STREAM_PLAYBACK) || | 440 | if ((substream->stream == SNDRV_PCM_STREAM_PLAYBACK) || |
448 | !ssi_private->asynchronous) | 441 | ssi_private->cpu_dai_drv.symmetric_rates) |
449 | clrsetbits_be32(&ssi->stccr, | 442 | clrsetbits_be32(&ssi->stccr, CCSR_SSI_SxCCR_WL_MASK, wl); |
450 | CCSR_SSI_SxCCR_WL_MASK, wl); | 443 | else |
451 | else | 444 | clrsetbits_be32(&ssi->srccr, CCSR_SSI_SxCCR_WL_MASK, wl); |
452 | clrsetbits_be32(&ssi->srccr, | ||
453 | CCSR_SSI_SxCCR_WL_MASK, wl); | ||
454 | } | ||
455 | 445 | ||
456 | return 0; | 446 | return 0; |
457 | } | 447 | } |
@@ -474,7 +464,6 @@ static int fsl_ssi_trigger(struct snd_pcm_substream *substream, int cmd, | |||
474 | 464 | ||
475 | switch (cmd) { | 465 | switch (cmd) { |
476 | case SNDRV_PCM_TRIGGER_START: | 466 | case SNDRV_PCM_TRIGGER_START: |
477 | clrbits32(&ssi->scr, CCSR_SSI_SCR_SSIEN); | ||
478 | case SNDRV_PCM_TRIGGER_PAUSE_RELEASE: | 467 | case SNDRV_PCM_TRIGGER_PAUSE_RELEASE: |
479 | if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) | 468 | if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) |
480 | setbits32(&ssi->scr, | 469 | setbits32(&ssi->scr, |
@@ -510,27 +499,18 @@ static void fsl_ssi_shutdown(struct snd_pcm_substream *substream, | |||
510 | struct snd_soc_pcm_runtime *rtd = substream->private_data; | 499 | struct snd_soc_pcm_runtime *rtd = substream->private_data; |
511 | struct fsl_ssi_private *ssi_private = snd_soc_dai_get_drvdata(rtd->cpu_dai); | 500 | struct fsl_ssi_private *ssi_private = snd_soc_dai_get_drvdata(rtd->cpu_dai); |
512 | 501 | ||
513 | if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) | ||
514 | ssi_private->playback--; | ||
515 | |||
516 | if (substream->stream == SNDRV_PCM_STREAM_CAPTURE) | ||
517 | ssi_private->capture--; | ||
518 | |||
519 | if (ssi_private->first_stream == substream) | 502 | if (ssi_private->first_stream == substream) |
520 | ssi_private->first_stream = ssi_private->second_stream; | 503 | ssi_private->first_stream = ssi_private->second_stream; |
521 | 504 | ||
522 | ssi_private->second_stream = NULL; | 505 | ssi_private->second_stream = NULL; |
523 | 506 | ||
524 | /* | 507 | /* |
525 | * If this is the last active substream, disable the SSI and release | 508 | * If this is the last active substream, disable the SSI. |
526 | * the IRQ. | ||
527 | */ | 509 | */ |
528 | if (!ssi_private->playback && !ssi_private->capture) { | 510 | if (!ssi_private->first_stream) { |
529 | struct ccsr_ssi __iomem *ssi = ssi_private->ssi; | 511 | struct ccsr_ssi __iomem *ssi = ssi_private->ssi; |
530 | 512 | ||
531 | clrbits32(&ssi->scr, CCSR_SSI_SCR_SSIEN); | 513 | clrbits32(&ssi->scr, CCSR_SSI_SCR_SSIEN); |
532 | |||
533 | free_irq(ssi_private->irq, ssi_private); | ||
534 | } | 514 | } |
535 | } | 515 | } |
536 | 516 | ||
@@ -675,22 +655,33 @@ static int __devinit fsl_ssi_probe(struct platform_device *pdev) | |||
675 | ret = of_address_to_resource(np, 0, &res); | 655 | ret = of_address_to_resource(np, 0, &res); |
676 | if (ret) { | 656 | if (ret) { |
677 | dev_err(&pdev->dev, "could not determine device resources\n"); | 657 | dev_err(&pdev->dev, "could not determine device resources\n"); |
678 | kfree(ssi_private); | 658 | goto error_kmalloc; |
679 | return ret; | ||
680 | } | 659 | } |
681 | ssi_private->ssi = of_iomap(np, 0); | 660 | ssi_private->ssi = of_iomap(np, 0); |
682 | if (!ssi_private->ssi) { | 661 | if (!ssi_private->ssi) { |
683 | dev_err(&pdev->dev, "could not map device resources\n"); | 662 | dev_err(&pdev->dev, "could not map device resources\n"); |
684 | kfree(ssi_private); | 663 | ret = -ENOMEM; |
685 | return -ENOMEM; | 664 | goto error_kmalloc; |
686 | } | 665 | } |
687 | ssi_private->ssi_phys = res.start; | 666 | ssi_private->ssi_phys = res.start; |
667 | |||
688 | ssi_private->irq = irq_of_parse_and_map(np, 0); | 668 | ssi_private->irq = irq_of_parse_and_map(np, 0); |
669 | if (ssi_private->irq == NO_IRQ) { | ||
670 | dev_err(&pdev->dev, "no irq for node %s\n", np->full_name); | ||
671 | ret = -ENXIO; | ||
672 | goto error_iomap; | ||
673 | } | ||
674 | |||
675 | /* The 'name' should not have any slashes in it. */ | ||
676 | ret = request_irq(ssi_private->irq, fsl_ssi_isr, 0, ssi_private->name, | ||
677 | ssi_private); | ||
678 | if (ret < 0) { | ||
679 | dev_err(&pdev->dev, "could not claim irq %u\n", ssi_private->irq); | ||
680 | goto error_irqmap; | ||
681 | } | ||
689 | 682 | ||
690 | /* Are the RX and the TX clocks locked? */ | 683 | /* Are the RX and the TX clocks locked? */ |
691 | if (of_find_property(np, "fsl,ssi-asynchronous", NULL)) | 684 | if (!of_find_property(np, "fsl,ssi-asynchronous", NULL)) |
692 | ssi_private->asynchronous = 1; | ||
693 | else | ||
694 | ssi_private->cpu_dai_drv.symmetric_rates = 1; | 685 | ssi_private->cpu_dai_drv.symmetric_rates = 1; |
695 | 686 | ||
696 | /* Determine the FIFO depth. */ | 687 | /* Determine the FIFO depth. */ |
@@ -711,7 +702,7 @@ static int __devinit fsl_ssi_probe(struct platform_device *pdev) | |||
711 | if (ret) { | 702 | if (ret) { |
712 | dev_err(&pdev->dev, "could not create sysfs %s file\n", | 703 | dev_err(&pdev->dev, "could not create sysfs %s file\n", |
713 | ssi_private->dev_attr.attr.name); | 704 | ssi_private->dev_attr.attr.name); |
714 | goto error; | 705 | goto error_irq; |
715 | } | 706 | } |
716 | 707 | ||
717 | /* Register with ASoC */ | 708 | /* Register with ASoC */ |
@@ -720,7 +711,7 @@ static int __devinit fsl_ssi_probe(struct platform_device *pdev) | |||
720 | ret = snd_soc_register_dai(&pdev->dev, &ssi_private->cpu_dai_drv); | 711 | ret = snd_soc_register_dai(&pdev->dev, &ssi_private->cpu_dai_drv); |
721 | if (ret) { | 712 | if (ret) { |
722 | dev_err(&pdev->dev, "failed to register DAI: %d\n", ret); | 713 | dev_err(&pdev->dev, "failed to register DAI: %d\n", ret); |
723 | goto error; | 714 | goto error_dev; |
724 | } | 715 | } |
725 | 716 | ||
726 | /* Trigger the machine driver's probe function. The platform driver | 717 | /* Trigger the machine driver's probe function. The platform driver |
@@ -741,18 +732,28 @@ static int __devinit fsl_ssi_probe(struct platform_device *pdev) | |||
741 | if (IS_ERR(ssi_private->pdev)) { | 732 | if (IS_ERR(ssi_private->pdev)) { |
742 | ret = PTR_ERR(ssi_private->pdev); | 733 | ret = PTR_ERR(ssi_private->pdev); |
743 | dev_err(&pdev->dev, "failed to register platform: %d\n", ret); | 734 | dev_err(&pdev->dev, "failed to register platform: %d\n", ret); |
744 | goto error; | 735 | goto error_dai; |
745 | } | 736 | } |
746 | 737 | ||
747 | return 0; | 738 | return 0; |
748 | 739 | ||
749 | error: | 740 | error_dai: |
750 | snd_soc_unregister_dai(&pdev->dev); | 741 | snd_soc_unregister_dai(&pdev->dev); |
742 | |||
743 | error_dev: | ||
751 | dev_set_drvdata(&pdev->dev, NULL); | 744 | dev_set_drvdata(&pdev->dev, NULL); |
752 | if (dev_attr) | 745 | device_remove_file(&pdev->dev, dev_attr); |
753 | device_remove_file(&pdev->dev, dev_attr); | 746 | |
747 | error_irq: | ||
748 | free_irq(ssi_private->irq, ssi_private); | ||
749 | |||
750 | error_irqmap: | ||
754 | irq_dispose_mapping(ssi_private->irq); | 751 | irq_dispose_mapping(ssi_private->irq); |
752 | |||
753 | error_iomap: | ||
755 | iounmap(ssi_private->ssi); | 754 | iounmap(ssi_private->ssi); |
755 | |||
756 | error_kmalloc: | ||
756 | kfree(ssi_private); | 757 | kfree(ssi_private); |
757 | 758 | ||
758 | return ret; | 759 | return ret; |
@@ -766,6 +767,9 @@ static int fsl_ssi_remove(struct platform_device *pdev) | |||
766 | snd_soc_unregister_dai(&pdev->dev); | 767 | snd_soc_unregister_dai(&pdev->dev); |
767 | device_remove_file(&pdev->dev, &ssi_private->dev_attr); | 768 | device_remove_file(&pdev->dev, &ssi_private->dev_attr); |
768 | 769 | ||
770 | free_irq(ssi_private->irq, ssi_private); | ||
771 | irq_dispose_mapping(ssi_private->irq); | ||
772 | |||
769 | kfree(ssi_private); | 773 | kfree(ssi_private); |
770 | dev_set_drvdata(&pdev->dev, NULL); | 774 | dev_set_drvdata(&pdev->dev, NULL); |
771 | 775 | ||
diff --git a/sound/soc/fsl/mpc8610_hpcd.c b/sound/soc/fsl/mpc8610_hpcd.c index 358f0baaf71b..31af405bda84 100644 --- a/sound/soc/fsl/mpc8610_hpcd.c +++ b/sound/soc/fsl/mpc8610_hpcd.c | |||
@@ -505,7 +505,7 @@ static int mpc8610_hpcd_probe(struct platform_device *pdev) | |||
505 | return 0; | 505 | return 0; |
506 | 506 | ||
507 | error_sound: | 507 | error_sound: |
508 | platform_device_unregister(sound_device); | 508 | platform_device_put(sound_device); |
509 | error: | 509 | error: |
510 | kfree(machine_data); | 510 | kfree(machine_data); |
511 | error_alloc: | 511 | error_alloc: |
diff --git a/sound/soc/fsl/p1022_ds.c b/sound/soc/fsl/p1022_ds.c index fcb862eb0c73..2c064a9824ad 100644 --- a/sound/soc/fsl/p1022_ds.c +++ b/sound/soc/fsl/p1022_ds.c | |||
@@ -267,7 +267,7 @@ static int codec_node_dev_name(struct device_node *np, char *buf, size_t len) | |||
267 | if (bus < 0) | 267 | if (bus < 0) |
268 | return bus; | 268 | return bus; |
269 | 269 | ||
270 | snprintf(buf, len, "%s-codec.%u-%04x", temp, bus, addr); | 270 | snprintf(buf, len, "%s.%u-%04x", temp, bus, addr); |
271 | 271 | ||
272 | return 0; | 272 | return 0; |
273 | } | 273 | } |
@@ -506,7 +506,7 @@ static int p1022_ds_probe(struct platform_device *pdev) | |||
506 | 506 | ||
507 | error: | 507 | error: |
508 | if (sound_device) | 508 | if (sound_device) |
509 | platform_device_unregister(sound_device); | 509 | platform_device_put(sound_device); |
510 | 510 | ||
511 | kfree(mdata); | 511 | kfree(mdata); |
512 | error_put: | 512 | error_put: |
diff --git a/sound/soc/imx/imx-pcm-fiq.c b/sound/soc/imx/imx-pcm-fiq.c index 7945625e0e08..c8527ead3736 100644 --- a/sound/soc/imx/imx-pcm-fiq.c +++ b/sound/soc/imx/imx-pcm-fiq.c | |||
@@ -242,23 +242,22 @@ static int imx_pcm_fiq_new(struct snd_soc_pcm_runtime *rtd) | |||
242 | { | 242 | { |
243 | struct snd_soc_dai *dai = rtd->cpu_dai; | 243 | struct snd_soc_dai *dai = rtd->cpu_dai; |
244 | struct snd_pcm *pcm = rtd->pcm; | 244 | struct snd_pcm *pcm = rtd->pcm; |
245 | struct snd_pcm_substream *substream; | ||
245 | int ret; | 246 | int ret; |
246 | 247 | ||
247 | ret = imx_pcm_new(rtd); | 248 | ret = imx_pcm_new(rtd); |
248 | if (ret) | 249 | if (ret) |
249 | return ret; | 250 | return ret; |
250 | 251 | ||
251 | if (dai->driver->playback.channels_min) { | 252 | substream = pcm->streams[SNDRV_PCM_STREAM_PLAYBACK].substream; |
252 | struct snd_pcm_substream *substream = | 253 | if (substream) { |
253 | pcm->streams[SNDRV_PCM_STREAM_PLAYBACK].substream; | ||
254 | struct snd_dma_buffer *buf = &substream->dma_buffer; | 254 | struct snd_dma_buffer *buf = &substream->dma_buffer; |
255 | 255 | ||
256 | imx_ssi_fiq_tx_buffer = (unsigned long)buf->area; | 256 | imx_ssi_fiq_tx_buffer = (unsigned long)buf->area; |
257 | } | 257 | } |
258 | 258 | ||
259 | if (dai->driver->capture.channels_min) { | 259 | substream = pcm->streams[SNDRV_PCM_STREAM_CAPTURE].substream; |
260 | struct snd_pcm_substream *substream = | 260 | if (substream) { |
261 | pcm->streams[SNDRV_PCM_STREAM_CAPTURE].substream; | ||
262 | struct snd_dma_buffer *buf = &substream->dma_buffer; | 261 | struct snd_dma_buffer *buf = &substream->dma_buffer; |
263 | 262 | ||
264 | imx_ssi_fiq_rx_buffer = (unsigned long)buf->area; | 263 | imx_ssi_fiq_rx_buffer = (unsigned long)buf->area; |
diff --git a/sound/soc/imx/imx-ssi.c b/sound/soc/imx/imx-ssi.c index 10a8e2783751..4297cb6af42e 100644 --- a/sound/soc/imx/imx-ssi.c +++ b/sound/soc/imx/imx-ssi.c | |||
@@ -357,8 +357,8 @@ int snd_imx_pcm_mmap(struct snd_pcm_substream *substream, | |||
357 | struct snd_pcm_runtime *runtime = substream->runtime; | 357 | struct snd_pcm_runtime *runtime = substream->runtime; |
358 | int ret; | 358 | int ret; |
359 | 359 | ||
360 | ret = dma_mmap_coherent(NULL, vma, runtime->dma_area, | 360 | ret = dma_mmap_writecombine(substream->pcm->card->dev, vma, |
361 | runtime->dma_addr, runtime->dma_bytes); | 361 | runtime->dma_area, runtime->dma_addr, runtime->dma_bytes); |
362 | 362 | ||
363 | pr_debug("%s: ret: %d %p 0x%08x 0x%08x\n", __func__, ret, | 363 | pr_debug("%s: ret: %d %p 0x%08x 0x%08x\n", __func__, ret, |
364 | runtime->dma_area, | 364 | runtime->dma_area, |
@@ -399,14 +399,14 @@ int imx_pcm_new(struct snd_soc_pcm_runtime *rtd) | |||
399 | card->dev->dma_mask = &imx_pcm_dmamask; | 399 | card->dev->dma_mask = &imx_pcm_dmamask; |
400 | if (!card->dev->coherent_dma_mask) | 400 | if (!card->dev->coherent_dma_mask) |
401 | card->dev->coherent_dma_mask = DMA_BIT_MASK(32); | 401 | card->dev->coherent_dma_mask = DMA_BIT_MASK(32); |
402 | if (dai->driver->playback.channels_min) { | 402 | if (pcm->streams[SNDRV_PCM_STREAM_PLAYBACK].substream) { |
403 | ret = imx_pcm_preallocate_dma_buffer(pcm, | 403 | ret = imx_pcm_preallocate_dma_buffer(pcm, |
404 | SNDRV_PCM_STREAM_PLAYBACK); | 404 | SNDRV_PCM_STREAM_PLAYBACK); |
405 | if (ret) | 405 | if (ret) |
406 | goto out; | 406 | goto out; |
407 | } | 407 | } |
408 | 408 | ||
409 | if (dai->driver->capture.channels_min) { | 409 | if (pcm->streams[SNDRV_PCM_STREAM_CAPTURE].substream) { |
410 | ret = imx_pcm_preallocate_dma_buffer(pcm, | 410 | ret = imx_pcm_preallocate_dma_buffer(pcm, |
411 | SNDRV_PCM_STREAM_CAPTURE); | 411 | SNDRV_PCM_STREAM_CAPTURE); |
412 | if (ret) | 412 | if (ret) |
diff --git a/sound/soc/mid-x86/sst_platform.c b/sound/soc/mid-x86/sst_platform.c index 3e7826058efe..9925d20ab0a3 100644 --- a/sound/soc/mid-x86/sst_platform.c +++ b/sound/soc/mid-x86/sst_platform.c | |||
@@ -226,13 +226,18 @@ static int sst_platform_init_stream(struct snd_pcm_substream *substream) | |||
226 | 226 | ||
227 | static int sst_platform_open(struct snd_pcm_substream *substream) | 227 | static int sst_platform_open(struct snd_pcm_substream *substream) |
228 | { | 228 | { |
229 | struct snd_pcm_runtime *runtime; | 229 | struct snd_pcm_runtime *runtime = substream->runtime; |
230 | struct sst_runtime_stream *stream; | 230 | struct sst_runtime_stream *stream; |
231 | int ret_val = 0; | 231 | int ret_val = 0; |
232 | 232 | ||
233 | pr_debug("sst_platform_open called\n"); | 233 | pr_debug("sst_platform_open called\n"); |
234 | runtime = substream->runtime; | 234 | |
235 | runtime->hw = sst_platform_pcm_hw; | 235 | snd_soc_set_runtime_hwparams(substream, &sst_platform_pcm_hw); |
236 | ret_val = snd_pcm_hw_constraint_integer(runtime, | ||
237 | SNDRV_PCM_HW_PARAM_PERIODS); | ||
238 | if (ret_val < 0) | ||
239 | return ret_val; | ||
240 | |||
236 | stream = kzalloc(sizeof(*stream), GFP_KERNEL); | 241 | stream = kzalloc(sizeof(*stream), GFP_KERNEL); |
237 | if (!stream) | 242 | if (!stream) |
238 | return -ENOMEM; | 243 | return -ENOMEM; |
@@ -259,8 +264,8 @@ static int sst_platform_open(struct snd_pcm_substream *substream) | |||
259 | return ret_val; | 264 | return ret_val; |
260 | } | 265 | } |
261 | runtime->private_data = stream; | 266 | runtime->private_data = stream; |
262 | return snd_pcm_hw_constraint_integer(runtime, | 267 | |
263 | SNDRV_PCM_HW_PARAM_PERIODS); | 268 | return 0; |
264 | } | 269 | } |
265 | 270 | ||
266 | static int sst_platform_close(struct snd_pcm_substream *substream) | 271 | static int sst_platform_close(struct snd_pcm_substream *substream) |
@@ -469,7 +474,7 @@ static struct platform_driver sst_platform_driver = { | |||
469 | static int __init sst_soc_platform_init(void) | 474 | static int __init sst_soc_platform_init(void) |
470 | { | 475 | { |
471 | pr_debug("sst_soc_platform_init called\n"); | 476 | pr_debug("sst_soc_platform_init called\n"); |
472 | return platform_driver_register(&sst_platform_driver); | 477 | return platform_driver_register(&sst_platform_driver); |
473 | } | 478 | } |
474 | module_init(sst_soc_platform_init); | 479 | module_init(sst_soc_platform_init); |
475 | 480 | ||
diff --git a/sound/soc/mxs/Kconfig b/sound/soc/mxs/Kconfig new file mode 100644 index 000000000000..e4ba8d5f25fa --- /dev/null +++ b/sound/soc/mxs/Kconfig | |||
@@ -0,0 +1,20 @@ | |||
1 | menuconfig SND_MXS_SOC | ||
2 | tristate "SoC Audio for Freescale MXS CPUs" | ||
3 | depends on ARCH_MXS | ||
4 | select SND_PCM | ||
5 | help | ||
6 | Say Y or M if you want to add support for codecs attached to | ||
7 | the MXS SAIF interface. | ||
8 | |||
9 | |||
10 | if SND_MXS_SOC | ||
11 | |||
12 | config SND_SOC_MXS_SGTL5000 | ||
13 | tristate "SoC Audio support for i.MX boards with sgtl5000" | ||
14 | depends on I2C | ||
15 | select SND_SOC_SGTL5000 | ||
16 | help | ||
17 | Say Y if you want to add support for SoC audio on an MXS board with | ||
18 | a sgtl5000 codec. | ||
19 | |||
20 | endif # SND_MXS_SOC | ||
diff --git a/sound/soc/mxs/Makefile b/sound/soc/mxs/Makefile new file mode 100644 index 000000000000..565b5b51e8b7 --- /dev/null +++ b/sound/soc/mxs/Makefile | |||
@@ -0,0 +1,10 @@ | |||
1 | # MXS Platform Support | ||
2 | snd-soc-mxs-objs := mxs-saif.o | ||
3 | snd-soc-mxs-pcm-objs := mxs-pcm.o | ||
4 | |||
5 | obj-$(CONFIG_SND_MXS_SOC) += snd-soc-mxs.o snd-soc-mxs-pcm.o | ||
6 | |||
7 | # i.MX Machine Support | ||
8 | snd-soc-mxs-sgtl5000-objs := mxs-sgtl5000.o | ||
9 | |||
10 | obj-$(CONFIG_SND_SOC_MXS_SGTL5000) += snd-soc-mxs-sgtl5000.o | ||
diff --git a/sound/soc/mxs/mxs-pcm.c b/sound/soc/mxs/mxs-pcm.c new file mode 100644 index 000000000000..dea5aa4aa647 --- /dev/null +++ b/sound/soc/mxs/mxs-pcm.c | |||
@@ -0,0 +1,359 @@ | |||
1 | /* | ||
2 | * Copyright (C) 2011 Freescale Semiconductor, Inc. All Rights Reserved. | ||
3 | * | ||
4 | * Based on sound/soc/imx/imx-pcm-dma-mx2.c | ||
5 | * | ||
6 | * This program is free software; you can redistribute it and/or modify | ||
7 | * it under the terms of the GNU General Public License as published by | ||
8 | * the Free Software Foundation; either version 2 of the License, or | ||
9 | * (at your option) any later version. | ||
10 | * | ||
11 | * This program is distributed in the hope that it will be useful, | ||
12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
14 | * GNU General Public License for more details. | ||
15 | * | ||
16 | * You should have received a copy of the GNU General Public License along | ||
17 | * with this program; if not, write to the Free Software Foundation, Inc., | ||
18 | * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. | ||
19 | */ | ||
20 | |||
21 | #include <linux/clk.h> | ||
22 | #include <linux/delay.h> | ||
23 | #include <linux/device.h> | ||
24 | #include <linux/dma-mapping.h> | ||
25 | #include <linux/init.h> | ||
26 | #include <linux/interrupt.h> | ||
27 | #include <linux/module.h> | ||
28 | #include <linux/platform_device.h> | ||
29 | #include <linux/slab.h> | ||
30 | #include <linux/dmaengine.h> | ||
31 | |||
32 | #include <sound/core.h> | ||
33 | #include <sound/initval.h> | ||
34 | #include <sound/pcm.h> | ||
35 | #include <sound/pcm_params.h> | ||
36 | #include <sound/soc.h> | ||
37 | |||
38 | #include <mach/dma.h> | ||
39 | #include "mxs-pcm.h" | ||
40 | |||
41 | static struct snd_pcm_hardware snd_mxs_hardware = { | ||
42 | .info = SNDRV_PCM_INFO_MMAP | | ||
43 | SNDRV_PCM_INFO_MMAP_VALID | | ||
44 | SNDRV_PCM_INFO_PAUSE | | ||
45 | SNDRV_PCM_INFO_RESUME | | ||
46 | SNDRV_PCM_INFO_INTERLEAVED, | ||
47 | .formats = SNDRV_PCM_FMTBIT_S16_LE | | ||
48 | SNDRV_PCM_FMTBIT_S20_3LE | | ||
49 | SNDRV_PCM_FMTBIT_S24_LE, | ||
50 | .channels_min = 2, | ||
51 | .channels_max = 2, | ||
52 | .period_bytes_min = 32, | ||
53 | .period_bytes_max = 8192, | ||
54 | .periods_min = 1, | ||
55 | .periods_max = 52, | ||
56 | .buffer_bytes_max = 64 * 1024, | ||
57 | .fifo_size = 32, | ||
58 | |||
59 | }; | ||
60 | |||
61 | static void audio_dma_irq(void *data) | ||
62 | { | ||
63 | struct snd_pcm_substream *substream = (struct snd_pcm_substream *)data; | ||
64 | struct snd_pcm_runtime *runtime = substream->runtime; | ||
65 | struct mxs_pcm_runtime_data *iprtd = runtime->private_data; | ||
66 | |||
67 | iprtd->offset += iprtd->period_bytes; | ||
68 | iprtd->offset %= iprtd->period_bytes * iprtd->periods; | ||
69 | snd_pcm_period_elapsed(substream); | ||
70 | } | ||
71 | |||
72 | static bool filter(struct dma_chan *chan, void *param) | ||
73 | { | ||
74 | struct mxs_pcm_runtime_data *iprtd = param; | ||
75 | struct mxs_pcm_dma_params *dma_params = iprtd->dma_params; | ||
76 | |||
77 | if (!mxs_dma_is_apbx(chan)) | ||
78 | return false; | ||
79 | |||
80 | if (chan->chan_id != dma_params->chan_num) | ||
81 | return false; | ||
82 | |||
83 | chan->private = &iprtd->dma_data; | ||
84 | |||
85 | return true; | ||
86 | } | ||
87 | |||
88 | static int mxs_dma_alloc(struct snd_pcm_substream *substream, | ||
89 | struct snd_pcm_hw_params *params) | ||
90 | { | ||
91 | struct snd_soc_pcm_runtime *rtd = substream->private_data; | ||
92 | struct snd_pcm_runtime *runtime = substream->runtime; | ||
93 | struct mxs_pcm_runtime_data *iprtd = runtime->private_data; | ||
94 | dma_cap_mask_t mask; | ||
95 | |||
96 | iprtd->dma_params = snd_soc_dai_get_dma_data(rtd->cpu_dai, substream); | ||
97 | |||
98 | dma_cap_zero(mask); | ||
99 | dma_cap_set(DMA_SLAVE, mask); | ||
100 | iprtd->dma_data.chan_irq = iprtd->dma_params->chan_irq; | ||
101 | iprtd->dma_chan = dma_request_channel(mask, filter, iprtd); | ||
102 | if (!iprtd->dma_chan) | ||
103 | return -EINVAL; | ||
104 | |||
105 | return 0; | ||
106 | } | ||
107 | |||
108 | static int snd_mxs_pcm_hw_params(struct snd_pcm_substream *substream, | ||
109 | struct snd_pcm_hw_params *params) | ||
110 | { | ||
111 | struct snd_pcm_runtime *runtime = substream->runtime; | ||
112 | struct mxs_pcm_runtime_data *iprtd = runtime->private_data; | ||
113 | unsigned long dma_addr; | ||
114 | struct dma_chan *chan; | ||
115 | int ret; | ||
116 | |||
117 | ret = mxs_dma_alloc(substream, params); | ||
118 | if (ret) | ||
119 | return ret; | ||
120 | chan = iprtd->dma_chan; | ||
121 | |||
122 | iprtd->size = params_buffer_bytes(params); | ||
123 | iprtd->periods = params_periods(params); | ||
124 | iprtd->period_bytes = params_period_bytes(params); | ||
125 | iprtd->offset = 0; | ||
126 | iprtd->period_time = HZ / (params_rate(params) / | ||
127 | params_period_size(params)); | ||
128 | |||
129 | snd_pcm_set_runtime_buffer(substream, &substream->dma_buffer); | ||
130 | |||
131 | dma_addr = runtime->dma_addr; | ||
132 | |||
133 | iprtd->buf = substream->dma_buffer.area; | ||
134 | |||
135 | iprtd->desc = chan->device->device_prep_dma_cyclic(chan, dma_addr, | ||
136 | iprtd->period_bytes * iprtd->periods, | ||
137 | iprtd->period_bytes, | ||
138 | substream->stream == SNDRV_PCM_STREAM_PLAYBACK ? | ||
139 | DMA_TO_DEVICE : DMA_FROM_DEVICE); | ||
140 | if (!iprtd->desc) { | ||
141 | dev_err(&chan->dev->device, "cannot prepare slave dma\n"); | ||
142 | return -EINVAL; | ||
143 | } | ||
144 | |||
145 | iprtd->desc->callback = audio_dma_irq; | ||
146 | iprtd->desc->callback_param = substream; | ||
147 | |||
148 | return 0; | ||
149 | } | ||
150 | |||
151 | static int snd_mxs_pcm_hw_free(struct snd_pcm_substream *substream) | ||
152 | { | ||
153 | struct snd_pcm_runtime *runtime = substream->runtime; | ||
154 | struct mxs_pcm_runtime_data *iprtd = runtime->private_data; | ||
155 | |||
156 | if (iprtd->dma_chan) { | ||
157 | dma_release_channel(iprtd->dma_chan); | ||
158 | iprtd->dma_chan = NULL; | ||
159 | } | ||
160 | |||
161 | return 0; | ||
162 | } | ||
163 | |||
164 | static int snd_mxs_pcm_trigger(struct snd_pcm_substream *substream, int cmd) | ||
165 | { | ||
166 | struct snd_pcm_runtime *runtime = substream->runtime; | ||
167 | struct mxs_pcm_runtime_data *iprtd = runtime->private_data; | ||
168 | |||
169 | switch (cmd) { | ||
170 | case SNDRV_PCM_TRIGGER_START: | ||
171 | case SNDRV_PCM_TRIGGER_RESUME: | ||
172 | case SNDRV_PCM_TRIGGER_PAUSE_RELEASE: | ||
173 | dmaengine_submit(iprtd->desc); | ||
174 | |||
175 | break; | ||
176 | case SNDRV_PCM_TRIGGER_STOP: | ||
177 | case SNDRV_PCM_TRIGGER_SUSPEND: | ||
178 | case SNDRV_PCM_TRIGGER_PAUSE_PUSH: | ||
179 | dmaengine_terminate_all(iprtd->dma_chan); | ||
180 | |||
181 | break; | ||
182 | default: | ||
183 | return -EINVAL; | ||
184 | } | ||
185 | |||
186 | return 0; | ||
187 | } | ||
188 | |||
189 | static snd_pcm_uframes_t snd_mxs_pcm_pointer( | ||
190 | struct snd_pcm_substream *substream) | ||
191 | { | ||
192 | struct snd_pcm_runtime *runtime = substream->runtime; | ||
193 | struct mxs_pcm_runtime_data *iprtd = runtime->private_data; | ||
194 | |||
195 | return bytes_to_frames(substream->runtime, iprtd->offset); | ||
196 | } | ||
197 | |||
198 | static int snd_mxs_open(struct snd_pcm_substream *substream) | ||
199 | { | ||
200 | struct snd_pcm_runtime *runtime = substream->runtime; | ||
201 | struct mxs_pcm_runtime_data *iprtd; | ||
202 | int ret; | ||
203 | |||
204 | iprtd = kzalloc(sizeof(*iprtd), GFP_KERNEL); | ||
205 | if (iprtd == NULL) | ||
206 | return -ENOMEM; | ||
207 | runtime->private_data = iprtd; | ||
208 | |||
209 | ret = snd_pcm_hw_constraint_integer(substream->runtime, | ||
210 | SNDRV_PCM_HW_PARAM_PERIODS); | ||
211 | if (ret < 0) { | ||
212 | kfree(iprtd); | ||
213 | return ret; | ||
214 | } | ||
215 | |||
216 | snd_soc_set_runtime_hwparams(substream, &snd_mxs_hardware); | ||
217 | |||
218 | return 0; | ||
219 | } | ||
220 | |||
221 | static int snd_mxs_close(struct snd_pcm_substream *substream) | ||
222 | { | ||
223 | struct snd_pcm_runtime *runtime = substream->runtime; | ||
224 | struct mxs_pcm_runtime_data *iprtd = runtime->private_data; | ||
225 | |||
226 | kfree(iprtd); | ||
227 | |||
228 | return 0; | ||
229 | } | ||
230 | |||
231 | static int snd_mxs_pcm_mmap(struct snd_pcm_substream *substream, | ||
232 | struct vm_area_struct *vma) | ||
233 | { | ||
234 | struct snd_pcm_runtime *runtime = substream->runtime; | ||
235 | |||
236 | return dma_mmap_writecombine(substream->pcm->card->dev, vma, | ||
237 | runtime->dma_area, | ||
238 | runtime->dma_addr, | ||
239 | runtime->dma_bytes); | ||
240 | } | ||
241 | |||
242 | static struct snd_pcm_ops mxs_pcm_ops = { | ||
243 | .open = snd_mxs_open, | ||
244 | .close = snd_mxs_close, | ||
245 | .ioctl = snd_pcm_lib_ioctl, | ||
246 | .hw_params = snd_mxs_pcm_hw_params, | ||
247 | .hw_free = snd_mxs_pcm_hw_free, | ||
248 | .trigger = snd_mxs_pcm_trigger, | ||
249 | .pointer = snd_mxs_pcm_pointer, | ||
250 | .mmap = snd_mxs_pcm_mmap, | ||
251 | }; | ||
252 | |||
253 | static int mxs_pcm_preallocate_dma_buffer(struct snd_pcm *pcm, int stream) | ||
254 | { | ||
255 | struct snd_pcm_substream *substream = pcm->streams[stream].substream; | ||
256 | struct snd_dma_buffer *buf = &substream->dma_buffer; | ||
257 | size_t size = snd_mxs_hardware.buffer_bytes_max; | ||
258 | |||
259 | buf->dev.type = SNDRV_DMA_TYPE_DEV; | ||
260 | buf->dev.dev = pcm->card->dev; | ||
261 | buf->private_data = NULL; | ||
262 | buf->area = dma_alloc_writecombine(pcm->card->dev, size, | ||
263 | &buf->addr, GFP_KERNEL); | ||
264 | if (!buf->area) | ||
265 | return -ENOMEM; | ||
266 | buf->bytes = size; | ||
267 | |||
268 | return 0; | ||
269 | } | ||
270 | |||
271 | static u64 mxs_pcm_dmamask = DMA_BIT_MASK(32); | ||
272 | static int mxs_pcm_new(struct snd_soc_pcm_runtime *rtd) | ||
273 | { | ||
274 | struct snd_card *card = rtd->card->snd_card; | ||
275 | struct snd_pcm *pcm = rtd->pcm; | ||
276 | int ret = 0; | ||
277 | |||
278 | if (!card->dev->dma_mask) | ||
279 | card->dev->dma_mask = &mxs_pcm_dmamask; | ||
280 | if (!card->dev->coherent_dma_mask) | ||
281 | card->dev->coherent_dma_mask = DMA_BIT_MASK(32); | ||
282 | |||
283 | if (pcm->streams[SNDRV_PCM_STREAM_PLAYBACK].substream) { | ||
284 | ret = mxs_pcm_preallocate_dma_buffer(pcm, | ||
285 | SNDRV_PCM_STREAM_PLAYBACK); | ||
286 | if (ret) | ||
287 | goto out; | ||
288 | } | ||
289 | |||
290 | if (pcm->streams[SNDRV_PCM_STREAM_CAPTURE].substream) { | ||
291 | ret = mxs_pcm_preallocate_dma_buffer(pcm, | ||
292 | SNDRV_PCM_STREAM_CAPTURE); | ||
293 | if (ret) | ||
294 | goto out; | ||
295 | } | ||
296 | |||
297 | out: | ||
298 | return ret; | ||
299 | } | ||
300 | |||
301 | static void mxs_pcm_free(struct snd_pcm *pcm) | ||
302 | { | ||
303 | struct snd_pcm_substream *substream; | ||
304 | struct snd_dma_buffer *buf; | ||
305 | int stream; | ||
306 | |||
307 | for (stream = 0; stream < 2; stream++) { | ||
308 | substream = pcm->streams[stream].substream; | ||
309 | if (!substream) | ||
310 | continue; | ||
311 | |||
312 | buf = &substream->dma_buffer; | ||
313 | if (!buf->area) | ||
314 | continue; | ||
315 | |||
316 | dma_free_writecombine(pcm->card->dev, buf->bytes, | ||
317 | buf->area, buf->addr); | ||
318 | buf->area = NULL; | ||
319 | } | ||
320 | } | ||
321 | |||
322 | static struct snd_soc_platform_driver mxs_soc_platform = { | ||
323 | .ops = &mxs_pcm_ops, | ||
324 | .pcm_new = mxs_pcm_new, | ||
325 | .pcm_free = mxs_pcm_free, | ||
326 | }; | ||
327 | |||
328 | static int __devinit mxs_soc_platform_probe(struct platform_device *pdev) | ||
329 | { | ||
330 | return snd_soc_register_platform(&pdev->dev, &mxs_soc_platform); | ||
331 | } | ||
332 | |||
333 | static int __devexit mxs_soc_platform_remove(struct platform_device *pdev) | ||
334 | { | ||
335 | snd_soc_unregister_platform(&pdev->dev); | ||
336 | |||
337 | return 0; | ||
338 | } | ||
339 | |||
340 | static struct platform_driver mxs_pcm_driver = { | ||
341 | .driver = { | ||
342 | .name = "mxs-pcm-audio", | ||
343 | .owner = THIS_MODULE, | ||
344 | }, | ||
345 | .probe = mxs_soc_platform_probe, | ||
346 | .remove = __devexit_p(mxs_soc_platform_remove), | ||
347 | }; | ||
348 | |||
349 | static int __init snd_mxs_pcm_init(void) | ||
350 | { | ||
351 | return platform_driver_register(&mxs_pcm_driver); | ||
352 | } | ||
353 | module_init(snd_mxs_pcm_init); | ||
354 | |||
355 | static void __exit snd_mxs_pcm_exit(void) | ||
356 | { | ||
357 | platform_driver_unregister(&mxs_pcm_driver); | ||
358 | } | ||
359 | module_exit(snd_mxs_pcm_exit); | ||
diff --git a/sound/soc/mxs/mxs-pcm.h b/sound/soc/mxs/mxs-pcm.h new file mode 100644 index 000000000000..f55ac4f7a76a --- /dev/null +++ b/sound/soc/mxs/mxs-pcm.h | |||
@@ -0,0 +1,43 @@ | |||
1 | /* | ||
2 | * Copyright (C) 2011 Freescale Semiconductor, Inc. All Rights Reserved. | ||
3 | * | ||
4 | * This program is free software; you can redistribute it and/or modify | ||
5 | * it under the terms of the GNU General Public License as published by | ||
6 | * the Free Software Foundation; either version 2 of the License, or | ||
7 | * (at your option) any later version. | ||
8 | * | ||
9 | * This program is distributed in the hope that it will be useful, | ||
10 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
12 | * GNU General Public License for more details. | ||
13 | * | ||
14 | * You should have received a copy of the GNU General Public License along | ||
15 | * with this program; if not, write to the Free Software Foundation, Inc., | ||
16 | * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. | ||
17 | */ | ||
18 | |||
19 | #ifndef _MXS_PCM_H | ||
20 | #define _MXS_PCM_H | ||
21 | |||
22 | #include <mach/dma.h> | ||
23 | |||
24 | struct mxs_pcm_dma_params { | ||
25 | int chan_irq; | ||
26 | int chan_num; | ||
27 | }; | ||
28 | |||
29 | struct mxs_pcm_runtime_data { | ||
30 | int period_bytes; | ||
31 | int periods; | ||
32 | int dma; | ||
33 | unsigned long offset; | ||
34 | unsigned long size; | ||
35 | void *buf; | ||
36 | int period_time; | ||
37 | struct dma_async_tx_descriptor *desc; | ||
38 | struct dma_chan *dma_chan; | ||
39 | struct mxs_dma_data dma_data; | ||
40 | struct mxs_pcm_dma_params *dma_params; | ||
41 | }; | ||
42 | |||
43 | #endif | ||
diff --git a/sound/soc/mxs/mxs-saif.c b/sound/soc/mxs/mxs-saif.c new file mode 100644 index 000000000000..401944cf4560 --- /dev/null +++ b/sound/soc/mxs/mxs-saif.c | |||
@@ -0,0 +1,797 @@ | |||
1 | /* | ||
2 | * Copyright 2011 Freescale Semiconductor, Inc. | ||
3 | * | ||
4 | * This program is free software; you can redistribute it and/or modify | ||
5 | * it under the terms of the GNU General Public License as published by | ||
6 | * the Free Software Foundation; either version 2 of the License, or | ||
7 | * (at your option) any later version. | ||
8 | * | ||
9 | * This program is distributed in the hope that it will be useful, | ||
10 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
12 | * GNU General Public License for more details. | ||
13 | * | ||
14 | * You should have received a copy of the GNU General Public License along | ||
15 | * with this program; if not, write to the Free Software Foundation, Inc., | ||
16 | * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. | ||
17 | */ | ||
18 | |||
19 | #include <linux/module.h> | ||
20 | #include <linux/init.h> | ||
21 | #include <linux/platform_device.h> | ||
22 | #include <linux/slab.h> | ||
23 | #include <linux/dma-mapping.h> | ||
24 | #include <linux/clk.h> | ||
25 | #include <linux/delay.h> | ||
26 | #include <linux/time.h> | ||
27 | #include <sound/core.h> | ||
28 | #include <sound/pcm.h> | ||
29 | #include <sound/pcm_params.h> | ||
30 | #include <sound/soc.h> | ||
31 | #include <sound/saif.h> | ||
32 | #include <mach/dma.h> | ||
33 | #include <asm/mach-types.h> | ||
34 | #include <mach/hardware.h> | ||
35 | #include <mach/mxs.h> | ||
36 | |||
37 | #include "mxs-saif.h" | ||
38 | |||
39 | static struct mxs_saif *mxs_saif[2]; | ||
40 | |||
41 | /* | ||
42 | * SAIF is a little different with other normal SOC DAIs on clock using. | ||
43 | * | ||
44 | * For MXS, two SAIF modules are instantiated on-chip. | ||
45 | * Each SAIF has a set of clock pins and can be operating in master | ||
46 | * mode simultaneously if they are connected to different off-chip codecs. | ||
47 | * Also, one of the two SAIFs can master or drive the clock pins while the | ||
48 | * other SAIF, in slave mode, receives clocking from the master SAIF. | ||
49 | * This also means that both SAIFs must operate at the same sample rate. | ||
50 | * | ||
51 | * We abstract this as each saif has a master, the master could be | ||
52 | * himself or other saifs. In the generic saif driver, saif does not need | ||
53 | * to know the different clkmux. Saif only needs to know who is his master | ||
54 | * and operating his master to generate the proper clock rate for him. | ||
55 | * The master id is provided in mach-specific layer according to different | ||
56 | * clkmux setting. | ||
57 | */ | ||
58 | |||
59 | static int mxs_saif_set_dai_sysclk(struct snd_soc_dai *cpu_dai, | ||
60 | int clk_id, unsigned int freq, int dir) | ||
61 | { | ||
62 | struct mxs_saif *saif = snd_soc_dai_get_drvdata(cpu_dai); | ||
63 | |||
64 | switch (clk_id) { | ||
65 | case MXS_SAIF_MCLK: | ||
66 | saif->mclk = freq; | ||
67 | break; | ||
68 | default: | ||
69 | return -EINVAL; | ||
70 | } | ||
71 | return 0; | ||
72 | } | ||
73 | |||
74 | /* | ||
75 | * Since SAIF may work on EXTMASTER mode, IOW, it's working BITCLK&LRCLK | ||
76 | * is provided by other SAIF, we provide a interface here to get its master | ||
77 | * from its master_id. | ||
78 | * Note that the master could be himself. | ||
79 | */ | ||
80 | static inline struct mxs_saif *mxs_saif_get_master(struct mxs_saif * saif) | ||
81 | { | ||
82 | return mxs_saif[saif->master_id]; | ||
83 | } | ||
84 | |||
85 | /* | ||
86 | * Set SAIF clock and MCLK | ||
87 | */ | ||
88 | static int mxs_saif_set_clk(struct mxs_saif *saif, | ||
89 | unsigned int mclk, | ||
90 | unsigned int rate) | ||
91 | { | ||
92 | u32 scr; | ||
93 | int ret; | ||
94 | struct mxs_saif *master_saif; | ||
95 | |||
96 | dev_dbg(saif->dev, "mclk %d rate %d\n", mclk, rate); | ||
97 | |||
98 | /* Set master saif to generate proper clock */ | ||
99 | master_saif = mxs_saif_get_master(saif); | ||
100 | if (!master_saif) | ||
101 | return -EINVAL; | ||
102 | |||
103 | dev_dbg(saif->dev, "master saif%d\n", master_saif->id); | ||
104 | |||
105 | /* Checking if can playback and capture simutaneously */ | ||
106 | if (master_saif->ongoing && rate != master_saif->cur_rate) { | ||
107 | dev_err(saif->dev, | ||
108 | "can not change clock, master saif%d(rate %d) is ongoing\n", | ||
109 | master_saif->id, master_saif->cur_rate); | ||
110 | return -EINVAL; | ||
111 | } | ||
112 | |||
113 | scr = __raw_readl(master_saif->base + SAIF_CTRL); | ||
114 | scr &= ~BM_SAIF_CTRL_BITCLK_MULT_RATE; | ||
115 | scr &= ~BM_SAIF_CTRL_BITCLK_BASE_RATE; | ||
116 | |||
117 | /* | ||
118 | * Set SAIF clock | ||
119 | * | ||
120 | * The SAIF clock should be either 384*fs or 512*fs. | ||
121 | * If MCLK is used, the SAIF clk ratio need to match mclk ratio. | ||
122 | * For 32x mclk, set saif clk as 512*fs. | ||
123 | * For 48x mclk, set saif clk as 384*fs. | ||
124 | * | ||
125 | * If MCLK is not used, we just set saif clk to 512*fs. | ||
126 | */ | ||
127 | if (master_saif->mclk_in_use) { | ||
128 | if (mclk % 32 == 0) { | ||
129 | scr &= ~BM_SAIF_CTRL_BITCLK_BASE_RATE; | ||
130 | ret = clk_set_rate(master_saif->clk, 512 * rate); | ||
131 | } else if (mclk % 48 == 0) { | ||
132 | scr |= BM_SAIF_CTRL_BITCLK_BASE_RATE; | ||
133 | ret = clk_set_rate(master_saif->clk, 384 * rate); | ||
134 | } else { | ||
135 | /* SAIF MCLK should be either 32x or 48x */ | ||
136 | return -EINVAL; | ||
137 | } | ||
138 | } else { | ||
139 | ret = clk_set_rate(master_saif->clk, 512 * rate); | ||
140 | scr &= ~BM_SAIF_CTRL_BITCLK_BASE_RATE; | ||
141 | } | ||
142 | |||
143 | if (ret) | ||
144 | return ret; | ||
145 | |||
146 | master_saif->cur_rate = rate; | ||
147 | |||
148 | if (!master_saif->mclk_in_use) { | ||
149 | __raw_writel(scr, master_saif->base + SAIF_CTRL); | ||
150 | return 0; | ||
151 | } | ||
152 | |||
153 | /* | ||
154 | * Program the over-sample rate for MCLK output | ||
155 | * | ||
156 | * The available MCLK range is 32x, 48x... 512x. The rate | ||
157 | * could be from 8kHz to 192kH. | ||
158 | */ | ||
159 | switch (mclk / rate) { | ||
160 | case 32: | ||
161 | scr |= BF_SAIF_CTRL_BITCLK_MULT_RATE(4); | ||
162 | break; | ||
163 | case 64: | ||
164 | scr |= BF_SAIF_CTRL_BITCLK_MULT_RATE(3); | ||
165 | break; | ||
166 | case 128: | ||
167 | scr |= BF_SAIF_CTRL_BITCLK_MULT_RATE(2); | ||
168 | break; | ||
169 | case 256: | ||
170 | scr |= BF_SAIF_CTRL_BITCLK_MULT_RATE(1); | ||
171 | break; | ||
172 | case 512: | ||
173 | scr |= BF_SAIF_CTRL_BITCLK_MULT_RATE(0); | ||
174 | break; | ||
175 | case 48: | ||
176 | scr |= BF_SAIF_CTRL_BITCLK_MULT_RATE(3); | ||
177 | break; | ||
178 | case 96: | ||
179 | scr |= BF_SAIF_CTRL_BITCLK_MULT_RATE(2); | ||
180 | break; | ||
181 | case 192: | ||
182 | scr |= BF_SAIF_CTRL_BITCLK_MULT_RATE(1); | ||
183 | break; | ||
184 | case 384: | ||
185 | scr |= BF_SAIF_CTRL_BITCLK_MULT_RATE(0); | ||
186 | break; | ||
187 | default: | ||
188 | return -EINVAL; | ||
189 | } | ||
190 | |||
191 | __raw_writel(scr, master_saif->base + SAIF_CTRL); | ||
192 | |||
193 | return 0; | ||
194 | } | ||
195 | |||
196 | /* | ||
197 | * Put and disable MCLK. | ||
198 | */ | ||
199 | int mxs_saif_put_mclk(unsigned int saif_id) | ||
200 | { | ||
201 | struct mxs_saif *saif = mxs_saif[saif_id]; | ||
202 | u32 stat; | ||
203 | |||
204 | if (!saif) | ||
205 | return -EINVAL; | ||
206 | |||
207 | stat = __raw_readl(saif->base + SAIF_STAT); | ||
208 | if (stat & BM_SAIF_STAT_BUSY) { | ||
209 | dev_err(saif->dev, "error: busy\n"); | ||
210 | return -EBUSY; | ||
211 | } | ||
212 | |||
213 | clk_disable(saif->clk); | ||
214 | |||
215 | /* disable MCLK output */ | ||
216 | __raw_writel(BM_SAIF_CTRL_CLKGATE, | ||
217 | saif->base + SAIF_CTRL + MXS_SET_ADDR); | ||
218 | __raw_writel(BM_SAIF_CTRL_RUN, | ||
219 | saif->base + SAIF_CTRL + MXS_CLR_ADDR); | ||
220 | |||
221 | saif->mclk_in_use = 0; | ||
222 | return 0; | ||
223 | } | ||
224 | |||
225 | /* | ||
226 | * Get MCLK and set clock rate, then enable it | ||
227 | * | ||
228 | * This interface is used for codecs who are using MCLK provided | ||
229 | * by saif. | ||
230 | */ | ||
231 | int mxs_saif_get_mclk(unsigned int saif_id, unsigned int mclk, | ||
232 | unsigned int rate) | ||
233 | { | ||
234 | struct mxs_saif *saif = mxs_saif[saif_id]; | ||
235 | u32 stat; | ||
236 | int ret; | ||
237 | struct mxs_saif *master_saif; | ||
238 | |||
239 | if (!saif) | ||
240 | return -EINVAL; | ||
241 | |||
242 | /* Clear Reset */ | ||
243 | __raw_writel(BM_SAIF_CTRL_SFTRST, | ||
244 | saif->base + SAIF_CTRL + MXS_CLR_ADDR); | ||
245 | |||
246 | /* FIXME: need clear clk gate for register r/w */ | ||
247 | __raw_writel(BM_SAIF_CTRL_CLKGATE, | ||
248 | saif->base + SAIF_CTRL + MXS_CLR_ADDR); | ||
249 | |||
250 | master_saif = mxs_saif_get_master(saif); | ||
251 | if (saif != master_saif) { | ||
252 | dev_err(saif->dev, "can not get mclk from a non-master saif\n"); | ||
253 | return -EINVAL; | ||
254 | } | ||
255 | |||
256 | stat = __raw_readl(saif->base + SAIF_STAT); | ||
257 | if (stat & BM_SAIF_STAT_BUSY) { | ||
258 | dev_err(saif->dev, "error: busy\n"); | ||
259 | return -EBUSY; | ||
260 | } | ||
261 | |||
262 | saif->mclk_in_use = 1; | ||
263 | ret = mxs_saif_set_clk(saif, mclk, rate); | ||
264 | if (ret) | ||
265 | return ret; | ||
266 | |||
267 | ret = clk_enable(saif->clk); | ||
268 | if (ret) | ||
269 | return ret; | ||
270 | |||
271 | /* enable MCLK output */ | ||
272 | __raw_writel(BM_SAIF_CTRL_RUN, | ||
273 | saif->base + SAIF_CTRL + MXS_SET_ADDR); | ||
274 | |||
275 | return 0; | ||
276 | } | ||
277 | |||
278 | /* | ||
279 | * SAIF DAI format configuration. | ||
280 | * Should only be called when port is inactive. | ||
281 | */ | ||
282 | static int mxs_saif_set_dai_fmt(struct snd_soc_dai *cpu_dai, unsigned int fmt) | ||
283 | { | ||
284 | u32 scr, stat; | ||
285 | u32 scr0; | ||
286 | struct mxs_saif *saif = snd_soc_dai_get_drvdata(cpu_dai); | ||
287 | |||
288 | stat = __raw_readl(saif->base + SAIF_STAT); | ||
289 | if (stat & BM_SAIF_STAT_BUSY) { | ||
290 | dev_err(cpu_dai->dev, "error: busy\n"); | ||
291 | return -EBUSY; | ||
292 | } | ||
293 | |||
294 | scr0 = __raw_readl(saif->base + SAIF_CTRL); | ||
295 | scr0 = scr0 & ~BM_SAIF_CTRL_BITCLK_EDGE & ~BM_SAIF_CTRL_LRCLK_POLARITY \ | ||
296 | & ~BM_SAIF_CTRL_JUSTIFY & ~BM_SAIF_CTRL_DELAY; | ||
297 | scr = 0; | ||
298 | |||
299 | /* DAI mode */ | ||
300 | switch (fmt & SND_SOC_DAIFMT_FORMAT_MASK) { | ||
301 | case SND_SOC_DAIFMT_I2S: | ||
302 | /* data frame low 1clk before data */ | ||
303 | scr |= BM_SAIF_CTRL_DELAY; | ||
304 | scr &= ~BM_SAIF_CTRL_LRCLK_POLARITY; | ||
305 | break; | ||
306 | case SND_SOC_DAIFMT_LEFT_J: | ||
307 | /* data frame high with data */ | ||
308 | scr &= ~BM_SAIF_CTRL_DELAY; | ||
309 | scr &= ~BM_SAIF_CTRL_LRCLK_POLARITY; | ||
310 | scr &= ~BM_SAIF_CTRL_JUSTIFY; | ||
311 | break; | ||
312 | default: | ||
313 | return -EINVAL; | ||
314 | } | ||
315 | |||
316 | /* DAI clock inversion */ | ||
317 | switch (fmt & SND_SOC_DAIFMT_INV_MASK) { | ||
318 | case SND_SOC_DAIFMT_IB_IF: | ||
319 | scr |= BM_SAIF_CTRL_BITCLK_EDGE; | ||
320 | scr |= BM_SAIF_CTRL_LRCLK_POLARITY; | ||
321 | break; | ||
322 | case SND_SOC_DAIFMT_IB_NF: | ||
323 | scr |= BM_SAIF_CTRL_BITCLK_EDGE; | ||
324 | scr &= ~BM_SAIF_CTRL_LRCLK_POLARITY; | ||
325 | break; | ||
326 | case SND_SOC_DAIFMT_NB_IF: | ||
327 | scr &= ~BM_SAIF_CTRL_BITCLK_EDGE; | ||
328 | scr |= BM_SAIF_CTRL_LRCLK_POLARITY; | ||
329 | break; | ||
330 | case SND_SOC_DAIFMT_NB_NF: | ||
331 | scr &= ~BM_SAIF_CTRL_BITCLK_EDGE; | ||
332 | scr &= ~BM_SAIF_CTRL_LRCLK_POLARITY; | ||
333 | break; | ||
334 | } | ||
335 | |||
336 | /* | ||
337 | * Note: We simply just support master mode since SAIF TX can only | ||
338 | * work as master. | ||
339 | * Here the master is relative to codec side. | ||
340 | * Saif internally could be slave when working on EXTMASTER mode. | ||
341 | * We just hide this to machine driver. | ||
342 | */ | ||
343 | switch (fmt & SND_SOC_DAIFMT_MASTER_MASK) { | ||
344 | case SND_SOC_DAIFMT_CBS_CFS: | ||
345 | if (saif->id == saif->master_id) | ||
346 | scr &= ~BM_SAIF_CTRL_SLAVE_MODE; | ||
347 | else | ||
348 | scr |= BM_SAIF_CTRL_SLAVE_MODE; | ||
349 | |||
350 | __raw_writel(scr | scr0, saif->base + SAIF_CTRL); | ||
351 | break; | ||
352 | default: | ||
353 | return -EINVAL; | ||
354 | } | ||
355 | |||
356 | return 0; | ||
357 | } | ||
358 | |||
359 | static int mxs_saif_startup(struct snd_pcm_substream *substream, | ||
360 | struct snd_soc_dai *cpu_dai) | ||
361 | { | ||
362 | struct mxs_saif *saif = snd_soc_dai_get_drvdata(cpu_dai); | ||
363 | snd_soc_dai_set_dma_data(cpu_dai, substream, &saif->dma_param); | ||
364 | |||
365 | /* clear error status to 0 for each re-open */ | ||
366 | saif->fifo_underrun = 0; | ||
367 | saif->fifo_overrun = 0; | ||
368 | |||
369 | /* Clear Reset for normal operations */ | ||
370 | __raw_writel(BM_SAIF_CTRL_SFTRST, | ||
371 | saif->base + SAIF_CTRL + MXS_CLR_ADDR); | ||
372 | |||
373 | /* clear clock gate */ | ||
374 | __raw_writel(BM_SAIF_CTRL_CLKGATE, | ||
375 | saif->base + SAIF_CTRL + MXS_CLR_ADDR); | ||
376 | |||
377 | return 0; | ||
378 | } | ||
379 | |||
380 | /* | ||
381 | * Should only be called when port is inactive. | ||
382 | * although can be called multiple times by upper layers. | ||
383 | */ | ||
384 | static int mxs_saif_hw_params(struct snd_pcm_substream *substream, | ||
385 | struct snd_pcm_hw_params *params, | ||
386 | struct snd_soc_dai *cpu_dai) | ||
387 | { | ||
388 | struct mxs_saif *saif = snd_soc_dai_get_drvdata(cpu_dai); | ||
389 | u32 scr, stat; | ||
390 | int ret; | ||
391 | |||
392 | /* mclk should already be set */ | ||
393 | if (!saif->mclk && saif->mclk_in_use) { | ||
394 | dev_err(cpu_dai->dev, "set mclk first\n"); | ||
395 | return -EINVAL; | ||
396 | } | ||
397 | |||
398 | stat = __raw_readl(saif->base + SAIF_STAT); | ||
399 | if (stat & BM_SAIF_STAT_BUSY) { | ||
400 | dev_err(cpu_dai->dev, "error: busy\n"); | ||
401 | return -EBUSY; | ||
402 | } | ||
403 | |||
404 | /* | ||
405 | * Set saif clk based on sample rate. | ||
406 | * If mclk is used, we also set mclk, if not, saif->mclk is | ||
407 | * default 0, means not used. | ||
408 | */ | ||
409 | ret = mxs_saif_set_clk(saif, saif->mclk, params_rate(params)); | ||
410 | if (ret) { | ||
411 | dev_err(cpu_dai->dev, "unable to get proper clk\n"); | ||
412 | return ret; | ||
413 | } | ||
414 | |||
415 | scr = __raw_readl(saif->base + SAIF_CTRL); | ||
416 | |||
417 | scr &= ~BM_SAIF_CTRL_WORD_LENGTH; | ||
418 | scr &= ~BM_SAIF_CTRL_BITCLK_48XFS_ENABLE; | ||
419 | switch (params_format(params)) { | ||
420 | case SNDRV_PCM_FORMAT_S16_LE: | ||
421 | scr |= BF_SAIF_CTRL_WORD_LENGTH(0); | ||
422 | break; | ||
423 | case SNDRV_PCM_FORMAT_S20_3LE: | ||
424 | scr |= BF_SAIF_CTRL_WORD_LENGTH(4); | ||
425 | scr |= BM_SAIF_CTRL_BITCLK_48XFS_ENABLE; | ||
426 | break; | ||
427 | case SNDRV_PCM_FORMAT_S24_LE: | ||
428 | scr |= BF_SAIF_CTRL_WORD_LENGTH(8); | ||
429 | scr |= BM_SAIF_CTRL_BITCLK_48XFS_ENABLE; | ||
430 | break; | ||
431 | default: | ||
432 | return -EINVAL; | ||
433 | } | ||
434 | |||
435 | /* Tx/Rx config */ | ||
436 | if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) { | ||
437 | /* enable TX mode */ | ||
438 | scr &= ~BM_SAIF_CTRL_READ_MODE; | ||
439 | } else { | ||
440 | /* enable RX mode */ | ||
441 | scr |= BM_SAIF_CTRL_READ_MODE; | ||
442 | } | ||
443 | |||
444 | __raw_writel(scr, saif->base + SAIF_CTRL); | ||
445 | return 0; | ||
446 | } | ||
447 | |||
448 | static int mxs_saif_prepare(struct snd_pcm_substream *substream, | ||
449 | struct snd_soc_dai *cpu_dai) | ||
450 | { | ||
451 | struct mxs_saif *saif = snd_soc_dai_get_drvdata(cpu_dai); | ||
452 | |||
453 | /* enable FIFO error irqs */ | ||
454 | __raw_writel(BM_SAIF_CTRL_FIFO_ERROR_IRQ_EN, | ||
455 | saif->base + SAIF_CTRL + MXS_SET_ADDR); | ||
456 | |||
457 | return 0; | ||
458 | } | ||
459 | |||
460 | static int mxs_saif_trigger(struct snd_pcm_substream *substream, int cmd, | ||
461 | struct snd_soc_dai *cpu_dai) | ||
462 | { | ||
463 | struct mxs_saif *saif = snd_soc_dai_get_drvdata(cpu_dai); | ||
464 | struct mxs_saif *master_saif; | ||
465 | u32 delay; | ||
466 | |||
467 | master_saif = mxs_saif_get_master(saif); | ||
468 | if (!master_saif) | ||
469 | return -EINVAL; | ||
470 | |||
471 | switch (cmd) { | ||
472 | case SNDRV_PCM_TRIGGER_START: | ||
473 | case SNDRV_PCM_TRIGGER_RESUME: | ||
474 | case SNDRV_PCM_TRIGGER_PAUSE_RELEASE: | ||
475 | dev_dbg(cpu_dai->dev, "start\n"); | ||
476 | |||
477 | clk_enable(master_saif->clk); | ||
478 | if (!master_saif->mclk_in_use) | ||
479 | __raw_writel(BM_SAIF_CTRL_RUN, | ||
480 | master_saif->base + SAIF_CTRL + MXS_SET_ADDR); | ||
481 | |||
482 | /* | ||
483 | * If the saif's master is not himself, we also need to enable | ||
484 | * itself clk for its internal basic logic to work. | ||
485 | */ | ||
486 | if (saif != master_saif) { | ||
487 | clk_enable(saif->clk); | ||
488 | __raw_writel(BM_SAIF_CTRL_RUN, | ||
489 | saif->base + SAIF_CTRL + MXS_SET_ADDR); | ||
490 | } | ||
491 | |||
492 | if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) { | ||
493 | /* | ||
494 | * write a data to saif data register to trigger | ||
495 | * the transfer | ||
496 | */ | ||
497 | __raw_writel(0, saif->base + SAIF_DATA); | ||
498 | } else { | ||
499 | /* | ||
500 | * read a data from saif data register to trigger | ||
501 | * the receive | ||
502 | */ | ||
503 | __raw_readl(saif->base + SAIF_DATA); | ||
504 | } | ||
505 | |||
506 | master_saif->ongoing = 1; | ||
507 | |||
508 | dev_dbg(saif->dev, "CTRL 0x%x STAT 0x%x\n", | ||
509 | __raw_readl(saif->base + SAIF_CTRL), | ||
510 | __raw_readl(saif->base + SAIF_STAT)); | ||
511 | |||
512 | dev_dbg(master_saif->dev, "CTRL 0x%x STAT 0x%x\n", | ||
513 | __raw_readl(master_saif->base + SAIF_CTRL), | ||
514 | __raw_readl(master_saif->base + SAIF_STAT)); | ||
515 | break; | ||
516 | case SNDRV_PCM_TRIGGER_SUSPEND: | ||
517 | case SNDRV_PCM_TRIGGER_STOP: | ||
518 | case SNDRV_PCM_TRIGGER_PAUSE_PUSH: | ||
519 | dev_dbg(cpu_dai->dev, "stop\n"); | ||
520 | |||
521 | /* wait a while for the current sample to complete */ | ||
522 | delay = USEC_PER_SEC / master_saif->cur_rate; | ||
523 | |||
524 | if (!master_saif->mclk_in_use) { | ||
525 | __raw_writel(BM_SAIF_CTRL_RUN, | ||
526 | master_saif->base + SAIF_CTRL + MXS_CLR_ADDR); | ||
527 | udelay(delay); | ||
528 | } | ||
529 | clk_disable(master_saif->clk); | ||
530 | |||
531 | if (saif != master_saif) { | ||
532 | __raw_writel(BM_SAIF_CTRL_RUN, | ||
533 | saif->base + SAIF_CTRL + MXS_CLR_ADDR); | ||
534 | udelay(delay); | ||
535 | clk_disable(saif->clk); | ||
536 | } | ||
537 | |||
538 | master_saif->ongoing = 0; | ||
539 | |||
540 | break; | ||
541 | default: | ||
542 | return -EINVAL; | ||
543 | } | ||
544 | |||
545 | return 0; | ||
546 | } | ||
547 | |||
548 | #define MXS_SAIF_RATES SNDRV_PCM_RATE_8000_192000 | ||
549 | #define MXS_SAIF_FORMATS \ | ||
550 | (SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S20_3LE | \ | ||
551 | SNDRV_PCM_FMTBIT_S24_LE) | ||
552 | |||
553 | static struct snd_soc_dai_ops mxs_saif_dai_ops = { | ||
554 | .startup = mxs_saif_startup, | ||
555 | .trigger = mxs_saif_trigger, | ||
556 | .prepare = mxs_saif_prepare, | ||
557 | .hw_params = mxs_saif_hw_params, | ||
558 | .set_sysclk = mxs_saif_set_dai_sysclk, | ||
559 | .set_fmt = mxs_saif_set_dai_fmt, | ||
560 | }; | ||
561 | |||
562 | static int mxs_saif_dai_probe(struct snd_soc_dai *dai) | ||
563 | { | ||
564 | struct mxs_saif *saif = dev_get_drvdata(dai->dev); | ||
565 | |||
566 | snd_soc_dai_set_drvdata(dai, saif); | ||
567 | |||
568 | return 0; | ||
569 | } | ||
570 | |||
571 | static struct snd_soc_dai_driver mxs_saif_dai = { | ||
572 | .name = "mxs-saif", | ||
573 | .probe = mxs_saif_dai_probe, | ||
574 | .playback = { | ||
575 | .channels_min = 2, | ||
576 | .channels_max = 2, | ||
577 | .rates = MXS_SAIF_RATES, | ||
578 | .formats = MXS_SAIF_FORMATS, | ||
579 | }, | ||
580 | .capture = { | ||
581 | .channels_min = 2, | ||
582 | .channels_max = 2, | ||
583 | .rates = MXS_SAIF_RATES, | ||
584 | .formats = MXS_SAIF_FORMATS, | ||
585 | }, | ||
586 | .ops = &mxs_saif_dai_ops, | ||
587 | }; | ||
588 | |||
589 | static irqreturn_t mxs_saif_irq(int irq, void *dev_id) | ||
590 | { | ||
591 | struct mxs_saif *saif = dev_id; | ||
592 | unsigned int stat; | ||
593 | |||
594 | stat = __raw_readl(saif->base + SAIF_STAT); | ||
595 | if (!(stat & (BM_SAIF_STAT_FIFO_UNDERFLOW_IRQ | | ||
596 | BM_SAIF_STAT_FIFO_OVERFLOW_IRQ))) | ||
597 | return IRQ_NONE; | ||
598 | |||
599 | if (stat & BM_SAIF_STAT_FIFO_UNDERFLOW_IRQ) { | ||
600 | dev_dbg(saif->dev, "underrun!!! %d\n", ++saif->fifo_underrun); | ||
601 | __raw_writel(BM_SAIF_STAT_FIFO_UNDERFLOW_IRQ, | ||
602 | saif->base + SAIF_STAT + MXS_CLR_ADDR); | ||
603 | } | ||
604 | |||
605 | if (stat & BM_SAIF_STAT_FIFO_OVERFLOW_IRQ) { | ||
606 | dev_dbg(saif->dev, "overrun!!! %d\n", ++saif->fifo_overrun); | ||
607 | __raw_writel(BM_SAIF_STAT_FIFO_OVERFLOW_IRQ, | ||
608 | saif->base + SAIF_STAT + MXS_CLR_ADDR); | ||
609 | } | ||
610 | |||
611 | dev_dbg(saif->dev, "SAIF_CTRL %x SAIF_STAT %x\n", | ||
612 | __raw_readl(saif->base + SAIF_CTRL), | ||
613 | __raw_readl(saif->base + SAIF_STAT)); | ||
614 | |||
615 | return IRQ_HANDLED; | ||
616 | } | ||
617 | |||
618 | static int mxs_saif_probe(struct platform_device *pdev) | ||
619 | { | ||
620 | struct resource *res; | ||
621 | struct mxs_saif *saif; | ||
622 | struct mxs_saif_platform_data *pdata; | ||
623 | int ret = 0; | ||
624 | |||
625 | if (pdev->id >= ARRAY_SIZE(mxs_saif)) | ||
626 | return -EINVAL; | ||
627 | |||
628 | pdata = pdev->dev.platform_data; | ||
629 | if (pdata && pdata->init) { | ||
630 | ret = pdata->init(); | ||
631 | if (ret) | ||
632 | return ret; | ||
633 | } | ||
634 | |||
635 | saif = kzalloc(sizeof(*saif), GFP_KERNEL); | ||
636 | if (!saif) | ||
637 | return -ENOMEM; | ||
638 | |||
639 | mxs_saif[pdev->id] = saif; | ||
640 | saif->id = pdev->id; | ||
641 | |||
642 | saif->master_id = saif->id; | ||
643 | if (pdata && pdata->get_master_id) { | ||
644 | saif->master_id = pdata->get_master_id(saif->id); | ||
645 | if (saif->master_id < 0 || | ||
646 | saif->master_id >= ARRAY_SIZE(mxs_saif)) | ||
647 | return -EINVAL; | ||
648 | } | ||
649 | |||
650 | saif->clk = clk_get(&pdev->dev, NULL); | ||
651 | if (IS_ERR(saif->clk)) { | ||
652 | ret = PTR_ERR(saif->clk); | ||
653 | dev_err(&pdev->dev, "Cannot get the clock: %d\n", | ||
654 | ret); | ||
655 | goto failed_clk; | ||
656 | } | ||
657 | |||
658 | res = platform_get_resource(pdev, IORESOURCE_MEM, 0); | ||
659 | if (!res) { | ||
660 | ret = -ENODEV; | ||
661 | dev_err(&pdev->dev, "failed to get io resource: %d\n", | ||
662 | ret); | ||
663 | goto failed_get_resource; | ||
664 | } | ||
665 | |||
666 | if (!request_mem_region(res->start, resource_size(res), "mxs-saif")) { | ||
667 | dev_err(&pdev->dev, "request_mem_region failed\n"); | ||
668 | ret = -EBUSY; | ||
669 | goto failed_get_resource; | ||
670 | } | ||
671 | |||
672 | saif->base = ioremap(res->start, resource_size(res)); | ||
673 | if (!saif->base) { | ||
674 | dev_err(&pdev->dev, "ioremap failed\n"); | ||
675 | ret = -ENODEV; | ||
676 | goto failed_ioremap; | ||
677 | } | ||
678 | |||
679 | res = platform_get_resource(pdev, IORESOURCE_DMA, 0); | ||
680 | if (!res) { | ||
681 | ret = -ENODEV; | ||
682 | dev_err(&pdev->dev, "failed to get dma resource: %d\n", | ||
683 | ret); | ||
684 | goto failed_ioremap; | ||
685 | } | ||
686 | saif->dma_param.chan_num = res->start; | ||
687 | |||
688 | saif->irq = platform_get_irq(pdev, 0); | ||
689 | if (saif->irq < 0) { | ||
690 | ret = saif->irq; | ||
691 | dev_err(&pdev->dev, "failed to get irq resource: %d\n", | ||
692 | ret); | ||
693 | goto failed_get_irq1; | ||
694 | } | ||
695 | |||
696 | saif->dev = &pdev->dev; | ||
697 | ret = request_irq(saif->irq, mxs_saif_irq, 0, "mxs-saif", saif); | ||
698 | if (ret) { | ||
699 | dev_err(&pdev->dev, "failed to request irq\n"); | ||
700 | goto failed_get_irq1; | ||
701 | } | ||
702 | |||
703 | saif->dma_param.chan_irq = platform_get_irq(pdev, 1); | ||
704 | if (saif->dma_param.chan_irq < 0) { | ||
705 | ret = saif->dma_param.chan_irq; | ||
706 | dev_err(&pdev->dev, "failed to get dma irq resource: %d\n", | ||
707 | ret); | ||
708 | goto failed_get_irq2; | ||
709 | } | ||
710 | |||
711 | platform_set_drvdata(pdev, saif); | ||
712 | |||
713 | ret = snd_soc_register_dai(&pdev->dev, &mxs_saif_dai); | ||
714 | if (ret) { | ||
715 | dev_err(&pdev->dev, "register DAI failed\n"); | ||
716 | goto failed_register; | ||
717 | } | ||
718 | |||
719 | saif->soc_platform_pdev = platform_device_alloc( | ||
720 | "mxs-pcm-audio", pdev->id); | ||
721 | if (!saif->soc_platform_pdev) { | ||
722 | ret = -ENOMEM; | ||
723 | goto failed_pdev_alloc; | ||
724 | } | ||
725 | |||
726 | platform_set_drvdata(saif->soc_platform_pdev, saif); | ||
727 | ret = platform_device_add(saif->soc_platform_pdev); | ||
728 | if (ret) { | ||
729 | dev_err(&pdev->dev, "failed to add soc platform device\n"); | ||
730 | goto failed_pdev_add; | ||
731 | } | ||
732 | |||
733 | return 0; | ||
734 | |||
735 | failed_pdev_add: | ||
736 | platform_device_put(saif->soc_platform_pdev); | ||
737 | failed_pdev_alloc: | ||
738 | snd_soc_unregister_dai(&pdev->dev); | ||
739 | failed_register: | ||
740 | failed_get_irq2: | ||
741 | free_irq(saif->irq, saif); | ||
742 | failed_get_irq1: | ||
743 | iounmap(saif->base); | ||
744 | failed_ioremap: | ||
745 | release_mem_region(res->start, resource_size(res)); | ||
746 | failed_get_resource: | ||
747 | clk_put(saif->clk); | ||
748 | failed_clk: | ||
749 | kfree(saif); | ||
750 | |||
751 | return ret; | ||
752 | } | ||
753 | |||
754 | static int __devexit mxs_saif_remove(struct platform_device *pdev) | ||
755 | { | ||
756 | struct resource *res = platform_get_resource(pdev, IORESOURCE_MEM, 0); | ||
757 | struct mxs_saif *saif = platform_get_drvdata(pdev); | ||
758 | |||
759 | platform_device_unregister(saif->soc_platform_pdev); | ||
760 | |||
761 | snd_soc_unregister_dai(&pdev->dev); | ||
762 | |||
763 | iounmap(saif->base); | ||
764 | release_mem_region(res->start, resource_size(res)); | ||
765 | free_irq(saif->irq, saif); | ||
766 | |||
767 | clk_put(saif->clk); | ||
768 | kfree(saif); | ||
769 | |||
770 | return 0; | ||
771 | } | ||
772 | |||
773 | static struct platform_driver mxs_saif_driver = { | ||
774 | .probe = mxs_saif_probe, | ||
775 | .remove = __devexit_p(mxs_saif_remove), | ||
776 | |||
777 | .driver = { | ||
778 | .name = "mxs-saif", | ||
779 | .owner = THIS_MODULE, | ||
780 | }, | ||
781 | }; | ||
782 | |||
783 | static int __init mxs_saif_init(void) | ||
784 | { | ||
785 | return platform_driver_register(&mxs_saif_driver); | ||
786 | } | ||
787 | |||
788 | static void __exit mxs_saif_exit(void) | ||
789 | { | ||
790 | platform_driver_unregister(&mxs_saif_driver); | ||
791 | } | ||
792 | |||
793 | module_init(mxs_saif_init); | ||
794 | module_exit(mxs_saif_exit); | ||
795 | MODULE_AUTHOR("Freescale Semiconductor, Inc."); | ||
796 | MODULE_DESCRIPTION("MXS ASoC SAIF driver"); | ||
797 | MODULE_LICENSE("GPL"); | ||
diff --git a/sound/soc/mxs/mxs-saif.h b/sound/soc/mxs/mxs-saif.h new file mode 100644 index 000000000000..12c91e4eb941 --- /dev/null +++ b/sound/soc/mxs/mxs-saif.h | |||
@@ -0,0 +1,134 @@ | |||
1 | /* | ||
2 | * Copyright (C) 2011 Freescale Semiconductor, Inc. All Rights Reserved. | ||
3 | * | ||
4 | * This program is free software; you can redistribute it and/or modify | ||
5 | * it under the terms of the GNU General Public License as published by | ||
6 | * the Free Software Foundation; either version 2 of the License, or | ||
7 | * (at your option) any later version. | ||
8 | * | ||
9 | * This program is distributed in the hope that it will be useful, | ||
10 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
12 | * GNU General Public License for more details. | ||
13 | * | ||
14 | * You should have received a copy of the GNU General Public License along | ||
15 | * with this program; if not, write to the Free Software Foundation, Inc., | ||
16 | * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. | ||
17 | */ | ||
18 | |||
19 | |||
20 | #ifndef _MXS_SAIF_H | ||
21 | #define _MXS_SAIF_H | ||
22 | |||
23 | #define SAIF_CTRL 0x0 | ||
24 | #define SAIF_STAT 0x10 | ||
25 | #define SAIF_DATA 0x20 | ||
26 | #define SAIF_VERSION 0X30 | ||
27 | |||
28 | /* SAIF_CTRL */ | ||
29 | #define BM_SAIF_CTRL_SFTRST 0x80000000 | ||
30 | #define BM_SAIF_CTRL_CLKGATE 0x40000000 | ||
31 | #define BP_SAIF_CTRL_BITCLK_MULT_RATE 27 | ||
32 | #define BM_SAIF_CTRL_BITCLK_MULT_RATE 0x38000000 | ||
33 | #define BF_SAIF_CTRL_BITCLK_MULT_RATE(v) \ | ||
34 | (((v) << 27) & BM_SAIF_CTRL_BITCLK_MULT_RATE) | ||
35 | #define BM_SAIF_CTRL_BITCLK_BASE_RATE 0x04000000 | ||
36 | #define BM_SAIF_CTRL_FIFO_ERROR_IRQ_EN 0x02000000 | ||
37 | #define BM_SAIF_CTRL_FIFO_SERVICE_IRQ_EN 0x01000000 | ||
38 | #define BP_SAIF_CTRL_RSRVD2 21 | ||
39 | #define BM_SAIF_CTRL_RSRVD2 0x00E00000 | ||
40 | |||
41 | #define BP_SAIF_CTRL_DMAWAIT_COUNT 16 | ||
42 | #define BM_SAIF_CTRL_DMAWAIT_COUNT 0x001F0000 | ||
43 | #define BF_SAIF_CTRL_DMAWAIT_COUNT(v) \ | ||
44 | (((v) << 16) & BM_SAIF_CTRL_DMAWAIT_COUNT) | ||
45 | #define BP_SAIF_CTRL_CHANNEL_NUM_SELECT 14 | ||
46 | #define BM_SAIF_CTRL_CHANNEL_NUM_SELECT 0x0000C000 | ||
47 | #define BF_SAIF_CTRL_CHANNEL_NUM_SELECT(v) \ | ||
48 | (((v) << 14) & BM_SAIF_CTRL_CHANNEL_NUM_SELECT) | ||
49 | #define BM_SAIF_CTRL_LRCLK_PULSE 0x00002000 | ||
50 | #define BM_SAIF_CTRL_BIT_ORDER 0x00001000 | ||
51 | #define BM_SAIF_CTRL_DELAY 0x00000800 | ||
52 | #define BM_SAIF_CTRL_JUSTIFY 0x00000400 | ||
53 | #define BM_SAIF_CTRL_LRCLK_POLARITY 0x00000200 | ||
54 | #define BM_SAIF_CTRL_BITCLK_EDGE 0x00000100 | ||
55 | #define BP_SAIF_CTRL_WORD_LENGTH 4 | ||
56 | #define BM_SAIF_CTRL_WORD_LENGTH 0x000000F0 | ||
57 | #define BF_SAIF_CTRL_WORD_LENGTH(v) \ | ||
58 | (((v) << 4) & BM_SAIF_CTRL_WORD_LENGTH) | ||
59 | #define BM_SAIF_CTRL_BITCLK_48XFS_ENABLE 0x00000008 | ||
60 | #define BM_SAIF_CTRL_SLAVE_MODE 0x00000004 | ||
61 | #define BM_SAIF_CTRL_READ_MODE 0x00000002 | ||
62 | #define BM_SAIF_CTRL_RUN 0x00000001 | ||
63 | |||
64 | /* SAIF_STAT */ | ||
65 | #define BM_SAIF_STAT_PRESENT 0x80000000 | ||
66 | #define BP_SAIF_STAT_RSRVD2 17 | ||
67 | #define BM_SAIF_STAT_RSRVD2 0x7FFE0000 | ||
68 | #define BF_SAIF_STAT_RSRVD2(v) \ | ||
69 | (((v) << 17) & BM_SAIF_STAT_RSRVD2) | ||
70 | #define BM_SAIF_STAT_DMA_PREQ 0x00010000 | ||
71 | #define BP_SAIF_STAT_RSRVD1 7 | ||
72 | #define BM_SAIF_STAT_RSRVD1 0x0000FF80 | ||
73 | #define BF_SAIF_STAT_RSRVD1(v) \ | ||
74 | (((v) << 7) & BM_SAIF_STAT_RSRVD1) | ||
75 | |||
76 | #define BM_SAIF_STAT_FIFO_UNDERFLOW_IRQ 0x00000040 | ||
77 | #define BM_SAIF_STAT_FIFO_OVERFLOW_IRQ 0x00000020 | ||
78 | #define BM_SAIF_STAT_FIFO_SERVICE_IRQ 0x00000010 | ||
79 | #define BP_SAIF_STAT_RSRVD0 1 | ||
80 | #define BM_SAIF_STAT_RSRVD0 0x0000000E | ||
81 | #define BF_SAIF_STAT_RSRVD0(v) \ | ||
82 | (((v) << 1) & BM_SAIF_STAT_RSRVD0) | ||
83 | #define BM_SAIF_STAT_BUSY 0x00000001 | ||
84 | |||
85 | /* SAFI_DATA */ | ||
86 | #define BP_SAIF_DATA_PCM_RIGHT 16 | ||
87 | #define BM_SAIF_DATA_PCM_RIGHT 0xFFFF0000 | ||
88 | #define BF_SAIF_DATA_PCM_RIGHT(v) \ | ||
89 | (((v) << 16) & BM_SAIF_DATA_PCM_RIGHT) | ||
90 | #define BP_SAIF_DATA_PCM_LEFT 0 | ||
91 | #define BM_SAIF_DATA_PCM_LEFT 0x0000FFFF | ||
92 | #define BF_SAIF_DATA_PCM_LEFT(v) \ | ||
93 | (((v) << 0) & BM_SAIF_DATA_PCM_LEFT) | ||
94 | |||
95 | /* SAIF_VERSION */ | ||
96 | #define BP_SAIF_VERSION_MAJOR 24 | ||
97 | #define BM_SAIF_VERSION_MAJOR 0xFF000000 | ||
98 | #define BF_SAIF_VERSION_MAJOR(v) \ | ||
99 | (((v) << 24) & BM_SAIF_VERSION_MAJOR) | ||
100 | #define BP_SAIF_VERSION_MINOR 16 | ||
101 | #define BM_SAIF_VERSION_MINOR 0x00FF0000 | ||
102 | #define BF_SAIF_VERSION_MINOR(v) \ | ||
103 | (((v) << 16) & BM_SAIF_VERSION_MINOR) | ||
104 | #define BP_SAIF_VERSION_STEP 0 | ||
105 | #define BM_SAIF_VERSION_STEP 0x0000FFFF | ||
106 | #define BF_SAIF_VERSION_STEP(v) \ | ||
107 | (((v) << 0) & BM_SAIF_VERSION_STEP) | ||
108 | |||
109 | #define MXS_SAIF_MCLK 0 | ||
110 | |||
111 | #include "mxs-pcm.h" | ||
112 | |||
113 | struct mxs_saif { | ||
114 | struct device *dev; | ||
115 | struct clk *clk; | ||
116 | unsigned int mclk; | ||
117 | unsigned int mclk_in_use; | ||
118 | void __iomem *base; | ||
119 | int irq; | ||
120 | struct mxs_pcm_dma_params dma_param; | ||
121 | unsigned int id; | ||
122 | unsigned int master_id; | ||
123 | unsigned int cur_rate; | ||
124 | unsigned int ongoing; | ||
125 | |||
126 | struct platform_device *soc_platform_pdev; | ||
127 | u32 fifo_underrun; | ||
128 | u32 fifo_overrun; | ||
129 | }; | ||
130 | |||
131 | extern int mxs_saif_put_mclk(unsigned int saif_id); | ||
132 | extern int mxs_saif_get_mclk(unsigned int saif_id, unsigned int mclk, | ||
133 | unsigned int rate); | ||
134 | #endif | ||
diff --git a/sound/soc/mxs/mxs-sgtl5000.c b/sound/soc/mxs/mxs-sgtl5000.c new file mode 100644 index 000000000000..7fbeaec06eb4 --- /dev/null +++ b/sound/soc/mxs/mxs-sgtl5000.c | |||
@@ -0,0 +1,173 @@ | |||
1 | /* | ||
2 | * Copyright 2011 Freescale Semiconductor, Inc. | ||
3 | * | ||
4 | * This program is free software; you can redistribute it and/or modify | ||
5 | * it under the terms of the GNU General Public License as published by | ||
6 | * the Free Software Foundation; either version 2 of the License, or | ||
7 | * (at your option) any later version. | ||
8 | * | ||
9 | * This program is distributed in the hope that it will be useful, | ||
10 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
12 | * GNU General Public License for more details. | ||
13 | * | ||
14 | * You should have received a copy of the GNU General Public License along | ||
15 | * with this program; if not, write to the Free Software Foundation, Inc., | ||
16 | * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. | ||
17 | */ | ||
18 | |||
19 | #include <linux/module.h> | ||
20 | #include <linux/device.h> | ||
21 | #include <sound/core.h> | ||
22 | #include <sound/pcm.h> | ||
23 | #include <sound/soc.h> | ||
24 | #include <sound/jack.h> | ||
25 | #include <sound/soc-dapm.h> | ||
26 | #include <asm/mach-types.h> | ||
27 | |||
28 | #include "../codecs/sgtl5000.h" | ||
29 | #include "mxs-saif.h" | ||
30 | |||
31 | static int mxs_sgtl5000_hw_params(struct snd_pcm_substream *substream, | ||
32 | struct snd_pcm_hw_params *params) | ||
33 | { | ||
34 | struct snd_soc_pcm_runtime *rtd = substream->private_data; | ||
35 | struct snd_soc_dai *codec_dai = rtd->codec_dai; | ||
36 | struct snd_soc_dai *cpu_dai = rtd->cpu_dai; | ||
37 | unsigned int rate = params_rate(params); | ||
38 | u32 dai_format, mclk; | ||
39 | int ret; | ||
40 | |||
41 | /* sgtl5000 does not support 512*rate when in 96000 fs */ | ||
42 | switch (rate) { | ||
43 | case 96000: | ||
44 | mclk = 256 * rate; | ||
45 | break; | ||
46 | default: | ||
47 | mclk = 512 * rate; | ||
48 | break; | ||
49 | } | ||
50 | |||
51 | /* Sgtl5000 sysclk should be >= 8MHz and <= 27M */ | ||
52 | if (mclk < 8000000 || mclk > 27000000) | ||
53 | return -EINVAL; | ||
54 | |||
55 | /* Set SGTL5000's SYSCLK (provided by SAIF MCLK) */ | ||
56 | ret = snd_soc_dai_set_sysclk(codec_dai, SGTL5000_SYSCLK, mclk, 0); | ||
57 | if (ret) | ||
58 | return ret; | ||
59 | |||
60 | /* The SAIF MCLK should be the same as SGTL5000_SYSCLK */ | ||
61 | ret = snd_soc_dai_set_sysclk(cpu_dai, MXS_SAIF_MCLK, mclk, 0); | ||
62 | if (ret) | ||
63 | return ret; | ||
64 | |||
65 | /* set codec to slave mode */ | ||
66 | dai_format = SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_NB_NF | | ||
67 | SND_SOC_DAIFMT_CBS_CFS; | ||
68 | |||
69 | /* set codec DAI configuration */ | ||
70 | ret = snd_soc_dai_set_fmt(codec_dai, dai_format); | ||
71 | if (ret) | ||
72 | return ret; | ||
73 | |||
74 | /* set cpu DAI configuration */ | ||
75 | ret = snd_soc_dai_set_fmt(cpu_dai, dai_format); | ||
76 | if (ret) | ||
77 | return ret; | ||
78 | |||
79 | return 0; | ||
80 | } | ||
81 | |||
82 | static struct snd_soc_ops mxs_sgtl5000_hifi_ops = { | ||
83 | .hw_params = mxs_sgtl5000_hw_params, | ||
84 | }; | ||
85 | |||
86 | static struct snd_soc_dai_link mxs_sgtl5000_dai[] = { | ||
87 | { | ||
88 | .name = "HiFi Tx", | ||
89 | .stream_name = "HiFi Playback", | ||
90 | .codec_dai_name = "sgtl5000", | ||
91 | .codec_name = "sgtl5000.0-000a", | ||
92 | .cpu_dai_name = "mxs-saif.0", | ||
93 | .platform_name = "mxs-pcm-audio.0", | ||
94 | .ops = &mxs_sgtl5000_hifi_ops, | ||
95 | }, { | ||
96 | .name = "HiFi Rx", | ||
97 | .stream_name = "HiFi Capture", | ||
98 | .codec_dai_name = "sgtl5000", | ||
99 | .codec_name = "sgtl5000.0-000a", | ||
100 | .cpu_dai_name = "mxs-saif.1", | ||
101 | .platform_name = "mxs-pcm-audio.1", | ||
102 | .ops = &mxs_sgtl5000_hifi_ops, | ||
103 | }, | ||
104 | }; | ||
105 | |||
106 | static struct snd_soc_card mxs_sgtl5000 = { | ||
107 | .name = "mxs_sgtl5000", | ||
108 | .dai_link = mxs_sgtl5000_dai, | ||
109 | .num_links = ARRAY_SIZE(mxs_sgtl5000_dai), | ||
110 | }; | ||
111 | |||
112 | static int __devinit mxs_sgtl5000_probe(struct platform_device *pdev) | ||
113 | { | ||
114 | struct snd_soc_card *card = &mxs_sgtl5000; | ||
115 | int ret; | ||
116 | |||
117 | /* | ||
118 | * Set an init clock(11.28Mhz) for sgtl5000 initialization(i2c r/w). | ||
119 | * The Sgtl5000 sysclk is derived from saif0 mclk and it's range | ||
120 | * should be >= 8MHz and <= 27M. | ||
121 | */ | ||
122 | ret = mxs_saif_get_mclk(0, 44100 * 256, 44100); | ||
123 | if (ret) | ||
124 | return ret; | ||
125 | |||
126 | card->dev = &pdev->dev; | ||
127 | platform_set_drvdata(pdev, card); | ||
128 | |||
129 | ret = snd_soc_register_card(card); | ||
130 | if (ret) { | ||
131 | dev_err(&pdev->dev, "snd_soc_register_card failed (%d)\n", | ||
132 | ret); | ||
133 | return ret; | ||
134 | } | ||
135 | |||
136 | return 0; | ||
137 | } | ||
138 | |||
139 | static int __devexit mxs_sgtl5000_remove(struct platform_device *pdev) | ||
140 | { | ||
141 | struct snd_soc_card *card = platform_get_drvdata(pdev); | ||
142 | |||
143 | mxs_saif_put_mclk(0); | ||
144 | |||
145 | snd_soc_unregister_card(card); | ||
146 | |||
147 | return 0; | ||
148 | } | ||
149 | |||
150 | static struct platform_driver mxs_sgtl5000_audio_driver = { | ||
151 | .driver = { | ||
152 | .name = "mxs-sgtl5000", | ||
153 | .owner = THIS_MODULE, | ||
154 | }, | ||
155 | .probe = mxs_sgtl5000_probe, | ||
156 | .remove = __devexit_p(mxs_sgtl5000_remove), | ||
157 | }; | ||
158 | |||
159 | static int __init mxs_sgtl5000_init(void) | ||
160 | { | ||
161 | return platform_driver_register(&mxs_sgtl5000_audio_driver); | ||
162 | } | ||
163 | module_init(mxs_sgtl5000_init); | ||
164 | |||
165 | static void __exit mxs_sgtl5000_exit(void) | ||
166 | { | ||
167 | platform_driver_unregister(&mxs_sgtl5000_audio_driver); | ||
168 | } | ||
169 | module_exit(mxs_sgtl5000_exit); | ||
170 | |||
171 | MODULE_AUTHOR("Freescale Semiconductor, Inc."); | ||
172 | MODULE_DESCRIPTION("MXS ALSA SoC Machine driver"); | ||
173 | MODULE_LICENSE("GPL"); | ||
diff --git a/sound/soc/nuc900/nuc900-pcm.c b/sound/soc/nuc900/nuc900-pcm.c index d589ef14e917..865b288bd748 100644 --- a/sound/soc/nuc900/nuc900-pcm.c +++ b/sound/soc/nuc900/nuc900-pcm.c | |||
@@ -268,7 +268,7 @@ static int nuc900_dma_open(struct snd_pcm_substream *substream) | |||
268 | nuc900_audio = nuc900_ac97_data; | 268 | nuc900_audio = nuc900_ac97_data; |
269 | 269 | ||
270 | if (request_irq(nuc900_audio->irq_num, nuc900_dma_interrupt, | 270 | if (request_irq(nuc900_audio->irq_num, nuc900_dma_interrupt, |
271 | IRQF_DISABLED, "nuc900-dma", substream)) | 271 | 0, "nuc900-dma", substream)) |
272 | return -EBUSY; | 272 | return -EBUSY; |
273 | 273 | ||
274 | runtime->private_data = nuc900_audio; | 274 | runtime->private_data = nuc900_audio; |
@@ -318,7 +318,6 @@ static u64 nuc900_pcm_dmamask = DMA_BIT_MASK(32); | |||
318 | static int nuc900_dma_new(struct snd_soc_pcm_runtime *rtd) | 318 | static int nuc900_dma_new(struct snd_soc_pcm_runtime *rtd) |
319 | { | 319 | { |
320 | struct snd_card *card = rtd->card->snd_card; | 320 | struct snd_card *card = rtd->card->snd_card; |
321 | struct snd_soc_dai *dai = rtd->cpu_dai; | ||
322 | struct snd_pcm *pcm = rtd->pcm; | 321 | struct snd_pcm *pcm = rtd->pcm; |
323 | 322 | ||
324 | if (!card->dev->dma_mask) | 323 | if (!card->dev->dma_mask) |
diff --git a/sound/soc/pxa/raumfeld.c b/sound/soc/pxa/raumfeld.c index 1a591f1ebfbd..b899a3bc8f42 100644 --- a/sound/soc/pxa/raumfeld.c +++ b/sound/soc/pxa/raumfeld.c | |||
@@ -306,8 +306,10 @@ static int __init raumfeld_audio_init(void) | |||
306 | &snd_soc_raumfeld_connector); | 306 | &snd_soc_raumfeld_connector); |
307 | 307 | ||
308 | ret = platform_device_add(raumfeld_audio_device); | 308 | ret = platform_device_add(raumfeld_audio_device); |
309 | if (ret < 0) | 309 | if (ret < 0) { |
310 | platform_device_put(raumfeld_audio_device); | ||
310 | return ret; | 311 | return ret; |
312 | } | ||
311 | 313 | ||
312 | raumfeld_enable_audio(true); | 314 | raumfeld_enable_audio(true); |
313 | return 0; | 315 | return 0; |
diff --git a/sound/soc/pxa/spitz.c b/sound/soc/pxa/spitz.c index b253d864868a..ce920e3cfea1 100644 --- a/sound/soc/pxa/spitz.c +++ b/sound/soc/pxa/spitz.c | |||
@@ -312,7 +312,7 @@ static struct snd_soc_dai_link spitz_dai = { | |||
312 | .cpu_dai_name = "pxa2xx-i2s", | 312 | .cpu_dai_name = "pxa2xx-i2s", |
313 | .codec_dai_name = "wm8750-hifi", | 313 | .codec_dai_name = "wm8750-hifi", |
314 | .platform_name = "pxa-pcm-audio", | 314 | .platform_name = "pxa-pcm-audio", |
315 | .codec_name = "wm8750-codec.0-001b", | 315 | .codec_name = "wm8750.0-001b", |
316 | .init = spitz_wm8750_init, | 316 | .init = spitz_wm8750_init, |
317 | .ops = &spitz_ops, | 317 | .ops = &spitz_ops, |
318 | }; | 318 | }; |
diff --git a/sound/soc/pxa/z2.c b/sound/soc/pxa/z2.c index d69d9fc32233..4b81ffd87566 100644 --- a/sound/soc/pxa/z2.c +++ b/sound/soc/pxa/z2.c | |||
@@ -198,7 +198,7 @@ static struct snd_soc_dai_link z2_dai = { | |||
198 | .cpu_dai_name = "pxa2xx-i2s", | 198 | .cpu_dai_name = "pxa2xx-i2s", |
199 | .codec_dai_name = "wm8750-hifi", | 199 | .codec_dai_name = "wm8750-hifi", |
200 | .platform_name = "pxa-pcm-audio", | 200 | .platform_name = "pxa-pcm-audio", |
201 | .codec_name = "wm8750-codec.0-001b", | 201 | .codec_name = "wm8750.0-001b", |
202 | .init = z2_wm8750_init, | 202 | .init = z2_wm8750_init, |
203 | .ops = &z2_ops, | 203 | .ops = &z2_ops, |
204 | }; | 204 | }; |
diff --git a/sound/soc/s6000/s6000-pcm.c b/sound/soc/s6000/s6000-pcm.c index 80c85fd64e1a..55efc2bdf0bd 100644 --- a/sound/soc/s6000/s6000-pcm.c +++ b/sound/soc/s6000/s6000-pcm.c | |||
@@ -446,7 +446,6 @@ static u64 s6000_pcm_dmamask = DMA_BIT_MASK(32); | |||
446 | static int s6000_pcm_new(struct snd_soc_pcm_runtime *runtime) | 446 | static int s6000_pcm_new(struct snd_soc_pcm_runtime *runtime) |
447 | { | 447 | { |
448 | struct snd_card *card = runtime->card->snd_card; | 448 | struct snd_card *card = runtime->card->snd_card; |
449 | struct snd_soc_dai *dai = runtime->cpu_dai; | ||
450 | struct snd_pcm *pcm = runtime->pcm; | 449 | struct snd_pcm *pcm = runtime->pcm; |
451 | struct s6000_pcm_dma_params *params; | 450 | struct s6000_pcm_dma_params *params; |
452 | int res; | 451 | int res; |
diff --git a/sound/soc/samsung/Kconfig b/sound/soc/samsung/Kconfig index 65f980ef2870..dd3b3eac0805 100644 --- a/sound/soc/samsung/Kconfig +++ b/sound/soc/samsung/Kconfig | |||
@@ -63,7 +63,7 @@ config SND_SOC_SAMSUNG_SMDK_WM8580 | |||
63 | 63 | ||
64 | config SND_SOC_SAMSUNG_SMDK_WM8994 | 64 | config SND_SOC_SAMSUNG_SMDK_WM8994 |
65 | tristate "SoC I2S Audio support for WM8994 on SMDK" | 65 | tristate "SoC I2S Audio support for WM8994 on SMDK" |
66 | depends on SND_SOC_SAMSUNG && (MACH_SMDKV310 || MACH_SMDKC210) | 66 | depends on SND_SOC_SAMSUNG && (MACH_SMDKV310 || MACH_SMDKC210 || MACH_SMDK4212) |
67 | select SND_SOC_WM8994 | 67 | select SND_SOC_WM8994 |
68 | select SND_SAMSUNG_I2S | 68 | select SND_SAMSUNG_I2S |
69 | help | 69 | help |
@@ -158,7 +158,7 @@ config SND_SOC_GONI_AQUILA_WM8994 | |||
158 | 158 | ||
159 | config SND_SOC_SAMSUNG_SMDK_SPDIF | 159 | config SND_SOC_SAMSUNG_SMDK_SPDIF |
160 | tristate "SoC S/PDIF Audio support for SMDK" | 160 | tristate "SoC S/PDIF Audio support for SMDK" |
161 | depends on SND_SOC_SAMSUNG && (MACH_SMDKC100 || MACH_SMDKC110 || MACH_SMDKV210 || MACH_SMDKV310) | 161 | depends on SND_SOC_SAMSUNG && (MACH_SMDKC100 || MACH_SMDKC110 || MACH_SMDKV210 || MACH_SMDKV310 || MACH_SMDK4212) |
162 | select SND_SAMSUNG_SPDIF | 162 | select SND_SAMSUNG_SPDIF |
163 | help | 163 | help |
164 | Say Y if you want to add support for SoC S/PDIF audio on the SMDK. | 164 | Say Y if you want to add support for SoC S/PDIF audio on the SMDK. |
@@ -173,7 +173,7 @@ config SND_SOC_SMDK_WM8580_PCM | |||
173 | 173 | ||
174 | config SND_SOC_SMDK_WM8994_PCM | 174 | config SND_SOC_SMDK_WM8994_PCM |
175 | tristate "SoC PCM Audio support for WM8994 on SMDK" | 175 | tristate "SoC PCM Audio support for WM8994 on SMDK" |
176 | depends on SND_SOC_SAMSUNG && (MACH_SMDKC210 || MACH_SMDKV310) | 176 | depends on SND_SOC_SAMSUNG && (MACH_SMDKC210 || MACH_SMDKV310 || MACH_SMDK4212) |
177 | select SND_SOC_WM8994 | 177 | select SND_SOC_WM8994 |
178 | select SND_SAMSUNG_PCM | 178 | select SND_SAMSUNG_PCM |
179 | help | 179 | help |
diff --git a/sound/soc/samsung/ac97.c b/sound/soc/samsung/ac97.c index f97110e72e85..884c8a107bf9 100644 --- a/sound/soc/samsung/ac97.c +++ b/sound/soc/samsung/ac97.c | |||
@@ -444,7 +444,7 @@ static __devinit int s3c_ac97_probe(struct platform_device *pdev) | |||
444 | } | 444 | } |
445 | 445 | ||
446 | ret = request_irq(irq_res->start, s3c_ac97_irq, | 446 | ret = request_irq(irq_res->start, s3c_ac97_irq, |
447 | IRQF_DISABLED, "AC97", NULL); | 447 | 0, "AC97", NULL); |
448 | if (ret < 0) { | 448 | if (ret < 0) { |
449 | dev_err(&pdev->dev, "ac97: interrupt request failed.\n"); | 449 | dev_err(&pdev->dev, "ac97: interrupt request failed.\n"); |
450 | goto err4; | 450 | goto err4; |
diff --git a/sound/soc/samsung/jive_wm8750.c b/sound/soc/samsung/jive_wm8750.c index 14eb6ea69e7c..ed8f13a29c85 100644 --- a/sound/soc/samsung/jive_wm8750.c +++ b/sound/soc/samsung/jive_wm8750.c | |||
@@ -131,7 +131,7 @@ static struct snd_soc_dai_link jive_dai = { | |||
131 | .cpu_dai_name = "s3c2412-i2s", | 131 | .cpu_dai_name = "s3c2412-i2s", |
132 | .codec_dai_name = "wm8750-hifi", | 132 | .codec_dai_name = "wm8750-hifi", |
133 | .platform_name = "samsung-audio", | 133 | .platform_name = "samsung-audio", |
134 | .codec_name = "wm8750-codec.0-001a", | 134 | .codec_name = "wm8750.0-001a", |
135 | .init = jive_wm8750_init, | 135 | .init = jive_wm8750_init, |
136 | .ops = &jive_ops, | 136 | .ops = &jive_ops, |
137 | }; | 137 | }; |
diff --git a/sound/soc/samsung/s3c2412-i2s.c b/sound/soc/samsung/s3c2412-i2s.c index 841ab14c1100..7ab8e2c29216 100644 --- a/sound/soc/samsung/s3c2412-i2s.c +++ b/sound/soc/samsung/s3c2412-i2s.c | |||
@@ -69,10 +69,10 @@ static int s3c2412_i2s_probe(struct snd_soc_dai *dai) | |||
69 | s3c2412_i2s.dma_playback = &s3c2412_i2s_pcm_stereo_out; | 69 | s3c2412_i2s.dma_playback = &s3c2412_i2s_pcm_stereo_out; |
70 | 70 | ||
71 | s3c2412_i2s.iis_cclk = clk_get(dai->dev, "i2sclk"); | 71 | s3c2412_i2s.iis_cclk = clk_get(dai->dev, "i2sclk"); |
72 | if (s3c2412_i2s.iis_cclk == NULL) { | 72 | if (IS_ERR(s3c2412_i2s.iis_cclk)) { |
73 | pr_err("failed to get i2sclk clock\n"); | 73 | pr_err("failed to get i2sclk clock\n"); |
74 | iounmap(s3c2412_i2s.regs); | 74 | iounmap(s3c2412_i2s.regs); |
75 | return -ENODEV; | 75 | return PTR_ERR(s3c2412_i2s.iis_cclk); |
76 | } | 76 | } |
77 | 77 | ||
78 | /* Set MPLL as the source for IIS CLK */ | 78 | /* Set MPLL as the source for IIS CLK */ |
diff --git a/sound/soc/samsung/s3c24xx-i2s.c b/sound/soc/samsung/s3c24xx-i2s.c index 63d8849d80bd..21c92e2e3007 100644 --- a/sound/soc/samsung/s3c24xx-i2s.c +++ b/sound/soc/samsung/s3c24xx-i2s.c | |||
@@ -383,10 +383,10 @@ static int s3c24xx_i2s_probe(struct snd_soc_dai *dai) | |||
383 | return -ENXIO; | 383 | return -ENXIO; |
384 | 384 | ||
385 | s3c24xx_i2s.iis_clk = clk_get(dai->dev, "iis"); | 385 | s3c24xx_i2s.iis_clk = clk_get(dai->dev, "iis"); |
386 | if (s3c24xx_i2s.iis_clk == NULL) { | 386 | if (IS_ERR(s3c24xx_i2s.iis_clk)) { |
387 | pr_err("failed to get iis_clock\n"); | 387 | pr_err("failed to get iis_clock\n"); |
388 | iounmap(s3c24xx_i2s.regs); | 388 | iounmap(s3c24xx_i2s.regs); |
389 | return -ENODEV; | 389 | return PTR_ERR(s3c24xx_i2s.iis_clk); |
390 | } | 390 | } |
391 | clk_enable(s3c24xx_i2s.iis_clk); | 391 | clk_enable(s3c24xx_i2s.iis_clk); |
392 | 392 | ||
diff --git a/sound/soc/samsung/s3c24xx_uda134x.c b/sound/soc/samsung/s3c24xx_uda134x.c index dc9d551f6788..65c1cfd47d8a 100644 --- a/sound/soc/samsung/s3c24xx_uda134x.c +++ b/sound/soc/samsung/s3c24xx_uda134x.c | |||
@@ -66,17 +66,17 @@ static int s3c24xx_uda134x_startup(struct snd_pcm_substream *substream) | |||
66 | pr_debug("%s %d\n", __func__, clk_users); | 66 | pr_debug("%s %d\n", __func__, clk_users); |
67 | if (clk_users == 0) { | 67 | if (clk_users == 0) { |
68 | xtal = clk_get(&s3c24xx_uda134x_snd_device->dev, "xtal"); | 68 | xtal = clk_get(&s3c24xx_uda134x_snd_device->dev, "xtal"); |
69 | if (!xtal) { | 69 | if (IS_ERR(xtal)) { |
70 | printk(KERN_ERR "%s cannot get xtal\n", __func__); | 70 | printk(KERN_ERR "%s cannot get xtal\n", __func__); |
71 | ret = -EBUSY; | 71 | ret = PTR_ERR(xtal); |
72 | } else { | 72 | } else { |
73 | pclk = clk_get(&s3c24xx_uda134x_snd_device->dev, | 73 | pclk = clk_get(&s3c24xx_uda134x_snd_device->dev, |
74 | "pclk"); | 74 | "pclk"); |
75 | if (!pclk) { | 75 | if (IS_ERR(pclk)) { |
76 | printk(KERN_ERR "%s cannot get pclk\n", | 76 | printk(KERN_ERR "%s cannot get pclk\n", |
77 | __func__); | 77 | __func__); |
78 | clk_put(xtal); | 78 | clk_put(xtal); |
79 | ret = -EBUSY; | 79 | ret = PTR_ERR(pclk); |
80 | } | 80 | } |
81 | } | 81 | } |
82 | if (!ret) { | 82 | if (!ret) { |
diff --git a/sound/soc/samsung/smartq_wm8987.c b/sound/soc/samsung/smartq_wm8987.c index 0a2c4f223038..bbd14768ecd3 100644 --- a/sound/soc/samsung/smartq_wm8987.c +++ b/sound/soc/samsung/smartq_wm8987.c | |||
@@ -207,7 +207,7 @@ static struct snd_soc_dai_link smartq_dai[] = { | |||
207 | .cpu_dai_name = "samsung-i2s.0", | 207 | .cpu_dai_name = "samsung-i2s.0", |
208 | .codec_dai_name = "wm8750-hifi", | 208 | .codec_dai_name = "wm8750-hifi", |
209 | .platform_name = "samsung-audio", | 209 | .platform_name = "samsung-audio", |
210 | .codec_name = "wm8750-codec.0-0x1a", | 210 | .codec_name = "wm8750.0-0x1a", |
211 | .init = smartq_wm8987_init, | 211 | .init = smartq_wm8987_init, |
212 | .ops = &smartq_hifi_ops, | 212 | .ops = &smartq_hifi_ops, |
213 | }, | 213 | }, |
diff --git a/sound/soc/samsung/smdk_wm8580.c b/sound/soc/samsung/smdk_wm8580.c index 3d26f6607aa4..20deecf3b243 100644 --- a/sound/soc/samsung/smdk_wm8580.c +++ b/sound/soc/samsung/smdk_wm8580.c | |||
@@ -210,7 +210,7 @@ static struct snd_soc_dai_link smdk_dai[] = { | |||
210 | .cpu_dai_name = "samsung-i2s.0", | 210 | .cpu_dai_name = "samsung-i2s.0", |
211 | .codec_dai_name = "wm8580-hifi-playback", | 211 | .codec_dai_name = "wm8580-hifi-playback", |
212 | .platform_name = "samsung-audio", | 212 | .platform_name = "samsung-audio", |
213 | .codec_name = "wm8580-codec.0-001b", | 213 | .codec_name = "wm8580.0-001b", |
214 | .init = smdk_wm8580_init_paifrx, | 214 | .init = smdk_wm8580_init_paifrx, |
215 | .ops = &smdk_ops, | 215 | .ops = &smdk_ops, |
216 | }, | 216 | }, |
@@ -220,7 +220,7 @@ static struct snd_soc_dai_link smdk_dai[] = { | |||
220 | .cpu_dai_name = "samsung-i2s.0", | 220 | .cpu_dai_name = "samsung-i2s.0", |
221 | .codec_dai_name = "wm8580-hifi-capture", | 221 | .codec_dai_name = "wm8580-hifi-capture", |
222 | .platform_name = "samsung-audio", | 222 | .platform_name = "samsung-audio", |
223 | .codec_name = "wm8580-codec.0-001b", | 223 | .codec_name = "wm8580.0-001b", |
224 | .init = smdk_wm8580_init_paiftx, | 224 | .init = smdk_wm8580_init_paiftx, |
225 | .ops = &smdk_ops, | 225 | .ops = &smdk_ops, |
226 | }, | 226 | }, |
@@ -230,7 +230,7 @@ static struct snd_soc_dai_link smdk_dai[] = { | |||
230 | .cpu_dai_name = "samsung-i2s.x", | 230 | .cpu_dai_name = "samsung-i2s.x", |
231 | .codec_dai_name = "wm8580-hifi-playback", | 231 | .codec_dai_name = "wm8580-hifi-playback", |
232 | .platform_name = "samsung-audio", | 232 | .platform_name = "samsung-audio", |
233 | .codec_name = "wm8580-codec.0-001b", | 233 | .codec_name = "wm8580.0-001b", |
234 | .init = smdk_wm8580_init_paifrx, | 234 | .init = smdk_wm8580_init_paifrx, |
235 | .ops = &smdk_ops, | 235 | .ops = &smdk_ops, |
236 | }, | 236 | }, |
diff --git a/sound/soc/samsung/smdk_wm8580pcm.c b/sound/soc/samsung/smdk_wm8580pcm.c index 0d12092df164..4b9c73477ce0 100644 --- a/sound/soc/samsung/smdk_wm8580pcm.c +++ b/sound/soc/samsung/smdk_wm8580pcm.c | |||
@@ -127,7 +127,7 @@ static struct snd_soc_dai_link smdk_dai[] = { | |||
127 | .cpu_dai_name = "samsung-pcm.0", | 127 | .cpu_dai_name = "samsung-pcm.0", |
128 | .codec_dai_name = "wm8580-hifi-playback", | 128 | .codec_dai_name = "wm8580-hifi-playback", |
129 | .platform_name = "samsung-audio", | 129 | .platform_name = "samsung-audio", |
130 | .codec_name = "wm8580-codec.0-001b", | 130 | .codec_name = "wm8580.0-001b", |
131 | .ops = &smdk_wm8580_pcm_ops, | 131 | .ops = &smdk_wm8580_pcm_ops, |
132 | }, { | 132 | }, { |
133 | .name = "WM8580 PAIF PCM TX", | 133 | .name = "WM8580 PAIF PCM TX", |
@@ -135,7 +135,7 @@ static struct snd_soc_dai_link smdk_dai[] = { | |||
135 | .cpu_dai_name = "samsung-pcm.0", | 135 | .cpu_dai_name = "samsung-pcm.0", |
136 | .codec_dai_name = "wm8580-hifi-capture", | 136 | .codec_dai_name = "wm8580-hifi-capture", |
137 | .platform_name = "samsung-audio", | 137 | .platform_name = "samsung-audio", |
138 | .codec_name = "wm8580-codec.0-001b", | 138 | .codec_name = "wm8580.0-001b", |
139 | .ops = &smdk_wm8580_pcm_ops, | 139 | .ops = &smdk_wm8580_pcm_ops, |
140 | }, | 140 | }, |
141 | }; | 141 | }; |
diff --git a/sound/soc/samsung/speyside.c b/sound/soc/samsung/speyside.c index 590e9274b062..b9e213f6cc06 100644 --- a/sound/soc/samsung/speyside.c +++ b/sound/soc/samsung/speyside.c | |||
@@ -125,10 +125,6 @@ static struct snd_soc_jack_pin speyside_headset_pins[] = { | |||
125 | .pin = "Headset Mic", | 125 | .pin = "Headset Mic", |
126 | .mask = SND_JACK_MICROPHONE, | 126 | .mask = SND_JACK_MICROPHONE, |
127 | }, | 127 | }, |
128 | { | ||
129 | .pin = "Headphone", | ||
130 | .mask = SND_JACK_HEADPHONE, | ||
131 | }, | ||
132 | }; | 128 | }; |
133 | 129 | ||
134 | /* Default the headphone selection to active high */ | 130 | /* Default the headphone selection to active high */ |
@@ -171,7 +167,8 @@ static int speyside_wm8996_init(struct snd_soc_pcm_runtime *rtd) | |||
171 | gpio_direction_output(WM8996_HPSEL_GPIO, speyside_jack_polarity); | 167 | gpio_direction_output(WM8996_HPSEL_GPIO, speyside_jack_polarity); |
172 | 168 | ||
173 | ret = snd_soc_jack_new(codec, "Headset", | 169 | ret = snd_soc_jack_new(codec, "Headset", |
174 | SND_JACK_HEADSET | SND_JACK_BTN_0, | 170 | SND_JACK_LINEOUT | SND_JACK_HEADSET | |
171 | SND_JACK_BTN_0, | ||
175 | &speyside_headset); | 172 | &speyside_headset); |
176 | if (ret) | 173 | if (ret) |
177 | return ret; | 174 | return ret; |
@@ -227,7 +224,7 @@ static int speyside_wm9081_init(struct snd_soc_dapm_context *dapm) | |||
227 | snd_soc_dapm_nc_pin(dapm, "LINEOUT"); | 224 | snd_soc_dapm_nc_pin(dapm, "LINEOUT"); |
228 | 225 | ||
229 | /* At any time the WM9081 is active it will have this clock */ | 226 | /* At any time the WM9081 is active it will have this clock */ |
230 | return snd_soc_codec_set_sysclk(dapm->codec, WM9081_SYSCLK_MCLK, | 227 | return snd_soc_codec_set_sysclk(dapm->codec, WM9081_SYSCLK_MCLK, 0, |
231 | 48000 * 256, 0); | 228 | 48000 * 256, 0); |
232 | } | 229 | } |
233 | 230 | ||
@@ -252,6 +249,7 @@ static const struct snd_kcontrol_new controls[] = { | |||
252 | SOC_DAPM_PIN_SWITCH("Main AMIC"), | 249 | SOC_DAPM_PIN_SWITCH("Main AMIC"), |
253 | SOC_DAPM_PIN_SWITCH("WM1250 Input"), | 250 | SOC_DAPM_PIN_SWITCH("WM1250 Input"), |
254 | SOC_DAPM_PIN_SWITCH("WM1250 Output"), | 251 | SOC_DAPM_PIN_SWITCH("WM1250 Output"), |
252 | SOC_DAPM_PIN_SWITCH("Headphone"), | ||
255 | }; | 253 | }; |
256 | 254 | ||
257 | static struct snd_soc_dapm_widget widgets[] = { | 255 | static struct snd_soc_dapm_widget widgets[] = { |
diff --git a/sound/soc/samsung/speyside_wm8962.c b/sound/soc/samsung/speyside_wm8962.c index 72535f2daaf2..3820a6b057dc 100644 --- a/sound/soc/samsung/speyside_wm8962.c +++ b/sound/soc/samsung/speyside_wm8962.c | |||
@@ -31,13 +31,13 @@ static int speyside_wm8962_set_bias_level(struct snd_soc_card *card, | |||
31 | if (dapm->bias_level == SND_SOC_BIAS_STANDBY) { | 31 | if (dapm->bias_level == SND_SOC_BIAS_STANDBY) { |
32 | ret = snd_soc_dai_set_pll(codec_dai, WM8962_FLL, | 32 | ret = snd_soc_dai_set_pll(codec_dai, WM8962_FLL, |
33 | WM8962_FLL_MCLK, 32768, | 33 | WM8962_FLL_MCLK, 32768, |
34 | 44100 * 256); | 34 | 44100 * 512); |
35 | if (ret < 0) | 35 | if (ret < 0) |
36 | pr_err("Failed to start FLL: %d\n", ret); | 36 | pr_err("Failed to start FLL: %d\n", ret); |
37 | 37 | ||
38 | ret = snd_soc_dai_set_sysclk(codec_dai, | 38 | ret = snd_soc_dai_set_sysclk(codec_dai, |
39 | WM8962_SYSCLK_FLL, | 39 | WM8962_SYSCLK_FLL, |
40 | 44100 * 256, | 40 | 44100 * 512, |
41 | SND_SOC_CLOCK_IN); | 41 | SND_SOC_CLOCK_IN); |
42 | if (ret < 0) { | 42 | if (ret < 0) { |
43 | pr_err("Failed to set SYSCLK: %d\n", ret); | 43 | pr_err("Failed to set SYSCLK: %d\n", ret); |
diff --git a/sound/soc/sh/fsi.c b/sound/soc/sh/fsi.c index 8e112ccffb13..1493ebf4d943 100644 --- a/sound/soc/sh/fsi.c +++ b/sound/soc/sh/fsi.c | |||
@@ -1285,7 +1285,7 @@ static int fsi_probe(struct platform_device *pdev) | |||
1285 | pm_runtime_enable(&pdev->dev); | 1285 | pm_runtime_enable(&pdev->dev); |
1286 | dev_set_drvdata(&pdev->dev, master); | 1286 | dev_set_drvdata(&pdev->dev, master); |
1287 | 1287 | ||
1288 | ret = request_irq(irq, &fsi_interrupt, IRQF_DISABLED, | 1288 | ret = request_irq(irq, &fsi_interrupt, 0, |
1289 | id_entry->name, master); | 1289 | id_entry->name, master); |
1290 | if (ret) { | 1290 | if (ret) { |
1291 | dev_err(&pdev->dev, "irq request err\n"); | 1291 | dev_err(&pdev->dev, "irq request err\n"); |
diff --git a/sound/soc/soc-cache.c b/sound/soc/soc-cache.c index 20b7f3b003a3..143c705ac27b 100644 --- a/sound/soc/soc-cache.c +++ b/sound/soc/soc-cache.c | |||
@@ -548,9 +548,6 @@ static inline int snd_soc_lzo_get_blkpos(struct snd_soc_codec *codec, | |||
548 | 548 | ||
549 | static inline int snd_soc_lzo_get_blksize(struct snd_soc_codec *codec) | 549 | static inline int snd_soc_lzo_get_blksize(struct snd_soc_codec *codec) |
550 | { | 550 | { |
551 | const struct snd_soc_codec_driver *codec_drv; | ||
552 | |||
553 | codec_drv = codec->driver; | ||
554 | return DIV_ROUND_UP(codec->reg_size, snd_soc_lzo_block_count()); | 551 | return DIV_ROUND_UP(codec->reg_size, snd_soc_lzo_block_count()); |
555 | } | 552 | } |
556 | 553 | ||
@@ -868,10 +865,6 @@ static int snd_soc_flat_cache_exit(struct snd_soc_codec *codec) | |||
868 | 865 | ||
869 | static int snd_soc_flat_cache_init(struct snd_soc_codec *codec) | 866 | static int snd_soc_flat_cache_init(struct snd_soc_codec *codec) |
870 | { | 867 | { |
871 | const struct snd_soc_codec_driver *codec_drv; | ||
872 | |||
873 | codec_drv = codec->driver; | ||
874 | |||
875 | if (codec->reg_def_copy) | 868 | if (codec->reg_def_copy) |
876 | codec->reg_cache = kmemdup(codec->reg_def_copy, | 869 | codec->reg_cache = kmemdup(codec->reg_def_copy, |
877 | codec->reg_size, GFP_KERNEL); | 870 | codec->reg_size, GFP_KERNEL); |
diff --git a/sound/soc/soc-core.c b/sound/soc/soc-core.c index ef69f5a02709..bd20154e8b34 100644 --- a/sound/soc/soc-core.c +++ b/sound/soc/soc-core.c | |||
@@ -106,7 +106,7 @@ static int format_register_str(struct snd_soc_codec *codec, | |||
106 | if (wordsize + regsize + 2 + 1 != len) | 106 | if (wordsize + regsize + 2 + 1 != len) |
107 | return -EINVAL; | 107 | return -EINVAL; |
108 | 108 | ||
109 | ret = snd_soc_read(codec , reg); | 109 | ret = snd_soc_read(codec, reg); |
110 | if (ret < 0) { | 110 | if (ret < 0) { |
111 | memset(regbuf, 'X', regsize); | 111 | memset(regbuf, 'X', regsize); |
112 | regbuf[regsize] = '\0'; | 112 | regbuf[regsize] = '\0'; |
@@ -144,7 +144,7 @@ static ssize_t soc_codec_reg_show(struct snd_soc_codec *codec, char *buf, | |||
144 | step = codec->driver->reg_cache_step; | 144 | step = codec->driver->reg_cache_step; |
145 | 145 | ||
146 | for (i = 0; i < codec->driver->reg_cache_size; i += step) { | 146 | for (i = 0; i < codec->driver->reg_cache_size; i += step) { |
147 | if (codec->readable_register && !codec->readable_register(codec, i)) | 147 | if (!snd_soc_codec_readable_register(codec, i)) |
148 | continue; | 148 | continue; |
149 | if (codec->driver->display_register) { | 149 | if (codec->driver->display_register) { |
150 | count += codec->driver->display_register(codec, buf + count, | 150 | count += codec->driver->display_register(codec, buf + count, |
@@ -245,7 +245,6 @@ static ssize_t codec_reg_write_file(struct file *file, | |||
245 | size_t buf_size; | 245 | size_t buf_size; |
246 | char *start = buf; | 246 | char *start = buf; |
247 | unsigned long reg, value; | 247 | unsigned long reg, value; |
248 | int step = 1; | ||
249 | struct snd_soc_codec *codec = file->private_data; | 248 | struct snd_soc_codec *codec = file->private_data; |
250 | 249 | ||
251 | buf_size = min(count, (sizeof(buf)-1)); | 250 | buf_size = min(count, (sizeof(buf)-1)); |
@@ -253,9 +252,6 @@ static ssize_t codec_reg_write_file(struct file *file, | |||
253 | return -EFAULT; | 252 | return -EFAULT; |
254 | buf[buf_size] = 0; | 253 | buf[buf_size] = 0; |
255 | 254 | ||
256 | if (codec->driver->reg_cache_step) | ||
257 | step = codec->driver->reg_cache_step; | ||
258 | |||
259 | while (*start == ' ') | 255 | while (*start == ' ') |
260 | start++; | 256 | start++; |
261 | reg = simple_strtoul(start, &start, 16); | 257 | reg = simple_strtoul(start, &start, 16); |
@@ -957,6 +953,8 @@ static int soc_probe_codec(struct snd_soc_card *card, | |||
957 | snd_soc_dapm_new_controls(&codec->dapm, driver->dapm_widgets, | 953 | snd_soc_dapm_new_controls(&codec->dapm, driver->dapm_widgets, |
958 | driver->num_dapm_widgets); | 954 | driver->num_dapm_widgets); |
959 | 955 | ||
956 | codec->dapm.idle_bias_off = driver->idle_bias_off; | ||
957 | |||
960 | if (driver->probe) { | 958 | if (driver->probe) { |
961 | ret = driver->probe(codec); | 959 | ret = driver->probe(codec); |
962 | if (ret < 0) { | 960 | if (ret < 0) { |
@@ -2680,7 +2678,7 @@ int snd_soc_dai_set_sysclk(struct snd_soc_dai *dai, int clk_id, | |||
2680 | if (dai->driver && dai->driver->ops->set_sysclk) | 2678 | if (dai->driver && dai->driver->ops->set_sysclk) |
2681 | return dai->driver->ops->set_sysclk(dai, clk_id, freq, dir); | 2679 | return dai->driver->ops->set_sysclk(dai, clk_id, freq, dir); |
2682 | else if (dai->codec && dai->codec->driver->set_sysclk) | 2680 | else if (dai->codec && dai->codec->driver->set_sysclk) |
2683 | return dai->codec->driver->set_sysclk(dai->codec, clk_id, | 2681 | return dai->codec->driver->set_sysclk(dai->codec, clk_id, 0, |
2684 | freq, dir); | 2682 | freq, dir); |
2685 | else | 2683 | else |
2686 | return -EINVAL; | 2684 | return -EINVAL; |
@@ -2691,16 +2689,18 @@ EXPORT_SYMBOL_GPL(snd_soc_dai_set_sysclk); | |||
2691 | * snd_soc_codec_set_sysclk - configure CODEC system or master clock. | 2689 | * snd_soc_codec_set_sysclk - configure CODEC system or master clock. |
2692 | * @codec: CODEC | 2690 | * @codec: CODEC |
2693 | * @clk_id: DAI specific clock ID | 2691 | * @clk_id: DAI specific clock ID |
2692 | * @source: Source for the clock | ||
2694 | * @freq: new clock frequency in Hz | 2693 | * @freq: new clock frequency in Hz |
2695 | * @dir: new clock direction - input/output. | 2694 | * @dir: new clock direction - input/output. |
2696 | * | 2695 | * |
2697 | * Configures the CODEC master (MCLK) or system (SYSCLK) clocking. | 2696 | * Configures the CODEC master (MCLK) or system (SYSCLK) clocking. |
2698 | */ | 2697 | */ |
2699 | int snd_soc_codec_set_sysclk(struct snd_soc_codec *codec, int clk_id, | 2698 | int snd_soc_codec_set_sysclk(struct snd_soc_codec *codec, int clk_id, |
2700 | unsigned int freq, int dir) | 2699 | int source, unsigned int freq, int dir) |
2701 | { | 2700 | { |
2702 | if (codec->driver->set_sysclk) | 2701 | if (codec->driver->set_sysclk) |
2703 | return codec->driver->set_sysclk(codec, clk_id, freq, dir); | 2702 | return codec->driver->set_sysclk(codec, clk_id, source, |
2703 | freq, dir); | ||
2704 | else | 2704 | else |
2705 | return -EINVAL; | 2705 | return -EINVAL; |
2706 | } | 2706 | } |
@@ -3153,6 +3153,7 @@ int snd_soc_register_platform(struct device *dev, | |||
3153 | platform->driver = platform_drv; | 3153 | platform->driver = platform_drv; |
3154 | platform->dapm.dev = dev; | 3154 | platform->dapm.dev = dev; |
3155 | platform->dapm.platform = platform; | 3155 | platform->dapm.platform = platform; |
3156 | platform->dapm.stream_event = platform_drv->stream_event; | ||
3156 | 3157 | ||
3157 | mutex_lock(&client_mutex); | 3158 | mutex_lock(&client_mutex); |
3158 | list_add(&platform->list, &platform_list); | 3159 | list_add(&platform->list, &platform_list); |
@@ -3265,6 +3266,7 @@ int snd_soc_register_codec(struct device *dev, | |||
3265 | codec->dapm.dev = dev; | 3266 | codec->dapm.dev = dev; |
3266 | codec->dapm.codec = codec; | 3267 | codec->dapm.codec = codec; |
3267 | codec->dapm.seq_notifier = codec_drv->seq_notifier; | 3268 | codec->dapm.seq_notifier = codec_drv->seq_notifier; |
3269 | codec->dapm.stream_event = codec_drv->stream_event; | ||
3268 | codec->dev = dev; | 3270 | codec->dev = dev; |
3269 | codec->driver = codec_drv; | 3271 | codec->driver = codec_drv; |
3270 | codec->num_dai = num_dai; | 3272 | codec->num_dai = num_dai; |
diff --git a/sound/soc/soc-dapm.c b/sound/soc/soc-dapm.c index d67c637557a7..4a440b52dd7a 100644 --- a/sound/soc/soc-dapm.c +++ b/sound/soc/soc-dapm.c | |||
@@ -443,6 +443,11 @@ static int dapm_new_mixer(struct snd_soc_dapm_widget *w) | |||
443 | if (path->name != (char *)w->kcontrol_news[i].name) | 443 | if (path->name != (char *)w->kcontrol_news[i].name) |
444 | continue; | 444 | continue; |
445 | 445 | ||
446 | if (w->kcontrols[i]) { | ||
447 | path->kcontrol = w->kcontrols[i]; | ||
448 | continue; | ||
449 | } | ||
450 | |||
446 | wlistsize = sizeof(struct snd_soc_dapm_widget_list) + | 451 | wlistsize = sizeof(struct snd_soc_dapm_widget_list) + |
447 | sizeof(struct snd_soc_dapm_widget *), | 452 | sizeof(struct snd_soc_dapm_widget *), |
448 | wlist = kzalloc(wlistsize, GFP_KERNEL); | 453 | wlist = kzalloc(wlistsize, GFP_KERNEL); |
@@ -579,8 +584,8 @@ static int dapm_new_mux(struct snd_soc_dapm_widget *w) | |||
579 | name + prefix_len, prefix); | 584 | name + prefix_len, prefix); |
580 | ret = snd_ctl_add(card, kcontrol); | 585 | ret = snd_ctl_add(card, kcontrol); |
581 | if (ret < 0) { | 586 | if (ret < 0) { |
582 | dev_err(dapm->dev, | 587 | dev_err(dapm->dev, "failed to add kcontrol %s: %d\n", |
583 | "asoc: failed to add kcontrol %s\n", w->name); | 588 | w->name, ret); |
584 | kfree(wlist); | 589 | kfree(wlist); |
585 | return ret; | 590 | return ret; |
586 | } | 591 | } |
@@ -1556,7 +1561,6 @@ static int dapm_mixer_update_power(struct snd_soc_dapm_widget *widget, | |||
1556 | /* found, now check type */ | 1561 | /* found, now check type */ |
1557 | found = 1; | 1562 | found = 1; |
1558 | path->connect = connect; | 1563 | path->connect = connect; |
1559 | break; | ||
1560 | } | 1564 | } |
1561 | 1565 | ||
1562 | if (found) | 1566 | if (found) |
@@ -2584,7 +2588,7 @@ static void soc_dapm_stream_event(struct snd_soc_dapm_context *dapm, | |||
2584 | { | 2588 | { |
2585 | if (!w->sname || w->dapm != dapm) | 2589 | if (!w->sname || w->dapm != dapm) |
2586 | continue; | 2590 | continue; |
2587 | dev_dbg(w->dapm->dev, "widget %s\n %s stream %s event %d\n", | 2591 | dev_vdbg(w->dapm->dev, "widget %s\n %s stream %s event %d\n", |
2588 | w->name, w->sname, stream, event); | 2592 | w->name, w->sname, stream, event); |
2589 | if (strstr(w->sname, stream)) { | 2593 | if (strstr(w->sname, stream)) { |
2590 | switch(event) { | 2594 | switch(event) { |
@@ -2604,6 +2608,10 @@ static void soc_dapm_stream_event(struct snd_soc_dapm_context *dapm, | |||
2604 | } | 2608 | } |
2605 | 2609 | ||
2606 | dapm_power_widgets(dapm, event); | 2610 | dapm_power_widgets(dapm, event); |
2611 | |||
2612 | /* do we need to notify any clients that DAPM stream is complete */ | ||
2613 | if (dapm->stream_event) | ||
2614 | dapm->stream_event(dapm, event); | ||
2607 | } | 2615 | } |
2608 | 2616 | ||
2609 | /** | 2617 | /** |
diff --git a/sound/soc/soc-io.c b/sound/soc/soc-io.c index a62f7dd4ba96..66fcccd79efe 100644 --- a/sound/soc/soc-io.c +++ b/sound/soc/soc-io.c | |||
@@ -13,26 +13,14 @@ | |||
13 | 13 | ||
14 | #include <linux/i2c.h> | 14 | #include <linux/i2c.h> |
15 | #include <linux/spi/spi.h> | 15 | #include <linux/spi/spi.h> |
16 | #include <linux/regmap.h> | ||
16 | #include <sound/soc.h> | 17 | #include <sound/soc.h> |
17 | 18 | ||
18 | #include <trace/events/asoc.h> | 19 | #include <trace/events/asoc.h> |
19 | 20 | ||
20 | #ifdef CONFIG_SPI_MASTER | 21 | #ifdef CONFIG_REGMAP |
21 | static int do_spi_write(void *control, const char *data, int len) | 22 | static int hw_write(struct snd_soc_codec *codec, unsigned int reg, |
22 | { | 23 | unsigned int value) |
23 | struct spi_device *spi = control; | ||
24 | int ret; | ||
25 | |||
26 | ret = spi_write(spi, data, len); | ||
27 | if (ret < 0) | ||
28 | return ret; | ||
29 | |||
30 | return len; | ||
31 | } | ||
32 | #endif | ||
33 | |||
34 | static int do_hw_write(struct snd_soc_codec *codec, unsigned int reg, | ||
35 | unsigned int value, const void *data, int len) | ||
36 | { | 24 | { |
37 | int ret; | 25 | int ret; |
38 | 26 | ||
@@ -49,13 +37,7 @@ static int do_hw_write(struct snd_soc_codec *codec, unsigned int reg, | |||
49 | return 0; | 37 | return 0; |
50 | } | 38 | } |
51 | 39 | ||
52 | ret = codec->hw_write(codec->control_data, data, len); | 40 | return regmap_write(codec->control_data, reg, value); |
53 | if (ret == len) | ||
54 | return 0; | ||
55 | if (ret < 0) | ||
56 | return ret; | ||
57 | else | ||
58 | return -EIO; | ||
59 | } | 41 | } |
60 | 42 | ||
61 | static unsigned int hw_read(struct snd_soc_codec *codec, unsigned int reg) | 43 | static unsigned int hw_read(struct snd_soc_codec *codec, unsigned int reg) |
@@ -69,8 +51,11 @@ static unsigned int hw_read(struct snd_soc_codec *codec, unsigned int reg) | |||
69 | if (codec->cache_only) | 51 | if (codec->cache_only) |
70 | return -1; | 52 | return -1; |
71 | 53 | ||
72 | BUG_ON(!codec->hw_read); | 54 | ret = regmap_read(codec->control_data, reg, &val); |
73 | return codec->hw_read(codec, reg); | 55 | if (ret == 0) |
56 | return val; | ||
57 | else | ||
58 | return ret; | ||
74 | } | 59 | } |
75 | 60 | ||
76 | ret = snd_soc_cache_read(codec, reg, &val); | 61 | ret = snd_soc_cache_read(codec, reg, &val); |
@@ -79,202 +64,18 @@ static unsigned int hw_read(struct snd_soc_codec *codec, unsigned int reg) | |||
79 | return val; | 64 | return val; |
80 | } | 65 | } |
81 | 66 | ||
82 | static int snd_soc_4_12_write(struct snd_soc_codec *codec, unsigned int reg, | ||
83 | unsigned int value) | ||
84 | { | ||
85 | u16 data; | ||
86 | |||
87 | data = cpu_to_be16((reg << 12) | (value & 0xffffff)); | ||
88 | |||
89 | return do_hw_write(codec, reg, value, &data, 2); | ||
90 | } | ||
91 | |||
92 | static int snd_soc_7_9_write(struct snd_soc_codec *codec, unsigned int reg, | ||
93 | unsigned int value) | ||
94 | { | ||
95 | u16 data; | ||
96 | |||
97 | data = cpu_to_be16((reg << 9) | (value & 0x1ff)); | ||
98 | |||
99 | return do_hw_write(codec, reg, value, &data, 2); | ||
100 | } | ||
101 | |||
102 | static int snd_soc_8_8_write(struct snd_soc_codec *codec, unsigned int reg, | ||
103 | unsigned int value) | ||
104 | { | ||
105 | u8 data[2]; | ||
106 | |||
107 | reg &= 0xff; | ||
108 | data[0] = reg; | ||
109 | data[1] = value & 0xff; | ||
110 | |||
111 | return do_hw_write(codec, reg, value, data, 2); | ||
112 | } | ||
113 | |||
114 | static int snd_soc_8_16_write(struct snd_soc_codec *codec, unsigned int reg, | ||
115 | unsigned int value) | ||
116 | { | ||
117 | u8 data[3]; | ||
118 | u16 val = cpu_to_be16(value); | ||
119 | |||
120 | data[0] = reg; | ||
121 | memcpy(&data[1], &val, sizeof(val)); | ||
122 | |||
123 | return do_hw_write(codec, reg, value, data, 3); | ||
124 | } | ||
125 | |||
126 | #if defined(CONFIG_I2C) || (defined(CONFIG_I2C_MODULE) && defined(MODULE)) | ||
127 | static unsigned int do_i2c_read(struct snd_soc_codec *codec, | ||
128 | void *reg, int reglen, | ||
129 | void *data, int datalen) | ||
130 | { | ||
131 | struct i2c_msg xfer[2]; | ||
132 | int ret; | ||
133 | struct i2c_client *client = codec->control_data; | ||
134 | |||
135 | /* Write register */ | ||
136 | xfer[0].addr = client->addr; | ||
137 | xfer[0].flags = 0; | ||
138 | xfer[0].len = reglen; | ||
139 | xfer[0].buf = reg; | ||
140 | |||
141 | /* Read data */ | ||
142 | xfer[1].addr = client->addr; | ||
143 | xfer[1].flags = I2C_M_RD; | ||
144 | xfer[1].len = datalen; | ||
145 | xfer[1].buf = data; | ||
146 | |||
147 | ret = i2c_transfer(client->adapter, xfer, 2); | ||
148 | if (ret == 2) | ||
149 | return 0; | ||
150 | else if (ret < 0) | ||
151 | return ret; | ||
152 | else | ||
153 | return -EIO; | ||
154 | } | ||
155 | #endif | ||
156 | |||
157 | #if defined(CONFIG_I2C) || (defined(CONFIG_I2C_MODULE) && defined(MODULE)) | ||
158 | static unsigned int snd_soc_8_8_read_i2c(struct snd_soc_codec *codec, | ||
159 | unsigned int r) | ||
160 | { | ||
161 | u8 reg = r; | ||
162 | u8 data; | ||
163 | int ret; | ||
164 | |||
165 | ret = do_i2c_read(codec, ®, 1, &data, 1); | ||
166 | if (ret < 0) | ||
167 | return 0; | ||
168 | return data; | ||
169 | } | ||
170 | #else | ||
171 | #define snd_soc_8_8_read_i2c NULL | ||
172 | #endif | ||
173 | |||
174 | #if defined(CONFIG_I2C) || (defined(CONFIG_I2C_MODULE) && defined(MODULE)) | ||
175 | static unsigned int snd_soc_8_16_read_i2c(struct snd_soc_codec *codec, | ||
176 | unsigned int r) | ||
177 | { | ||
178 | u8 reg = r; | ||
179 | u16 data; | ||
180 | int ret; | ||
181 | |||
182 | ret = do_i2c_read(codec, ®, 1, &data, 2); | ||
183 | if (ret < 0) | ||
184 | return 0; | ||
185 | return (data >> 8) | ((data & 0xff) << 8); | ||
186 | } | ||
187 | #else | ||
188 | #define snd_soc_8_16_read_i2c NULL | ||
189 | #endif | ||
190 | |||
191 | #if defined(CONFIG_I2C) || (defined(CONFIG_I2C_MODULE) && defined(MODULE)) | ||
192 | static unsigned int snd_soc_16_8_read_i2c(struct snd_soc_codec *codec, | ||
193 | unsigned int r) | ||
194 | { | ||
195 | u16 reg = r; | ||
196 | u8 data; | ||
197 | int ret; | ||
198 | |||
199 | ret = do_i2c_read(codec, ®, 2, &data, 1); | ||
200 | if (ret < 0) | ||
201 | return 0; | ||
202 | return data; | ||
203 | } | ||
204 | #else | ||
205 | #define snd_soc_16_8_read_i2c NULL | ||
206 | #endif | ||
207 | |||
208 | #if defined(CONFIG_SPI_MASTER) | ||
209 | static unsigned int snd_soc_16_8_read_spi(struct snd_soc_codec *codec, | ||
210 | unsigned int r) | ||
211 | { | ||
212 | struct spi_device *spi = codec->control_data; | ||
213 | |||
214 | const u16 reg = cpu_to_be16(r | 0x100); | ||
215 | u8 data; | ||
216 | int ret; | ||
217 | |||
218 | ret = spi_write_then_read(spi, ®, 2, &data, 1); | ||
219 | if (ret < 0) | ||
220 | return 0; | ||
221 | return data; | ||
222 | } | ||
223 | #else | ||
224 | #define snd_soc_16_8_read_spi NULL | ||
225 | #endif | ||
226 | |||
227 | static int snd_soc_16_8_write(struct snd_soc_codec *codec, unsigned int reg, | ||
228 | unsigned int value) | ||
229 | { | ||
230 | u8 data[3]; | ||
231 | u16 rval = cpu_to_be16(reg); | ||
232 | |||
233 | memcpy(data, &rval, sizeof(rval)); | ||
234 | data[2] = value; | ||
235 | |||
236 | return do_hw_write(codec, reg, value, data, 3); | ||
237 | } | ||
238 | |||
239 | #if defined(CONFIG_I2C) || (defined(CONFIG_I2C_MODULE) && defined(MODULE)) | ||
240 | static unsigned int snd_soc_16_16_read_i2c(struct snd_soc_codec *codec, | ||
241 | unsigned int r) | ||
242 | { | ||
243 | u16 reg = cpu_to_be16(r); | ||
244 | u16 data; | ||
245 | int ret; | ||
246 | |||
247 | ret = do_i2c_read(codec, ®, 2, &data, 2); | ||
248 | if (ret < 0) | ||
249 | return 0; | ||
250 | return be16_to_cpu(data); | ||
251 | } | ||
252 | #else | ||
253 | #define snd_soc_16_16_read_i2c NULL | ||
254 | #endif | ||
255 | |||
256 | static int snd_soc_16_16_write(struct snd_soc_codec *codec, unsigned int reg, | ||
257 | unsigned int value) | ||
258 | { | ||
259 | u16 data[2]; | ||
260 | |||
261 | data[0] = cpu_to_be16(reg); | ||
262 | data[1] = cpu_to_be16(value); | ||
263 | |||
264 | return do_hw_write(codec, reg, value, data, sizeof(data)); | ||
265 | } | ||
266 | |||
267 | /* Primitive bulk write support for soc-cache. The data pointed to by | 67 | /* Primitive bulk write support for soc-cache. The data pointed to by |
268 | * `data' needs to already be in the form the hardware expects | 68 | * `data' needs to already be in the form the hardware expects. Any |
269 | * including any leading register specific data. Any data written | 69 | * data written through this function will not go through the cache as |
270 | * through this function will not go through the cache as it only | 70 | * it only handles writing to volatile or out of bounds registers. |
271 | * handles writing to volatile or out of bounds registers. | 71 | * |
72 | * This is currently only supported for devices using the regmap API | ||
73 | * wrappers. | ||
272 | */ | 74 | */ |
273 | static int snd_soc_hw_bulk_write_raw(struct snd_soc_codec *codec, unsigned int reg, | 75 | static int snd_soc_hw_bulk_write_raw(struct snd_soc_codec *codec, |
76 | unsigned int reg, | ||
274 | const void *data, size_t len) | 77 | const void *data, size_t len) |
275 | { | 78 | { |
276 | int ret; | ||
277 | |||
278 | /* To ensure that we don't get out of sync with the cache, check | 79 | /* To ensure that we don't get out of sync with the cache, check |
279 | * whether the base register is volatile or if we've directly asked | 80 | * whether the base register is volatile or if we've directly asked |
280 | * to bypass the cache. Out of bounds registers are considered | 81 | * to bypass the cache. Out of bounds registers are considered |
@@ -285,68 +86,9 @@ static int snd_soc_hw_bulk_write_raw(struct snd_soc_codec *codec, unsigned int r | |||
285 | && reg < codec->driver->reg_cache_size) | 86 | && reg < codec->driver->reg_cache_size) |
286 | return -EINVAL; | 87 | return -EINVAL; |
287 | 88 | ||
288 | switch (codec->control_type) { | 89 | return regmap_raw_write(codec->control_data, reg, data, len); |
289 | #if defined(CONFIG_I2C) || (defined(CONFIG_I2C_MODULE) && defined(MODULE)) | ||
290 | case SND_SOC_I2C: | ||
291 | ret = i2c_master_send(to_i2c_client(codec->dev), data, len); | ||
292 | break; | ||
293 | #endif | ||
294 | #if defined(CONFIG_SPI_MASTER) | ||
295 | case SND_SOC_SPI: | ||
296 | ret = spi_write(to_spi_device(codec->dev), data, len); | ||
297 | break; | ||
298 | #endif | ||
299 | default: | ||
300 | BUG(); | ||
301 | } | ||
302 | |||
303 | if (ret == len) | ||
304 | return 0; | ||
305 | if (ret < 0) | ||
306 | return ret; | ||
307 | else | ||
308 | return -EIO; | ||
309 | } | 90 | } |
310 | 91 | ||
311 | static struct { | ||
312 | int addr_bits; | ||
313 | int data_bits; | ||
314 | int (*write)(struct snd_soc_codec *codec, unsigned int, unsigned int); | ||
315 | unsigned int (*read)(struct snd_soc_codec *, unsigned int); | ||
316 | unsigned int (*i2c_read)(struct snd_soc_codec *, unsigned int); | ||
317 | unsigned int (*spi_read)(struct snd_soc_codec *, unsigned int); | ||
318 | } io_types[] = { | ||
319 | { | ||
320 | .addr_bits = 4, .data_bits = 12, | ||
321 | .write = snd_soc_4_12_write, | ||
322 | }, | ||
323 | { | ||
324 | .addr_bits = 7, .data_bits = 9, | ||
325 | .write = snd_soc_7_9_write, | ||
326 | }, | ||
327 | { | ||
328 | .addr_bits = 8, .data_bits = 8, | ||
329 | .write = snd_soc_8_8_write, | ||
330 | .i2c_read = snd_soc_8_8_read_i2c, | ||
331 | }, | ||
332 | { | ||
333 | .addr_bits = 8, .data_bits = 16, | ||
334 | .write = snd_soc_8_16_write, | ||
335 | .i2c_read = snd_soc_8_16_read_i2c, | ||
336 | }, | ||
337 | { | ||
338 | .addr_bits = 16, .data_bits = 8, | ||
339 | .write = snd_soc_16_8_write, | ||
340 | .i2c_read = snd_soc_16_8_read_i2c, | ||
341 | .spi_read = snd_soc_16_8_read_spi, | ||
342 | }, | ||
343 | { | ||
344 | .addr_bits = 16, .data_bits = 16, | ||
345 | .write = snd_soc_16_16_write, | ||
346 | .i2c_read = snd_soc_16_16_read_i2c, | ||
347 | }, | ||
348 | }; | ||
349 | |||
350 | /** | 92 | /** |
351 | * snd_soc_codec_set_cache_io: Set up standard I/O functions. | 93 | * snd_soc_codec_set_cache_io: Set up standard I/O functions. |
352 | * | 94 | * |
@@ -370,50 +112,51 @@ int snd_soc_codec_set_cache_io(struct snd_soc_codec *codec, | |||
370 | int addr_bits, int data_bits, | 112 | int addr_bits, int data_bits, |
371 | enum snd_soc_control_type control) | 113 | enum snd_soc_control_type control) |
372 | { | 114 | { |
373 | int i; | 115 | struct regmap_config config; |
374 | |||
375 | for (i = 0; i < ARRAY_SIZE(io_types); i++) | ||
376 | if (io_types[i].addr_bits == addr_bits && | ||
377 | io_types[i].data_bits == data_bits) | ||
378 | break; | ||
379 | if (i == ARRAY_SIZE(io_types)) { | ||
380 | printk(KERN_ERR | ||
381 | "No I/O functions for %d bit address %d bit data\n", | ||
382 | addr_bits, data_bits); | ||
383 | return -EINVAL; | ||
384 | } | ||
385 | 116 | ||
386 | codec->write = io_types[i].write; | 117 | memset(&config, 0, sizeof(config)); |
118 | codec->write = hw_write; | ||
387 | codec->read = hw_read; | 119 | codec->read = hw_read; |
388 | codec->bulk_write_raw = snd_soc_hw_bulk_write_raw; | 120 | codec->bulk_write_raw = snd_soc_hw_bulk_write_raw; |
389 | 121 | ||
122 | config.reg_bits = addr_bits; | ||
123 | config.val_bits = data_bits; | ||
124 | |||
390 | switch (control) { | 125 | switch (control) { |
126 | #if defined(CONFIG_REGMAP_I2C) || defined(CONFIG_REGMAP_I2C_MODULE) | ||
391 | case SND_SOC_I2C: | 127 | case SND_SOC_I2C: |
392 | #if defined(CONFIG_I2C) || (defined(CONFIG_I2C_MODULE) && defined(MODULE)) | 128 | codec->control_data = regmap_init_i2c(to_i2c_client(codec->dev), |
393 | codec->hw_write = (hw_write_t)i2c_master_send; | 129 | &config); |
394 | #endif | ||
395 | if (io_types[i].i2c_read) | ||
396 | codec->hw_read = io_types[i].i2c_read; | ||
397 | |||
398 | codec->control_data = container_of(codec->dev, | ||
399 | struct i2c_client, | ||
400 | dev); | ||
401 | break; | 130 | break; |
131 | #endif | ||
402 | 132 | ||
133 | #if defined(CONFIG_REGMAP_SPI) || defined(CONFIG_REGMAP_SPI_MODULE) | ||
403 | case SND_SOC_SPI: | 134 | case SND_SOC_SPI: |
404 | #ifdef CONFIG_SPI_MASTER | 135 | codec->control_data = regmap_init_spi(to_spi_device(codec->dev), |
405 | codec->hw_write = do_spi_write; | 136 | &config); |
137 | break; | ||
406 | #endif | 138 | #endif |
407 | if (io_types[i].spi_read) | ||
408 | codec->hw_read = io_types[i].spi_read; | ||
409 | 139 | ||
410 | codec->control_data = container_of(codec->dev, | 140 | case SND_SOC_REGMAP: |
411 | struct spi_device, | 141 | /* Device has made its own regmap arrangements */ |
412 | dev); | ||
413 | break; | 142 | break; |
143 | |||
144 | default: | ||
145 | return -EINVAL; | ||
414 | } | 146 | } |
415 | 147 | ||
148 | if (IS_ERR(codec->control_data)) | ||
149 | return PTR_ERR(codec->control_data); | ||
150 | |||
416 | return 0; | 151 | return 0; |
417 | } | 152 | } |
418 | EXPORT_SYMBOL_GPL(snd_soc_codec_set_cache_io); | 153 | EXPORT_SYMBOL_GPL(snd_soc_codec_set_cache_io); |
419 | 154 | #else | |
155 | int snd_soc_codec_set_cache_io(struct snd_soc_codec *codec, | ||
156 | int addr_bits, int data_bits, | ||
157 | enum snd_soc_control_type control) | ||
158 | { | ||
159 | return -ENOTSUPP; | ||
160 | } | ||
161 | EXPORT_SYMBOL_GPL(snd_soc_codec_set_cache_io); | ||
162 | #endif | ||
diff --git a/sound/soc/soc-pcm.c b/sound/soc/soc-pcm.c index 2879c883eebc..1aee9fcdf650 100644 --- a/sound/soc/soc-pcm.c +++ b/sound/soc/soc-pcm.c | |||
@@ -27,8 +27,6 @@ | |||
27 | #include <sound/soc.h> | 27 | #include <sound/soc.h> |
28 | #include <sound/initval.h> | 28 | #include <sound/initval.h> |
29 | 29 | ||
30 | static DEFINE_MUTEX(pcm_mutex); | ||
31 | |||
32 | static int soc_pcm_apply_symmetry(struct snd_pcm_substream *substream) | 30 | static int soc_pcm_apply_symmetry(struct snd_pcm_substream *substream) |
33 | { | 31 | { |
34 | struct snd_soc_pcm_runtime *rtd = substream->private_data; | 32 | struct snd_soc_pcm_runtime *rtd = substream->private_data; |
diff --git a/sound/soc/txx9/txx9aclc-ac97.c b/sound/soc/txx9/txx9aclc-ac97.c index 743d07b82c06..a4e3f5501847 100644 --- a/sound/soc/txx9/txx9aclc-ac97.c +++ b/sound/soc/txx9/txx9aclc-ac97.c | |||
@@ -201,7 +201,7 @@ static int __devinit txx9aclc_ac97_dev_probe(struct platform_device *pdev) | |||
201 | if (!drvdata->base) | 201 | if (!drvdata->base) |
202 | return -EBUSY; | 202 | return -EBUSY; |
203 | err = devm_request_irq(&pdev->dev, irq, txx9aclc_ac97_irq, | 203 | err = devm_request_irq(&pdev->dev, irq, txx9aclc_ac97_irq, |
204 | IRQF_DISABLED, dev_name(&pdev->dev), drvdata); | 204 | 0, dev_name(&pdev->dev), drvdata); |
205 | if (err < 0) | 205 | if (err < 0) |
206 | return err; | 206 | return err; |
207 | 207 | ||
diff --git a/sound/sparc/amd7930.c b/sound/sparc/amd7930.c index ad7d4d7d9237..f036776380b5 100644 --- a/sound/sparc/amd7930.c +++ b/sound/sparc/amd7930.c | |||
@@ -962,7 +962,7 @@ static int __devinit snd_amd7930_create(struct snd_card *card, | |||
962 | amd7930_idle(amd); | 962 | amd7930_idle(amd); |
963 | 963 | ||
964 | if (request_irq(irq, snd_amd7930_interrupt, | 964 | if (request_irq(irq, snd_amd7930_interrupt, |
965 | IRQF_DISABLED | IRQF_SHARED, "amd7930", amd)) { | 965 | IRQF_SHARED, "amd7930", amd)) { |
966 | snd_printk(KERN_ERR "amd7930-%d: Unable to grab IRQ %d\n", | 966 | snd_printk(KERN_ERR "amd7930-%d: Unable to grab IRQ %d\n", |
967 | dev, irq); | 967 | dev, irq); |
968 | snd_amd7930_free(amd); | 968 | snd_amd7930_free(amd); |