diff options
340 files changed, 9234 insertions, 13384 deletions
diff --git a/arch/arm/mach-davinci/devices.c b/arch/arm/mach-davinci/devices.c index 8b7201e4c79c..de40e9c787e1 100644 --- a/arch/arm/mach-davinci/devices.c +++ b/arch/arm/mach-davinci/devices.c | |||
@@ -295,6 +295,18 @@ static void davinci_init_wdt(void) | |||
295 | 295 | ||
296 | /*-------------------------------------------------------------------------*/ | 296 | /*-------------------------------------------------------------------------*/ |
297 | 297 | ||
298 | struct platform_device davinci_pcm_device = { | ||
299 | .name = "davinci-pcm-audio", | ||
300 | .id = -1, | ||
301 | }; | ||
302 | |||
303 | static void davinci_init_pcm(void) | ||
304 | { | ||
305 | platform_device_register(&davinci_pcm_device); | ||
306 | } | ||
307 | |||
308 | /*-------------------------------------------------------------------------*/ | ||
309 | |||
298 | struct davinci_timer_instance davinci_timer_instance[2] = { | 310 | struct davinci_timer_instance davinci_timer_instance[2] = { |
299 | { | 311 | { |
300 | .base = DAVINCI_TIMER0_BASE, | 312 | .base = DAVINCI_TIMER0_BASE, |
@@ -315,6 +327,7 @@ static int __init davinci_init_devices(void) | |||
315 | /* please keep these calls, and their implementations above, | 327 | /* please keep these calls, and their implementations above, |
316 | * in alphabetical order so they're easier to sort through. | 328 | * in alphabetical order so they're easier to sort through. |
317 | */ | 329 | */ |
330 | davinci_init_pcm(); | ||
318 | davinci_init_wdt(); | 331 | davinci_init_wdt(); |
319 | 332 | ||
320 | return 0; | 333 | return 0; |
diff --git a/arch/arm/mach-ep93xx/core.c b/arch/arm/mach-ep93xx/core.c index b4ee5409eb72..b5261d44b263 100644 --- a/arch/arm/mach-ep93xx/core.c +++ b/arch/arm/mach-ep93xx/core.c | |||
@@ -732,9 +732,15 @@ static struct platform_device ep93xx_i2s_device = { | |||
732 | .resource = ep93xx_i2s_resource, | 732 | .resource = ep93xx_i2s_resource, |
733 | }; | 733 | }; |
734 | 734 | ||
735 | static struct platform_device ep93xx_pcm_device = { | ||
736 | .name = "ep93xx-pcm-audio", | ||
737 | .id = -1, | ||
738 | }; | ||
739 | |||
735 | void __init ep93xx_register_i2s(void) | 740 | void __init ep93xx_register_i2s(void) |
736 | { | 741 | { |
737 | platform_device_register(&ep93xx_i2s_device); | 742 | platform_device_register(&ep93xx_i2s_device); |
743 | platform_device_register(&ep93xx_pcm_device); | ||
738 | } | 744 | } |
739 | 745 | ||
740 | #define EP93XX_SYSCON_DEVCFG_I2S_MASK (EP93XX_SYSCON_DEVCFG_I2SONSSP | \ | 746 | #define EP93XX_SYSCON_DEVCFG_I2S_MASK (EP93XX_SYSCON_DEVCFG_I2SONSSP | \ |
diff --git a/arch/arm/mach-kirkwood/common.c b/arch/arm/mach-kirkwood/common.c index e1f3efedbcf1..07690132cdbf 100644 --- a/arch/arm/mach-kirkwood/common.c +++ b/arch/arm/mach-kirkwood/common.c | |||
@@ -896,10 +896,16 @@ static struct platform_device kirkwood_i2s_device = { | |||
896 | }, | 896 | }, |
897 | }; | 897 | }; |
898 | 898 | ||
899 | static struct platform_device kirkwood_pcm_device = { | ||
900 | .name = "kirkwood-pcm", | ||
901 | .id = -1, | ||
902 | }; | ||
903 | |||
899 | void __init kirkwood_audio_init(void) | 904 | void __init kirkwood_audio_init(void) |
900 | { | 905 | { |
901 | kirkwood_clk_ctrl |= CGC_AUDIO; | 906 | kirkwood_clk_ctrl |= CGC_AUDIO; |
902 | platform_device_register(&kirkwood_i2s_device); | 907 | platform_device_register(&kirkwood_i2s_device); |
908 | platform_device_register(&kirkwood_pcm_device); | ||
903 | } | 909 | } |
904 | 910 | ||
905 | /***************************************************************************** | 911 | /***************************************************************************** |
diff --git a/arch/arm/mach-mx2/clock_imx27.c b/arch/arm/mach-mx2/clock_imx27.c index 0f0823c8b170..379de9c59332 100644 --- a/arch/arm/mach-mx2/clock_imx27.c +++ b/arch/arm/mach-mx2/clock_imx27.c | |||
@@ -653,8 +653,8 @@ static struct clk_lookup lookups[] = { | |||
653 | _REGISTER_CLOCK("mxc-ehci.1", "usb_ahb", usb_clk1) | 653 | _REGISTER_CLOCK("mxc-ehci.1", "usb_ahb", usb_clk1) |
654 | _REGISTER_CLOCK("mxc-ehci.2", "usb", usb_clk) | 654 | _REGISTER_CLOCK("mxc-ehci.2", "usb", usb_clk) |
655 | _REGISTER_CLOCK("mxc-ehci.2", "usb_ahb", usb_clk1) | 655 | _REGISTER_CLOCK("mxc-ehci.2", "usb_ahb", usb_clk1) |
656 | _REGISTER_CLOCK("imx-ssi.0", NULL, ssi1_clk) | 656 | _REGISTER_CLOCK("imx-ssi-dai.0", NULL, ssi1_clk) |
657 | _REGISTER_CLOCK("imx-ssi.1", NULL, ssi2_clk) | 657 | _REGISTER_CLOCK("imx-ssi-dai.1", NULL, ssi2_clk) |
658 | _REGISTER_CLOCK("mxc_nand.0", NULL, nfc_clk) | 658 | _REGISTER_CLOCK("mxc_nand.0", NULL, nfc_clk) |
659 | _REGISTER_CLOCK(NULL, "vpu", vpu_clk) | 659 | _REGISTER_CLOCK(NULL, "vpu", vpu_clk) |
660 | _REGISTER_CLOCK(NULL, "dma", dma_clk) | 660 | _REGISTER_CLOCK(NULL, "dma", dma_clk) |
diff --git a/arch/arm/mach-mx2/devices.c b/arch/arm/mach-mx2/devices.c index a0aeb8a4adc1..2354d67a10db 100644 --- a/arch/arm/mach-mx2/devices.c +++ b/arch/arm/mach-mx2/devices.c | |||
@@ -415,7 +415,7 @@ struct platform_device mxc_usbh2 = { | |||
415 | }; \ | 415 | }; \ |
416 | \ | 416 | \ |
417 | struct platform_device imx_ssi_device ## n = { \ | 417 | struct platform_device imx_ssi_device ## n = { \ |
418 | .name = "imx-ssi", \ | 418 | .name = "imx-ssi-dai", \ |
419 | .id = n, \ | 419 | .id = n, \ |
420 | .num_resources = ARRAY_SIZE(imx_ssi_resources ## n), \ | 420 | .num_resources = ARRAY_SIZE(imx_ssi_resources ## n), \ |
421 | .resource = imx_ssi_resources ## n, \ | 421 | .resource = imx_ssi_resources ## n, \ |
diff --git a/arch/arm/mach-mx3/clock-imx31.c b/arch/arm/mach-mx3/clock-imx31.c index 9a9eb6de6127..9b52a67abf2d 100644 --- a/arch/arm/mach-mx3/clock-imx31.c +++ b/arch/arm/mach-mx3/clock-imx31.c | |||
@@ -558,8 +558,8 @@ static struct clk_lookup lookups[] = { | |||
558 | _REGISTER_CLOCK("mxc_w1.0", NULL, owire_clk) | 558 | _REGISTER_CLOCK("mxc_w1.0", NULL, owire_clk) |
559 | _REGISTER_CLOCK("mxc-mmc.0", NULL, sdhc1_clk) | 559 | _REGISTER_CLOCK("mxc-mmc.0", NULL, sdhc1_clk) |
560 | _REGISTER_CLOCK("mxc-mmc.1", NULL, sdhc2_clk) | 560 | _REGISTER_CLOCK("mxc-mmc.1", NULL, sdhc2_clk) |
561 | _REGISTER_CLOCK("imx-ssi.0", NULL, ssi1_clk) | 561 | _REGISTER_CLOCK("imx-ssi-dai.0", NULL, ssi1_clk) |
562 | _REGISTER_CLOCK("imx-ssi.1", NULL, ssi2_clk) | 562 | _REGISTER_CLOCK("imx-ssi-dai.1", NULL, ssi2_clk) |
563 | _REGISTER_CLOCK(NULL, "firi", firi_clk) | 563 | _REGISTER_CLOCK(NULL, "firi", firi_clk) |
564 | _REGISTER_CLOCK(NULL, "ata", ata_clk) | 564 | _REGISTER_CLOCK(NULL, "ata", ata_clk) |
565 | _REGISTER_CLOCK(NULL, "rtic", rtic_clk) | 565 | _REGISTER_CLOCK(NULL, "rtic", rtic_clk) |
diff --git a/arch/arm/mach-mx3/clock-imx35.c b/arch/arm/mach-mx3/clock-imx35.c index 9f3e943e2232..7b5acd5aa7c1 100644 --- a/arch/arm/mach-mx3/clock-imx35.c +++ b/arch/arm/mach-mx3/clock-imx35.c | |||
@@ -464,8 +464,8 @@ static struct clk_lookup lookups[] = { | |||
464 | _REGISTER_CLOCK(NULL, "sdma", sdma_clk) | 464 | _REGISTER_CLOCK(NULL, "sdma", sdma_clk) |
465 | _REGISTER_CLOCK(NULL, "spba", spba_clk) | 465 | _REGISTER_CLOCK(NULL, "spba", spba_clk) |
466 | _REGISTER_CLOCK(NULL, "spdif", spdif_clk) | 466 | _REGISTER_CLOCK(NULL, "spdif", spdif_clk) |
467 | _REGISTER_CLOCK("imx-ssi.0", NULL, ssi1_clk) | 467 | _REGISTER_CLOCK("imx-ssi-dai.0", NULL, ssi1_clk) |
468 | _REGISTER_CLOCK("imx-ssi.1", NULL, ssi2_clk) | 468 | _REGISTER_CLOCK("imx-ssi-dai.1", NULL, ssi2_clk) |
469 | _REGISTER_CLOCK("imx-uart.0", NULL, uart1_clk) | 469 | _REGISTER_CLOCK("imx-uart.0", NULL, uart1_clk) |
470 | _REGISTER_CLOCK("imx-uart.1", NULL, uart2_clk) | 470 | _REGISTER_CLOCK("imx-uart.1", NULL, uart2_clk) |
471 | _REGISTER_CLOCK("imx-uart.2", NULL, uart3_clk) | 471 | _REGISTER_CLOCK("imx-uart.2", NULL, uart3_clk) |
diff --git a/arch/arm/mach-mx3/devices.c b/arch/arm/mach-mx3/devices.c index db7acd6e9101..27cfc39106a8 100644 --- a/arch/arm/mach-mx3/devices.c +++ b/arch/arm/mach-mx3/devices.c | |||
@@ -562,14 +562,14 @@ static struct resource imx_ssi_resources1[] = { | |||
562 | }; | 562 | }; |
563 | 563 | ||
564 | struct platform_device imx_ssi_device0 = { | 564 | struct platform_device imx_ssi_device0 = { |
565 | .name = "imx-ssi", | 565 | .name = "imx-ssi-dai", |
566 | .id = 0, | 566 | .id = 0, |
567 | .num_resources = ARRAY_SIZE(imx_ssi_resources0), | 567 | .num_resources = ARRAY_SIZE(imx_ssi_resources0), |
568 | .resource = imx_ssi_resources0, | 568 | .resource = imx_ssi_resources0, |
569 | }; | 569 | }; |
570 | 570 | ||
571 | struct platform_device imx_ssi_device1 = { | 571 | struct platform_device imx_ssi_device1 = { |
572 | .name = "imx-ssi", | 572 | .name = "imx-ssi-dai", |
573 | .id = 1, | 573 | .id = 1, |
574 | .num_resources = ARRAY_SIZE(imx_ssi_resources1), | 574 | .num_resources = ARRAY_SIZE(imx_ssi_resources1), |
575 | .resource = imx_ssi_resources1, | 575 | .resource = imx_ssi_resources1, |
diff --git a/arch/arm/mach-omap1/devices.c b/arch/arm/mach-omap1/devices.c index 379100c17639..eb98eb8d3731 100644 --- a/arch/arm/mach-omap1/devices.c +++ b/arch/arm/mach-omap1/devices.c | |||
@@ -25,6 +25,7 @@ | |||
25 | #include <mach/gpio.h> | 25 | #include <mach/gpio.h> |
26 | #include <plat/mmc.h> | 26 | #include <plat/mmc.h> |
27 | #include <plat/omap7xx.h> | 27 | #include <plat/omap7xx.h> |
28 | #include <plat/mcbsp.h> | ||
28 | 29 | ||
29 | /*-------------------------------------------------------------------------*/ | 30 | /*-------------------------------------------------------------------------*/ |
30 | 31 | ||
@@ -267,6 +268,30 @@ static inline void omap_init_sti(void) | |||
267 | static inline void omap_init_sti(void) {} | 268 | static inline void omap_init_sti(void) {} |
268 | #endif | 269 | #endif |
269 | 270 | ||
271 | #if defined(CONFIG_SND_SOC) || defined(CONFIG_SND_SOC_MODULE) | ||
272 | |||
273 | static struct platform_device omap_pcm = { | ||
274 | .name = "omap-pcm-audio", | ||
275 | .id = -1, | ||
276 | }; | ||
277 | |||
278 | OMAP_MCBSP_PLATFORM_DEVICE(1); | ||
279 | OMAP_MCBSP_PLATFORM_DEVICE(2); | ||
280 | OMAP_MCBSP_PLATFORM_DEVICE(3); | ||
281 | |||
282 | static void omap_init_audio(void) | ||
283 | { | ||
284 | platform_device_register(&omap_mcbsp1); | ||
285 | platform_device_register(&omap_mcbsp2); | ||
286 | if (!cpu_is_omap7xx()) | ||
287 | platform_device_register(&omap_mcbsp3); | ||
288 | platform_device_register(&omap_pcm); | ||
289 | } | ||
290 | |||
291 | #else | ||
292 | static inline void omap_init_audio(void) {} | ||
293 | #endif | ||
294 | |||
270 | /*-------------------------------------------------------------------------*/ | 295 | /*-------------------------------------------------------------------------*/ |
271 | 296 | ||
272 | /* | 297 | /* |
@@ -299,6 +324,7 @@ static int __init omap1_init_devices(void) | |||
299 | omap_init_rtc(); | 324 | omap_init_rtc(); |
300 | omap_init_spi100k(); | 325 | omap_init_spi100k(); |
301 | omap_init_sti(); | 326 | omap_init_sti(); |
327 | omap_init_audio(); | ||
302 | 328 | ||
303 | return 0; | 329 | return 0; |
304 | } | 330 | } |
diff --git a/arch/arm/mach-omap2/board-n8x0.c b/arch/arm/mach-omap2/board-n8x0.c index 3ccc34ebdcc7..04df912a7b55 100644 --- a/arch/arm/mach-omap2/board-n8x0.c +++ b/arch/arm/mach-omap2/board-n8x0.c | |||
@@ -20,6 +20,7 @@ | |||
20 | #include <linux/i2c.h> | 20 | #include <linux/i2c.h> |
21 | #include <linux/spi/spi.h> | 21 | #include <linux/spi/spi.h> |
22 | #include <linux/usb/musb.h> | 22 | #include <linux/usb/musb.h> |
23 | #include <sound/tlv320aic3x.h> | ||
23 | 24 | ||
24 | #include <asm/mach/arch.h> | 25 | #include <asm/mach/arch.h> |
25 | #include <asm/mach-types.h> | 26 | #include <asm/mach-types.h> |
@@ -612,11 +613,25 @@ static int n8x0_menelaus_late_init(struct device *dev) | |||
612 | return 0; | 613 | return 0; |
613 | } | 614 | } |
614 | 615 | ||
616 | static struct aic3x_setup_data n810_aic33_setup = { | ||
617 | .gpio_func[0] = AIC3X_GPIO1_FUNC_DISABLED, | ||
618 | .gpio_func[1] = AIC3X_GPIO2_FUNC_DIGITAL_MIC_INPUT, | ||
619 | }; | ||
620 | |||
621 | static struct aic3x_pdata n810_aic33_data = { | ||
622 | .setup = &n810_aic33_setup, | ||
623 | .gpio_reset = -1, | ||
624 | }; | ||
625 | |||
615 | static struct i2c_board_info __initdata n8x0_i2c_board_info_1[] = { | 626 | static struct i2c_board_info __initdata n8x0_i2c_board_info_1[] = { |
616 | { | 627 | { |
617 | I2C_BOARD_INFO("menelaus", 0x72), | 628 | I2C_BOARD_INFO("menelaus", 0x72), |
618 | .irq = INT_24XX_SYS_NIRQ, | 629 | .irq = INT_24XX_SYS_NIRQ, |
619 | }, | 630 | }, |
631 | { | ||
632 | I2C_BOARD_INFO("tlv320aic3x", 0x1b), | ||
633 | .platform_data = &n810_aic33_data, | ||
634 | }, | ||
620 | }; | 635 | }; |
621 | 636 | ||
622 | static struct menelaus_platform_data n8x0_menelaus_platform_data = { | 637 | static struct menelaus_platform_data n8x0_menelaus_platform_data = { |
diff --git a/arch/arm/mach-omap2/board-rx51-peripherals.c b/arch/arm/mach-omap2/board-rx51-peripherals.c index abdf321c2d41..28978c08bced 100644 --- a/arch/arm/mach-omap2/board-rx51-peripherals.c +++ b/arch/arm/mach-omap2/board-rx51-peripherals.c | |||
@@ -23,6 +23,7 @@ | |||
23 | #include <linux/gpio.h> | 23 | #include <linux/gpio.h> |
24 | #include <linux/gpio_keys.h> | 24 | #include <linux/gpio_keys.h> |
25 | #include <linux/mmc/host.h> | 25 | #include <linux/mmc/host.h> |
26 | #include <sound/tlv320aic3x.h> | ||
26 | 27 | ||
27 | #include <plat/mcspi.h> | 28 | #include <plat/mcspi.h> |
28 | #include <plat/mux.h> | 29 | #include <plat/mux.h> |
@@ -686,7 +687,6 @@ static struct twl4030_power_data rx51_t2scripts_data __initdata = { | |||
686 | }; | 687 | }; |
687 | 688 | ||
688 | 689 | ||
689 | |||
690 | static struct twl4030_platform_data rx51_twldata __initdata = { | 690 | static struct twl4030_platform_data rx51_twldata __initdata = { |
691 | .irq_base = TWL4030_IRQ_BASE, | 691 | .irq_base = TWL4030_IRQ_BASE, |
692 | .irq_end = TWL4030_IRQ_END, | 692 | .irq_end = TWL4030_IRQ_END, |
@@ -716,9 +716,21 @@ static struct i2c_board_info __initdata rx51_peripherals_i2c_board_info_1[] = { | |||
716 | }, | 716 | }, |
717 | }; | 717 | }; |
718 | 718 | ||
719 | /* Audio setup data */ | ||
720 | static struct aic3x_setup_data rx51_aic34_setup = { | ||
721 | .gpio_func[0] = AIC3X_GPIO1_FUNC_DISABLED, | ||
722 | .gpio_func[1] = AIC3X_GPIO2_FUNC_DIGITAL_MIC_INPUT, | ||
723 | }; | ||
724 | |||
725 | static struct aic3x_pdata rx51_aic34_data = { | ||
726 | .setup = &rx51_aic34_setup, | ||
727 | .gpio_reset = 60, | ||
728 | }; | ||
729 | |||
719 | static struct i2c_board_info __initdata rx51_peripherals_i2c_board_info_2[] = { | 730 | static struct i2c_board_info __initdata rx51_peripherals_i2c_board_info_2[] = { |
720 | { | 731 | { |
721 | I2C_BOARD_INFO("tlv320aic3x", 0x18), | 732 | I2C_BOARD_INFO("tlv320aic3x", 0x18), |
733 | .platform_data = &rx51_aic34_data, | ||
722 | }, | 734 | }, |
723 | }; | 735 | }; |
724 | 736 | ||
diff --git a/arch/arm/mach-omap2/board-zoom2.c b/arch/arm/mach-omap2/board-zoom2.c index 803ef14cbf2d..410fe006c0f6 100644 --- a/arch/arm/mach-omap2/board-zoom2.c +++ b/arch/arm/mach-omap2/board-zoom2.c | |||
@@ -14,6 +14,7 @@ | |||
14 | #include <linux/platform_device.h> | 14 | #include <linux/platform_device.h> |
15 | #include <linux/input.h> | 15 | #include <linux/input.h> |
16 | #include <linux/gpio.h> | 16 | #include <linux/gpio.h> |
17 | #include <linux/i2c/twl.h> | ||
17 | 18 | ||
18 | #include <asm/mach-types.h> | 19 | #include <asm/mach-types.h> |
19 | #include <asm/mach/arch.h> | 20 | #include <asm/mach/arch.h> |
@@ -34,8 +35,11 @@ static void __init omap_zoom2_init_irq(void) | |||
34 | omap_gpio_init(); | 35 | omap_gpio_init(); |
35 | } | 36 | } |
36 | 37 | ||
37 | /* REVISIT: These audio entries can be removed once MFD code is merged */ | 38 | /* EXTMUTE callback function */ |
38 | #if 0 | 39 | void zoom2_set_hs_extmute(int mute) |
40 | { | ||
41 | gpio_set_value(ZOOM2_HEADSET_EXTMUTE_GPIO, mute); | ||
42 | } | ||
39 | 43 | ||
40 | static struct twl4030_madc_platform_data zoom2_madc_data = { | 44 | static struct twl4030_madc_platform_data zoom2_madc_data = { |
41 | .irq_line = 1, | 45 | .irq_line = 1, |
@@ -43,6 +47,9 @@ static struct twl4030_madc_platform_data zoom2_madc_data = { | |||
43 | 47 | ||
44 | static struct twl4030_codec_audio_data zoom2_audio_data = { | 48 | static struct twl4030_codec_audio_data zoom2_audio_data = { |
45 | .audio_mclk = 26000000, | 49 | .audio_mclk = 26000000, |
50 | .ramp_delay_value = 3, /* 161 ms */ | ||
51 | .hs_extmute = 1, | ||
52 | .set_hs_extmute = zoom2_set_hs_extmute, | ||
46 | }; | 53 | }; |
47 | 54 | ||
48 | static struct twl4030_codec_data zoom2_codec_data = { | 55 | static struct twl4030_codec_data zoom2_codec_data = { |
@@ -64,10 +71,24 @@ static struct twl4030_platform_data zoom2_twldata = { | |||
64 | .vmmc1 = &zoom2_vmmc1, | 71 | .vmmc1 = &zoom2_vmmc1, |
65 | .vmmc2 = &zoom2_vmmc2, | 72 | .vmmc2 = &zoom2_vmmc2, |
66 | .vsim = &zoom2_vsim, | 73 | .vsim = &zoom2_vsim, |
74 | }; | ||
67 | 75 | ||
76 | static struct i2c_board_info __initdata zoom2_i2c_boardinfo[] = { | ||
77 | { | ||
78 | I2C_BOARD_INFO("twl4030", 0x48), | ||
79 | .flags = I2C_CLIENT_WAKE, | ||
80 | .irq = INT_34XX_SYS_NIRQ, | ||
81 | .platform_data = &zoom2_twldata, | ||
82 | }, | ||
68 | }; | 83 | }; |
69 | 84 | ||
70 | #endif | 85 | static int __init omap3_zoom2_i2c_init(void) |
86 | { | ||
87 | omap_register_i2c_bus(1, 2600, zoom2_i2c_boardinfo, | ||
88 | ARRAY_SIZE(zoom2_i2c_boardinfo)); | ||
89 | return 0; | ||
90 | } | ||
91 | |||
71 | 92 | ||
72 | #ifdef CONFIG_OMAP_MUX | 93 | #ifdef CONFIG_OMAP_MUX |
73 | static struct omap_board_mux board_mux[] __initdata = { | 94 | static struct omap_board_mux board_mux[] __initdata = { |
@@ -81,6 +102,7 @@ static void __init omap_zoom2_init(void) | |||
81 | { | 102 | { |
82 | omap3_mux_init(board_mux, OMAP_PACKAGE_CBB); | 103 | omap3_mux_init(board_mux, OMAP_PACKAGE_CBB); |
83 | zoom_peripherals_init(); | 104 | zoom_peripherals_init(); |
105 | omap3_zoom2_i2c_init(); | ||
84 | zoom_debugboard_init(); | 106 | zoom_debugboard_init(); |
85 | } | 107 | } |
86 | 108 | ||
diff --git a/arch/arm/mach-omap2/devices.c b/arch/arm/mach-omap2/devices.c index 03e6c9ed82a4..f9a5961d23a7 100644 --- a/arch/arm/mach-omap2/devices.c +++ b/arch/arm/mach-omap2/devices.c | |||
@@ -29,6 +29,7 @@ | |||
29 | #include <mach/gpio.h> | 29 | #include <mach/gpio.h> |
30 | #include <plat/mmc.h> | 30 | #include <plat/mmc.h> |
31 | #include <plat/dma.h> | 31 | #include <plat/dma.h> |
32 | #include <plat/mcbsp.h> | ||
32 | 33 | ||
33 | #include "mux.h" | 34 | #include "mux.h" |
34 | 35 | ||
@@ -289,6 +290,43 @@ static inline void omap_init_sti(void) | |||
289 | static inline void omap_init_sti(void) {} | 290 | static inline void omap_init_sti(void) {} |
290 | #endif | 291 | #endif |
291 | 292 | ||
293 | #if defined(CONFIG_SND_SOC) || defined(CONFIG_SND_SOC_MODULE) | ||
294 | |||
295 | static struct platform_device omap_pcm = { | ||
296 | .name = "omap-pcm-audio", | ||
297 | .id = -1, | ||
298 | }; | ||
299 | |||
300 | /* | ||
301 | * OMAP2420 has 2 McBSP ports | ||
302 | * OMAP2430 has 5 McBSP ports | ||
303 | * OMAP3 has 5 McBSP ports | ||
304 | * OMAP4 has 4 McBSP ports | ||
305 | */ | ||
306 | OMAP_MCBSP_PLATFORM_DEVICE(1); | ||
307 | OMAP_MCBSP_PLATFORM_DEVICE(2); | ||
308 | OMAP_MCBSP_PLATFORM_DEVICE(3); | ||
309 | OMAP_MCBSP_PLATFORM_DEVICE(4); | ||
310 | OMAP_MCBSP_PLATFORM_DEVICE(5); | ||
311 | |||
312 | static void omap_init_audio(void) | ||
313 | { | ||
314 | platform_device_register(&omap_mcbsp1); | ||
315 | platform_device_register(&omap_mcbsp2); | ||
316 | if (cpu_is_omap243x() || cpu_is_omap34xx() || cpu_is_omap44xx()) { | ||
317 | platform_device_register(&omap_mcbsp3); | ||
318 | platform_device_register(&omap_mcbsp4); | ||
319 | } | ||
320 | if (cpu_is_omap243x() || cpu_is_omap34xx()) | ||
321 | platform_device_register(&omap_mcbsp5); | ||
322 | |||
323 | platform_device_register(&omap_pcm); | ||
324 | } | ||
325 | |||
326 | #else | ||
327 | static inline void omap_init_audio(void) {} | ||
328 | #endif | ||
329 | |||
292 | #if defined(CONFIG_SPI_OMAP24XX) || defined(CONFIG_SPI_OMAP24XX_MODULE) | 330 | #if defined(CONFIG_SPI_OMAP24XX) || defined(CONFIG_SPI_OMAP24XX_MODULE) |
293 | 331 | ||
294 | #include <plat/mcspi.h> | 332 | #include <plat/mcspi.h> |
@@ -901,6 +939,7 @@ static int __init omap2_init_devices(void) | |||
901 | * in alphabetical order so they're easier to sort through. | 939 | * in alphabetical order so they're easier to sort through. |
902 | */ | 940 | */ |
903 | omap_hsmmc_reset(); | 941 | omap_hsmmc_reset(); |
942 | omap_init_audio(); | ||
904 | omap_init_camera(); | 943 | omap_init_camera(); |
905 | omap_init_mbox(); | 944 | omap_init_mbox(); |
906 | omap_init_mcspi(); | 945 | omap_init_mcspi(); |
diff --git a/arch/arm/mach-omap2/include/mach/board-zoom.h b/arch/arm/mach-omap2/include/mach/board-zoom.h index c93b29e21b78..b6a010fc8bda 100644 --- a/arch/arm/mach-omap2/include/mach/board-zoom.h +++ b/arch/arm/mach-omap2/include/mach/board-zoom.h | |||
@@ -3,3 +3,5 @@ | |||
3 | */ | 3 | */ |
4 | extern int __init zoom_debugboard_init(void); | 4 | extern int __init zoom_debugboard_init(void); |
5 | extern void __init zoom_peripherals_init(void); | 5 | extern void __init zoom_peripherals_init(void); |
6 | |||
7 | #define ZOOM2_HEADSET_EXTMUTE_GPIO 153 | ||
diff --git a/arch/arm/mach-pxa/devices.c b/arch/arm/mach-pxa/devices.c index 8e10db148f1b..200c31a2730e 100644 --- a/arch/arm/mach-pxa/devices.c +++ b/arch/arm/mach-pxa/devices.c | |||
@@ -340,6 +340,31 @@ struct platform_device pxa_device_i2s = { | |||
340 | .num_resources = ARRAY_SIZE(pxai2s_resources), | 340 | .num_resources = ARRAY_SIZE(pxai2s_resources), |
341 | }; | 341 | }; |
342 | 342 | ||
343 | struct platform_device pxa_device_asoc_ssp1 = { | ||
344 | .name = "pxa-ssp-dai", | ||
345 | .id = 0, | ||
346 | }; | ||
347 | |||
348 | struct platform_device pxa_device_asoc_ssp2= { | ||
349 | .name = "pxa-ssp-dai", | ||
350 | .id = 1, | ||
351 | }; | ||
352 | |||
353 | struct platform_device pxa_device_asoc_ssp3 = { | ||
354 | .name = "pxa-ssp-dai", | ||
355 | .id = 2, | ||
356 | }; | ||
357 | |||
358 | struct platform_device pxa_device_asoc_ssp4 = { | ||
359 | .name = "pxa-ssp-dai", | ||
360 | .id = 3, | ||
361 | }; | ||
362 | |||
363 | struct platform_device pxa_device_asoc_platform = { | ||
364 | .name = "pxa-pcm-audio", | ||
365 | .id = -1, | ||
366 | }; | ||
367 | |||
343 | static u64 pxaficp_dmamask = ~(u32)0; | 368 | static u64 pxaficp_dmamask = ~(u32)0; |
344 | 369 | ||
345 | struct platform_device pxa_device_ficp = { | 370 | struct platform_device pxa_device_ficp = { |
diff --git a/arch/arm/mach-pxa/devices.h b/arch/arm/mach-pxa/devices.h index 93817d99761e..506fd5753ccc 100644 --- a/arch/arm/mach-pxa/devices.h +++ b/arch/arm/mach-pxa/devices.h | |||
@@ -37,4 +37,10 @@ extern struct platform_device pxa3xx_device_i2c_power; | |||
37 | 37 | ||
38 | extern struct platform_device pxa3xx_device_gcu; | 38 | extern struct platform_device pxa3xx_device_gcu; |
39 | 39 | ||
40 | extern struct platform_device pxa_device_asoc_platform; | ||
41 | extern struct platform_device pxa_device_asoc_ssp1; | ||
42 | extern struct platform_device pxa_device_asoc_ssp2; | ||
43 | extern struct platform_device pxa_device_asoc_ssp3; | ||
44 | extern struct platform_device pxa_device_asoc_ssp4; | ||
45 | |||
40 | void __init pxa_register_device(struct platform_device *dev, void *data); | 46 | void __init pxa_register_device(struct platform_device *dev, void *data); |
diff --git a/arch/arm/mach-pxa/pxa27x.c b/arch/arm/mach-pxa/pxa27x.c index 0af36177ff08..465008293a25 100644 --- a/arch/arm/mach-pxa/pxa27x.c +++ b/arch/arm/mach-pxa/pxa27x.c | |||
@@ -384,6 +384,10 @@ void __init pxa27x_set_i2c_power_info(struct i2c_pxa_platform_data *info) | |||
384 | static struct platform_device *devices[] __initdata = { | 384 | static struct platform_device *devices[] __initdata = { |
385 | &pxa27x_device_udc, | 385 | &pxa27x_device_udc, |
386 | &pxa_device_i2s, | 386 | &pxa_device_i2s, |
387 | &pxa_device_asoc_ssp1, | ||
388 | &pxa_device_asoc_ssp2, | ||
389 | &pxa_device_asoc_ssp3, | ||
390 | &pxa_device_asoc_platform, | ||
387 | &sa1100_device_rtc, | 391 | &sa1100_device_rtc, |
388 | &pxa_device_rtc, | 392 | &pxa_device_rtc, |
389 | &pxa27x_device_ssp1, | 393 | &pxa27x_device_ssp1, |
diff --git a/arch/arm/mach-pxa/pxa3xx.c b/arch/arm/mach-pxa/pxa3xx.c index f544e58e1536..f7a3b158ca97 100644 --- a/arch/arm/mach-pxa/pxa3xx.c +++ b/arch/arm/mach-pxa/pxa3xx.c | |||
@@ -597,6 +597,11 @@ void __init pxa3xx_set_i2c_power_info(struct i2c_pxa_platform_data *info) | |||
597 | static struct platform_device *devices[] __initdata = { | 597 | static struct platform_device *devices[] __initdata = { |
598 | &pxa27x_device_udc, | 598 | &pxa27x_device_udc, |
599 | &pxa_device_i2s, | 599 | &pxa_device_i2s, |
600 | &pxa_device_asoc_ssp1, | ||
601 | &pxa_device_asoc_ssp2, | ||
602 | &pxa_device_asoc_ssp3, | ||
603 | &pxa_device_asoc_ssp4, | ||
604 | &pxa_device_asoc_platform, | ||
600 | &sa1100_device_rtc, | 605 | &sa1100_device_rtc, |
601 | &pxa_device_rtc, | 606 | &pxa_device_rtc, |
602 | &pxa27x_device_ssp1, | 607 | &pxa27x_device_ssp1, |
diff --git a/arch/arm/mach-pxa/zylonite.c b/arch/arm/mach-pxa/zylonite.c index c479cbecf784..5ba9d99a1bf6 100644 --- a/arch/arm/mach-pxa/zylonite.c +++ b/arch/arm/mach-pxa/zylonite.c | |||
@@ -45,6 +45,16 @@ int wm9713_irq; | |||
45 | int lcd_id; | 45 | int lcd_id; |
46 | int lcd_orientation; | 46 | int lcd_orientation; |
47 | 47 | ||
48 | struct platform_device pxa_device_wm9713_audio = { | ||
49 | .name = "wm9713-codec", | ||
50 | .id = -1, | ||
51 | }; | ||
52 | |||
53 | static void __init zylonite_init_wm9713_audio(void) | ||
54 | { | ||
55 | platform_device_register(&pxa_device_wm9713_audio); | ||
56 | } | ||
57 | |||
48 | static struct resource smc91x_resources[] = { | 58 | static struct resource smc91x_resources[] = { |
49 | [0] = { | 59 | [0] = { |
50 | .start = ZYLONITE_ETH_PHYS + 0x300, | 60 | .start = ZYLONITE_ETH_PHYS + 0x300, |
@@ -408,6 +418,7 @@ static void __init zylonite_init(void) | |||
408 | zylonite_init_nand(); | 418 | zylonite_init_nand(); |
409 | zylonite_init_leds(); | 419 | zylonite_init_leds(); |
410 | zylonite_init_ohci(); | 420 | zylonite_init_ohci(); |
421 | zylonite_init_wm9713_audio(); | ||
411 | } | 422 | } |
412 | 423 | ||
413 | MACHINE_START(ZYLONITE, "PXA3xx Platform Development Kit (aka Zylonite)") | 424 | MACHINE_START(ZYLONITE, "PXA3xx Platform Development Kit (aka Zylonite)") |
diff --git a/arch/arm/mach-s3c64xx/dev-audio.c b/arch/arm/mach-s3c64xx/dev-audio.c index c3e9e73bd0f9..55ae1b0afae9 100644 --- a/arch/arm/mach-s3c64xx/dev-audio.c +++ b/arch/arm/mach-s3c64xx/dev-audio.c | |||
@@ -333,3 +333,16 @@ void __init s3c64xx_ac97_setup_gpio(int num) | |||
333 | else | 333 | else |
334 | s3c_ac97_pdata.cfg_gpio = s3c64xx_ac97_cfg_gpe; | 334 | s3c_ac97_pdata.cfg_gpio = s3c64xx_ac97_cfg_gpe; |
335 | } | 335 | } |
336 | |||
337 | static u64 s3c_device_audio_dmamask = 0xffffffffUL; | ||
338 | |||
339 | struct platform_device s3c_device_pcm = { | ||
340 | .name = "s3c24xx-pcm-audio", | ||
341 | .id = -1, | ||
342 | .dev = { | ||
343 | .dma_mask = &s3c_device_audio_dmamask, | ||
344 | .coherent_dma_mask = 0xffffffffUL | ||
345 | } | ||
346 | }; | ||
347 | EXPORT_SYMBOL(s3c_device_pcm); | ||
348 | |||
diff --git a/arch/arm/mach-s3c64xx/mach-smdk6410.c b/arch/arm/mach-s3c64xx/mach-smdk6410.c index d9a03555f88b..362fc76ee726 100644 --- a/arch/arm/mach-s3c64xx/mach-smdk6410.c +++ b/arch/arm/mach-s3c64xx/mach-smdk6410.c | |||
@@ -256,6 +256,7 @@ static struct platform_device *smdk6410_devices[] __initdata = { | |||
256 | &s3c_device_fb, | 256 | &s3c_device_fb, |
257 | &s3c_device_ohci, | 257 | &s3c_device_ohci, |
258 | &s3c_device_usb_hsotg, | 258 | &s3c_device_usb_hsotg, |
259 | &s3c_device_pcm, | ||
259 | &s3c64xx_device_iisv4, | 260 | &s3c64xx_device_iisv4, |
260 | 261 | ||
261 | #ifdef CONFIG_REGULATOR | 262 | #ifdef CONFIG_REGULATOR |
diff --git a/arch/arm/plat-mxc/audmux-v2.c b/arch/arm/plat-mxc/audmux-v2.c index 0c2cc5cd4d83..7c479e4fa999 100644 --- a/arch/arm/plat-mxc/audmux-v2.c +++ b/arch/arm/plat-mxc/audmux-v2.c | |||
@@ -49,9 +49,9 @@ static const char *audmux_port_string(int port) | |||
49 | { | 49 | { |
50 | switch (port) { | 50 | switch (port) { |
51 | case MX31_AUDMUX_PORT1_SSI0: | 51 | case MX31_AUDMUX_PORT1_SSI0: |
52 | return "imx-ssi.0"; | 52 | return "imx-ssi-dai.0"; |
53 | case MX31_AUDMUX_PORT2_SSI1: | 53 | case MX31_AUDMUX_PORT2_SSI1: |
54 | return "imx-ssi.1"; | 54 | return "imx-ssi-dai.1"; |
55 | case MX31_AUDMUX_PORT3_SSI_PINS_3: | 55 | case MX31_AUDMUX_PORT3_SSI_PINS_3: |
56 | return "SSI3"; | 56 | return "SSI3"; |
57 | case MX31_AUDMUX_PORT4_SSI_PINS_4: | 57 | case MX31_AUDMUX_PORT4_SSI_PINS_4: |
diff --git a/arch/arm/plat-omap/include/plat/mcbsp.h b/arch/arm/plat-omap/include/plat/mcbsp.h index b4ff6a11a8f2..5b20103e68eb 100644 --- a/arch/arm/plat-omap/include/plat/mcbsp.h +++ b/arch/arm/plat-omap/include/plat/mcbsp.h | |||
@@ -30,6 +30,13 @@ | |||
30 | #include <mach/hardware.h> | 30 | #include <mach/hardware.h> |
31 | #include <plat/clock.h> | 31 | #include <plat/clock.h> |
32 | 32 | ||
33 | /* macro for building platform_device for McBSP ports */ | ||
34 | #define OMAP_MCBSP_PLATFORM_DEVICE(port_nr) \ | ||
35 | static struct platform_device omap_mcbsp##port_nr = { \ | ||
36 | .name = "omap-mcbsp-dai", \ | ||
37 | .id = OMAP_MCBSP##port_nr, \ | ||
38 | } | ||
39 | |||
33 | #define OMAP7XX_MCBSP1_BASE 0xfffb1000 | 40 | #define OMAP7XX_MCBSP1_BASE 0xfffb1000 |
34 | #define OMAP7XX_MCBSP2_BASE 0xfffb1800 | 41 | #define OMAP7XX_MCBSP2_BASE 0xfffb1800 |
35 | 42 | ||
diff --git a/arch/arm/plat-s3c24xx/devs.c b/arch/arm/plat-s3c24xx/devs.c index 452e18438b41..9f8ee5e38615 100644 --- a/arch/arm/plat-s3c24xx/devs.c +++ b/arch/arm/plat-s3c24xx/devs.c | |||
@@ -481,7 +481,7 @@ static struct resource s3c_ac97_resource[] = { | |||
481 | }, | 481 | }, |
482 | }; | 482 | }; |
483 | 483 | ||
484 | static u64 s3c_device_ac97_dmamask = 0xffffffffUL; | 484 | static u64 s3c_device_audio_dmamask = 0xffffffffUL; |
485 | 485 | ||
486 | struct platform_device s3c_device_ac97 = { | 486 | struct platform_device s3c_device_ac97 = { |
487 | .name = "s3c-ac97", | 487 | .name = "s3c-ac97", |
@@ -489,11 +489,37 @@ struct platform_device s3c_device_ac97 = { | |||
489 | .num_resources = ARRAY_SIZE(s3c_ac97_resource), | 489 | .num_resources = ARRAY_SIZE(s3c_ac97_resource), |
490 | .resource = s3c_ac97_resource, | 490 | .resource = s3c_ac97_resource, |
491 | .dev = { | 491 | .dev = { |
492 | .dma_mask = &s3c_device_ac97_dmamask, | 492 | .dma_mask = &s3c_device_audio_dmamask, |
493 | .coherent_dma_mask = 0xffffffffUL | 493 | .coherent_dma_mask = 0xffffffffUL |
494 | } | 494 | } |
495 | }; | 495 | }; |
496 | 496 | ||
497 | EXPORT_SYMBOL(s3c_device_ac97); | 497 | EXPORT_SYMBOL(s3c_device_ac97); |
498 | 498 | ||
499 | /* ASoC PCM DMA */ | ||
500 | |||
501 | struct platform_device s3c_device_pcm = { | ||
502 | .name = "s3c24xx-pcm-audio", | ||
503 | .id = -1, | ||
504 | .dev = { | ||
505 | .dma_mask = &s3c_device_audio_dmamask, | ||
506 | .coherent_dma_mask = 0xffffffffUL | ||
507 | } | ||
508 | }; | ||
509 | |||
510 | EXPORT_SYMBOL(s3c_device_pcm); | ||
511 | |||
512 | /* ASoC I2S */ | ||
513 | |||
514 | struct platform_device s3c2412_device_iis = { | ||
515 | .name = "s3c2412-iis", | ||
516 | .id = -1, | ||
517 | .dev = { | ||
518 | .dma_mask = &s3c_device_audio_dmamask, | ||
519 | .coherent_dma_mask = 0xffffffffUL | ||
520 | } | ||
521 | }; | ||
522 | |||
523 | EXPORT_SYMBOL(s3c2412_device_iis); | ||
524 | |||
499 | #endif // CONFIG_CPU_S32440 | 525 | #endif // CONFIG_CPU_S32440 |
diff --git a/arch/arm/plat-samsung/include/plat/devs.h b/arch/arm/plat-samsung/include/plat/devs.h index e6144e4b9118..9ea6786d459d 100644 --- a/arch/arm/plat-samsung/include/plat/devs.h +++ b/arch/arm/plat-samsung/include/plat/devs.h | |||
@@ -32,6 +32,8 @@ extern struct platform_device s3c64xx_device_iisv4; | |||
32 | extern struct platform_device s3c64xx_device_spi0; | 32 | extern struct platform_device s3c64xx_device_spi0; |
33 | extern struct platform_device s3c64xx_device_spi1; | 33 | extern struct platform_device s3c64xx_device_spi1; |
34 | 34 | ||
35 | extern struct platform_device s3c_device_pcm; | ||
36 | |||
35 | extern struct platform_device s3c64xx_device_pcm0; | 37 | extern struct platform_device s3c64xx_device_pcm0; |
36 | extern struct platform_device s3c64xx_device_pcm1; | 38 | extern struct platform_device s3c64xx_device_pcm1; |
37 | 39 | ||
diff --git a/arch/powerpc/boot/dts/mpc8610_hpcd.dts b/arch/powerpc/boot/dts/mpc8610_hpcd.dts index 9535ce68caae..83c3218cb4da 100644 --- a/arch/powerpc/boot/dts/mpc8610_hpcd.dts +++ b/arch/powerpc/boot/dts/mpc8610_hpcd.dts | |||
@@ -286,6 +286,7 @@ | |||
286 | 286 | ||
287 | ssi@16100 { | 287 | ssi@16100 { |
288 | compatible = "fsl,mpc8610-ssi"; | 288 | compatible = "fsl,mpc8610-ssi"; |
289 | status = "disabled"; | ||
289 | cell-index = <1>; | 290 | cell-index = <1>; |
290 | reg = <0x16100 0x100>; | 291 | reg = <0x16100 0x100>; |
291 | interrupt-parent = <&mpic>; | 292 | interrupt-parent = <&mpic>; |
diff --git a/arch/powerpc/include/asm/immap_86xx.h b/arch/powerpc/include/asm/fsl_guts.h index 0f165e59c326..bebd12463ec9 100644 --- a/arch/powerpc/include/asm/immap_86xx.h +++ b/arch/powerpc/include/asm/fsl_guts.h | |||
@@ -1,5 +1,5 @@ | |||
1 | /** | 1 | /** |
2 | * MPC86xx Internal Memory Map | 2 | * Freecale 85xx and 86xx Global Utilties register set |
3 | * | 3 | * |
4 | * Authors: Jeff Brown | 4 | * Authors: Jeff Brown |
5 | * Timur Tabi <timur@freescale.com> | 5 | * Timur Tabi <timur@freescale.com> |
@@ -10,73 +10,112 @@ | |||
10 | * under the terms of the GNU General Public License as published by the | 10 | * under the terms of the GNU General Public License as published by the |
11 | * Free Software Foundation; either version 2 of the License, or (at your | 11 | * Free Software Foundation; either version 2 of the License, or (at your |
12 | * option) any later version. | 12 | * option) any later version. |
13 | * | ||
14 | * This header file defines structures for various 86xx SOC devices that are | ||
15 | * used by multiple source files. | ||
16 | */ | 13 | */ |
17 | 14 | ||
18 | #ifndef __ASM_POWERPC_IMMAP_86XX_H__ | 15 | #ifndef __ASM_POWERPC_FSL_GUTS_H__ |
19 | #define __ASM_POWERPC_IMMAP_86XX_H__ | 16 | #define __ASM_POWERPC_FSL_GUTS_H__ |
20 | #ifdef __KERNEL__ | 17 | #ifdef __KERNEL__ |
21 | 18 | ||
22 | /* Global Utility Registers */ | 19 | /* |
23 | struct ccsr_guts { | 20 | * These #ifdefs are safe because it's not possible to build a kernel that |
21 | * runs on e500 and e600 cores. | ||
22 | */ | ||
23 | |||
24 | #if !defined(CONFIG_PPC_85xx) && !defined(CONFIG_PPC_86xx) | ||
25 | #error Only 85xx and 86xx SOCs are supported | ||
26 | #endif | ||
27 | |||
28 | /** | ||
29 | * Global Utility Registers. | ||
30 | * | ||
31 | * Not all registers defined in this structure are available on all chips, so | ||
32 | * you are expected to know whether a given register actually exists on your | ||
33 | * chip before you access it. | ||
34 | * | ||
35 | * Also, some registers are similar on different chips but have slightly | ||
36 | * different names. In these cases, one name is chosen to avoid extraneous | ||
37 | * #ifdefs. | ||
38 | */ | ||
39 | #ifdef CONFIG_PPC_85xx | ||
40 | struct ccsr_guts_85xx { | ||
41 | #else | ||
42 | struct ccsr_guts_86xx { | ||
43 | #endif | ||
24 | __be32 porpllsr; /* 0x.0000 - POR PLL Ratio Status Register */ | 44 | __be32 porpllsr; /* 0x.0000 - POR PLL Ratio Status Register */ |
25 | __be32 porbmsr; /* 0x.0004 - POR Boot Mode Status Register */ | 45 | __be32 porbmsr; /* 0x.0004 - POR Boot Mode Status Register */ |
26 | __be32 porimpscr; /* 0x.0008 - POR I/O Impedance Status and Control Register */ | 46 | __be32 porimpscr; /* 0x.0008 - POR I/O Impedance Status and Control Register */ |
27 | __be32 pordevsr; /* 0x.000c - POR I/O Device Status Register */ | 47 | __be32 pordevsr; /* 0x.000c - POR I/O Device Status Register */ |
28 | __be32 pordbgmsr; /* 0x.0010 - POR Debug Mode Status Register */ | 48 | __be32 pordbgmsr; /* 0x.0010 - POR Debug Mode Status Register */ |
29 | u8 res1[0x20 - 0x14]; | 49 | __be32 pordevsr2; /* 0x.0014 - POR device status register 2 */ |
50 | u8 res018[0x20 - 0x18]; | ||
30 | __be32 porcir; /* 0x.0020 - POR Configuration Information Register */ | 51 | __be32 porcir; /* 0x.0020 - POR Configuration Information Register */ |
31 | u8 res2[0x30 - 0x24]; | 52 | u8 res024[0x30 - 0x24]; |
32 | __be32 gpiocr; /* 0x.0030 - GPIO Control Register */ | 53 | __be32 gpiocr; /* 0x.0030 - GPIO Control Register */ |
33 | u8 res3[0x40 - 0x34]; | 54 | u8 res034[0x40 - 0x34]; |
34 | __be32 gpoutdr; /* 0x.0040 - General-Purpose Output Data Register */ | 55 | __be32 gpoutdr; /* 0x.0040 - General-Purpose Output Data Register */ |
35 | u8 res4[0x50 - 0x44]; | 56 | u8 res044[0x50 - 0x44]; |
36 | __be32 gpindr; /* 0x.0050 - General-Purpose Input Data Register */ | 57 | __be32 gpindr; /* 0x.0050 - General-Purpose Input Data Register */ |
37 | u8 res5[0x60 - 0x54]; | 58 | u8 res054[0x60 - 0x54]; |
38 | __be32 pmuxcr; /* 0x.0060 - Alternate Function Signal Multiplex Control */ | 59 | __be32 pmuxcr; /* 0x.0060 - Alternate Function Signal Multiplex Control */ |
39 | u8 res6[0x70 - 0x64]; | 60 | __be32 pmuxcr2; /* 0x.0064 - Alternate function signal multiplex control 2 */ |
61 | __be32 dmuxcr; /* 0x.0068 - DMA Mux Control Register */ | ||
62 | u8 res06c[0x70 - 0x6c]; | ||
40 | __be32 devdisr; /* 0x.0070 - Device Disable Control */ | 63 | __be32 devdisr; /* 0x.0070 - Device Disable Control */ |
41 | __be32 devdisr2; /* 0x.0074 - Device Disable Control 2 */ | 64 | __be32 devdisr2; /* 0x.0074 - Device Disable Control 2 */ |
42 | u8 res7[0x80 - 0x78]; | 65 | u8 res078[0x7c - 0x78]; |
66 | __be32 pmjcr; /* 0x.007c - 4 Power Management Jog Control Register */ | ||
43 | __be32 powmgtcsr; /* 0x.0080 - Power Management Status and Control Register */ | 67 | __be32 powmgtcsr; /* 0x.0080 - Power Management Status and Control Register */ |
44 | u8 res8[0x90 - 0x84]; | 68 | __be32 pmrccr; /* 0x.0084 - Power Management Reset Counter Configuration Register */ |
69 | __be32 pmpdccr; /* 0x.0088 - Power Management Power Down Counter Configuration Register */ | ||
70 | __be32 pmcdr; /* 0x.008c - 4Power management clock disable register */ | ||
45 | __be32 mcpsumr; /* 0x.0090 - Machine Check Summary Register */ | 71 | __be32 mcpsumr; /* 0x.0090 - Machine Check Summary Register */ |
46 | __be32 rstrscr; /* 0x.0094 - Reset Request Status and Control Register */ | 72 | __be32 rstrscr; /* 0x.0094 - Reset Request Status and Control Register */ |
47 | u8 res9[0xA0 - 0x98]; | 73 | __be32 ectrstcr; /* 0x.0098 - Exception reset control register */ |
74 | __be32 autorstsr; /* 0x.009c - Automatic reset status register */ | ||
48 | __be32 pvr; /* 0x.00a0 - Processor Version Register */ | 75 | __be32 pvr; /* 0x.00a0 - Processor Version Register */ |
49 | __be32 svr; /* 0x.00a4 - System Version Register */ | 76 | __be32 svr; /* 0x.00a4 - System Version Register */ |
50 | u8 res10[0xB0 - 0xA8]; | 77 | u8 res0a8[0xb0 - 0xa8]; |
51 | __be32 rstcr; /* 0x.00b0 - Reset Control Register */ | 78 | __be32 rstcr; /* 0x.00b0 - Reset Control Register */ |
52 | u8 res11[0xC0 - 0xB4]; | 79 | u8 res0b4[0xc0 - 0xb4]; |
80 | #ifdef CONFIG_PPC_85xx | ||
81 | __be32 iovselsr; /* 0x.00c0 - I/O voltage select status register */ | ||
82 | #else | ||
53 | __be32 elbcvselcr; /* 0x.00c0 - eLBC Voltage Select Ctrl Reg */ | 83 | __be32 elbcvselcr; /* 0x.00c0 - eLBC Voltage Select Ctrl Reg */ |
54 | u8 res12[0x800 - 0xC4]; | 84 | #endif |
85 | u8 res0c4[0x224 - 0xc4]; | ||
86 | __be32 iodelay1; /* 0x.0224 - IO delay control register 1 */ | ||
87 | __be32 iodelay2; /* 0x.0228 - IO delay control register 2 */ | ||
88 | u8 res22c[0x800 - 0x22c]; | ||
55 | __be32 clkdvdr; /* 0x.0800 - Clock Divide Register */ | 89 | __be32 clkdvdr; /* 0x.0800 - Clock Divide Register */ |
56 | u8 res13[0x900 - 0x804]; | 90 | u8 res804[0x900 - 0x804]; |
57 | __be32 ircr; /* 0x.0900 - Infrared Control Register */ | 91 | __be32 ircr; /* 0x.0900 - Infrared Control Register */ |
58 | u8 res14[0x908 - 0x904]; | 92 | u8 res904[0x908 - 0x904]; |
59 | __be32 dmacr; /* 0x.0908 - DMA Control Register */ | 93 | __be32 dmacr; /* 0x.0908 - DMA Control Register */ |
60 | u8 res15[0x914 - 0x90C]; | 94 | u8 res90c[0x914 - 0x90c]; |
61 | __be32 elbccr; /* 0x.0914 - eLBC Control Register */ | 95 | __be32 elbccr; /* 0x.0914 - eLBC Control Register */ |
62 | u8 res16[0xB20 - 0x918]; | 96 | u8 res918[0xb20 - 0x918]; |
63 | __be32 ddr1clkdr; /* 0x.0b20 - DDR1 Clock Disable Register */ | 97 | __be32 ddr1clkdr; /* 0x.0b20 - DDR1 Clock Disable Register */ |
64 | __be32 ddr2clkdr; /* 0x.0b24 - DDR2 Clock Disable Register */ | 98 | __be32 ddr2clkdr; /* 0x.0b24 - DDR2 Clock Disable Register */ |
65 | __be32 ddrclkdr; /* 0x.0b28 - DDR Clock Disable Register */ | 99 | __be32 ddrclkdr; /* 0x.0b28 - DDR Clock Disable Register */ |
66 | u8 res17[0xE00 - 0xB2C]; | 100 | u8 resb2c[0xe00 - 0xb2c]; |
67 | __be32 clkocr; /* 0x.0e00 - Clock Out Select Register */ | 101 | __be32 clkocr; /* 0x.0e00 - Clock Out Select Register */ |
68 | u8 res18[0xE10 - 0xE04]; | 102 | u8 rese04[0xe10 - 0xe04]; |
69 | __be32 ddrdllcr; /* 0x.0e10 - DDR DLL Control Register */ | 103 | __be32 ddrdllcr; /* 0x.0e10 - DDR DLL Control Register */ |
70 | u8 res19[0xE20 - 0xE14]; | 104 | u8 rese14[0xe20 - 0xe14]; |
71 | __be32 lbcdllcr; /* 0x.0e20 - LBC DLL Control Register */ | 105 | __be32 lbcdllcr; /* 0x.0e20 - LBC DLL Control Register */ |
72 | u8 res20[0xF04 - 0xE24]; | 106 | __be32 cpfor; /* 0x.0e24 - L2 charge pump fuse override register */ |
107 | u8 rese28[0xf04 - 0xe28]; | ||
73 | __be32 srds1cr0; /* 0x.0f04 - SerDes1 Control Register 0 */ | 108 | __be32 srds1cr0; /* 0x.0f04 - SerDes1 Control Register 0 */ |
74 | __be32 srds1cr1; /* 0x.0f08 - SerDes1 Control Register 0 */ | 109 | __be32 srds1cr1; /* 0x.0f08 - SerDes1 Control Register 0 */ |
75 | u8 res21[0xF40 - 0xF0C]; | 110 | u8 resf0c[0xf2c - 0xf0c]; |
76 | __be32 srds2cr0; /* 0x.0f40 - SerDes1 Control Register 0 */ | 111 | __be32 itcr; /* 0x.0f2c - Internal transaction control register */ |
77 | __be32 srds2cr1; /* 0x.0f44 - SerDes1 Control Register 0 */ | 112 | u8 resf30[0xf40 - 0xf30]; |
113 | __be32 srds2cr0; /* 0x.0f40 - SerDes2 Control Register 0 */ | ||
114 | __be32 srds2cr1; /* 0x.0f44 - SerDes2 Control Register 0 */ | ||
78 | } __attribute__ ((packed)); | 115 | } __attribute__ ((packed)); |
79 | 116 | ||
117 | #ifdef CONFIG_PPC_86xx | ||
118 | |||
80 | #define CCSR_GUTS_DMACR_DEV_SSI 0 /* DMA controller/channel set to SSI */ | 119 | #define CCSR_GUTS_DMACR_DEV_SSI 0 /* DMA controller/channel set to SSI */ |
81 | #define CCSR_GUTS_DMACR_DEV_IR 1 /* DMA controller/channel set to IR */ | 120 | #define CCSR_GUTS_DMACR_DEV_IR 1 /* DMA controller/channel set to IR */ |
82 | 121 | ||
@@ -93,7 +132,7 @@ struct ccsr_guts { | |||
93 | * ch: The channel on the DMA controller (0, 1, 2, or 3) | 132 | * ch: The channel on the DMA controller (0, 1, 2, or 3) |
94 | * device: The device to set as the source (CCSR_GUTS_DMACR_DEV_xx) | 133 | * device: The device to set as the source (CCSR_GUTS_DMACR_DEV_xx) |
95 | */ | 134 | */ |
96 | static inline void guts_set_dmacr(struct ccsr_guts __iomem *guts, | 135 | static inline void guts_set_dmacr(struct ccsr_guts_86xx __iomem *guts, |
97 | unsigned int co, unsigned int ch, unsigned int device) | 136 | unsigned int co, unsigned int ch, unsigned int device) |
98 | { | 137 | { |
99 | unsigned int shift = 16 + (8 * (1 - co) + 2 * (3 - ch)); | 138 | unsigned int shift = 16 + (8 * (1 - co) + 2 * (3 - ch)); |
@@ -129,7 +168,7 @@ static inline void guts_set_dmacr(struct ccsr_guts __iomem *guts, | |||
129 | * ch: The channel on the DMA controller (0, 1, 2, or 3) | 168 | * ch: The channel on the DMA controller (0, 1, 2, or 3) |
130 | * value: the new value for the bit (0 or 1) | 169 | * value: the new value for the bit (0 or 1) |
131 | */ | 170 | */ |
132 | static inline void guts_set_pmuxcr_dma(struct ccsr_guts __iomem *guts, | 171 | static inline void guts_set_pmuxcr_dma(struct ccsr_guts_86xx __iomem *guts, |
133 | unsigned int co, unsigned int ch, unsigned int value) | 172 | unsigned int co, unsigned int ch, unsigned int value) |
134 | { | 173 | { |
135 | if ((ch == 0) || (ch == 3)) { | 174 | if ((ch == 0) || (ch == 3)) { |
@@ -152,5 +191,7 @@ static inline void guts_set_pmuxcr_dma(struct ccsr_guts __iomem *guts, | |||
152 | #define CCSR_GUTS_CLKDVDR_SSICLK_MASK 0x000000FF | 191 | #define CCSR_GUTS_CLKDVDR_SSICLK_MASK 0x000000FF |
153 | #define CCSR_GUTS_CLKDVDR_SSICLK(x) ((x) & CCSR_GUTS_CLKDVDR_SSICLK_MASK) | 192 | #define CCSR_GUTS_CLKDVDR_SSICLK(x) ((x) & CCSR_GUTS_CLKDVDR_SSICLK_MASK) |
154 | 193 | ||
155 | #endif /* __ASM_POWERPC_IMMAP_86XX_H__ */ | 194 | #endif |
156 | #endif /* __KERNEL__ */ | 195 | |
196 | #endif | ||
197 | #endif | ||
diff --git a/drivers/input/misc/twl4030-vibra.c b/drivers/input/misc/twl4030-vibra.c index 4f9b2afc24e8..014dd4ad0d4f 100644 --- a/drivers/input/misc/twl4030-vibra.c +++ b/drivers/input/misc/twl4030-vibra.c | |||
@@ -271,7 +271,7 @@ static struct platform_driver twl4030_vibra_driver = { | |||
271 | .probe = twl4030_vibra_probe, | 271 | .probe = twl4030_vibra_probe, |
272 | .remove = __devexit_p(twl4030_vibra_remove), | 272 | .remove = __devexit_p(twl4030_vibra_remove), |
273 | .driver = { | 273 | .driver = { |
274 | .name = "twl4030_codec_vibra", | 274 | .name = "twl4030-vibra", |
275 | .owner = THIS_MODULE, | 275 | .owner = THIS_MODULE, |
276 | #ifdef CONFIG_PM | 276 | #ifdef CONFIG_PM |
277 | .pm = &twl4030_vibra_pm_ops, | 277 | .pm = &twl4030_vibra_pm_ops, |
@@ -291,7 +291,7 @@ static void __exit twl4030_vibra_exit(void) | |||
291 | } | 291 | } |
292 | module_exit(twl4030_vibra_exit); | 292 | module_exit(twl4030_vibra_exit); |
293 | 293 | ||
294 | MODULE_ALIAS("platform:twl4030_codec_vibra"); | 294 | MODULE_ALIAS("platform:twl4030-vibra"); |
295 | 295 | ||
296 | MODULE_DESCRIPTION("TWL4030 Vibra driver"); | 296 | MODULE_DESCRIPTION("TWL4030 Vibra driver"); |
297 | MODULE_LICENSE("GPL"); | 297 | MODULE_LICENSE("GPL"); |
diff --git a/drivers/mfd/twl-core.c b/drivers/mfd/twl-core.c index 720e099e506d..5d0fb60a4c14 100644 --- a/drivers/mfd/twl-core.c +++ b/drivers/mfd/twl-core.c | |||
@@ -698,17 +698,17 @@ add_children(struct twl4030_platform_data *pdata, unsigned long features) | |||
698 | 698 | ||
699 | if (twl_has_codec() && pdata->codec && twl_class_is_4030()) { | 699 | if (twl_has_codec() && pdata->codec && twl_class_is_4030()) { |
700 | sub_chip_id = twl_map[TWL_MODULE_AUDIO_VOICE].sid; | 700 | sub_chip_id = twl_map[TWL_MODULE_AUDIO_VOICE].sid; |
701 | child = add_child(sub_chip_id, "twl4030_codec", | 701 | child = add_child(sub_chip_id, "twl4030-audio", |
702 | pdata->codec, sizeof(*pdata->codec), | 702 | pdata->codec, sizeof(*pdata->codec), |
703 | false, 0, 0); | 703 | false, 0, 0); |
704 | if (IS_ERR(child)) | 704 | if (IS_ERR(child)) |
705 | return PTR_ERR(child); | 705 | return PTR_ERR(child); |
706 | } | 706 | } |
707 | 707 | ||
708 | /* Phoenix*/ | 708 | /* Phoenix codec driver is probed directly atm */ |
709 | if (twl_has_codec() && pdata->codec && twl_class_is_6030()) { | 709 | if (twl_has_codec() && pdata->codec && twl_class_is_6030()) { |
710 | sub_chip_id = twl_map[TWL_MODULE_AUDIO_VOICE].sid; | 710 | sub_chip_id = twl_map[TWL_MODULE_AUDIO_VOICE].sid; |
711 | child = add_child(sub_chip_id, "twl6040_codec", | 711 | child = add_child(sub_chip_id, "twl6040-codec", |
712 | pdata->codec, sizeof(*pdata->codec), | 712 | pdata->codec, sizeof(*pdata->codec), |
713 | false, 0, 0); | 713 | false, 0, 0); |
714 | if (IS_ERR(child)) | 714 | if (IS_ERR(child)) |
diff --git a/drivers/mfd/twl4030-codec.c b/drivers/mfd/twl4030-codec.c index add6f67d8032..9a4b196d6deb 100644 --- a/drivers/mfd/twl4030-codec.c +++ b/drivers/mfd/twl4030-codec.c | |||
@@ -207,14 +207,14 @@ static int __devinit twl4030_codec_probe(struct platform_device *pdev) | |||
207 | 207 | ||
208 | if (pdata->audio) { | 208 | if (pdata->audio) { |
209 | cell = &codec->cells[childs]; | 209 | cell = &codec->cells[childs]; |
210 | cell->name = "twl4030_codec_audio"; | 210 | cell->name = "twl4030-codec"; |
211 | cell->platform_data = pdata->audio; | 211 | cell->platform_data = pdata->audio; |
212 | cell->data_size = sizeof(*pdata->audio); | 212 | cell->data_size = sizeof(*pdata->audio); |
213 | childs++; | 213 | childs++; |
214 | } | 214 | } |
215 | if (pdata->vibra) { | 215 | if (pdata->vibra) { |
216 | cell = &codec->cells[childs]; | 216 | cell = &codec->cells[childs]; |
217 | cell->name = "twl4030_codec_vibra"; | 217 | cell->name = "twl4030-vibra"; |
218 | cell->platform_data = pdata->vibra; | 218 | cell->platform_data = pdata->vibra; |
219 | cell->data_size = sizeof(*pdata->vibra); | 219 | cell->data_size = sizeof(*pdata->vibra); |
220 | childs++; | 220 | childs++; |
@@ -249,14 +249,14 @@ static int __devexit twl4030_codec_remove(struct platform_device *pdev) | |||
249 | return 0; | 249 | return 0; |
250 | } | 250 | } |
251 | 251 | ||
252 | MODULE_ALIAS("platform:twl4030_codec"); | 252 | MODULE_ALIAS("platform:twl4030-audio"); |
253 | 253 | ||
254 | static struct platform_driver twl4030_codec_driver = { | 254 | static struct platform_driver twl4030_codec_driver = { |
255 | .probe = twl4030_codec_probe, | 255 | .probe = twl4030_codec_probe, |
256 | .remove = __devexit_p(twl4030_codec_remove), | 256 | .remove = __devexit_p(twl4030_codec_remove), |
257 | .driver = { | 257 | .driver = { |
258 | .owner = THIS_MODULE, | 258 | .owner = THIS_MODULE, |
259 | .name = "twl4030_codec", | 259 | .name = "twl4030-audio", |
260 | }, | 260 | }, |
261 | }; | 261 | }; |
262 | 262 | ||
diff --git a/include/linux/i2c/twl.h b/include/linux/i2c/twl.h index 6de90bfc6acd..4793d8a7f480 100644 --- a/include/linux/i2c/twl.h +++ b/include/linux/i2c/twl.h | |||
@@ -553,8 +553,12 @@ extern void twl4030_power_init(struct twl4030_power_data *triton2_scripts); | |||
553 | extern int twl4030_remove_script(u8 flags); | 553 | extern int twl4030_remove_script(u8 flags); |
554 | 554 | ||
555 | struct twl4030_codec_audio_data { | 555 | struct twl4030_codec_audio_data { |
556 | unsigned int audio_mclk; | 556 | unsigned int audio_mclk; /* not used, will be removed */ |
557 | unsigned int digimic_delay; /* in ms */ | ||
557 | unsigned int ramp_delay_value; | 558 | unsigned int ramp_delay_value; |
559 | unsigned int offset_cncl_path; | ||
560 | unsigned int check_defaults:1; | ||
561 | unsigned int reset_registers:1; | ||
558 | unsigned int hs_extmute:1; | 562 | unsigned int hs_extmute:1; |
559 | void (*set_hs_extmute)(int mute); | 563 | void (*set_hs_extmute)(int mute); |
560 | }; | 564 | }; |
diff --git a/include/sound/sh_fsi.h b/include/sound/sh_fsi.h index 9d51d6f35893..3fd6456d07d7 100644 --- a/include/sound/sh_fsi.h +++ b/include/sound/sh_fsi.h | |||
@@ -114,7 +114,7 @@ struct sh_fsi_platform_info { | |||
114 | int (*set_rate)(int is_porta, int rate); /* for master mode */ | 114 | int (*set_rate)(int is_porta, int rate); /* for master mode */ |
115 | }; | 115 | }; |
116 | 116 | ||
117 | extern struct snd_soc_dai fsi_soc_dai[2]; | 117 | extern struct snd_soc_dai_driver fsi_soc_dai[2]; |
118 | extern struct snd_soc_platform fsi_soc_platform; | 118 | extern struct snd_soc_platform_driver fsi_soc_platform; |
119 | 119 | ||
120 | #endif /* __SOUND_FSI_H */ | 120 | #endif /* __SOUND_FSI_H */ |
diff --git a/include/sound/soc-dai.h b/include/sound/soc-dai.h index 377693a14385..e7b680248006 100644 --- a/include/sound/soc-dai.h +++ b/include/sound/soc-dai.h | |||
@@ -91,15 +91,17 @@ struct snd_pcm_substream; | |||
91 | SNDRV_PCM_FMTBIT_S32_LE |\ | 91 | SNDRV_PCM_FMTBIT_S32_LE |\ |
92 | SNDRV_PCM_FMTBIT_S32_BE) | 92 | SNDRV_PCM_FMTBIT_S32_BE) |
93 | 93 | ||
94 | struct snd_soc_dai_ops; | 94 | struct snd_soc_dai_driver; |
95 | struct snd_soc_dai; | 95 | struct snd_soc_dai; |
96 | struct snd_ac97_bus_ops; | 96 | struct snd_ac97_bus_ops; |
97 | 97 | ||
98 | /* Digital Audio Interface registration */ | 98 | /* Digital Audio Interface registration */ |
99 | int snd_soc_register_dai(struct snd_soc_dai *dai); | 99 | int snd_soc_register_dai(struct device *dev, |
100 | void snd_soc_unregister_dai(struct snd_soc_dai *dai); | 100 | struct snd_soc_dai_driver *dai_drv); |
101 | int snd_soc_register_dais(struct snd_soc_dai *dai, size_t count); | 101 | void snd_soc_unregister_dai(struct device *dev); |
102 | void snd_soc_unregister_dais(struct snd_soc_dai *dai, size_t count); | 102 | int snd_soc_register_dais(struct device *dev, |
103 | struct snd_soc_dai_driver *dai_drv, size_t count); | ||
104 | void snd_soc_unregister_dais(struct device *dev, size_t count); | ||
103 | 105 | ||
104 | /* Digital Audio Interface clocking API.*/ | 106 | /* Digital Audio Interface clocking API.*/ |
105 | int snd_soc_dai_set_sysclk(struct snd_soc_dai *dai, int clk_id, | 107 | int snd_soc_dai_set_sysclk(struct snd_soc_dai *dai, int clk_id, |
@@ -126,16 +128,6 @@ int snd_soc_dai_set_tristate(struct snd_soc_dai *dai, int tristate); | |||
126 | /* Digital Audio Interface mute */ | 128 | /* Digital Audio Interface mute */ |
127 | int snd_soc_dai_digital_mute(struct snd_soc_dai *dai, int mute); | 129 | int snd_soc_dai_digital_mute(struct snd_soc_dai *dai, int mute); |
128 | 130 | ||
129 | /* | ||
130 | * Digital Audio Interface. | ||
131 | * | ||
132 | * Describes the Digital Audio Interface in terms of its ALSA, DAI and AC97 | ||
133 | * operations and capabilities. Codec and platform drivers will register this | ||
134 | * structure for every DAI they have. | ||
135 | * | ||
136 | * This structure covers the clocking, formating and ALSA operations for each | ||
137 | * interface. | ||
138 | */ | ||
139 | struct snd_soc_dai_ops { | 131 | struct snd_soc_dai_ops { |
140 | /* | 132 | /* |
141 | * DAI clocking configuration, all optional. | 133 | * DAI clocking configuration, all optional. |
@@ -191,24 +183,24 @@ struct snd_soc_dai_ops { | |||
191 | }; | 183 | }; |
192 | 184 | ||
193 | /* | 185 | /* |
194 | * Digital Audio Interface runtime data. | 186 | * Digital Audio Interface Driver. |
195 | * | 187 | * |
196 | * Holds runtime data for a DAI. | 188 | * Describes the Digital Audio Interface in terms of its ALSA, DAI and AC97 |
189 | * operations and capabilities. Codec and platform drivers will register this | ||
190 | * structure for every DAI they have. | ||
191 | * | ||
192 | * This structure covers the clocking, formating and ALSA operations for each | ||
193 | * interface. | ||
197 | */ | 194 | */ |
198 | struct snd_soc_dai { | 195 | struct snd_soc_dai_driver { |
199 | /* DAI description */ | 196 | /* DAI description */ |
200 | char *name; | 197 | const char *name; |
201 | unsigned int id; | 198 | unsigned int id; |
202 | int ac97_control; | 199 | int ac97_control; |
203 | 200 | ||
204 | struct device *dev; | 201 | /* DAI driver callbacks */ |
205 | void *ac97_pdata; /* platform_data for the ac97 codec */ | 202 | int (*probe)(struct snd_soc_dai *dai); |
206 | 203 | int (*remove)(struct snd_soc_dai *dai); | |
207 | /* DAI callbacks */ | ||
208 | int (*probe)(struct platform_device *pdev, | ||
209 | struct snd_soc_dai *dai); | ||
210 | void (*remove)(struct platform_device *pdev, | ||
211 | struct snd_soc_dai *dai); | ||
212 | int (*suspend)(struct snd_soc_dai *dai); | 204 | int (*suspend)(struct snd_soc_dai *dai); |
213 | int (*resume)(struct snd_soc_dai *dai); | 205 | int (*resume)(struct snd_soc_dai *dai); |
214 | 206 | ||
@@ -219,26 +211,51 @@ struct snd_soc_dai { | |||
219 | struct snd_soc_pcm_stream capture; | 211 | struct snd_soc_pcm_stream capture; |
220 | struct snd_soc_pcm_stream playback; | 212 | struct snd_soc_pcm_stream playback; |
221 | unsigned int symmetric_rates:1; | 213 | unsigned int symmetric_rates:1; |
214 | }; | ||
215 | |||
216 | /* | ||
217 | * Digital Audio Interface runtime data. | ||
218 | * | ||
219 | * Holds runtime data for a DAI. | ||
220 | */ | ||
221 | struct snd_soc_dai { | ||
222 | const char *name; | ||
223 | int id; | ||
224 | struct device *dev; | ||
225 | void *ac97_pdata; /* platform_data for the ac97 codec */ | ||
226 | |||
227 | /* driver ops */ | ||
228 | struct snd_soc_dai_driver *driver; | ||
222 | 229 | ||
223 | /* DAI runtime info */ | 230 | /* DAI runtime info */ |
224 | struct snd_soc_codec *codec; | 231 | unsigned int capture_active:1; /* stream is in use */ |
232 | unsigned int playback_active:1; /* stream is in use */ | ||
233 | unsigned int symmetric_rates:1; | ||
234 | struct snd_pcm_runtime *runtime; | ||
225 | unsigned int active; | 235 | unsigned int active; |
226 | unsigned char pop_wait:1; | 236 | unsigned char pop_wait:1; |
237 | unsigned char probed:1; | ||
227 | 238 | ||
228 | /* DAI private data */ | 239 | /* DAI DMA data */ |
229 | void *private_data; | 240 | void *playback_dma_data; |
241 | void *capture_dma_data; | ||
230 | 242 | ||
231 | /* parent platform */ | 243 | /* parent platform/codec */ |
232 | struct snd_soc_platform *platform; | 244 | union { |
245 | struct snd_soc_platform *platform; | ||
246 | struct snd_soc_codec *codec; | ||
247 | }; | ||
248 | struct snd_soc_card *card; | ||
233 | 249 | ||
234 | struct list_head list; | 250 | struct list_head list; |
251 | struct list_head card_list; | ||
235 | }; | 252 | }; |
236 | 253 | ||
237 | static inline void *snd_soc_dai_get_dma_data(const struct snd_soc_dai *dai, | 254 | static inline void *snd_soc_dai_get_dma_data(const struct snd_soc_dai *dai, |
238 | const struct snd_pcm_substream *ss) | 255 | const struct snd_pcm_substream *ss) |
239 | { | 256 | { |
240 | return (ss->stream == SNDRV_PCM_STREAM_PLAYBACK) ? | 257 | return (ss->stream == SNDRV_PCM_STREAM_PLAYBACK) ? |
241 | dai->playback.dma_data : dai->capture.dma_data; | 258 | dai->playback_dma_data : dai->capture_dma_data; |
242 | } | 259 | } |
243 | 260 | ||
244 | static inline void snd_soc_dai_set_dma_data(struct snd_soc_dai *dai, | 261 | static inline void snd_soc_dai_set_dma_data(struct snd_soc_dai *dai, |
@@ -246,9 +263,20 @@ static inline void snd_soc_dai_set_dma_data(struct snd_soc_dai *dai, | |||
246 | void *data) | 263 | void *data) |
247 | { | 264 | { |
248 | if (ss->stream == SNDRV_PCM_STREAM_PLAYBACK) | 265 | if (ss->stream == SNDRV_PCM_STREAM_PLAYBACK) |
249 | dai->playback.dma_data = data; | 266 | dai->playback_dma_data = data; |
250 | else | 267 | else |
251 | dai->capture.dma_data = data; | 268 | dai->capture_dma_data = data; |
269 | } | ||
270 | |||
271 | static inline void snd_soc_dai_set_drvdata(struct snd_soc_dai *dai, | ||
272 | void *data) | ||
273 | { | ||
274 | dev_set_drvdata(dai->dev, data); | ||
275 | } | ||
276 | |||
277 | static inline void *snd_soc_dai_get_drvdata(struct snd_soc_dai *dai) | ||
278 | { | ||
279 | return dev_get_drvdata(dai->dev); | ||
252 | } | 280 | } |
253 | 281 | ||
254 | #endif | 282 | #endif |
diff --git a/include/sound/soc-dapm.h b/include/sound/soc-dapm.h index c5d9987bc897..c4a445651ca0 100644 --- a/include/sound/soc-dapm.h +++ b/include/sound/soc-dapm.h | |||
@@ -322,14 +322,14 @@ int snd_soc_dapm_new_controls(struct snd_soc_codec *codec, | |||
322 | 322 | ||
323 | /* dapm path setup */ | 323 | /* dapm path setup */ |
324 | int snd_soc_dapm_new_widgets(struct snd_soc_codec *codec); | 324 | int snd_soc_dapm_new_widgets(struct snd_soc_codec *codec); |
325 | void snd_soc_dapm_free(struct snd_soc_device *socdev); | 325 | void snd_soc_dapm_free(struct snd_soc_codec *codec); |
326 | int snd_soc_dapm_add_routes(struct snd_soc_codec *codec, | 326 | int snd_soc_dapm_add_routes(struct snd_soc_codec *codec, |
327 | const struct snd_soc_dapm_route *route, int num); | 327 | const struct snd_soc_dapm_route *route, int num); |
328 | 328 | ||
329 | /* dapm events */ | 329 | /* dapm events */ |
330 | int snd_soc_dapm_stream_event(struct snd_soc_codec *codec, char *stream, | 330 | int snd_soc_dapm_stream_event(struct snd_soc_pcm_runtime *rtd, |
331 | int event); | 331 | const char *stream, int event); |
332 | void snd_soc_dapm_shutdown(struct snd_soc_device *socdev); | 332 | void snd_soc_dapm_shutdown(struct snd_soc_card *card); |
333 | 333 | ||
334 | /* dapm sys fs - used by the core */ | 334 | /* dapm sys fs - used by the core */ |
335 | int snd_soc_dapm_sys_add(struct device *dev); | 335 | int snd_soc_dapm_sys_add(struct device *dev); |
diff --git a/include/sound/soc-of-simple.h b/include/sound/soc-of-simple.h deleted file mode 100644 index a064e1934a56..000000000000 --- a/include/sound/soc-of-simple.h +++ /dev/null | |||
@@ -1,25 +0,0 @@ | |||
1 | /* | ||
2 | * OF helpers for ALSA SoC | ||
3 | * | ||
4 | * Copyright (C) 2008, Secret Lab Technologies Ltd. | ||
5 | */ | ||
6 | |||
7 | #ifndef _INCLUDE_SOC_OF_H_ | ||
8 | #define _INCLUDE_SOC_OF_H_ | ||
9 | |||
10 | #if defined(CONFIG_SND_SOC_OF_SIMPLE) || defined(CONFIG_SND_SOC_OF_SIMPLE_MODULE) | ||
11 | |||
12 | #include <linux/of.h> | ||
13 | #include <sound/soc.h> | ||
14 | |||
15 | int of_snd_soc_register_codec(struct snd_soc_codec_device *codec_dev, | ||
16 | void *codec_data, struct snd_soc_dai *dai, | ||
17 | struct device_node *node); | ||
18 | |||
19 | int of_snd_soc_register_platform(struct snd_soc_platform *platform, | ||
20 | struct device_node *node, | ||
21 | struct snd_soc_dai *cpu_dai); | ||
22 | |||
23 | #endif | ||
24 | |||
25 | #endif /* _INCLUDE_SOC_OF_H_ */ | ||
diff --git a/include/sound/soc.h b/include/sound/soc.h index 65e9d03ed4f5..d31e8b7b2d5e 100644 --- a/include/sound/soc.h +++ b/include/sound/soc.h | |||
@@ -228,13 +228,17 @@ struct snd_soc_ops; | |||
228 | struct snd_soc_dai_mode; | 228 | struct snd_soc_dai_mode; |
229 | struct snd_soc_pcm_runtime; | 229 | struct snd_soc_pcm_runtime; |
230 | struct snd_soc_dai; | 230 | struct snd_soc_dai; |
231 | struct snd_soc_dai_driver; | ||
231 | struct snd_soc_platform; | 232 | struct snd_soc_platform; |
232 | struct snd_soc_dai_link; | 233 | struct snd_soc_dai_link; |
234 | struct snd_soc_platform_driver; | ||
233 | struct snd_soc_codec; | 235 | struct snd_soc_codec; |
236 | struct snd_soc_codec_driver; | ||
234 | struct soc_enum; | 237 | struct soc_enum; |
235 | struct snd_soc_ac97_ops; | 238 | struct snd_soc_ac97_ops; |
236 | struct snd_soc_jack; | 239 | struct snd_soc_jack; |
237 | struct snd_soc_jack_pin; | 240 | struct snd_soc_jack_pin; |
241 | |||
238 | #ifdef CONFIG_GPIOLIB | 242 | #ifdef CONFIG_GPIOLIB |
239 | struct snd_soc_jack_gpio; | 243 | struct snd_soc_jack_gpio; |
240 | #endif | 244 | #endif |
@@ -249,19 +253,18 @@ enum snd_soc_control_type { | |||
249 | SND_SOC_SPI, | 253 | SND_SOC_SPI, |
250 | }; | 254 | }; |
251 | 255 | ||
252 | int snd_soc_register_platform(struct snd_soc_platform *platform); | 256 | int snd_soc_register_platform(struct device *dev, |
253 | void snd_soc_unregister_platform(struct snd_soc_platform *platform); | 257 | struct snd_soc_platform_driver *platform_drv); |
254 | int snd_soc_register_codec(struct snd_soc_codec *codec); | 258 | void snd_soc_unregister_platform(struct device *dev); |
255 | void snd_soc_unregister_codec(struct snd_soc_codec *codec); | 259 | int snd_soc_register_codec(struct device *dev, |
260 | struct snd_soc_codec_driver *codec_drv, | ||
261 | struct snd_soc_dai_driver *dai_drv, int num_dai); | ||
262 | void snd_soc_unregister_codec(struct device *dev); | ||
256 | int snd_soc_codec_volatile_register(struct snd_soc_codec *codec, int reg); | 263 | int snd_soc_codec_volatile_register(struct snd_soc_codec *codec, int reg); |
257 | int snd_soc_codec_set_cache_io(struct snd_soc_codec *codec, | 264 | int snd_soc_codec_set_cache_io(struct snd_soc_codec *codec, |
258 | int addr_bits, int data_bits, | 265 | int addr_bits, int data_bits, |
259 | enum snd_soc_control_type control); | 266 | enum snd_soc_control_type control); |
260 | 267 | ||
261 | /* pcm <-> DAI connect */ | ||
262 | void snd_soc_free_pcms(struct snd_soc_device *socdev); | ||
263 | int snd_soc_new_pcms(struct snd_soc_device *socdev, int idx, const char *xid); | ||
264 | |||
265 | /* Utility functions to get clock rates from various things */ | 268 | /* Utility functions to get clock rates from various things */ |
266 | int snd_soc_calc_frame_size(int sample_size, int channels, int tdm_slots); | 269 | int snd_soc_calc_frame_size(int sample_size, int channels, int tdm_slots); |
267 | int snd_soc_params_to_frame_size(struct snd_pcm_hw_params *params); | 270 | int snd_soc_params_to_frame_size(struct snd_pcm_hw_params *params); |
@@ -273,7 +276,7 @@ int snd_soc_set_runtime_hwparams(struct snd_pcm_substream *substream, | |||
273 | const struct snd_pcm_hardware *hw); | 276 | const struct snd_pcm_hardware *hw); |
274 | 277 | ||
275 | /* Jack reporting */ | 278 | /* Jack reporting */ |
276 | int snd_soc_jack_new(struct snd_soc_card *card, const char *id, int type, | 279 | int snd_soc_jack_new(struct snd_soc_codec *codec, const char *id, int type, |
277 | struct snd_soc_jack *jack); | 280 | struct snd_soc_jack *jack); |
278 | void snd_soc_jack_report(struct snd_soc_jack *jack, int status, int mask); | 281 | void snd_soc_jack_report(struct snd_soc_jack *jack, int status, int mask); |
279 | int snd_soc_jack_add_pins(struct snd_soc_jack *jack, int count, | 282 | int snd_soc_jack_add_pins(struct snd_soc_jack *jack, int count, |
@@ -390,7 +393,7 @@ struct snd_soc_jack_gpio { | |||
390 | 393 | ||
391 | struct snd_soc_jack { | 394 | struct snd_soc_jack { |
392 | struct snd_jack *jack; | 395 | struct snd_jack *jack; |
393 | struct snd_soc_card *card; | 396 | struct snd_soc_codec *codec; |
394 | struct list_head pins; | 397 | struct list_head pins; |
395 | int status; | 398 | int status; |
396 | struct blocking_notifier_head notifier; | 399 | struct blocking_notifier_head notifier; |
@@ -398,15 +401,13 @@ struct snd_soc_jack { | |||
398 | 401 | ||
399 | /* SoC PCM stream information */ | 402 | /* SoC PCM stream information */ |
400 | struct snd_soc_pcm_stream { | 403 | struct snd_soc_pcm_stream { |
401 | char *stream_name; | 404 | const char *stream_name; |
402 | u64 formats; /* SNDRV_PCM_FMTBIT_* */ | 405 | u64 formats; /* SNDRV_PCM_FMTBIT_* */ |
403 | unsigned int rates; /* SNDRV_PCM_RATE_* */ | 406 | unsigned int rates; /* SNDRV_PCM_RATE_* */ |
404 | unsigned int rate_min; /* min rate */ | 407 | unsigned int rate_min; /* min rate */ |
405 | unsigned int rate_max; /* max rate */ | 408 | unsigned int rate_max; /* max rate */ |
406 | unsigned int channels_min; /* min channels */ | 409 | unsigned int channels_min; /* min channels */ |
407 | unsigned int channels_max; /* max channels */ | 410 | unsigned int channels_max; /* max channels */ |
408 | unsigned int active; /* stream is in use */ | ||
409 | void *dma_data; /* used by platform code */ | ||
410 | }; | 411 | }; |
411 | 412 | ||
412 | /* SoC audio ops */ | 413 | /* SoC audio ops */ |
@@ -419,44 +420,35 @@ struct snd_soc_ops { | |||
419 | int (*trigger)(struct snd_pcm_substream *, int); | 420 | int (*trigger)(struct snd_pcm_substream *, int); |
420 | }; | 421 | }; |
421 | 422 | ||
422 | /* SoC Audio Codec */ | 423 | /* SoC Audio Codec device */ |
423 | struct snd_soc_codec { | 424 | struct snd_soc_codec { |
424 | char *name; | 425 | const char *name; |
425 | struct module *owner; | 426 | int id; |
426 | struct mutex mutex; | ||
427 | struct device *dev; | 427 | struct device *dev; |
428 | struct snd_soc_device *socdev; | 428 | struct snd_soc_codec_driver *driver; |
429 | 429 | ||
430 | struct mutex mutex; | ||
431 | struct snd_soc_card *card; | ||
430 | struct list_head list; | 432 | struct list_head list; |
431 | 433 | struct list_head card_list; | |
432 | /* callbacks */ | 434 | int num_dai; |
433 | int (*set_bias_level)(struct snd_soc_codec *, | ||
434 | enum snd_soc_bias_level level); | ||
435 | 435 | ||
436 | /* runtime */ | 436 | /* runtime */ |
437 | struct snd_card *card; | ||
438 | struct snd_ac97 *ac97; /* for ad-hoc ac97 devices */ | 437 | struct snd_ac97 *ac97; /* for ad-hoc ac97 devices */ |
439 | unsigned int active; | 438 | unsigned int active; |
440 | unsigned int pcm_devs; | 439 | unsigned int idle_bias_off:1; /* Use BIAS_OFF instead of STANDBY */ |
441 | void *drvdata; | 440 | unsigned int cache_only:1; /* Suppress writes to hardware */ |
441 | unsigned int cache_sync:1; /* Cache needs to be synced to hardware */ | ||
442 | unsigned int suspended:1; /* Codec is in suspend PM state */ | ||
443 | unsigned int probed:1; /* Codec has been probed */ | ||
444 | unsigned int ac97_registered:1; /* Codec has been AC97 registered */ | ||
445 | unsigned int sysfs_registered:1; /* codec has been sysfs registered */ | ||
442 | 446 | ||
443 | /* codec IO */ | 447 | /* codec IO */ |
444 | void *control_data; /* codec control (i2c/3wire) data */ | 448 | void *control_data; /* codec control (i2c/3wire) data */ |
445 | unsigned int (*read)(struct snd_soc_codec *, unsigned int); | ||
446 | int (*write)(struct snd_soc_codec *, unsigned int, unsigned int); | ||
447 | int (*display_register)(struct snd_soc_codec *, char *, | ||
448 | size_t, unsigned int); | ||
449 | int (*volatile_register)(unsigned int); | ||
450 | int (*readable_register)(unsigned int); | ||
451 | hw_write_t hw_write; | 449 | hw_write_t hw_write; |
452 | unsigned int (*hw_read)(struct snd_soc_codec *, unsigned int); | 450 | unsigned int (*hw_read)(struct snd_soc_codec *, unsigned int); |
453 | void *reg_cache; | 451 | void *reg_cache; |
454 | short reg_cache_size; | ||
455 | short reg_cache_step; | ||
456 | |||
457 | unsigned int idle_bias_off:1; /* Use BIAS_OFF instead of STANDBY */ | ||
458 | unsigned int cache_only:1; /* Suppress writes to hardware */ | ||
459 | unsigned int cache_sync:1; /* Cache needs to be synced to hardware */ | ||
460 | 452 | ||
461 | /* dapm */ | 453 | /* dapm */ |
462 | u32 pop_time; | 454 | u32 pop_time; |
@@ -466,10 +458,6 @@ struct snd_soc_codec { | |||
466 | enum snd_soc_bias_level suspend_bias_level; | 458 | enum snd_soc_bias_level suspend_bias_level; |
467 | struct delayed_work delayed_work; | 459 | struct delayed_work delayed_work; |
468 | 460 | ||
469 | /* codec DAI's */ | ||
470 | struct snd_soc_dai *dai; | ||
471 | unsigned int num_dai; | ||
472 | |||
473 | #ifdef CONFIG_DEBUG_FS | 461 | #ifdef CONFIG_DEBUG_FS |
474 | struct dentry *debugfs_codec_root; | 462 | struct dentry *debugfs_codec_root; |
475 | struct dentry *debugfs_reg; | 463 | struct dentry *debugfs_reg; |
@@ -478,23 +466,40 @@ struct snd_soc_codec { | |||
478 | #endif | 466 | #endif |
479 | }; | 467 | }; |
480 | 468 | ||
481 | /* codec device */ | 469 | /* codec driver */ |
482 | struct snd_soc_codec_device { | 470 | struct snd_soc_codec_driver { |
483 | int (*probe)(struct platform_device *pdev); | 471 | |
484 | int (*remove)(struct platform_device *pdev); | 472 | /* driver ops */ |
485 | int (*suspend)(struct platform_device *pdev, pm_message_t state); | 473 | int (*probe)(struct snd_soc_codec *); |
486 | int (*resume)(struct platform_device *pdev); | 474 | int (*remove)(struct snd_soc_codec *); |
475 | int (*suspend)(struct snd_soc_codec *, | ||
476 | pm_message_t state); | ||
477 | int (*resume)(struct snd_soc_codec *); | ||
478 | |||
479 | /* codec IO */ | ||
480 | unsigned int (*read)(struct snd_soc_codec *, unsigned int); | ||
481 | int (*write)(struct snd_soc_codec *, unsigned int, unsigned int); | ||
482 | int (*display_register)(struct snd_soc_codec *, char *, | ||
483 | size_t, unsigned int); | ||
484 | int (*volatile_register)(unsigned int); | ||
485 | int (*readable_register)(unsigned int); | ||
486 | short reg_cache_size; | ||
487 | short reg_cache_step; | ||
488 | short reg_word_size; | ||
489 | const void *reg_cache_default; | ||
490 | |||
491 | /* codec bias level */ | ||
492 | int (*set_bias_level)(struct snd_soc_codec *, | ||
493 | enum snd_soc_bias_level level); | ||
487 | }; | 494 | }; |
488 | 495 | ||
489 | /* SoC platform interface */ | 496 | /* SoC platform interface */ |
490 | struct snd_soc_platform { | 497 | struct snd_soc_platform_driver { |
491 | char *name; | ||
492 | struct list_head list; | ||
493 | 498 | ||
494 | int (*probe)(struct platform_device *pdev); | 499 | int (*probe)(struct snd_soc_platform *); |
495 | int (*remove)(struct platform_device *pdev); | 500 | int (*remove)(struct snd_soc_platform *); |
496 | int (*suspend)(struct snd_soc_dai_link *dai_link); | 501 | int (*suspend)(struct snd_soc_dai *dai); |
497 | int (*resume)(struct snd_soc_dai_link *dai_link); | 502 | int (*resume)(struct snd_soc_dai *dai); |
498 | 503 | ||
499 | /* pcm creation and destruction */ | 504 | /* pcm creation and destruction */ |
500 | int (*pcm_new)(struct snd_card *, struct snd_soc_dai *, | 505 | int (*pcm_new)(struct snd_card *, struct snd_soc_dai *, |
@@ -509,23 +514,31 @@ struct snd_soc_platform { | |||
509 | struct snd_soc_dai *); | 514 | struct snd_soc_dai *); |
510 | 515 | ||
511 | /* platform stream ops */ | 516 | /* platform stream ops */ |
512 | struct snd_pcm_ops *pcm_ops; | 517 | struct snd_pcm_ops *ops; |
513 | }; | 518 | }; |
514 | 519 | ||
515 | /* SoC machine DAI configuration, glues a codec and cpu DAI together */ | 520 | struct snd_soc_platform { |
516 | struct snd_soc_dai_link { | 521 | const char *name; |
517 | char *name; /* Codec name */ | 522 | int id; |
518 | char *stream_name; /* Stream name */ | 523 | struct device *dev; |
524 | struct snd_soc_platform_driver *driver; | ||
519 | 525 | ||
520 | /* DAI */ | 526 | unsigned int suspended:1; /* platform is suspended */ |
521 | struct snd_soc_dai *codec_dai; | 527 | unsigned int probed:1; |
522 | struct snd_soc_dai *cpu_dai; | ||
523 | 528 | ||
524 | /* machine stream operations */ | 529 | struct snd_soc_card *card; |
525 | struct snd_soc_ops *ops; | 530 | struct list_head list; |
531 | struct list_head card_list; | ||
532 | }; | ||
526 | 533 | ||
527 | /* codec/machine specific init - e.g. add machine controls */ | 534 | struct snd_soc_dai_link { |
528 | int (*init)(struct snd_soc_codec *codec); | 535 | /* config - must be set by machine driver */ |
536 | const char *name; /* Codec name */ | ||
537 | const char *stream_name; /* Stream name */ | ||
538 | const char *codec_name; /* for multi-codec */ | ||
539 | const char *platform_name; /* for multi-platform */ | ||
540 | const char *cpu_dai_name; | ||
541 | const char *codec_dai_name; | ||
529 | 542 | ||
530 | /* Keep DAI active over suspend */ | 543 | /* Keep DAI active over suspend */ |
531 | unsigned int ignore_suspend:1; | 544 | unsigned int ignore_suspend:1; |
@@ -533,21 +546,24 @@ struct snd_soc_dai_link { | |||
533 | /* Symmetry requirements */ | 546 | /* Symmetry requirements */ |
534 | unsigned int symmetric_rates:1; | 547 | unsigned int symmetric_rates:1; |
535 | 548 | ||
536 | /* Symmetry data - only valid if symmetry is being enforced */ | 549 | /* codec/machine specific init - e.g. add machine controls */ |
537 | unsigned int rate; | 550 | int (*init)(struct snd_soc_pcm_runtime *rtd); |
538 | 551 | ||
539 | /* DAI pcm */ | 552 | /* machine stream operations */ |
540 | struct snd_pcm *pcm; | 553 | struct snd_soc_ops *ops; |
541 | }; | 554 | }; |
542 | 555 | ||
543 | /* SoC card */ | 556 | /* SoC card */ |
544 | struct snd_soc_card { | 557 | struct snd_soc_card { |
545 | char *name; | 558 | const char *name; |
546 | struct device *dev; | 559 | struct device *dev; |
560 | struct snd_card *snd_card; | ||
561 | struct module *owner; | ||
547 | 562 | ||
548 | struct list_head list; | 563 | struct list_head list; |
564 | struct mutex mutex; | ||
549 | 565 | ||
550 | int instantiated; | 566 | bool instantiated; |
551 | 567 | ||
552 | int (*probe)(struct platform_device *pdev); | 568 | int (*probe)(struct platform_device *pdev); |
553 | int (*remove)(struct platform_device *pdev); | 569 | int (*remove)(struct platform_device *pdev); |
@@ -568,28 +584,38 @@ struct snd_soc_card { | |||
568 | /* CPU <--> Codec DAI links */ | 584 | /* CPU <--> Codec DAI links */ |
569 | struct snd_soc_dai_link *dai_link; | 585 | struct snd_soc_dai_link *dai_link; |
570 | int num_links; | 586 | int num_links; |
587 | struct snd_soc_pcm_runtime *rtd; | ||
588 | int num_rtd; | ||
571 | 589 | ||
572 | struct snd_soc_device *socdev; | ||
573 | |||
574 | struct snd_soc_codec *codec; | ||
575 | |||
576 | struct snd_soc_platform *platform; | ||
577 | struct delayed_work delayed_work; | ||
578 | struct work_struct deferred_resume_work; | 590 | struct work_struct deferred_resume_work; |
591 | |||
592 | /* lists of probed devices belonging to this card */ | ||
593 | struct list_head codec_dev_list; | ||
594 | struct list_head platform_dev_list; | ||
595 | struct list_head dai_dev_list; | ||
579 | }; | 596 | }; |
580 | 597 | ||
581 | /* SoC Device - the audio subsystem */ | 598 | /* SoC machine DAI configuration, glues a codec and cpu DAI together */ |
582 | struct snd_soc_device { | 599 | struct snd_soc_pcm_runtime { |
583 | struct device *dev; | 600 | struct device dev; |
584 | struct snd_soc_card *card; | 601 | struct snd_soc_card *card; |
585 | struct snd_soc_codec_device *codec_dev; | 602 | struct snd_soc_dai_link *dai_link; |
586 | void *codec_data; | 603 | |
587 | }; | 604 | unsigned int complete:1; |
605 | unsigned int dev_registered:1; | ||
588 | 606 | ||
589 | /* runtime channel data */ | 607 | /* Symmetry data - only valid if symmetry is being enforced */ |
590 | struct snd_soc_pcm_runtime { | 608 | unsigned int rate; |
591 | struct snd_soc_dai_link *dai; | 609 | long pmdown_time; |
592 | struct snd_soc_device *socdev; | 610 | |
611 | /* runtime devices */ | ||
612 | struct snd_pcm *pcm; | ||
613 | struct snd_soc_codec *codec; | ||
614 | struct snd_soc_platform *platform; | ||
615 | struct snd_soc_dai *codec_dai; | ||
616 | struct snd_soc_dai *cpu_dai; | ||
617 | |||
618 | struct delayed_work delayed_work; | ||
593 | }; | 619 | }; |
594 | 620 | ||
595 | /* mixer control */ | 621 | /* mixer control */ |
@@ -615,24 +641,48 @@ struct soc_enum { | |||
615 | static inline unsigned int snd_soc_read(struct snd_soc_codec *codec, | 641 | static inline unsigned int snd_soc_read(struct snd_soc_codec *codec, |
616 | unsigned int reg) | 642 | unsigned int reg) |
617 | { | 643 | { |
618 | return codec->read(codec, reg); | 644 | return codec->driver->read(codec, reg); |
619 | } | 645 | } |
620 | 646 | ||
621 | static inline unsigned int snd_soc_write(struct snd_soc_codec *codec, | 647 | static inline unsigned int snd_soc_write(struct snd_soc_codec *codec, |
622 | unsigned int reg, unsigned int val) | 648 | unsigned int reg, unsigned int val) |
623 | { | 649 | { |
624 | return codec->write(codec, reg, val); | 650 | return codec->driver->write(codec, reg, val); |
625 | } | 651 | } |
626 | 652 | ||
653 | /* device driver data */ | ||
654 | |||
627 | static inline void snd_soc_codec_set_drvdata(struct snd_soc_codec *codec, | 655 | static inline void snd_soc_codec_set_drvdata(struct snd_soc_codec *codec, |
628 | void *data) | 656 | void *data) |
629 | { | 657 | { |
630 | codec->drvdata = data; | 658 | dev_set_drvdata(codec->dev, data); |
631 | } | 659 | } |
632 | 660 | ||
633 | static inline void *snd_soc_codec_get_drvdata(struct snd_soc_codec *codec) | 661 | static inline void *snd_soc_codec_get_drvdata(struct snd_soc_codec *codec) |
634 | { | 662 | { |
635 | return codec->drvdata; | 663 | return dev_get_drvdata(codec->dev); |
664 | } | ||
665 | |||
666 | static inline void snd_soc_platform_set_drvdata(struct snd_soc_platform *platform, | ||
667 | void *data) | ||
668 | { | ||
669 | dev_set_drvdata(platform->dev, data); | ||
670 | } | ||
671 | |||
672 | static inline void *snd_soc_platform_get_drvdata(struct snd_soc_platform *platform) | ||
673 | { | ||
674 | return dev_get_drvdata(platform->dev); | ||
675 | } | ||
676 | |||
677 | static inline void snd_soc_pcm_set_drvdata(struct snd_soc_pcm_runtime *rtd, | ||
678 | void *data) | ||
679 | { | ||
680 | dev_set_drvdata(&rtd->dev, data); | ||
681 | } | ||
682 | |||
683 | static inline void *snd_soc_pcm_get_drvdata(struct snd_soc_pcm_runtime *rtd) | ||
684 | { | ||
685 | return dev_get_drvdata(&rtd->dev); | ||
636 | } | 686 | } |
637 | 687 | ||
638 | #include <sound/soc-dai.h> | 688 | #include <sound/soc-dai.h> |
diff --git a/include/sound/tlv320aic3x.h b/include/sound/tlv320aic3x.h index b1a5f34e5cfa..99e0308bf2c2 100644 --- a/include/sound/tlv320aic3x.h +++ b/include/sound/tlv320aic3x.h | |||
@@ -10,8 +10,49 @@ | |||
10 | #ifndef __TLV320AIC3x_H__ | 10 | #ifndef __TLV320AIC3x_H__ |
11 | #define __TLV320AIC3x_H__ | 11 | #define __TLV320AIC3x_H__ |
12 | 12 | ||
13 | /* GPIO API */ | ||
14 | enum { | ||
15 | AIC3X_GPIO1_FUNC_DISABLED = 0, | ||
16 | AIC3X_GPIO1_FUNC_AUDIO_WORDCLK_ADC = 1, | ||
17 | AIC3X_GPIO1_FUNC_CLOCK_MUX = 2, | ||
18 | AIC3X_GPIO1_FUNC_CLOCK_MUX_DIV2 = 3, | ||
19 | AIC3X_GPIO1_FUNC_CLOCK_MUX_DIV4 = 4, | ||
20 | AIC3X_GPIO1_FUNC_CLOCK_MUX_DIV8 = 5, | ||
21 | AIC3X_GPIO1_FUNC_SHORT_CIRCUIT_IRQ = 6, | ||
22 | AIC3X_GPIO1_FUNC_AGC_NOISE_IRQ = 7, | ||
23 | AIC3X_GPIO1_FUNC_INPUT = 8, | ||
24 | AIC3X_GPIO1_FUNC_OUTPUT = 9, | ||
25 | AIC3X_GPIO1_FUNC_DIGITAL_MIC_MODCLK = 10, | ||
26 | AIC3X_GPIO1_FUNC_AUDIO_WORDCLK = 11, | ||
27 | AIC3X_GPIO1_FUNC_BUTTON_IRQ = 12, | ||
28 | AIC3X_GPIO1_FUNC_HEADSET_DETECT_IRQ = 13, | ||
29 | AIC3X_GPIO1_FUNC_HEADSET_DETECT_OR_BUTTON_IRQ = 14, | ||
30 | AIC3X_GPIO1_FUNC_ALL_IRQ = 16 | ||
31 | }; | ||
32 | |||
33 | enum { | ||
34 | AIC3X_GPIO2_FUNC_DISABLED = 0, | ||
35 | AIC3X_GPIO2_FUNC_HEADSET_DETECT_IRQ = 2, | ||
36 | AIC3X_GPIO2_FUNC_INPUT = 3, | ||
37 | AIC3X_GPIO2_FUNC_OUTPUT = 4, | ||
38 | AIC3X_GPIO2_FUNC_DIGITAL_MIC_INPUT = 5, | ||
39 | AIC3X_GPIO2_FUNC_AUDIO_BITCLK = 8, | ||
40 | AIC3X_GPIO2_FUNC_HEADSET_DETECT_OR_BUTTON_IRQ = 9, | ||
41 | AIC3X_GPIO2_FUNC_ALL_IRQ = 10, | ||
42 | AIC3X_GPIO2_FUNC_SHORT_CIRCUIT_OR_AGC_IRQ = 11, | ||
43 | AIC3X_GPIO2_FUNC_HEADSET_OR_BUTTON_PRESS_OR_SHORT_CIRCUIT_IRQ = 12, | ||
44 | AIC3X_GPIO2_FUNC_SHORT_CIRCUIT_IRQ = 13, | ||
45 | AIC3X_GPIO2_FUNC_AGC_NOISE_IRQ = 14, | ||
46 | AIC3X_GPIO2_FUNC_BUTTON_PRESS_IRQ = 15 | ||
47 | }; | ||
48 | |||
49 | struct aic3x_setup_data { | ||
50 | unsigned int gpio_func[2]; | ||
51 | }; | ||
52 | |||
13 | struct aic3x_pdata { | 53 | struct aic3x_pdata { |
14 | int gpio_reset; /* < 0 if not used */ | 54 | int gpio_reset; /* < 0 if not used */ |
55 | struct aic3x_setup_data *setup; | ||
15 | }; | 56 | }; |
16 | 57 | ||
17 | #endif \ No newline at end of file | 58 | #endif |
diff --git a/sound/soc/atmel/atmel-pcm.c b/sound/soc/atmel/atmel-pcm.c index dc5249fba85c..d0e75323ec19 100644 --- a/sound/soc/atmel/atmel-pcm.c +++ b/sound/soc/atmel/atmel-pcm.c | |||
@@ -179,7 +179,7 @@ static int atmel_pcm_hw_params(struct snd_pcm_substream *substream, | |||
179 | snd_pcm_set_runtime_buffer(substream, &substream->dma_buffer); | 179 | snd_pcm_set_runtime_buffer(substream, &substream->dma_buffer); |
180 | runtime->dma_bytes = params_buffer_bytes(params); | 180 | runtime->dma_bytes = params_buffer_bytes(params); |
181 | 181 | ||
182 | prtd->params = snd_soc_dai_get_dma_data(rtd->dai->cpu_dai, substream); | 182 | prtd->params = snd_soc_dai_get_dma_data(rtd->cpu_dai, substream); |
183 | prtd->params->dma_intr_handler = atmel_pcm_dma_irq; | 183 | prtd->params->dma_intr_handler = atmel_pcm_dma_irq; |
184 | 184 | ||
185 | prtd->dma_buffer = runtime->dma_addr; | 185 | prtd->dma_buffer = runtime->dma_addr; |
@@ -374,14 +374,14 @@ static int atmel_pcm_new(struct snd_card *card, | |||
374 | if (!card->dev->coherent_dma_mask) | 374 | if (!card->dev->coherent_dma_mask) |
375 | card->dev->coherent_dma_mask = 0xffffffff; | 375 | card->dev->coherent_dma_mask = 0xffffffff; |
376 | 376 | ||
377 | if (dai->playback.channels_min) { | 377 | if (dai->driver->playback.channels_min) { |
378 | ret = atmel_pcm_preallocate_dma_buffer(pcm, | 378 | ret = atmel_pcm_preallocate_dma_buffer(pcm, |
379 | SNDRV_PCM_STREAM_PLAYBACK); | 379 | SNDRV_PCM_STREAM_PLAYBACK); |
380 | if (ret) | 380 | if (ret) |
381 | goto out; | 381 | goto out; |
382 | } | 382 | } |
383 | 383 | ||
384 | if (dai->capture.channels_min) { | 384 | if (dai->driver->capture.channels_min) { |
385 | pr_debug("at32-pcm:" | 385 | pr_debug("at32-pcm:" |
386 | "Allocating PCM capture DMA buffer\n"); | 386 | "Allocating PCM capture DMA buffer\n"); |
387 | ret = atmel_pcm_preallocate_dma_buffer(pcm, | 387 | ret = atmel_pcm_preallocate_dma_buffer(pcm, |
@@ -414,12 +414,9 @@ static void atmel_pcm_free_dma_buffers(struct snd_pcm *pcm) | |||
414 | } | 414 | } |
415 | 415 | ||
416 | #ifdef CONFIG_PM | 416 | #ifdef CONFIG_PM |
417 | static int atmel_pcm_suspend(struct snd_soc_dai_link *dai_link) | 417 | static int atmel_pcm_suspend(struct snd_soc_dai *dai) |
418 | { | 418 | { |
419 | struct snd_pcm *pcm = dai_link->pcm; | 419 | struct snd_pcm_runtime *runtime = dai->runtime; |
420 | struct snd_pcm_str *stream = &pcm->streams[0]; | ||
421 | struct snd_pcm_substream *substream = stream->substream; | ||
422 | struct snd_pcm_runtime *runtime = substream->runtime; | ||
423 | struct atmel_runtime_data *prtd; | 420 | struct atmel_runtime_data *prtd; |
424 | struct atmel_pcm_dma_params *params; | 421 | struct atmel_pcm_dma_params *params; |
425 | 422 | ||
@@ -441,12 +438,9 @@ static int atmel_pcm_suspend(struct snd_soc_dai_link *dai_link) | |||
441 | return 0; | 438 | return 0; |
442 | } | 439 | } |
443 | 440 | ||
444 | static int atmel_pcm_resume(struct snd_soc_dai_link *dai_link) | 441 | static int atmel_pcm_resume(struct snd_soc_dai *dai) |
445 | { | 442 | { |
446 | struct snd_pcm *pcm = dai_link->pcm; | 443 | struct snd_pcm_runtime *runtime = dai->runtime; |
447 | struct snd_pcm_str *stream = &pcm->streams[0]; | ||
448 | struct snd_pcm_substream *substream = stream->substream; | ||
449 | struct snd_pcm_runtime *runtime = substream->runtime; | ||
450 | struct atmel_runtime_data *prtd; | 444 | struct atmel_runtime_data *prtd; |
451 | struct atmel_pcm_dma_params *params; | 445 | struct atmel_pcm_dma_params *params; |
452 | 446 | ||
@@ -470,27 +464,46 @@ static int atmel_pcm_resume(struct snd_soc_dai_link *dai_link) | |||
470 | #define atmel_pcm_resume NULL | 464 | #define atmel_pcm_resume NULL |
471 | #endif | 465 | #endif |
472 | 466 | ||
473 | struct snd_soc_platform atmel_soc_platform = { | 467 | static struct snd_soc_platform_driver atmel_soc_platform = { |
474 | .name = "atmel-audio", | 468 | .ops = &atmel_pcm_ops, |
475 | .pcm_ops = &atmel_pcm_ops, | ||
476 | .pcm_new = atmel_pcm_new, | 469 | .pcm_new = atmel_pcm_new, |
477 | .pcm_free = atmel_pcm_free_dma_buffers, | 470 | .pcm_free = atmel_pcm_free_dma_buffers, |
478 | .suspend = atmel_pcm_suspend, | 471 | .suspend = atmel_pcm_suspend, |
479 | .resume = atmel_pcm_resume, | 472 | .resume = atmel_pcm_resume, |
480 | }; | 473 | }; |
481 | EXPORT_SYMBOL_GPL(atmel_soc_platform); | ||
482 | 474 | ||
483 | static int __init atmel_pcm_modinit(void) | 475 | static int __devinit atmel_soc_platform_probe(struct platform_device *pdev) |
476 | { | ||
477 | return snd_soc_register_platform(&pdev->dev, &atmel_soc_platform); | ||
478 | } | ||
479 | |||
480 | static int __devexit atmel_soc_platform_remove(struct platform_device *pdev) | ||
481 | { | ||
482 | snd_soc_unregister_platform(&pdev->dev); | ||
483 | return 0; | ||
484 | } | ||
485 | |||
486 | static struct platform_driver atmel_pcm_driver = { | ||
487 | .driver = { | ||
488 | .name = "atmel-pcm-audio", | ||
489 | .owner = THIS_MODULE, | ||
490 | }, | ||
491 | |||
492 | .probe = atmel_soc_platform_probe, | ||
493 | .remove = __devexit_p(atmel_soc_platform_remove), | ||
494 | }; | ||
495 | |||
496 | static int __init snd_atmel_pcm_init(void) | ||
484 | { | 497 | { |
485 | return snd_soc_register_platform(&atmel_soc_platform); | 498 | return platform_driver_register(&atmel_pcm_driver); |
486 | } | 499 | } |
487 | module_init(atmel_pcm_modinit); | 500 | module_init(snd_atmel_pcm_init); |
488 | 501 | ||
489 | static void __exit atmel_pcm_modexit(void) | 502 | static void __exit snd_atmel_pcm_exit(void) |
490 | { | 503 | { |
491 | snd_soc_unregister_platform(&atmel_soc_platform); | 504 | platform_driver_unregister(&atmel_pcm_driver); |
492 | } | 505 | } |
493 | module_exit(atmel_pcm_modexit); | 506 | module_exit(snd_atmel_pcm_exit); |
494 | 507 | ||
495 | MODULE_AUTHOR("Sedji Gaouaou <sedji.gaouaou@atmel.com>"); | 508 | MODULE_AUTHOR("Sedji Gaouaou <sedji.gaouaou@atmel.com>"); |
496 | MODULE_DESCRIPTION("Atmel PCM module"); | 509 | MODULE_DESCRIPTION("Atmel PCM module"); |
diff --git a/sound/soc/atmel/atmel-pcm.h b/sound/soc/atmel/atmel-pcm.h index ec9b2824b663..2597329302e7 100644 --- a/sound/soc/atmel/atmel-pcm.h +++ b/sound/soc/atmel/atmel-pcm.h | |||
@@ -74,9 +74,6 @@ struct atmel_pcm_dma_params { | |||
74 | void (*dma_intr_handler)(u32, struct snd_pcm_substream *); | 74 | void (*dma_intr_handler)(u32, struct snd_pcm_substream *); |
75 | }; | 75 | }; |
76 | 76 | ||
77 | extern struct snd_soc_platform atmel_soc_platform; | ||
78 | |||
79 | |||
80 | /* | 77 | /* |
81 | * SSC register access (since ssc_writel() / ssc_readl() require literal name) | 78 | * SSC register access (since ssc_writel() / ssc_readl() require literal name) |
82 | */ | 79 | */ |
diff --git a/sound/soc/atmel/atmel_ssc_dai.c b/sound/soc/atmel/atmel_ssc_dai.c index c85844d4845b..eabf66af12cd 100644 --- a/sound/soc/atmel/atmel_ssc_dai.c +++ b/sound/soc/atmel/atmel_ssc_dai.c | |||
@@ -205,8 +205,7 @@ static irqreturn_t atmel_ssc_interrupt(int irq, void *dev_id) | |||
205 | static int atmel_ssc_startup(struct snd_pcm_substream *substream, | 205 | static int atmel_ssc_startup(struct snd_pcm_substream *substream, |
206 | struct snd_soc_dai *dai) | 206 | struct snd_soc_dai *dai) |
207 | { | 207 | { |
208 | struct snd_soc_pcm_runtime *rtd = snd_pcm_substream_chip(substream); | 208 | struct atmel_ssc_info *ssc_p = &ssc_info[dai->id]; |
209 | struct atmel_ssc_info *ssc_p = &ssc_info[rtd->dai->cpu_dai->id]; | ||
210 | int dir_mask; | 209 | int dir_mask; |
211 | 210 | ||
212 | pr_debug("atmel_ssc_startup: SSC_SR=0x%u\n", | 211 | pr_debug("atmel_ssc_startup: SSC_SR=0x%u\n", |
@@ -235,8 +234,7 @@ static int atmel_ssc_startup(struct snd_pcm_substream *substream, | |||
235 | static void atmel_ssc_shutdown(struct snd_pcm_substream *substream, | 234 | static void atmel_ssc_shutdown(struct snd_pcm_substream *substream, |
236 | struct snd_soc_dai *dai) | 235 | struct snd_soc_dai *dai) |
237 | { | 236 | { |
238 | struct snd_soc_pcm_runtime *rtd = snd_pcm_substream_chip(substream); | 237 | struct atmel_ssc_info *ssc_p = &ssc_info[dai->id]; |
239 | struct atmel_ssc_info *ssc_p = &ssc_info[rtd->dai->cpu_dai->id]; | ||
240 | struct atmel_pcm_dma_params *dma_params; | 238 | struct atmel_pcm_dma_params *dma_params; |
241 | int dir, dir_mask; | 239 | int dir, dir_mask; |
242 | 240 | ||
@@ -338,7 +336,7 @@ static int atmel_ssc_hw_params(struct snd_pcm_substream *substream, | |||
338 | struct snd_soc_dai *dai) | 336 | struct snd_soc_dai *dai) |
339 | { | 337 | { |
340 | struct snd_soc_pcm_runtime *rtd = snd_pcm_substream_chip(substream); | 338 | struct snd_soc_pcm_runtime *rtd = snd_pcm_substream_chip(substream); |
341 | int id = rtd->dai->cpu_dai->id; | 339 | int id = dai->id; |
342 | struct atmel_ssc_info *ssc_p = &ssc_info[id]; | 340 | struct atmel_ssc_info *ssc_p = &ssc_info[id]; |
343 | struct atmel_pcm_dma_params *dma_params; | 341 | struct atmel_pcm_dma_params *dma_params; |
344 | int dir, channels, bits; | 342 | int dir, channels, bits; |
@@ -368,7 +366,7 @@ static int atmel_ssc_hw_params(struct snd_pcm_substream *substream, | |||
368 | * function. It should not be used for other purposes | 366 | * function. It should not be used for other purposes |
369 | * as it is common to all substreams. | 367 | * as it is common to all substreams. |
370 | */ | 368 | */ |
371 | snd_soc_dai_set_dma_data(rtd->dai->cpu_dai, substream, dma_params); | 369 | snd_soc_dai_set_dma_data(rtd->cpu_dai, substream, dma_params); |
372 | 370 | ||
373 | channels = params_channels(params); | 371 | channels = params_channels(params); |
374 | 372 | ||
@@ -605,8 +603,7 @@ static int atmel_ssc_hw_params(struct snd_pcm_substream *substream, | |||
605 | static int atmel_ssc_prepare(struct snd_pcm_substream *substream, | 603 | static int atmel_ssc_prepare(struct snd_pcm_substream *substream, |
606 | struct snd_soc_dai *dai) | 604 | struct snd_soc_dai *dai) |
607 | { | 605 | { |
608 | struct snd_soc_pcm_runtime *rtd = snd_pcm_substream_chip(substream); | 606 | struct atmel_ssc_info *ssc_p = &ssc_info[dai->id]; |
609 | struct atmel_ssc_info *ssc_p = &ssc_info[rtd->dai->cpu_dai->id]; | ||
610 | struct atmel_pcm_dma_params *dma_params; | 607 | struct atmel_pcm_dma_params *dma_params; |
611 | int dir; | 608 | int dir; |
612 | 609 | ||
@@ -690,6 +687,32 @@ static int atmel_ssc_resume(struct snd_soc_dai *cpu_dai) | |||
690 | # define atmel_ssc_resume NULL | 687 | # define atmel_ssc_resume NULL |
691 | #endif /* CONFIG_PM */ | 688 | #endif /* CONFIG_PM */ |
692 | 689 | ||
690 | static int atmel_ssc_probe(struct snd_soc_dai *dai) | ||
691 | { | ||
692 | struct atmel_ssc_info *ssc_p = &ssc_info[dai->id]; | ||
693 | int ret = 0; | ||
694 | |||
695 | snd_soc_dai_set_drvdata(dai, ssc_p); | ||
696 | |||
697 | /* | ||
698 | * Request SSC device | ||
699 | */ | ||
700 | ssc_p->ssc = ssc_request(dai->id); | ||
701 | if (IS_ERR(ssc_p->ssc)) { | ||
702 | printk(KERN_ERR "ASoC: Failed to request SSC %d\n", dai->id); | ||
703 | ret = PTR_ERR(ssc_p->ssc); | ||
704 | } | ||
705 | |||
706 | return ret; | ||
707 | } | ||
708 | |||
709 | static int atmel_ssc_remove(struct snd_soc_dai *dai) | ||
710 | { | ||
711 | struct atmel_ssc_info *ssc_p = snd_soc_dai_get_drvdata(dai); | ||
712 | |||
713 | ssc_free(ssc_p->ssc); | ||
714 | return 0; | ||
715 | } | ||
693 | 716 | ||
694 | #define ATMEL_SSC_RATES (SNDRV_PCM_RATE_8000_96000) | 717 | #define ATMEL_SSC_RATES (SNDRV_PCM_RATE_8000_96000) |
695 | 718 | ||
@@ -705,9 +728,11 @@ static struct snd_soc_dai_ops atmel_ssc_dai_ops = { | |||
705 | .set_clkdiv = atmel_ssc_set_dai_clkdiv, | 728 | .set_clkdiv = atmel_ssc_set_dai_clkdiv, |
706 | }; | 729 | }; |
707 | 730 | ||
708 | struct snd_soc_dai atmel_ssc_dai[NUM_SSC_DEVICES] = { | 731 | static struct snd_soc_dai_driver atmel_ssc_dai[NUM_SSC_DEVICES] = { |
709 | { .name = "atmel-ssc0", | 732 | { |
710 | .id = 0, | 733 | .name = "atmel-ssc-dai.0", |
734 | .probe = atmel_ssc_probe, | ||
735 | .remove = atmel_ssc_remove, | ||
711 | .suspend = atmel_ssc_suspend, | 736 | .suspend = atmel_ssc_suspend, |
712 | .resume = atmel_ssc_resume, | 737 | .resume = atmel_ssc_resume, |
713 | .playback = { | 738 | .playback = { |
@@ -721,11 +746,12 @@ struct snd_soc_dai atmel_ssc_dai[NUM_SSC_DEVICES] = { | |||
721 | .rates = ATMEL_SSC_RATES, | 746 | .rates = ATMEL_SSC_RATES, |
722 | .formats = ATMEL_SSC_FORMATS,}, | 747 | .formats = ATMEL_SSC_FORMATS,}, |
723 | .ops = &atmel_ssc_dai_ops, | 748 | .ops = &atmel_ssc_dai_ops, |
724 | .private_data = &ssc_info[0], | ||
725 | }, | 749 | }, |
726 | #if NUM_SSC_DEVICES == 3 | 750 | #if NUM_SSC_DEVICES == 3 |
727 | { .name = "atmel-ssc1", | 751 | { |
728 | .id = 1, | 752 | .name = "atmel-ssc-dai.1", |
753 | .probe = atmel_ssc_probe, | ||
754 | .remove = atmel_ssc_remove, | ||
729 | .suspend = atmel_ssc_suspend, | 755 | .suspend = atmel_ssc_suspend, |
730 | .resume = atmel_ssc_resume, | 756 | .resume = atmel_ssc_resume, |
731 | .playback = { | 757 | .playback = { |
@@ -739,10 +765,11 @@ struct snd_soc_dai atmel_ssc_dai[NUM_SSC_DEVICES] = { | |||
739 | .rates = ATMEL_SSC_RATES, | 765 | .rates = ATMEL_SSC_RATES, |
740 | .formats = ATMEL_SSC_FORMATS,}, | 766 | .formats = ATMEL_SSC_FORMATS,}, |
741 | .ops = &atmel_ssc_dai_ops, | 767 | .ops = &atmel_ssc_dai_ops, |
742 | .private_data = &ssc_info[1], | ||
743 | }, | 768 | }, |
744 | { .name = "atmel-ssc2", | 769 | { |
745 | .id = 2, | 770 | .name = "atmel-ssc-dai.2", |
771 | .probe = atmel_ssc_probe, | ||
772 | .remove = atmel_ssc_remove, | ||
746 | .suspend = atmel_ssc_suspend, | 773 | .suspend = atmel_ssc_suspend, |
747 | .resume = atmel_ssc_resume, | 774 | .resume = atmel_ssc_resume, |
748 | .playback = { | 775 | .playback = { |
@@ -756,23 +783,43 @@ struct snd_soc_dai atmel_ssc_dai[NUM_SSC_DEVICES] = { | |||
756 | .rates = ATMEL_SSC_RATES, | 783 | .rates = ATMEL_SSC_RATES, |
757 | .formats = ATMEL_SSC_FORMATS,}, | 784 | .formats = ATMEL_SSC_FORMATS,}, |
758 | .ops = &atmel_ssc_dai_ops, | 785 | .ops = &atmel_ssc_dai_ops, |
759 | .private_data = &ssc_info[2], | ||
760 | }, | 786 | }, |
761 | #endif | 787 | #endif |
762 | }; | 788 | }; |
763 | EXPORT_SYMBOL_GPL(atmel_ssc_dai); | ||
764 | 789 | ||
765 | static int __init atmel_ssc_modinit(void) | 790 | static __devinit int asoc_ssc_probe(struct platform_device *pdev) |
791 | { | ||
792 | return snd_soc_register_dais(&pdev->dev, atmel_ssc_dai, | ||
793 | ARRAY_SIZE(atmel_ssc_dai)); | ||
794 | } | ||
795 | |||
796 | static int __devexit asoc_ssc_remove(struct platform_device *pdev) | ||
797 | { | ||
798 | snd_soc_unregister_dais(&pdev->dev, ARRAY_SIZE(atmel_ssc_dai)); | ||
799 | return 0; | ||
800 | } | ||
801 | |||
802 | static struct platform_driver asoc_ssc_driver = { | ||
803 | .driver = { | ||
804 | .name = "atmel-ssc-dai", | ||
805 | .owner = THIS_MODULE, | ||
806 | }, | ||
807 | |||
808 | .probe = asoc_ssc_probe, | ||
809 | .remove = __devexit_p(asoc_ssc_remove), | ||
810 | }; | ||
811 | |||
812 | static int __init snd_atmel_ssc_init(void) | ||
766 | { | 813 | { |
767 | return snd_soc_register_dais(atmel_ssc_dai, ARRAY_SIZE(atmel_ssc_dai)); | 814 | return platform_driver_register(&asoc_ssc_driver); |
768 | } | 815 | } |
769 | module_init(atmel_ssc_modinit); | 816 | module_init(snd_atmel_ssc_init); |
770 | 817 | ||
771 | static void __exit atmel_ssc_modexit(void) | 818 | static void __exit snd_atmel_ssc_exit(void) |
772 | { | 819 | { |
773 | snd_soc_unregister_dais(atmel_ssc_dai, ARRAY_SIZE(atmel_ssc_dai)); | 820 | platform_driver_unregister(&asoc_ssc_driver); |
774 | } | 821 | } |
775 | module_exit(atmel_ssc_modexit); | 822 | module_exit(snd_atmel_ssc_exit); |
776 | 823 | ||
777 | /* Module information */ | 824 | /* Module information */ |
778 | MODULE_AUTHOR("Sedji Gaouaou, sedji.gaouaou@atmel.com, www.atmel.com"); | 825 | MODULE_AUTHOR("Sedji Gaouaou, sedji.gaouaou@atmel.com, www.atmel.com"); |
diff --git a/sound/soc/atmel/atmel_ssc_dai.h b/sound/soc/atmel/atmel_ssc_dai.h index 391135f9c6c1..392a46953112 100644 --- a/sound/soc/atmel/atmel_ssc_dai.h +++ b/sound/soc/atmel/atmel_ssc_dai.h | |||
@@ -116,6 +116,5 @@ struct atmel_ssc_info { | |||
116 | struct atmel_pcm_dma_params *dma_params[2]; | 116 | struct atmel_pcm_dma_params *dma_params[2]; |
117 | struct atmel_ssc_state ssc_state; | 117 | struct atmel_ssc_state ssc_state; |
118 | }; | 118 | }; |
119 | extern struct snd_soc_dai atmel_ssc_dai[]; | ||
120 | 119 | ||
121 | #endif /* _AT91_SSC_DAI_H */ | 120 | #endif /* _AT91_SSC_DAI_H */ |
diff --git a/sound/soc/atmel/playpaq_wm8510.c b/sound/soc/atmel/playpaq_wm8510.c index 9df4c68ef000..5f4e59f4461c 100644 --- a/sound/soc/atmel/playpaq_wm8510.c +++ b/sound/soc/atmel/playpaq_wm8510.c | |||
@@ -83,7 +83,7 @@ static struct ssc_clock_data playpaq_wm8510_calc_ssc_clock( | |||
83 | struct snd_pcm_hw_params *params, | 83 | struct snd_pcm_hw_params *params, |
84 | struct snd_soc_dai *cpu_dai) | 84 | struct snd_soc_dai *cpu_dai) |
85 | { | 85 | { |
86 | struct at32_ssc_info *ssc_p = cpu_dai->private_data; | 86 | struct at32_ssc_info *ssc_p = snd_soc_dai_get_drvdata(cpu_dai); |
87 | struct ssc_device *ssc = ssc_p->ssc; | 87 | struct ssc_device *ssc = ssc_p->ssc; |
88 | struct ssc_clock_data cd; | 88 | struct ssc_clock_data cd; |
89 | unsigned int rate, width_bits, channels; | 89 | unsigned int rate, width_bits, channels; |
@@ -131,9 +131,9 @@ static int playpaq_wm8510_hw_params(struct snd_pcm_substream *substream, | |||
131 | struct snd_pcm_hw_params *params) | 131 | struct snd_pcm_hw_params *params) |
132 | { | 132 | { |
133 | struct snd_soc_pcm_runtime *rtd = substream->private_data; | 133 | struct snd_soc_pcm_runtime *rtd = substream->private_data; |
134 | struct snd_soc_dai *codec_dai = rtd->dai->codec_dai; | 134 | struct snd_soc_dai *codec_dai = rtd->codec_dai; |
135 | struct snd_soc_dai *cpu_dai = rtd->dai->cpu_dai; | 135 | struct snd_soc_dai *cpu_dai = rtd->cpu_dai; |
136 | struct at32_ssc_info *ssc_p = cpu_dai->private_data; | 136 | struct at32_ssc_info *ssc_p = snd_soc_dai_get_drvdata(cpu_dai); |
137 | struct ssc_device *ssc = ssc_p->ssc; | 137 | struct ssc_device *ssc = ssc_p->ssc; |
138 | unsigned int pll_out = 0, bclk = 0, mclk_div = 0; | 138 | unsigned int pll_out = 0, bclk = 0, mclk_div = 0; |
139 | int ret; | 139 | int ret; |
@@ -315,8 +315,9 @@ static const struct snd_soc_dapm_route intercon[] = { | |||
315 | 315 | ||
316 | 316 | ||
317 | 317 | ||
318 | static int playpaq_wm8510_init(struct snd_soc_codec *codec) | 318 | static int playpaq_wm8510_init(struct snd_soc_pcm_runtime *rtd) |
319 | { | 319 | { |
320 | struct snd_soc_codec *codec = rtd->codec; | ||
320 | int i; | 321 | int i; |
321 | 322 | ||
322 | /* | 323 | /* |
@@ -342,7 +343,7 @@ static int playpaq_wm8510_init(struct snd_soc_codec *codec) | |||
342 | 343 | ||
343 | 344 | ||
344 | /* Make CSB show PLL rate */ | 345 | /* Make CSB show PLL rate */ |
345 | snd_soc_dai_set_clkdiv(codec->dai, WM8510_OPCLKDIV, | 346 | snd_soc_dai_set_clkdiv(rtd->codec_dai, WM8510_OPCLKDIV, |
346 | WM8510_OPCLKDIV_1 | 4); | 347 | WM8510_OPCLKDIV_1 | 4); |
347 | 348 | ||
348 | return 0; | 349 | return 0; |
@@ -353,8 +354,10 @@ static int playpaq_wm8510_init(struct snd_soc_codec *codec) | |||
353 | static struct snd_soc_dai_link playpaq_wm8510_dai = { | 354 | static struct snd_soc_dai_link playpaq_wm8510_dai = { |
354 | .name = "WM8510", | 355 | .name = "WM8510", |
355 | .stream_name = "WM8510 PCM", | 356 | .stream_name = "WM8510 PCM", |
356 | .cpu_dai = &at32_ssc_dai[0], | 357 | .cpu_dai_name= "atmel-ssc-dai.0", |
357 | .codec_dai = &wm8510_dai, | 358 | .platform_name = "atmel-pcm-audio", |
359 | .codec_name = "wm8510-codec.0-0x1a", | ||
360 | .codec_dai_name = "wm8510-hifi", | ||
358 | .init = playpaq_wm8510_init, | 361 | .init = playpaq_wm8510_init, |
359 | .ops = &playpaq_wm8510_ops, | 362 | .ops = &playpaq_wm8510_ops, |
360 | }; | 363 | }; |
@@ -363,46 +366,16 @@ static struct snd_soc_dai_link playpaq_wm8510_dai = { | |||
363 | 366 | ||
364 | static struct snd_soc_card snd_soc_playpaq = { | 367 | static struct snd_soc_card snd_soc_playpaq = { |
365 | .name = "LRS_PlayPaq_WM8510", | 368 | .name = "LRS_PlayPaq_WM8510", |
366 | .platform = &at32_soc_platform, | ||
367 | .dai_link = &playpaq_wm8510_dai, | 369 | .dai_link = &playpaq_wm8510_dai, |
368 | .num_links = 1, | 370 | .num_links = 1, |
369 | }; | 371 | }; |
370 | 372 | ||
371 | |||
372 | |||
373 | static struct wm8510_setup_data playpaq_wm8510_setup = { | ||
374 | .i2c_bus = 0, | ||
375 | .i2c_address = 0x1a, | ||
376 | }; | ||
377 | |||
378 | |||
379 | |||
380 | static struct snd_soc_device playpaq_wm8510_snd_devdata = { | ||
381 | .card = &snd_soc_playpaq, | ||
382 | .codec_dev = &soc_codec_dev_wm8510, | ||
383 | .codec_data = &playpaq_wm8510_setup, | ||
384 | }; | ||
385 | |||
386 | static struct platform_device *playpaq_snd_device; | 373 | static struct platform_device *playpaq_snd_device; |
387 | 374 | ||
388 | 375 | ||
389 | static int __init playpaq_asoc_init(void) | 376 | static int __init playpaq_asoc_init(void) |
390 | { | 377 | { |
391 | int ret = 0; | 378 | int ret = 0; |
392 | struct at32_ssc_info *ssc_p = playpaq_wm8510_dai.cpu_dai->private_data; | ||
393 | struct ssc_device *ssc = NULL; | ||
394 | |||
395 | |||
396 | /* | ||
397 | * Request SSC device | ||
398 | */ | ||
399 | ssc = ssc_request(0); | ||
400 | if (IS_ERR(ssc)) { | ||
401 | ret = PTR_ERR(ssc); | ||
402 | goto err_ssc; | ||
403 | } | ||
404 | ssc_p->ssc = ssc; | ||
405 | |||
406 | 379 | ||
407 | /* | 380 | /* |
408 | * Configure MCLK for WM8510 | 381 | * Configure MCLK for WM8510 |
@@ -439,8 +412,7 @@ static int __init playpaq_asoc_init(void) | |||
439 | goto err_device_alloc; | 412 | goto err_device_alloc; |
440 | } | 413 | } |
441 | 414 | ||
442 | platform_set_drvdata(playpaq_snd_device, &playpaq_wm8510_snd_devdata); | 415 | platform_set_drvdata(playpaq_snd_device, &snd_soc_playpaq); |
443 | playpaq_wm8510_snd_devdata.dev = &playpaq_snd_device->dev; | ||
444 | 416 | ||
445 | ret = platform_device_add(playpaq_snd_device); | 417 | ret = platform_device_add(playpaq_snd_device); |
446 | if (ret) { | 418 | if (ret) { |
@@ -468,25 +440,12 @@ err_pll0: | |||
468 | clk_put(_gclk0); | 440 | clk_put(_gclk0); |
469 | _gclk0 = NULL; | 441 | _gclk0 = NULL; |
470 | } | 442 | } |
471 | err_gclk0: | ||
472 | ssc_free(ssc); | ||
473 | err_ssc: | ||
474 | return ret; | 443 | return ret; |
475 | } | 444 | } |
476 | 445 | ||
477 | 446 | ||
478 | static void __exit playpaq_asoc_exit(void) | 447 | static void __exit playpaq_asoc_exit(void) |
479 | { | 448 | { |
480 | struct at32_ssc_info *ssc_p = playpaq_wm8510_dai.cpu_dai->private_data; | ||
481 | struct ssc_device *ssc; | ||
482 | |||
483 | if (ssc_p != NULL) { | ||
484 | ssc = ssc_p->ssc; | ||
485 | if (ssc != NULL) | ||
486 | ssc_free(ssc); | ||
487 | ssc_p->ssc = NULL; | ||
488 | } | ||
489 | |||
490 | if (_gclk0 != NULL) { | 449 | if (_gclk0 != NULL) { |
491 | clk_put(_gclk0); | 450 | clk_put(_gclk0); |
492 | _gclk0 = NULL; | 451 | _gclk0 = NULL; |
diff --git a/sound/soc/atmel/sam9g20_wm8731.c b/sound/soc/atmel/sam9g20_wm8731.c index e028744c32ce..66a6f1879689 100644 --- a/sound/soc/atmel/sam9g20_wm8731.c +++ b/sound/soc/atmel/sam9g20_wm8731.c | |||
@@ -69,8 +69,8 @@ static int at91sam9g20ek_hw_params(struct snd_pcm_substream *substream, | |||
69 | struct snd_pcm_hw_params *params) | 69 | struct snd_pcm_hw_params *params) |
70 | { | 70 | { |
71 | struct snd_soc_pcm_runtime *rtd = substream->private_data; | 71 | struct snd_soc_pcm_runtime *rtd = substream->private_data; |
72 | struct snd_soc_dai *codec_dai = rtd->dai->codec_dai; | 72 | struct snd_soc_dai *codec_dai = rtd->codec_dai; |
73 | struct snd_soc_dai *cpu_dai = rtd->dai->cpu_dai; | 73 | struct snd_soc_dai *cpu_dai = rtd->cpu_dai; |
74 | int ret; | 74 | int ret; |
75 | 75 | ||
76 | /* set codec DAI configuration */ | 76 | /* set codec DAI configuration */ |
@@ -136,9 +136,10 @@ static const struct snd_soc_dapm_route intercon[] = { | |||
136 | /* | 136 | /* |
137 | * Logic for a wm8731 as connected on a at91sam9g20ek board. | 137 | * Logic for a wm8731 as connected on a at91sam9g20ek board. |
138 | */ | 138 | */ |
139 | static int at91sam9g20ek_wm8731_init(struct snd_soc_codec *codec) | 139 | static int at91sam9g20ek_wm8731_init(struct snd_soc_pcm_runtime *rtd) |
140 | { | 140 | { |
141 | struct snd_soc_dai *codec_dai = &codec->dai[0]; | 141 | struct snd_soc_codec *codec = rtd->codec; |
142 | struct snd_soc_dai *codec_dai = rtd->codec_dai; | ||
142 | int ret; | 143 | int ret; |
143 | 144 | ||
144 | printk(KERN_DEBUG | 145 | printk(KERN_DEBUG |
@@ -179,31 +180,25 @@ static int at91sam9g20ek_wm8731_init(struct snd_soc_codec *codec) | |||
179 | static struct snd_soc_dai_link at91sam9g20ek_dai = { | 180 | static struct snd_soc_dai_link at91sam9g20ek_dai = { |
180 | .name = "WM8731", | 181 | .name = "WM8731", |
181 | .stream_name = "WM8731 PCM", | 182 | .stream_name = "WM8731 PCM", |
182 | .cpu_dai = &atmel_ssc_dai[0], | 183 | .cpu_dai_name = "atmel-ssc-dai.0", |
183 | .codec_dai = &wm8731_dai, | 184 | .codec_dai_name = "wm8731-hifi", |
184 | .init = at91sam9g20ek_wm8731_init, | 185 | .init = at91sam9g20ek_wm8731_init, |
186 | .platform_name = "atmel_pcm-audio", | ||
187 | .codec_name = "wm8731-codec.0-001a", | ||
185 | .ops = &at91sam9g20ek_ops, | 188 | .ops = &at91sam9g20ek_ops, |
186 | }; | 189 | }; |
187 | 190 | ||
188 | static struct snd_soc_card snd_soc_at91sam9g20ek = { | 191 | static struct snd_soc_card snd_soc_at91sam9g20ek = { |
189 | .name = "AT91SAMG20-EK", | 192 | .name = "AT91SAMG20-EK", |
190 | .platform = &atmel_soc_platform, | ||
191 | .dai_link = &at91sam9g20ek_dai, | 193 | .dai_link = &at91sam9g20ek_dai, |
192 | .num_links = 1, | 194 | .num_links = 1, |
193 | .set_bias_level = at91sam9g20ek_set_bias_level, | 195 | .set_bias_level = at91sam9g20ek_set_bias_level, |
194 | }; | 196 | }; |
195 | 197 | ||
196 | static struct snd_soc_device at91sam9g20ek_snd_devdata = { | ||
197 | .card = &snd_soc_at91sam9g20ek, | ||
198 | .codec_dev = &soc_codec_dev_wm8731, | ||
199 | }; | ||
200 | |||
201 | static struct platform_device *at91sam9g20ek_snd_device; | 198 | static struct platform_device *at91sam9g20ek_snd_device; |
202 | 199 | ||
203 | static int __init at91sam9g20ek_init(void) | 200 | static int __init at91sam9g20ek_init(void) |
204 | { | 201 | { |
205 | struct atmel_ssc_info *ssc_p = at91sam9g20ek_dai.cpu_dai->private_data; | ||
206 | struct ssc_device *ssc = NULL; | ||
207 | struct clk *pllb; | 202 | struct clk *pllb; |
208 | int ret; | 203 | int ret; |
209 | 204 | ||
@@ -235,18 +230,6 @@ static int __init at91sam9g20ek_init(void) | |||
235 | 230 | ||
236 | clk_set_rate(mclk, MCLK_RATE); | 231 | clk_set_rate(mclk, MCLK_RATE); |
237 | 232 | ||
238 | /* | ||
239 | * Request SSC device | ||
240 | */ | ||
241 | ssc = ssc_request(0); | ||
242 | if (IS_ERR(ssc)) { | ||
243 | printk(KERN_ERR "ASoC: Failed to request SSC 0\n"); | ||
244 | ret = PTR_ERR(ssc); | ||
245 | ssc = NULL; | ||
246 | goto err_ssc; | ||
247 | } | ||
248 | ssc_p->ssc = ssc; | ||
249 | |||
250 | at91sam9g20ek_snd_device = platform_device_alloc("soc-audio", -1); | 233 | at91sam9g20ek_snd_device = platform_device_alloc("soc-audio", -1); |
251 | if (!at91sam9g20ek_snd_device) { | 234 | if (!at91sam9g20ek_snd_device) { |
252 | printk(KERN_ERR "ASoC: Platform device allocation failed\n"); | 235 | printk(KERN_ERR "ASoC: Platform device allocation failed\n"); |
@@ -254,8 +237,7 @@ static int __init at91sam9g20ek_init(void) | |||
254 | } | 237 | } |
255 | 238 | ||
256 | platform_set_drvdata(at91sam9g20ek_snd_device, | 239 | platform_set_drvdata(at91sam9g20ek_snd_device, |
257 | &at91sam9g20ek_snd_devdata); | 240 | &snd_soc_at91sam9g20ek); |
258 | at91sam9g20ek_snd_devdata.dev = &at91sam9g20ek_snd_device->dev; | ||
259 | 241 | ||
260 | ret = platform_device_add(at91sam9g20ek_snd_device); | 242 | ret = platform_device_add(at91sam9g20ek_snd_device); |
261 | if (ret) { | 243 | if (ret) { |
@@ -265,9 +247,6 @@ static int __init at91sam9g20ek_init(void) | |||
265 | 247 | ||
266 | return ret; | 248 | return ret; |
267 | 249 | ||
268 | err_ssc: | ||
269 | ssc_free(ssc); | ||
270 | ssc_p->ssc = NULL; | ||
271 | err_mclk: | 250 | err_mclk: |
272 | clk_put(mclk); | 251 | clk_put(mclk); |
273 | mclk = NULL; | 252 | mclk = NULL; |
@@ -277,16 +256,6 @@ err: | |||
277 | 256 | ||
278 | static void __exit at91sam9g20ek_exit(void) | 257 | static void __exit at91sam9g20ek_exit(void) |
279 | { | 258 | { |
280 | struct atmel_ssc_info *ssc_p = at91sam9g20ek_dai.cpu_dai->private_data; | ||
281 | struct ssc_device *ssc; | ||
282 | |||
283 | if (ssc_p != NULL) { | ||
284 | ssc = ssc_p->ssc; | ||
285 | if (ssc != NULL) | ||
286 | ssc_free(ssc); | ||
287 | ssc_p->ssc = NULL; | ||
288 | } | ||
289 | |||
290 | platform_device_unregister(at91sam9g20ek_snd_device); | 259 | platform_device_unregister(at91sam9g20ek_snd_device); |
291 | at91sam9g20ek_snd_device = NULL; | 260 | at91sam9g20ek_snd_device = NULL; |
292 | clk_put(mclk); | 261 | clk_put(mclk); |
diff --git a/sound/soc/atmel/snd-soc-afeb9260.c b/sound/soc/atmel/snd-soc-afeb9260.c index 23349de27313..e3d283561c19 100644 --- a/sound/soc/atmel/snd-soc-afeb9260.c +++ b/sound/soc/atmel/snd-soc-afeb9260.c | |||
@@ -46,8 +46,8 @@ static int afeb9260_hw_params(struct snd_pcm_substream *substream, | |||
46 | struct snd_pcm_hw_params *params) | 46 | struct snd_pcm_hw_params *params) |
47 | { | 47 | { |
48 | struct snd_soc_pcm_runtime *rtd = substream->private_data; | 48 | struct snd_soc_pcm_runtime *rtd = substream->private_data; |
49 | struct snd_soc_dai *codec_dai = rtd->dai->codec_dai; | 49 | struct snd_soc_dai *codec_dai = rtd->codec_dai; |
50 | struct snd_soc_dai *cpu_dai = rtd->dai->cpu_dai; | 50 | struct snd_soc_dai *cpu_dai = rtd->cpu_dai; |
51 | int err; | 51 | int err; |
52 | 52 | ||
53 | /* Set codec DAI configuration */ | 53 | /* Set codec DAI configuration */ |
@@ -102,8 +102,9 @@ static const struct snd_soc_dapm_route audio_map[] = { | |||
102 | {"MICIN", NULL, "Mic Jack"}, | 102 | {"MICIN", NULL, "Mic Jack"}, |
103 | }; | 103 | }; |
104 | 104 | ||
105 | static int afeb9260_tlv320aic23_init(struct snd_soc_codec *codec) | 105 | static int afeb9260_tlv320aic23_init(struct snd_soc_pcm_runtime *rtd) |
106 | { | 106 | { |
107 | struct snd_soc_codec *codec = rtd->codec; | ||
107 | 108 | ||
108 | /* Add afeb9260 specific widgets */ | 109 | /* Add afeb9260 specific widgets */ |
109 | snd_soc_dapm_new_controls(codec, tlv320aic23_dapm_widgets, | 110 | snd_soc_dapm_new_controls(codec, tlv320aic23_dapm_widgets, |
@@ -125,8 +126,10 @@ static int afeb9260_tlv320aic23_init(struct snd_soc_codec *codec) | |||
125 | static struct snd_soc_dai_link afeb9260_dai = { | 126 | static struct snd_soc_dai_link afeb9260_dai = { |
126 | .name = "TLV320AIC23", | 127 | .name = "TLV320AIC23", |
127 | .stream_name = "AIC23", | 128 | .stream_name = "AIC23", |
128 | .cpu_dai = &atmel_ssc_dai[0], | 129 | .cpu_dai_name = "atmel-ssc-dai.0", |
129 | .codec_dai = &tlv320aic23_dai, | 130 | .codec_dai_name = "tlv320aic23-hifi", |
131 | .platform_name = "atmel_pcm-audio", | ||
132 | .codec_name = "tlv320aic23-codec.0-0x1a", | ||
130 | .init = afeb9260_tlv320aic23_init, | 133 | .init = afeb9260_tlv320aic23_init, |
131 | .ops = &afeb9260_ops, | 134 | .ops = &afeb9260_ops, |
132 | }; | 135 | }; |
@@ -134,37 +137,20 @@ static struct snd_soc_dai_link afeb9260_dai = { | |||
134 | /* Audio machine driver */ | 137 | /* Audio machine driver */ |
135 | static struct snd_soc_card snd_soc_machine_afeb9260 = { | 138 | static struct snd_soc_card snd_soc_machine_afeb9260 = { |
136 | .name = "AFEB9260", | 139 | .name = "AFEB9260", |
137 | .platform = &atmel_soc_platform, | ||
138 | .dai_link = &afeb9260_dai, | 140 | .dai_link = &afeb9260_dai, |
139 | .num_links = 1, | 141 | .num_links = 1, |
140 | }; | 142 | }; |
141 | 143 | ||
142 | /* Audio subsystem */ | ||
143 | static struct snd_soc_device afeb9260_snd_devdata = { | ||
144 | .card = &snd_soc_machine_afeb9260, | ||
145 | .codec_dev = &soc_codec_dev_tlv320aic23, | ||
146 | }; | ||
147 | |||
148 | static struct platform_device *afeb9260_snd_device; | 144 | static struct platform_device *afeb9260_snd_device; |
149 | 145 | ||
150 | static int __init afeb9260_soc_init(void) | 146 | static int __init afeb9260_soc_init(void) |
151 | { | 147 | { |
152 | int err; | 148 | int err; |
153 | struct device *dev; | 149 | struct device *dev; |
154 | struct atmel_ssc_info *ssc_p = afeb9260_dai.cpu_dai->private_data; | ||
155 | struct ssc_device *ssc = NULL; | ||
156 | 150 | ||
157 | if (!(machine_is_afeb9260())) | 151 | if (!(machine_is_afeb9260())) |
158 | return -ENODEV; | 152 | return -ENODEV; |
159 | 153 | ||
160 | ssc = ssc_request(0); | ||
161 | if (IS_ERR(ssc)) { | ||
162 | printk(KERN_ERR "ASoC: Failed to request SSC 0\n"); | ||
163 | err = PTR_ERR(ssc); | ||
164 | ssc = NULL; | ||
165 | goto err_ssc; | ||
166 | } | ||
167 | ssc_p->ssc = ssc; | ||
168 | 154 | ||
169 | afeb9260_snd_device = platform_device_alloc("soc-audio", -1); | 155 | afeb9260_snd_device = platform_device_alloc("soc-audio", -1); |
170 | if (!afeb9260_snd_device) { | 156 | if (!afeb9260_snd_device) { |
@@ -172,8 +158,7 @@ static int __init afeb9260_soc_init(void) | |||
172 | return -ENOMEM; | 158 | return -ENOMEM; |
173 | } | 159 | } |
174 | 160 | ||
175 | platform_set_drvdata(afeb9260_snd_device, &afeb9260_snd_devdata); | 161 | platform_set_drvdata(afeb9260_snd_device, &snd_soc_machine_afeb9260); |
176 | afeb9260_snd_devdata.dev = &afeb9260_snd_device->dev; | ||
177 | err = platform_device_add(afeb9260_snd_device); | 162 | err = platform_device_add(afeb9260_snd_device); |
178 | if (err) | 163 | if (err) |
179 | goto err1; | 164 | goto err1; |
@@ -184,9 +169,7 @@ static int __init afeb9260_soc_init(void) | |||
184 | err1: | 169 | err1: |
185 | platform_device_del(afeb9260_snd_device); | 170 | platform_device_del(afeb9260_snd_device); |
186 | platform_device_put(afeb9260_snd_device); | 171 | platform_device_put(afeb9260_snd_device); |
187 | err_ssc: | ||
188 | return err; | 172 | return err; |
189 | |||
190 | } | 173 | } |
191 | 174 | ||
192 | static void __exit afeb9260_soc_exit(void) | 175 | static void __exit afeb9260_soc_exit(void) |
diff --git a/sound/soc/au1x/db1200.c b/sound/soc/au1x/db1200.c index cdf7be1b9b91..8780c90107fc 100644 --- a/sound/soc/au1x/db1200.c +++ b/sound/soc/au1x/db1200.c | |||
@@ -19,7 +19,6 @@ | |||
19 | #include <asm/mach-au1x00/au1xxx_dbdma.h> | 19 | #include <asm/mach-au1x00/au1xxx_dbdma.h> |
20 | #include <asm/mach-db1x00/bcsr.h> | 20 | #include <asm/mach-db1x00/bcsr.h> |
21 | 21 | ||
22 | #include "../codecs/ac97.h" | ||
23 | #include "../codecs/wm8731.h" | 22 | #include "../codecs/wm8731.h" |
24 | #include "psc.h" | 23 | #include "psc.h" |
25 | 24 | ||
@@ -28,20 +27,16 @@ | |||
28 | static struct snd_soc_dai_link db1200_ac97_dai = { | 27 | static struct snd_soc_dai_link db1200_ac97_dai = { |
29 | .name = "AC97", | 28 | .name = "AC97", |
30 | .stream_name = "AC97 HiFi", | 29 | .stream_name = "AC97 HiFi", |
31 | .cpu_dai = &au1xpsc_ac97_dai, | 30 | .cpu_dai_name = "au1xpsc-ac97", |
32 | .codec_dai = &ac97_dai, | 31 | .codec_dai_name = "ac97-hifi", |
32 | .platform_name = "au1xpsc-pcm-audio", | ||
33 | .codec_name = "ac97-codec", | ||
33 | }; | 34 | }; |
34 | 35 | ||
35 | static struct snd_soc_card db1200_ac97_machine = { | 36 | static struct snd_soc_card db1200_ac97_machine = { |
36 | .name = "DB1200_AC97", | 37 | .name = "DB1200_AC97", |
37 | .dai_link = &db1200_ac97_dai, | 38 | .dai_link = &db1200_ac97_dai, |
38 | .num_links = 1, | 39 | .num_links = 1, |
39 | .platform = &au1xpsc_soc_platform, | ||
40 | }; | ||
41 | |||
42 | static struct snd_soc_device db1200_ac97_devdata = { | ||
43 | .card = &db1200_ac97_machine, | ||
44 | .codec_dev = &soc_codec_dev_ac97, | ||
45 | }; | 40 | }; |
46 | 41 | ||
47 | /*------------------------- I2S PART ---------------------------*/ | 42 | /*------------------------- I2S PART ---------------------------*/ |
@@ -49,8 +44,8 @@ static struct snd_soc_device db1200_ac97_devdata = { | |||
49 | static int db1200_i2s_startup(struct snd_pcm_substream *substream) | 44 | static int db1200_i2s_startup(struct snd_pcm_substream *substream) |
50 | { | 45 | { |
51 | struct snd_soc_pcm_runtime *rtd = substream->private_data; | 46 | struct snd_soc_pcm_runtime *rtd = substream->private_data; |
52 | struct snd_soc_dai *codec_dai = rtd->dai->codec_dai; | 47 | struct snd_soc_dai *codec_dai = rtd->codec_dai; |
53 | struct snd_soc_dai *cpu_dai = rtd->dai->cpu_dai; | 48 | struct snd_soc_dai *cpu_dai = rtd->cpu_dai; |
54 | int ret; | 49 | int ret; |
55 | 50 | ||
56 | /* WM8731 has its own 12MHz crystal */ | 51 | /* WM8731 has its own 12MHz crystal */ |
@@ -80,8 +75,10 @@ static struct snd_soc_ops db1200_i2s_wm8731_ops = { | |||
80 | static struct snd_soc_dai_link db1200_i2s_dai = { | 75 | static struct snd_soc_dai_link db1200_i2s_dai = { |
81 | .name = "WM8731", | 76 | .name = "WM8731", |
82 | .stream_name = "WM8731 PCM", | 77 | .stream_name = "WM8731 PCM", |
83 | .cpu_dai = &au1xpsc_i2s_dai, | 78 | .cpu_dai_name = "au1xpsc", |
84 | .codec_dai = &wm8731_dai, | 79 | .codec_dai_name = "wm8731-hifi" |
80 | .platform_name = "au1xpsc-pcm-audio", | ||
81 | .codec_name = "wm8731-codec.0-001a", | ||
85 | .ops = &db1200_i2s_wm8731_ops, | 82 | .ops = &db1200_i2s_wm8731_ops, |
86 | }; | 83 | }; |
87 | 84 | ||
@@ -89,12 +86,6 @@ static struct snd_soc_card db1200_i2s_machine = { | |||
89 | .name = "DB1200_I2S", | 86 | .name = "DB1200_I2S", |
90 | .dai_link = &db1200_i2s_dai, | 87 | .dai_link = &db1200_i2s_dai, |
91 | .num_links = 1, | 88 | .num_links = 1, |
92 | .platform = &au1xpsc_soc_platform, | ||
93 | }; | ||
94 | |||
95 | static struct snd_soc_device db1200_i2s_devdata = { | ||
96 | .card = &db1200_i2s_machine, | ||
97 | .codec_dev = &soc_codec_dev_wm8731, | ||
98 | }; | 89 | }; |
99 | 90 | ||
100 | /*------------------------- COMMON PART ---------------------------*/ | 91 | /*------------------------- COMMON PART ---------------------------*/ |
@@ -112,12 +103,10 @@ static int __init db1200_audio_load(void) | |||
112 | 103 | ||
113 | /* DB1200 board setup set PSC1MUX to preferred audio device */ | 104 | /* DB1200 board setup set PSC1MUX to preferred audio device */ |
114 | if (bcsr_read(BCSR_RESETS) & BCSR_RESETS_PSC1MUX) | 105 | if (bcsr_read(BCSR_RESETS) & BCSR_RESETS_PSC1MUX) |
115 | platform_set_drvdata(db1200_asoc_dev, &db1200_i2s_devdata); | 106 | platform_set_drvdata(db1200_asoc_dev, &db1200_i2s_machine); |
116 | else | 107 | else |
117 | platform_set_drvdata(db1200_asoc_dev, &db1200_ac97_devdata); | 108 | platform_set_drvdata(db1200_asoc_dev, &db1200_ac97_machine); |
118 | 109 | ||
119 | db1200_ac97_devdata.dev = &db1200_asoc_dev->dev; | ||
120 | db1200_i2s_devdata.dev = &db1200_asoc_dev->dev; | ||
121 | ret = platform_device_add(db1200_asoc_dev); | 110 | ret = platform_device_add(db1200_asoc_dev); |
122 | 111 | ||
123 | if (ret) { | 112 | if (ret) { |
diff --git a/sound/soc/au1x/dbdma2.c b/sound/soc/au1x/dbdma2.c index 6d9f4c624949..00fdb9cbfc2d 100644 --- a/sound/soc/au1x/dbdma2.c +++ b/sound/soc/au1x/dbdma2.c | |||
@@ -329,7 +329,7 @@ static int au1xpsc_pcm_new(struct snd_card *card, | |||
329 | return 0; | 329 | return 0; |
330 | } | 330 | } |
331 | 331 | ||
332 | static int au1xpsc_pcm_probe(struct platform_device *pdev) | 332 | static int au1xpsc_pcm_probe(struct snd_soc_platform *platform) |
333 | { | 333 | { |
334 | if (!au1xpsc_audio_pcmdma[PCM_TX] || !au1xpsc_audio_pcmdma[PCM_RX]) | 334 | if (!au1xpsc_audio_pcmdma[PCM_TX] || !au1xpsc_audio_pcmdma[PCM_RX]) |
335 | return -ENODEV; | 335 | return -ENODEV; |
@@ -337,17 +337,10 @@ static int au1xpsc_pcm_probe(struct platform_device *pdev) | |||
337 | return 0; | 337 | return 0; |
338 | } | 338 | } |
339 | 339 | ||
340 | static int au1xpsc_pcm_remove(struct platform_device *pdev) | ||
341 | { | ||
342 | return 0; | ||
343 | } | ||
344 | |||
345 | /* au1xpsc audio platform */ | 340 | /* au1xpsc audio platform */ |
346 | struct snd_soc_platform au1xpsc_soc_platform = { | 341 | struct snd_soc_platform_driver au1xpsc_soc_platform = { |
347 | .name = "au1xpsc-pcm-dbdma", | ||
348 | .probe = au1xpsc_pcm_probe, | 342 | .probe = au1xpsc_pcm_probe, |
349 | .remove = au1xpsc_pcm_remove, | 343 | .ops = &au1xpsc_pcm_ops, |
350 | .pcm_ops = &au1xpsc_pcm_ops, | ||
351 | .pcm_new = au1xpsc_pcm_new, | 344 | .pcm_new = au1xpsc_pcm_new, |
352 | .pcm_free = au1xpsc_pcm_free_dma_buffers, | 345 | .pcm_free = au1xpsc_pcm_free_dma_buffers, |
353 | }; | 346 | }; |
@@ -387,7 +380,7 @@ static int __devinit au1xpsc_pcm_drvprobe(struct platform_device *pdev) | |||
387 | } | 380 | } |
388 | (au1xpsc_audio_pcmdma[PCM_RX])->ddma_id = r->start; | 381 | (au1xpsc_audio_pcmdma[PCM_RX])->ddma_id = r->start; |
389 | 382 | ||
390 | ret = snd_soc_register_platform(&au1xpsc_soc_platform); | 383 | ret = snd_soc_register_platform(&pdev->dev, &au1xpsc_soc_platform); |
391 | if (!ret) | 384 | if (!ret) |
392 | return ret; | 385 | return ret; |
393 | 386 | ||
@@ -404,7 +397,7 @@ static int __devexit au1xpsc_pcm_drvremove(struct platform_device *pdev) | |||
404 | { | 397 | { |
405 | int i; | 398 | int i; |
406 | 399 | ||
407 | snd_soc_unregister_platform(&au1xpsc_soc_platform); | 400 | snd_soc_unregister_platform(&pdev->dev); |
408 | 401 | ||
409 | for (i = 0; i < 2; i++) { | 402 | for (i = 0; i < 2; i++) { |
410 | if (au1xpsc_audio_pcmdma[i]) { | 403 | if (au1xpsc_audio_pcmdma[i]) { |
@@ -419,7 +412,7 @@ static int __devexit au1xpsc_pcm_drvremove(struct platform_device *pdev) | |||
419 | 412 | ||
420 | static struct platform_driver au1xpsc_pcm_driver = { | 413 | static struct platform_driver au1xpsc_pcm_driver = { |
421 | .driver = { | 414 | .driver = { |
422 | .name = "au1xpsc-pcm", | 415 | .name = "au1xpsc-pcm-audio", |
423 | .owner = THIS_MODULE, | 416 | .owner = THIS_MODULE, |
424 | }, | 417 | }, |
425 | .probe = au1xpsc_pcm_drvprobe, | 418 | .probe = au1xpsc_pcm_drvprobe, |
diff --git a/sound/soc/au1x/psc-ac97.c b/sound/soc/au1x/psc-ac97.c index d14a5a91a465..6a9516cbe424 100644 --- a/sound/soc/au1x/psc-ac97.c +++ b/sound/soc/au1x/psc-ac97.c | |||
@@ -315,27 +315,19 @@ static int au1xpsc_ac97_trigger(struct snd_pcm_substream *substream, | |||
315 | return ret; | 315 | return ret; |
316 | } | 316 | } |
317 | 317 | ||
318 | static int au1xpsc_ac97_probe(struct platform_device *pdev, | 318 | static int au1xpsc_ac97_probe(struct snd_soc_dai *dai) |
319 | struct snd_soc_dai *dai) | ||
320 | { | 319 | { |
321 | return au1xpsc_ac97_workdata ? 0 : -ENODEV; | 320 | return au1xpsc_ac97_workdata ? 0 : -ENODEV; |
322 | } | 321 | } |
323 | 322 | ||
324 | static void au1xpsc_ac97_remove(struct platform_device *pdev, | ||
325 | struct snd_soc_dai *dai) | ||
326 | { | ||
327 | } | ||
328 | |||
329 | static struct snd_soc_dai_ops au1xpsc_ac97_dai_ops = { | 323 | static struct snd_soc_dai_ops au1xpsc_ac97_dai_ops = { |
330 | .trigger = au1xpsc_ac97_trigger, | 324 | .trigger = au1xpsc_ac97_trigger, |
331 | .hw_params = au1xpsc_ac97_hw_params, | 325 | .hw_params = au1xpsc_ac97_hw_params, |
332 | }; | 326 | }; |
333 | 327 | ||
334 | struct snd_soc_dai au1xpsc_ac97_dai = { | 328 | struct snd_soc_dai_driver au1xpsc_ac97_dai = { |
335 | .name = "au1xpsc_ac97", | ||
336 | .ac97_control = 1, | 329 | .ac97_control = 1, |
337 | .probe = au1xpsc_ac97_probe, | 330 | .probe = au1xpsc_ac97_probe, |
338 | .remove = au1xpsc_ac97_remove, | ||
339 | .playback = { | 331 | .playback = { |
340 | .rates = AC97_RATES, | 332 | .rates = AC97_RATES, |
341 | .formats = AC97_FMTS, | 333 | .formats = AC97_FMTS, |
@@ -395,7 +387,7 @@ static int __devinit au1xpsc_ac97_drvprobe(struct platform_device *pdev) | |||
395 | au_writel(PSC_SEL_PS_AC97MODE | sel, PSC_SEL(wd)); | 387 | au_writel(PSC_SEL_PS_AC97MODE | sel, PSC_SEL(wd)); |
396 | au_sync(); | 388 | au_sync(); |
397 | 389 | ||
398 | ret = snd_soc_register_dai(&au1xpsc_ac97_dai); | 390 | ret = snd_soc_register_dai(&pdev->dev, &au1xpsc_ac97_dai); |
399 | if (ret) | 391 | if (ret) |
400 | goto out1; | 392 | goto out1; |
401 | 393 | ||
@@ -406,7 +398,7 @@ static int __devinit au1xpsc_ac97_drvprobe(struct platform_device *pdev) | |||
406 | return 0; | 398 | return 0; |
407 | } | 399 | } |
408 | 400 | ||
409 | snd_soc_unregister_dai(&au1xpsc_ac97_dai); | 401 | snd_soc_unregister_dai(&pdev->dev); |
410 | out1: | 402 | out1: |
411 | release_mem_region(r->start, resource_size(r)); | 403 | release_mem_region(r->start, resource_size(r)); |
412 | out0: | 404 | out0: |
@@ -422,7 +414,7 @@ static int __devexit au1xpsc_ac97_drvremove(struct platform_device *pdev) | |||
422 | if (wd->dmapd) | 414 | if (wd->dmapd) |
423 | au1xpsc_pcm_destroy(wd->dmapd); | 415 | au1xpsc_pcm_destroy(wd->dmapd); |
424 | 416 | ||
425 | snd_soc_unregister_dai(&au1xpsc_ac97_dai); | 417 | snd_soc_unregister_dai(&pdev->dev); |
426 | 418 | ||
427 | /* disable PSC completely */ | 419 | /* disable PSC completely */ |
428 | au_writel(0, AC97_CFG(wd)); | 420 | au_writel(0, AC97_CFG(wd)); |
@@ -485,7 +477,7 @@ static struct dev_pm_ops au1xpscac97_pmops = { | |||
485 | 477 | ||
486 | static struct platform_driver au1xpsc_ac97_driver = { | 478 | static struct platform_driver au1xpsc_ac97_driver = { |
487 | .driver = { | 479 | .driver = { |
488 | .name = "au1xpsc_ac97", | 480 | .name = "au1xpsc-ac97", |
489 | .owner = THIS_MODULE, | 481 | .owner = THIS_MODULE, |
490 | .pm = AU1XPSCAC97_PMOPS, | 482 | .pm = AU1XPSCAC97_PMOPS, |
491 | }, | 483 | }, |
diff --git a/sound/soc/au1x/psc-i2s.c b/sound/soc/au1x/psc-i2s.c index 6083fe7799fa..94e560a8756d 100644 --- a/sound/soc/au1x/psc-i2s.c +++ b/sound/soc/au1x/psc-i2s.c | |||
@@ -263,27 +263,19 @@ static int au1xpsc_i2s_trigger(struct snd_pcm_substream *substream, int cmd, | |||
263 | return ret; | 263 | return ret; |
264 | } | 264 | } |
265 | 265 | ||
266 | static int au1xpsc_i2s_probe(struct platform_device *pdev, | 266 | static int au1xpsc_i2s_probe(struct snd_soc_dai *dai) |
267 | struct snd_soc_dai *dai) | ||
268 | { | 267 | { |
269 | return au1xpsc_i2s_workdata ? 0 : -ENODEV; | 268 | return au1xpsc_i2s_workdata ? 0 : -ENODEV; |
270 | } | 269 | } |
271 | 270 | ||
272 | static void au1xpsc_i2s_remove(struct platform_device *pdev, | ||
273 | struct snd_soc_dai *dai) | ||
274 | { | ||
275 | } | ||
276 | |||
277 | static struct snd_soc_dai_ops au1xpsc_i2s_dai_ops = { | 271 | static struct snd_soc_dai_ops au1xpsc_i2s_dai_ops = { |
278 | .trigger = au1xpsc_i2s_trigger, | 272 | .trigger = au1xpsc_i2s_trigger, |
279 | .hw_params = au1xpsc_i2s_hw_params, | 273 | .hw_params = au1xpsc_i2s_hw_params, |
280 | .set_fmt = au1xpsc_i2s_set_fmt, | 274 | .set_fmt = au1xpsc_i2s_set_fmt, |
281 | }; | 275 | }; |
282 | 276 | ||
283 | struct snd_soc_dai au1xpsc_i2s_dai = { | 277 | static struct snd_soc_dai_driver au1xpsc_i2s_dai = { |
284 | .name = "au1xpsc_i2s", | ||
285 | .probe = au1xpsc_i2s_probe, | 278 | .probe = au1xpsc_i2s_probe, |
286 | .remove = au1xpsc_i2s_remove, | ||
287 | .playback = { | 279 | .playback = { |
288 | .rates = AU1XPSC_I2S_RATES, | 280 | .rates = AU1XPSC_I2S_RATES, |
289 | .formats = AU1XPSC_I2S_FMTS, | 281 | .formats = AU1XPSC_I2S_FMTS, |
@@ -298,7 +290,6 @@ struct snd_soc_dai au1xpsc_i2s_dai = { | |||
298 | }, | 290 | }, |
299 | .ops = &au1xpsc_i2s_dai_ops, | 291 | .ops = &au1xpsc_i2s_dai_ops, |
300 | }; | 292 | }; |
301 | EXPORT_SYMBOL(au1xpsc_i2s_dai); | ||
302 | 293 | ||
303 | static int __devinit au1xpsc_i2s_drvprobe(struct platform_device *pdev) | 294 | static int __devinit au1xpsc_i2s_drvprobe(struct platform_device *pdev) |
304 | { | 295 | { |
@@ -346,7 +337,7 @@ static int __devinit au1xpsc_i2s_drvprobe(struct platform_device *pdev) | |||
346 | * time out. | 337 | * time out. |
347 | */ | 338 | */ |
348 | 339 | ||
349 | ret = snd_soc_register_dai(&au1xpsc_i2s_dai); | 340 | ret = snd_soc_register_dai(&pdev->dev, &au1xpsc_i2s_dai); |
350 | if (ret) | 341 | if (ret) |
351 | goto out1; | 342 | goto out1; |
352 | 343 | ||
@@ -358,7 +349,7 @@ static int __devinit au1xpsc_i2s_drvprobe(struct platform_device *pdev) | |||
358 | return 0; | 349 | return 0; |
359 | } | 350 | } |
360 | 351 | ||
361 | snd_soc_unregister_dai(&au1xpsc_i2s_dai); | 352 | snd_soc_unregister_dai(&pdev->dev); |
362 | out1: | 353 | out1: |
363 | release_mem_region(r->start, resource_size(r)); | 354 | release_mem_region(r->start, resource_size(r)); |
364 | out0: | 355 | out0: |
@@ -374,7 +365,7 @@ static int __devexit au1xpsc_i2s_drvremove(struct platform_device *pdev) | |||
374 | if (wd->dmapd) | 365 | if (wd->dmapd) |
375 | au1xpsc_pcm_destroy(wd->dmapd); | 366 | au1xpsc_pcm_destroy(wd->dmapd); |
376 | 367 | ||
377 | snd_soc_unregister_dai(&au1xpsc_i2s_dai); | 368 | snd_soc_unregister_dai(&pdev->dev); |
378 | 369 | ||
379 | au_writel(0, I2S_CFG(wd)); | 370 | au_writel(0, I2S_CFG(wd)); |
380 | au_sync(); | 371 | au_sync(); |
@@ -436,7 +427,7 @@ static struct dev_pm_ops au1xpsci2s_pmops = { | |||
436 | 427 | ||
437 | static struct platform_driver au1xpsc_i2s_driver = { | 428 | static struct platform_driver au1xpsc_i2s_driver = { |
438 | .driver = { | 429 | .driver = { |
439 | .name = "au1xpsc_i2s", | 430 | .name = "au1xpsc", |
440 | .owner = THIS_MODULE, | 431 | .owner = THIS_MODULE, |
441 | .pm = AU1XPSCI2S_PMOPS, | 432 | .pm = AU1XPSCI2S_PMOPS, |
442 | }, | 433 | }, |
diff --git a/sound/soc/au1x/psc.h b/sound/soc/au1x/psc.h index 093775d4dc3e..f281443fd52f 100644 --- a/sound/soc/au1x/psc.h +++ b/sound/soc/au1x/psc.h | |||
@@ -16,9 +16,6 @@ | |||
16 | #ifndef _AU1X_PCM_H | 16 | #ifndef _AU1X_PCM_H |
17 | #define _AU1X_PCM_H | 17 | #define _AU1X_PCM_H |
18 | 18 | ||
19 | extern struct snd_soc_dai au1xpsc_ac97_dai; | ||
20 | extern struct snd_soc_dai au1xpsc_i2s_dai; | ||
21 | extern struct snd_soc_platform au1xpsc_soc_platform; | ||
22 | extern struct snd_ac97_bus_ops soc_ac97_ops; | 19 | extern struct snd_ac97_bus_ops soc_ac97_ops; |
23 | 20 | ||
24 | /* DBDMA helpers */ | 21 | /* DBDMA helpers */ |
diff --git a/sound/soc/blackfin/bf5xx-ac97-pcm.c b/sound/soc/blackfin/bf5xx-ac97-pcm.c index 5e7aacf3bb5a..5a2fd8abaefa 100644 --- a/sound/soc/blackfin/bf5xx-ac97-pcm.c +++ b/sound/soc/blackfin/bf5xx-ac97-pcm.c | |||
@@ -422,14 +422,14 @@ int bf5xx_pcm_ac97_new(struct snd_card *card, struct snd_soc_dai *dai, | |||
422 | if (!card->dev->coherent_dma_mask) | 422 | if (!card->dev->coherent_dma_mask) |
423 | card->dev->coherent_dma_mask = DMA_BIT_MASK(32); | 423 | card->dev->coherent_dma_mask = DMA_BIT_MASK(32); |
424 | 424 | ||
425 | if (dai->playback.channels_min) { | 425 | if (dai->driver->playback.channels_min) { |
426 | ret = bf5xx_pcm_preallocate_dma_buffer(pcm, | 426 | ret = bf5xx_pcm_preallocate_dma_buffer(pcm, |
427 | SNDRV_PCM_STREAM_PLAYBACK); | 427 | SNDRV_PCM_STREAM_PLAYBACK); |
428 | if (ret) | 428 | if (ret) |
429 | goto out; | 429 | goto out; |
430 | } | 430 | } |
431 | 431 | ||
432 | if (dai->capture.channels_min) { | 432 | if (dai->driver->capture.channels_min) { |
433 | ret = bf5xx_pcm_preallocate_dma_buffer(pcm, | 433 | ret = bf5xx_pcm_preallocate_dma_buffer(pcm, |
434 | SNDRV_PCM_STREAM_CAPTURE); | 434 | SNDRV_PCM_STREAM_CAPTURE); |
435 | if (ret) | 435 | if (ret) |
@@ -439,25 +439,44 @@ int bf5xx_pcm_ac97_new(struct snd_card *card, struct snd_soc_dai *dai, | |||
439 | return ret; | 439 | return ret; |
440 | } | 440 | } |
441 | 441 | ||
442 | struct snd_soc_platform bf5xx_ac97_soc_platform = { | 442 | static struct snd_soc_platform_driver bf5xx_ac97_soc_platform = { |
443 | .name = "bf5xx-audio", | 443 | .ops = &bf5xx_pcm_ac97_ops, |
444 | .pcm_ops = &bf5xx_pcm_ac97_ops, | ||
445 | .pcm_new = bf5xx_pcm_ac97_new, | 444 | .pcm_new = bf5xx_pcm_ac97_new, |
446 | .pcm_free = bf5xx_pcm_free_dma_buffers, | 445 | .pcm_free = bf5xx_pcm_free_dma_buffers, |
447 | }; | 446 | }; |
448 | EXPORT_SYMBOL_GPL(bf5xx_ac97_soc_platform); | ||
449 | 447 | ||
450 | static int __init bfin_ac97_init(void) | 448 | static int __devinit bf5xx_soc_platform_probe(struct platform_device *pdev) |
451 | { | 449 | { |
452 | return snd_soc_register_platform(&bf5xx_ac97_soc_platform); | 450 | return snd_soc_register_platform(&pdev->dev, &bf5xx_ac97_soc_platform); |
453 | } | 451 | } |
454 | module_init(bfin_ac97_init); | ||
455 | 452 | ||
456 | static void __exit bfin_ac97_exit(void) | 453 | static int __devexit bf5xx_soc_platform_remove(struct platform_device *pdev) |
457 | { | 454 | { |
458 | snd_soc_unregister_platform(&bf5xx_ac97_soc_platform); | 455 | snd_soc_unregister_platform(&pdev->dev); |
456 | return 0; | ||
457 | } | ||
458 | |||
459 | static struct platform_driver bf5xx_pcm_driver = { | ||
460 | .driver = { | ||
461 | .name = "bf5xx-pcm-audio", | ||
462 | .owner = THIS_MODULE, | ||
463 | }, | ||
464 | |||
465 | .probe = bf5xx_soc_platform_probe, | ||
466 | .remove = __devexit_p(bf5xx_soc_platform_remove), | ||
467 | }; | ||
468 | |||
469 | static int __init snd_bf5xx_pcm_init(void) | ||
470 | { | ||
471 | return platform_driver_register(&bf5xx_pcm_driver); | ||
472 | } | ||
473 | module_init(snd_bf5xx_pcm_init); | ||
474 | |||
475 | static void __exit snd_bf5xx_pcm_exit(void) | ||
476 | { | ||
477 | platform_driver_unregister(&bf5xx_pcm_driver); | ||
459 | } | 478 | } |
460 | module_exit(bfin_ac97_exit); | 479 | module_exit(snd_bf5xx_pcm_exit); |
461 | 480 | ||
462 | MODULE_AUTHOR("Cliff Cai"); | 481 | MODULE_AUTHOR("Cliff Cai"); |
463 | MODULE_DESCRIPTION("ADI Blackfin AC97 PCM DMA module"); | 482 | MODULE_DESCRIPTION("ADI Blackfin AC97 PCM DMA module"); |
diff --git a/sound/soc/blackfin/bf5xx-ac97-pcm.h b/sound/soc/blackfin/bf5xx-ac97-pcm.h index 350125a0ae21..d324d5826a9b 100644 --- a/sound/soc/blackfin/bf5xx-ac97-pcm.h +++ b/sound/soc/blackfin/bf5xx-ac97-pcm.h | |||
@@ -23,7 +23,4 @@ struct bf5xx_gpio { | |||
23 | u32 frm; | 23 | u32 frm; |
24 | }; | 24 | }; |
25 | 25 | ||
26 | /* platform data */ | ||
27 | extern struct snd_soc_platform bf5xx_ac97_soc_platform; | ||
28 | |||
29 | #endif | 26 | #endif |
diff --git a/sound/soc/blackfin/bf5xx-ac97.c b/sound/soc/blackfin/bf5xx-ac97.c index c0eba5109980..c5f856ec27ca 100644 --- a/sound/soc/blackfin/bf5xx-ac97.c +++ b/sound/soc/blackfin/bf5xx-ac97.c | |||
@@ -255,7 +255,7 @@ EXPORT_SYMBOL_GPL(soc_ac97_ops); | |||
255 | #ifdef CONFIG_PM | 255 | #ifdef CONFIG_PM |
256 | static int bf5xx_ac97_suspend(struct snd_soc_dai *dai) | 256 | static int bf5xx_ac97_suspend(struct snd_soc_dai *dai) |
257 | { | 257 | { |
258 | struct sport_device *sport = dai->private_data; | 258 | struct sport_device *sport = snd_soc_dai_get_drvdata(dai); |
259 | 259 | ||
260 | pr_debug("%s : sport %d\n", __func__, dai->id); | 260 | pr_debug("%s : sport %d\n", __func__, dai->id); |
261 | if (!dai->active) | 261 | if (!dai->active) |
@@ -270,7 +270,7 @@ static int bf5xx_ac97_suspend(struct snd_soc_dai *dai) | |||
270 | static int bf5xx_ac97_resume(struct snd_soc_dai *dai) | 270 | static int bf5xx_ac97_resume(struct snd_soc_dai *dai) |
271 | { | 271 | { |
272 | int ret; | 272 | int ret; |
273 | struct sport_device *sport = dai->private_data; | 273 | struct sport_device *sport = snd_soc_dai_get_drvdata(dai); |
274 | 274 | ||
275 | pr_debug("%s : sport %d\n", __func__, dai->id); | 275 | pr_debug("%s : sport %d\n", __func__, dai->id); |
276 | if (!dai->active) | 276 | if (!dai->active) |
@@ -306,8 +306,7 @@ static int bf5xx_ac97_resume(struct snd_soc_dai *dai) | |||
306 | #define bf5xx_ac97_resume NULL | 306 | #define bf5xx_ac97_resume NULL |
307 | #endif | 307 | #endif |
308 | 308 | ||
309 | static int bf5xx_ac97_probe(struct platform_device *pdev, | 309 | static int bf5xx_ac97_probe(struct snd_soc_dai *dai) |
310 | struct snd_soc_dai *dai) | ||
311 | { | 310 | { |
312 | int ret = 0; | 311 | int ret = 0; |
313 | cmd_count = (int *)get_zeroed_page(GFP_KERNEL); | 312 | cmd_count = (int *)get_zeroed_page(GFP_KERNEL); |
@@ -379,8 +378,7 @@ peripheral_err: | |||
379 | return ret; | 378 | return ret; |
380 | } | 379 | } |
381 | 380 | ||
382 | static void bf5xx_ac97_remove(struct platform_device *pdev, | 381 | static int bf5xx_ac97_remove(struct snd_soc_dai *dai) |
383 | struct snd_soc_dai *dai) | ||
384 | { | 382 | { |
385 | free_page((unsigned long)cmd_count); | 383 | free_page((unsigned long)cmd_count); |
386 | cmd_count = NULL; | 384 | cmd_count = NULL; |
@@ -388,11 +386,10 @@ static void bf5xx_ac97_remove(struct platform_device *pdev, | |||
388 | #ifdef CONFIG_SND_BF5XX_HAVE_COLD_RESET | 386 | #ifdef CONFIG_SND_BF5XX_HAVE_COLD_RESET |
389 | gpio_free(CONFIG_SND_BF5XX_RESET_GPIO_NUM); | 387 | gpio_free(CONFIG_SND_BF5XX_RESET_GPIO_NUM); |
390 | #endif | 388 | #endif |
389 | return 0; | ||
391 | } | 390 | } |
392 | 391 | ||
393 | struct snd_soc_dai bfin_ac97_dai = { | 392 | struct snd_soc_dai_driver bfin_ac97_dai = { |
394 | .name = "bf5xx-ac97", | ||
395 | .id = 0, | ||
396 | .ac97_control = 1, | 393 | .ac97_control = 1, |
397 | .probe = bf5xx_ac97_probe, | 394 | .probe = bf5xx_ac97_probe, |
398 | .remove = bf5xx_ac97_remove, | 395 | .remove = bf5xx_ac97_remove, |
@@ -417,18 +414,40 @@ struct snd_soc_dai bfin_ac97_dai = { | |||
417 | }; | 414 | }; |
418 | EXPORT_SYMBOL_GPL(bfin_ac97_dai); | 415 | EXPORT_SYMBOL_GPL(bfin_ac97_dai); |
419 | 416 | ||
417 | static __devinit int asoc_bfin_ac97_probe(struct platform_device *pdev) | ||
418 | { | ||
419 | return snd_soc_register_dai(&pdev->dev, &bfin_ac97_dai); | ||
420 | } | ||
421 | |||
422 | static int __devexit asoc_bfin_ac97_remove(struct platform_device *pdev) | ||
423 | { | ||
424 | snd_soc_unregister_dai(&pdev->dev); | ||
425 | return 0; | ||
426 | } | ||
427 | |||
428 | static struct platform_driver asoc_bfin_ac97_driver = { | ||
429 | .driver = { | ||
430 | .name = "bfin-ac97", | ||
431 | .owner = THIS_MODULE, | ||
432 | }, | ||
433 | |||
434 | .probe = asoc_bfin_ac97_probe, | ||
435 | .remove = __devexit_p(asoc_bfin_ac97_remove), | ||
436 | }; | ||
437 | |||
420 | static int __init bfin_ac97_init(void) | 438 | static int __init bfin_ac97_init(void) |
421 | { | 439 | { |
422 | return snd_soc_register_dai(&bfin_ac97_dai); | 440 | return platform_driver_register(&asoc_bfin_ac97_driver); |
423 | } | 441 | } |
424 | module_init(bfin_ac97_init); | 442 | module_init(bfin_ac97_init); |
425 | 443 | ||
426 | static void __exit bfin_ac97_exit(void) | 444 | static void __exit bfin_ac97_exit(void) |
427 | { | 445 | { |
428 | snd_soc_unregister_dai(&bfin_ac97_dai); | 446 | platform_driver_unregister(&asoc_bfin_ac97_driver); |
429 | } | 447 | } |
430 | module_exit(bfin_ac97_exit); | 448 | module_exit(bfin_ac97_exit); |
431 | 449 | ||
450 | |||
432 | MODULE_AUTHOR("Roy Huang"); | 451 | MODULE_AUTHOR("Roy Huang"); |
433 | MODULE_DESCRIPTION("AC97 driver for ADI Blackfin"); | 452 | MODULE_DESCRIPTION("AC97 driver for ADI Blackfin"); |
434 | MODULE_LICENSE("GPL"); | 453 | MODULE_LICENSE("GPL"); |
diff --git a/sound/soc/blackfin/bf5xx-ac97.h b/sound/soc/blackfin/bf5xx-ac97.h index a1f97dd809d6..15c635e33f4d 100644 --- a/sound/soc/blackfin/bf5xx-ac97.h +++ b/sound/soc/blackfin/bf5xx-ac97.h | |||
@@ -50,8 +50,6 @@ struct ac97_frame { | |||
50 | #define TAG_PCM_SR 0x0080 | 50 | #define TAG_PCM_SR 0x0080 |
51 | #define TAG_PCM_LFE 0x0040 | 51 | #define TAG_PCM_LFE 0x0040 |
52 | 52 | ||
53 | extern struct snd_soc_dai bfin_ac97_dai; | ||
54 | |||
55 | void bf5xx_pcm_to_ac97(struct ac97_frame *dst, const __u16 *src, \ | 53 | void bf5xx_pcm_to_ac97(struct ac97_frame *dst, const __u16 *src, \ |
56 | size_t count, unsigned int chan_mask); | 54 | size_t count, unsigned int chan_mask); |
57 | 55 | ||
diff --git a/sound/soc/blackfin/bf5xx-ad1836.c b/sound/soc/blackfin/bf5xx-ad1836.c index 0f45a3f56be8..2394bff2b655 100644 --- a/sound/soc/blackfin/bf5xx-ad1836.c +++ b/sound/soc/blackfin/bf5xx-ad1836.c | |||
@@ -40,9 +40,9 @@ static struct snd_soc_card bf5xx_ad1836; | |||
40 | static int bf5xx_ad1836_startup(struct snd_pcm_substream *substream) | 40 | static int bf5xx_ad1836_startup(struct snd_pcm_substream *substream) |
41 | { | 41 | { |
42 | struct snd_soc_pcm_runtime *rtd = substream->private_data; | 42 | struct snd_soc_pcm_runtime *rtd = substream->private_data; |
43 | struct snd_soc_dai *cpu_dai = rtd->dai->cpu_dai; | 43 | struct snd_soc_dai *cpu_dai = rtd->cpu_dai; |
44 | 44 | ||
45 | cpu_dai->private_data = sport_handle; | 45 | snd_soc_dai_set_drvdata(cpu_dai, sport_handle); |
46 | return 0; | 46 | return 0; |
47 | } | 47 | } |
48 | 48 | ||
@@ -50,8 +50,8 @@ static int bf5xx_ad1836_hw_params(struct snd_pcm_substream *substream, | |||
50 | struct snd_pcm_hw_params *params) | 50 | struct snd_pcm_hw_params *params) |
51 | { | 51 | { |
52 | struct snd_soc_pcm_runtime *rtd = substream->private_data; | 52 | struct snd_soc_pcm_runtime *rtd = substream->private_data; |
53 | struct snd_soc_dai *cpu_dai = rtd->dai->cpu_dai; | 53 | struct snd_soc_dai *cpu_dai = rtd->cpu_dai; |
54 | struct snd_soc_dai *codec_dai = rtd->dai->codec_dai; | 54 | struct snd_soc_dai *codec_dai = rtd->codec_dai; |
55 | unsigned int channel_map[] = {0, 4, 1, 5, 2, 6, 3, 7}; | 55 | unsigned int channel_map[] = {0, 4, 1, 5, 2, 6, 3, 7}; |
56 | int ret = 0; | 56 | int ret = 0; |
57 | /* set cpu DAI configuration */ | 57 | /* set cpu DAI configuration */ |
@@ -83,23 +83,19 @@ static struct snd_soc_ops bf5xx_ad1836_ops = { | |||
83 | static struct snd_soc_dai_link bf5xx_ad1836_dai = { | 83 | static struct snd_soc_dai_link bf5xx_ad1836_dai = { |
84 | .name = "ad1836", | 84 | .name = "ad1836", |
85 | .stream_name = "AD1836", | 85 | .stream_name = "AD1836", |
86 | .cpu_dai = &bf5xx_tdm_dai, | 86 | .cpu_dai_name = "bf5xx-tdm", |
87 | .codec_dai = &ad1836_dai, | 87 | .codec_dai_name = "ad1836-hifi", |
88 | .platform_name = "bf5xx-tdm-pcm-audio", | ||
89 | .codec_name = "ad1836-codec.0", | ||
88 | .ops = &bf5xx_ad1836_ops, | 90 | .ops = &bf5xx_ad1836_ops, |
89 | }; | 91 | }; |
90 | 92 | ||
91 | static struct snd_soc_card bf5xx_ad1836 = { | 93 | static struct snd_soc_card bf5xx_ad1836 = { |
92 | .name = "bf5xx_ad1836", | 94 | .name = "bf5xx_ad1836", |
93 | .platform = &bf5xx_tdm_soc_platform, | ||
94 | .dai_link = &bf5xx_ad1836_dai, | 95 | .dai_link = &bf5xx_ad1836_dai, |
95 | .num_links = 1, | 96 | .num_links = 1, |
96 | }; | 97 | }; |
97 | 98 | ||
98 | static struct snd_soc_device bf5xx_ad1836_snd_devdata = { | ||
99 | .card = &bf5xx_ad1836, | ||
100 | .codec_dev = &soc_codec_dev_ad1836, | ||
101 | }; | ||
102 | |||
103 | static struct platform_device *bfxx_ad1836_snd_device; | 99 | static struct platform_device *bfxx_ad1836_snd_device; |
104 | 100 | ||
105 | static int __init bf5xx_ad1836_init(void) | 101 | static int __init bf5xx_ad1836_init(void) |
@@ -110,8 +106,7 @@ static int __init bf5xx_ad1836_init(void) | |||
110 | if (!bfxx_ad1836_snd_device) | 106 | if (!bfxx_ad1836_snd_device) |
111 | return -ENOMEM; | 107 | return -ENOMEM; |
112 | 108 | ||
113 | platform_set_drvdata(bfxx_ad1836_snd_device, &bf5xx_ad1836_snd_devdata); | 109 | platform_set_drvdata(bfxx_ad1836_snd_device, &bf5xx_ad1836); |
114 | bf5xx_ad1836_snd_devdata.dev = &bfxx_ad1836_snd_device->dev; | ||
115 | ret = platform_device_add(bfxx_ad1836_snd_device); | 110 | ret = platform_device_add(bfxx_ad1836_snd_device); |
116 | 111 | ||
117 | if (ret) | 112 | if (ret) |
diff --git a/sound/soc/blackfin/bf5xx-ad193x.c b/sound/soc/blackfin/bf5xx-ad193x.c index b8c9060cfd8e..e4a625317a1a 100644 --- a/sound/soc/blackfin/bf5xx-ad193x.c +++ b/sound/soc/blackfin/bf5xx-ad193x.c | |||
@@ -49,9 +49,9 @@ static struct snd_soc_card bf5xx_ad193x; | |||
49 | static int bf5xx_ad193x_startup(struct snd_pcm_substream *substream) | 49 | static int bf5xx_ad193x_startup(struct snd_pcm_substream *substream) |
50 | { | 50 | { |
51 | struct snd_soc_pcm_runtime *rtd = substream->private_data; | 51 | struct snd_soc_pcm_runtime *rtd = substream->private_data; |
52 | struct snd_soc_dai *cpu_dai = rtd->dai->cpu_dai; | 52 | struct snd_soc_dai *cpu_dai = rtd->cpu_dai; |
53 | 53 | ||
54 | cpu_dai->private_data = sport_handle; | 54 | snd_soc_dai_set_drvdata(cpu_dai, sport_handle); |
55 | return 0; | 55 | return 0; |
56 | } | 56 | } |
57 | 57 | ||
@@ -59,8 +59,8 @@ static int bf5xx_ad193x_hw_params(struct snd_pcm_substream *substream, | |||
59 | struct snd_pcm_hw_params *params) | 59 | struct snd_pcm_hw_params *params) |
60 | { | 60 | { |
61 | struct snd_soc_pcm_runtime *rtd = substream->private_data; | 61 | struct snd_soc_pcm_runtime *rtd = substream->private_data; |
62 | struct snd_soc_dai *cpu_dai = rtd->dai->cpu_dai; | 62 | struct snd_soc_dai *cpu_dai = rtd->cpu_dai; |
63 | struct snd_soc_dai *codec_dai = rtd->dai->codec_dai; | 63 | struct snd_soc_dai *codec_dai = rtd->codec_dai; |
64 | unsigned int channel_map[] = {0, 1, 2, 3, 4, 5, 6, 7}; | 64 | unsigned int channel_map[] = {0, 1, 2, 3, 4, 5, 6, 7}; |
65 | int ret = 0; | 65 | int ret = 0; |
66 | /* set cpu DAI configuration */ | 66 | /* set cpu DAI configuration */ |
@@ -97,23 +97,19 @@ static struct snd_soc_ops bf5xx_ad193x_ops = { | |||
97 | static struct snd_soc_dai_link bf5xx_ad193x_dai = { | 97 | static struct snd_soc_dai_link bf5xx_ad193x_dai = { |
98 | .name = "ad193x", | 98 | .name = "ad193x", |
99 | .stream_name = "AD193X", | 99 | .stream_name = "AD193X", |
100 | .cpu_dai = &bf5xx_tdm_dai, | 100 | .cpu_dai_name = "bf5xx-tdm", |
101 | .codec_dai = &ad193x_dai, | 101 | .codec_dai_name ="ad193x-hifi", |
102 | .platform_name = "bf5xx-tdm-pcm-audio", | ||
103 | .codec_name = "ad193x-codec.5", | ||
102 | .ops = &bf5xx_ad193x_ops, | 104 | .ops = &bf5xx_ad193x_ops, |
103 | }; | 105 | }; |
104 | 106 | ||
105 | static struct snd_soc_card bf5xx_ad193x = { | 107 | static struct snd_soc_card bf5xx_ad193x = { |
106 | .name = "bf5xx_ad193x", | 108 | .name = "bf5xx_ad193x", |
107 | .platform = &bf5xx_tdm_soc_platform, | ||
108 | .dai_link = &bf5xx_ad193x_dai, | 109 | .dai_link = &bf5xx_ad193x_dai, |
109 | .num_links = 1, | 110 | .num_links = 1, |
110 | }; | 111 | }; |
111 | 112 | ||
112 | static struct snd_soc_device bf5xx_ad193x_snd_devdata = { | ||
113 | .card = &bf5xx_ad193x, | ||
114 | .codec_dev = &soc_codec_dev_ad193x, | ||
115 | }; | ||
116 | |||
117 | static struct platform_device *bfxx_ad193x_snd_device; | 113 | static struct platform_device *bfxx_ad193x_snd_device; |
118 | 114 | ||
119 | static int __init bf5xx_ad193x_init(void) | 115 | static int __init bf5xx_ad193x_init(void) |
@@ -124,8 +120,7 @@ static int __init bf5xx_ad193x_init(void) | |||
124 | if (!bfxx_ad193x_snd_device) | 120 | if (!bfxx_ad193x_snd_device) |
125 | return -ENOMEM; | 121 | return -ENOMEM; |
126 | 122 | ||
127 | platform_set_drvdata(bfxx_ad193x_snd_device, &bf5xx_ad193x_snd_devdata); | 123 | platform_set_drvdata(bfxx_ad193x_snd_device, &bf5xx_ad193x); |
128 | bf5xx_ad193x_snd_devdata.dev = &bfxx_ad193x_snd_device->dev; | ||
129 | ret = platform_device_add(bfxx_ad193x_snd_device); | 124 | ret = platform_device_add(bfxx_ad193x_snd_device); |
130 | 125 | ||
131 | if (ret) | 126 | if (ret) |
diff --git a/sound/soc/blackfin/bf5xx-ad1980.c b/sound/soc/blackfin/bf5xx-ad1980.c index d8f591273778..a31bdf656fce 100644 --- a/sound/soc/blackfin/bf5xx-ad1980.c +++ b/sound/soc/blackfin/bf5xx-ad1980.c | |||
@@ -48,10 +48,10 @@ static struct snd_soc_card bf5xx_board; | |||
48 | static int bf5xx_board_startup(struct snd_pcm_substream *substream) | 48 | static int bf5xx_board_startup(struct snd_pcm_substream *substream) |
49 | { | 49 | { |
50 | struct snd_soc_pcm_runtime *rtd = substream->private_data; | 50 | struct snd_soc_pcm_runtime *rtd = substream->private_data; |
51 | struct snd_soc_dai *cpu_dai = rtd->dai->cpu_dai; | 51 | struct snd_soc_dai *cpu_dai = rtd->cpu_dai; |
52 | 52 | ||
53 | pr_debug("%s enter\n", __func__); | 53 | pr_debug("%s enter\n", __func__); |
54 | cpu_dai->private_data = sport_handle; | 54 | snd_soc_dai_set_drvdata(cpu_dai, sport_handle); |
55 | return 0; | 55 | return 0; |
56 | } | 56 | } |
57 | 57 | ||
@@ -62,23 +62,19 @@ static struct snd_soc_ops bf5xx_board_ops = { | |||
62 | static struct snd_soc_dai_link bf5xx_board_dai = { | 62 | static struct snd_soc_dai_link bf5xx_board_dai = { |
63 | .name = "AC97", | 63 | .name = "AC97", |
64 | .stream_name = "AC97 HiFi", | 64 | .stream_name = "AC97 HiFi", |
65 | .cpu_dai = &bfin_ac97_dai, | 65 | .cpu_dai_name = "bfin-ac97", |
66 | .codec_dai = &ad1980_dai, | 66 | .codec_dai_name = "ad1980-hifi", |
67 | .platform_name = "bfin-pcm-audio", | ||
68 | .codec_name = "ad1980-codec", | ||
67 | .ops = &bf5xx_board_ops, | 69 | .ops = &bf5xx_board_ops, |
68 | }; | 70 | }; |
69 | 71 | ||
70 | static struct snd_soc_card bf5xx_board = { | 72 | static struct snd_soc_card bf5xx_board = { |
71 | .name = "bf5xx-board", | 73 | .name = "bf5xx-board", |
72 | .platform = &bf5xx_ac97_soc_platform, | ||
73 | .dai_link = &bf5xx_board_dai, | 74 | .dai_link = &bf5xx_board_dai, |
74 | .num_links = 1, | 75 | .num_links = 1, |
75 | }; | 76 | }; |
76 | 77 | ||
77 | static struct snd_soc_device bf5xx_board_snd_devdata = { | ||
78 | .card = &bf5xx_board, | ||
79 | .codec_dev = &soc_codec_dev_ad1980, | ||
80 | }; | ||
81 | |||
82 | static struct platform_device *bf5xx_board_snd_device; | 78 | static struct platform_device *bf5xx_board_snd_device; |
83 | 79 | ||
84 | static int __init bf5xx_board_init(void) | 80 | static int __init bf5xx_board_init(void) |
@@ -89,8 +85,7 @@ static int __init bf5xx_board_init(void) | |||
89 | if (!bf5xx_board_snd_device) | 85 | if (!bf5xx_board_snd_device) |
90 | return -ENOMEM; | 86 | return -ENOMEM; |
91 | 87 | ||
92 | platform_set_drvdata(bf5xx_board_snd_device, &bf5xx_board_snd_devdata); | 88 | platform_set_drvdata(bf5xx_board_snd_device, &bf5xx_board); |
93 | bf5xx_board_snd_devdata.dev = &bf5xx_board_snd_device->dev; | ||
94 | ret = platform_device_add(bf5xx_board_snd_device); | 89 | ret = platform_device_add(bf5xx_board_snd_device); |
95 | 90 | ||
96 | if (ret) | 91 | if (ret) |
diff --git a/sound/soc/blackfin/bf5xx-ad73311.c b/sound/soc/blackfin/bf5xx-ad73311.c index 9825b71d0e28..900ced54ac79 100644 --- a/sound/soc/blackfin/bf5xx-ad73311.c +++ b/sound/soc/blackfin/bf5xx-ad73311.c | |||
@@ -47,7 +47,6 @@ | |||
47 | #include "../codecs/ad73311.h" | 47 | #include "../codecs/ad73311.h" |
48 | #include "bf5xx-sport.h" | 48 | #include "bf5xx-sport.h" |
49 | #include "bf5xx-i2s-pcm.h" | 49 | #include "bf5xx-i2s-pcm.h" |
50 | #include "bf5xx-i2s.h" | ||
51 | 50 | ||
52 | #if CONFIG_SND_BF5XX_SPORT_NUM == 0 | 51 | #if CONFIG_SND_BF5XX_SPORT_NUM == 0 |
53 | #define bfin_write_SPORT_TCR1 bfin_write_SPORT0_TCR1 | 52 | #define bfin_write_SPORT_TCR1 bfin_write_SPORT0_TCR1 |
@@ -150,10 +149,10 @@ static int bf5xx_probe(struct platform_device *pdev) | |||
150 | static int bf5xx_ad73311_startup(struct snd_pcm_substream *substream) | 149 | static int bf5xx_ad73311_startup(struct snd_pcm_substream *substream) |
151 | { | 150 | { |
152 | struct snd_soc_pcm_runtime *rtd = substream->private_data; | 151 | struct snd_soc_pcm_runtime *rtd = substream->private_data; |
153 | struct snd_soc_dai *cpu_dai = rtd->dai->cpu_dai; | 152 | struct snd_soc_dai *cpu_dai = rtd->cpu_dai; |
154 | 153 | ||
155 | pr_debug("%s enter\n", __func__); | 154 | pr_debug("%s enter\n", __func__); |
156 | cpu_dai->private_data = sport_handle; | 155 | snd_soc_dai_set_drvdata(cpu_dai, sport_handle); |
157 | return 0; | 156 | return 0; |
158 | } | 157 | } |
159 | 158 | ||
@@ -161,7 +160,7 @@ static int bf5xx_ad73311_hw_params(struct snd_pcm_substream *substream, | |||
161 | struct snd_pcm_hw_params *params) | 160 | struct snd_pcm_hw_params *params) |
162 | { | 161 | { |
163 | struct snd_soc_pcm_runtime *rtd = substream->private_data; | 162 | struct snd_soc_pcm_runtime *rtd = substream->private_data; |
164 | struct snd_soc_dai *cpu_dai = rtd->dai->cpu_dai; | 163 | struct snd_soc_dai *cpu_dai = rtd->cpu_dai; |
165 | int ret = 0; | 164 | int ret = 0; |
166 | 165 | ||
167 | pr_debug("%s rate %d format %x\n", __func__, params_rate(params), | 166 | pr_debug("%s rate %d format %x\n", __func__, params_rate(params), |
@@ -185,24 +184,20 @@ static struct snd_soc_ops bf5xx_ad73311_ops = { | |||
185 | static struct snd_soc_dai_link bf5xx_ad73311_dai = { | 184 | static struct snd_soc_dai_link bf5xx_ad73311_dai = { |
186 | .name = "ad73311", | 185 | .name = "ad73311", |
187 | .stream_name = "AD73311", | 186 | .stream_name = "AD73311", |
188 | .cpu_dai = &bf5xx_i2s_dai, | 187 | .cpu_dai_name = "bf5xx-i2s", |
189 | .codec_dai = &ad73311_dai, | 188 | .codec_dai_name = "ad73311-hifi", |
189 | .platform_name = "bfin-pcm-audio", | ||
190 | .codec_name = "ad73311-codec", | ||
190 | .ops = &bf5xx_ad73311_ops, | 191 | .ops = &bf5xx_ad73311_ops, |
191 | }; | 192 | }; |
192 | 193 | ||
193 | static struct snd_soc_card bf5xx_ad73311 = { | 194 | static struct snd_soc_card bf5xx_ad73311 = { |
194 | .name = "bf5xx_ad73311", | 195 | .name = "bf5xx_ad73311", |
195 | .platform = &bf5xx_i2s_soc_platform, | ||
196 | .probe = bf5xx_probe, | 196 | .probe = bf5xx_probe, |
197 | .dai_link = &bf5xx_ad73311_dai, | 197 | .dai_link = &bf5xx_ad73311_dai, |
198 | .num_links = 1, | 198 | .num_links = 1, |
199 | }; | 199 | }; |
200 | 200 | ||
201 | static struct snd_soc_device bf5xx_ad73311_snd_devdata = { | ||
202 | .card = &bf5xx_ad73311, | ||
203 | .codec_dev = &soc_codec_dev_ad73311, | ||
204 | }; | ||
205 | |||
206 | static struct platform_device *bf5xx_ad73311_snd_device; | 201 | static struct platform_device *bf5xx_ad73311_snd_device; |
207 | 202 | ||
208 | static int __init bf5xx_ad73311_init(void) | 203 | static int __init bf5xx_ad73311_init(void) |
@@ -214,8 +209,7 @@ static int __init bf5xx_ad73311_init(void) | |||
214 | if (!bf5xx_ad73311_snd_device) | 209 | if (!bf5xx_ad73311_snd_device) |
215 | return -ENOMEM; | 210 | return -ENOMEM; |
216 | 211 | ||
217 | platform_set_drvdata(bf5xx_ad73311_snd_device, &bf5xx_ad73311_snd_devdata); | 212 | platform_set_drvdata(bf5xx_ad73311_snd_device, &bf5xx_ad73311); |
218 | bf5xx_ad73311_snd_devdata.dev = &bf5xx_ad73311_snd_device->dev; | ||
219 | ret = platform_device_add(bf5xx_ad73311_snd_device); | 213 | ret = platform_device_add(bf5xx_ad73311_snd_device); |
220 | 214 | ||
221 | if (ret) | 215 | if (ret) |
diff --git a/sound/soc/blackfin/bf5xx-i2s-pcm.c b/sound/soc/blackfin/bf5xx-i2s-pcm.c index 1d2a1adf2575..890a0dccf902 100644 --- a/sound/soc/blackfin/bf5xx-i2s-pcm.c +++ b/sound/soc/blackfin/bf5xx-i2s-pcm.c | |||
@@ -40,7 +40,6 @@ | |||
40 | #include <asm/dma.h> | 40 | #include <asm/dma.h> |
41 | 41 | ||
42 | #include "bf5xx-i2s-pcm.h" | 42 | #include "bf5xx-i2s-pcm.h" |
43 | #include "bf5xx-i2s.h" | ||
44 | #include "bf5xx-sport.h" | 43 | #include "bf5xx-sport.h" |
45 | 44 | ||
46 | static void bf5xx_dma_irq(void *data) | 45 | static void bf5xx_dma_irq(void *data) |
@@ -257,14 +256,14 @@ int bf5xx_pcm_i2s_new(struct snd_card *card, struct snd_soc_dai *dai, | |||
257 | if (!card->dev->coherent_dma_mask) | 256 | if (!card->dev->coherent_dma_mask) |
258 | card->dev->coherent_dma_mask = DMA_BIT_MASK(32); | 257 | card->dev->coherent_dma_mask = DMA_BIT_MASK(32); |
259 | 258 | ||
260 | if (dai->playback.channels_min) { | 259 | if (dai->driver->playback.channels_min) { |
261 | ret = bf5xx_pcm_preallocate_dma_buffer(pcm, | 260 | ret = bf5xx_pcm_preallocate_dma_buffer(pcm, |
262 | SNDRV_PCM_STREAM_PLAYBACK); | 261 | SNDRV_PCM_STREAM_PLAYBACK); |
263 | if (ret) | 262 | if (ret) |
264 | goto out; | 263 | goto out; |
265 | } | 264 | } |
266 | 265 | ||
267 | if (dai->capture.channels_min) { | 266 | if (dai->driver->capture.channels_min) { |
268 | ret = bf5xx_pcm_preallocate_dma_buffer(pcm, | 267 | ret = bf5xx_pcm_preallocate_dma_buffer(pcm, |
269 | SNDRV_PCM_STREAM_CAPTURE); | 268 | SNDRV_PCM_STREAM_CAPTURE); |
270 | if (ret) | 269 | if (ret) |
@@ -274,25 +273,44 @@ int bf5xx_pcm_i2s_new(struct snd_card *card, struct snd_soc_dai *dai, | |||
274 | return ret; | 273 | return ret; |
275 | } | 274 | } |
276 | 275 | ||
277 | struct snd_soc_platform bf5xx_i2s_soc_platform = { | 276 | static struct snd_soc_platform_driver bf5xx_i2s_soc_platform = { |
278 | .name = "bf5xx-audio", | 277 | .ops = &bf5xx_pcm_i2s_ops, |
279 | .pcm_ops = &bf5xx_pcm_i2s_ops, | ||
280 | .pcm_new = bf5xx_pcm_i2s_new, | 278 | .pcm_new = bf5xx_pcm_i2s_new, |
281 | .pcm_free = bf5xx_pcm_free_dma_buffers, | 279 | .pcm_free = bf5xx_pcm_free_dma_buffers, |
282 | }; | 280 | }; |
283 | EXPORT_SYMBOL_GPL(bf5xx_i2s_soc_platform); | ||
284 | 281 | ||
285 | static int __init bfin_i2s_init(void) | 282 | static int __devinit bfin_i2s_soc_platform_probe(struct platform_device *pdev) |
286 | { | 283 | { |
287 | return snd_soc_register_platform(&bf5xx_i2s_soc_platform); | 284 | return snd_soc_register_platform(&pdev->dev, &bf5xx_i2s_soc_platform); |
288 | } | 285 | } |
289 | module_init(bfin_i2s_init); | ||
290 | 286 | ||
291 | static void __exit bfin_i2s_exit(void) | 287 | static int __devexit bfin_i2s_soc_platform_remove(struct platform_device *pdev) |
292 | { | 288 | { |
293 | snd_soc_unregister_platform(&bf5xx_i2s_soc_platform); | 289 | snd_soc_unregister_platform(&pdev->dev); |
290 | return 0; | ||
291 | } | ||
292 | |||
293 | static struct platform_driver bfin_i2s_pcm_driver = { | ||
294 | .driver = { | ||
295 | .name = "bfin-pcm-audio", | ||
296 | .owner = THIS_MODULE, | ||
297 | }, | ||
298 | |||
299 | .probe = bfin_i2s_soc_platform_probe, | ||
300 | .remove = __devexit_p(bfin_i2s_soc_platform_remove), | ||
301 | }; | ||
302 | |||
303 | static int __init snd_bfin_i2s_pcm_init(void) | ||
304 | { | ||
305 | return platform_driver_register(&bfin_i2s_pcm_driver); | ||
306 | } | ||
307 | module_init(snd_bfin_i2s_pcm_init); | ||
308 | |||
309 | static void __exit snd_bfin_i2s_pcm_exit(void) | ||
310 | { | ||
311 | platform_driver_unregister(&bfin_i2s_pcm_driver); | ||
294 | } | 312 | } |
295 | module_exit(bfin_i2s_exit); | 313 | module_exit(snd_bfin_i2s_pcm_exit); |
296 | 314 | ||
297 | MODULE_AUTHOR("Cliff Cai"); | 315 | MODULE_AUTHOR("Cliff Cai"); |
298 | MODULE_DESCRIPTION("ADI Blackfin I2S PCM DMA module"); | 316 | MODULE_DESCRIPTION("ADI Blackfin I2S PCM DMA module"); |
diff --git a/sound/soc/blackfin/bf5xx-i2s-pcm.h b/sound/soc/blackfin/bf5xx-i2s-pcm.h index 4d4609a97c59..0c2c5a68d4ff 100644 --- a/sound/soc/blackfin/bf5xx-i2s-pcm.h +++ b/sound/soc/blackfin/bf5xx-i2s-pcm.h | |||
@@ -23,7 +23,4 @@ struct bf5xx_gpio { | |||
23 | u32 frm; | 23 | u32 frm; |
24 | }; | 24 | }; |
25 | 25 | ||
26 | /* platform data */ | ||
27 | extern struct snd_soc_platform bf5xx_i2s_soc_platform; | ||
28 | |||
29 | #endif | 26 | #endif |
diff --git a/sound/soc/blackfin/bf5xx-i2s.c b/sound/soc/blackfin/bf5xx-i2s.c index 3e6ada0dd1c4..d453b1e9d607 100644 --- a/sound/soc/blackfin/bf5xx-i2s.c +++ b/sound/soc/blackfin/bf5xx-i2s.c | |||
@@ -42,7 +42,6 @@ | |||
42 | #include <linux/gpio.h> | 42 | #include <linux/gpio.h> |
43 | 43 | ||
44 | #include "bf5xx-sport.h" | 44 | #include "bf5xx-sport.h" |
45 | #include "bf5xx-i2s.h" | ||
46 | 45 | ||
47 | struct bf5xx_i2s_port { | 46 | struct bf5xx_i2s_port { |
48 | u16 tcr1; | 47 | u16 tcr1; |
@@ -195,8 +194,7 @@ static void bf5xx_i2s_shutdown(struct snd_pcm_substream *substream, | |||
195 | bf5xx_i2s.configured = 0; | 194 | bf5xx_i2s.configured = 0; |
196 | } | 195 | } |
197 | 196 | ||
198 | static int bf5xx_i2s_probe(struct platform_device *pdev, | 197 | static int bf5xx_i2s_probe(struct snd_soc_dai *dai) |
199 | struct snd_soc_dai *dai) | ||
200 | { | 198 | { |
201 | pr_debug("%s enter\n", __func__); | 199 | pr_debug("%s enter\n", __func__); |
202 | if (peripheral_request_list(&sport_req[sport_num][0], "soc-audio")) { | 200 | if (peripheral_request_list(&sport_req[sport_num][0], "soc-audio")) { |
@@ -215,11 +213,11 @@ static int bf5xx_i2s_probe(struct platform_device *pdev, | |||
215 | return 0; | 213 | return 0; |
216 | } | 214 | } |
217 | 215 | ||
218 | static void bf5xx_i2s_remove(struct platform_device *pdev, | 216 | static int bf5xx_i2s_remove(struct snd_soc_dai *dai) |
219 | struct snd_soc_dai *dai) | ||
220 | { | 217 | { |
221 | pr_debug("%s enter\n", __func__); | 218 | pr_debug("%s enter\n", __func__); |
222 | peripheral_free_list(&sport_req[sport_num][0]); | 219 | peripheral_free_list(&sport_req[sport_num][0]); |
220 | return 0; | ||
223 | } | 221 | } |
224 | 222 | ||
225 | #ifdef CONFIG_PM | 223 | #ifdef CONFIG_PM |
@@ -228,9 +226,9 @@ static int bf5xx_i2s_suspend(struct snd_soc_dai *dai) | |||
228 | 226 | ||
229 | pr_debug("%s : sport %d\n", __func__, dai->id); | 227 | pr_debug("%s : sport %d\n", __func__, dai->id); |
230 | 228 | ||
231 | if (dai->capture.active) | 229 | if (dai->capture_active) |
232 | sport_rx_stop(sport_handle); | 230 | sport_rx_stop(sport_handle); |
233 | if (dai->playback.active) | 231 | if (dai->playback_active) |
234 | sport_tx_stop(sport_handle); | 232 | sport_tx_stop(sport_handle); |
235 | return 0; | 233 | return 0; |
236 | } | 234 | } |
@@ -277,9 +275,7 @@ static struct snd_soc_dai_ops bf5xx_i2s_dai_ops = { | |||
277 | .set_fmt = bf5xx_i2s_set_dai_fmt, | 275 | .set_fmt = bf5xx_i2s_set_dai_fmt, |
278 | }; | 276 | }; |
279 | 277 | ||
280 | struct snd_soc_dai bf5xx_i2s_dai = { | 278 | static struct snd_soc_dai_driver bf5xx_i2s_dai = { |
281 | .name = "bf5xx-i2s", | ||
282 | .id = 0, | ||
283 | .probe = bf5xx_i2s_probe, | 279 | .probe = bf5xx_i2s_probe, |
284 | .remove = bf5xx_i2s_remove, | 280 | .remove = bf5xx_i2s_remove, |
285 | .suspend = bf5xx_i2s_suspend, | 281 | .suspend = bf5xx_i2s_suspend, |
@@ -296,18 +292,39 @@ struct snd_soc_dai bf5xx_i2s_dai = { | |||
296 | .formats = BF5XX_I2S_FORMATS,}, | 292 | .formats = BF5XX_I2S_FORMATS,}, |
297 | .ops = &bf5xx_i2s_dai_ops, | 293 | .ops = &bf5xx_i2s_dai_ops, |
298 | }; | 294 | }; |
299 | EXPORT_SYMBOL_GPL(bf5xx_i2s_dai); | 295 | |
296 | static int bfin_i2s_drv_probe(struct platform_device *pdev) | ||
297 | { | ||
298 | return snd_soc_register_dai(&pdev->dev, &bf5xx_i2s_dai); | ||
299 | } | ||
300 | |||
301 | static int __devexit bfin_i2s_drv_remove(struct platform_device *pdev) | ||
302 | { | ||
303 | snd_soc_unregister_dai(&pdev->dev); | ||
304 | return 0; | ||
305 | } | ||
306 | |||
307 | static struct platform_driver bfin_i2s_driver = { | ||
308 | .probe = bfin_i2s_drv_probe, | ||
309 | .remove = __devexit_p(bfin_i2s_drv_remove), | ||
310 | |||
311 | .driver = { | ||
312 | .name = "bf5xx-i2s", | ||
313 | .owner = THIS_MODULE, | ||
314 | }, | ||
315 | }; | ||
300 | 316 | ||
301 | static int __init bfin_i2s_init(void) | 317 | static int __init bfin_i2s_init(void) |
302 | { | 318 | { |
303 | return snd_soc_register_dai(&bf5xx_i2s_dai); | 319 | return platform_driver_register(&bfin_i2s_driver); |
304 | } | 320 | } |
305 | module_init(bfin_i2s_init); | ||
306 | 321 | ||
307 | static void __exit bfin_i2s_exit(void) | 322 | static void __exit bfin_i2s_exit(void) |
308 | { | 323 | { |
309 | snd_soc_unregister_dai(&bf5xx_i2s_dai); | 324 | platform_driver_unregister(&bfin_i2s_driver); |
310 | } | 325 | } |
326 | |||
327 | module_init(bfin_i2s_init); | ||
311 | module_exit(bfin_i2s_exit); | 328 | module_exit(bfin_i2s_exit); |
312 | 329 | ||
313 | /* Module information */ | 330 | /* Module information */ |
diff --git a/sound/soc/blackfin/bf5xx-i2s.h b/sound/soc/blackfin/bf5xx-i2s.h deleted file mode 100644 index 264ecdcba35a..000000000000 --- a/sound/soc/blackfin/bf5xx-i2s.h +++ /dev/null | |||
@@ -1,14 +0,0 @@ | |||
1 | /* | ||
2 | * sound/soc/blackfin/bf5xx-i2s.h | ||
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 _BF5XX_I2S_H | ||
10 | #define _BF5XX_I2S_H | ||
11 | |||
12 | extern struct snd_soc_dai bf5xx_i2s_dai; | ||
13 | |||
14 | #endif | ||
diff --git a/sound/soc/blackfin/bf5xx-ssm2602.c b/sound/soc/blackfin/bf5xx-ssm2602.c index 3a00fa4dbe6d..36f2769eb912 100644 --- a/sound/soc/blackfin/bf5xx-ssm2602.c +++ b/sound/soc/blackfin/bf5xx-ssm2602.c | |||
@@ -42,17 +42,16 @@ | |||
42 | #include "../codecs/ssm2602.h" | 42 | #include "../codecs/ssm2602.h" |
43 | #include "bf5xx-sport.h" | 43 | #include "bf5xx-sport.h" |
44 | #include "bf5xx-i2s-pcm.h" | 44 | #include "bf5xx-i2s-pcm.h" |
45 | #include "bf5xx-i2s.h" | ||
46 | 45 | ||
47 | static struct snd_soc_card bf5xx_ssm2602; | 46 | static struct snd_soc_card bf5xx_ssm2602; |
48 | 47 | ||
49 | static int bf5xx_ssm2602_startup(struct snd_pcm_substream *substream) | 48 | static int bf5xx_ssm2602_startup(struct snd_pcm_substream *substream) |
50 | { | 49 | { |
51 | struct snd_soc_pcm_runtime *rtd = substream->private_data; | 50 | struct snd_soc_pcm_runtime *rtd = substream->private_data; |
52 | struct snd_soc_dai *cpu_dai = rtd->dai->cpu_dai; | 51 | struct snd_soc_dai *cpu_dai = rtd->cpu_dai; |
53 | 52 | ||
54 | pr_debug("%s enter\n", __func__); | 53 | pr_debug("%s enter\n", __func__); |
55 | cpu_dai->private_data = sport_handle; | 54 | snd_soc_dai_set_drvdata(cpu_dai, sport_handle); |
56 | return 0; | 55 | return 0; |
57 | } | 56 | } |
58 | 57 | ||
@@ -60,8 +59,8 @@ static int bf5xx_ssm2602_hw_params(struct snd_pcm_substream *substream, | |||
60 | struct snd_pcm_hw_params *params) | 59 | struct snd_pcm_hw_params *params) |
61 | { | 60 | { |
62 | struct snd_soc_pcm_runtime *rtd = substream->private_data; | 61 | struct snd_soc_pcm_runtime *rtd = substream->private_data; |
63 | struct snd_soc_dai *codec_dai = rtd->dai->codec_dai; | 62 | struct snd_soc_dai *codec_dai = rtd->codec_dai; |
64 | struct snd_soc_dai *cpu_dai = rtd->dai->cpu_dai; | 63 | struct snd_soc_dai *cpu_dai = rtd->cpu_dai; |
65 | unsigned int clk = 0; | 64 | unsigned int clk = 0; |
66 | int ret = 0; | 65 | int ret = 0; |
67 | 66 | ||
@@ -118,36 +117,19 @@ static struct snd_soc_ops bf5xx_ssm2602_ops = { | |||
118 | static struct snd_soc_dai_link bf5xx_ssm2602_dai = { | 117 | static struct snd_soc_dai_link bf5xx_ssm2602_dai = { |
119 | .name = "ssm2602", | 118 | .name = "ssm2602", |
120 | .stream_name = "SSM2602", | 119 | .stream_name = "SSM2602", |
121 | .cpu_dai = &bf5xx_i2s_dai, | 120 | .cpu_dai_name = "bf5xx-i2s", |
122 | .codec_dai = &ssm2602_dai, | 121 | .codec_dai_name = "ssm2602-hifi", |
122 | .platform_name = "bf5xx-pcm-audio", | ||
123 | .codec_name = "ssm2602-codec.0-0x1b", | ||
123 | .ops = &bf5xx_ssm2602_ops, | 124 | .ops = &bf5xx_ssm2602_ops, |
124 | }; | 125 | }; |
125 | 126 | ||
126 | /* | ||
127 | * SSM2602 2 wire address is determined by CSB | ||
128 | * state during powerup. | ||
129 | * low = 0x1a | ||
130 | * high = 0x1b | ||
131 | */ | ||
132 | |||
133 | static struct ssm2602_setup_data bf5xx_ssm2602_setup = { | ||
134 | .i2c_bus = 0, | ||
135 | .i2c_address = 0x1b, | ||
136 | }; | ||
137 | |||
138 | static struct snd_soc_card bf5xx_ssm2602 = { | 127 | static struct snd_soc_card bf5xx_ssm2602 = { |
139 | .name = "bf5xx_ssm2602", | 128 | .name = "bf5xx_ssm2602", |
140 | .platform = &bf5xx_i2s_soc_platform, | ||
141 | .dai_link = &bf5xx_ssm2602_dai, | 129 | .dai_link = &bf5xx_ssm2602_dai, |
142 | .num_links = 1, | 130 | .num_links = 1, |
143 | }; | 131 | }; |
144 | 132 | ||
145 | static struct snd_soc_device bf5xx_ssm2602_snd_devdata = { | ||
146 | .card = &bf5xx_ssm2602, | ||
147 | .codec_dev = &soc_codec_dev_ssm2602, | ||
148 | .codec_data = &bf5xx_ssm2602_setup, | ||
149 | }; | ||
150 | |||
151 | static struct platform_device *bf5xx_ssm2602_snd_device; | 133 | static struct platform_device *bf5xx_ssm2602_snd_device; |
152 | 134 | ||
153 | static int __init bf5xx_ssm2602_init(void) | 135 | static int __init bf5xx_ssm2602_init(void) |
@@ -159,9 +141,7 @@ static int __init bf5xx_ssm2602_init(void) | |||
159 | if (!bf5xx_ssm2602_snd_device) | 141 | if (!bf5xx_ssm2602_snd_device) |
160 | return -ENOMEM; | 142 | return -ENOMEM; |
161 | 143 | ||
162 | platform_set_drvdata(bf5xx_ssm2602_snd_device, | 144 | platform_set_drvdata(bf5xx_ssm2602_snd_device, &bf5xx_ssm2602); |
163 | &bf5xx_ssm2602_snd_devdata); | ||
164 | bf5xx_ssm2602_snd_devdata.dev = &bf5xx_ssm2602_snd_device->dev; | ||
165 | ret = platform_device_add(bf5xx_ssm2602_snd_device); | 145 | ret = platform_device_add(bf5xx_ssm2602_snd_device); |
166 | 146 | ||
167 | if (ret) | 147 | if (ret) |
diff --git a/sound/soc/blackfin/bf5xx-tdm-pcm.c b/sound/soc/blackfin/bf5xx-tdm-pcm.c index 6bac1ac1a315..74cf759b78a6 100644 --- a/sound/soc/blackfin/bf5xx-tdm-pcm.c +++ b/sound/soc/blackfin/bf5xx-tdm-pcm.c | |||
@@ -290,14 +290,14 @@ static int bf5xx_pcm_tdm_new(struct snd_card *card, struct snd_soc_dai *dai, | |||
290 | if (!card->dev->coherent_dma_mask) | 290 | if (!card->dev->coherent_dma_mask) |
291 | card->dev->coherent_dma_mask = DMA_BIT_MASK(32); | 291 | card->dev->coherent_dma_mask = DMA_BIT_MASK(32); |
292 | 292 | ||
293 | if (dai->playback.channels_min) { | 293 | if (dai->driver->playback.channels_min) { |
294 | ret = bf5xx_pcm_preallocate_dma_buffer(pcm, | 294 | ret = bf5xx_pcm_preallocate_dma_buffer(pcm, |
295 | SNDRV_PCM_STREAM_PLAYBACK); | 295 | SNDRV_PCM_STREAM_PLAYBACK); |
296 | if (ret) | 296 | if (ret) |
297 | goto out; | 297 | goto out; |
298 | } | 298 | } |
299 | 299 | ||
300 | if (dai->capture.channels_min) { | 300 | if (dai->driver->capture.channels_min) { |
301 | ret = bf5xx_pcm_preallocate_dma_buffer(pcm, | 301 | ret = bf5xx_pcm_preallocate_dma_buffer(pcm, |
302 | SNDRV_PCM_STREAM_CAPTURE); | 302 | SNDRV_PCM_STREAM_CAPTURE); |
303 | if (ret) | 303 | if (ret) |
@@ -307,25 +307,44 @@ out: | |||
307 | return ret; | 307 | return ret; |
308 | } | 308 | } |
309 | 309 | ||
310 | struct snd_soc_platform bf5xx_tdm_soc_platform = { | 310 | static struct snd_soc_platform_driver bf5xx_tdm_soc_platform = { |
311 | .name = "bf5xx-audio", | 311 | .ops = &bf5xx_pcm_tdm_ops, |
312 | .pcm_ops = &bf5xx_pcm_tdm_ops, | ||
313 | .pcm_new = bf5xx_pcm_tdm_new, | 312 | .pcm_new = bf5xx_pcm_tdm_new, |
314 | .pcm_free = bf5xx_pcm_free_dma_buffers, | 313 | .pcm_free = bf5xx_pcm_free_dma_buffers, |
315 | }; | 314 | }; |
316 | EXPORT_SYMBOL_GPL(bf5xx_tdm_soc_platform); | ||
317 | 315 | ||
318 | static int __init bfin_pcm_tdm_init(void) | 316 | static int __devinit bf5xx_soc_platform_probe(struct platform_device *pdev) |
319 | { | 317 | { |
320 | return snd_soc_register_platform(&bf5xx_tdm_soc_platform); | 318 | return snd_soc_register_platform(&pdev->dev, &bf5xx_tdm_soc_platform); |
321 | } | 319 | } |
322 | module_init(bfin_pcm_tdm_init); | ||
323 | 320 | ||
324 | static void __exit bfin_pcm_tdm_exit(void) | 321 | static int __devexit bf5xx_soc_platform_remove(struct platform_device *pdev) |
325 | { | 322 | { |
326 | snd_soc_unregister_platform(&bf5xx_tdm_soc_platform); | 323 | snd_soc_unregister_platform(&pdev->dev); |
324 | return 0; | ||
325 | } | ||
326 | |||
327 | static struct platform_driver bfin_tdm_driver = { | ||
328 | .driver = { | ||
329 | .name = "bf5xx-tdm-pcm-audio", | ||
330 | .owner = THIS_MODULE, | ||
331 | }, | ||
332 | |||
333 | .probe = bf5xx_soc_platform_probe, | ||
334 | .remove = __devexit_p(bf5xx_soc_platform_remove), | ||
335 | }; | ||
336 | |||
337 | static int __init snd_bfin_tdm_init(void) | ||
338 | { | ||
339 | return platform_driver_register(&bfin_tdm_driver); | ||
340 | } | ||
341 | module_init(snd_bfin_tdm_init); | ||
342 | |||
343 | static void __exit snd_bfin_tdm_exit(void) | ||
344 | { | ||
345 | platform_driver_unregister(&bfin_tdm_driver); | ||
327 | } | 346 | } |
328 | module_exit(bfin_pcm_tdm_exit); | 347 | module_exit(snd_bfin_tdm_exit); |
329 | 348 | ||
330 | MODULE_AUTHOR("Barry Song"); | 349 | MODULE_AUTHOR("Barry Song"); |
331 | MODULE_DESCRIPTION("ADI Blackfin TDM PCM DMA module"); | 350 | MODULE_DESCRIPTION("ADI Blackfin TDM PCM DMA module"); |
diff --git a/sound/soc/blackfin/bf5xx-tdm-pcm.h b/sound/soc/blackfin/bf5xx-tdm-pcm.h index ddc5047df88c..7f8cc01c4477 100644 --- a/sound/soc/blackfin/bf5xx-tdm-pcm.h +++ b/sound/soc/blackfin/bf5xx-tdm-pcm.h | |||
@@ -15,7 +15,4 @@ struct bf5xx_pcm_dma_params { | |||
15 | char *name; /* stream identifier */ | 15 | char *name; /* stream identifier */ |
16 | }; | 16 | }; |
17 | 17 | ||
18 | /* platform data */ | ||
19 | extern struct snd_soc_platform bf5xx_tdm_soc_platform; | ||
20 | |||
21 | #endif | 18 | #endif |
diff --git a/sound/soc/blackfin/bf5xx-tdm.c b/sound/soc/blackfin/bf5xx-tdm.c index 24c14269f4bc..125123929f16 100644 --- a/sound/soc/blackfin/bf5xx-tdm.c +++ b/sound/soc/blackfin/bf5xx-tdm.c | |||
@@ -214,9 +214,9 @@ static int bf5xx_tdm_suspend(struct snd_soc_dai *dai) | |||
214 | 214 | ||
215 | if (!dai->active) | 215 | if (!dai->active) |
216 | return 0; | 216 | return 0; |
217 | if (dai->capture.active) | 217 | if (dai->capture_active) |
218 | sport_rx_stop(sport); | 218 | sport_rx_stop(sport); |
219 | if (dai->playback.active) | 219 | if (dai->playback_active) |
220 | sport_tx_stop(sport); | 220 | sport_tx_stop(sport); |
221 | return 0; | 221 | return 0; |
222 | } | 222 | } |
@@ -224,7 +224,7 @@ static int bf5xx_tdm_suspend(struct snd_soc_dai *dai) | |||
224 | static int bf5xx_tdm_resume(struct snd_soc_dai *dai) | 224 | static int bf5xx_tdm_resume(struct snd_soc_dai *dai) |
225 | { | 225 | { |
226 | int ret; | 226 | int ret; |
227 | struct sport_device *sport = dai->private_data; | 227 | struct sport_device *sport = snd_soc_dai_get_drvdata(dai); |
228 | 228 | ||
229 | if (!dai->active) | 229 | if (!dai->active) |
230 | return 0; | 230 | return 0; |
@@ -262,9 +262,7 @@ static struct snd_soc_dai_ops bf5xx_tdm_dai_ops = { | |||
262 | .set_channel_map = bf5xx_tdm_set_channel_map, | 262 | .set_channel_map = bf5xx_tdm_set_channel_map, |
263 | }; | 263 | }; |
264 | 264 | ||
265 | struct snd_soc_dai bf5xx_tdm_dai = { | 265 | static struct snd_soc_dai_driver bf5xx_tdm_dai = { |
266 | .name = "bf5xx-tdm", | ||
267 | .id = 0, | ||
268 | .suspend = bf5xx_tdm_suspend, | 266 | .suspend = bf5xx_tdm_suspend, |
269 | .resume = bf5xx_tdm_resume, | 267 | .resume = bf5xx_tdm_resume, |
270 | .playback = { | 268 | .playback = { |
@@ -279,7 +277,6 @@ struct snd_soc_dai bf5xx_tdm_dai = { | |||
279 | .formats = SNDRV_PCM_FMTBIT_S32_LE,}, | 277 | .formats = SNDRV_PCM_FMTBIT_S32_LE,}, |
280 | .ops = &bf5xx_tdm_dai_ops, | 278 | .ops = &bf5xx_tdm_dai_ops, |
281 | }; | 279 | }; |
282 | EXPORT_SYMBOL_GPL(bf5xx_tdm_dai); | ||
283 | 280 | ||
284 | static int __devinit bfin_tdm_probe(struct platform_device *pdev) | 281 | static int __devinit bfin_tdm_probe(struct platform_device *pdev) |
285 | { | 282 | { |
@@ -320,7 +317,7 @@ static int __devinit bfin_tdm_probe(struct platform_device *pdev) | |||
320 | goto sport_config_err; | 317 | goto sport_config_err; |
321 | } | 318 | } |
322 | 319 | ||
323 | ret = snd_soc_register_dai(&bf5xx_tdm_dai); | 320 | ret = snd_soc_register_dai(&pdev->dev, &bf5xx_tdm_dai); |
324 | if (ret) { | 321 | if (ret) { |
325 | pr_err("Failed to register DAI: %d\n", ret); | 322 | pr_err("Failed to register DAI: %d\n", ret); |
326 | goto sport_config_err; | 323 | goto sport_config_err; |
@@ -337,7 +334,7 @@ sport_config_err: | |||
337 | static int __devexit bfin_tdm_remove(struct platform_device *pdev) | 334 | static int __devexit bfin_tdm_remove(struct platform_device *pdev) |
338 | { | 335 | { |
339 | peripheral_free_list(&sport_req[sport_num][0]); | 336 | peripheral_free_list(&sport_req[sport_num][0]); |
340 | snd_soc_unregister_dai(&bf5xx_tdm_dai); | 337 | snd_soc_unregister_dai(&pdev->dev); |
341 | 338 | ||
342 | return 0; | 339 | return 0; |
343 | } | 340 | } |
diff --git a/sound/soc/blackfin/bf5xx-tdm.h b/sound/soc/blackfin/bf5xx-tdm.h index 04189a18c1ba..e986a3ea3315 100644 --- a/sound/soc/blackfin/bf5xx-tdm.h +++ b/sound/soc/blackfin/bf5xx-tdm.h | |||
@@ -20,6 +20,4 @@ struct bf5xx_tdm_port { | |||
20 | int configured; | 20 | int configured; |
21 | }; | 21 | }; |
22 | 22 | ||
23 | extern struct snd_soc_dai bf5xx_tdm_dai; | ||
24 | |||
25 | #endif | 23 | #endif |
diff --git a/sound/soc/codecs/ac97.c b/sound/soc/codecs/ac97.c index 1f5e57a4bb7a..12c87d37eba1 100644 --- a/sound/soc/codecs/ac97.c +++ b/sound/soc/codecs/ac97.c | |||
@@ -21,7 +21,6 @@ | |||
21 | #include <sound/ac97_codec.h> | 21 | #include <sound/ac97_codec.h> |
22 | #include <sound/initval.h> | 22 | #include <sound/initval.h> |
23 | #include <sound/soc.h> | 23 | #include <sound/soc.h> |
24 | #include "ac97.h" | ||
25 | 24 | ||
26 | #define AC97_VERSION "0.6" | 25 | #define AC97_VERSION "0.6" |
27 | 26 | ||
@@ -30,8 +29,7 @@ static int ac97_prepare(struct snd_pcm_substream *substream, | |||
30 | { | 29 | { |
31 | struct snd_pcm_runtime *runtime = substream->runtime; | 30 | struct snd_pcm_runtime *runtime = substream->runtime; |
32 | struct snd_soc_pcm_runtime *rtd = substream->private_data; | 31 | struct snd_soc_pcm_runtime *rtd = substream->private_data; |
33 | struct snd_soc_device *socdev = rtd->socdev; | 32 | struct snd_soc_codec *codec = rtd->codec; |
34 | struct snd_soc_codec *codec = socdev->card->codec; | ||
35 | 33 | ||
36 | int reg = (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) ? | 34 | int reg = (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) ? |
37 | AC97_PCM_FRONT_DAC_RATE : AC97_PCM_LR_ADC_RATE; | 35 | AC97_PCM_FRONT_DAC_RATE : AC97_PCM_LR_ADC_RATE; |
@@ -46,8 +44,8 @@ static struct snd_soc_dai_ops ac97_dai_ops = { | |||
46 | .prepare = ac97_prepare, | 44 | .prepare = ac97_prepare, |
47 | }; | 45 | }; |
48 | 46 | ||
49 | struct snd_soc_dai ac97_dai = { | 47 | static struct snd_soc_dai_driver ac97_dai = { |
50 | .name = "AC97 HiFi", | 48 | .name = "ac97-hifi", |
51 | .ac97_control = 1, | 49 | .ac97_control = 1, |
52 | .playback = { | 50 | .playback = { |
53 | .stream_name = "AC97 Playback", | 51 | .stream_name = "AC97 Playback", |
@@ -63,7 +61,6 @@ struct snd_soc_dai ac97_dai = { | |||
63 | .formats = SND_SOC_STD_AC97_FMTS,}, | 61 | .formats = SND_SOC_STD_AC97_FMTS,}, |
64 | .ops = &ac97_dai_ops, | 62 | .ops = &ac97_dai_ops, |
65 | }; | 63 | }; |
66 | EXPORT_SYMBOL_GPL(ac97_dai); | ||
67 | 64 | ||
68 | static unsigned int ac97_read(struct snd_soc_codec *codec, | 65 | static unsigned int ac97_read(struct snd_soc_codec *codec, |
69 | unsigned int reg) | 66 | unsigned int reg) |
@@ -78,95 +75,49 @@ static int ac97_write(struct snd_soc_codec *codec, unsigned int reg, | |||
78 | return 0; | 75 | return 0; |
79 | } | 76 | } |
80 | 77 | ||
81 | static int ac97_soc_probe(struct platform_device *pdev) | 78 | static int ac97_soc_probe(struct snd_soc_codec *codec) |
82 | { | 79 | { |
83 | struct snd_soc_device *socdev = platform_get_drvdata(pdev); | ||
84 | struct snd_soc_card *card = socdev->card; | ||
85 | struct snd_soc_codec *codec; | ||
86 | struct snd_ac97_bus *ac97_bus; | 80 | struct snd_ac97_bus *ac97_bus; |
87 | struct snd_ac97_template ac97_template; | 81 | struct snd_ac97_template ac97_template; |
88 | int i; | 82 | int ret; |
89 | int ret = 0; | ||
90 | 83 | ||
91 | printk(KERN_INFO "AC97 SoC Audio Codec %s\n", AC97_VERSION); | 84 | printk(KERN_INFO "AC97 SoC Audio Codec %s\n", AC97_VERSION); |
92 | 85 | ||
93 | socdev->card->codec = kzalloc(sizeof(struct snd_soc_codec), GFP_KERNEL); | 86 | ret = snd_soc_new_ac97_codec(codec, &soc_ac97_ops, 0); |
94 | if (!socdev->card->codec) | 87 | if (ret < 0) { |
95 | return -ENOMEM; | 88 | printk(KERN_ERR "ASoC: failed to init gen ac97 glue\n"); |
96 | codec = socdev->card->codec; | 89 | return ret; |
97 | mutex_init(&codec->mutex); | 90 | } |
98 | |||
99 | codec->name = "AC97"; | ||
100 | codec->owner = THIS_MODULE; | ||
101 | codec->dai = &ac97_dai; | ||
102 | codec->num_dai = 1; | ||
103 | codec->write = ac97_write; | ||
104 | codec->read = ac97_read; | ||
105 | INIT_LIST_HEAD(&codec->dapm_widgets); | ||
106 | INIT_LIST_HEAD(&codec->dapm_paths); | ||
107 | |||
108 | /* register pcms */ | ||
109 | ret = snd_soc_new_pcms(socdev, SNDRV_DEFAULT_IDX1, SNDRV_DEFAULT_STR1); | ||
110 | if (ret < 0) | ||
111 | goto err; | ||
112 | 91 | ||
113 | /* add codec as bus device for standard ac97 */ | 92 | /* add codec as bus device for standard ac97 */ |
114 | ret = snd_ac97_bus(codec->card, 0, &soc_ac97_ops, NULL, &ac97_bus); | 93 | ret = snd_ac97_bus(codec->card->snd_card, 0, &soc_ac97_ops, NULL, &ac97_bus); |
115 | if (ret < 0) | 94 | if (ret < 0) |
116 | goto bus_err; | 95 | return ret; |
117 | 96 | ||
118 | memset(&ac97_template, 0, sizeof(struct snd_ac97_template)); | 97 | memset(&ac97_template, 0, sizeof(struct snd_ac97_template)); |
119 | ret = snd_ac97_mixer(ac97_bus, &ac97_template, &codec->ac97); | 98 | ret = snd_ac97_mixer(ac97_bus, &ac97_template, &codec->ac97); |
120 | if (ret < 0) | 99 | if (ret < 0) |
121 | goto bus_err; | 100 | return ret; |
122 | |||
123 | for (i = 0; i < card->num_links; i++) { | ||
124 | if (card->dai_link[i].codec_dai->ac97_control) { | ||
125 | snd_ac97_dev_add_pdata(codec->ac97, | ||
126 | card->dai_link[i].cpu_dai->ac97_pdata); | ||
127 | } | ||
128 | } | ||
129 | 101 | ||
130 | return 0; | 102 | return 0; |
131 | |||
132 | bus_err: | ||
133 | snd_soc_free_pcms(socdev); | ||
134 | |||
135 | err: | ||
136 | kfree(socdev->card->codec); | ||
137 | socdev->card->codec = NULL; | ||
138 | return ret; | ||
139 | } | 103 | } |
140 | 104 | ||
141 | static int ac97_soc_remove(struct platform_device *pdev) | 105 | static int ac97_soc_remove(struct snd_soc_codec *codec) |
142 | { | 106 | { |
143 | struct snd_soc_device *socdev = platform_get_drvdata(pdev); | ||
144 | struct snd_soc_codec *codec = socdev->card->codec; | ||
145 | |||
146 | if (!codec) | ||
147 | return 0; | ||
148 | |||
149 | snd_soc_free_pcms(socdev); | ||
150 | kfree(socdev->card->codec); | ||
151 | |||
152 | return 0; | 107 | return 0; |
153 | } | 108 | } |
154 | 109 | ||
155 | #ifdef CONFIG_PM | 110 | #ifdef CONFIG_PM |
156 | static int ac97_soc_suspend(struct platform_device *pdev, pm_message_t msg) | 111 | static int ac97_soc_suspend(struct snd_soc_codec *codec, pm_message_t msg) |
157 | { | 112 | { |
158 | struct snd_soc_device *socdev = platform_get_drvdata(pdev); | 113 | snd_ac97_suspend(codec->ac97); |
159 | |||
160 | snd_ac97_suspend(socdev->card->codec->ac97); | ||
161 | 114 | ||
162 | return 0; | 115 | return 0; |
163 | } | 116 | } |
164 | 117 | ||
165 | static int ac97_soc_resume(struct platform_device *pdev) | 118 | static int ac97_soc_resume(struct snd_soc_codec *codec) |
166 | { | 119 | { |
167 | struct snd_soc_device *socdev = platform_get_drvdata(pdev); | 120 | snd_ac97_resume(codec->ac97); |
168 | |||
169 | snd_ac97_resume(socdev->card->codec->ac97); | ||
170 | 121 | ||
171 | return 0; | 122 | return 0; |
172 | } | 123 | } |
@@ -175,13 +126,48 @@ static int ac97_soc_resume(struct platform_device *pdev) | |||
175 | #define ac97_soc_resume NULL | 126 | #define ac97_soc_resume NULL |
176 | #endif | 127 | #endif |
177 | 128 | ||
178 | struct snd_soc_codec_device soc_codec_dev_ac97 = { | 129 | static struct snd_soc_codec_driver soc_codec_dev_ac97 = { |
130 | .write = ac97_write, | ||
131 | .read = ac97_read, | ||
179 | .probe = ac97_soc_probe, | 132 | .probe = ac97_soc_probe, |
180 | .remove = ac97_soc_remove, | 133 | .remove = ac97_soc_remove, |
181 | .suspend = ac97_soc_suspend, | 134 | .suspend = ac97_soc_suspend, |
182 | .resume = ac97_soc_resume, | 135 | .resume = ac97_soc_resume, |
183 | }; | 136 | }; |
184 | EXPORT_SYMBOL_GPL(soc_codec_dev_ac97); | 137 | |
138 | static __devinit int ac97_probe(struct platform_device *pdev) | ||
139 | { | ||
140 | return snd_soc_register_codec(&pdev->dev, | ||
141 | &soc_codec_dev_ac97, &ac97_dai, 1); | ||
142 | } | ||
143 | |||
144 | static int __devexit ac97_remove(struct platform_device *pdev) | ||
145 | { | ||
146 | snd_soc_unregister_codec(&pdev->dev); | ||
147 | return 0; | ||
148 | } | ||
149 | |||
150 | static struct platform_driver ac97_codec_driver = { | ||
151 | .driver = { | ||
152 | .name = "ac97-codec", | ||
153 | .owner = THIS_MODULE, | ||
154 | }, | ||
155 | |||
156 | .probe = ac97_probe, | ||
157 | .remove = __devexit_p(ac97_remove), | ||
158 | }; | ||
159 | |||
160 | static int __init ac97_init(void) | ||
161 | { | ||
162 | return platform_driver_register(&ac97_codec_driver); | ||
163 | } | ||
164 | module_init(ac97_init); | ||
165 | |||
166 | static void __exit ac97_exit(void) | ||
167 | { | ||
168 | platform_driver_unregister(&ac97_codec_driver); | ||
169 | } | ||
170 | module_exit(ac97_exit); | ||
185 | 171 | ||
186 | MODULE_DESCRIPTION("Soc Generic AC97 driver"); | 172 | MODULE_DESCRIPTION("Soc Generic AC97 driver"); |
187 | MODULE_AUTHOR("Liam Girdwood"); | 173 | MODULE_AUTHOR("Liam Girdwood"); |
diff --git a/sound/soc/codecs/ac97.h b/sound/soc/codecs/ac97.h deleted file mode 100644 index 281aa42e2bbb..000000000000 --- a/sound/soc/codecs/ac97.h +++ /dev/null | |||
@@ -1,19 +0,0 @@ | |||
1 | /* | ||
2 | * linux/sound/codecs/ac97.h -- ALSA SoC Layer | ||
3 | * | ||
4 | * Author: Liam Girdwood | ||
5 | * Created: Dec 1st 2005 | ||
6 | * Copyright: Wolfson Microelectronics. PLC. | ||
7 | * | ||
8 | * This program is free software; you can redistribute it and/or modify | ||
9 | * it under the terms of the GNU General Public License version 2 as | ||
10 | * published by the Free Software Foundation. | ||
11 | */ | ||
12 | |||
13 | #ifndef __LINUX_SND_SOC_AC97_H | ||
14 | #define __LINUX_SND_SOC_AC97_H | ||
15 | |||
16 | extern struct snd_soc_codec_device soc_codec_dev_ac97; | ||
17 | extern struct snd_soc_dai ac97_dai; | ||
18 | |||
19 | #endif | ||
diff --git a/sound/soc/codecs/ad1836.c b/sound/soc/codecs/ad1836.c index a01006c8c606..d272534c8f84 100644 --- a/sound/soc/codecs/ad1836.c +++ b/sound/soc/codecs/ad1836.c | |||
@@ -33,15 +33,10 @@ | |||
33 | 33 | ||
34 | /* codec private data */ | 34 | /* codec private data */ |
35 | struct ad1836_priv { | 35 | struct ad1836_priv { |
36 | struct snd_soc_codec codec; | 36 | enum snd_soc_control_type control_type; |
37 | u16 reg_cache[AD1836_NUM_REGS]; | 37 | void *control_data; |
38 | }; | 38 | }; |
39 | 39 | ||
40 | static struct snd_soc_codec *ad1836_codec; | ||
41 | struct snd_soc_codec_device soc_codec_dev_ad1836; | ||
42 | static int ad1836_register(struct ad1836_priv *ad1836); | ||
43 | static void ad1836_unregister(struct ad1836_priv *ad1836); | ||
44 | |||
45 | /* | 40 | /* |
46 | * AD1836 volume/mute/de-emphasis etc. controls | 41 | * AD1836 volume/mute/de-emphasis etc. controls |
47 | */ | 42 | */ |
@@ -146,8 +141,7 @@ static int ad1836_hw_params(struct snd_pcm_substream *substream, | |||
146 | int word_len = 0; | 141 | int word_len = 0; |
147 | 142 | ||
148 | struct snd_soc_pcm_runtime *rtd = substream->private_data; | 143 | struct snd_soc_pcm_runtime *rtd = substream->private_data; |
149 | struct snd_soc_device *socdev = rtd->socdev; | 144 | struct snd_soc_codec *codec = rtd->codec; |
150 | struct snd_soc_codec *codec = socdev->card->codec; | ||
151 | 145 | ||
152 | /* bit size */ | 146 | /* bit size */ |
153 | switch (params_format(params)) { | 147 | switch (params_format(params)) { |
@@ -173,12 +167,9 @@ static int ad1836_hw_params(struct snd_pcm_substream *substream, | |||
173 | } | 167 | } |
174 | 168 | ||
175 | #ifdef CONFIG_PM | 169 | #ifdef CONFIG_PM |
176 | static int ad1836_soc_suspend(struct platform_device *pdev, | 170 | static int ad1836_soc_suspend(struct snd_soc_codec *codec, |
177 | pm_message_t state) | 171 | pm_message_t state) |
178 | { | 172 | { |
179 | struct snd_soc_device *socdev = platform_get_drvdata(pdev); | ||
180 | struct snd_soc_codec *codec = socdev->card->codec; | ||
181 | |||
182 | /* reset clock control mode */ | 173 | /* reset clock control mode */ |
183 | u16 adc_ctrl2 = snd_soc_read(codec, AD1836_ADC_CTRL2); | 174 | u16 adc_ctrl2 = snd_soc_read(codec, AD1836_ADC_CTRL2); |
184 | adc_ctrl2 &= ~AD1836_ADC_SERFMT_MASK; | 175 | adc_ctrl2 &= ~AD1836_ADC_SERFMT_MASK; |
@@ -186,11 +177,8 @@ static int ad1836_soc_suspend(struct platform_device *pdev, | |||
186 | return snd_soc_write(codec, AD1836_ADC_CTRL2, adc_ctrl2); | 177 | return snd_soc_write(codec, AD1836_ADC_CTRL2, adc_ctrl2); |
187 | } | 178 | } |
188 | 179 | ||
189 | static int ad1836_soc_resume(struct platform_device *pdev) | 180 | static int ad1836_soc_resume(struct snd_soc_codec *codec) |
190 | { | 181 | { |
191 | struct snd_soc_device *socdev = platform_get_drvdata(pdev); | ||
192 | struct snd_soc_codec *codec = socdev->card->codec; | ||
193 | |||
194 | /* restore clock control mode */ | 182 | /* restore clock control mode */ |
195 | u16 adc_ctrl2 = snd_soc_read(codec, AD1836_ADC_CTRL2); | 183 | u16 adc_ctrl2 = snd_soc_read(codec, AD1836_ADC_CTRL2); |
196 | adc_ctrl2 |= AD1836_ADC_AUX; | 184 | adc_ctrl2 |= AD1836_ADC_AUX; |
@@ -202,49 +190,14 @@ static int ad1836_soc_resume(struct platform_device *pdev) | |||
202 | #define ad1836_soc_resume NULL | 190 | #define ad1836_soc_resume NULL |
203 | #endif | 191 | #endif |
204 | 192 | ||
205 | static int __devinit ad1836_spi_probe(struct spi_device *spi) | ||
206 | { | ||
207 | struct snd_soc_codec *codec; | ||
208 | struct ad1836_priv *ad1836; | ||
209 | |||
210 | ad1836 = kzalloc(sizeof(struct ad1836_priv), GFP_KERNEL); | ||
211 | if (ad1836 == NULL) | ||
212 | return -ENOMEM; | ||
213 | |||
214 | codec = &ad1836->codec; | ||
215 | codec->control_data = spi; | ||
216 | codec->dev = &spi->dev; | ||
217 | |||
218 | dev_set_drvdata(&spi->dev, ad1836); | ||
219 | |||
220 | return ad1836_register(ad1836); | ||
221 | } | ||
222 | |||
223 | static int __devexit ad1836_spi_remove(struct spi_device *spi) | ||
224 | { | ||
225 | struct ad1836_priv *ad1836 = dev_get_drvdata(&spi->dev); | ||
226 | |||
227 | ad1836_unregister(ad1836); | ||
228 | return 0; | ||
229 | } | ||
230 | |||
231 | static struct spi_driver ad1836_spi_driver = { | ||
232 | .driver = { | ||
233 | .name = "ad1836", | ||
234 | .owner = THIS_MODULE, | ||
235 | }, | ||
236 | .probe = ad1836_spi_probe, | ||
237 | .remove = __devexit_p(ad1836_spi_remove), | ||
238 | }; | ||
239 | |||
240 | static struct snd_soc_dai_ops ad1836_dai_ops = { | 193 | static struct snd_soc_dai_ops ad1836_dai_ops = { |
241 | .hw_params = ad1836_hw_params, | 194 | .hw_params = ad1836_hw_params, |
242 | .set_fmt = ad1836_set_dai_fmt, | 195 | .set_fmt = ad1836_set_dai_fmt, |
243 | }; | 196 | }; |
244 | 197 | ||
245 | /* codec DAI instance */ | 198 | /* codec DAI instance */ |
246 | struct snd_soc_dai ad1836_dai = { | 199 | static struct snd_soc_dai_driver ad1836_dai = { |
247 | .name = "AD1836", | 200 | .name = "ad1836-hifi", |
248 | .playback = { | 201 | .playback = { |
249 | .stream_name = "Playback", | 202 | .stream_name = "Playback", |
250 | .channels_min = 2, | 203 | .channels_min = 2, |
@@ -263,35 +216,13 @@ struct snd_soc_dai ad1836_dai = { | |||
263 | }, | 216 | }, |
264 | .ops = &ad1836_dai_ops, | 217 | .ops = &ad1836_dai_ops, |
265 | }; | 218 | }; |
266 | EXPORT_SYMBOL_GPL(ad1836_dai); | ||
267 | 219 | ||
268 | static int ad1836_register(struct ad1836_priv *ad1836) | 220 | static int ad1836_probe(struct snd_soc_codec *codec) |
269 | { | 221 | { |
270 | int ret; | 222 | struct ad1836_priv *ad1836 = snd_soc_codec_get_drvdata(codec); |
271 | struct snd_soc_codec *codec = &ad1836->codec; | 223 | int ret = 0; |
272 | |||
273 | if (ad1836_codec) { | ||
274 | dev_err(codec->dev, "Another ad1836 is registered\n"); | ||
275 | kfree(ad1836); | ||
276 | return -EINVAL; | ||
277 | } | ||
278 | |||
279 | mutex_init(&codec->mutex); | ||
280 | INIT_LIST_HEAD(&codec->dapm_widgets); | ||
281 | INIT_LIST_HEAD(&codec->dapm_paths); | ||
282 | snd_soc_codec_set_drvdata(codec, ad1836); | ||
283 | codec->reg_cache = ad1836->reg_cache; | ||
284 | codec->reg_cache_size = AD1836_NUM_REGS; | ||
285 | codec->name = "AD1836"; | ||
286 | codec->owner = THIS_MODULE; | ||
287 | codec->dai = &ad1836_dai; | ||
288 | codec->num_dai = 1; | ||
289 | INIT_LIST_HEAD(&codec->dapm_widgets); | ||
290 | INIT_LIST_HEAD(&codec->dapm_paths); | ||
291 | |||
292 | ad1836_dai.dev = codec->dev; | ||
293 | ad1836_codec = codec; | ||
294 | 224 | ||
225 | codec->control_data = ad1836->control_data; | ||
295 | ret = snd_soc_codec_set_cache_io(codec, 4, 12, SND_SOC_SPI); | 226 | ret = snd_soc_codec_set_cache_io(codec, 4, 12, SND_SOC_SPI); |
296 | if (ret < 0) { | 227 | if (ret < 0) { |
297 | dev_err(codec->dev, "failed to set cache I/O: %d\n", | 228 | dev_err(codec->dev, "failed to set cache I/O: %d\n", |
@@ -319,81 +250,69 @@ static int ad1836_register(struct ad1836_priv *ad1836) | |||
319 | snd_soc_write(codec, AD1836_DAC_L3_VOL, 0x3FF); | 250 | snd_soc_write(codec, AD1836_DAC_L3_VOL, 0x3FF); |
320 | snd_soc_write(codec, AD1836_DAC_R3_VOL, 0x3FF); | 251 | snd_soc_write(codec, AD1836_DAC_R3_VOL, 0x3FF); |
321 | 252 | ||
322 | ret = snd_soc_register_codec(codec); | ||
323 | if (ret != 0) { | ||
324 | dev_err(codec->dev, "Failed to register codec: %d\n", ret); | ||
325 | kfree(ad1836); | ||
326 | return ret; | ||
327 | } | ||
328 | |||
329 | ret = snd_soc_register_dai(&ad1836_dai); | ||
330 | if (ret != 0) { | ||
331 | dev_err(codec->dev, "Failed to register DAI: %d\n", ret); | ||
332 | snd_soc_unregister_codec(codec); | ||
333 | kfree(ad1836); | ||
334 | return ret; | ||
335 | } | ||
336 | |||
337 | return 0; | ||
338 | } | ||
339 | |||
340 | static void ad1836_unregister(struct ad1836_priv *ad1836) | ||
341 | { | ||
342 | snd_soc_unregister_dai(&ad1836_dai); | ||
343 | snd_soc_unregister_codec(&ad1836->codec); | ||
344 | kfree(ad1836); | ||
345 | ad1836_codec = NULL; | ||
346 | } | ||
347 | |||
348 | static int ad1836_probe(struct platform_device *pdev) | ||
349 | { | ||
350 | struct snd_soc_device *socdev = platform_get_drvdata(pdev); | ||
351 | struct snd_soc_codec *codec; | ||
352 | int ret = 0; | ||
353 | |||
354 | if (ad1836_codec == NULL) { | ||
355 | dev_err(&pdev->dev, "Codec device not registered\n"); | ||
356 | return -ENODEV; | ||
357 | } | ||
358 | |||
359 | socdev->card->codec = ad1836_codec; | ||
360 | codec = ad1836_codec; | ||
361 | |||
362 | /* register pcms */ | ||
363 | ret = snd_soc_new_pcms(socdev, SNDRV_DEFAULT_IDX1, SNDRV_DEFAULT_STR1); | ||
364 | if (ret < 0) { | ||
365 | dev_err(codec->dev, "failed to create pcms: %d\n", ret); | ||
366 | goto pcm_err; | ||
367 | } | ||
368 | |||
369 | snd_soc_add_controls(codec, ad1836_snd_controls, | 253 | snd_soc_add_controls(codec, ad1836_snd_controls, |
370 | ARRAY_SIZE(ad1836_snd_controls)); | 254 | ARRAY_SIZE(ad1836_snd_controls)); |
371 | snd_soc_dapm_new_controls(codec, ad1836_dapm_widgets, | 255 | snd_soc_dapm_new_controls(codec, ad1836_dapm_widgets, |
372 | ARRAY_SIZE(ad1836_dapm_widgets)); | 256 | ARRAY_SIZE(ad1836_dapm_widgets)); |
373 | snd_soc_dapm_add_routes(codec, audio_paths, ARRAY_SIZE(audio_paths)); | 257 | snd_soc_dapm_add_routes(codec, audio_paths, ARRAY_SIZE(audio_paths)); |
374 | 258 | ||
375 | pcm_err: | ||
376 | return ret; | 259 | return ret; |
377 | } | 260 | } |
378 | 261 | ||
379 | /* power down chip */ | 262 | /* power down chip */ |
380 | static int ad1836_remove(struct platform_device *pdev) | 263 | static int ad1836_remove(struct snd_soc_codec *codec) |
381 | { | 264 | { |
382 | struct snd_soc_device *socdev = platform_get_drvdata(pdev); | 265 | /* reset clock control mode */ |
383 | 266 | u16 adc_ctrl2 = snd_soc_read(codec, AD1836_ADC_CTRL2); | |
384 | snd_soc_free_pcms(socdev); | 267 | adc_ctrl2 &= ~AD1836_ADC_SERFMT_MASK; |
385 | snd_soc_dapm_free(socdev); | ||
386 | 268 | ||
387 | return 0; | 269 | return snd_soc_write(codec, AD1836_ADC_CTRL2, adc_ctrl2); |
388 | } | 270 | } |
389 | 271 | ||
390 | struct snd_soc_codec_device soc_codec_dev_ad1836 = { | 272 | static struct snd_soc_codec_driver soc_codec_dev_ad1836 = { |
391 | .probe = ad1836_probe, | 273 | .probe = ad1836_probe, |
392 | .remove = ad1836_remove, | 274 | .remove = ad1836_remove, |
393 | .suspend = ad1836_soc_suspend, | 275 | .suspend = ad1836_soc_suspend, |
394 | .resume = ad1836_soc_resume, | 276 | .resume = ad1836_soc_resume, |
277 | .reg_cache_size = AD1836_NUM_REGS, | ||
278 | .reg_word_size = sizeof(u16), | ||
279 | }; | ||
280 | |||
281 | static int __devinit ad1836_spi_probe(struct spi_device *spi) | ||
282 | { | ||
283 | struct ad1836_priv *ad1836; | ||
284 | int ret; | ||
285 | |||
286 | ad1836 = kzalloc(sizeof(struct ad1836_priv), GFP_KERNEL); | ||
287 | if (ad1836 == NULL) | ||
288 | return -ENOMEM; | ||
289 | |||
290 | spi_set_drvdata(spi, ad1836); | ||
291 | ad1836->control_data = spi; | ||
292 | ad1836->control_type = SND_SOC_SPI; | ||
293 | |||
294 | ret = snd_soc_register_codec(&spi->dev, | ||
295 | &soc_codec_dev_ad1836, &ad1836_dai, 1); | ||
296 | if (ret < 0) | ||
297 | kfree(ad1836); | ||
298 | return ret; | ||
299 | } | ||
300 | |||
301 | static int __devexit ad1836_spi_remove(struct spi_device *spi) | ||
302 | { | ||
303 | snd_soc_unregister_codec(&spi->dev); | ||
304 | kfree(spi_get_drvdata(spi)); | ||
305 | return 0; | ||
306 | } | ||
307 | |||
308 | static struct spi_driver ad1836_spi_driver = { | ||
309 | .driver = { | ||
310 | .name = "ad1836-codec", | ||
311 | .owner = THIS_MODULE, | ||
312 | }, | ||
313 | .probe = ad1836_spi_probe, | ||
314 | .remove = __devexit_p(ad1836_spi_remove), | ||
395 | }; | 315 | }; |
396 | EXPORT_SYMBOL_GPL(soc_codec_dev_ad1836); | ||
397 | 316 | ||
398 | static int __init ad1836_init(void) | 317 | static int __init ad1836_init(void) |
399 | { | 318 | { |
diff --git a/sound/soc/codecs/ad1836.h b/sound/soc/codecs/ad1836.h index e9d90d3951c5..845596717fdf 100644 --- a/sound/soc/codecs/ad1836.h +++ b/sound/soc/codecs/ad1836.h | |||
@@ -60,6 +60,4 @@ | |||
60 | 60 | ||
61 | #define AD1836_NUM_REGS 16 | 61 | #define AD1836_NUM_REGS 16 |
62 | 62 | ||
63 | extern struct snd_soc_dai ad1836_dai; | ||
64 | extern struct snd_soc_codec_device soc_codec_dev_ad1836; | ||
65 | #endif | 63 | #endif |
diff --git a/sound/soc/codecs/ad193x.c b/sound/soc/codecs/ad193x.c index 1def75e4862f..fa2834c91b9f 100644 --- a/sound/soc/codecs/ad193x.c +++ b/sound/soc/codecs/ad193x.c | |||
@@ -24,9 +24,10 @@ | |||
24 | 24 | ||
25 | /* codec private data */ | 25 | /* codec private data */ |
26 | struct ad193x_priv { | 26 | struct ad193x_priv { |
27 | unsigned int sysclk; | ||
28 | struct snd_soc_codec codec; | ||
29 | u8 reg_cache[AD193X_NUM_REGS]; | 27 | u8 reg_cache[AD193X_NUM_REGS]; |
28 | enum snd_soc_control_type bus_type; | ||
29 | void *control_data; | ||
30 | int sysclk; | ||
30 | }; | 31 | }; |
31 | 32 | ||
32 | /* ad193x register cache & default register settings */ | 33 | /* ad193x register cache & default register settings */ |
@@ -34,9 +35,6 @@ static const u8 ad193x_reg[AD193X_NUM_REGS] = { | |||
34 | 0, 0, 0, 0, 0, 0, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0, 0, 0, | 35 | 0, 0, 0, 0, 0, 0, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0, 0, 0, |
35 | }; | 36 | }; |
36 | 37 | ||
37 | static struct snd_soc_codec *ad193x_codec; | ||
38 | struct snd_soc_codec_device soc_codec_dev_ad193x; | ||
39 | |||
40 | /* | 38 | /* |
41 | * AD193X volume/mute/de-emphasis etc. controls | 39 | * AD193X volume/mute/de-emphasis etc. controls |
42 | */ | 40 | */ |
@@ -275,8 +273,7 @@ static int ad193x_hw_params(struct snd_pcm_substream *substream, | |||
275 | int word_len = 0, reg = 0, master_rate = 0; | 273 | int word_len = 0, reg = 0, master_rate = 0; |
276 | 274 | ||
277 | struct snd_soc_pcm_runtime *rtd = substream->private_data; | 275 | struct snd_soc_pcm_runtime *rtd = substream->private_data; |
278 | struct snd_soc_device *socdev = rtd->socdev; | 276 | struct snd_soc_codec *codec = rtd->codec; |
279 | struct snd_soc_codec *codec = socdev->card->codec; | ||
280 | struct ad193x_priv *ad193x = snd_soc_codec_get_drvdata(codec); | 277 | struct ad193x_priv *ad193x = snd_soc_codec_get_drvdata(codec); |
281 | 278 | ||
282 | /* bit size */ | 279 | /* bit size */ |
@@ -323,100 +320,6 @@ static int ad193x_hw_params(struct snd_pcm_substream *substream, | |||
323 | return 0; | 320 | return 0; |
324 | } | 321 | } |
325 | 322 | ||
326 | static int ad193x_bus_probe(struct device *dev, void *ctrl_data, int bus_type) | ||
327 | { | ||
328 | struct snd_soc_codec *codec; | ||
329 | struct ad193x_priv *ad193x; | ||
330 | int ret; | ||
331 | |||
332 | if (ad193x_codec) { | ||
333 | dev_err(dev, "Another ad193x is registered\n"); | ||
334 | return -EINVAL; | ||
335 | } | ||
336 | |||
337 | ad193x = kzalloc(sizeof(struct ad193x_priv), GFP_KERNEL); | ||
338 | if (ad193x == NULL) | ||
339 | return -ENOMEM; | ||
340 | |||
341 | dev_set_drvdata(dev, ad193x); | ||
342 | |||
343 | codec = &ad193x->codec; | ||
344 | mutex_init(&codec->mutex); | ||
345 | codec->control_data = ctrl_data; | ||
346 | codec->dev = dev; | ||
347 | snd_soc_codec_set_drvdata(codec, ad193x); | ||
348 | codec->reg_cache = ad193x->reg_cache; | ||
349 | codec->reg_cache_size = AD193X_NUM_REGS; | ||
350 | codec->name = "AD193X"; | ||
351 | codec->owner = THIS_MODULE; | ||
352 | codec->dai = &ad193x_dai; | ||
353 | codec->num_dai = 1; | ||
354 | INIT_LIST_HEAD(&codec->dapm_widgets); | ||
355 | INIT_LIST_HEAD(&codec->dapm_paths); | ||
356 | |||
357 | ad193x_dai.dev = codec->dev; | ||
358 | ad193x_codec = codec; | ||
359 | |||
360 | memcpy(codec->reg_cache, ad193x_reg, AD193X_NUM_REGS); | ||
361 | |||
362 | if (bus_type == SND_SOC_I2C) | ||
363 | ret = snd_soc_codec_set_cache_io(codec, 8, 8, bus_type); | ||
364 | else | ||
365 | ret = snd_soc_codec_set_cache_io(codec, 16, 8, bus_type); | ||
366 | if (ret < 0) { | ||
367 | dev_err(codec->dev, "failed to set cache I/O: %d\n", | ||
368 | ret); | ||
369 | kfree(ad193x); | ||
370 | return ret; | ||
371 | } | ||
372 | |||
373 | /* default setting for ad193x */ | ||
374 | |||
375 | /* unmute dac channels */ | ||
376 | snd_soc_write(codec, AD193X_DAC_CHNL_MUTE, 0x0); | ||
377 | /* de-emphasis: 48kHz, powedown dac */ | ||
378 | snd_soc_write(codec, AD193X_DAC_CTRL2, 0x1A); | ||
379 | /* powerdown dac, dac in tdm mode */ | ||
380 | snd_soc_write(codec, AD193X_DAC_CTRL0, 0x41); | ||
381 | /* high-pass filter enable */ | ||
382 | snd_soc_write(codec, AD193X_ADC_CTRL0, 0x3); | ||
383 | /* sata delay=1, adc aux mode */ | ||
384 | snd_soc_write(codec, AD193X_ADC_CTRL1, 0x43); | ||
385 | /* pll input: mclki/xi */ | ||
386 | snd_soc_write(codec, AD193X_PLL_CLK_CTRL0, 0x99); /* mclk=24.576Mhz: 0x9D; mclk=12.288Mhz: 0x99 */ | ||
387 | snd_soc_write(codec, AD193X_PLL_CLK_CTRL1, 0x04); | ||
388 | ad193x->sysclk = 12288000; | ||
389 | |||
390 | ret = snd_soc_register_codec(codec); | ||
391 | if (ret != 0) { | ||
392 | dev_err(codec->dev, "Failed to register codec: %d\n", ret); | ||
393 | kfree(ad193x); | ||
394 | return ret; | ||
395 | } | ||
396 | |||
397 | ret = snd_soc_register_dai(&ad193x_dai); | ||
398 | if (ret != 0) { | ||
399 | dev_err(codec->dev, "Failed to register DAI: %d\n", ret); | ||
400 | snd_soc_unregister_codec(codec); | ||
401 | kfree(ad193x); | ||
402 | return ret; | ||
403 | } | ||
404 | |||
405 | return 0; | ||
406 | } | ||
407 | |||
408 | static int ad193x_bus_remove(struct device *dev) | ||
409 | { | ||
410 | struct ad193x_priv *ad193x = dev_get_drvdata(dev); | ||
411 | |||
412 | snd_soc_unregister_dai(&ad193x_dai); | ||
413 | snd_soc_unregister_codec(&ad193x->codec); | ||
414 | kfree(ad193x); | ||
415 | ad193x_codec = NULL; | ||
416 | |||
417 | return 0; | ||
418 | } | ||
419 | |||
420 | static struct snd_soc_dai_ops ad193x_dai_ops = { | 323 | static struct snd_soc_dai_ops ad193x_dai_ops = { |
421 | .hw_params = ad193x_hw_params, | 324 | .hw_params = ad193x_hw_params, |
422 | .digital_mute = ad193x_mute, | 325 | .digital_mute = ad193x_mute, |
@@ -426,8 +329,8 @@ static struct snd_soc_dai_ops ad193x_dai_ops = { | |||
426 | }; | 329 | }; |
427 | 330 | ||
428 | /* codec DAI instance */ | 331 | /* codec DAI instance */ |
429 | struct snd_soc_dai ad193x_dai = { | 332 | static struct snd_soc_dai_driver ad193x_dai = { |
430 | .name = "AD193X", | 333 | .name = "ad193x-hifi", |
431 | .playback = { | 334 | .playback = { |
432 | .stream_name = "Playback", | 335 | .stream_name = "Playback", |
433 | .channels_min = 2, | 336 | .channels_min = 2, |
@@ -446,28 +349,39 @@ struct snd_soc_dai ad193x_dai = { | |||
446 | }, | 349 | }, |
447 | .ops = &ad193x_dai_ops, | 350 | .ops = &ad193x_dai_ops, |
448 | }; | 351 | }; |
449 | EXPORT_SYMBOL_GPL(ad193x_dai); | ||
450 | 352 | ||
451 | static int ad193x_probe(struct platform_device *pdev) | 353 | static int ad193x_probe(struct snd_soc_codec *codec) |
452 | { | 354 | { |
453 | struct snd_soc_device *socdev = platform_get_drvdata(pdev); | 355 | struct ad193x_priv *ad193x = snd_soc_codec_get_drvdata(codec); |
454 | struct snd_soc_codec *codec; | 356 | int ret; |
455 | int ret = 0; | ||
456 | 357 | ||
457 | if (ad193x_codec == NULL) { | 358 | codec->control_data = ad193x->control_data; |
458 | dev_err(&pdev->dev, "Codec device not registered\n"); | 359 | if (ad193x->bus_type == SND_SOC_I2C) |
459 | return -ENODEV; | 360 | ret = snd_soc_codec_set_cache_io(codec, 8, 8, ad193x->bus_type); |
361 | else | ||
362 | ret = snd_soc_codec_set_cache_io(codec, 16, 8, ad193x->bus_type); | ||
363 | if (ret < 0) { | ||
364 | dev_err(codec->dev, "failed to set cache I/O: %d\n", | ||
365 | ret); | ||
366 | kfree(ad193x); | ||
367 | return ret; | ||
460 | } | 368 | } |
461 | 369 | ||
462 | socdev->card->codec = ad193x_codec; | 370 | /* default setting for ad193x */ |
463 | codec = ad193x_codec; | ||
464 | 371 | ||
465 | /* register pcms */ | 372 | /* unmute dac channels */ |
466 | ret = snd_soc_new_pcms(socdev, SNDRV_DEFAULT_IDX1, SNDRV_DEFAULT_STR1); | 373 | snd_soc_write(codec, AD193X_DAC_CHNL_MUTE, 0x0); |
467 | if (ret < 0) { | 374 | /* de-emphasis: 48kHz, powedown dac */ |
468 | dev_err(codec->dev, "failed to create pcms: %d\n", ret); | 375 | snd_soc_write(codec, AD193X_DAC_CTRL2, 0x1A); |
469 | goto pcm_err; | 376 | /* powerdown dac, dac in tdm mode */ |
470 | } | 377 | snd_soc_write(codec, AD193X_DAC_CTRL0, 0x41); |
378 | /* high-pass filter enable */ | ||
379 | snd_soc_write(codec, AD193X_ADC_CTRL0, 0x3); | ||
380 | /* sata delay=1, adc aux mode */ | ||
381 | snd_soc_write(codec, AD193X_ADC_CTRL1, 0x43); | ||
382 | /* pll input: mclki/xi */ | ||
383 | snd_soc_write(codec, AD193X_PLL_CLK_CTRL0, 0x99); /* mclk=24.576Mhz: 0x9D; mclk=12.288Mhz: 0x99 */ | ||
384 | snd_soc_write(codec, AD193X_PLL_CLK_CTRL1, 0x04); | ||
471 | 385 | ||
472 | snd_soc_add_controls(codec, ad193x_snd_controls, | 386 | snd_soc_add_controls(codec, ad193x_snd_controls, |
473 | ARRAY_SIZE(ad193x_snd_controls)); | 387 | ARRAY_SIZE(ad193x_snd_controls)); |
@@ -475,41 +389,47 @@ static int ad193x_probe(struct platform_device *pdev) | |||
475 | ARRAY_SIZE(ad193x_dapm_widgets)); | 389 | ARRAY_SIZE(ad193x_dapm_widgets)); |
476 | snd_soc_dapm_add_routes(codec, audio_paths, ARRAY_SIZE(audio_paths)); | 390 | snd_soc_dapm_add_routes(codec, audio_paths, ARRAY_SIZE(audio_paths)); |
477 | 391 | ||
478 | pcm_err: | ||
479 | return ret; | 392 | return ret; |
480 | } | 393 | } |
481 | 394 | ||
482 | /* power down chip */ | 395 | static struct snd_soc_codec_driver soc_codec_dev_ad193x = { |
483 | static int ad193x_remove(struct platform_device *pdev) | ||
484 | { | ||
485 | struct snd_soc_device *socdev = platform_get_drvdata(pdev); | ||
486 | |||
487 | snd_soc_free_pcms(socdev); | ||
488 | snd_soc_dapm_free(socdev); | ||
489 | |||
490 | return 0; | ||
491 | } | ||
492 | |||
493 | struct snd_soc_codec_device soc_codec_dev_ad193x = { | ||
494 | .probe = ad193x_probe, | 396 | .probe = ad193x_probe, |
495 | .remove = ad193x_remove, | 397 | .reg_cache_default = ad193x_reg, |
398 | .reg_cache_size = AD193X_NUM_REGS, | ||
399 | .reg_word_size = sizeof(u16), | ||
496 | }; | 400 | }; |
497 | EXPORT_SYMBOL_GPL(soc_codec_dev_ad193x); | ||
498 | 401 | ||
499 | #if defined(CONFIG_SPI_MASTER) | 402 | #if defined(CONFIG_SPI_MASTER) |
500 | static int __devinit ad193x_spi_probe(struct spi_device *spi) | 403 | static int __devinit ad193x_spi_probe(struct spi_device *spi) |
501 | { | 404 | { |
502 | return ad193x_bus_probe(&spi->dev, spi, SND_SOC_SPI); | 405 | struct ad193x_priv *ad193x; |
406 | int ret; | ||
407 | |||
408 | ad193x = kzalloc(sizeof(struct ad193x_priv), GFP_KERNEL); | ||
409 | if (ad193x == NULL) | ||
410 | return -ENOMEM; | ||
411 | |||
412 | spi_set_drvdata(spi, ad193x); | ||
413 | ad193x->control_data = spi; | ||
414 | ad193x->bus_type = SND_SOC_SPI; | ||
415 | |||
416 | ret = snd_soc_register_codec(&spi->dev, | ||
417 | &soc_codec_dev_ad193x, &ad193x_dai, 1); | ||
418 | if (ret < 0) | ||
419 | kfree(ad193x); | ||
420 | return ret; | ||
503 | } | 421 | } |
504 | 422 | ||
505 | static int __devexit ad193x_spi_remove(struct spi_device *spi) | 423 | static int __devexit ad193x_spi_remove(struct spi_device *spi) |
506 | { | 424 | { |
507 | return ad193x_bus_remove(&spi->dev); | 425 | snd_soc_unregister_codec(&spi->dev); |
426 | kfree(spi_get_drvdata(spi)); | ||
427 | return 0; | ||
508 | } | 428 | } |
509 | 429 | ||
510 | static struct spi_driver ad193x_spi_driver = { | 430 | static struct spi_driver ad193x_spi_driver = { |
511 | .driver = { | 431 | .driver = { |
512 | .name = "ad193x", | 432 | .name = "ad193x-codec", |
513 | .owner = THIS_MODULE, | 433 | .owner = THIS_MODULE, |
514 | }, | 434 | }, |
515 | .probe = ad193x_spi_probe, | 435 | .probe = ad193x_spi_probe, |
@@ -528,17 +448,34 @@ MODULE_DEVICE_TABLE(i2c, ad193x_id); | |||
528 | static int __devinit ad193x_i2c_probe(struct i2c_client *client, | 448 | static int __devinit ad193x_i2c_probe(struct i2c_client *client, |
529 | const struct i2c_device_id *id) | 449 | const struct i2c_device_id *id) |
530 | { | 450 | { |
531 | return ad193x_bus_probe(&client->dev, client, SND_SOC_I2C); | 451 | struct ad193x_priv *ad193x; |
452 | int ret; | ||
453 | |||
454 | ad193x = kzalloc(sizeof(struct ad193x_priv), GFP_KERNEL); | ||
455 | if (ad193x == NULL) | ||
456 | return -ENOMEM; | ||
457 | |||
458 | i2c_set_clientdata(client, ad193x); | ||
459 | ad193x->control_data = client; | ||
460 | ad193x->bus_type = SND_SOC_I2C; | ||
461 | |||
462 | ret = snd_soc_register_codec(&client->dev, | ||
463 | &soc_codec_dev_ad193x, &ad193x_dai, 1); | ||
464 | if (ret < 0) | ||
465 | kfree(ad193x); | ||
466 | return ret; | ||
532 | } | 467 | } |
533 | 468 | ||
534 | static int __devexit ad193x_i2c_remove(struct i2c_client *client) | 469 | static int __devexit ad193x_i2c_remove(struct i2c_client *client) |
535 | { | 470 | { |
536 | return ad193x_bus_remove(&client->dev); | 471 | snd_soc_unregister_codec(&client->dev); |
472 | kfree(i2c_get_clientdata(client)); | ||
473 | return 0; | ||
537 | } | 474 | } |
538 | 475 | ||
539 | static struct i2c_driver ad193x_i2c_driver = { | 476 | static struct i2c_driver ad193x_i2c_driver = { |
540 | .driver = { | 477 | .driver = { |
541 | .name = "ad193x", | 478 | .name = "ad193x-codec", |
542 | }, | 479 | }, |
543 | .probe = ad193x_i2c_probe, | 480 | .probe = ad193x_i2c_probe, |
544 | .remove = __devexit_p(ad193x_i2c_remove), | 481 | .remove = __devexit_p(ad193x_i2c_remove), |
diff --git a/sound/soc/codecs/ad193x.h b/sound/soc/codecs/ad193x.h index 654ba64ae04c..9747b5497877 100644 --- a/sound/soc/codecs/ad193x.h +++ b/sound/soc/codecs/ad193x.h | |||
@@ -80,7 +80,4 @@ | |||
80 | 80 | ||
81 | #define AD193X_NUM_REGS 17 | 81 | #define AD193X_NUM_REGS 17 |
82 | 82 | ||
83 | extern struct snd_soc_dai ad193x_dai; | ||
84 | extern struct snd_soc_codec_device soc_codec_dev_ad193x; | ||
85 | |||
86 | #endif | 83 | #endif |
diff --git a/sound/soc/codecs/ad1980.c b/sound/soc/codecs/ad1980.c index 042072738cdc..1371afac657b 100644 --- a/sound/soc/codecs/ad1980.c +++ b/sound/soc/codecs/ad1980.c | |||
@@ -130,8 +130,8 @@ static int ac97_write(struct snd_soc_codec *codec, unsigned int reg, | |||
130 | return 0; | 130 | return 0; |
131 | } | 131 | } |
132 | 132 | ||
133 | struct snd_soc_dai ad1980_dai = { | 133 | struct snd_soc_dai_driver ad1980_dai = { |
134 | .name = "AC97", | 134 | .name = "ad1980-hifi", |
135 | .ac97_control = 1, | 135 | .ac97_control = 1, |
136 | .playback = { | 136 | .playback = { |
137 | .stream_name = "Playback", | 137 | .stream_name = "Playback", |
@@ -177,53 +177,20 @@ err: | |||
177 | return -EIO; | 177 | return -EIO; |
178 | } | 178 | } |
179 | 179 | ||
180 | static int ad1980_soc_probe(struct platform_device *pdev) | 180 | static int ad1980_soc_probe(struct snd_soc_codec *codec) |
181 | { | 181 | { |
182 | struct snd_soc_device *socdev = platform_get_drvdata(pdev); | 182 | int ret; |
183 | struct snd_soc_codec *codec; | ||
184 | int ret = 0; | ||
185 | u16 vendor_id2; | 183 | u16 vendor_id2; |
186 | u16 ext_status; | 184 | u16 ext_status; |
187 | 185 | ||
188 | printk(KERN_INFO "AD1980 SoC Audio Codec\n"); | 186 | printk(KERN_INFO "AD1980 SoC Audio Codec\n"); |
189 | 187 | ||
190 | socdev->card->codec = kzalloc(sizeof(struct snd_soc_codec), GFP_KERNEL); | ||
191 | if (socdev->card->codec == NULL) | ||
192 | return -ENOMEM; | ||
193 | codec = socdev->card->codec; | ||
194 | mutex_init(&codec->mutex); | ||
195 | |||
196 | codec->reg_cache = | ||
197 | kzalloc(sizeof(u16) * ARRAY_SIZE(ad1980_reg), GFP_KERNEL); | ||
198 | if (codec->reg_cache == NULL) { | ||
199 | ret = -ENOMEM; | ||
200 | goto cache_err; | ||
201 | } | ||
202 | memcpy(codec->reg_cache, ad1980_reg, sizeof(u16) * \ | ||
203 | ARRAY_SIZE(ad1980_reg)); | ||
204 | codec->reg_cache_size = sizeof(u16) * ARRAY_SIZE(ad1980_reg); | ||
205 | codec->reg_cache_step = 2; | ||
206 | codec->name = "AD1980"; | ||
207 | codec->owner = THIS_MODULE; | ||
208 | codec->dai = &ad1980_dai; | ||
209 | codec->num_dai = 1; | ||
210 | codec->write = ac97_write; | ||
211 | codec->read = ac97_read; | ||
212 | INIT_LIST_HEAD(&codec->dapm_widgets); | ||
213 | INIT_LIST_HEAD(&codec->dapm_paths); | ||
214 | |||
215 | ret = snd_soc_new_ac97_codec(codec, &soc_ac97_ops, 0); | 188 | ret = snd_soc_new_ac97_codec(codec, &soc_ac97_ops, 0); |
216 | if (ret < 0) { | 189 | if (ret < 0) { |
217 | printk(KERN_ERR "ad1980: failed to register AC97 codec\n"); | 190 | printk(KERN_ERR "ad1980: failed to register AC97 codec\n"); |
218 | goto codec_err; | 191 | return ret; |
219 | } | 192 | } |
220 | 193 | ||
221 | /* register pcms */ | ||
222 | ret = snd_soc_new_pcms(socdev, SNDRV_DEFAULT_IDX1, SNDRV_DEFAULT_STR1); | ||
223 | if (ret < 0) | ||
224 | goto pcm_err; | ||
225 | |||
226 | |||
227 | ret = ad1980_reset(codec, 0); | 194 | ret = ad1980_reset(codec, 0); |
228 | if (ret < 0) { | 195 | if (ret < 0) { |
229 | printk(KERN_ERR "Failed to reset AD1980: AC97 link error\n"); | 196 | printk(KERN_ERR "Failed to reset AD1980: AC97 link error\n"); |
@@ -262,41 +229,59 @@ static int ad1980_soc_probe(struct platform_device *pdev) | |||
262 | return 0; | 229 | return 0; |
263 | 230 | ||
264 | reset_err: | 231 | reset_err: |
265 | snd_soc_free_pcms(socdev); | ||
266 | |||
267 | pcm_err: | ||
268 | snd_soc_free_ac97_codec(codec); | 232 | snd_soc_free_ac97_codec(codec); |
269 | |||
270 | codec_err: | ||
271 | kfree(codec->reg_cache); | ||
272 | |||
273 | cache_err: | ||
274 | kfree(socdev->card->codec); | ||
275 | socdev->card->codec = NULL; | ||
276 | return ret; | 233 | return ret; |
277 | } | 234 | } |
278 | 235 | ||
279 | static int ad1980_soc_remove(struct platform_device *pdev) | 236 | static int ad1980_soc_remove(struct snd_soc_codec *codec) |
280 | { | 237 | { |
281 | struct snd_soc_device *socdev = platform_get_drvdata(pdev); | ||
282 | struct snd_soc_codec *codec = socdev->card->codec; | ||
283 | |||
284 | if (codec == NULL) | ||
285 | return 0; | ||
286 | |||
287 | snd_soc_dapm_free(socdev); | ||
288 | snd_soc_free_pcms(socdev); | ||
289 | snd_soc_free_ac97_codec(codec); | 238 | snd_soc_free_ac97_codec(codec); |
290 | kfree(codec->reg_cache); | ||
291 | kfree(codec); | ||
292 | return 0; | 239 | return 0; |
293 | } | 240 | } |
294 | 241 | ||
295 | struct snd_soc_codec_device soc_codec_dev_ad1980 = { | 242 | static struct snd_soc_codec_driver soc_codec_dev_ad1980 = { |
296 | .probe = ad1980_soc_probe, | 243 | .probe = ad1980_soc_probe, |
297 | .remove = ad1980_soc_remove, | 244 | .remove = ad1980_soc_remove, |
245 | .reg_cache_size = ARRAY_SIZE(ad1980_reg), | ||
246 | .reg_word_size = sizeof(u16), | ||
247 | .reg_cache_step = 2, | ||
248 | .write = ac97_write, | ||
249 | .read = ac97_read, | ||
298 | }; | 250 | }; |
299 | EXPORT_SYMBOL_GPL(soc_codec_dev_ad1980); | 251 | |
252 | static __devinit int ad1980_probe(struct platform_device *pdev) | ||
253 | { | ||
254 | return snd_soc_register_codec(&pdev->dev, | ||
255 | &soc_codec_dev_ad1980, &ad1980_dai, 1); | ||
256 | } | ||
257 | |||
258 | static int __devexit ad1980_remove(struct platform_device *pdev) | ||
259 | { | ||
260 | snd_soc_unregister_codec(&pdev->dev); | ||
261 | return 0; | ||
262 | } | ||
263 | |||
264 | static struct platform_driver ad1980_codec_driver = { | ||
265 | .driver = { | ||
266 | .name = "ad1980-codec", | ||
267 | .owner = THIS_MODULE, | ||
268 | }, | ||
269 | |||
270 | .probe = ad1980_probe, | ||
271 | .remove = __devexit_p(ad1980_remove), | ||
272 | }; | ||
273 | |||
274 | static int __init ad1980_init(void) | ||
275 | { | ||
276 | return platform_driver_register(&ad1980_codec_driver); | ||
277 | } | ||
278 | module_init(ad1980_init); | ||
279 | |||
280 | static void __exit ad1980_exit(void) | ||
281 | { | ||
282 | platform_driver_unregister(&ad1980_codec_driver); | ||
283 | } | ||
284 | module_exit(ad1980_exit); | ||
300 | 285 | ||
301 | MODULE_DESCRIPTION("ASoC ad1980 driver"); | 286 | MODULE_DESCRIPTION("ASoC ad1980 driver"); |
302 | MODULE_AUTHOR("Roy Huang, Cliff Cai"); | 287 | MODULE_AUTHOR("Roy Huang, Cliff Cai"); |
diff --git a/sound/soc/codecs/ad1980.h b/sound/soc/codecs/ad1980.h index db6c8500d66b..29b5a8750926 100644 --- a/sound/soc/codecs/ad1980.h +++ b/sound/soc/codecs/ad1980.h | |||
@@ -17,7 +17,4 @@ | |||
17 | #define PR5 0x2000 | 17 | #define PR5 0x2000 |
18 | #define PR6 0x4000 | 18 | #define PR6 0x4000 |
19 | 19 | ||
20 | extern struct snd_soc_dai ad1980_dai; | ||
21 | extern struct snd_soc_codec_device soc_codec_dev_ad1980; | ||
22 | |||
23 | #endif | 20 | #endif |
diff --git a/sound/soc/codecs/ad73311.c b/sound/soc/codecs/ad73311.c index 475807bea2c2..c53955fe17b6 100644 --- a/sound/soc/codecs/ad73311.c +++ b/sound/soc/codecs/ad73311.c | |||
@@ -23,8 +23,8 @@ | |||
23 | 23 | ||
24 | #include "ad73311.h" | 24 | #include "ad73311.h" |
25 | 25 | ||
26 | struct snd_soc_dai ad73311_dai = { | 26 | static struct snd_soc_dai_driver ad73311_dai = { |
27 | .name = "AD73311", | 27 | .name = "ad73311-hifi", |
28 | .playback = { | 28 | .playback = { |
29 | .stream_name = "Playback", | 29 | .stream_name = "Playback", |
30 | .channels_min = 1, | 30 | .channels_min = 1, |
@@ -38,68 +38,40 @@ struct snd_soc_dai ad73311_dai = { | |||
38 | .rates = SNDRV_PCM_RATE_8000, | 38 | .rates = SNDRV_PCM_RATE_8000, |
39 | .formats = SNDRV_PCM_FMTBIT_S16_LE, }, | 39 | .formats = SNDRV_PCM_FMTBIT_S16_LE, }, |
40 | }; | 40 | }; |
41 | EXPORT_SYMBOL_GPL(ad73311_dai); | ||
42 | 41 | ||
43 | static int ad73311_soc_probe(struct platform_device *pdev) | 42 | static struct snd_soc_codec_driver soc_codec_dev_ad73311; |
44 | { | ||
45 | struct snd_soc_device *socdev = platform_get_drvdata(pdev); | ||
46 | struct snd_soc_codec *codec; | ||
47 | int ret = 0; | ||
48 | |||
49 | codec = kzalloc(sizeof(struct snd_soc_codec), GFP_KERNEL); | ||
50 | if (codec == NULL) | ||
51 | return -ENOMEM; | ||
52 | mutex_init(&codec->mutex); | ||
53 | codec->name = "AD73311"; | ||
54 | codec->owner = THIS_MODULE; | ||
55 | codec->dai = &ad73311_dai; | ||
56 | codec->num_dai = 1; | ||
57 | socdev->card->codec = codec; | ||
58 | INIT_LIST_HEAD(&codec->dapm_widgets); | ||
59 | INIT_LIST_HEAD(&codec->dapm_paths); | ||
60 | |||
61 | /* register pcms */ | ||
62 | ret = snd_soc_new_pcms(socdev, SNDRV_DEFAULT_IDX1, SNDRV_DEFAULT_STR1); | ||
63 | if (ret < 0) { | ||
64 | printk(KERN_ERR "ad73311: failed to create pcms\n"); | ||
65 | goto pcm_err; | ||
66 | } | ||
67 | |||
68 | return ret; | ||
69 | 43 | ||
70 | pcm_err: | 44 | static int ad73311_probe(struct platform_device *pdev) |
71 | kfree(socdev->card->codec); | 45 | { |
72 | socdev->card->codec = NULL; | 46 | return snd_soc_register_codec(&pdev->dev, |
73 | return ret; | 47 | &soc_codec_dev_ad73311, &ad73311_dai, 1); |
74 | } | 48 | } |
75 | 49 | ||
76 | static int ad73311_soc_remove(struct platform_device *pdev) | 50 | static int ad73311_remove(struct platform_device *pdev) |
77 | { | 51 | { |
78 | struct snd_soc_device *socdev = platform_get_drvdata(pdev); | 52 | snd_soc_unregister_codec(&pdev->dev); |
79 | struct snd_soc_codec *codec = socdev->card->codec; | ||
80 | |||
81 | if (codec == NULL) | ||
82 | return 0; | ||
83 | snd_soc_free_pcms(socdev); | ||
84 | kfree(codec); | ||
85 | return 0; | 53 | return 0; |
86 | } | 54 | } |
87 | 55 | ||
88 | struct snd_soc_codec_device soc_codec_dev_ad73311 = { | 56 | static struct platform_driver ad73311_codec_driver = { |
89 | .probe = ad73311_soc_probe, | 57 | .driver = { |
90 | .remove = ad73311_soc_remove, | 58 | .name = "ad73311-codec", |
59 | .owner = THIS_MODULE, | ||
60 | }, | ||
61 | |||
62 | .probe = ad73311_probe, | ||
63 | .remove = __devexit_p(ad73311_remove), | ||
91 | }; | 64 | }; |
92 | EXPORT_SYMBOL_GPL(soc_codec_dev_ad73311); | ||
93 | 65 | ||
94 | static int __init ad73311_init(void) | 66 | static int __init ad73311_init(void) |
95 | { | 67 | { |
96 | return snd_soc_register_dai(&ad73311_dai); | 68 | return platform_driver_register(&ad73311_codec_driver); |
97 | } | 69 | } |
98 | module_init(ad73311_init); | 70 | module_init(ad73311_init); |
99 | 71 | ||
100 | static void __exit ad73311_exit(void) | 72 | static void __exit ad73311_exit(void) |
101 | { | 73 | { |
102 | snd_soc_unregister_dai(&ad73311_dai); | 74 | platform_driver_unregister(&ad73311_codec_driver); |
103 | } | 75 | } |
104 | module_exit(ad73311_exit); | 76 | module_exit(ad73311_exit); |
105 | 77 | ||
diff --git a/sound/soc/codecs/ad73311.h b/sound/soc/codecs/ad73311.h index 569573d2d4d7..4b353eefc0bf 100644 --- a/sound/soc/codecs/ad73311.h +++ b/sound/soc/codecs/ad73311.h | |||
@@ -85,6 +85,4 @@ | |||
85 | #define REGF_INV (1 << 6) | 85 | #define REGF_INV (1 << 6) |
86 | #define REGF_ALB (1 << 7) | 86 | #define REGF_ALB (1 << 7) |
87 | 87 | ||
88 | extern struct snd_soc_dai ad73311_dai; | ||
89 | extern struct snd_soc_codec_device soc_codec_dev_ad73311; | ||
90 | #endif | 88 | #endif |
diff --git a/sound/soc/codecs/ads117x.c b/sound/soc/codecs/ads117x.c index f8e75edb27b7..8402854ec15e 100644 --- a/sound/soc/codecs/ads117x.c +++ b/sound/soc/codecs/ads117x.c | |||
@@ -19,16 +19,12 @@ | |||
19 | #include <sound/initval.h> | 19 | #include <sound/initval.h> |
20 | #include <sound/soc.h> | 20 | #include <sound/soc.h> |
21 | 21 | ||
22 | #include "ads117x.h" | ||
23 | |||
24 | #define ADS117X_RATES (SNDRV_PCM_RATE_8000_48000) | 22 | #define ADS117X_RATES (SNDRV_PCM_RATE_8000_48000) |
25 | |||
26 | #define ADS117X_FORMATS (SNDRV_PCM_FMTBIT_S16_LE) | 23 | #define ADS117X_FORMATS (SNDRV_PCM_FMTBIT_S16_LE) |
27 | 24 | ||
28 | struct snd_soc_dai ads117x_dai = { | 25 | static struct snd_soc_dai_driver ads117x_dai = { |
29 | /* ADC */ | 26 | /* ADC */ |
30 | .name = "ADS117X ADC", | 27 | .name = "ads117x-hifi", |
31 | .id = 1, | ||
32 | .capture = { | 28 | .capture = { |
33 | .stream_name = "Capture", | 29 | .stream_name = "Capture", |
34 | .channels_min = 1, | 30 | .channels_min = 1, |
@@ -36,75 +32,29 @@ struct snd_soc_dai ads117x_dai = { | |||
36 | .rates = ADS117X_RATES, | 32 | .rates = ADS117X_RATES, |
37 | .formats = ADS117X_FORMATS,}, | 33 | .formats = ADS117X_FORMATS,}, |
38 | }; | 34 | }; |
39 | EXPORT_SYMBOL_GPL(ads117x_dai); | ||
40 | |||
41 | static int ads117x_probe(struct platform_device *pdev) | ||
42 | { | ||
43 | struct snd_soc_device *socdev = platform_get_drvdata(pdev); | ||
44 | struct snd_soc_codec *codec; | ||
45 | int ret; | ||
46 | |||
47 | codec = kzalloc(sizeof(struct snd_soc_codec), GFP_KERNEL); | ||
48 | if (codec == NULL) | ||
49 | return -ENOMEM; | ||
50 | 35 | ||
51 | socdev->card->codec = codec; | 36 | static struct snd_soc_codec_driver soc_codec_dev_ads117x; |
52 | mutex_init(&codec->mutex); | ||
53 | INIT_LIST_HEAD(&codec->dapm_widgets); | ||
54 | INIT_LIST_HEAD(&codec->dapm_paths); | ||
55 | codec->name = "ADS117X"; | ||
56 | codec->owner = THIS_MODULE; | ||
57 | codec->dai = &ads117x_dai; | ||
58 | codec->num_dai = 1; | ||
59 | |||
60 | /* register pcms */ | ||
61 | ret = snd_soc_new_pcms(socdev, SNDRV_DEFAULT_IDX1, SNDRV_DEFAULT_STR1); | ||
62 | if (ret < 0) { | ||
63 | printk(KERN_ERR "ads117x: failed to create pcms\n"); | ||
64 | kfree(codec); | ||
65 | return ret; | ||
66 | } | ||
67 | |||
68 | return 0; | ||
69 | } | ||
70 | |||
71 | static int ads117x_remove(struct platform_device *pdev) | ||
72 | { | ||
73 | struct snd_soc_device *socdev = platform_get_drvdata(pdev); | ||
74 | struct snd_soc_codec *codec = socdev->card->codec; | ||
75 | |||
76 | snd_soc_free_pcms(socdev); | ||
77 | kfree(codec); | ||
78 | |||
79 | return 0; | ||
80 | } | ||
81 | |||
82 | struct snd_soc_codec_device soc_codec_dev_ads117x = { | ||
83 | .probe = ads117x_probe, | ||
84 | .remove = ads117x_remove, | ||
85 | }; | ||
86 | EXPORT_SYMBOL_GPL(soc_codec_dev_ads117x); | ||
87 | 37 | ||
88 | static __devinit int ads117x_platform_probe(struct platform_device *pdev) | 38 | static __devinit int ads117x_probe(struct platform_device *pdev) |
89 | { | 39 | { |
90 | ads117x_dai.dev = &pdev->dev; | 40 | return snd_soc_register_codec(&pdev->dev, |
91 | return snd_soc_register_dai(&ads117x_dai); | 41 | &soc_codec_dev_ads117x, &ads117x_dai, 1); |
92 | } | 42 | } |
93 | 43 | ||
94 | static int __devexit ads117x_platform_remove(struct platform_device *pdev) | 44 | static int __devexit ads117x_remove(struct platform_device *pdev) |
95 | { | 45 | { |
96 | snd_soc_unregister_dai(&ads117x_dai); | 46 | snd_soc_unregister_codec(&pdev->dev); |
97 | return 0; | 47 | return 0; |
98 | } | 48 | } |
99 | 49 | ||
100 | static struct platform_driver ads117x_codec_driver = { | 50 | static struct platform_driver ads117x_codec_driver = { |
101 | .driver = { | 51 | .driver = { |
102 | .name = "ads117x", | 52 | .name = "ads117x-codec", |
103 | .owner = THIS_MODULE, | 53 | .owner = THIS_MODULE, |
104 | }, | 54 | }, |
105 | 55 | ||
106 | .probe = ads117x_platform_probe, | 56 | .probe = ads117x_probe, |
107 | .remove = __devexit_p(ads117x_platform_remove), | 57 | .remove = __devexit_p(ads117x_remove), |
108 | }; | 58 | }; |
109 | 59 | ||
110 | static int __init ads117x_init(void) | 60 | static int __init ads117x_init(void) |
diff --git a/sound/soc/codecs/ads117x.h b/sound/soc/codecs/ads117x.h index dbcf50ec9bd1..3ce028614002 100644 --- a/sound/soc/codecs/ads117x.h +++ b/sound/soc/codecs/ads117x.h | |||
@@ -9,5 +9,5 @@ | |||
9 | * Free Software Foundation; either version 2 of the License, or (at your | 9 | * Free Software Foundation; either version 2 of the License, or (at your |
10 | * option) any later version. | 10 | * option) any later version. |
11 | */ | 11 | */ |
12 | extern struct snd_soc_dai ads117x_dai; | 12 | extern struct snd_soc_dai_driver ads117x_dai; |
13 | extern struct snd_soc_codec_device soc_codec_dev_ads117x; | 13 | extern struct snd_soc_codec_driver soc_codec_dev_ads117x; |
diff --git a/sound/soc/codecs/ak4104.c b/sound/soc/codecs/ak4104.c index 192aebda3029..c27f8f59dc66 100644 --- a/sound/soc/codecs/ak4104.c +++ b/sound/soc/codecs/ak4104.c | |||
@@ -17,8 +17,6 @@ | |||
17 | #include <linux/spi/spi.h> | 17 | #include <linux/spi/spi.h> |
18 | #include <sound/asoundef.h> | 18 | #include <sound/asoundef.h> |
19 | 19 | ||
20 | #include "ak4104.h" | ||
21 | |||
22 | /* AK4104 registers addresses */ | 20 | /* AK4104 registers addresses */ |
23 | #define AK4104_REG_CONTROL1 0x00 | 21 | #define AK4104_REG_CONTROL1 0x00 |
24 | #define AK4104_REG_RESERVED 0x01 | 22 | #define AK4104_REG_RESERVED 0x01 |
@@ -45,11 +43,11 @@ | |||
45 | #define AK4104_TX_TXE (1 << 0) | 43 | #define AK4104_TX_TXE (1 << 0) |
46 | #define AK4104_TX_V (1 << 1) | 44 | #define AK4104_TX_V (1 << 1) |
47 | 45 | ||
48 | #define DRV_NAME "ak4104" | 46 | #define DRV_NAME "ak4104-codec" |
49 | 47 | ||
50 | struct ak4104_private { | 48 | struct ak4104_private { |
51 | struct snd_soc_codec codec; | 49 | enum snd_soc_control_type control_type; |
52 | u8 reg_cache[AK4104_NUM_REGS]; | 50 | void *control_data; |
53 | }; | 51 | }; |
54 | 52 | ||
55 | static int ak4104_fill_cache(struct snd_soc_codec *codec) | 53 | static int ak4104_fill_cache(struct snd_soc_codec *codec) |
@@ -58,7 +56,7 @@ static int ak4104_fill_cache(struct snd_soc_codec *codec) | |||
58 | u8 *reg_cache = codec->reg_cache; | 56 | u8 *reg_cache = codec->reg_cache; |
59 | struct spi_device *spi = codec->control_data; | 57 | struct spi_device *spi = codec->control_data; |
60 | 58 | ||
61 | for (i = 0; i < codec->reg_cache_size; i++) { | 59 | for (i = 0; i < codec->driver->reg_cache_size; i++) { |
62 | int ret = spi_w8r8(spi, i | AK4104_READ); | 60 | int ret = spi_w8r8(spi, i | AK4104_READ); |
63 | if (ret < 0) { | 61 | if (ret < 0) { |
64 | dev_err(&spi->dev, "SPI write failure\n"); | 62 | dev_err(&spi->dev, "SPI write failure\n"); |
@@ -76,7 +74,7 @@ static unsigned int ak4104_read_reg_cache(struct snd_soc_codec *codec, | |||
76 | { | 74 | { |
77 | u8 *reg_cache = codec->reg_cache; | 75 | u8 *reg_cache = codec->reg_cache; |
78 | 76 | ||
79 | if (reg >= codec->reg_cache_size) | 77 | if (reg >= codec->driver->reg_cache_size) |
80 | return -EINVAL; | 78 | return -EINVAL; |
81 | 79 | ||
82 | return reg_cache[reg]; | 80 | return reg_cache[reg]; |
@@ -88,7 +86,7 @@ static int ak4104_spi_write(struct snd_soc_codec *codec, unsigned int reg, | |||
88 | u8 *cache = codec->reg_cache; | 86 | u8 *cache = codec->reg_cache; |
89 | struct spi_device *spi = codec->control_data; | 87 | struct spi_device *spi = codec->control_data; |
90 | 88 | ||
91 | if (reg >= codec->reg_cache_size) | 89 | if (reg >= codec->driver->reg_cache_size) |
92 | return -EINVAL; | 90 | return -EINVAL; |
93 | 91 | ||
94 | /* only write to the hardware if value has changed */ | 92 | /* only write to the hardware if value has changed */ |
@@ -145,8 +143,7 @@ static int ak4104_hw_params(struct snd_pcm_substream *substream, | |||
145 | struct snd_soc_dai *dai) | 143 | struct snd_soc_dai *dai) |
146 | { | 144 | { |
147 | struct snd_soc_pcm_runtime *rtd = substream->private_data; | 145 | struct snd_soc_pcm_runtime *rtd = substream->private_data; |
148 | struct snd_soc_device *socdev = rtd->socdev; | 146 | struct snd_soc_codec *codec = rtd->codec; |
149 | struct snd_soc_codec *codec = socdev->card->codec; | ||
150 | int val = 0; | 147 | int val = 0; |
151 | 148 | ||
152 | /* set the IEC958 bits: consumer mode, no copyright bit */ | 149 | /* set the IEC958 bits: consumer mode, no copyright bit */ |
@@ -178,8 +175,8 @@ static struct snd_soc_dai_ops ak4101_dai_ops = { | |||
178 | .set_fmt = ak4104_set_dai_fmt, | 175 | .set_fmt = ak4104_set_dai_fmt, |
179 | }; | 176 | }; |
180 | 177 | ||
181 | struct snd_soc_dai ak4104_dai = { | 178 | static struct snd_soc_dai_driver ak4104_dai = { |
182 | .name = DRV_NAME, | 179 | .name = "ak4104-hifi", |
183 | .playback = { | 180 | .playback = { |
184 | .stream_name = "Playback", | 181 | .stream_name = "Playback", |
185 | .channels_min = 2, | 182 | .channels_min = 2, |
@@ -192,45 +189,17 @@ struct snd_soc_dai ak4104_dai = { | |||
192 | .ops = &ak4101_dai_ops, | 189 | .ops = &ak4101_dai_ops, |
193 | }; | 190 | }; |
194 | 191 | ||
195 | static struct snd_soc_codec *ak4104_codec; | 192 | static int ak4104_probe(struct snd_soc_codec *codec) |
196 | |||
197 | static int ak4104_spi_probe(struct spi_device *spi) | ||
198 | { | 193 | { |
199 | struct snd_soc_codec *codec; | 194 | struct ak4104_private *ak4104 = snd_soc_codec_get_drvdata(codec); |
200 | struct ak4104_private *ak4104; | ||
201 | int ret, val; | 195 | int ret, val; |
202 | 196 | ||
203 | spi->bits_per_word = 8; | 197 | codec->control_data = ak4104->control_data; |
204 | spi->mode = SPI_MODE_0; | ||
205 | ret = spi_setup(spi); | ||
206 | if (ret < 0) | ||
207 | return ret; | ||
208 | |||
209 | ak4104 = kzalloc(sizeof(struct ak4104_private), GFP_KERNEL); | ||
210 | if (!ak4104) { | ||
211 | dev_err(&spi->dev, "could not allocate codec\n"); | ||
212 | return -ENOMEM; | ||
213 | } | ||
214 | |||
215 | codec = &ak4104->codec; | ||
216 | mutex_init(&codec->mutex); | ||
217 | INIT_LIST_HEAD(&codec->dapm_widgets); | ||
218 | INIT_LIST_HEAD(&codec->dapm_paths); | ||
219 | |||
220 | codec->dev = &spi->dev; | ||
221 | codec->name = DRV_NAME; | ||
222 | codec->owner = THIS_MODULE; | ||
223 | codec->dai = &ak4104_dai; | ||
224 | codec->num_dai = 1; | ||
225 | snd_soc_codec_set_drvdata(codec, ak4104); | ||
226 | codec->control_data = spi; | ||
227 | codec->reg_cache = ak4104->reg_cache; | ||
228 | codec->reg_cache_size = AK4104_NUM_REGS; | ||
229 | 198 | ||
230 | /* read all regs and fill the cache */ | 199 | /* read all regs and fill the cache */ |
231 | ret = ak4104_fill_cache(codec); | 200 | ret = ak4104_fill_cache(codec); |
232 | if (ret < 0) { | 201 | if (ret < 0) { |
233 | dev_err(&spi->dev, "failed to fill register cache\n"); | 202 | dev_err(codec->dev, "failed to fill register cache\n"); |
234 | return ret; | 203 | return ret; |
235 | } | 204 | } |
236 | 205 | ||
@@ -238,93 +207,81 @@ static int ak4104_spi_probe(struct spi_device *spi) | |||
238 | * should contain 0x5b. Not a good way to verify the presence of | 207 | * should contain 0x5b. Not a good way to verify the presence of |
239 | * the device, but there is no hardware ID register. */ | 208 | * the device, but there is no hardware ID register. */ |
240 | if (ak4104_read_reg_cache(codec, AK4104_REG_RESERVED) != | 209 | if (ak4104_read_reg_cache(codec, AK4104_REG_RESERVED) != |
241 | AK4104_RESERVED_VAL) { | 210 | AK4104_RESERVED_VAL) |
242 | ret = -ENODEV; | 211 | return -ENODEV; |
243 | goto error_free_codec; | ||
244 | } | ||
245 | 212 | ||
246 | /* set power-up and non-reset bits */ | 213 | /* set power-up and non-reset bits */ |
247 | val = ak4104_read_reg_cache(codec, AK4104_REG_CONTROL1); | 214 | val = ak4104_read_reg_cache(codec, AK4104_REG_CONTROL1); |
248 | val |= AK4104_CONTROL1_PW | AK4104_CONTROL1_RSTN; | 215 | val |= AK4104_CONTROL1_PW | AK4104_CONTROL1_RSTN; |
249 | ret = ak4104_spi_write(codec, AK4104_REG_CONTROL1, val); | 216 | ret = ak4104_spi_write(codec, AK4104_REG_CONTROL1, val); |
250 | if (ret < 0) | 217 | if (ret < 0) |
251 | goto error_free_codec; | 218 | return ret; |
252 | 219 | ||
253 | /* enable transmitter */ | 220 | /* enable transmitter */ |
254 | val = ak4104_read_reg_cache(codec, AK4104_REG_TX); | 221 | val = ak4104_read_reg_cache(codec, AK4104_REG_TX); |
255 | val |= AK4104_TX_TXE; | 222 | val |= AK4104_TX_TXE; |
256 | ret = ak4104_spi_write(codec, AK4104_REG_TX, val); | 223 | ret = ak4104_spi_write(codec, AK4104_REG_TX, val); |
257 | if (ret < 0) | 224 | if (ret < 0) |
258 | goto error_free_codec; | 225 | return ret; |
259 | |||
260 | ak4104_codec = codec; | ||
261 | ret = snd_soc_register_dai(&ak4104_dai); | ||
262 | if (ret < 0) { | ||
263 | dev_err(&spi->dev, "failed to register DAI\n"); | ||
264 | goto error_free_codec; | ||
265 | } | ||
266 | 226 | ||
267 | spi_set_drvdata(spi, ak4104); | 227 | dev_info(codec->dev, "SPI device initialized\n"); |
268 | dev_info(&spi->dev, "SPI device initialized\n"); | ||
269 | return 0; | 228 | return 0; |
270 | |||
271 | error_free_codec: | ||
272 | kfree(ak4104); | ||
273 | ak4104_dai.dev = NULL; | ||
274 | return ret; | ||
275 | } | 229 | } |
276 | 230 | ||
277 | static int __devexit ak4104_spi_remove(struct spi_device *spi) | 231 | static int ak4104_remove(struct snd_soc_codec *codec) |
278 | { | 232 | { |
279 | int ret, val; | 233 | int val, ret; |
280 | struct ak4104_private *ak4104 = spi_get_drvdata(spi); | ||
281 | 234 | ||
282 | val = ak4104_read_reg_cache(&ak4104->codec, AK4104_REG_CONTROL1); | 235 | val = ak4104_read_reg_cache(codec, AK4104_REG_CONTROL1); |
283 | if (val < 0) | 236 | if (val < 0) |
284 | return val; | 237 | return val; |
285 | 238 | ||
286 | /* clear power-up and non-reset bits */ | 239 | /* clear power-up and non-reset bits */ |
287 | val &= ~(AK4104_CONTROL1_PW | AK4104_CONTROL1_RSTN); | 240 | val &= ~(AK4104_CONTROL1_PW | AK4104_CONTROL1_RSTN); |
288 | ret = ak4104_spi_write(&ak4104->codec, AK4104_REG_CONTROL1, val); | 241 | ret = ak4104_spi_write(codec, AK4104_REG_CONTROL1, val); |
289 | if (ret < 0) | ||
290 | return ret; | ||
291 | 242 | ||
292 | ak4104_codec = NULL; | 243 | return ret; |
293 | kfree(ak4104); | ||
294 | return 0; | ||
295 | } | 244 | } |
296 | 245 | ||
297 | static int ak4104_probe(struct platform_device *pdev) | 246 | static struct snd_soc_codec_driver soc_codec_device_ak4104 = { |
247 | .probe = ak4104_probe, | ||
248 | .remove = ak4104_remove, | ||
249 | .reg_cache_size = AK4104_NUM_REGS, | ||
250 | .reg_word_size = sizeof(u16), | ||
251 | }; | ||
252 | |||
253 | static int ak4104_spi_probe(struct spi_device *spi) | ||
298 | { | 254 | { |
299 | struct snd_soc_device *socdev = platform_get_drvdata(pdev); | 255 | struct ak4104_private *ak4104; |
300 | struct snd_soc_codec *codec = ak4104_codec; | ||
301 | int ret; | 256 | int ret; |
302 | 257 | ||
303 | /* Connect the codec to the socdev. snd_soc_new_pcms() needs this. */ | 258 | spi->bits_per_word = 8; |
304 | socdev->card->codec = codec; | 259 | spi->mode = SPI_MODE_0; |
305 | 260 | ret = spi_setup(spi); | |
306 | /* Register PCMs */ | 261 | if (ret < 0) |
307 | ret = snd_soc_new_pcms(socdev, SNDRV_DEFAULT_IDX1, SNDRV_DEFAULT_STR1); | ||
308 | if (ret < 0) { | ||
309 | dev_err(codec->dev, "failed to create pcms\n"); | ||
310 | return ret; | 262 | return ret; |
311 | } | ||
312 | 263 | ||
313 | return 0; | 264 | ak4104 = kzalloc(sizeof(struct ak4104_private), GFP_KERNEL); |
265 | if (ak4104 == NULL) | ||
266 | return -ENOMEM; | ||
267 | |||
268 | ak4104->control_data = spi; | ||
269 | ak4104->control_type = SND_SOC_SPI; | ||
270 | spi_set_drvdata(spi, ak4104); | ||
271 | |||
272 | ret = snd_soc_register_codec(&spi->dev, | ||
273 | &soc_codec_device_ak4104, &ak4104_dai, 1); | ||
274 | if (ret < 0) | ||
275 | kfree(ak4104); | ||
276 | return ret; | ||
314 | } | 277 | } |
315 | 278 | ||
316 | static int ak4104_remove(struct platform_device *pdev) | 279 | static int __devexit ak4104_spi_remove(struct spi_device *spi) |
317 | { | 280 | { |
318 | struct snd_soc_device *socdev = platform_get_drvdata(pdev); | 281 | snd_soc_unregister_codec(&spi->dev); |
319 | snd_soc_free_pcms(socdev); | 282 | kfree(spi_get_drvdata(spi)); |
320 | return 0; | 283 | return 0; |
321 | }; | 284 | } |
322 | |||
323 | struct snd_soc_codec_device soc_codec_device_ak4104 = { | ||
324 | .probe = ak4104_probe, | ||
325 | .remove = ak4104_remove | ||
326 | }; | ||
327 | EXPORT_SYMBOL_GPL(soc_codec_device_ak4104); | ||
328 | 285 | ||
329 | static struct spi_driver ak4104_spi_driver = { | 286 | static struct spi_driver ak4104_spi_driver = { |
330 | .driver = { | 287 | .driver = { |
diff --git a/sound/soc/codecs/ak4104.h b/sound/soc/codecs/ak4104.h deleted file mode 100644 index eb88fe7e4def..000000000000 --- a/sound/soc/codecs/ak4104.h +++ /dev/null | |||
@@ -1,7 +0,0 @@ | |||
1 | #ifndef _AK4104_H | ||
2 | #define _AK4104_H | ||
3 | |||
4 | extern struct snd_soc_dai ak4104_dai; | ||
5 | extern struct snd_soc_codec_device soc_codec_device_ak4104; | ||
6 | |||
7 | #endif | ||
diff --git a/sound/soc/codecs/ak4535.c b/sound/soc/codecs/ak4535.c index d4253675b2d3..cd88c8f32a38 100644 --- a/sound/soc/codecs/ak4535.c +++ b/sound/soc/codecs/ak4535.c | |||
@@ -31,11 +31,11 @@ | |||
31 | 31 | ||
32 | #define AK4535_VERSION "0.3" | 32 | #define AK4535_VERSION "0.3" |
33 | 33 | ||
34 | struct snd_soc_codec_device soc_codec_dev_ak4535; | ||
35 | |||
36 | /* codec private data */ | 34 | /* codec private data */ |
37 | struct ak4535_priv { | 35 | struct ak4535_priv { |
38 | unsigned int sysclk; | 36 | unsigned int sysclk; |
37 | enum snd_soc_control_type control_type; | ||
38 | void *control_data; | ||
39 | }; | 39 | }; |
40 | 40 | ||
41 | /* | 41 | /* |
@@ -313,8 +313,7 @@ static int ak4535_hw_params(struct snd_pcm_substream *substream, | |||
313 | struct snd_soc_dai *dai) | 313 | struct snd_soc_dai *dai) |
314 | { | 314 | { |
315 | struct snd_soc_pcm_runtime *rtd = substream->private_data; | 315 | struct snd_soc_pcm_runtime *rtd = substream->private_data; |
316 | struct snd_soc_device *socdev = rtd->socdev; | 316 | struct snd_soc_codec *codec = rtd->codec; |
317 | struct snd_soc_codec *codec = socdev->card->codec; | ||
318 | struct ak4535_priv *ak4535 = snd_soc_codec_get_drvdata(codec); | 317 | struct ak4535_priv *ak4535 = snd_soc_codec_get_drvdata(codec); |
319 | u8 mode2 = ak4535_read_reg_cache(codec, AK4535_MODE2) & ~(0x3 << 5); | 318 | u8 mode2 = ak4535_read_reg_cache(codec, AK4535_MODE2) & ~(0x3 << 5); |
320 | int rate = params_rate(params), fs = 256; | 319 | int rate = params_rate(params), fs = 256; |
@@ -378,14 +377,16 @@ static int ak4535_mute(struct snd_soc_dai *dai, int mute) | |||
378 | static int ak4535_set_bias_level(struct snd_soc_codec *codec, | 377 | static int ak4535_set_bias_level(struct snd_soc_codec *codec, |
379 | enum snd_soc_bias_level level) | 378 | enum snd_soc_bias_level level) |
380 | { | 379 | { |
381 | u16 i; | 380 | u16 i, mute_reg; |
382 | 381 | ||
383 | switch (level) { | 382 | switch (level) { |
384 | case SND_SOC_BIAS_ON: | 383 | case SND_SOC_BIAS_ON: |
385 | ak4535_mute(codec->dai, 0); | 384 | mute_reg = ak4535_read_reg_cache(codec, AK4535_DAC) & 0xffdf; |
385 | ak4535_write(codec, AK4535_DAC, mute_reg); | ||
386 | break; | 386 | break; |
387 | case SND_SOC_BIAS_PREPARE: | 387 | case SND_SOC_BIAS_PREPARE: |
388 | ak4535_mute(codec->dai, 1); | 388 | mute_reg = ak4535_read_reg_cache(codec, AK4535_DAC) & 0xffdf; |
389 | ak4535_write(codec, AK4535_DAC, mute_reg | 0x20); | ||
389 | break; | 390 | break; |
390 | case SND_SOC_BIAS_STANDBY: | 391 | case SND_SOC_BIAS_STANDBY: |
391 | i = ak4535_read_reg_cache(codec, AK4535_PM1); | 392 | i = ak4535_read_reg_cache(codec, AK4535_PM1); |
@@ -413,8 +414,8 @@ static struct snd_soc_dai_ops ak4535_dai_ops = { | |||
413 | .set_sysclk = ak4535_set_dai_sysclk, | 414 | .set_sysclk = ak4535_set_dai_sysclk, |
414 | }; | 415 | }; |
415 | 416 | ||
416 | struct snd_soc_dai ak4535_dai = { | 417 | static struct snd_soc_dai_driver ak4535_dai = { |
417 | .name = "AK4535", | 418 | .name = "ak4535-hifi", |
418 | .playback = { | 419 | .playback = { |
419 | .stream_name = "Playback", | 420 | .stream_name = "Playback", |
420 | .channels_min = 1, | 421 | .channels_min = 1, |
@@ -429,54 +430,27 @@ struct snd_soc_dai ak4535_dai = { | |||
429 | .formats = SNDRV_PCM_FMTBIT_S16_LE,}, | 430 | .formats = SNDRV_PCM_FMTBIT_S16_LE,}, |
430 | .ops = &ak4535_dai_ops, | 431 | .ops = &ak4535_dai_ops, |
431 | }; | 432 | }; |
432 | EXPORT_SYMBOL_GPL(ak4535_dai); | ||
433 | 433 | ||
434 | static int ak4535_suspend(struct platform_device *pdev, pm_message_t state) | 434 | static int ak4535_suspend(struct snd_soc_codec *codec, pm_message_t state) |
435 | { | 435 | { |
436 | struct snd_soc_device *socdev = platform_get_drvdata(pdev); | ||
437 | struct snd_soc_codec *codec = socdev->card->codec; | ||
438 | |||
439 | ak4535_set_bias_level(codec, SND_SOC_BIAS_OFF); | 436 | ak4535_set_bias_level(codec, SND_SOC_BIAS_OFF); |
440 | return 0; | 437 | return 0; |
441 | } | 438 | } |
442 | 439 | ||
443 | static int ak4535_resume(struct platform_device *pdev) | 440 | static int ak4535_resume(struct snd_soc_codec *codec) |
444 | { | 441 | { |
445 | struct snd_soc_device *socdev = platform_get_drvdata(pdev); | ||
446 | struct snd_soc_codec *codec = socdev->card->codec; | ||
447 | ak4535_sync(codec); | 442 | ak4535_sync(codec); |
448 | ak4535_set_bias_level(codec, SND_SOC_BIAS_STANDBY); | 443 | ak4535_set_bias_level(codec, SND_SOC_BIAS_STANDBY); |
449 | return 0; | 444 | return 0; |
450 | } | 445 | } |
451 | 446 | ||
452 | /* | 447 | static int ak4535_probe(struct snd_soc_codec *codec) |
453 | * initialise the AK4535 driver | ||
454 | * register the mixer and dsp interfaces with the kernel | ||
455 | */ | ||
456 | static int ak4535_init(struct snd_soc_device *socdev) | ||
457 | { | 448 | { |
458 | struct snd_soc_codec *codec = socdev->card->codec; | 449 | struct ak4535_priv *ak4535 = snd_soc_codec_get_drvdata(codec); |
459 | int ret = 0; | ||
460 | 450 | ||
461 | codec->name = "AK4535"; | 451 | printk(KERN_INFO "AK4535 Audio Codec %s", AK4535_VERSION); |
462 | codec->owner = THIS_MODULE; | ||
463 | codec->read = ak4535_read_reg_cache; | ||
464 | codec->write = ak4535_write; | ||
465 | codec->set_bias_level = ak4535_set_bias_level; | ||
466 | codec->dai = &ak4535_dai; | ||
467 | codec->num_dai = 1; | ||
468 | codec->reg_cache_size = ARRAY_SIZE(ak4535_reg); | ||
469 | codec->reg_cache = kmemdup(ak4535_reg, sizeof(ak4535_reg), GFP_KERNEL); | ||
470 | |||
471 | if (codec->reg_cache == NULL) | ||
472 | return -ENOMEM; | ||
473 | 452 | ||
474 | /* register pcms */ | 453 | codec->control_data = ak4535->control_data; |
475 | ret = snd_soc_new_pcms(socdev, SNDRV_DEFAULT_IDX1, SNDRV_DEFAULT_STR1); | ||
476 | if (ret < 0) { | ||
477 | printk(KERN_ERR "ak4535: failed to create pcms\n"); | ||
478 | goto pcm_err; | ||
479 | } | ||
480 | 454 | ||
481 | /* power on device */ | 455 | /* power on device */ |
482 | ak4535_set_bias_level(codec, SND_SOC_BIAS_STANDBY); | 456 | ak4535_set_bias_level(codec, SND_SOC_BIAS_STANDBY); |
@@ -485,39 +459,55 @@ static int ak4535_init(struct snd_soc_device *socdev) | |||
485 | ARRAY_SIZE(ak4535_snd_controls)); | 459 | ARRAY_SIZE(ak4535_snd_controls)); |
486 | ak4535_add_widgets(codec); | 460 | ak4535_add_widgets(codec); |
487 | 461 | ||
488 | return ret; | 462 | return 0; |
489 | 463 | } | |
490 | pcm_err: | ||
491 | kfree(codec->reg_cache); | ||
492 | 464 | ||
493 | return ret; | 465 | /* power down chip */ |
466 | static int ak4535_remove(struct snd_soc_codec *codec) | ||
467 | { | ||
468 | ak4535_set_bias_level(codec, SND_SOC_BIAS_OFF); | ||
469 | return 0; | ||
494 | } | 470 | } |
495 | 471 | ||
496 | static struct snd_soc_device *ak4535_socdev; | 472 | static struct snd_soc_codec_driver soc_codec_dev_ak4535 = { |
473 | .probe = ak4535_probe, | ||
474 | .remove = ak4535_remove, | ||
475 | .suspend = ak4535_suspend, | ||
476 | .resume = ak4535_resume, | ||
477 | .read = ak4535_read_reg_cache, | ||
478 | .write = ak4535_write, | ||
479 | .set_bias_level = ak4535_set_bias_level, | ||
480 | .reg_cache_size = ARRAY_SIZE(ak4535_reg), | ||
481 | .reg_word_size = sizeof(u8), | ||
482 | .reg_cache_default = ak4535_reg, | ||
483 | }; | ||
497 | 484 | ||
498 | #if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE) | 485 | #if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE) |
499 | 486 | static __devinit int ak4535_i2c_probe(struct i2c_client *i2c, | |
500 | static int ak4535_i2c_probe(struct i2c_client *i2c, | 487 | const struct i2c_device_id *id) |
501 | const struct i2c_device_id *id) | ||
502 | { | 488 | { |
503 | struct snd_soc_device *socdev = ak4535_socdev; | 489 | struct ak4535_priv *ak4535; |
504 | struct snd_soc_codec *codec = socdev->card->codec; | ||
505 | int ret; | 490 | int ret; |
506 | 491 | ||
507 | i2c_set_clientdata(i2c, codec); | 492 | ak4535 = kzalloc(sizeof(struct ak4535_priv), GFP_KERNEL); |
508 | codec->control_data = i2c; | 493 | if (ak4535 == NULL) |
494 | return -ENOMEM; | ||
509 | 495 | ||
510 | ret = ak4535_init(socdev); | 496 | i2c_set_clientdata(i2c, ak4535); |
511 | if (ret < 0) | 497 | ak4535->control_data = i2c; |
512 | printk(KERN_ERR "failed to initialise AK4535\n"); | 498 | ak4535->control_type = SND_SOC_I2C; |
513 | 499 | ||
500 | ret = snd_soc_register_codec(&i2c->dev, | ||
501 | &soc_codec_dev_ak4535, &ak4535_dai, 1); | ||
502 | if (ret < 0) | ||
503 | kfree(ak4535); | ||
514 | return ret; | 504 | return ret; |
515 | } | 505 | } |
516 | 506 | ||
517 | static int ak4535_i2c_remove(struct i2c_client *client) | 507 | static __devexit int ak4535_i2c_remove(struct i2c_client *client) |
518 | { | 508 | { |
519 | struct snd_soc_codec *codec = i2c_get_clientdata(client); | 509 | snd_soc_unregister_codec(&client->dev); |
520 | kfree(codec->reg_cache); | 510 | kfree(i2c_get_clientdata(client)); |
521 | return 0; | 511 | return 0; |
522 | } | 512 | } |
523 | 513 | ||
@@ -529,138 +519,34 @@ MODULE_DEVICE_TABLE(i2c, ak4535_i2c_id); | |||
529 | 519 | ||
530 | static struct i2c_driver ak4535_i2c_driver = { | 520 | static struct i2c_driver ak4535_i2c_driver = { |
531 | .driver = { | 521 | .driver = { |
532 | .name = "AK4535 I2C Codec", | 522 | .name = "ak4535-codec", |
533 | .owner = THIS_MODULE, | 523 | .owner = THIS_MODULE, |
534 | }, | 524 | }, |
535 | .probe = ak4535_i2c_probe, | 525 | .probe = ak4535_i2c_probe, |
536 | .remove = ak4535_i2c_remove, | 526 | .remove = __devexit_p(ak4535_i2c_remove), |
537 | .id_table = ak4535_i2c_id, | 527 | .id_table = ak4535_i2c_id, |
538 | }; | 528 | }; |
539 | |||
540 | static int ak4535_add_i2c_device(struct platform_device *pdev, | ||
541 | const struct ak4535_setup_data *setup) | ||
542 | { | ||
543 | struct i2c_board_info info; | ||
544 | struct i2c_adapter *adapter; | ||
545 | struct i2c_client *client; | ||
546 | int ret; | ||
547 | |||
548 | ret = i2c_add_driver(&ak4535_i2c_driver); | ||
549 | if (ret != 0) { | ||
550 | dev_err(&pdev->dev, "can't add i2c driver\n"); | ||
551 | return ret; | ||
552 | } | ||
553 | |||
554 | memset(&info, 0, sizeof(struct i2c_board_info)); | ||
555 | info.addr = setup->i2c_address; | ||
556 | strlcpy(info.type, "ak4535", I2C_NAME_SIZE); | ||
557 | |||
558 | adapter = i2c_get_adapter(setup->i2c_bus); | ||
559 | if (!adapter) { | ||
560 | dev_err(&pdev->dev, "can't get i2c adapter %d\n", | ||
561 | setup->i2c_bus); | ||
562 | goto err_driver; | ||
563 | } | ||
564 | |||
565 | client = i2c_new_device(adapter, &info); | ||
566 | i2c_put_adapter(adapter); | ||
567 | if (!client) { | ||
568 | dev_err(&pdev->dev, "can't add i2c device at 0x%x\n", | ||
569 | (unsigned int)info.addr); | ||
570 | goto err_driver; | ||
571 | } | ||
572 | |||
573 | return 0; | ||
574 | |||
575 | err_driver: | ||
576 | i2c_del_driver(&ak4535_i2c_driver); | ||
577 | return -ENODEV; | ||
578 | } | ||
579 | #endif | 529 | #endif |
580 | 530 | ||
581 | static int ak4535_probe(struct platform_device *pdev) | 531 | static int __init ak4535_modinit(void) |
582 | { | 532 | { |
583 | struct snd_soc_device *socdev = platform_get_drvdata(pdev); | 533 | int ret = 0; |
584 | struct ak4535_setup_data *setup; | ||
585 | struct snd_soc_codec *codec; | ||
586 | struct ak4535_priv *ak4535; | ||
587 | int ret; | ||
588 | |||
589 | printk(KERN_INFO "AK4535 Audio Codec %s", AK4535_VERSION); | ||
590 | |||
591 | setup = socdev->codec_data; | ||
592 | codec = kzalloc(sizeof(struct snd_soc_codec), GFP_KERNEL); | ||
593 | if (codec == NULL) | ||
594 | return -ENOMEM; | ||
595 | |||
596 | ak4535 = kzalloc(sizeof(struct ak4535_priv), GFP_KERNEL); | ||
597 | if (ak4535 == NULL) { | ||
598 | kfree(codec); | ||
599 | return -ENOMEM; | ||
600 | } | ||
601 | |||
602 | snd_soc_codec_set_drvdata(codec, ak4535); | ||
603 | socdev->card->codec = codec; | ||
604 | mutex_init(&codec->mutex); | ||
605 | INIT_LIST_HEAD(&codec->dapm_widgets); | ||
606 | INIT_LIST_HEAD(&codec->dapm_paths); | ||
607 | |||
608 | ak4535_socdev = socdev; | ||
609 | ret = -ENODEV; | ||
610 | |||
611 | #if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE) | 534 | #if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE) |
612 | if (setup->i2c_address) { | 535 | ret = i2c_add_driver(&ak4535_i2c_driver); |
613 | codec->hw_write = (hw_write_t)i2c_master_send; | ||
614 | ret = ak4535_add_i2c_device(pdev, setup); | ||
615 | } | ||
616 | #endif | ||
617 | |||
618 | if (ret != 0) { | 536 | if (ret != 0) { |
619 | kfree(snd_soc_codec_get_drvdata(codec)); | 537 | printk(KERN_ERR "Failed to register AK4535 I2C driver: %d\n", |
620 | kfree(codec); | 538 | ret); |
621 | } | 539 | } |
540 | #endif | ||
622 | return ret; | 541 | return ret; |
623 | } | 542 | } |
543 | module_init(ak4535_modinit); | ||
624 | 544 | ||
625 | /* power down chip */ | 545 | static void __exit ak4535_exit(void) |
626 | static int ak4535_remove(struct platform_device *pdev) | ||
627 | { | 546 | { |
628 | struct snd_soc_device *socdev = platform_get_drvdata(pdev); | ||
629 | struct snd_soc_codec *codec = socdev->card->codec; | ||
630 | |||
631 | if (codec->control_data) | ||
632 | ak4535_set_bias_level(codec, SND_SOC_BIAS_OFF); | ||
633 | |||
634 | snd_soc_free_pcms(socdev); | ||
635 | snd_soc_dapm_free(socdev); | ||
636 | #if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE) | 547 | #if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE) |
637 | if (codec->control_data) | ||
638 | i2c_unregister_device(codec->control_data); | ||
639 | i2c_del_driver(&ak4535_i2c_driver); | 548 | i2c_del_driver(&ak4535_i2c_driver); |
640 | #endif | 549 | #endif |
641 | kfree(snd_soc_codec_get_drvdata(codec)); | ||
642 | kfree(codec); | ||
643 | |||
644 | return 0; | ||
645 | } | ||
646 | |||
647 | struct snd_soc_codec_device soc_codec_dev_ak4535 = { | ||
648 | .probe = ak4535_probe, | ||
649 | .remove = ak4535_remove, | ||
650 | .suspend = ak4535_suspend, | ||
651 | .resume = ak4535_resume, | ||
652 | }; | ||
653 | EXPORT_SYMBOL_GPL(soc_codec_dev_ak4535); | ||
654 | |||
655 | static int __init ak4535_modinit(void) | ||
656 | { | ||
657 | return snd_soc_register_dai(&ak4535_dai); | ||
658 | } | ||
659 | module_init(ak4535_modinit); | ||
660 | |||
661 | static void __exit ak4535_exit(void) | ||
662 | { | ||
663 | snd_soc_unregister_dai(&ak4535_dai); | ||
664 | } | 550 | } |
665 | module_exit(ak4535_exit); | 551 | module_exit(ak4535_exit); |
666 | 552 | ||
diff --git a/sound/soc/codecs/ak4535.h b/sound/soc/codecs/ak4535.h index c7a58703ea39..0431e5f634a2 100644 --- a/sound/soc/codecs/ak4535.h +++ b/sound/soc/codecs/ak4535.h | |||
@@ -36,12 +36,4 @@ | |||
36 | 36 | ||
37 | #define AK4535_CACHEREGNUM 0x10 | 37 | #define AK4535_CACHEREGNUM 0x10 |
38 | 38 | ||
39 | struct ak4535_setup_data { | ||
40 | int i2c_bus; | ||
41 | unsigned short i2c_address; | ||
42 | }; | ||
43 | |||
44 | extern struct snd_soc_dai ak4535_dai; | ||
45 | extern struct snd_soc_codec_device soc_codec_dev_ak4535; | ||
46 | |||
47 | #endif | 39 | #endif |
diff --git a/sound/soc/codecs/ak4642.c b/sound/soc/codecs/ak4642.c index 3d7dc55305ec..31b35e967398 100644 --- a/sound/soc/codecs/ak4642.c +++ b/sound/soc/codecs/ak4642.c | |||
@@ -30,8 +30,6 @@ | |||
30 | #include <sound/initval.h> | 30 | #include <sound/initval.h> |
31 | #include <sound/tlv.h> | 31 | #include <sound/tlv.h> |
32 | 32 | ||
33 | #include "ak4642.h" | ||
34 | |||
35 | #define AK4642_VERSION "0.0.1" | 33 | #define AK4642_VERSION "0.0.1" |
36 | 34 | ||
37 | #define PW_MGMT1 0x00 | 35 | #define PW_MGMT1 0x00 |
@@ -102,7 +100,6 @@ | |||
102 | #define FS3 (1 << 5) | 100 | #define FS3 (1 << 5) |
103 | #define FS_MASK (FS0 | FS1 | FS2 | FS3) | 101 | #define FS_MASK (FS0 | FS1 | FS2 | FS3) |
104 | 102 | ||
105 | struct snd_soc_codec_device soc_codec_dev_ak4642; | ||
106 | 103 | ||
107 | /* | 104 | /* |
108 | * Playback Volume (table 39) | 105 | * Playback Volume (table 39) |
@@ -123,11 +120,11 @@ static const struct snd_kcontrol_new ak4642_snd_controls[] = { | |||
123 | 120 | ||
124 | /* codec private data */ | 121 | /* codec private data */ |
125 | struct ak4642_priv { | 122 | struct ak4642_priv { |
126 | struct snd_soc_codec codec; | 123 | unsigned int sysclk; |
124 | enum snd_soc_control_type control_type; | ||
125 | void *control_data; | ||
127 | }; | 126 | }; |
128 | 127 | ||
129 | static struct snd_soc_codec *ak4642_codec; | ||
130 | |||
131 | /* | 128 | /* |
132 | * ak4642 register cache | 129 | * ak4642 register cache |
133 | */ | 130 | */ |
@@ -393,8 +390,8 @@ static struct snd_soc_dai_ops ak4642_dai_ops = { | |||
393 | .hw_params = ak4642_dai_hw_params, | 390 | .hw_params = ak4642_dai_hw_params, |
394 | }; | 391 | }; |
395 | 392 | ||
396 | struct snd_soc_dai ak4642_dai = { | 393 | static struct snd_soc_dai_driver ak4642_dai = { |
397 | .name = "AK4642", | 394 | .name = "ak4642-hifi", |
398 | .playback = { | 395 | .playback = { |
399 | .stream_name = "Playback", | 396 | .stream_name = "Playback", |
400 | .channels_min = 1, | 397 | .channels_min = 1, |
@@ -410,112 +407,63 @@ struct snd_soc_dai ak4642_dai = { | |||
410 | .ops = &ak4642_dai_ops, | 407 | .ops = &ak4642_dai_ops, |
411 | .symmetric_rates = 1, | 408 | .symmetric_rates = 1, |
412 | }; | 409 | }; |
413 | EXPORT_SYMBOL_GPL(ak4642_dai); | ||
414 | 410 | ||
415 | static int ak4642_resume(struct platform_device *pdev) | 411 | static int ak4642_resume(struct snd_soc_codec *codec) |
416 | { | 412 | { |
417 | struct snd_soc_device *socdev = platform_get_drvdata(pdev); | ||
418 | struct snd_soc_codec *codec = socdev->card->codec; | ||
419 | |||
420 | ak4642_sync(codec); | 413 | ak4642_sync(codec); |
421 | return 0; | 414 | return 0; |
422 | } | 415 | } |
423 | 416 | ||
424 | /* | 417 | |
425 | * initialise the AK4642 driver | 418 | static int ak4642_probe(struct snd_soc_codec *codec) |
426 | * register the mixer and dsp interfaces with the kernel | ||
427 | */ | ||
428 | static int ak4642_init(struct ak4642_priv *ak4642) | ||
429 | { | 419 | { |
430 | struct snd_soc_codec *codec = &ak4642->codec; | 420 | struct ak4642_priv *ak4642 = snd_soc_codec_get_drvdata(codec); |
431 | int ret = 0; | ||
432 | 421 | ||
433 | if (ak4642_codec) { | 422 | dev_info(codec->dev, "AK4642 Audio Codec %s", AK4642_VERSION); |
434 | dev_err(codec->dev, "Another ak4642 is registered\n"); | ||
435 | return -EINVAL; | ||
436 | } | ||
437 | 423 | ||
438 | mutex_init(&codec->mutex); | ||
439 | INIT_LIST_HEAD(&codec->dapm_widgets); | ||
440 | INIT_LIST_HEAD(&codec->dapm_paths); | ||
441 | |||
442 | snd_soc_codec_set_drvdata(codec, ak4642); | ||
443 | codec->name = "AK4642"; | ||
444 | codec->owner = THIS_MODULE; | ||
445 | codec->read = ak4642_read_reg_cache; | ||
446 | codec->write = ak4642_write; | ||
447 | codec->dai = &ak4642_dai; | ||
448 | codec->num_dai = 1; | ||
449 | codec->hw_write = (hw_write_t)i2c_master_send; | 424 | codec->hw_write = (hw_write_t)i2c_master_send; |
450 | codec->reg_cache_size = ARRAY_SIZE(ak4642_reg); | 425 | codec->control_data = ak4642->control_data; |
451 | codec->reg_cache = kmemdup(ak4642_reg, | ||
452 | sizeof(ak4642_reg), GFP_KERNEL); | ||
453 | |||
454 | if (!codec->reg_cache) | ||
455 | return -ENOMEM; | ||
456 | |||
457 | ak4642_dai.dev = codec->dev; | ||
458 | ak4642_codec = codec; | ||
459 | |||
460 | ret = snd_soc_register_codec(codec); | ||
461 | if (ret) { | ||
462 | dev_err(codec->dev, "Failed to register codec: %d\n", ret); | ||
463 | goto reg_cache_err; | ||
464 | } | ||
465 | 426 | ||
466 | ret = snd_soc_register_dai(&ak4642_dai); | ||
467 | if (ret) { | ||
468 | dev_err(codec->dev, "Failed to register DAI: %d\n", ret); | ||
469 | snd_soc_unregister_codec(codec); | ||
470 | goto reg_cache_err; | ||
471 | } | ||
472 | |||
473 | return ret; | ||
474 | |||
475 | reg_cache_err: | ||
476 | kfree(codec->reg_cache); | ||
477 | codec->reg_cache = NULL; | ||
478 | 427 | ||
479 | return ret; | 428 | return 0; |
480 | } | 429 | } |
481 | 430 | ||
431 | static struct snd_soc_codec_driver soc_codec_dev_ak4642 = { | ||
432 | .probe = ak4642_probe, | ||
433 | .resume = ak4642_resume, | ||
434 | .read = ak4642_read_reg_cache, | ||
435 | .write = ak4642_write, | ||
436 | .reg_cache_size = ARRAY_SIZE(ak4642_reg), | ||
437 | .reg_word_size = sizeof(u8), | ||
438 | .reg_cache_default = ak4642_reg, | ||
439 | }; | ||
440 | |||
482 | #if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE) | 441 | #if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE) |
483 | static int ak4642_i2c_probe(struct i2c_client *i2c, | 442 | static __devinit int ak4642_i2c_probe(struct i2c_client *i2c, |
484 | const struct i2c_device_id *id) | 443 | const struct i2c_device_id *id) |
485 | { | 444 | { |
486 | struct ak4642_priv *ak4642; | 445 | struct ak4642_priv *ak4642; |
487 | struct snd_soc_codec *codec; | ||
488 | int ret; | 446 | int ret; |
489 | 447 | ||
490 | ak4642 = kzalloc(sizeof(struct ak4642_priv), GFP_KERNEL); | 448 | ak4642 = kzalloc(sizeof(struct ak4642_priv), GFP_KERNEL); |
491 | if (!ak4642) | 449 | if (ak4642 == NULL) |
492 | return -ENOMEM; | 450 | return -ENOMEM; |
493 | 451 | ||
494 | codec = &ak4642->codec; | ||
495 | codec->dev = &i2c->dev; | ||
496 | |||
497 | i2c_set_clientdata(i2c, ak4642); | 452 | i2c_set_clientdata(i2c, ak4642); |
498 | codec->control_data = i2c; | 453 | ak4642->control_data = i2c; |
454 | ak4642->control_type = SND_SOC_I2C; | ||
499 | 455 | ||
500 | ret = ak4642_init(ak4642); | 456 | ret = snd_soc_register_codec(&i2c->dev, |
501 | if (ret < 0) { | 457 | &soc_codec_dev_ak4642, &ak4642_dai, 1); |
502 | printk(KERN_ERR "failed to initialise AK4642\n"); | 458 | if (ret < 0) |
503 | kfree(ak4642); | 459 | kfree(ak4642); |
504 | } | ||
505 | |||
506 | return ret; | 460 | return ret; |
507 | } | 461 | } |
508 | 462 | ||
509 | static int ak4642_i2c_remove(struct i2c_client *client) | 463 | static __devexit int ak4642_i2c_remove(struct i2c_client *client) |
510 | { | 464 | { |
511 | struct ak4642_priv *ak4642 = i2c_get_clientdata(client); | 465 | snd_soc_unregister_codec(&client->dev); |
512 | 466 | kfree(i2c_get_clientdata(client)); | |
513 | snd_soc_unregister_dai(&ak4642_dai); | ||
514 | snd_soc_unregister_codec(&ak4642->codec); | ||
515 | kfree(ak4642->codec.reg_cache); | ||
516 | kfree(ak4642); | ||
517 | ak4642_codec = NULL; | ||
518 | |||
519 | return 0; | 467 | return 0; |
520 | } | 468 | } |
521 | 469 | ||
@@ -528,64 +476,15 @@ MODULE_DEVICE_TABLE(i2c, ak4642_i2c_id); | |||
528 | 476 | ||
529 | static struct i2c_driver ak4642_i2c_driver = { | 477 | static struct i2c_driver ak4642_i2c_driver = { |
530 | .driver = { | 478 | .driver = { |
531 | .name = "AK4642 I2C Codec", | 479 | .name = "ak4642-codec", |
532 | .owner = THIS_MODULE, | 480 | .owner = THIS_MODULE, |
533 | }, | 481 | }, |
534 | .probe = ak4642_i2c_probe, | 482 | .probe = ak4642_i2c_probe, |
535 | .remove = ak4642_i2c_remove, | 483 | .remove = __devexit_p(ak4642_i2c_remove), |
536 | .id_table = ak4642_i2c_id, | 484 | .id_table = ak4642_i2c_id, |
537 | }; | 485 | }; |
538 | |||
539 | #endif | 486 | #endif |
540 | 487 | ||
541 | static int ak4642_probe(struct platform_device *pdev) | ||
542 | { | ||
543 | struct snd_soc_device *socdev = platform_get_drvdata(pdev); | ||
544 | int ret; | ||
545 | |||
546 | if (!ak4642_codec) { | ||
547 | dev_err(&pdev->dev, "Codec device not registered\n"); | ||
548 | return -ENODEV; | ||
549 | } | ||
550 | |||
551 | socdev->card->codec = ak4642_codec; | ||
552 | |||
553 | /* register pcms */ | ||
554 | ret = snd_soc_new_pcms(socdev, SNDRV_DEFAULT_IDX1, SNDRV_DEFAULT_STR1); | ||
555 | if (ret < 0) { | ||
556 | printk(KERN_ERR "ak4642: failed to create pcms\n"); | ||
557 | goto pcm_err; | ||
558 | } | ||
559 | |||
560 | snd_soc_add_controls(ak4642_codec, ak4642_snd_controls, | ||
561 | ARRAY_SIZE(ak4642_snd_controls)); | ||
562 | |||
563 | dev_info(&pdev->dev, "AK4642 Audio Codec %s", AK4642_VERSION); | ||
564 | return ret; | ||
565 | |||
566 | pcm_err: | ||
567 | return ret; | ||
568 | |||
569 | } | ||
570 | |||
571 | /* power down chip */ | ||
572 | static int ak4642_remove(struct platform_device *pdev) | ||
573 | { | ||
574 | struct snd_soc_device *socdev = platform_get_drvdata(pdev); | ||
575 | |||
576 | snd_soc_free_pcms(socdev); | ||
577 | snd_soc_dapm_free(socdev); | ||
578 | |||
579 | return 0; | ||
580 | } | ||
581 | |||
582 | struct snd_soc_codec_device soc_codec_dev_ak4642 = { | ||
583 | .probe = ak4642_probe, | ||
584 | .remove = ak4642_remove, | ||
585 | .resume = ak4642_resume, | ||
586 | }; | ||
587 | EXPORT_SYMBOL_GPL(soc_codec_dev_ak4642); | ||
588 | |||
589 | static int __init ak4642_modinit(void) | 488 | static int __init ak4642_modinit(void) |
590 | { | 489 | { |
591 | int ret = 0; | 490 | int ret = 0; |
diff --git a/sound/soc/codecs/ak4642.h b/sound/soc/codecs/ak4642.h deleted file mode 100644 index e476833d314e..000000000000 --- a/sound/soc/codecs/ak4642.h +++ /dev/null | |||
@@ -1,20 +0,0 @@ | |||
1 | /* | ||
2 | * ak4642.h -- AK4642 Soc Audio driver | ||
3 | * | ||
4 | * Copyright (C) 2009 Renesas Solutions Corp. | ||
5 | * Kuninori Morimoto <morimoto.kuninori@renesas.com> | ||
6 | * | ||
7 | * Based on ak4535.c | ||
8 | * | ||
9 | * This program is free software; you can redistribute it and/or modify | ||
10 | * it under the terms of the GNU General Public License version 2 as | ||
11 | * published by the Free Software Foundation. | ||
12 | */ | ||
13 | |||
14 | #ifndef _AK4642_H | ||
15 | #define _AK4642_H | ||
16 | |||
17 | extern struct snd_soc_dai ak4642_dai; | ||
18 | extern struct snd_soc_codec_device soc_codec_dev_ak4642; | ||
19 | |||
20 | #endif | ||
diff --git a/sound/soc/codecs/ak4671.c b/sound/soc/codecs/ak4671.c index 87566932a3b1..239f0562003c 100644 --- a/sound/soc/codecs/ak4671.c +++ b/sound/soc/codecs/ak4671.c | |||
@@ -23,11 +23,11 @@ | |||
23 | 23 | ||
24 | #include "ak4671.h" | 24 | #include "ak4671.h" |
25 | 25 | ||
26 | static struct snd_soc_codec *ak4671_codec; | ||
27 | 26 | ||
28 | /* codec private data */ | 27 | /* codec private data */ |
29 | struct ak4671_priv { | 28 | struct ak4671_priv { |
30 | struct snd_soc_codec codec; | 29 | enum snd_soc_control_type control_type; |
30 | void *control_data; | ||
31 | u8 reg_cache[AK4671_CACHEREGNUM]; | 31 | u8 reg_cache[AK4671_CACHEREGNUM]; |
32 | }; | 32 | }; |
33 | 33 | ||
@@ -619,8 +619,8 @@ static struct snd_soc_dai_ops ak4671_dai_ops = { | |||
619 | .set_fmt = ak4671_set_dai_fmt, | 619 | .set_fmt = ak4671_set_dai_fmt, |
620 | }; | 620 | }; |
621 | 621 | ||
622 | struct snd_soc_dai ak4671_dai = { | 622 | static struct snd_soc_dai_driver ak4671_dai = { |
623 | .name = "AK4671", | 623 | .name = "ak4671-hifi", |
624 | .playback = { | 624 | .playback = { |
625 | .stream_name = "Playback", | 625 | .stream_name = "Playback", |
626 | .channels_min = 1, | 626 | .channels_min = 1, |
@@ -635,27 +635,19 @@ struct snd_soc_dai ak4671_dai = { | |||
635 | .formats = AK4671_FORMATS,}, | 635 | .formats = AK4671_FORMATS,}, |
636 | .ops = &ak4671_dai_ops, | 636 | .ops = &ak4671_dai_ops, |
637 | }; | 637 | }; |
638 | EXPORT_SYMBOL_GPL(ak4671_dai); | ||
639 | 638 | ||
640 | static int ak4671_probe(struct platform_device *pdev) | 639 | static int ak4671_probe(struct snd_soc_codec *codec) |
641 | { | 640 | { |
642 | struct snd_soc_device *socdev = platform_get_drvdata(pdev); | 641 | struct ak4671_priv *ak4671 = snd_soc_codec_get_drvdata(codec); |
643 | struct snd_soc_codec *codec; | 642 | int ret; |
644 | int ret = 0; | ||
645 | |||
646 | if (ak4671_codec == NULL) { | ||
647 | dev_err(&pdev->dev, "Codec device not registered\n"); | ||
648 | return -ENODEV; | ||
649 | } | ||
650 | 643 | ||
651 | socdev->card->codec = ak4671_codec; | 644 | codec->hw_write = (hw_write_t)i2c_master_send; |
652 | codec = ak4671_codec; | 645 | codec->bias_level = SND_SOC_BIAS_OFF; |
653 | 646 | ||
654 | /* register pcms */ | 647 | ret = snd_soc_codec_set_cache_io(codec, 8, 8, ak4671->control_type); |
655 | ret = snd_soc_new_pcms(socdev, SNDRV_DEFAULT_IDX1, SNDRV_DEFAULT_STR1); | ||
656 | if (ret < 0) { | 648 | if (ret < 0) { |
657 | dev_err(codec->dev, "failed to create pcms: %d\n", ret); | 649 | dev_err(codec->dev, "Failed to set cache I/O: %d\n", ret); |
658 | goto pcm_err; | 650 | return ret; |
659 | } | 651 | } |
660 | 652 | ||
661 | snd_soc_add_controls(codec, ak4671_snd_controls, | 653 | snd_soc_add_controls(codec, ak4671_snd_controls, |
@@ -665,121 +657,48 @@ static int ak4671_probe(struct platform_device *pdev) | |||
665 | ak4671_set_bias_level(codec, SND_SOC_BIAS_STANDBY); | 657 | ak4671_set_bias_level(codec, SND_SOC_BIAS_STANDBY); |
666 | 658 | ||
667 | return ret; | 659 | return ret; |
668 | |||
669 | pcm_err: | ||
670 | return ret; | ||
671 | } | 660 | } |
672 | 661 | ||
673 | static int ak4671_remove(struct platform_device *pdev) | 662 | static int ak4671_remove(struct snd_soc_codec *codec) |
674 | { | 663 | { |
675 | struct snd_soc_device *socdev = platform_get_drvdata(pdev); | 664 | ak4671_set_bias_level(codec, SND_SOC_BIAS_OFF); |
676 | |||
677 | snd_soc_free_pcms(socdev); | ||
678 | snd_soc_dapm_free(socdev); | ||
679 | |||
680 | return 0; | 665 | return 0; |
681 | } | 666 | } |
682 | 667 | ||
683 | struct snd_soc_codec_device soc_codec_dev_ak4671 = { | 668 | static struct snd_soc_codec_driver soc_codec_dev_ak4671 = { |
684 | .probe = ak4671_probe, | 669 | .probe = ak4671_probe, |
685 | .remove = ak4671_remove, | 670 | .remove = ak4671_remove, |
671 | .set_bias_level = ak4671_set_bias_level, | ||
672 | .reg_cache_size = AK4671_CACHEREGNUM, | ||
673 | .reg_word_size = sizeof(u8), | ||
674 | .reg_cache_default = ak4671_reg, | ||
686 | }; | 675 | }; |
687 | EXPORT_SYMBOL_GPL(soc_codec_dev_ak4671); | ||
688 | |||
689 | static int ak4671_register(struct ak4671_priv *ak4671, | ||
690 | enum snd_soc_control_type control) | ||
691 | { | ||
692 | int ret; | ||
693 | struct snd_soc_codec *codec = &ak4671->codec; | ||
694 | |||
695 | if (ak4671_codec) { | ||
696 | dev_err(codec->dev, "Another AK4671 is registered\n"); | ||
697 | ret = -EINVAL; | ||
698 | goto err; | ||
699 | } | ||
700 | |||
701 | mutex_init(&codec->mutex); | ||
702 | INIT_LIST_HEAD(&codec->dapm_widgets); | ||
703 | INIT_LIST_HEAD(&codec->dapm_paths); | ||
704 | |||
705 | snd_soc_codec_set_drvdata(codec, ak4671); | ||
706 | codec->name = "AK4671"; | ||
707 | codec->owner = THIS_MODULE; | ||
708 | codec->bias_level = SND_SOC_BIAS_OFF; | ||
709 | codec->set_bias_level = ak4671_set_bias_level; | ||
710 | codec->dai = &ak4671_dai; | ||
711 | codec->num_dai = 1; | ||
712 | codec->reg_cache_size = AK4671_CACHEREGNUM; | ||
713 | codec->reg_cache = &ak4671->reg_cache; | ||
714 | |||
715 | memcpy(codec->reg_cache, ak4671_reg, sizeof(ak4671_reg)); | ||
716 | |||
717 | ret = snd_soc_codec_set_cache_io(codec, 8, 8, control); | ||
718 | if (ret < 0) { | ||
719 | dev_err(codec->dev, "Failed to set cache I/O: %d\n", ret); | ||
720 | goto err; | ||
721 | } | ||
722 | |||
723 | ak4671_dai.dev = codec->dev; | ||
724 | ak4671_codec = codec; | ||
725 | |||
726 | ret = snd_soc_register_codec(codec); | ||
727 | if (ret != 0) { | ||
728 | dev_err(codec->dev, "Failed to register codec: %d\n", ret); | ||
729 | goto err; | ||
730 | } | ||
731 | |||
732 | ret = snd_soc_register_dai(&ak4671_dai); | ||
733 | if (ret != 0) { | ||
734 | dev_err(codec->dev, "Failed to register DAI: %d\n", ret); | ||
735 | goto err_codec; | ||
736 | } | ||
737 | |||
738 | return 0; | ||
739 | |||
740 | err_codec: | ||
741 | snd_soc_unregister_codec(codec); | ||
742 | err: | ||
743 | kfree(ak4671); | ||
744 | return ret; | ||
745 | } | ||
746 | |||
747 | static void ak4671_unregister(struct ak4671_priv *ak4671) | ||
748 | { | ||
749 | ak4671_set_bias_level(&ak4671->codec, SND_SOC_BIAS_OFF); | ||
750 | snd_soc_unregister_dai(&ak4671_dai); | ||
751 | snd_soc_unregister_codec(&ak4671->codec); | ||
752 | kfree(ak4671); | ||
753 | ak4671_codec = NULL; | ||
754 | } | ||
755 | 676 | ||
756 | static int __devinit ak4671_i2c_probe(struct i2c_client *client, | 677 | static int __devinit ak4671_i2c_probe(struct i2c_client *client, |
757 | const struct i2c_device_id *id) | 678 | const struct i2c_device_id *id) |
758 | { | 679 | { |
759 | struct ak4671_priv *ak4671; | 680 | struct ak4671_priv *ak4671; |
760 | struct snd_soc_codec *codec; | 681 | int ret; |
761 | 682 | ||
762 | ak4671 = kzalloc(sizeof(struct ak4671_priv), GFP_KERNEL); | 683 | ak4671 = kzalloc(sizeof(struct ak4671_priv), GFP_KERNEL); |
763 | if (ak4671 == NULL) | 684 | if (ak4671 == NULL) |
764 | return -ENOMEM; | 685 | return -ENOMEM; |
765 | 686 | ||
766 | codec = &ak4671->codec; | ||
767 | codec->hw_write = (hw_write_t)i2c_master_send; | ||
768 | |||
769 | i2c_set_clientdata(client, ak4671); | 687 | i2c_set_clientdata(client, ak4671); |
770 | codec->control_data = client; | 688 | ak4671->control_data = client; |
771 | 689 | ak4671->control_type = SND_SOC_I2C; | |
772 | codec->dev = &client->dev; | ||
773 | 690 | ||
774 | return ak4671_register(ak4671, SND_SOC_I2C); | 691 | ret = snd_soc_register_codec(&client->dev, |
692 | &soc_codec_dev_ak4671, &ak4671_dai, 1); | ||
693 | if (ret < 0) | ||
694 | kfree(ak4671); | ||
695 | return ret; | ||
775 | } | 696 | } |
776 | 697 | ||
777 | static __devexit int ak4671_i2c_remove(struct i2c_client *client) | 698 | static __devexit int ak4671_i2c_remove(struct i2c_client *client) |
778 | { | 699 | { |
779 | struct ak4671_priv *ak4671 = i2c_get_clientdata(client); | 700 | snd_soc_unregister_codec(&client->dev); |
780 | 701 | kfree(i2c_get_clientdata(client)); | |
781 | ak4671_unregister(ak4671); | ||
782 | |||
783 | return 0; | 702 | return 0; |
784 | } | 703 | } |
785 | 704 | ||
@@ -791,7 +710,7 @@ MODULE_DEVICE_TABLE(i2c, ak4671_i2c_id); | |||
791 | 710 | ||
792 | static struct i2c_driver ak4671_i2c_driver = { | 711 | static struct i2c_driver ak4671_i2c_driver = { |
793 | .driver = { | 712 | .driver = { |
794 | .name = "ak4671", | 713 | .name = "ak4671-codec", |
795 | .owner = THIS_MODULE, | 714 | .owner = THIS_MODULE, |
796 | }, | 715 | }, |
797 | .probe = ak4671_i2c_probe, | 716 | .probe = ak4671_i2c_probe, |
diff --git a/sound/soc/codecs/ak4671.h b/sound/soc/codecs/ak4671.h index e2fad964e88b..61cb7ab7552c 100644 --- a/sound/soc/codecs/ak4671.h +++ b/sound/soc/codecs/ak4671.h | |||
@@ -150,7 +150,4 @@ | |||
150 | /* AK4671_LOUT2_POWER_MANAGEMENT (0x10) Fields */ | 150 | /* AK4671_LOUT2_POWER_MANAGEMENT (0x10) Fields */ |
151 | #define AK4671_MUTEN 0x04 | 151 | #define AK4671_MUTEN 0x04 |
152 | 152 | ||
153 | extern struct snd_soc_dai ak4671_dai; | ||
154 | extern struct snd_soc_codec_device soc_codec_dev_ak4671; | ||
155 | |||
156 | #endif | 153 | #endif |
diff --git a/sound/soc/codecs/cq93vc.c b/sound/soc/codecs/cq93vc.c index a320fb5a0e26..823643932dde 100644 --- a/sound/soc/codecs/cq93vc.c +++ b/sound/soc/codecs/cq93vc.c | |||
@@ -30,6 +30,7 @@ | |||
30 | #include <linux/slab.h> | 30 | #include <linux/slab.h> |
31 | #include <linux/clk.h> | 31 | #include <linux/clk.h> |
32 | #include <linux/mfd/davinci_voicecodec.h> | 32 | #include <linux/mfd/davinci_voicecodec.h> |
33 | #include <linux/spi/spi.h> | ||
33 | 34 | ||
34 | #include <sound/core.h> | 35 | #include <sound/core.h> |
35 | #include <sound/pcm.h> | 36 | #include <sound/pcm.h> |
@@ -41,8 +42,6 @@ | |||
41 | 42 | ||
42 | #include <mach/dm365.h> | 43 | #include <mach/dm365.h> |
43 | 44 | ||
44 | #include "cq93vc.h" | ||
45 | |||
46 | static inline unsigned int cq93vc_read(struct snd_soc_codec *codec, | 45 | static inline unsigned int cq93vc_read(struct snd_soc_codec *codec, |
47 | unsigned int reg) | 46 | unsigned int reg) |
48 | { | 47 | { |
@@ -130,8 +129,8 @@ static struct snd_soc_dai_ops cq93vc_dai_ops = { | |||
130 | .set_sysclk = cq93vc_set_dai_sysclk, | 129 | .set_sysclk = cq93vc_set_dai_sysclk, |
131 | }; | 130 | }; |
132 | 131 | ||
133 | struct snd_soc_dai cq93vc_dai = { | 132 | static struct snd_soc_dai_driver cq93vc_dai = { |
134 | .name = "CQ93VC", | 133 | .name = "cq93vc-hifi", |
135 | .playback = { | 134 | .playback = { |
136 | .stream_name = "Playback", | 135 | .stream_name = "Playback", |
137 | .channels_min = 1, | 136 | .channels_min = 1, |
@@ -146,36 +145,20 @@ struct snd_soc_dai cq93vc_dai = { | |||
146 | .formats = CQ93VC_FORMATS,}, | 145 | .formats = CQ93VC_FORMATS,}, |
147 | .ops = &cq93vc_dai_ops, | 146 | .ops = &cq93vc_dai_ops, |
148 | }; | 147 | }; |
149 | EXPORT_SYMBOL_GPL(cq93vc_dai); | ||
150 | 148 | ||
151 | static int cq93vc_resume(struct platform_device *pdev) | 149 | static int cq93vc_resume(struct snd_soc_codec *codec) |
152 | { | 150 | { |
153 | struct snd_soc_device *socdev = platform_get_drvdata(pdev); | ||
154 | struct snd_soc_codec *codec = socdev->card->codec; | ||
155 | |||
156 | cq93vc_set_bias_level(codec, SND_SOC_BIAS_STANDBY); | 151 | cq93vc_set_bias_level(codec, SND_SOC_BIAS_STANDBY); |
157 | 152 | ||
158 | return 0; | 153 | return 0; |
159 | } | 154 | } |
160 | 155 | ||
161 | static struct snd_soc_codec *cq93vc_codec; | 156 | static int cq93vc_probe(struct snd_soc_codec *codec) |
162 | |||
163 | static int cq93vc_probe(struct platform_device *pdev) | ||
164 | { | 157 | { |
165 | struct snd_soc_device *socdev = platform_get_drvdata(pdev); | 158 | struct davinci_vc *davinci_vc = codec->dev->platform_data; |
166 | struct device *dev = &pdev->dev; | 159 | |
167 | struct snd_soc_codec *codec; | 160 | davinci_vc->cq93vc.codec = codec; |
168 | int ret; | 161 | codec->control_data = davinci_vc; |
169 | |||
170 | socdev->card->codec = cq93vc_codec; | ||
171 | codec = socdev->card->codec; | ||
172 | |||
173 | /* Register pcms */ | ||
174 | ret = snd_soc_new_pcms(socdev, SNDRV_DEFAULT_IDX1, SNDRV_DEFAULT_STR1); | ||
175 | if (ret < 0) { | ||
176 | dev_err(dev, "%s: failed to create pcms\n", pdev->name); | ||
177 | return ret; | ||
178 | } | ||
179 | 162 | ||
180 | /* Set controls */ | 163 | /* Set controls */ |
181 | snd_soc_add_controls(codec, cq93vc_snd_controls, | 164 | snd_soc_add_controls(codec, cq93vc_snd_controls, |
@@ -187,108 +170,51 @@ static int cq93vc_probe(struct platform_device *pdev) | |||
187 | return 0; | 170 | return 0; |
188 | } | 171 | } |
189 | 172 | ||
190 | static int cq93vc_remove(struct platform_device *pdev) | 173 | static int cq93vc_remove(struct snd_soc_codec *codec) |
191 | { | 174 | { |
192 | struct snd_soc_device *socdev = platform_get_drvdata(pdev); | 175 | cq93vc_set_bias_level(codec, SND_SOC_BIAS_OFF); |
193 | |||
194 | snd_soc_free_pcms(socdev); | ||
195 | snd_soc_dapm_free(socdev); | ||
196 | 176 | ||
197 | return 0; | 177 | return 0; |
198 | } | 178 | } |
199 | 179 | ||
200 | struct snd_soc_codec_device soc_codec_dev_cq93vc = { | 180 | static struct snd_soc_codec_driver soc_codec_dev_cq93vc = { |
181 | .read = cq93vc_read, | ||
182 | .write = cq93vc_write, | ||
183 | .set_bias_level = cq93vc_set_bias_level, | ||
201 | .probe = cq93vc_probe, | 184 | .probe = cq93vc_probe, |
202 | .remove = cq93vc_remove, | 185 | .remove = cq93vc_remove, |
203 | .resume = cq93vc_resume, | 186 | .resume = cq93vc_resume, |
204 | }; | 187 | }; |
205 | EXPORT_SYMBOL_GPL(soc_codec_dev_cq93vc); | ||
206 | 188 | ||
207 | static __init int cq93vc_codec_probe(struct platform_device *pdev) | 189 | static int cq93vc_platform_probe(struct platform_device *pdev) |
208 | { | 190 | { |
209 | struct davinci_vc *davinci_vc = platform_get_drvdata(pdev); | 191 | return snd_soc_register_codec(&pdev->dev, |
210 | struct snd_soc_codec *codec; | 192 | &soc_codec_dev_cq93vc, &cq93vc_dai, 1); |
211 | int ret; | ||
212 | |||
213 | codec = kzalloc(sizeof(struct snd_soc_codec), GFP_KERNEL); | ||
214 | if (codec == NULL) { | ||
215 | dev_dbg(davinci_vc->dev, | ||
216 | "could not allocate memory for codec data\n"); | ||
217 | return -ENOMEM; | ||
218 | } | ||
219 | |||
220 | davinci_vc->cq93vc.codec = codec; | ||
221 | |||
222 | cq93vc_dai.dev = &pdev->dev; | ||
223 | |||
224 | mutex_init(&codec->mutex); | ||
225 | INIT_LIST_HEAD(&codec->dapm_widgets); | ||
226 | INIT_LIST_HEAD(&codec->dapm_paths); | ||
227 | codec->dev = &pdev->dev; | ||
228 | codec->name = "CQ93VC"; | ||
229 | codec->owner = THIS_MODULE; | ||
230 | codec->read = cq93vc_read; | ||
231 | codec->write = cq93vc_write; | ||
232 | codec->set_bias_level = cq93vc_set_bias_level; | ||
233 | codec->dai = &cq93vc_dai; | ||
234 | codec->num_dai = 1; | ||
235 | codec->control_data = davinci_vc; | ||
236 | |||
237 | cq93vc_codec = codec; | ||
238 | |||
239 | ret = snd_soc_register_codec(codec); | ||
240 | if (ret) { | ||
241 | dev_err(davinci_vc->dev, "failed to register codec\n"); | ||
242 | goto fail1; | ||
243 | } | ||
244 | |||
245 | ret = snd_soc_register_dai(&cq93vc_dai); | ||
246 | if (ret) { | ||
247 | dev_err(davinci_vc->dev, "could register dai\n"); | ||
248 | goto fail2; | ||
249 | } | ||
250 | return 0; | ||
251 | |||
252 | fail2: | ||
253 | snd_soc_unregister_codec(codec); | ||
254 | |||
255 | fail1: | ||
256 | kfree(codec); | ||
257 | cq93vc_codec = NULL; | ||
258 | |||
259 | return ret; | ||
260 | } | 193 | } |
261 | 194 | ||
262 | static int __devexit cq93vc_codec_remove(struct platform_device *pdev) | 195 | static int cq93vc_platform_remove(struct platform_device *pdev) |
263 | { | 196 | { |
264 | struct snd_soc_device *socdev = platform_get_drvdata(pdev); | 197 | snd_soc_unregister_codec(&pdev->dev); |
265 | struct snd_soc_codec *codec = socdev->card->codec; | ||
266 | |||
267 | snd_soc_unregister_dai(&cq93vc_dai); | ||
268 | snd_soc_unregister_codec(&codec); | ||
269 | |||
270 | kfree(codec); | ||
271 | cq93vc_codec = NULL; | ||
272 | |||
273 | return 0; | 198 | return 0; |
274 | } | 199 | } |
275 | 200 | ||
276 | static struct platform_driver cq93vc_codec_driver = { | 201 | static struct platform_driver cq93vc_codec_driver = { |
277 | .driver = { | 202 | .driver = { |
278 | .name = "cq93vc", | 203 | .name = "cq93vc-codec", |
279 | .owner = THIS_MODULE, | 204 | .owner = THIS_MODULE, |
280 | }, | 205 | }, |
281 | .probe = cq93vc_codec_probe, | 206 | |
282 | .remove = __devexit_p(cq93vc_codec_remove), | 207 | .probe = cq93vc_platform_probe, |
208 | .remove = __devexit_p(cq93vc_platform_remove), | ||
283 | }; | 209 | }; |
284 | 210 | ||
285 | static __init int cq93vc_init(void) | 211 | static int __init cq93vc_init(void) |
286 | { | 212 | { |
287 | return platform_driver_probe(&cq93vc_codec_driver, cq93vc_codec_probe); | 213 | return platform_driver_register(&cq93vc_codec_driver); |
288 | } | 214 | } |
289 | module_init(cq93vc_init); | 215 | module_init(cq93vc_init); |
290 | 216 | ||
291 | static __exit void cq93vc_exit(void) | 217 | static void __exit cq93vc_exit(void) |
292 | { | 218 | { |
293 | platform_driver_unregister(&cq93vc_codec_driver); | 219 | platform_driver_unregister(&cq93vc_codec_driver); |
294 | } | 220 | } |
diff --git a/sound/soc/codecs/cq93vc.h b/sound/soc/codecs/cq93vc.h deleted file mode 100644 index 845b1968ef9c..000000000000 --- a/sound/soc/codecs/cq93vc.h +++ /dev/null | |||
@@ -1,29 +0,0 @@ | |||
1 | /* | ||
2 | * ALSA SoC CQ0093 Voice Codec Driver for DaVinci platforms | ||
3 | * | ||
4 | * Copyright (C) 2010 Texas Instruments, Inc | ||
5 | * | ||
6 | * Author: Miguel Aguilar <miguel.aguilar@ridgerun.com> | ||
7 | * | ||
8 | * This program is free software; you can redistribute it and/or modify | ||
9 | * it under the terms of the GNU General Public License as published by | ||
10 | * the Free Software Foundation; either version 2 of the License, or | ||
11 | * (at your option) any later version. | ||
12 | * | ||
13 | * This program is distributed in the hope that it will be useful, | ||
14 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
15 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
16 | * GNU General Public License for more details. | ||
17 | * | ||
18 | * You should have received a copy of the GNU General Public License | ||
19 | * along with this program; if not, write to the Free Software | ||
20 | * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA | ||
21 | */ | ||
22 | |||
23 | #ifndef _CQ93VC_H | ||
24 | #define _CQ93VC_H | ||
25 | |||
26 | extern struct snd_soc_dai cq93vc_dai; | ||
27 | extern struct snd_soc_codec_device soc_codec_dev_cq93vc; | ||
28 | |||
29 | #endif | ||
diff --git a/sound/soc/codecs/cs4270.c b/sound/soc/codecs/cs4270.c index 30d949239def..6542dc038951 100644 --- a/sound/soc/codecs/cs4270.c +++ b/sound/soc/codecs/cs4270.c | |||
@@ -31,8 +31,6 @@ | |||
31 | #include <linux/delay.h> | 31 | #include <linux/delay.h> |
32 | #include <linux/regulator/consumer.h> | 32 | #include <linux/regulator/consumer.h> |
33 | 33 | ||
34 | #include "cs4270.h" | ||
35 | |||
36 | /* | 34 | /* |
37 | * The codec isn't really big-endian or little-endian, since the I2S | 35 | * The codec isn't really big-endian or little-endian, since the I2S |
38 | * interface requires data to be sent serially with the MSbit first. | 36 | * interface requires data to be sent serially with the MSbit first. |
@@ -114,7 +112,8 @@ static const char *supply_names[] = { | |||
114 | 112 | ||
115 | /* Private data for the CS4270 */ | 113 | /* Private data for the CS4270 */ |
116 | struct cs4270_private { | 114 | struct cs4270_private { |
117 | struct snd_soc_codec codec; | 115 | enum snd_soc_control_type control_type; |
116 | void *control_data; | ||
118 | u8 reg_cache[CS4270_NUMREGS]; | 117 | u8 reg_cache[CS4270_NUMREGS]; |
119 | unsigned int mclk; /* Input frequency of the MCLK pin */ | 118 | unsigned int mclk; /* Input frequency of the MCLK pin */ |
120 | unsigned int mode; /* The mode (I2S or left-justified) */ | 119 | unsigned int mode; /* The mode (I2S or left-justified) */ |
@@ -212,44 +211,8 @@ static int cs4270_set_dai_sysclk(struct snd_soc_dai *codec_dai, | |||
212 | { | 211 | { |
213 | struct snd_soc_codec *codec = codec_dai->codec; | 212 | struct snd_soc_codec *codec = codec_dai->codec; |
214 | struct cs4270_private *cs4270 = snd_soc_codec_get_drvdata(codec); | 213 | struct cs4270_private *cs4270 = snd_soc_codec_get_drvdata(codec); |
215 | unsigned int rates = 0; | ||
216 | unsigned int rate_min = -1; | ||
217 | unsigned int rate_max = 0; | ||
218 | unsigned int i; | ||
219 | 214 | ||
220 | cs4270->mclk = freq; | 215 | cs4270->mclk = freq; |
221 | |||
222 | if (cs4270->mclk) { | ||
223 | for (i = 0; i < NUM_MCLK_RATIOS; i++) { | ||
224 | unsigned int rate = freq / cs4270_mode_ratios[i].ratio; | ||
225 | rates |= snd_pcm_rate_to_rate_bit(rate); | ||
226 | if (rate < rate_min) | ||
227 | rate_min = rate; | ||
228 | if (rate > rate_max) | ||
229 | rate_max = rate; | ||
230 | } | ||
231 | /* FIXME: soc should support a rate list */ | ||
232 | rates &= ~SNDRV_PCM_RATE_KNOT; | ||
233 | |||
234 | if (!rates) { | ||
235 | dev_err(codec->dev, "could not find a valid sample rate\n"); | ||
236 | return -EINVAL; | ||
237 | } | ||
238 | } else { | ||
239 | /* enable all possible rates */ | ||
240 | rates = SNDRV_PCM_RATE_8000_192000; | ||
241 | rate_min = 8000; | ||
242 | rate_max = 192000; | ||
243 | } | ||
244 | |||
245 | codec_dai->playback.rates = rates; | ||
246 | codec_dai->playback.rate_min = rate_min; | ||
247 | codec_dai->playback.rate_max = rate_max; | ||
248 | |||
249 | codec_dai->capture.rates = rates; | ||
250 | codec_dai->capture.rate_min = rate_min; | ||
251 | codec_dai->capture.rate_max = rate_max; | ||
252 | |||
253 | return 0; | 216 | return 0; |
254 | } | 217 | } |
255 | 218 | ||
@@ -410,8 +373,7 @@ static int cs4270_hw_params(struct snd_pcm_substream *substream, | |||
410 | struct snd_soc_dai *dai) | 373 | struct snd_soc_dai *dai) |
411 | { | 374 | { |
412 | struct snd_soc_pcm_runtime *rtd = substream->private_data; | 375 | struct snd_soc_pcm_runtime *rtd = substream->private_data; |
413 | struct snd_soc_device *socdev = rtd->socdev; | 376 | struct snd_soc_codec *codec = rtd->codec; |
414 | struct snd_soc_codec *codec = socdev->card->codec; | ||
415 | struct cs4270_private *cs4270 = snd_soc_codec_get_drvdata(codec); | 377 | struct cs4270_private *cs4270 = snd_soc_codec_get_drvdata(codec); |
416 | int ret; | 378 | int ret; |
417 | unsigned int i; | 379 | unsigned int i; |
@@ -549,19 +511,6 @@ static const struct snd_kcontrol_new cs4270_snd_controls[] = { | |||
549 | snd_soc_get_volsw, cs4270_soc_put_mute), | 511 | snd_soc_get_volsw, cs4270_soc_put_mute), |
550 | }; | 512 | }; |
551 | 513 | ||
552 | /* | ||
553 | * cs4270_codec - global variable to store codec for the ASoC probe function | ||
554 | * | ||
555 | * If struct i2c_driver had a private_data field, we wouldn't need to use | ||
556 | * cs4270_codec. This is the only way to pass the codec structure from | ||
557 | * cs4270_i2c_probe() to cs4270_probe(). Unfortunately, there is no good | ||
558 | * way to synchronize these two functions. cs4270_i2c_probe() can be called | ||
559 | * multiple times before cs4270_probe() is called even once. So for now, we | ||
560 | * also only allow cs4270_i2c_probe() to be run once. That means that we do | ||
561 | * not support more than one cs4270 device in the system, at least for now. | ||
562 | */ | ||
563 | static struct snd_soc_codec *cs4270_codec; | ||
564 | |||
565 | static struct snd_soc_dai_ops cs4270_dai_ops = { | 514 | static struct snd_soc_dai_ops cs4270_dai_ops = { |
566 | .hw_params = cs4270_hw_params, | 515 | .hw_params = cs4270_hw_params, |
567 | .set_sysclk = cs4270_set_dai_sysclk, | 516 | .set_sysclk = cs4270_set_dai_sysclk, |
@@ -569,20 +518,24 @@ static struct snd_soc_dai_ops cs4270_dai_ops = { | |||
569 | .digital_mute = cs4270_dai_mute, | 518 | .digital_mute = cs4270_dai_mute, |
570 | }; | 519 | }; |
571 | 520 | ||
572 | struct snd_soc_dai cs4270_dai = { | 521 | struct snd_soc_dai_driver cs4270_dai = { |
573 | .name = "cs4270", | 522 | .name = "cs4270-hifi", |
574 | .playback = { | 523 | .playback = { |
575 | .stream_name = "Playback", | 524 | .stream_name = "Playback", |
576 | .channels_min = 1, | 525 | .channels_min = 1, |
577 | .channels_max = 2, | 526 | .channels_max = 2, |
578 | .rates = 0, | 527 | .rates = SNDRV_PCM_RATE_CONTINUOUS, |
528 | .rate_min = 4000, | ||
529 | .rate_max = 216000, | ||
579 | .formats = CS4270_FORMATS, | 530 | .formats = CS4270_FORMATS, |
580 | }, | 531 | }, |
581 | .capture = { | 532 | .capture = { |
582 | .stream_name = "Capture", | 533 | .stream_name = "Capture", |
583 | .channels_min = 1, | 534 | .channels_min = 1, |
584 | .channels_max = 2, | 535 | .channels_max = 2, |
585 | .rates = 0, | 536 | .rates = SNDRV_PCM_RATE_CONTINUOUS, |
537 | .rate_min = 4000, | ||
538 | .rate_max = 216000, | ||
586 | .formats = CS4270_FORMATS, | 539 | .formats = CS4270_FORMATS, |
587 | }, | 540 | }, |
588 | .ops = &cs4270_dai_ops, | 541 | .ops = &cs4270_dai_ops, |
@@ -596,153 +549,19 @@ EXPORT_SYMBOL_GPL(cs4270_dai); | |||
596 | * This function is called when ASoC has all the pieces it needs to | 549 | * This function is called when ASoC has all the pieces it needs to |
597 | * instantiate a sound driver. | 550 | * instantiate a sound driver. |
598 | */ | 551 | */ |
599 | static int cs4270_probe(struct platform_device *pdev) | 552 | static int cs4270_probe(struct snd_soc_codec *codec) |
600 | { | ||
601 | struct snd_soc_device *socdev = platform_get_drvdata(pdev); | ||
602 | struct snd_soc_codec *codec = cs4270_codec; | ||
603 | struct cs4270_private *cs4270 = snd_soc_codec_get_drvdata(codec); | ||
604 | int i, ret; | ||
605 | |||
606 | /* Connect the codec to the socdev. snd_soc_new_pcms() needs this. */ | ||
607 | socdev->card->codec = codec; | ||
608 | |||
609 | /* Register PCMs */ | ||
610 | ret = snd_soc_new_pcms(socdev, SNDRV_DEFAULT_IDX1, SNDRV_DEFAULT_STR1); | ||
611 | if (ret < 0) { | ||
612 | dev_err(codec->dev, "failed to create pcms\n"); | ||
613 | return ret; | ||
614 | } | ||
615 | |||
616 | /* Add the non-DAPM controls */ | ||
617 | ret = snd_soc_add_controls(codec, cs4270_snd_controls, | ||
618 | ARRAY_SIZE(cs4270_snd_controls)); | ||
619 | if (ret < 0) { | ||
620 | dev_err(codec->dev, "failed to add controls\n"); | ||
621 | goto error_free_pcms; | ||
622 | } | ||
623 | |||
624 | /* get the power supply regulators */ | ||
625 | for (i = 0; i < ARRAY_SIZE(supply_names); i++) | ||
626 | cs4270->supplies[i].supply = supply_names[i]; | ||
627 | |||
628 | ret = regulator_bulk_get(codec->dev, ARRAY_SIZE(cs4270->supplies), | ||
629 | cs4270->supplies); | ||
630 | if (ret < 0) | ||
631 | goto error_free_pcms; | ||
632 | |||
633 | ret = regulator_bulk_enable(ARRAY_SIZE(cs4270->supplies), | ||
634 | cs4270->supplies); | ||
635 | if (ret < 0) | ||
636 | goto error_free_regulators; | ||
637 | |||
638 | return 0; | ||
639 | |||
640 | error_free_regulators: | ||
641 | regulator_bulk_free(ARRAY_SIZE(cs4270->supplies), | ||
642 | cs4270->supplies); | ||
643 | |||
644 | error_free_pcms: | ||
645 | snd_soc_free_pcms(socdev); | ||
646 | |||
647 | return ret; | ||
648 | } | ||
649 | |||
650 | /** | ||
651 | * cs4270_remove - ASoC remove function | ||
652 | * @pdev: platform device | ||
653 | * | ||
654 | * This function is the counterpart to cs4270_probe(). | ||
655 | */ | ||
656 | static int cs4270_remove(struct platform_device *pdev) | ||
657 | { | 553 | { |
658 | struct snd_soc_device *socdev = platform_get_drvdata(pdev); | ||
659 | struct snd_soc_codec *codec = cs4270_codec; | ||
660 | struct cs4270_private *cs4270 = snd_soc_codec_get_drvdata(codec); | 554 | struct cs4270_private *cs4270 = snd_soc_codec_get_drvdata(codec); |
555 | int i, ret, reg; | ||
661 | 556 | ||
662 | snd_soc_free_pcms(socdev); | 557 | codec->control_data = cs4270->control_data; |
663 | regulator_bulk_disable(ARRAY_SIZE(cs4270->supplies), cs4270->supplies); | ||
664 | regulator_bulk_free(ARRAY_SIZE(cs4270->supplies), cs4270->supplies); | ||
665 | |||
666 | return 0; | ||
667 | }; | ||
668 | |||
669 | /** | ||
670 | * cs4270_i2c_probe - initialize the I2C interface of the CS4270 | ||
671 | * @i2c_client: the I2C client object | ||
672 | * @id: the I2C device ID (ignored) | ||
673 | * | ||
674 | * This function is called whenever the I2C subsystem finds a device that | ||
675 | * matches the device ID given via a prior call to i2c_add_driver(). | ||
676 | */ | ||
677 | static int cs4270_i2c_probe(struct i2c_client *i2c_client, | ||
678 | const struct i2c_device_id *id) | ||
679 | { | ||
680 | struct snd_soc_codec *codec; | ||
681 | struct cs4270_private *cs4270; | ||
682 | unsigned int reg; | ||
683 | int ret; | ||
684 | |||
685 | /* For now, we only support one cs4270 device in the system. See the | ||
686 | * comment for cs4270_codec. | ||
687 | */ | ||
688 | if (cs4270_codec) { | ||
689 | dev_err(&i2c_client->dev, "ignoring CS4270 at addr %X\n", | ||
690 | i2c_client->addr); | ||
691 | dev_err(&i2c_client->dev, "only one per board allowed\n"); | ||
692 | /* Should we return something other than ENODEV here? */ | ||
693 | return -ENODEV; | ||
694 | } | ||
695 | |||
696 | /* Verify that we have a CS4270 */ | ||
697 | |||
698 | ret = i2c_smbus_read_byte_data(i2c_client, CS4270_CHIPID); | ||
699 | if (ret < 0) { | ||
700 | dev_err(&i2c_client->dev, "failed to read i2c at addr %X\n", | ||
701 | i2c_client->addr); | ||
702 | return ret; | ||
703 | } | ||
704 | /* The top four bits of the chip ID should be 1100. */ | ||
705 | if ((ret & 0xF0) != 0xC0) { | ||
706 | dev_err(&i2c_client->dev, "device at addr %X is not a CS4270\n", | ||
707 | i2c_client->addr); | ||
708 | return -ENODEV; | ||
709 | } | ||
710 | |||
711 | dev_info(&i2c_client->dev, "found device at i2c address %X\n", | ||
712 | i2c_client->addr); | ||
713 | dev_info(&i2c_client->dev, "hardware revision %X\n", ret & 0xF); | ||
714 | |||
715 | /* Allocate enough space for the snd_soc_codec structure | ||
716 | and our private data together. */ | ||
717 | cs4270 = kzalloc(sizeof(struct cs4270_private), GFP_KERNEL); | ||
718 | if (!cs4270) { | ||
719 | dev_err(&i2c_client->dev, "could not allocate codec\n"); | ||
720 | return -ENOMEM; | ||
721 | } | ||
722 | codec = &cs4270->codec; | ||
723 | |||
724 | mutex_init(&codec->mutex); | ||
725 | INIT_LIST_HEAD(&codec->dapm_widgets); | ||
726 | INIT_LIST_HEAD(&codec->dapm_paths); | ||
727 | |||
728 | codec->dev = &i2c_client->dev; | ||
729 | codec->name = "CS4270"; | ||
730 | codec->owner = THIS_MODULE; | ||
731 | codec->dai = &cs4270_dai; | ||
732 | codec->num_dai = 1; | ||
733 | snd_soc_codec_set_drvdata(codec, cs4270); | ||
734 | codec->control_data = i2c_client; | ||
735 | codec->read = cs4270_read_reg_cache; | ||
736 | codec->write = cs4270_i2c_write; | ||
737 | codec->reg_cache = cs4270->reg_cache; | ||
738 | codec->reg_cache_size = CS4270_NUMREGS; | ||
739 | 558 | ||
740 | /* The I2C interface is set up, so pre-fill our register cache */ | 559 | /* The I2C interface is set up, so pre-fill our register cache */ |
741 | 560 | ||
742 | ret = cs4270_fill_cache(codec); | 561 | ret = cs4270_fill_cache(codec); |
743 | if (ret < 0) { | 562 | if (ret < 0) { |
744 | dev_err(&i2c_client->dev, "failed to fill register cache\n"); | 563 | dev_err(codec->dev, "failed to fill register cache\n"); |
745 | goto error_free_codec; | 564 | return ret; |
746 | } | 565 | } |
747 | 566 | ||
748 | /* Disable auto-mute. This feature appears to be buggy. In some | 567 | /* Disable auto-mute. This feature appears to be buggy. In some |
@@ -755,7 +574,7 @@ static int cs4270_i2c_probe(struct i2c_client *i2c_client, | |||
755 | reg &= ~CS4270_MUTE_AUTO; | 574 | reg &= ~CS4270_MUTE_AUTO; |
756 | ret = cs4270_i2c_write(codec, CS4270_MUTE, reg); | 575 | ret = cs4270_i2c_write(codec, CS4270_MUTE, reg); |
757 | if (ret < 0) { | 576 | if (ret < 0) { |
758 | dev_err(&i2c_client->dev, "i2c write failed\n"); | 577 | dev_err(codec->dev, "i2c write failed\n"); |
759 | return ret; | 578 | return ret; |
760 | } | 579 | } |
761 | 580 | ||
@@ -769,65 +588,56 @@ static int cs4270_i2c_probe(struct i2c_client *i2c_client, | |||
769 | reg &= ~(CS4270_TRANS_SOFT | CS4270_TRANS_ZERO); | 588 | reg &= ~(CS4270_TRANS_SOFT | CS4270_TRANS_ZERO); |
770 | ret = cs4270_i2c_write(codec, CS4270_TRANS, reg); | 589 | ret = cs4270_i2c_write(codec, CS4270_TRANS, reg); |
771 | if (ret < 0) { | 590 | if (ret < 0) { |
772 | dev_err(&i2c_client->dev, "i2c write failed\n"); | 591 | dev_err(codec->dev, "i2c write failed\n"); |
773 | return ret; | 592 | return ret; |
774 | } | 593 | } |
775 | 594 | ||
776 | /* Initialize the DAI. Normally, we'd prefer to have a kmalloc'd DAI | 595 | /* Add the non-DAPM controls */ |
777 | * structure for each CS4270 device, but the machine driver needs to | 596 | ret = snd_soc_add_controls(codec, cs4270_snd_controls, |
778 | * have a pointer to the DAI structure, so for now it must be a global | 597 | ARRAY_SIZE(cs4270_snd_controls)); |
779 | * variable. | ||
780 | */ | ||
781 | cs4270_dai.dev = &i2c_client->dev; | ||
782 | |||
783 | /* Register the DAI. If all the other ASoC driver have already | ||
784 | * registered, then this will call our probe function, so | ||
785 | * cs4270_codec needs to be ready. | ||
786 | */ | ||
787 | cs4270_codec = codec; | ||
788 | ret = snd_soc_register_dai(&cs4270_dai); | ||
789 | if (ret < 0) { | 598 | if (ret < 0) { |
790 | dev_err(&i2c_client->dev, "failed to register DAIe\n"); | 599 | dev_err(codec->dev, "failed to add controls\n"); |
791 | goto error_free_codec; | 600 | return ret; |
792 | } | 601 | } |
793 | 602 | ||
794 | i2c_set_clientdata(i2c_client, cs4270); | 603 | /* get the power supply regulators */ |
604 | for (i = 0; i < ARRAY_SIZE(supply_names); i++) | ||
605 | cs4270->supplies[i].supply = supply_names[i]; | ||
606 | |||
607 | ret = regulator_bulk_get(codec->dev, ARRAY_SIZE(cs4270->supplies), | ||
608 | cs4270->supplies); | ||
609 | if (ret < 0) | ||
610 | return ret; | ||
611 | |||
612 | ret = regulator_bulk_enable(ARRAY_SIZE(cs4270->supplies), | ||
613 | cs4270->supplies); | ||
614 | if (ret < 0) | ||
615 | goto error_free_regulators; | ||
795 | 616 | ||
796 | return 0; | 617 | return 0; |
797 | 618 | ||
798 | error_free_codec: | 619 | error_free_regulators: |
799 | kfree(cs4270); | 620 | regulator_bulk_free(ARRAY_SIZE(cs4270->supplies), |
800 | cs4270_codec = NULL; | 621 | cs4270->supplies); |
801 | cs4270_dai.dev = NULL; | ||
802 | 622 | ||
803 | return ret; | 623 | return ret; |
804 | } | 624 | } |
805 | 625 | ||
806 | /** | 626 | /** |
807 | * cs4270_i2c_remove - remove an I2C device | 627 | * cs4270_remove - ASoC remove function |
808 | * @i2c_client: the I2C client object | 628 | * @pdev: platform device |
809 | * | 629 | * |
810 | * This function is the counterpart to cs4270_i2c_probe(). | 630 | * This function is the counterpart to cs4270_probe(). |
811 | */ | 631 | */ |
812 | static int cs4270_i2c_remove(struct i2c_client *i2c_client) | 632 | static int cs4270_remove(struct snd_soc_codec *codec) |
813 | { | 633 | { |
814 | struct cs4270_private *cs4270 = i2c_get_clientdata(i2c_client); | 634 | struct cs4270_private *cs4270 = snd_soc_codec_get_drvdata(codec); |
815 | 635 | ||
816 | kfree(cs4270); | 636 | regulator_bulk_disable(ARRAY_SIZE(cs4270->supplies), cs4270->supplies); |
817 | cs4270_codec = NULL; | 637 | regulator_bulk_free(ARRAY_SIZE(cs4270->supplies), cs4270->supplies); |
818 | cs4270_dai.dev = NULL; | ||
819 | 638 | ||
820 | return 0; | 639 | return 0; |
821 | } | ||
822 | |||
823 | /* | ||
824 | * cs4270_id - I2C device IDs supported by this driver | ||
825 | */ | ||
826 | static struct i2c_device_id cs4270_id[] = { | ||
827 | {"cs4270", 0}, | ||
828 | {} | ||
829 | }; | 640 | }; |
830 | MODULE_DEVICE_TABLE(i2c, cs4270_id); | ||
831 | 641 | ||
832 | #ifdef CONFIG_PM | 642 | #ifdef CONFIG_PM |
833 | 643 | ||
@@ -840,9 +650,8 @@ MODULE_DEVICE_TABLE(i2c, cs4270_id); | |||
840 | * and all registers are written back to the hardware when resuming. | 650 | * and all registers are written back to the hardware when resuming. |
841 | */ | 651 | */ |
842 | 652 | ||
843 | static int cs4270_soc_suspend(struct platform_device *pdev, pm_message_t mesg) | 653 | static int cs4270_soc_suspend(struct snd_soc_codec *codec, pm_message_t mesg) |
844 | { | 654 | { |
845 | struct snd_soc_codec *codec = cs4270_codec; | ||
846 | struct cs4270_private *cs4270 = snd_soc_codec_get_drvdata(codec); | 655 | struct cs4270_private *cs4270 = snd_soc_codec_get_drvdata(codec); |
847 | int reg, ret; | 656 | int reg, ret; |
848 | 657 | ||
@@ -860,9 +669,8 @@ static int cs4270_soc_suspend(struct platform_device *pdev, pm_message_t mesg) | |||
860 | return 0; | 669 | return 0; |
861 | } | 670 | } |
862 | 671 | ||
863 | static int cs4270_soc_resume(struct platform_device *pdev) | 672 | static int cs4270_soc_resume(struct snd_soc_codec *codec) |
864 | { | 673 | { |
865 | struct snd_soc_codec *codec = cs4270_codec; | ||
866 | struct cs4270_private *cs4270 = snd_soc_codec_get_drvdata(codec); | 674 | struct cs4270_private *cs4270 = snd_soc_codec_get_drvdata(codec); |
867 | struct i2c_client *i2c_client = codec->control_data; | 675 | struct i2c_client *i2c_client = codec->control_data; |
868 | int reg; | 676 | int reg; |
@@ -896,6 +704,95 @@ static int cs4270_soc_resume(struct platform_device *pdev) | |||
896 | #endif /* CONFIG_PM */ | 704 | #endif /* CONFIG_PM */ |
897 | 705 | ||
898 | /* | 706 | /* |
707 | * ASoC codec device structure | ||
708 | * | ||
709 | * Assign this variable to the codec_dev field of the machine driver's | ||
710 | * snd_soc_device structure. | ||
711 | */ | ||
712 | static struct snd_soc_codec_driver soc_codec_device_cs4270 = { | ||
713 | .probe = cs4270_probe, | ||
714 | .remove = cs4270_remove, | ||
715 | .suspend = cs4270_soc_suspend, | ||
716 | .resume = cs4270_soc_resume, | ||
717 | .read = cs4270_read_reg_cache, | ||
718 | .write = cs4270_i2c_write, | ||
719 | .reg_cache_size = CS4270_NUMREGS, | ||
720 | .reg_word_size = sizeof(u8), | ||
721 | }; | ||
722 | |||
723 | /** | ||
724 | * cs4270_i2c_probe - initialize the I2C interface of the CS4270 | ||
725 | * @i2c_client: the I2C client object | ||
726 | * @id: the I2C device ID (ignored) | ||
727 | * | ||
728 | * This function is called whenever the I2C subsystem finds a device that | ||
729 | * matches the device ID given via a prior call to i2c_add_driver(). | ||
730 | */ | ||
731 | static int cs4270_i2c_probe(struct i2c_client *i2c_client, | ||
732 | const struct i2c_device_id *id) | ||
733 | { | ||
734 | struct cs4270_private *cs4270; | ||
735 | int ret; | ||
736 | |||
737 | /* Verify that we have a CS4270 */ | ||
738 | |||
739 | ret = i2c_smbus_read_byte_data(i2c_client, CS4270_CHIPID); | ||
740 | if (ret < 0) { | ||
741 | dev_err(&i2c_client->dev, "failed to read i2c at addr %X\n", | ||
742 | i2c_client->addr); | ||
743 | return ret; | ||
744 | } | ||
745 | /* The top four bits of the chip ID should be 1100. */ | ||
746 | if ((ret & 0xF0) != 0xC0) { | ||
747 | dev_err(&i2c_client->dev, "device at addr %X is not a CS4270\n", | ||
748 | i2c_client->addr); | ||
749 | return -ENODEV; | ||
750 | } | ||
751 | |||
752 | dev_info(&i2c_client->dev, "found device at i2c address %X\n", | ||
753 | i2c_client->addr); | ||
754 | dev_info(&i2c_client->dev, "hardware revision %X\n", ret & 0xF); | ||
755 | |||
756 | cs4270 = kzalloc(sizeof(struct cs4270_private), GFP_KERNEL); | ||
757 | if (!cs4270) { | ||
758 | dev_err(&i2c_client->dev, "could not allocate codec\n"); | ||
759 | return -ENOMEM; | ||
760 | } | ||
761 | |||
762 | i2c_set_clientdata(i2c_client, cs4270); | ||
763 | cs4270->control_data = i2c_client; | ||
764 | cs4270->control_type = SND_SOC_I2C; | ||
765 | |||
766 | ret = snd_soc_register_codec(&i2c_client->dev, | ||
767 | &soc_codec_device_cs4270, &cs4270_dai, 1); | ||
768 | if (ret < 0) | ||
769 | kfree(cs4270); | ||
770 | return ret; | ||
771 | } | ||
772 | |||
773 | /** | ||
774 | * cs4270_i2c_remove - remove an I2C device | ||
775 | * @i2c_client: the I2C client object | ||
776 | * | ||
777 | * This function is the counterpart to cs4270_i2c_probe(). | ||
778 | */ | ||
779 | static int cs4270_i2c_remove(struct i2c_client *i2c_client) | ||
780 | { | ||
781 | snd_soc_unregister_codec(&i2c_client->dev); | ||
782 | kfree(i2c_get_clientdata(i2c_client)); | ||
783 | return 0; | ||
784 | } | ||
785 | |||
786 | /* | ||
787 | * cs4270_id - I2C device IDs supported by this driver | ||
788 | */ | ||
789 | static struct i2c_device_id cs4270_id[] = { | ||
790 | {"cs4270", 0}, | ||
791 | {} | ||
792 | }; | ||
793 | MODULE_DEVICE_TABLE(i2c, cs4270_id); | ||
794 | |||
795 | /* | ||
899 | * cs4270_i2c_driver - I2C device identification | 796 | * cs4270_i2c_driver - I2C device identification |
900 | * | 797 | * |
901 | * This structure tells the I2C subsystem how to identify and support a | 798 | * This structure tells the I2C subsystem how to identify and support a |
@@ -903,7 +800,7 @@ static int cs4270_soc_resume(struct platform_device *pdev) | |||
903 | */ | 800 | */ |
904 | static struct i2c_driver cs4270_i2c_driver = { | 801 | static struct i2c_driver cs4270_i2c_driver = { |
905 | .driver = { | 802 | .driver = { |
906 | .name = "cs4270", | 803 | .name = "cs4270-codec", |
907 | .owner = THIS_MODULE, | 804 | .owner = THIS_MODULE, |
908 | }, | 805 | }, |
909 | .id_table = cs4270_id, | 806 | .id_table = cs4270_id, |
@@ -911,20 +808,6 @@ static struct i2c_driver cs4270_i2c_driver = { | |||
911 | .remove = cs4270_i2c_remove, | 808 | .remove = cs4270_i2c_remove, |
912 | }; | 809 | }; |
913 | 810 | ||
914 | /* | ||
915 | * ASoC codec device structure | ||
916 | * | ||
917 | * Assign this variable to the codec_dev field of the machine driver's | ||
918 | * snd_soc_device structure. | ||
919 | */ | ||
920 | struct snd_soc_codec_device soc_codec_device_cs4270 = { | ||
921 | .probe = cs4270_probe, | ||
922 | .remove = cs4270_remove, | ||
923 | .suspend = cs4270_soc_suspend, | ||
924 | .resume = cs4270_soc_resume, | ||
925 | }; | ||
926 | EXPORT_SYMBOL_GPL(soc_codec_device_cs4270); | ||
927 | |||
928 | static int __init cs4270_init(void) | 811 | static int __init cs4270_init(void) |
929 | { | 812 | { |
930 | pr_info("Cirrus Logic CS4270 ALSA SoC Codec Driver\n"); | 813 | pr_info("Cirrus Logic CS4270 ALSA SoC Codec Driver\n"); |
diff --git a/sound/soc/codecs/cs4270.h b/sound/soc/codecs/cs4270.h deleted file mode 100644 index adc6cd9667d4..000000000000 --- a/sound/soc/codecs/cs4270.h +++ /dev/null | |||
@@ -1,28 +0,0 @@ | |||
1 | /* | ||
2 | * Cirrus Logic CS4270 ALSA SoC Codec Driver | ||
3 | * | ||
4 | * Author: Timur Tabi <timur@freescale.com> | ||
5 | * | ||
6 | * Copyright 2007 Freescale Semiconductor, Inc. This file is licensed under | ||
7 | * the terms of the GNU General Public License version 2. This program | ||
8 | * is licensed "as is" without any warranty of any kind, whether express | ||
9 | * or implied. | ||
10 | */ | ||
11 | |||
12 | #ifndef _CS4270_H | ||
13 | #define _CS4270_H | ||
14 | |||
15 | /* | ||
16 | * The ASoC codec DAI structure for the CS4270. Assign this structure to | ||
17 | * the .codec_dai field of your machine driver's snd_soc_dai_link structure. | ||
18 | */ | ||
19 | extern struct snd_soc_dai cs4270_dai; | ||
20 | |||
21 | /* | ||
22 | * The ASoC codec device structure for the CS4270. Assign this structure | ||
23 | * to the .codec_dev field of your machine driver's snd_soc_device | ||
24 | * structure. | ||
25 | */ | ||
26 | extern struct snd_soc_codec_device soc_codec_device_cs4270; | ||
27 | |||
28 | #endif | ||
diff --git a/sound/soc/codecs/cs42l51.c b/sound/soc/codecs/cs42l51.c index dd9b8550c402..8a25743870c2 100644 --- a/sound/soc/codecs/cs42l51.c +++ b/sound/soc/codecs/cs42l51.c | |||
@@ -42,15 +42,14 @@ enum master_slave_mode { | |||
42 | }; | 42 | }; |
43 | 43 | ||
44 | struct cs42l51_private { | 44 | struct cs42l51_private { |
45 | enum snd_soc_control_type control_type; | ||
46 | void *control_data; | ||
45 | unsigned int mclk; | 47 | unsigned int mclk; |
46 | unsigned int audio_mode; /* The mode (I2S or left-justified) */ | 48 | unsigned int audio_mode; /* The mode (I2S or left-justified) */ |
47 | enum master_slave_mode func; | 49 | enum master_slave_mode func; |
48 | struct snd_soc_codec codec; | ||
49 | u8 reg_cache[CS42L51_NUMREGS]; | 50 | u8 reg_cache[CS42L51_NUMREGS]; |
50 | }; | 51 | }; |
51 | 52 | ||
52 | static struct snd_soc_codec *cs42l51_codec; | ||
53 | |||
54 | #define CS42L51_FORMATS ( \ | 53 | #define CS42L51_FORMATS ( \ |
55 | SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S16_BE | \ | 54 | SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S16_BE | \ |
56 | SNDRV_PCM_FMTBIT_S18_3LE | SNDRV_PCM_FMTBIT_S18_3BE | \ | 55 | SNDRV_PCM_FMTBIT_S18_3LE | SNDRV_PCM_FMTBIT_S18_3BE | \ |
@@ -75,134 +74,6 @@ static int cs42l51_fill_cache(struct snd_soc_codec *codec) | |||
75 | return 0; | 74 | return 0; |
76 | } | 75 | } |
77 | 76 | ||
78 | static int cs42l51_i2c_probe(struct i2c_client *i2c_client, | ||
79 | const struct i2c_device_id *id) | ||
80 | { | ||
81 | struct snd_soc_codec *codec; | ||
82 | struct cs42l51_private *cs42l51; | ||
83 | int ret = 0; | ||
84 | int reg; | ||
85 | |||
86 | if (cs42l51_codec) | ||
87 | return -EBUSY; | ||
88 | |||
89 | /* Verify that we have a CS42L51 */ | ||
90 | ret = i2c_smbus_read_byte_data(i2c_client, CS42L51_CHIP_REV_ID); | ||
91 | if (ret < 0) { | ||
92 | dev_err(&i2c_client->dev, "failed to read I2C\n"); | ||
93 | goto error; | ||
94 | } | ||
95 | |||
96 | if ((ret != CS42L51_MK_CHIP_REV(CS42L51_CHIP_ID, CS42L51_CHIP_REV_A)) && | ||
97 | (ret != CS42L51_MK_CHIP_REV(CS42L51_CHIP_ID, CS42L51_CHIP_REV_B))) { | ||
98 | dev_err(&i2c_client->dev, "Invalid chip id\n"); | ||
99 | ret = -ENODEV; | ||
100 | goto error; | ||
101 | } | ||
102 | |||
103 | dev_info(&i2c_client->dev, "found device cs42l51 rev %d\n", | ||
104 | ret & 7); | ||
105 | |||
106 | cs42l51 = kzalloc(sizeof(struct cs42l51_private), GFP_KERNEL); | ||
107 | if (!cs42l51) { | ||
108 | dev_err(&i2c_client->dev, "could not allocate codec\n"); | ||
109 | return -ENOMEM; | ||
110 | } | ||
111 | codec = &cs42l51->codec; | ||
112 | |||
113 | mutex_init(&codec->mutex); | ||
114 | INIT_LIST_HEAD(&codec->dapm_widgets); | ||
115 | INIT_LIST_HEAD(&codec->dapm_paths); | ||
116 | |||
117 | codec->dev = &i2c_client->dev; | ||
118 | codec->name = "CS42L51"; | ||
119 | codec->owner = THIS_MODULE; | ||
120 | codec->dai = &cs42l51_dai; | ||
121 | codec->num_dai = 1; | ||
122 | snd_soc_codec_set_drvdata(codec, cs42l51); | ||
123 | |||
124 | codec->control_data = i2c_client; | ||
125 | codec->reg_cache = cs42l51->reg_cache; | ||
126 | codec->reg_cache_size = CS42L51_NUMREGS; | ||
127 | i2c_set_clientdata(i2c_client, codec); | ||
128 | |||
129 | ret = cs42l51_fill_cache(codec); | ||
130 | if (ret < 0) { | ||
131 | dev_err(&i2c_client->dev, "failed to fill register cache\n"); | ||
132 | goto error_alloc; | ||
133 | } | ||
134 | |||
135 | ret = snd_soc_codec_set_cache_io(codec, 8, 8, SND_SOC_I2C); | ||
136 | if (ret < 0) { | ||
137 | dev_err(&i2c_client->dev, "Failed to set cache I/O: %d\n", ret); | ||
138 | goto error_alloc; | ||
139 | } | ||
140 | |||
141 | /* | ||
142 | * DAC configuration | ||
143 | * - Use signal processor | ||
144 | * - auto mute | ||
145 | * - vol changes immediate | ||
146 | * - no de-emphasize | ||
147 | */ | ||
148 | reg = CS42L51_DAC_CTL_DATA_SEL(1) | ||
149 | | CS42L51_DAC_CTL_AMUTE | CS42L51_DAC_CTL_DACSZ(0); | ||
150 | ret = snd_soc_write(codec, CS42L51_DAC_CTL, reg); | ||
151 | if (ret < 0) | ||
152 | goto error_alloc; | ||
153 | |||
154 | cs42l51_dai.dev = codec->dev; | ||
155 | cs42l51_codec = codec; | ||
156 | |||
157 | ret = snd_soc_register_codec(codec); | ||
158 | if (ret != 0) { | ||
159 | dev_err(codec->dev, "Failed to register codec: %d\n", ret); | ||
160 | goto error_alloc; | ||
161 | } | ||
162 | |||
163 | ret = snd_soc_register_dai(&cs42l51_dai); | ||
164 | if (ret < 0) { | ||
165 | dev_err(&i2c_client->dev, "failed to register DAIe\n"); | ||
166 | goto error_reg; | ||
167 | } | ||
168 | |||
169 | return 0; | ||
170 | |||
171 | error_reg: | ||
172 | snd_soc_unregister_codec(codec); | ||
173 | error_alloc: | ||
174 | kfree(cs42l51); | ||
175 | error: | ||
176 | return ret; | ||
177 | } | ||
178 | |||
179 | static int cs42l51_i2c_remove(struct i2c_client *client) | ||
180 | { | ||
181 | struct cs42l51_private *cs42l51 = i2c_get_clientdata(client); | ||
182 | snd_soc_unregister_dai(&cs42l51_dai); | ||
183 | snd_soc_unregister_codec(cs42l51_codec); | ||
184 | cs42l51_codec = NULL; | ||
185 | kfree(cs42l51); | ||
186 | return 0; | ||
187 | } | ||
188 | |||
189 | |||
190 | static const struct i2c_device_id cs42l51_id[] = { | ||
191 | {"cs42l51", 0}, | ||
192 | {} | ||
193 | }; | ||
194 | MODULE_DEVICE_TABLE(i2c, cs42l51_id); | ||
195 | |||
196 | static struct i2c_driver cs42l51_i2c_driver = { | ||
197 | .driver = { | ||
198 | .name = "CS42L51 I2C", | ||
199 | .owner = THIS_MODULE, | ||
200 | }, | ||
201 | .id_table = cs42l51_id, | ||
202 | .probe = cs42l51_i2c_probe, | ||
203 | .remove = cs42l51_i2c_remove, | ||
204 | }; | ||
205 | |||
206 | static int cs42l51_get_chan_mix(struct snd_kcontrol *kcontrol, | 77 | static int cs42l51_get_chan_mix(struct snd_kcontrol *kcontrol, |
207 | struct snd_ctl_elem_value *ucontrol) | 78 | struct snd_ctl_elem_value *ucontrol) |
208 | { | 79 | { |
@@ -484,51 +355,8 @@ static int cs42l51_set_dai_sysclk(struct snd_soc_dai *codec_dai, | |||
484 | { | 355 | { |
485 | struct snd_soc_codec *codec = codec_dai->codec; | 356 | struct snd_soc_codec *codec = codec_dai->codec; |
486 | struct cs42l51_private *cs42l51 = snd_soc_codec_get_drvdata(codec); | 357 | struct cs42l51_private *cs42l51 = snd_soc_codec_get_drvdata(codec); |
487 | struct cs42l51_ratios *ratios = NULL; | ||
488 | int nr_ratios = 0; | ||
489 | unsigned int rates = 0; | ||
490 | unsigned int rate_min = -1; | ||
491 | unsigned int rate_max = 0; | ||
492 | int i; | ||
493 | 358 | ||
494 | cs42l51->mclk = freq; | 359 | cs42l51->mclk = freq; |
495 | |||
496 | switch (cs42l51->func) { | ||
497 | case MODE_MASTER: | ||
498 | return -EINVAL; | ||
499 | case MODE_SLAVE: | ||
500 | ratios = slave_ratios; | ||
501 | nr_ratios = ARRAY_SIZE(slave_ratios); | ||
502 | break; | ||
503 | case MODE_SLAVE_AUTO: | ||
504 | ratios = slave_auto_ratios; | ||
505 | nr_ratios = ARRAY_SIZE(slave_auto_ratios); | ||
506 | break; | ||
507 | } | ||
508 | |||
509 | for (i = 0; i < nr_ratios; i++) { | ||
510 | unsigned int rate = freq / ratios[i].ratio; | ||
511 | rates |= snd_pcm_rate_to_rate_bit(rate); | ||
512 | if (rate < rate_min) | ||
513 | rate_min = rate; | ||
514 | if (rate > rate_max) | ||
515 | rate_max = rate; | ||
516 | } | ||
517 | rates &= ~SNDRV_PCM_RATE_KNOT; | ||
518 | |||
519 | if (!rates) { | ||
520 | dev_err(codec->dev, "could not find a valid sample rate\n"); | ||
521 | return -EINVAL; | ||
522 | } | ||
523 | |||
524 | codec_dai->playback.rates = rates; | ||
525 | codec_dai->playback.rate_min = rate_min; | ||
526 | codec_dai->playback.rate_max = rate_max; | ||
527 | |||
528 | codec_dai->capture.rates = rates; | ||
529 | codec_dai->capture.rate_min = rate_min; | ||
530 | codec_dai->capture.rate_max = rate_max; | ||
531 | |||
532 | return 0; | 360 | return 0; |
533 | } | 361 | } |
534 | 362 | ||
@@ -537,8 +365,7 @@ static int cs42l51_hw_params(struct snd_pcm_substream *substream, | |||
537 | struct snd_soc_dai *dai) | 365 | struct snd_soc_dai *dai) |
538 | { | 366 | { |
539 | struct snd_soc_pcm_runtime *rtd = substream->private_data; | 367 | struct snd_soc_pcm_runtime *rtd = substream->private_data; |
540 | struct snd_soc_device *socdev = rtd->socdev; | 368 | struct snd_soc_codec *codec = rtd->codec; |
541 | struct snd_soc_codec *codec = socdev->card->codec; | ||
542 | struct cs42l51_private *cs42l51 = snd_soc_codec_get_drvdata(codec); | 369 | struct cs42l51_private *cs42l51 = snd_soc_codec_get_drvdata(codec); |
543 | int ret; | 370 | int ret; |
544 | unsigned int i; | 371 | unsigned int i; |
@@ -670,8 +497,8 @@ static struct snd_soc_dai_ops cs42l51_dai_ops = { | |||
670 | .digital_mute = cs42l51_dai_mute, | 497 | .digital_mute = cs42l51_dai_mute, |
671 | }; | 498 | }; |
672 | 499 | ||
673 | struct snd_soc_dai cs42l51_dai = { | 500 | static struct snd_soc_dai_driver cs42l51_dai = { |
674 | .name = "CS42L51 HiFi", | 501 | .name = "cs42l51-hifi", |
675 | .playback = { | 502 | .playback = { |
676 | .stream_name = "Playback", | 503 | .stream_name = "Playback", |
677 | .channels_min = 1, | 504 | .channels_min = 1, |
@@ -688,30 +515,39 @@ struct snd_soc_dai cs42l51_dai = { | |||
688 | }, | 515 | }, |
689 | .ops = &cs42l51_dai_ops, | 516 | .ops = &cs42l51_dai_ops, |
690 | }; | 517 | }; |
691 | EXPORT_SYMBOL_GPL(cs42l51_dai); | ||
692 | |||
693 | 518 | ||
694 | static int cs42l51_probe(struct platform_device *pdev) | 519 | static int cs42l51_probe(struct snd_soc_codec *codec) |
695 | { | 520 | { |
696 | struct snd_soc_device *socdev = platform_get_drvdata(pdev); | 521 | struct cs42l51_private *cs42l51 = snd_soc_codec_get_drvdata(codec); |
697 | struct snd_soc_codec *codec; | 522 | int ret, reg; |
698 | int ret = 0; | ||
699 | 523 | ||
700 | if (!cs42l51_codec) { | 524 | codec->control_data = cs42l51->control_data; |
701 | dev_err(&pdev->dev, "CS42L51 codec not yet registered\n"); | ||
702 | return -EINVAL; | ||
703 | } | ||
704 | 525 | ||
705 | socdev->card->codec = cs42l51_codec; | 526 | ret = cs42l51_fill_cache(codec); |
706 | codec = socdev->card->codec; | 527 | if (ret < 0) { |
528 | dev_err(codec->dev, "failed to fill register cache\n"); | ||
529 | return ret; | ||
530 | } | ||
707 | 531 | ||
708 | /* Register PCMs */ | 532 | ret = snd_soc_codec_set_cache_io(codec, 8, 8, cs42l51->control_type); |
709 | ret = snd_soc_new_pcms(socdev, SNDRV_DEFAULT_IDX1, SNDRV_DEFAULT_STR1); | ||
710 | if (ret < 0) { | 533 | if (ret < 0) { |
711 | dev_err(&pdev->dev, "failed to create PCMs\n"); | 534 | dev_err(codec->dev, "Failed to set cache I/O: %d\n", ret); |
712 | return ret; | 535 | return ret; |
713 | } | 536 | } |
714 | 537 | ||
538 | /* | ||
539 | * DAC configuration | ||
540 | * - Use signal processor | ||
541 | * - auto mute | ||
542 | * - vol changes immediate | ||
543 | * - no de-emphasize | ||
544 | */ | ||
545 | reg = CS42L51_DAC_CTL_DATA_SEL(1) | ||
546 | | CS42L51_DAC_CTL_AMUTE | CS42L51_DAC_CTL_DACSZ(0); | ||
547 | ret = snd_soc_write(codec, CS42L51_DAC_CTL, reg); | ||
548 | if (ret < 0) | ||
549 | return ret; | ||
550 | |||
715 | snd_soc_add_controls(codec, cs42l51_snd_controls, | 551 | snd_soc_add_controls(codec, cs42l51_snd_controls, |
716 | ARRAY_SIZE(cs42l51_snd_controls)); | 552 | ARRAY_SIZE(cs42l51_snd_controls)); |
717 | snd_soc_dapm_new_controls(codec, cs42l51_dapm_widgets, | 553 | snd_soc_dapm_new_controls(codec, cs42l51_dapm_widgets, |
@@ -722,22 +558,77 @@ static int cs42l51_probe(struct platform_device *pdev) | |||
722 | return 0; | 558 | return 0; |
723 | } | 559 | } |
724 | 560 | ||
561 | static struct snd_soc_codec_driver soc_codec_device_cs42l51 = { | ||
562 | .probe = cs42l51_probe, | ||
563 | .reg_cache_size = CS42L51_NUMREGS, | ||
564 | .reg_word_size = sizeof(u8), | ||
565 | }; | ||
725 | 566 | ||
726 | static int cs42l51_remove(struct platform_device *pdev) | 567 | static int cs42l51_i2c_probe(struct i2c_client *i2c_client, |
568 | const struct i2c_device_id *id) | ||
727 | { | 569 | { |
728 | struct snd_soc_device *socdev = platform_get_drvdata(pdev); | 570 | struct cs42l51_private *cs42l51; |
571 | int ret; | ||
729 | 572 | ||
730 | snd_soc_free_pcms(socdev); | 573 | /* Verify that we have a CS42L51 */ |
731 | snd_soc_dapm_free(socdev); | 574 | ret = i2c_smbus_read_byte_data(i2c_client, CS42L51_CHIP_REV_ID); |
575 | if (ret < 0) { | ||
576 | dev_err(&i2c_client->dev, "failed to read I2C\n"); | ||
577 | goto error; | ||
578 | } | ||
579 | |||
580 | if ((ret != CS42L51_MK_CHIP_REV(CS42L51_CHIP_ID, CS42L51_CHIP_REV_A)) && | ||
581 | (ret != CS42L51_MK_CHIP_REV(CS42L51_CHIP_ID, CS42L51_CHIP_REV_B))) { | ||
582 | dev_err(&i2c_client->dev, "Invalid chip id\n"); | ||
583 | ret = -ENODEV; | ||
584 | goto error; | ||
585 | } | ||
586 | |||
587 | dev_info(&i2c_client->dev, "found device cs42l51 rev %d\n", | ||
588 | ret & 7); | ||
589 | |||
590 | cs42l51 = kzalloc(sizeof(struct cs42l51_private), GFP_KERNEL); | ||
591 | if (!cs42l51) { | ||
592 | dev_err(&i2c_client->dev, "could not allocate codec\n"); | ||
593 | return -ENOMEM; | ||
594 | } | ||
595 | |||
596 | i2c_set_clientdata(i2c_client, cs42l51); | ||
597 | cs42l51->control_data = i2c_client; | ||
598 | cs42l51->control_type = SND_SOC_I2C; | ||
732 | 599 | ||
600 | ret = snd_soc_register_codec(&i2c_client->dev, | ||
601 | &soc_codec_device_cs42l51, &cs42l51_dai, 1); | ||
602 | if (ret < 0) | ||
603 | kfree(cs42l51); | ||
604 | error: | ||
605 | return ret; | ||
606 | } | ||
607 | |||
608 | static int cs42l51_i2c_remove(struct i2c_client *client) | ||
609 | { | ||
610 | struct cs42l51_private *cs42l51 = i2c_get_clientdata(client); | ||
611 | |||
612 | snd_soc_unregister_codec(&client->dev); | ||
613 | kfree(cs42l51); | ||
733 | return 0; | 614 | return 0; |
734 | } | 615 | } |
735 | 616 | ||
736 | struct snd_soc_codec_device soc_codec_device_cs42l51 = { | 617 | static const struct i2c_device_id cs42l51_id[] = { |
737 | .probe = cs42l51_probe, | 618 | {"cs42l51", 0}, |
738 | .remove = cs42l51_remove | 619 | {} |
620 | }; | ||
621 | MODULE_DEVICE_TABLE(i2c, cs42l51_id); | ||
622 | |||
623 | static struct i2c_driver cs42l51_i2c_driver = { | ||
624 | .driver = { | ||
625 | .name = "cs42L51-codec", | ||
626 | .owner = THIS_MODULE, | ||
627 | }, | ||
628 | .id_table = cs42l51_id, | ||
629 | .probe = cs42l51_i2c_probe, | ||
630 | .remove = cs42l51_i2c_remove, | ||
739 | }; | 631 | }; |
740 | EXPORT_SYMBOL_GPL(soc_codec_device_cs42l51); | ||
741 | 632 | ||
742 | static int __init cs42l51_init(void) | 633 | static int __init cs42l51_init(void) |
743 | { | 634 | { |
diff --git a/sound/soc/codecs/cs42l51.h b/sound/soc/codecs/cs42l51.h index 8f0bd9786ad2..2beeb171db4b 100644 --- a/sound/soc/codecs/cs42l51.h +++ b/sound/soc/codecs/cs42l51.h | |||
@@ -158,6 +158,4 @@ | |||
158 | #define CS42L51_LASTREG 0x20 | 158 | #define CS42L51_LASTREG 0x20 |
159 | #define CS42L51_NUMREGS (CS42L51_LASTREG - CS42L51_FIRSTREG + 1) | 159 | #define CS42L51_NUMREGS (CS42L51_LASTREG - CS42L51_FIRSTREG + 1) |
160 | 160 | ||
161 | extern struct snd_soc_dai cs42l51_dai; | ||
162 | extern struct snd_soc_codec_device soc_codec_device_cs42l51; | ||
163 | #endif | 161 | #endif |
diff --git a/sound/soc/codecs/cx20442.c b/sound/soc/codecs/cx20442.c index f07a415c753f..cf4323dbf9c4 100644 --- a/sound/soc/codecs/cx20442.c +++ b/sound/soc/codecs/cx20442.c | |||
@@ -24,7 +24,8 @@ | |||
24 | 24 | ||
25 | 25 | ||
26 | struct cx20442_priv { | 26 | struct cx20442_priv { |
27 | struct snd_soc_codec codec; | 27 | enum snd_soc_control_type control_type; |
28 | void *control_data; | ||
28 | u8 reg_cache[1]; | 29 | u8 reg_cache[1]; |
29 | }; | 30 | }; |
30 | 31 | ||
@@ -102,7 +103,7 @@ static unsigned int cx20442_read_reg_cache(struct snd_soc_codec *codec, | |||
102 | { | 103 | { |
103 | u8 *reg_cache = codec->reg_cache; | 104 | u8 *reg_cache = codec->reg_cache; |
104 | 105 | ||
105 | if (reg >= codec->reg_cache_size) | 106 | if (reg >= codec->driver->reg_cache_size) |
106 | return -EINVAL; | 107 | return -EINVAL; |
107 | 108 | ||
108 | return reg_cache[reg]; | 109 | return reg_cache[reg]; |
@@ -164,16 +165,17 @@ static int cx20442_pm_to_v253_vsp(u8 value) | |||
164 | static int cx20442_write(struct snd_soc_codec *codec, unsigned int reg, | 165 | static int cx20442_write(struct snd_soc_codec *codec, unsigned int reg, |
165 | unsigned int value) | 166 | unsigned int value) |
166 | { | 167 | { |
168 | struct cx20442_priv *cx20442 = snd_soc_codec_get_drvdata(codec); | ||
167 | u8 *reg_cache = codec->reg_cache; | 169 | u8 *reg_cache = codec->reg_cache; |
168 | int vls, vsp, old, len; | 170 | int vls, vsp, old, len; |
169 | char buf[18]; | 171 | char buf[18]; |
170 | 172 | ||
171 | if (reg >= codec->reg_cache_size) | 173 | if (reg >= codec->driver->reg_cache_size) |
172 | return -EINVAL; | 174 | return -EINVAL; |
173 | 175 | ||
174 | /* hw_write and control_data pointers required for talking to the modem | 176 | /* hw_write and control_data pointers required for talking to the modem |
175 | * are expected to be set by the line discipline initialization code */ | 177 | * are expected to be set by the line discipline initialization code */ |
176 | if (!codec->hw_write || !codec->control_data) | 178 | if (!codec->hw_write || !cx20442->control_data) |
177 | return -EIO; | 179 | return -EIO; |
178 | 180 | ||
179 | old = reg_cache[reg]; | 181 | old = reg_cache[reg]; |
@@ -202,17 +204,13 @@ static int cx20442_write(struct snd_soc_codec *codec, unsigned int reg, | |||
202 | return -ENOMEM; | 204 | return -ENOMEM; |
203 | 205 | ||
204 | dev_dbg(codec->dev, "%s: %s\n", __func__, buf); | 206 | dev_dbg(codec->dev, "%s: %s\n", __func__, buf); |
205 | if (codec->hw_write(codec->control_data, buf, len) != len) | 207 | if (codec->hw_write(cx20442->control_data, buf, len) != len) |
206 | return -EIO; | 208 | return -EIO; |
207 | 209 | ||
208 | return 0; | 210 | return 0; |
209 | } | 211 | } |
210 | 212 | ||
211 | 213 | ||
212 | /* Moved up here as line discipline referres it during initialization */ | ||
213 | static struct snd_soc_codec *cx20442_codec; | ||
214 | |||
215 | |||
216 | /* | 214 | /* |
217 | * Line discpline related code | 215 | * Line discpline related code |
218 | * | 216 | * |
@@ -228,15 +226,15 @@ static const char *v253_init = "ate0m0q0+fclass=8\r"; | |||
228 | /* Line discipline .open() */ | 226 | /* Line discipline .open() */ |
229 | static int v253_open(struct tty_struct *tty) | 227 | static int v253_open(struct tty_struct *tty) |
230 | { | 228 | { |
231 | struct snd_soc_codec *codec = cx20442_codec; | ||
232 | int ret, len = strlen(v253_init); | 229 | int ret, len = strlen(v253_init); |
233 | 230 | ||
234 | /* Doesn't make sense without write callback */ | 231 | /* Doesn't make sense without write callback */ |
235 | if (!tty->ops->write) | 232 | if (!tty->ops->write) |
236 | return -EINVAL; | 233 | return -EINVAL; |
237 | 234 | ||
238 | /* Pass the codec structure address for use by other ldisc callbacks */ | 235 | /* Won't work if no codec pointer has been passed by a card driver */ |
239 | tty->disc_data = codec; | 236 | if (!tty->disc_data) |
237 | return -ENODEV; | ||
240 | 238 | ||
241 | if (tty->ops->write(tty, v253_init, len) != len) { | 239 | if (tty->ops->write(tty, v253_init, len) != len) { |
242 | ret = -EIO; | 240 | ret = -EIO; |
@@ -253,15 +251,18 @@ err: | |||
253 | static void v253_close(struct tty_struct *tty) | 251 | static void v253_close(struct tty_struct *tty) |
254 | { | 252 | { |
255 | struct snd_soc_codec *codec = tty->disc_data; | 253 | struct snd_soc_codec *codec = tty->disc_data; |
254 | struct cx20442_priv *cx20442; | ||
256 | 255 | ||
257 | tty->disc_data = NULL; | 256 | tty->disc_data = NULL; |
258 | 257 | ||
259 | if (!codec) | 258 | if (!codec) |
260 | return; | 259 | return; |
261 | 260 | ||
261 | cx20442 = snd_soc_codec_get_drvdata(codec); | ||
262 | |||
262 | /* Prevent the codec driver from further accessing the modem */ | 263 | /* Prevent the codec driver from further accessing the modem */ |
263 | codec->hw_write = NULL; | 264 | codec->hw_write = NULL; |
264 | codec->control_data = NULL; | 265 | cx20442->control_data = NULL; |
265 | codec->pop_time = 0; | 266 | codec->pop_time = 0; |
266 | } | 267 | } |
267 | 268 | ||
@@ -277,15 +278,18 @@ static void v253_receive(struct tty_struct *tty, | |||
277 | const unsigned char *cp, char *fp, int count) | 278 | const unsigned char *cp, char *fp, int count) |
278 | { | 279 | { |
279 | struct snd_soc_codec *codec = tty->disc_data; | 280 | struct snd_soc_codec *codec = tty->disc_data; |
281 | struct cx20442_priv *cx20442; | ||
280 | 282 | ||
281 | if (!codec) | 283 | if (!codec) |
282 | return; | 284 | return; |
283 | 285 | ||
284 | if (!codec->control_data) { | 286 | cx20442 = snd_soc_codec_get_drvdata(codec); |
287 | |||
288 | if (!cx20442->control_data) { | ||
285 | /* First modem response, complete setup procedure */ | 289 | /* First modem response, complete setup procedure */ |
286 | 290 | ||
287 | /* Set up codec driver access to modem controls */ | 291 | /* Set up codec driver access to modem controls */ |
288 | codec->control_data = tty; | 292 | cx20442->control_data = tty; |
289 | codec->hw_write = (hw_write_t)tty->ops->write; | 293 | codec->hw_write = (hw_write_t)tty->ops->write; |
290 | codec->pop_time = 1; | 294 | codec->pop_time = 1; |
291 | } | 295 | } |
@@ -313,8 +317,8 @@ EXPORT_SYMBOL_GPL(v253_ops); | |||
313 | * Codec DAI | 317 | * Codec DAI |
314 | */ | 318 | */ |
315 | 319 | ||
316 | struct snd_soc_dai cx20442_dai = { | 320 | static struct snd_soc_dai_driver cx20442_dai = { |
317 | .name = "CX20442", | 321 | .name = "cx20442-hifi", |
318 | .playback = { | 322 | .playback = { |
319 | .stream_name = "Playback", | 323 | .stream_name = "Playback", |
320 | .channels_min = 1, | 324 | .channels_min = 1, |
@@ -330,142 +334,63 @@ struct snd_soc_dai cx20442_dai = { | |||
330 | .formats = SNDRV_PCM_FMTBIT_S16_LE, | 334 | .formats = SNDRV_PCM_FMTBIT_S16_LE, |
331 | }, | 335 | }, |
332 | }; | 336 | }; |
333 | EXPORT_SYMBOL_GPL(cx20442_dai); | ||
334 | 337 | ||
335 | static int cx20442_codec_probe(struct platform_device *pdev) | 338 | static int cx20442_codec_probe(struct snd_soc_codec *codec) |
336 | { | 339 | { |
337 | struct snd_soc_device *socdev = platform_get_drvdata(pdev); | 340 | struct cx20442_priv *cx20442; |
338 | struct snd_soc_codec *codec; | ||
339 | int ret; | ||
340 | |||
341 | if (!cx20442_codec) { | ||
342 | dev_err(&pdev->dev, "cx20442 not yet discovered\n"); | ||
343 | return -ENODEV; | ||
344 | } | ||
345 | codec = cx20442_codec; | ||
346 | |||
347 | socdev->card->codec = codec; | ||
348 | 341 | ||
349 | /* register pcms */ | 342 | cx20442 = kzalloc(sizeof(struct cx20442_priv), GFP_KERNEL); |
350 | ret = snd_soc_new_pcms(socdev, SNDRV_DEFAULT_IDX1, SNDRV_DEFAULT_STR1); | 343 | if (cx20442 == NULL) |
351 | if (ret < 0) { | 344 | return -ENOMEM; |
352 | dev_err(&pdev->dev, "failed to create pcms\n"); | 345 | snd_soc_codec_set_drvdata(codec, cx20442); |
353 | goto pcm_err; | ||
354 | } | ||
355 | 346 | ||
356 | cx20442_add_widgets(codec); | 347 | cx20442_add_widgets(codec); |
357 | 348 | ||
358 | pcm_err: | 349 | cx20442->control_data = NULL; |
359 | return ret; | 350 | codec->hw_write = NULL; |
351 | codec->pop_time = 0; | ||
352 | |||
353 | return 0; | ||
360 | } | 354 | } |
361 | 355 | ||
362 | /* power down chip */ | 356 | /* power down chip */ |
363 | static int cx20442_codec_remove(struct platform_device *pdev) | 357 | static int cx20442_codec_remove(struct snd_soc_codec *codec) |
364 | { | 358 | { |
365 | struct snd_soc_device *socdev = platform_get_drvdata(pdev); | 359 | struct cx20442_priv *cx20442 = snd_soc_codec_get_drvdata(codec); |
366 | 360 | ||
367 | snd_soc_free_pcms(socdev); | 361 | if (cx20442->control_data) { |
368 | snd_soc_dapm_free(socdev); | 362 | struct tty_struct *tty = cx20442->control_data; |
363 | tty_hangup(tty); | ||
364 | } | ||
369 | 365 | ||
366 | kfree(cx20442); | ||
370 | return 0; | 367 | return 0; |
371 | } | 368 | } |
372 | 369 | ||
373 | struct snd_soc_codec_device cx20442_codec_dev = { | 370 | static struct snd_soc_codec_driver cx20442_codec_dev = { |
374 | .probe = cx20442_codec_probe, | 371 | .probe = cx20442_codec_probe, |
375 | .remove = cx20442_codec_remove, | 372 | .remove = cx20442_codec_remove, |
373 | .reg_cache_size = 1, | ||
374 | .reg_word_size = sizeof(u8), | ||
375 | .read = cx20442_read_reg_cache, | ||
376 | .write = cx20442_write, | ||
376 | }; | 377 | }; |
377 | EXPORT_SYMBOL_GPL(cx20442_codec_dev); | ||
378 | |||
379 | static int cx20442_register(struct cx20442_priv *cx20442) | ||
380 | { | ||
381 | struct snd_soc_codec *codec = &cx20442->codec; | ||
382 | int ret; | ||
383 | |||
384 | mutex_init(&codec->mutex); | ||
385 | INIT_LIST_HEAD(&codec->dapm_widgets); | ||
386 | INIT_LIST_HEAD(&codec->dapm_paths); | ||
387 | |||
388 | codec->name = "CX20442"; | ||
389 | codec->owner = THIS_MODULE; | ||
390 | snd_soc_codec_set_drvdata(codec, cx20442); | ||
391 | |||
392 | codec->dai = &cx20442_dai; | ||
393 | codec->num_dai = 1; | ||
394 | |||
395 | codec->reg_cache = &cx20442->reg_cache; | ||
396 | codec->reg_cache_size = ARRAY_SIZE(cx20442->reg_cache); | ||
397 | codec->read = cx20442_read_reg_cache; | ||
398 | codec->write = cx20442_write; | ||
399 | |||
400 | codec->bias_level = SND_SOC_BIAS_OFF; | ||
401 | |||
402 | cx20442_dai.dev = codec->dev; | ||
403 | |||
404 | cx20442_codec = codec; | ||
405 | |||
406 | ret = snd_soc_register_codec(codec); | ||
407 | if (ret != 0) { | ||
408 | dev_err(codec->dev, "Failed to register codec: %d\n", ret); | ||
409 | goto err; | ||
410 | } | ||
411 | |||
412 | ret = snd_soc_register_dai(&cx20442_dai); | ||
413 | if (ret != 0) { | ||
414 | dev_err(codec->dev, "Failed to register DAI: %d\n", ret); | ||
415 | goto err_codec; | ||
416 | } | ||
417 | |||
418 | return 0; | ||
419 | |||
420 | err_codec: | ||
421 | snd_soc_unregister_codec(codec); | ||
422 | err: | ||
423 | cx20442_codec = NULL; | ||
424 | kfree(cx20442); | ||
425 | return ret; | ||
426 | } | ||
427 | |||
428 | static void cx20442_unregister(struct cx20442_priv *cx20442) | ||
429 | { | ||
430 | snd_soc_unregister_dai(&cx20442_dai); | ||
431 | snd_soc_unregister_codec(&cx20442->codec); | ||
432 | |||
433 | cx20442_codec = NULL; | ||
434 | kfree(cx20442); | ||
435 | } | ||
436 | 378 | ||
437 | static int cx20442_platform_probe(struct platform_device *pdev) | 379 | static int cx20442_platform_probe(struct platform_device *pdev) |
438 | { | 380 | { |
439 | struct cx20442_priv *cx20442; | 381 | return snd_soc_register_codec(&pdev->dev, |
440 | struct snd_soc_codec *codec; | 382 | &cx20442_codec_dev, &cx20442_dai, 1); |
441 | |||
442 | cx20442 = kzalloc(sizeof(struct cx20442_priv), GFP_KERNEL); | ||
443 | if (cx20442 == NULL) | ||
444 | return -ENOMEM; | ||
445 | |||
446 | codec = &cx20442->codec; | ||
447 | |||
448 | codec->control_data = NULL; | ||
449 | codec->hw_write = NULL; | ||
450 | codec->pop_time = 0; | ||
451 | |||
452 | codec->dev = &pdev->dev; | ||
453 | platform_set_drvdata(pdev, cx20442); | ||
454 | |||
455 | return cx20442_register(cx20442); | ||
456 | } | 383 | } |
457 | 384 | ||
458 | static int __exit cx20442_platform_remove(struct platform_device *pdev) | 385 | static int __exit cx20442_platform_remove(struct platform_device *pdev) |
459 | { | 386 | { |
460 | struct cx20442_priv *cx20442 = platform_get_drvdata(pdev); | 387 | snd_soc_unregister_codec(&pdev->dev); |
461 | |||
462 | cx20442_unregister(cx20442); | ||
463 | return 0; | 388 | return 0; |
464 | } | 389 | } |
465 | 390 | ||
466 | static struct platform_driver cx20442_platform_driver = { | 391 | static struct platform_driver cx20442_platform_driver = { |
467 | .driver = { | 392 | .driver = { |
468 | .name = "cx20442", | 393 | .name = "cx20442-codec", |
469 | .owner = THIS_MODULE, | 394 | .owner = THIS_MODULE, |
470 | }, | 395 | }, |
471 | .probe = cx20442_platform_probe, | 396 | .probe = cx20442_platform_probe, |
@@ -487,4 +412,4 @@ module_exit(cx20442_exit); | |||
487 | MODULE_DESCRIPTION("ASoC CX20442-11 voice modem codec driver"); | 412 | MODULE_DESCRIPTION("ASoC CX20442-11 voice modem codec driver"); |
488 | MODULE_AUTHOR("Janusz Krzysztofik"); | 413 | MODULE_AUTHOR("Janusz Krzysztofik"); |
489 | MODULE_LICENSE("GPL"); | 414 | MODULE_LICENSE("GPL"); |
490 | MODULE_ALIAS("platform:cx20442"); | 415 | MODULE_ALIAS("platform:cx20442-codec"); |
diff --git a/sound/soc/codecs/cx20442.h b/sound/soc/codecs/cx20442.h index 688a5eb62e17..c7a7c79ef0cd 100644 --- a/sound/soc/codecs/cx20442.h +++ b/sound/soc/codecs/cx20442.h | |||
@@ -13,8 +13,6 @@ | |||
13 | #ifndef _CX20442_CODEC_H | 13 | #ifndef _CX20442_CODEC_H |
14 | #define _CX20442_CODEC_H | 14 | #define _CX20442_CODEC_H |
15 | 15 | ||
16 | extern struct snd_soc_dai cx20442_dai; | ||
17 | extern struct snd_soc_codec_device cx20442_codec_dev; | ||
18 | extern struct tty_ldisc_ops v253_ops; | 16 | extern struct tty_ldisc_ops v253_ops; |
19 | 17 | ||
20 | #endif | 18 | #endif |
diff --git a/sound/soc/codecs/da7210.c b/sound/soc/codecs/da7210.c index 3c51d6a57523..eabf3c062500 100644 --- a/sound/soc/codecs/da7210.c +++ b/sound/soc/codecs/da7210.c | |||
@@ -25,8 +25,6 @@ | |||
25 | #include <sound/initval.h> | 25 | #include <sound/initval.h> |
26 | #include <sound/tlv.h> | 26 | #include <sound/tlv.h> |
27 | 27 | ||
28 | #include "da7210.h" | ||
29 | |||
30 | /* DA7210 register space */ | 28 | /* DA7210 register space */ |
31 | #define DA7210_STATUS 0x02 | 29 | #define DA7210_STATUS 0x02 |
32 | #define DA7210_STARTUP1 0x03 | 30 | #define DA7210_STARTUP1 0x03 |
@@ -162,11 +160,10 @@ static const struct snd_kcontrol_new da7210_snd_controls[] = { | |||
162 | 160 | ||
163 | /* Codec private data */ | 161 | /* Codec private data */ |
164 | struct da7210_priv { | 162 | struct da7210_priv { |
165 | struct snd_soc_codec codec; | 163 | enum snd_soc_control_type control_type; |
164 | void *control_data; | ||
166 | }; | 165 | }; |
167 | 166 | ||
168 | static struct snd_soc_codec *da7210_codec; | ||
169 | |||
170 | /* | 167 | /* |
171 | * Register cache | 168 | * Register cache |
172 | */ | 169 | */ |
@@ -209,12 +206,12 @@ static int da7210_write(struct snd_soc_codec *codec, u32 reg, u32 value) | |||
209 | u8 *cache = codec->reg_cache; | 206 | u8 *cache = codec->reg_cache; |
210 | u8 data[2]; | 207 | u8 data[2]; |
211 | 208 | ||
212 | BUG_ON(codec->volatile_register); | 209 | BUG_ON(codec->driver->volatile_register); |
213 | 210 | ||
214 | data[0] = reg & 0xff; | 211 | data[0] = reg & 0xff; |
215 | data[1] = value & 0xff; | 212 | data[1] = value & 0xff; |
216 | 213 | ||
217 | if (reg >= codec->reg_cache_size) | 214 | if (reg >= codec->driver->reg_cache_size) |
218 | return -EIO; | 215 | return -EIO; |
219 | 216 | ||
220 | if (2 != codec->hw_write(codec->control_data, data, 2)) | 217 | if (2 != codec->hw_write(codec->control_data, data, 2)) |
@@ -267,8 +264,7 @@ static int da7210_hw_params(struct snd_pcm_substream *substream, | |||
267 | struct snd_soc_dai *dai) | 264 | struct snd_soc_dai *dai) |
268 | { | 265 | { |
269 | struct snd_soc_pcm_runtime *rtd = substream->private_data; | 266 | struct snd_soc_pcm_runtime *rtd = substream->private_data; |
270 | struct snd_soc_device *socdev = rtd->socdev; | 267 | struct snd_soc_codec *codec = rtd->codec; |
271 | struct snd_soc_codec *codec = socdev->card->codec; | ||
272 | u32 dai_cfg1; | 268 | u32 dai_cfg1; |
273 | u32 hpf_reg, hpf_mask, hpf_value; | 269 | u32 hpf_reg, hpf_mask, hpf_value; |
274 | u32 fs, bypass; | 270 | u32 fs, bypass; |
@@ -430,9 +426,8 @@ static struct snd_soc_dai_ops da7210_dai_ops = { | |||
430 | .set_fmt = da7210_set_dai_fmt, | 426 | .set_fmt = da7210_set_dai_fmt, |
431 | }; | 427 | }; |
432 | 428 | ||
433 | struct snd_soc_dai da7210_dai = { | 429 | static struct snd_soc_dai_driver da7210_dai = { |
434 | .name = "DA7210 IIS", | 430 | .name = "da7210-hifi", |
435 | .id = 0, | ||
436 | /* playback capabilities */ | 431 | /* playback capabilities */ |
437 | .playback = { | 432 | .playback = { |
438 | .stream_name = "Playback", | 433 | .stream_name = "Playback", |
@@ -452,55 +447,15 @@ struct snd_soc_dai da7210_dai = { | |||
452 | .ops = &da7210_dai_ops, | 447 | .ops = &da7210_dai_ops, |
453 | .symmetric_rates = 1, | 448 | .symmetric_rates = 1, |
454 | }; | 449 | }; |
455 | EXPORT_SYMBOL_GPL(da7210_dai); | ||
456 | 450 | ||
457 | /* | 451 | static int da7210_probe(struct snd_soc_codec *codec) |
458 | * Initialize the DA7210 driver | ||
459 | * register the mixer and dsp interfaces with the kernel | ||
460 | */ | ||
461 | static int da7210_init(struct da7210_priv *da7210) | ||
462 | { | 452 | { |
463 | struct snd_soc_codec *codec = &da7210->codec; | 453 | struct da7210_priv *da7210 = snd_soc_codec_get_drvdata(codec); |
464 | int ret = 0; | ||
465 | 454 | ||
466 | if (da7210_codec) { | 455 | dev_info(codec->dev, "DA7210 Audio Codec %s\n", DA7210_VERSION); |
467 | dev_err(codec->dev, "Another da7210 is registered\n"); | ||
468 | return -EINVAL; | ||
469 | } | ||
470 | 456 | ||
471 | mutex_init(&codec->mutex); | 457 | codec->control_data = da7210->control_data; |
472 | INIT_LIST_HEAD(&codec->dapm_widgets); | ||
473 | INIT_LIST_HEAD(&codec->dapm_paths); | ||
474 | |||
475 | snd_soc_codec_set_drvdata(codec, da7210); | ||
476 | codec->name = "DA7210"; | ||
477 | codec->owner = THIS_MODULE; | ||
478 | codec->read = da7210_read; | ||
479 | codec->write = da7210_write; | ||
480 | codec->dai = &da7210_dai; | ||
481 | codec->num_dai = 1; | ||
482 | codec->hw_write = (hw_write_t)i2c_master_send; | 458 | codec->hw_write = (hw_write_t)i2c_master_send; |
483 | codec->reg_cache_size = ARRAY_SIZE(da7210_reg); | ||
484 | codec->reg_cache = kmemdup(da7210_reg, | ||
485 | sizeof(da7210_reg), GFP_KERNEL); | ||
486 | |||
487 | if (!codec->reg_cache) | ||
488 | return -ENOMEM; | ||
489 | |||
490 | da7210_dai.dev = codec->dev; | ||
491 | da7210_codec = codec; | ||
492 | |||
493 | ret = snd_soc_register_codec(codec); | ||
494 | if (ret) { | ||
495 | dev_err(codec->dev, "Failed to register CODEC: %d\n", ret); | ||
496 | goto init_err; | ||
497 | } | ||
498 | |||
499 | ret = snd_soc_register_dai(&da7210_dai); | ||
500 | if (ret) { | ||
501 | dev_err(codec->dev, "Failed to register DAI: %d\n", ret); | ||
502 | goto codec_err; | ||
503 | } | ||
504 | 459 | ||
505 | /* FIXME | 460 | /* FIXME |
506 | * | 461 | * |
@@ -583,54 +538,50 @@ static int da7210_init(struct da7210_priv *da7210) | |||
583 | /* Activate all enabled subsystem */ | 538 | /* Activate all enabled subsystem */ |
584 | da7210_write(codec, DA7210_STARTUP1, DA7210_SC_MST_EN); | 539 | da7210_write(codec, DA7210_STARTUP1, DA7210_SC_MST_EN); |
585 | 540 | ||
586 | return ret; | 541 | snd_soc_add_controls(codec, da7210_snd_controls, |
587 | 542 | ARRAY_SIZE(da7210_snd_controls)); | |
588 | codec_err: | ||
589 | snd_soc_unregister_codec(codec); | ||
590 | init_err: | ||
591 | kfree(codec->reg_cache); | ||
592 | codec->reg_cache = NULL; | ||
593 | 543 | ||
594 | return ret; | 544 | dev_info(codec->dev, "DA7210 Audio Codec %s\n", DA7210_VERSION); |
595 | 545 | ||
546 | return 0; | ||
596 | } | 547 | } |
597 | 548 | ||
549 | static struct snd_soc_codec_driver soc_codec_dev_da7210 = { | ||
550 | .probe = da7210_probe, | ||
551 | .read = da7210_read, | ||
552 | .write = da7210_write, | ||
553 | .reg_cache_size = ARRAY_SIZE(da7210_reg), | ||
554 | .reg_word_size = sizeof(u8), | ||
555 | .reg_cache_default = da7210_reg, | ||
556 | }; | ||
557 | |||
598 | #if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE) | 558 | #if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE) |
599 | static int __devinit da7210_i2c_probe(struct i2c_client *i2c, | 559 | static int __devinit da7210_i2c_probe(struct i2c_client *i2c, |
600 | const struct i2c_device_id *id) | 560 | const struct i2c_device_id *id) |
601 | { | 561 | { |
602 | struct da7210_priv *da7210; | 562 | struct da7210_priv *da7210; |
603 | struct snd_soc_codec *codec; | ||
604 | int ret; | 563 | int ret; |
605 | 564 | ||
606 | da7210 = kzalloc(sizeof(struct da7210_priv), GFP_KERNEL); | 565 | da7210 = kzalloc(sizeof(struct da7210_priv), GFP_KERNEL); |
607 | if (!da7210) | 566 | if (!da7210) |
608 | return -ENOMEM; | 567 | return -ENOMEM; |
609 | 568 | ||
610 | codec = &da7210->codec; | ||
611 | codec->dev = &i2c->dev; | ||
612 | |||
613 | i2c_set_clientdata(i2c, da7210); | 569 | i2c_set_clientdata(i2c, da7210); |
614 | codec->control_data = i2c; | 570 | da7210->control_data = i2c; |
571 | da7210->control_type = SND_SOC_I2C; | ||
615 | 572 | ||
616 | ret = da7210_init(da7210); | 573 | ret = snd_soc_register_codec(&i2c->dev, |
617 | if (ret < 0) { | 574 | &soc_codec_dev_da7210, &da7210_dai, 1); |
618 | pr_err("Failed to initialise da7210 audio codec\n"); | 575 | if (ret < 0) |
619 | kfree(da7210); | 576 | kfree(da7210); |
620 | } | ||
621 | 577 | ||
622 | return ret; | 578 | return ret; |
623 | } | 579 | } |
624 | 580 | ||
625 | static int __devexit da7210_i2c_remove(struct i2c_client *client) | 581 | static int __devexit da7210_i2c_remove(struct i2c_client *client) |
626 | { | 582 | { |
627 | struct da7210_priv *da7210 = i2c_get_clientdata(client); | 583 | snd_soc_unregister_codec(&client->dev); |
628 | 584 | kfree(i2c_get_clientdata(client)); | |
629 | snd_soc_unregister_dai(&da7210_dai); | ||
630 | kfree(da7210->codec.reg_cache); | ||
631 | kfree(da7210); | ||
632 | da7210_codec = NULL; | ||
633 | |||
634 | return 0; | 585 | return 0; |
635 | } | 586 | } |
636 | 587 | ||
@@ -643,7 +594,7 @@ MODULE_DEVICE_TABLE(i2c, da7210_i2c_id); | |||
643 | /* I2C codec control layer */ | 594 | /* I2C codec control layer */ |
644 | static struct i2c_driver da7210_i2c_driver = { | 595 | static struct i2c_driver da7210_i2c_driver = { |
645 | .driver = { | 596 | .driver = { |
646 | .name = "DA7210 I2C Codec", | 597 | .name = "da7210-codec", |
647 | .owner = THIS_MODULE, | 598 | .owner = THIS_MODULE, |
648 | }, | 599 | }, |
649 | .probe = da7210_i2c_probe, | 600 | .probe = da7210_i2c_probe, |
@@ -652,50 +603,6 @@ static struct i2c_driver da7210_i2c_driver = { | |||
652 | }; | 603 | }; |
653 | #endif | 604 | #endif |
654 | 605 | ||
655 | static int da7210_probe(struct platform_device *pdev) | ||
656 | { | ||
657 | struct snd_soc_device *socdev = platform_get_drvdata(pdev); | ||
658 | struct snd_soc_codec *codec; | ||
659 | int ret; | ||
660 | |||
661 | if (!da7210_codec) { | ||
662 | dev_err(&pdev->dev, "Codec device not registered\n"); | ||
663 | return -ENODEV; | ||
664 | } | ||
665 | |||
666 | socdev->card->codec = da7210_codec; | ||
667 | codec = da7210_codec; | ||
668 | |||
669 | /* Register pcms */ | ||
670 | ret = snd_soc_new_pcms(socdev, SNDRV_DEFAULT_IDX1, SNDRV_DEFAULT_STR1); | ||
671 | if (ret < 0) | ||
672 | goto pcm_err; | ||
673 | |||
674 | snd_soc_add_controls(da7210_codec, da7210_snd_controls, | ||
675 | ARRAY_SIZE(da7210_snd_controls)); | ||
676 | |||
677 | dev_info(&pdev->dev, "DA7210 Audio Codec %s\n", DA7210_VERSION); | ||
678 | |||
679 | pcm_err: | ||
680 | return ret; | ||
681 | } | ||
682 | |||
683 | static int da7210_remove(struct platform_device *pdev) | ||
684 | { | ||
685 | struct snd_soc_device *socdev = platform_get_drvdata(pdev); | ||
686 | |||
687 | snd_soc_free_pcms(socdev); | ||
688 | snd_soc_dapm_free(socdev); | ||
689 | |||
690 | return 0; | ||
691 | } | ||
692 | |||
693 | struct snd_soc_codec_device soc_codec_dev_da7210 = { | ||
694 | .probe = da7210_probe, | ||
695 | .remove = da7210_remove, | ||
696 | }; | ||
697 | EXPORT_SYMBOL_GPL(soc_codec_dev_da7210); | ||
698 | |||
699 | static int __init da7210_modinit(void) | 606 | static int __init da7210_modinit(void) |
700 | { | 607 | { |
701 | int ret = 0; | 608 | int ret = 0; |
diff --git a/sound/soc/codecs/da7210.h b/sound/soc/codecs/da7210.h deleted file mode 100644 index 390d621eb742..000000000000 --- a/sound/soc/codecs/da7210.h +++ /dev/null | |||
@@ -1,24 +0,0 @@ | |||
1 | /* | ||
2 | * da7210.h -- audio driver for da7210 | ||
3 | * | ||
4 | * Copyright (c) 2009 Dialog Semiconductor | ||
5 | * Written by David Chen <Dajun.chen@diasemi.com> | ||
6 | * | ||
7 | * Copyright (C) 2009 Renesas Solutions Corp. | ||
8 | * Cleanups by Kuninori Morimoto <morimoto.kuninori@renesas.com> | ||
9 | * | ||
10 | * This program is free software; you can redistribute it and/or modify it | ||
11 | * under the terms of the GNU General Public License as published by the | ||
12 | * Free Software Foundation; either version 2 of the License, or (at your | ||
13 | * option) any later version. | ||
14 | * | ||
15 | */ | ||
16 | |||
17 | #ifndef _DA7210_H | ||
18 | #define _DA7210_H | ||
19 | |||
20 | extern struct snd_soc_dai da7210_dai; | ||
21 | extern struct snd_soc_codec_device soc_codec_dev_da7210; | ||
22 | |||
23 | #endif | ||
24 | |||
diff --git a/sound/soc/codecs/jz4740.c b/sound/soc/codecs/jz4740.c index 66557de1e4fe..16253ec9b022 100644 --- a/sound/soc/codecs/jz4740.c +++ b/sound/soc/codecs/jz4740.c | |||
@@ -74,29 +74,22 @@ static const uint32_t jz4740_codec_regs[] = { | |||
74 | struct jz4740_codec { | 74 | struct jz4740_codec { |
75 | void __iomem *base; | 75 | void __iomem *base; |
76 | struct resource *mem; | 76 | struct resource *mem; |
77 | |||
78 | uint32_t reg_cache[2]; | ||
79 | struct snd_soc_codec codec; | ||
80 | }; | 77 | }; |
81 | 78 | ||
82 | static inline struct jz4740_codec *codec_to_jz4740(struct snd_soc_codec *codec) | ||
83 | { | ||
84 | return container_of(codec, struct jz4740_codec, codec); | ||
85 | } | ||
86 | |||
87 | static unsigned int jz4740_codec_read(struct snd_soc_codec *codec, | 79 | static unsigned int jz4740_codec_read(struct snd_soc_codec *codec, |
88 | unsigned int reg) | 80 | unsigned int reg) |
89 | { | 81 | { |
90 | struct jz4740_codec *jz4740_codec = codec_to_jz4740(codec); | 82 | struct jz4740_codec *jz4740_codec = snd_soc_codec_get_drvdata(codec); |
91 | return readl(jz4740_codec->base + (reg << 2)); | 83 | return readl(jz4740_codec->base + (reg << 2)); |
92 | } | 84 | } |
93 | 85 | ||
94 | static int jz4740_codec_write(struct snd_soc_codec *codec, unsigned int reg, | 86 | static int jz4740_codec_write(struct snd_soc_codec *codec, unsigned int reg, |
95 | unsigned int val) | 87 | unsigned int val) |
96 | { | 88 | { |
97 | struct jz4740_codec *jz4740_codec = codec_to_jz4740(codec); | 89 | struct jz4740_codec *jz4740_codec = snd_soc_codec_get_drvdata(codec); |
90 | u32 *cache = codec->reg_cache; | ||
98 | 91 | ||
99 | jz4740_codec->reg_cache[reg] = val; | 92 | cache[reg] = val; |
100 | writel(val, jz4740_codec->base + (reg << 2)); | 93 | writel(val, jz4740_codec->base + (reg << 2)); |
101 | 94 | ||
102 | return 0; | 95 | return 0; |
@@ -172,8 +165,7 @@ static int jz4740_codec_hw_params(struct snd_pcm_substream *substream, | |||
172 | { | 165 | { |
173 | uint32_t val; | 166 | uint32_t val; |
174 | struct snd_soc_pcm_runtime *rtd = substream->private_data; | 167 | struct snd_soc_pcm_runtime *rtd = substream->private_data; |
175 | struct snd_soc_device *socdev = rtd->socdev; | 168 | struct snd_soc_codec *codec =rtd->codec; |
176 | struct snd_soc_codec *codec = socdev->card->codec; | ||
177 | 169 | ||
178 | switch (params_rate(params)) { | 170 | switch (params_rate(params)) { |
179 | case 8000: | 171 | case 8000: |
@@ -219,8 +211,8 @@ static struct snd_soc_dai_ops jz4740_codec_dai_ops = { | |||
219 | .hw_params = jz4740_codec_hw_params, | 211 | .hw_params = jz4740_codec_hw_params, |
220 | }; | 212 | }; |
221 | 213 | ||
222 | struct snd_soc_dai jz4740_codec_dai = { | 214 | static struct snd_soc_dai_driver jz4740_codec_dai = { |
223 | .name = "jz4740", | 215 | .name = "jz4740-hifi", |
224 | .playback = { | 216 | .playback = { |
225 | .stream_name = "Playback", | 217 | .stream_name = "Playback", |
226 | .channels_min = 2, | 218 | .channels_min = 2, |
@@ -238,7 +230,6 @@ struct snd_soc_dai jz4740_codec_dai = { | |||
238 | .ops = &jz4740_codec_dai_ops, | 230 | .ops = &jz4740_codec_dai_ops, |
239 | .symmetric_rates = 1, | 231 | .symmetric_rates = 1, |
240 | }; | 232 | }; |
241 | EXPORT_SYMBOL_GPL(jz4740_codec_dai); | ||
242 | 233 | ||
243 | static void jz4740_codec_wakeup(struct snd_soc_codec *codec) | 234 | static void jz4740_codec_wakeup(struct snd_soc_codec *codec) |
244 | { | 235 | { |
@@ -302,23 +293,10 @@ static int jz4740_codec_set_bias_level(struct snd_soc_codec *codec, | |||
302 | return 0; | 293 | return 0; |
303 | } | 294 | } |
304 | 295 | ||
305 | static struct snd_soc_codec *jz4740_codec_codec; | 296 | static int jz4740_codec_dev_probe(struct snd_soc_codec *codec) |
306 | |||
307 | static int jz4740_codec_dev_probe(struct platform_device *pdev) | ||
308 | { | 297 | { |
309 | int ret; | 298 | snd_soc_update_bits(codec, JZ4740_REG_CODEC_1, |
310 | struct snd_soc_device *socdev = platform_get_drvdata(pdev); | 299 | JZ4740_CODEC_1_SW2_ENABLE, JZ4740_CODEC_1_SW2_ENABLE); |
311 | struct snd_soc_codec *codec = jz4740_codec_codec; | ||
312 | |||
313 | BUG_ON(!codec); | ||
314 | |||
315 | socdev->card->codec = codec; | ||
316 | |||
317 | ret = snd_soc_new_pcms(socdev, SNDRV_DEFAULT_IDX1, SNDRV_DEFAULT_STR1); | ||
318 | if (ret) { | ||
319 | dev_err(&pdev->dev, "Failed to create pcms: %d\n", ret); | ||
320 | return ret; | ||
321 | } | ||
322 | 300 | ||
323 | snd_soc_add_controls(codec, jz4740_codec_controls, | 301 | snd_soc_add_controls(codec, jz4740_codec_controls, |
324 | ARRAY_SIZE(jz4740_codec_controls)); | 302 | ARRAY_SIZE(jz4740_codec_controls)); |
@@ -331,34 +309,27 @@ static int jz4740_codec_dev_probe(struct platform_device *pdev) | |||
331 | 309 | ||
332 | snd_soc_dapm_new_widgets(codec); | 310 | snd_soc_dapm_new_widgets(codec); |
333 | 311 | ||
312 | jz4740_codec_set_bias_level(codec, SND_SOC_BIAS_STANDBY); | ||
313 | |||
334 | return 0; | 314 | return 0; |
335 | } | 315 | } |
336 | 316 | ||
337 | static int jz4740_codec_dev_remove(struct platform_device *pdev) | 317 | static int jz4740_codec_dev_remove(struct snd_soc_codec *codec) |
338 | { | 318 | { |
339 | struct snd_soc_device *socdev = platform_get_drvdata(pdev); | 319 | jz4740_codec_set_bias_level(codec, SND_SOC_BIAS_OFF); |
340 | |||
341 | snd_soc_free_pcms(socdev); | ||
342 | snd_soc_dapm_free(socdev); | ||
343 | 320 | ||
344 | return 0; | 321 | return 0; |
345 | } | 322 | } |
346 | 323 | ||
347 | #ifdef CONFIG_PM_SLEEP | 324 | #ifdef CONFIG_PM_SLEEP |
348 | 325 | ||
349 | static int jz4740_codec_suspend(struct platform_device *pdev, pm_message_t state) | 326 | static int jz4740_codec_suspend(struct snd_soc_codec *codec, pm_message_t state) |
350 | { | 327 | { |
351 | struct snd_soc_device *socdev = platform_get_drvdata(pdev); | ||
352 | struct snd_soc_codec *codec = socdev->card->codec; | ||
353 | |||
354 | return jz4740_codec_set_bias_level(codec, SND_SOC_BIAS_OFF); | 328 | return jz4740_codec_set_bias_level(codec, SND_SOC_BIAS_OFF); |
355 | } | 329 | } |
356 | 330 | ||
357 | static int jz4740_codec_resume(struct platform_device *pdev) | 331 | static int jz4740_codec_resume(struct snd_soc_codec *codec) |
358 | { | 332 | { |
359 | struct snd_soc_device *socdev = platform_get_drvdata(pdev); | ||
360 | struct snd_soc_codec *codec = socdev->card->codec; | ||
361 | |||
362 | return jz4740_codec_set_bias_level(codec, SND_SOC_BIAS_STANDBY); | 333 | return jz4740_codec_set_bias_level(codec, SND_SOC_BIAS_STANDBY); |
363 | } | 334 | } |
364 | 335 | ||
@@ -367,19 +338,23 @@ static int jz4740_codec_resume(struct platform_device *pdev) | |||
367 | #define jz4740_codec_resume NULL | 338 | #define jz4740_codec_resume NULL |
368 | #endif | 339 | #endif |
369 | 340 | ||
370 | struct snd_soc_codec_device soc_codec_dev_jz4740_codec = { | 341 | static struct snd_soc_codec_driver soc_codec_dev_jz4740_codec = { |
371 | .probe = jz4740_codec_dev_probe, | 342 | .probe = jz4740_codec_dev_probe, |
372 | .remove = jz4740_codec_dev_remove, | 343 | .remove = jz4740_codec_dev_remove, |
373 | .suspend = jz4740_codec_suspend, | 344 | .suspend = jz4740_codec_suspend, |
374 | .resume = jz4740_codec_resume, | 345 | .resume = jz4740_codec_resume, |
346 | .read = jz4740_codec_read, | ||
347 | .write = jz4740_codec_write, | ||
348 | .set_bias_level = jz4740_codec_set_bias_level, | ||
349 | .reg_cache_default = jz4740_codec_regs, | ||
350 | .reg_word_size = sizeof(u32), | ||
351 | .reg_cache_size = 2, | ||
375 | }; | 352 | }; |
376 | EXPORT_SYMBOL_GPL(soc_codec_dev_jz4740_codec); | ||
377 | 353 | ||
378 | static int __devinit jz4740_codec_probe(struct platform_device *pdev) | 354 | static int __devinit jz4740_codec_probe(struct platform_device *pdev) |
379 | { | 355 | { |
380 | int ret; | 356 | int ret; |
381 | struct jz4740_codec *jz4740_codec; | 357 | struct jz4740_codec *jz4740_codec; |
382 | struct snd_soc_codec *codec; | ||
383 | struct resource *mem; | 358 | struct resource *mem; |
384 | 359 | ||
385 | jz4740_codec = kzalloc(sizeof(*jz4740_codec), GFP_KERNEL); | 360 | jz4740_codec = kzalloc(sizeof(*jz4740_codec), GFP_KERNEL); |
@@ -408,55 +383,17 @@ static int __devinit jz4740_codec_probe(struct platform_device *pdev) | |||
408 | } | 383 | } |
409 | jz4740_codec->mem = mem; | 384 | jz4740_codec->mem = mem; |
410 | 385 | ||
411 | jz4740_codec_dai.dev = &pdev->dev; | ||
412 | |||
413 | codec = &jz4740_codec->codec; | ||
414 | |||
415 | codec->dev = &pdev->dev; | ||
416 | codec->name = "jz4740"; | ||
417 | codec->owner = THIS_MODULE; | ||
418 | |||
419 | codec->read = jz4740_codec_read; | ||
420 | codec->write = jz4740_codec_write; | ||
421 | codec->set_bias_level = jz4740_codec_set_bias_level; | ||
422 | codec->bias_level = SND_SOC_BIAS_OFF; | ||
423 | |||
424 | codec->dai = &jz4740_codec_dai; | ||
425 | codec->num_dai = 1; | ||
426 | |||
427 | codec->reg_cache = jz4740_codec->reg_cache; | ||
428 | codec->reg_cache_size = 2; | ||
429 | memcpy(codec->reg_cache, jz4740_codec_regs, sizeof(jz4740_codec_regs)); | ||
430 | |||
431 | mutex_init(&codec->mutex); | ||
432 | INIT_LIST_HEAD(&codec->dapm_widgets); | ||
433 | INIT_LIST_HEAD(&codec->dapm_paths); | ||
434 | |||
435 | jz4740_codec_codec = codec; | ||
436 | |||
437 | snd_soc_update_bits(codec, JZ4740_REG_CODEC_1, | ||
438 | JZ4740_CODEC_1_SW2_ENABLE, JZ4740_CODEC_1_SW2_ENABLE); | ||
439 | |||
440 | platform_set_drvdata(pdev, jz4740_codec); | 386 | platform_set_drvdata(pdev, jz4740_codec); |
441 | 387 | ||
442 | ret = snd_soc_register_codec(codec); | 388 | ret = snd_soc_register_codec(&pdev->dev, |
389 | &soc_codec_dev_jz4740_codec, &jz4740_codec_dai, 1); | ||
443 | if (ret) { | 390 | if (ret) { |
444 | dev_err(&pdev->dev, "Failed to register codec\n"); | 391 | dev_err(&pdev->dev, "Failed to register codec\n"); |
445 | goto err_iounmap; | 392 | goto err_iounmap; |
446 | } | 393 | } |
447 | 394 | ||
448 | ret = snd_soc_register_dai(&jz4740_codec_dai); | ||
449 | if (ret) { | ||
450 | dev_err(&pdev->dev, "Failed to register codec dai\n"); | ||
451 | goto err_unregister_codec; | ||
452 | } | ||
453 | |||
454 | jz4740_codec_set_bias_level(codec, SND_SOC_BIAS_STANDBY); | ||
455 | |||
456 | return 0; | 395 | return 0; |
457 | 396 | ||
458 | err_unregister_codec: | ||
459 | snd_soc_unregister_codec(codec); | ||
460 | err_iounmap: | 397 | err_iounmap: |
461 | iounmap(jz4740_codec->base); | 398 | iounmap(jz4740_codec->base); |
462 | err_release_mem_region: | 399 | err_release_mem_region: |
@@ -472,8 +409,7 @@ static int __devexit jz4740_codec_remove(struct platform_device *pdev) | |||
472 | struct jz4740_codec *jz4740_codec = platform_get_drvdata(pdev); | 409 | struct jz4740_codec *jz4740_codec = platform_get_drvdata(pdev); |
473 | struct resource *mem = jz4740_codec->mem; | 410 | struct resource *mem = jz4740_codec->mem; |
474 | 411 | ||
475 | snd_soc_unregister_dai(&jz4740_codec_dai); | 412 | snd_soc_unregister_codec(&pdev->dev); |
476 | snd_soc_unregister_codec(&jz4740_codec->codec); | ||
477 | 413 | ||
478 | iounmap(jz4740_codec->base); | 414 | iounmap(jz4740_codec->base); |
479 | release_mem_region(mem->start, resource_size(mem)); | 415 | release_mem_region(mem->start, resource_size(mem)); |
diff --git a/sound/soc/codecs/jz4740.h b/sound/soc/codecs/jz4740.h deleted file mode 100644 index b5a0691be763..000000000000 --- a/sound/soc/codecs/jz4740.h +++ /dev/null | |||
@@ -1,20 +0,0 @@ | |||
1 | /* | ||
2 | * Copyright (C) 2009, Lars-Peter Clausen <lars@metafoo.de> | ||
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 | * You should have received a copy of the GNU General Public License along | ||
9 | * with this program; if not, write to the Free Software Foundation, Inc., | ||
10 | * 675 Mass Ave, Cambridge, MA 02139, USA. | ||
11 | * | ||
12 | */ | ||
13 | |||
14 | #ifndef __SND_SOC_CODECS_JZ4740_CODEC_H__ | ||
15 | #define __SND_SOC_CODECS_JZ4740_CODEC_H__ | ||
16 | |||
17 | extern struct snd_soc_dai jz4740_codec_dai; | ||
18 | extern struct snd_soc_codec_device soc_codec_dev_jz4740_codec; | ||
19 | |||
20 | #endif | ||
diff --git a/sound/soc/codecs/pcm3008.c b/sound/soc/codecs/pcm3008.c index 5a5f187a2657..bd8f26e41602 100644 --- a/sound/soc/codecs/pcm3008.c +++ b/sound/soc/codecs/pcm3008.c | |||
@@ -32,8 +32,8 @@ | |||
32 | #define PCM3008_RATES (SNDRV_PCM_RATE_32000 | SNDRV_PCM_RATE_44100 | \ | 32 | #define PCM3008_RATES (SNDRV_PCM_RATE_32000 | SNDRV_PCM_RATE_44100 | \ |
33 | SNDRV_PCM_RATE_48000) | 33 | SNDRV_PCM_RATE_48000) |
34 | 34 | ||
35 | struct snd_soc_dai pcm3008_dai = { | 35 | static struct snd_soc_dai_driver pcm3008_dai = { |
36 | .name = "PCM3008 HiFi", | 36 | .name = "pcm3008-hifi", |
37 | .playback = { | 37 | .playback = { |
38 | .stream_name = "PCM3008 Playback", | 38 | .stream_name = "PCM3008 Playback", |
39 | .channels_min = 1, | 39 | .channels_min = 1, |
@@ -49,7 +49,6 @@ struct snd_soc_dai pcm3008_dai = { | |||
49 | .formats = SNDRV_PCM_FMTBIT_S16_LE, | 49 | .formats = SNDRV_PCM_FMTBIT_S16_LE, |
50 | }, | 50 | }, |
51 | }; | 51 | }; |
52 | EXPORT_SYMBOL_GPL(pcm3008_dai); | ||
53 | 52 | ||
54 | static void pcm3008_gpio_free(struct pcm3008_setup_data *setup) | 53 | static void pcm3008_gpio_free(struct pcm3008_setup_data *setup) |
55 | { | 54 | { |
@@ -59,38 +58,13 @@ static void pcm3008_gpio_free(struct pcm3008_setup_data *setup) | |||
59 | gpio_free(setup->pdda_pin); | 58 | gpio_free(setup->pdda_pin); |
60 | } | 59 | } |
61 | 60 | ||
62 | static int pcm3008_soc_probe(struct platform_device *pdev) | 61 | static int pcm3008_soc_probe(struct snd_soc_codec *codec) |
63 | { | 62 | { |
64 | struct snd_soc_device *socdev = platform_get_drvdata(pdev); | 63 | struct pcm3008_setup_data *setup = codec->dev->platform_data; |
65 | struct snd_soc_codec *codec; | ||
66 | struct pcm3008_setup_data *setup = socdev->codec_data; | ||
67 | int ret = 0; | 64 | int ret = 0; |
68 | 65 | ||
69 | printk(KERN_INFO "PCM3008 SoC Audio Codec %s\n", PCM3008_VERSION); | 66 | printk(KERN_INFO "PCM3008 SoC Audio Codec %s\n", PCM3008_VERSION); |
70 | 67 | ||
71 | socdev->card->codec = kzalloc(sizeof(struct snd_soc_codec), GFP_KERNEL); | ||
72 | if (!socdev->card->codec) | ||
73 | return -ENOMEM; | ||
74 | |||
75 | codec = socdev->card->codec; | ||
76 | mutex_init(&codec->mutex); | ||
77 | |||
78 | codec->name = "PCM3008"; | ||
79 | codec->owner = THIS_MODULE; | ||
80 | codec->dai = &pcm3008_dai; | ||
81 | codec->num_dai = 1; | ||
82 | codec->write = NULL; | ||
83 | codec->read = NULL; | ||
84 | INIT_LIST_HEAD(&codec->dapm_widgets); | ||
85 | INIT_LIST_HEAD(&codec->dapm_paths); | ||
86 | |||
87 | /* Register PCMs. */ | ||
88 | ret = snd_soc_new_pcms(socdev, SNDRV_DEFAULT_IDX1, SNDRV_DEFAULT_STR1); | ||
89 | if (ret < 0) { | ||
90 | printk(KERN_ERR "pcm3008: failed to create pcms\n"); | ||
91 | goto pcm_err; | ||
92 | } | ||
93 | |||
94 | /* DEM1 DEM0 DE-EMPHASIS_MODE | 68 | /* DEM1 DEM0 DE-EMPHASIS_MODE |
95 | * Low Low De-emphasis 44.1 kHz ON | 69 | * Low Low De-emphasis 44.1 kHz ON |
96 | * Low High De-emphasis OFF | 70 | * Low High De-emphasis OFF |
@@ -130,33 +104,22 @@ static int pcm3008_soc_probe(struct platform_device *pdev) | |||
130 | 104 | ||
131 | gpio_err: | 105 | gpio_err: |
132 | pcm3008_gpio_free(setup); | 106 | pcm3008_gpio_free(setup); |
133 | pcm_err: | ||
134 | kfree(socdev->card->codec); | ||
135 | 107 | ||
136 | return ret; | 108 | return ret; |
137 | } | 109 | } |
138 | 110 | ||
139 | static int pcm3008_soc_remove(struct platform_device *pdev) | 111 | static int pcm3008_soc_remove(struct snd_soc_codec *codec) |
140 | { | 112 | { |
141 | struct snd_soc_device *socdev = platform_get_drvdata(pdev); | 113 | struct pcm3008_setup_data *setup = codec->dev->platform_data; |
142 | struct snd_soc_codec *codec = socdev->card->codec; | ||
143 | struct pcm3008_setup_data *setup = socdev->codec_data; | ||
144 | |||
145 | if (!codec) | ||
146 | return 0; | ||
147 | 114 | ||
148 | pcm3008_gpio_free(setup); | 115 | pcm3008_gpio_free(setup); |
149 | snd_soc_free_pcms(socdev); | ||
150 | kfree(socdev->card->codec); | ||
151 | |||
152 | return 0; | 116 | return 0; |
153 | } | 117 | } |
154 | 118 | ||
155 | #ifdef CONFIG_PM | 119 | #ifdef CONFIG_PM |
156 | static int pcm3008_soc_suspend(struct platform_device *pdev, pm_message_t msg) | 120 | static int pcm3008_soc_suspend(struct snd_soc_codec *codec, pm_message_t msg) |
157 | { | 121 | { |
158 | struct snd_soc_device *socdev = platform_get_drvdata(pdev); | 122 | struct pcm3008_setup_data *setup = codec->dev->platform_data; |
159 | struct pcm3008_setup_data *setup = socdev->codec_data; | ||
160 | 123 | ||
161 | gpio_set_value(setup->pdad_pin, 0); | 124 | gpio_set_value(setup->pdad_pin, 0); |
162 | gpio_set_value(setup->pdda_pin, 0); | 125 | gpio_set_value(setup->pdda_pin, 0); |
@@ -164,10 +127,9 @@ static int pcm3008_soc_suspend(struct platform_device *pdev, pm_message_t msg) | |||
164 | return 0; | 127 | return 0; |
165 | } | 128 | } |
166 | 129 | ||
167 | static int pcm3008_soc_resume(struct platform_device *pdev) | 130 | static int pcm3008_soc_resume(struct snd_soc_codec *codec) |
168 | { | 131 | { |
169 | struct snd_soc_device *socdev = platform_get_drvdata(pdev); | 132 | struct pcm3008_setup_data *setup = codec->dev->platform_data; |
170 | struct pcm3008_setup_data *setup = socdev->codec_data; | ||
171 | 133 | ||
172 | gpio_set_value(setup->pdad_pin, 1); | 134 | gpio_set_value(setup->pdad_pin, 1); |
173 | gpio_set_value(setup->pdda_pin, 1); | 135 | gpio_set_value(setup->pdda_pin, 1); |
@@ -179,23 +141,45 @@ static int pcm3008_soc_resume(struct platform_device *pdev) | |||
179 | #define pcm3008_soc_resume NULL | 141 | #define pcm3008_soc_resume NULL |
180 | #endif | 142 | #endif |
181 | 143 | ||
182 | struct snd_soc_codec_device soc_codec_dev_pcm3008 = { | 144 | static struct snd_soc_codec_driver soc_codec_dev_pcm3008 = { |
183 | .probe = pcm3008_soc_probe, | 145 | .probe = pcm3008_soc_probe, |
184 | .remove = pcm3008_soc_remove, | 146 | .remove = pcm3008_soc_remove, |
185 | .suspend = pcm3008_soc_suspend, | 147 | .suspend = pcm3008_soc_suspend, |
186 | .resume = pcm3008_soc_resume, | 148 | .resume = pcm3008_soc_resume, |
187 | }; | 149 | }; |
188 | EXPORT_SYMBOL_GPL(soc_codec_dev_pcm3008); | ||
189 | 150 | ||
190 | static int __init pcm3008_init(void) | 151 | static int __devinit pcm3008_codec_probe(struct platform_device *pdev) |
152 | { | ||
153 | return snd_soc_register_codec(&pdev->dev, | ||
154 | &soc_codec_dev_pcm3008, &pcm3008_dai, 1); | ||
155 | } | ||
156 | |||
157 | static int __devexit pcm3008_codec_remove(struct platform_device *pdev) | ||
158 | { | ||
159 | snd_soc_unregister_codec(&pdev->dev); | ||
160 | return 0; | ||
161 | } | ||
162 | |||
163 | MODULE_ALIAS("platform:pcm3008-codec"); | ||
164 | |||
165 | static struct platform_driver pcm3008_codec_driver = { | ||
166 | .probe = pcm3008_codec_probe, | ||
167 | .remove = __devexit_p(pcm3008_codec_remove), | ||
168 | .driver = { | ||
169 | .name = "pcm3008-codec", | ||
170 | .owner = THIS_MODULE, | ||
171 | }, | ||
172 | }; | ||
173 | |||
174 | static int __init pcm3008_modinit(void) | ||
191 | { | 175 | { |
192 | return snd_soc_register_dai(&pcm3008_dai); | 176 | return platform_driver_register(&pcm3008_codec_driver); |
193 | } | 177 | } |
194 | module_init(pcm3008_init); | 178 | module_init(pcm3008_modinit); |
195 | 179 | ||
196 | static void __exit pcm3008_exit(void) | 180 | static void __exit pcm3008_exit(void) |
197 | { | 181 | { |
198 | snd_soc_unregister_dai(&pcm3008_dai); | 182 | platform_driver_unregister(&pcm3008_codec_driver); |
199 | } | 183 | } |
200 | module_exit(pcm3008_exit); | 184 | module_exit(pcm3008_exit); |
201 | 185 | ||
diff --git a/sound/soc/codecs/pcm3008.h b/sound/soc/codecs/pcm3008.h index d04e87d3c060..7e5489ab4812 100644 --- a/sound/soc/codecs/pcm3008.h +++ b/sound/soc/codecs/pcm3008.h | |||
@@ -19,7 +19,4 @@ struct pcm3008_setup_data { | |||
19 | unsigned pdda_pin; | 19 | unsigned pdda_pin; |
20 | }; | 20 | }; |
21 | 21 | ||
22 | extern struct snd_soc_codec_device soc_codec_dev_pcm3008; | ||
23 | extern struct snd_soc_dai pcm3008_dai; | ||
24 | |||
25 | #endif | 22 | #endif |
diff --git a/sound/soc/codecs/spdif_transciever.c b/sound/soc/codecs/spdif_transciever.c index 9119836051a4..4c32b54913ad 100644 --- a/sound/soc/codecs/spdif_transciever.c +++ b/sound/soc/codecs/spdif_transciever.c | |||
@@ -21,57 +21,16 @@ | |||
21 | #include <sound/pcm.h> | 21 | #include <sound/pcm.h> |
22 | #include <sound/initval.h> | 22 | #include <sound/initval.h> |
23 | 23 | ||
24 | #include "spdif_transciever.h" | ||
25 | |||
26 | MODULE_LICENSE("GPL"); | 24 | MODULE_LICENSE("GPL"); |
27 | 25 | ||
28 | #define STUB_RATES SNDRV_PCM_RATE_8000_96000 | 26 | #define STUB_RATES SNDRV_PCM_RATE_8000_96000 |
29 | #define STUB_FORMATS SNDRV_PCM_FMTBIT_S16_LE | 27 | #define STUB_FORMATS SNDRV_PCM_FMTBIT_S16_LE |
30 | 28 | ||
31 | static struct snd_soc_codec *spdif_dit_codec; | ||
32 | |||
33 | static int spdif_dit_codec_probe(struct platform_device *pdev) | ||
34 | { | ||
35 | struct snd_soc_device *socdev = platform_get_drvdata(pdev); | ||
36 | struct snd_soc_codec *codec; | ||
37 | int ret; | ||
38 | |||
39 | if (spdif_dit_codec == NULL) { | ||
40 | dev_err(&pdev->dev, "Codec device not registered\n"); | ||
41 | return -ENODEV; | ||
42 | } | ||
43 | |||
44 | socdev->card->codec = spdif_dit_codec; | ||
45 | codec = spdif_dit_codec; | ||
46 | |||
47 | ret = snd_soc_new_pcms(socdev, SNDRV_DEFAULT_IDX1, SNDRV_DEFAULT_STR1); | ||
48 | if (ret < 0) { | ||
49 | dev_err(codec->dev, "failed to create pcms: %d\n", ret); | ||
50 | goto err_create_pcms; | ||
51 | } | ||
52 | |||
53 | return 0; | ||
54 | |||
55 | err_create_pcms: | ||
56 | return ret; | ||
57 | } | ||
58 | |||
59 | static int spdif_dit_codec_remove(struct platform_device *pdev) | ||
60 | { | ||
61 | struct snd_soc_device *socdev = platform_get_drvdata(pdev); | ||
62 | |||
63 | snd_soc_free_pcms(socdev); | ||
64 | |||
65 | return 0; | ||
66 | } | ||
67 | 29 | ||
68 | struct snd_soc_codec_device soc_codec_dev_spdif_dit = { | 30 | static struct snd_soc_codec_driver soc_codec_spdif_dit; |
69 | .probe = spdif_dit_codec_probe, | ||
70 | .remove = spdif_dit_codec_remove, | ||
71 | }; EXPORT_SYMBOL_GPL(soc_codec_dev_spdif_dit); | ||
72 | 31 | ||
73 | struct snd_soc_dai dit_stub_dai = { | 32 | static struct snd_soc_dai_driver dit_stub_dai = { |
74 | .name = "DIT", | 33 | .name = "dit-hifi", |
75 | .playback = { | 34 | .playback = { |
76 | .stream_name = "Playback", | 35 | .stream_name = "Playback", |
77 | .channels_min = 1, | 36 | .channels_min = 1, |
@@ -80,65 +39,16 @@ struct snd_soc_dai dit_stub_dai = { | |||
80 | .formats = STUB_FORMATS, | 39 | .formats = STUB_FORMATS, |
81 | }, | 40 | }, |
82 | }; | 41 | }; |
83 | EXPORT_SYMBOL_GPL(dit_stub_dai); | ||
84 | 42 | ||
85 | static int spdif_dit_probe(struct platform_device *pdev) | 43 | static int spdif_dit_probe(struct platform_device *pdev) |
86 | { | 44 | { |
87 | struct snd_soc_codec *codec; | 45 | return snd_soc_register_codec(&pdev->dev, &soc_codec_spdif_dit, |
88 | int ret; | 46 | &dit_stub_dai, 1); |
89 | |||
90 | if (spdif_dit_codec) { | ||
91 | dev_err(&pdev->dev, "Another Codec is registered\n"); | ||
92 | ret = -EINVAL; | ||
93 | goto err_reg_codec; | ||
94 | } | ||
95 | |||
96 | codec = kzalloc(sizeof(struct snd_soc_codec), GFP_KERNEL); | ||
97 | if (codec == NULL) | ||
98 | return -ENOMEM; | ||
99 | |||
100 | codec->dev = &pdev->dev; | ||
101 | |||
102 | mutex_init(&codec->mutex); | ||
103 | |||
104 | INIT_LIST_HEAD(&codec->dapm_widgets); | ||
105 | INIT_LIST_HEAD(&codec->dapm_paths); | ||
106 | |||
107 | codec->name = "spdif-dit"; | ||
108 | codec->owner = THIS_MODULE; | ||
109 | codec->dai = &dit_stub_dai; | ||
110 | codec->num_dai = 1; | ||
111 | |||
112 | spdif_dit_codec = codec; | ||
113 | |||
114 | ret = snd_soc_register_codec(codec); | ||
115 | if (ret < 0) { | ||
116 | dev_err(codec->dev, "Failed to register codec: %d\n", ret); | ||
117 | goto err_reg_codec; | ||
118 | } | ||
119 | |||
120 | dit_stub_dai.dev = &pdev->dev; | ||
121 | ret = snd_soc_register_dai(&dit_stub_dai); | ||
122 | if (ret < 0) { | ||
123 | dev_err(codec->dev, "Failed to register dai: %d\n", ret); | ||
124 | goto err_reg_dai; | ||
125 | } | ||
126 | |||
127 | return 0; | ||
128 | |||
129 | err_reg_dai: | ||
130 | snd_soc_unregister_codec(codec); | ||
131 | err_reg_codec: | ||
132 | kfree(spdif_dit_codec); | ||
133 | return ret; | ||
134 | } | 47 | } |
135 | 48 | ||
136 | static int spdif_dit_remove(struct platform_device *pdev) | 49 | static int spdif_dit_remove(struct platform_device *pdev) |
137 | { | 50 | { |
138 | snd_soc_unregister_dai(&dit_stub_dai); | 51 | snd_soc_unregister_codec(&pdev->dev); |
139 | snd_soc_unregister_codec(spdif_dit_codec); | ||
140 | kfree(spdif_dit_codec); | ||
141 | spdif_dit_codec = NULL; | ||
142 | return 0; | 52 | return 0; |
143 | } | 53 | } |
144 | 54 | ||
diff --git a/sound/soc/codecs/spdif_transciever.h b/sound/soc/codecs/spdif_transciever.h deleted file mode 100644 index 1e102124f546..000000000000 --- a/sound/soc/codecs/spdif_transciever.h +++ /dev/null | |||
@@ -1,18 +0,0 @@ | |||
1 | /* | ||
2 | * ALSA SoC DIT/DIR driver header | ||
3 | * | ||
4 | * Author: Steve Chen, <schen@mvista.com> | ||
5 | * Copyright: (C) 2008 MontaVista Software, Inc., <source@mvista.com> | ||
6 | * | ||
7 | * This program is free software; you can redistribute it and/or modify | ||
8 | * it under the terms of the GNU General Public License version 2 as | ||
9 | * published by the Free Software Foundation. | ||
10 | */ | ||
11 | |||
12 | #ifndef CODEC_STUBS_H | ||
13 | #define CODEC_STUBS_H | ||
14 | |||
15 | extern struct snd_soc_codec_device soc_codec_dev_spdif_dit; | ||
16 | extern struct snd_soc_dai dit_stub_dai; | ||
17 | |||
18 | #endif /* CODEC_STUBS_H */ | ||
diff --git a/sound/soc/codecs/ssm2602.c b/sound/soc/codecs/ssm2602.c index b47ed4f6ab20..67d8c044ca04 100644 --- a/sound/soc/codecs/ssm2602.c +++ b/sound/soc/codecs/ssm2602.c | |||
@@ -45,11 +45,11 @@ | |||
45 | 45 | ||
46 | #define SSM2602_VERSION "0.1" | 46 | #define SSM2602_VERSION "0.1" |
47 | 47 | ||
48 | struct snd_soc_codec_device soc_codec_dev_ssm2602; | ||
49 | |||
50 | /* codec private data */ | 48 | /* codec private data */ |
51 | struct ssm2602_priv { | 49 | struct ssm2602_priv { |
52 | unsigned int sysclk; | 50 | unsigned int sysclk; |
51 | enum snd_soc_control_type control_type; | ||
52 | void *control_data; | ||
53 | struct snd_pcm_substream *master_substream; | 53 | struct snd_pcm_substream *master_substream; |
54 | struct snd_pcm_substream *slave_substream; | 54 | struct snd_pcm_substream *slave_substream; |
55 | }; | 55 | }; |
@@ -276,8 +276,7 @@ static int ssm2602_hw_params(struct snd_pcm_substream *substream, | |||
276 | { | 276 | { |
277 | u16 srate; | 277 | u16 srate; |
278 | struct snd_soc_pcm_runtime *rtd = substream->private_data; | 278 | struct snd_soc_pcm_runtime *rtd = substream->private_data; |
279 | struct snd_soc_device *socdev = rtd->socdev; | 279 | struct snd_soc_codec *codec = rtd->codec; |
280 | struct snd_soc_codec *codec = socdev->card->codec; | ||
281 | struct ssm2602_priv *ssm2602 = snd_soc_codec_get_drvdata(codec); | 280 | struct ssm2602_priv *ssm2602 = snd_soc_codec_get_drvdata(codec); |
282 | struct i2c_client *i2c = codec->control_data; | 281 | struct i2c_client *i2c = codec->control_data; |
283 | u16 iface = ssm2602_read_reg_cache(codec, SSM2602_IFACE) & 0xfff3; | 282 | u16 iface = ssm2602_read_reg_cache(codec, SSM2602_IFACE) & 0xfff3; |
@@ -321,8 +320,7 @@ static int ssm2602_startup(struct snd_pcm_substream *substream, | |||
321 | struct snd_soc_dai *dai) | 320 | struct snd_soc_dai *dai) |
322 | { | 321 | { |
323 | struct snd_soc_pcm_runtime *rtd = substream->private_data; | 322 | struct snd_soc_pcm_runtime *rtd = substream->private_data; |
324 | struct snd_soc_device *socdev = rtd->socdev; | 323 | struct snd_soc_codec *codec = rtd->codec; |
325 | struct snd_soc_codec *codec = socdev->card->codec; | ||
326 | struct ssm2602_priv *ssm2602 = snd_soc_codec_get_drvdata(codec); | 324 | struct ssm2602_priv *ssm2602 = snd_soc_codec_get_drvdata(codec); |
327 | struct i2c_client *i2c = codec->control_data; | 325 | struct i2c_client *i2c = codec->control_data; |
328 | struct snd_pcm_runtime *master_runtime; | 326 | struct snd_pcm_runtime *master_runtime; |
@@ -360,8 +358,7 @@ static int ssm2602_pcm_prepare(struct snd_pcm_substream *substream, | |||
360 | struct snd_soc_dai *dai) | 358 | struct snd_soc_dai *dai) |
361 | { | 359 | { |
362 | struct snd_soc_pcm_runtime *rtd = substream->private_data; | 360 | struct snd_soc_pcm_runtime *rtd = substream->private_data; |
363 | struct snd_soc_device *socdev = rtd->socdev; | 361 | struct snd_soc_codec *codec = rtd->codec; |
364 | struct snd_soc_codec *codec = socdev->card->codec; | ||
365 | /* set active */ | 362 | /* set active */ |
366 | ssm2602_write(codec, SSM2602_ACTIVE, ACTIVE_ACTIVATE_CODEC); | 363 | ssm2602_write(codec, SSM2602_ACTIVE, ACTIVE_ACTIVATE_CODEC); |
367 | 364 | ||
@@ -372,8 +369,7 @@ static void ssm2602_shutdown(struct snd_pcm_substream *substream, | |||
372 | struct snd_soc_dai *dai) | 369 | struct snd_soc_dai *dai) |
373 | { | 370 | { |
374 | struct snd_soc_pcm_runtime *rtd = substream->private_data; | 371 | struct snd_soc_pcm_runtime *rtd = substream->private_data; |
375 | struct snd_soc_device *socdev = rtd->socdev; | 372 | struct snd_soc_codec *codec = rtd->codec; |
376 | struct snd_soc_codec *codec = socdev->card->codec; | ||
377 | struct ssm2602_priv *ssm2602 = snd_soc_codec_get_drvdata(codec); | 373 | struct ssm2602_priv *ssm2602 = snd_soc_codec_get_drvdata(codec); |
378 | 374 | ||
379 | /* deactivate */ | 375 | /* deactivate */ |
@@ -518,8 +514,8 @@ static struct snd_soc_dai_ops ssm2602_dai_ops = { | |||
518 | .set_fmt = ssm2602_set_dai_fmt, | 514 | .set_fmt = ssm2602_set_dai_fmt, |
519 | }; | 515 | }; |
520 | 516 | ||
521 | struct snd_soc_dai ssm2602_dai = { | 517 | static struct snd_soc_dai_driver ssm2602_dai = { |
522 | .name = "SSM2602", | 518 | .name = "ssm2602-hifi", |
523 | .playback = { | 519 | .playback = { |
524 | .stream_name = "Playback", | 520 | .stream_name = "Playback", |
525 | .channels_min = 2, | 521 | .channels_min = 2, |
@@ -534,21 +530,15 @@ struct snd_soc_dai ssm2602_dai = { | |||
534 | .formats = SSM2602_FORMATS,}, | 530 | .formats = SSM2602_FORMATS,}, |
535 | .ops = &ssm2602_dai_ops, | 531 | .ops = &ssm2602_dai_ops, |
536 | }; | 532 | }; |
537 | EXPORT_SYMBOL_GPL(ssm2602_dai); | ||
538 | 533 | ||
539 | static int ssm2602_suspend(struct platform_device *pdev, pm_message_t state) | 534 | static int ssm2602_suspend(struct snd_soc_codec *codec, pm_message_t state) |
540 | { | 535 | { |
541 | struct snd_soc_device *socdev = platform_get_drvdata(pdev); | ||
542 | struct snd_soc_codec *codec = socdev->card->codec; | ||
543 | |||
544 | ssm2602_set_bias_level(codec, SND_SOC_BIAS_OFF); | 536 | ssm2602_set_bias_level(codec, SND_SOC_BIAS_OFF); |
545 | return 0; | 537 | return 0; |
546 | } | 538 | } |
547 | 539 | ||
548 | static int ssm2602_resume(struct platform_device *pdev) | 540 | static int ssm2602_resume(struct snd_soc_codec *codec) |
549 | { | 541 | { |
550 | struct snd_soc_device *socdev = platform_get_drvdata(pdev); | ||
551 | struct snd_soc_codec *codec = socdev->card->codec; | ||
552 | int i; | 542 | int i; |
553 | u8 data[2]; | 543 | u8 data[2]; |
554 | u16 *cache = codec->reg_cache; | 544 | u16 *cache = codec->reg_cache; |
@@ -563,36 +553,18 @@ static int ssm2602_resume(struct platform_device *pdev) | |||
563 | return 0; | 553 | return 0; |
564 | } | 554 | } |
565 | 555 | ||
566 | /* | 556 | static int ssm2602_probe(struct snd_soc_codec *codec) |
567 | * initialise the ssm2602 driver | ||
568 | * register the mixer and dsp interfaces with the kernel | ||
569 | */ | ||
570 | static int ssm2602_init(struct snd_soc_device *socdev) | ||
571 | { | 557 | { |
572 | struct snd_soc_codec *codec = socdev->card->codec; | 558 | struct ssm2602_priv *ssm2602 = snd_soc_codec_get_drvdata(codec); |
573 | int reg, ret = 0; | 559 | int ret = 0, reg; |
574 | 560 | ||
575 | codec->name = "SSM2602"; | 561 | pr_info("ssm2602 Audio Codec %s", SSM2602_VERSION); |
576 | codec->owner = THIS_MODULE; | 562 | |
577 | codec->read = ssm2602_read_reg_cache; | 563 | codec->bias_level = SND_SOC_BIAS_OFF, |
578 | codec->write = ssm2602_write; | 564 | codec->control_data = ssm2602->control_data; |
579 | codec->set_bias_level = ssm2602_set_bias_level; | ||
580 | codec->dai = &ssm2602_dai; | ||
581 | codec->num_dai = 1; | ||
582 | codec->reg_cache_size = sizeof(ssm2602_reg); | ||
583 | codec->reg_cache = kmemdup(ssm2602_reg, sizeof(ssm2602_reg), | ||
584 | GFP_KERNEL); | ||
585 | if (codec->reg_cache == NULL) | ||
586 | return -ENOMEM; | ||
587 | 565 | ||
588 | ssm2602_reset(codec); | 566 | ssm2602_reset(codec); |
589 | 567 | ||
590 | /* register pcms */ | ||
591 | ret = snd_soc_new_pcms(socdev, SNDRV_DEFAULT_IDX1, SNDRV_DEFAULT_STR1); | ||
592 | if (ret < 0) { | ||
593 | pr_err("ssm2602: failed to create pcms\n"); | ||
594 | goto pcm_err; | ||
595 | } | ||
596 | /*power on device*/ | 568 | /*power on device*/ |
597 | ssm2602_write(codec, SSM2602_ACTIVE, 0); | 569 | ssm2602_write(codec, SSM2602_ACTIVE, 0); |
598 | /* set the update bits */ | 570 | /* set the update bits */ |
@@ -614,13 +586,27 @@ static int ssm2602_init(struct snd_soc_device *socdev) | |||
614 | ssm2602_add_widgets(codec); | 586 | ssm2602_add_widgets(codec); |
615 | 587 | ||
616 | return ret; | 588 | return ret; |
589 | } | ||
617 | 590 | ||
618 | pcm_err: | 591 | /* remove everything here */ |
619 | kfree(codec->reg_cache); | 592 | static int ssm2602_remove(struct snd_soc_codec *codec) |
620 | return ret; | 593 | { |
594 | ssm2602_set_bias_level(codec, SND_SOC_BIAS_OFF); | ||
595 | return 0; | ||
621 | } | 596 | } |
622 | 597 | ||
623 | static struct snd_soc_device *ssm2602_socdev; | 598 | static struct snd_soc_codec_driver soc_codec_dev_ssm2602 = { |
599 | .probe = ssm2602_probe, | ||
600 | .remove = ssm2602_remove, | ||
601 | .suspend = ssm2602_suspend, | ||
602 | .resume = ssm2602_resume, | ||
603 | .read = ssm2602_read_reg_cache, | ||
604 | .write = ssm2602_write, | ||
605 | .set_bias_level = ssm2602_set_bias_level, | ||
606 | .reg_cache_size = sizeof(ssm2602_reg), | ||
607 | .reg_word_size = sizeof(u16), | ||
608 | .reg_cache_default = ssm2602_reg, | ||
609 | }; | ||
624 | 610 | ||
625 | #if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE) | 611 | #if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE) |
626 | /* | 612 | /* |
@@ -632,24 +618,28 @@ static struct snd_soc_device *ssm2602_socdev; | |||
632 | static int ssm2602_i2c_probe(struct i2c_client *i2c, | 618 | static int ssm2602_i2c_probe(struct i2c_client *i2c, |
633 | const struct i2c_device_id *id) | 619 | const struct i2c_device_id *id) |
634 | { | 620 | { |
635 | struct snd_soc_device *socdev = ssm2602_socdev; | 621 | struct ssm2602_priv *ssm2602; |
636 | struct snd_soc_codec *codec = socdev->card->codec; | ||
637 | int ret; | 622 | int ret; |
638 | 623 | ||
639 | i2c_set_clientdata(i2c, codec); | 624 | ssm2602 = kzalloc(sizeof(struct ssm2602_priv), GFP_KERNEL); |
640 | codec->control_data = i2c; | 625 | if (ssm2602 == NULL) |
626 | return -ENOMEM; | ||
641 | 627 | ||
642 | ret = ssm2602_init(socdev); | 628 | i2c_set_clientdata(i2c, ssm2602); |
643 | if (ret < 0) | 629 | ssm2602->control_data = i2c; |
644 | pr_err("failed to initialise SSM2602\n"); | 630 | ssm2602->control_type = SND_SOC_I2C; |
645 | 631 | ||
632 | ret = snd_soc_register_codec(&i2c->dev, | ||
633 | &soc_codec_dev_ssm2602, &ssm2602_dai, 1); | ||
634 | if (ret < 0) | ||
635 | kfree(ssm2602); | ||
646 | return ret; | 636 | return ret; |
647 | } | 637 | } |
648 | 638 | ||
649 | static int ssm2602_i2c_remove(struct i2c_client *client) | 639 | static int ssm2602_i2c_remove(struct i2c_client *client) |
650 | { | 640 | { |
651 | struct snd_soc_codec *codec = i2c_get_clientdata(client); | 641 | snd_soc_unregister_codec(&client->dev); |
652 | kfree(codec->reg_cache); | 642 | kfree(i2c_get_clientdata(client)); |
653 | return 0; | 643 | return 0; |
654 | } | 644 | } |
655 | 645 | ||
@@ -658,130 +648,39 @@ static const struct i2c_device_id ssm2602_i2c_id[] = { | |||
658 | { } | 648 | { } |
659 | }; | 649 | }; |
660 | MODULE_DEVICE_TABLE(i2c, ssm2602_i2c_id); | 650 | MODULE_DEVICE_TABLE(i2c, ssm2602_i2c_id); |
651 | |||
661 | /* corgi i2c codec control layer */ | 652 | /* corgi i2c codec control layer */ |
662 | static struct i2c_driver ssm2602_i2c_driver = { | 653 | static struct i2c_driver ssm2602_i2c_driver = { |
663 | .driver = { | 654 | .driver = { |
664 | .name = "SSM2602 I2C Codec", | 655 | .name = "ssm2602-codec", |
665 | .owner = THIS_MODULE, | 656 | .owner = THIS_MODULE, |
666 | }, | 657 | }, |
667 | .probe = ssm2602_i2c_probe, | 658 | .probe = ssm2602_i2c_probe, |
668 | .remove = ssm2602_i2c_remove, | 659 | .remove = ssm2602_i2c_remove, |
669 | .id_table = ssm2602_i2c_id, | 660 | .id_table = ssm2602_i2c_id, |
670 | }; | 661 | }; |
671 | |||
672 | static int ssm2602_add_i2c_device(struct platform_device *pdev, | ||
673 | const struct ssm2602_setup_data *setup) | ||
674 | { | ||
675 | struct i2c_board_info info; | ||
676 | struct i2c_adapter *adapter; | ||
677 | struct i2c_client *client; | ||
678 | int ret; | ||
679 | |||
680 | ret = i2c_add_driver(&ssm2602_i2c_driver); | ||
681 | if (ret != 0) { | ||
682 | dev_err(&pdev->dev, "can't add i2c driver\n"); | ||
683 | return ret; | ||
684 | } | ||
685 | memset(&info, 0, sizeof(struct i2c_board_info)); | ||
686 | info.addr = setup->i2c_address; | ||
687 | strlcpy(info.type, "ssm2602", I2C_NAME_SIZE); | ||
688 | adapter = i2c_get_adapter(setup->i2c_bus); | ||
689 | if (!adapter) { | ||
690 | dev_err(&pdev->dev, "can't get i2c adapter %d\n", | ||
691 | setup->i2c_bus); | ||
692 | goto err_driver; | ||
693 | } | ||
694 | client = i2c_new_device(adapter, &info); | ||
695 | i2c_put_adapter(adapter); | ||
696 | if (!client) { | ||
697 | dev_err(&pdev->dev, "can't add i2c device at 0x%x\n", | ||
698 | (unsigned int)info.addr); | ||
699 | goto err_driver; | ||
700 | } | ||
701 | return 0; | ||
702 | err_driver: | ||
703 | i2c_del_driver(&ssm2602_i2c_driver); | ||
704 | return -ENODEV; | ||
705 | } | ||
706 | #endif | 662 | #endif |
707 | 663 | ||
708 | static int ssm2602_probe(struct platform_device *pdev) | 664 | |
665 | static int __init ssm2602_modinit(void) | ||
709 | { | 666 | { |
710 | struct snd_soc_device *socdev = platform_get_drvdata(pdev); | ||
711 | struct ssm2602_setup_data *setup; | ||
712 | struct snd_soc_codec *codec; | ||
713 | struct ssm2602_priv *ssm2602; | ||
714 | int ret = 0; | 667 | int ret = 0; |
715 | |||
716 | pr_info("ssm2602 Audio Codec %s", SSM2602_VERSION); | ||
717 | |||
718 | setup = socdev->codec_data; | ||
719 | codec = kzalloc(sizeof(struct snd_soc_codec), GFP_KERNEL); | ||
720 | if (codec == NULL) | ||
721 | return -ENOMEM; | ||
722 | |||
723 | ssm2602 = kzalloc(sizeof(struct ssm2602_priv), GFP_KERNEL); | ||
724 | if (ssm2602 == NULL) { | ||
725 | kfree(codec); | ||
726 | return -ENOMEM; | ||
727 | } | ||
728 | |||
729 | snd_soc_codec_set_drvdata(codec, ssm2602); | ||
730 | socdev->card->codec = codec; | ||
731 | mutex_init(&codec->mutex); | ||
732 | INIT_LIST_HEAD(&codec->dapm_widgets); | ||
733 | INIT_LIST_HEAD(&codec->dapm_paths); | ||
734 | |||
735 | ssm2602_socdev = socdev; | ||
736 | #if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE) | 668 | #if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE) |
737 | if (setup->i2c_address) { | 669 | ret = i2c_add_driver(&ssm2602_i2c_driver); |
738 | codec->hw_write = (hw_write_t)i2c_master_send; | 670 | if (ret != 0) { |
739 | ret = ssm2602_add_i2c_device(pdev, setup); | 671 | printk(KERN_ERR "Failed to register SSM2602 I2C driver: %d\n", |
672 | ret); | ||
740 | } | 673 | } |
741 | #else | ||
742 | /* other interfaces */ | ||
743 | #endif | 674 | #endif |
744 | return ret; | 675 | return ret; |
745 | } | 676 | } |
677 | module_init(ssm2602_modinit); | ||
746 | 678 | ||
747 | /* remove everything here */ | 679 | static void __exit ssm2602_exit(void) |
748 | static int ssm2602_remove(struct platform_device *pdev) | ||
749 | { | 680 | { |
750 | struct snd_soc_device *socdev = platform_get_drvdata(pdev); | ||
751 | struct snd_soc_codec *codec = socdev->card->codec; | ||
752 | |||
753 | if (codec->control_data) | ||
754 | ssm2602_set_bias_level(codec, SND_SOC_BIAS_OFF); | ||
755 | |||
756 | snd_soc_free_pcms(socdev); | ||
757 | snd_soc_dapm_free(socdev); | ||
758 | #if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE) | 681 | #if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE) |
759 | i2c_unregister_device(codec->control_data); | ||
760 | i2c_del_driver(&ssm2602_i2c_driver); | 682 | i2c_del_driver(&ssm2602_i2c_driver); |
761 | #endif | 683 | #endif |
762 | kfree(snd_soc_codec_get_drvdata(codec)); | ||
763 | kfree(codec); | ||
764 | |||
765 | return 0; | ||
766 | } | ||
767 | |||
768 | struct snd_soc_codec_device soc_codec_dev_ssm2602 = { | ||
769 | .probe = ssm2602_probe, | ||
770 | .remove = ssm2602_remove, | ||
771 | .suspend = ssm2602_suspend, | ||
772 | .resume = ssm2602_resume, | ||
773 | }; | ||
774 | EXPORT_SYMBOL_GPL(soc_codec_dev_ssm2602); | ||
775 | |||
776 | static int __init ssm2602_modinit(void) | ||
777 | { | ||
778 | return snd_soc_register_dai(&ssm2602_dai); | ||
779 | } | ||
780 | module_init(ssm2602_modinit); | ||
781 | |||
782 | static void __exit ssm2602_exit(void) | ||
783 | { | ||
784 | snd_soc_unregister_dai(&ssm2602_dai); | ||
785 | } | 684 | } |
786 | module_exit(ssm2602_exit); | 685 | module_exit(ssm2602_exit); |
787 | 686 | ||
diff --git a/sound/soc/codecs/ssm2602.h b/sound/soc/codecs/ssm2602.h index f344e6d76e31..42a47d0f8e25 100644 --- a/sound/soc/codecs/ssm2602.h +++ b/sound/soc/codecs/ssm2602.h | |||
@@ -124,7 +124,4 @@ struct ssm2602_setup_data { | |||
124 | unsigned short i2c_address; | 124 | unsigned short i2c_address; |
125 | }; | 125 | }; |
126 | 126 | ||
127 | extern struct snd_soc_dai ssm2602_dai; | ||
128 | extern struct snd_soc_codec_device soc_codec_dev_ssm2602; | ||
129 | |||
130 | #endif | 127 | #endif |
diff --git a/sound/soc/codecs/stac9766.c b/sound/soc/codecs/stac9766.c index ee86568545c2..00d67cc8e206 100644 --- a/sound/soc/codecs/stac9766.c +++ b/sound/soc/codecs/stac9766.c | |||
@@ -25,7 +25,6 @@ | |||
25 | #include <sound/pcm_params.h> | 25 | #include <sound/pcm_params.h> |
26 | #include <sound/soc.h> | 26 | #include <sound/soc.h> |
27 | #include <sound/tlv.h> | 27 | #include <sound/tlv.h> |
28 | #include <sound/soc-of-simple.h> | ||
29 | 28 | ||
30 | #include "stac9766.h" | 29 | #include "stac9766.h" |
31 | 30 | ||
@@ -257,20 +256,15 @@ static int stac9766_reset(struct snd_soc_codec *codec, int try_warm) | |||
257 | return 0; | 256 | return 0; |
258 | } | 257 | } |
259 | 258 | ||
260 | static int stac9766_codec_suspend(struct platform_device *pdev, | 259 | static int stac9766_codec_suspend(struct snd_soc_codec *codec, |
261 | pm_message_t state) | 260 | pm_message_t state) |
262 | { | 261 | { |
263 | struct snd_soc_device *socdev = platform_get_drvdata(pdev); | ||
264 | struct snd_soc_codec *codec = socdev->card->codec; | ||
265 | |||
266 | stac9766_set_bias_level(codec, SND_SOC_BIAS_OFF); | 262 | stac9766_set_bias_level(codec, SND_SOC_BIAS_OFF); |
267 | return 0; | 263 | return 0; |
268 | } | 264 | } |
269 | 265 | ||
270 | static int stac9766_codec_resume(struct platform_device *pdev) | 266 | static int stac9766_codec_resume(struct snd_soc_codec *codec) |
271 | { | 267 | { |
272 | struct snd_soc_device *socdev = platform_get_drvdata(pdev); | ||
273 | struct snd_soc_codec *codec = socdev->card->codec; | ||
274 | u16 id, reset; | 268 | u16 id, reset; |
275 | 269 | ||
276 | reset = 0; | 270 | reset = 0; |
@@ -300,10 +294,9 @@ static struct snd_soc_dai_ops stac9766_dai_ops_digital = { | |||
300 | .prepare = ac97_digital_prepare, | 294 | .prepare = ac97_digital_prepare, |
301 | }; | 295 | }; |
302 | 296 | ||
303 | struct snd_soc_dai stac9766_dai[] = { | 297 | static struct snd_soc_dai_driver stac9766_dai[] = { |
304 | { | 298 | { |
305 | .name = "stac9766 analog", | 299 | .name = "stac9766-hifi-analog", |
306 | .id = 0, | ||
307 | .ac97_control = 1, | 300 | .ac97_control = 1, |
308 | 301 | ||
309 | /* stream cababilities */ | 302 | /* stream cababilities */ |
@@ -325,8 +318,7 @@ struct snd_soc_dai stac9766_dai[] = { | |||
325 | .ops = &stac9766_dai_ops_analog, | 318 | .ops = &stac9766_dai_ops_analog, |
326 | }, | 319 | }, |
327 | { | 320 | { |
328 | .name = "stac9766 IEC958", | 321 | .name = "stac9766-hifi-IEC958", |
329 | .id = 1, | ||
330 | .ac97_control = 1, | 322 | .ac97_control = 1, |
331 | 323 | ||
332 | /* stream cababilities */ | 324 | /* stream cababilities */ |
@@ -342,57 +334,24 @@ struct snd_soc_dai stac9766_dai[] = { | |||
342 | .ops = &stac9766_dai_ops_digital, | 334 | .ops = &stac9766_dai_ops_digital, |
343 | } | 335 | } |
344 | }; | 336 | }; |
345 | EXPORT_SYMBOL_GPL(stac9766_dai); | ||
346 | 337 | ||
347 | static int stac9766_codec_probe(struct platform_device *pdev) | 338 | static int stac9766_codec_probe(struct snd_soc_codec *codec) |
348 | { | 339 | { |
349 | struct snd_soc_device *socdev = platform_get_drvdata(pdev); | ||
350 | struct snd_soc_codec *codec; | ||
351 | int ret = 0; | 340 | int ret = 0; |
352 | 341 | ||
353 | printk(KERN_INFO "STAC9766 SoC Audio Codec %s\n", STAC9766_VERSION); | 342 | printk(KERN_INFO "STAC9766 SoC Audio Codec %s\n", STAC9766_VERSION); |
354 | 343 | ||
355 | socdev->card->codec = kzalloc(sizeof(struct snd_soc_codec), GFP_KERNEL); | ||
356 | if (socdev->card->codec == NULL) | ||
357 | return -ENOMEM; | ||
358 | codec = socdev->card->codec; | ||
359 | mutex_init(&codec->mutex); | ||
360 | |||
361 | codec->reg_cache = kmemdup(stac9766_reg, sizeof(stac9766_reg), | ||
362 | GFP_KERNEL); | ||
363 | if (codec->reg_cache == NULL) { | ||
364 | ret = -ENOMEM; | ||
365 | goto cache_err; | ||
366 | } | ||
367 | codec->reg_cache_size = sizeof(stac9766_reg); | ||
368 | codec->reg_cache_step = 2; | ||
369 | |||
370 | codec->name = "STAC9766"; | ||
371 | codec->owner = THIS_MODULE; | ||
372 | codec->dai = stac9766_dai; | ||
373 | codec->num_dai = ARRAY_SIZE(stac9766_dai); | ||
374 | codec->write = stac9766_ac97_write; | ||
375 | codec->read = stac9766_ac97_read; | ||
376 | codec->set_bias_level = stac9766_set_bias_level; | ||
377 | INIT_LIST_HEAD(&codec->dapm_widgets); | ||
378 | INIT_LIST_HEAD(&codec->dapm_paths); | ||
379 | |||
380 | ret = snd_soc_new_ac97_codec(codec, &soc_ac97_ops, 0); | 344 | ret = snd_soc_new_ac97_codec(codec, &soc_ac97_ops, 0); |
381 | if (ret < 0) | 345 | if (ret < 0) |
382 | goto codec_err; | 346 | goto codec_err; |
383 | 347 | ||
384 | /* register pcms */ | ||
385 | ret = snd_soc_new_pcms(socdev, SNDRV_DEFAULT_IDX1, SNDRV_DEFAULT_STR1); | ||
386 | if (ret < 0) | ||
387 | goto pcm_err; | ||
388 | |||
389 | /* do a cold reset for the controller and then try | 348 | /* do a cold reset for the controller and then try |
390 | * a warm reset followed by an optional cold reset for codec */ | 349 | * a warm reset followed by an optional cold reset for codec */ |
391 | stac9766_reset(codec, 0); | 350 | stac9766_reset(codec, 0); |
392 | ret = stac9766_reset(codec, 1); | 351 | ret = stac9766_reset(codec, 1); |
393 | if (ret < 0) { | 352 | if (ret < 0) { |
394 | printk(KERN_ERR "Failed to reset STAC9766: AC97 link error\n"); | 353 | printk(KERN_ERR "Failed to reset STAC9766: AC97 link error\n"); |
395 | goto reset_err; | 354 | goto codec_err; |
396 | } | 355 | } |
397 | 356 | ||
398 | stac9766_set_bias_level(codec, SND_SOC_BIAS_STANDBY); | 357 | stac9766_set_bias_level(codec, SND_SOC_BIAS_STANDBY); |
@@ -402,40 +361,63 @@ static int stac9766_codec_probe(struct platform_device *pdev) | |||
402 | 361 | ||
403 | return 0; | 362 | return 0; |
404 | 363 | ||
405 | reset_err: | ||
406 | snd_soc_free_pcms(socdev); | ||
407 | pcm_err: | ||
408 | snd_soc_free_ac97_codec(codec); | ||
409 | codec_err: | 364 | codec_err: |
410 | kfree(snd_soc_codec_get_drvdata(codec)); | 365 | snd_soc_free_ac97_codec(codec); |
411 | cache_err: | ||
412 | kfree(socdev->card->codec); | ||
413 | socdev->card->codec = NULL; | ||
414 | return ret; | 366 | return ret; |
415 | } | 367 | } |
416 | 368 | ||
417 | static int stac9766_codec_remove(struct platform_device *pdev) | 369 | static int stac9766_codec_remove(struct snd_soc_codec *codec) |
418 | { | 370 | { |
419 | struct snd_soc_device *socdev = platform_get_drvdata(pdev); | ||
420 | struct snd_soc_codec *codec = socdev->card->codec; | ||
421 | |||
422 | if (codec == NULL) | ||
423 | return 0; | ||
424 | |||
425 | snd_soc_free_pcms(socdev); | ||
426 | snd_soc_free_ac97_codec(codec); | 371 | snd_soc_free_ac97_codec(codec); |
427 | kfree(codec->reg_cache); | ||
428 | kfree(codec); | ||
429 | return 0; | 372 | return 0; |
430 | } | 373 | } |
431 | 374 | ||
432 | struct snd_soc_codec_device soc_codec_dev_stac9766 = { | 375 | static struct snd_soc_codec_driver soc_codec_dev_stac9766 = { |
376 | .write = stac9766_ac97_write, | ||
377 | .read = stac9766_ac97_read, | ||
378 | .set_bias_level = stac9766_set_bias_level, | ||
433 | .probe = stac9766_codec_probe, | 379 | .probe = stac9766_codec_probe, |
434 | .remove = stac9766_codec_remove, | 380 | .remove = stac9766_codec_remove, |
435 | .suspend = stac9766_codec_suspend, | 381 | .suspend = stac9766_codec_suspend, |
436 | .resume = stac9766_codec_resume, | 382 | .resume = stac9766_codec_resume, |
383 | .reg_cache_size = sizeof(stac9766_reg), | ||
384 | .reg_word_size = sizeof(u16), | ||
385 | .reg_cache_step = 2, | ||
386 | }; | ||
387 | |||
388 | static __devinit int stac9766_probe(struct platform_device *pdev) | ||
389 | { | ||
390 | return snd_soc_register_codec(&pdev->dev, | ||
391 | &soc_codec_dev_stac9766, stac9766_dai, ARRAY_SIZE(stac9766_dai)); | ||
392 | } | ||
393 | |||
394 | static int __devexit stac9766_remove(struct platform_device *pdev) | ||
395 | { | ||
396 | snd_soc_unregister_codec(&pdev->dev); | ||
397 | return 0; | ||
398 | } | ||
399 | |||
400 | static struct platform_driver stac9766_codec_driver = { | ||
401 | .driver = { | ||
402 | .name = "stac9766-codec", | ||
403 | .owner = THIS_MODULE, | ||
404 | }, | ||
405 | |||
406 | .probe = stac9766_probe, | ||
407 | .remove = __devexit_p(stac9766_remove), | ||
437 | }; | 408 | }; |
438 | EXPORT_SYMBOL_GPL(soc_codec_dev_stac9766); | 409 | |
410 | static int __init stac9766_init(void) | ||
411 | { | ||
412 | return platform_driver_register(&stac9766_codec_driver); | ||
413 | } | ||
414 | module_init(stac9766_init); | ||
415 | |||
416 | static void __exit stac9766_exit(void) | ||
417 | { | ||
418 | platform_driver_unregister(&stac9766_codec_driver); | ||
419 | } | ||
420 | module_exit(stac9766_exit); | ||
439 | 421 | ||
440 | MODULE_DESCRIPTION("ASoC stac9766 driver"); | 422 | MODULE_DESCRIPTION("ASoC stac9766 driver"); |
441 | MODULE_AUTHOR("Jon Smirl <jonsmirl@gmail.com>"); | 423 | MODULE_AUTHOR("Jon Smirl <jonsmirl@gmail.com>"); |
diff --git a/sound/soc/codecs/stac9766.h b/sound/soc/codecs/stac9766.h index 65642eb8393e..c726f907e2c0 100644 --- a/sound/soc/codecs/stac9766.h +++ b/sound/soc/codecs/stac9766.h | |||
@@ -14,8 +14,4 @@ | |||
14 | #define STAC9766_DAI_AC97_ANALOG 0 | 14 | #define STAC9766_DAI_AC97_ANALOG 0 |
15 | #define STAC9766_DAI_AC97_DIGITAL 1 | 15 | #define STAC9766_DAI_AC97_DIGITAL 1 |
16 | 16 | ||
17 | extern struct snd_soc_dai stac9766_dai[]; | ||
18 | extern struct snd_soc_codec_device soc_codec_dev_stac9766; | ||
19 | |||
20 | |||
21 | #endif | 17 | #endif |
diff --git a/sound/soc/codecs/tlv320aic23.c b/sound/soc/codecs/tlv320aic23.c index 0a4b0fef3355..e8652b1ae326 100644 --- a/sound/soc/codecs/tlv320aic23.c +++ b/sound/soc/codecs/tlv320aic23.c | |||
@@ -240,7 +240,8 @@ static const struct snd_soc_dapm_route intercon[] = { | |||
240 | 240 | ||
241 | /* AIC23 driver data */ | 241 | /* AIC23 driver data */ |
242 | struct aic23 { | 242 | struct aic23 { |
243 | struct snd_soc_codec codec; | 243 | enum snd_soc_control_type control_type; |
244 | void *control_data; | ||
244 | int mclk; | 245 | int mclk; |
245 | int requested_adc; | 246 | int requested_adc; |
246 | int requested_dac; | 247 | int requested_dac; |
@@ -404,11 +405,10 @@ static int tlv320aic23_hw_params(struct snd_pcm_substream *substream, | |||
404 | struct snd_soc_dai *dai) | 405 | struct snd_soc_dai *dai) |
405 | { | 406 | { |
406 | struct snd_soc_pcm_runtime *rtd = substream->private_data; | 407 | struct snd_soc_pcm_runtime *rtd = substream->private_data; |
407 | struct snd_soc_device *socdev = rtd->socdev; | 408 | struct snd_soc_codec *codec = rtd->codec; |
408 | struct snd_soc_codec *codec = socdev->card->codec; | ||
409 | u16 iface_reg; | 409 | u16 iface_reg; |
410 | int ret; | 410 | int ret; |
411 | struct aic23 *aic23 = container_of(codec, struct aic23, codec); | 411 | struct aic23 *aic23 = snd_soc_codec_get_drvdata(codec); |
412 | u32 sample_rate_adc = aic23->requested_adc; | 412 | u32 sample_rate_adc = aic23->requested_adc; |
413 | u32 sample_rate_dac = aic23->requested_dac; | 413 | u32 sample_rate_dac = aic23->requested_dac; |
414 | u32 sample_rate = params_rate(params); | 414 | u32 sample_rate = params_rate(params); |
@@ -452,8 +452,7 @@ static int tlv320aic23_pcm_prepare(struct snd_pcm_substream *substream, | |||
452 | struct snd_soc_dai *dai) | 452 | struct snd_soc_dai *dai) |
453 | { | 453 | { |
454 | struct snd_soc_pcm_runtime *rtd = substream->private_data; | 454 | struct snd_soc_pcm_runtime *rtd = substream->private_data; |
455 | struct snd_soc_device *socdev = rtd->socdev; | 455 | struct snd_soc_codec *codec = rtd->codec; |
456 | struct snd_soc_codec *codec = socdev->card->codec; | ||
457 | 456 | ||
458 | /* set active */ | 457 | /* set active */ |
459 | tlv320aic23_write(codec, TLV320AIC23_ACTIVE, 0x0001); | 458 | tlv320aic23_write(codec, TLV320AIC23_ACTIVE, 0x0001); |
@@ -465,9 +464,8 @@ static void tlv320aic23_shutdown(struct snd_pcm_substream *substream, | |||
465 | struct snd_soc_dai *dai) | 464 | struct snd_soc_dai *dai) |
466 | { | 465 | { |
467 | struct snd_soc_pcm_runtime *rtd = substream->private_data; | 466 | struct snd_soc_pcm_runtime *rtd = substream->private_data; |
468 | struct snd_soc_device *socdev = rtd->socdev; | 467 | struct snd_soc_codec *codec = rtd->codec; |
469 | struct snd_soc_codec *codec = socdev->card->codec; | 468 | struct aic23 *aic23 = snd_soc_codec_get_drvdata(codec); |
470 | struct aic23 *aic23 = container_of(codec, struct aic23, codec); | ||
471 | 469 | ||
472 | /* deactivate */ | 470 | /* deactivate */ |
473 | if (!codec->active) { | 471 | if (!codec->active) { |
@@ -546,8 +544,7 @@ static int tlv320aic23_set_dai_fmt(struct snd_soc_dai *codec_dai, | |||
546 | static int tlv320aic23_set_dai_sysclk(struct snd_soc_dai *codec_dai, | 544 | static int tlv320aic23_set_dai_sysclk(struct snd_soc_dai *codec_dai, |
547 | int clk_id, unsigned int freq, int dir) | 545 | int clk_id, unsigned int freq, int dir) |
548 | { | 546 | { |
549 | struct snd_soc_codec *codec = codec_dai->codec; | 547 | struct aic23 *aic23 = snd_soc_dai_get_drvdata(codec_dai); |
550 | struct aic23 *aic23 = container_of(codec, struct aic23, codec); | ||
551 | aic23->mclk = freq; | 548 | aic23->mclk = freq; |
552 | return 0; | 549 | return 0; |
553 | } | 550 | } |
@@ -594,8 +591,8 @@ static struct snd_soc_dai_ops tlv320aic23_dai_ops = { | |||
594 | .set_sysclk = tlv320aic23_set_dai_sysclk, | 591 | .set_sysclk = tlv320aic23_set_dai_sysclk, |
595 | }; | 592 | }; |
596 | 593 | ||
597 | struct snd_soc_dai tlv320aic23_dai = { | 594 | static struct snd_soc_dai_driver tlv320aic23_dai = { |
598 | .name = "tlv320aic23", | 595 | .name = "tlv320aic23-hifi", |
599 | .playback = { | 596 | .playback = { |
600 | .stream_name = "Playback", | 597 | .stream_name = "Playback", |
601 | .channels_min = 2, | 598 | .channels_min = 2, |
@@ -610,23 +607,17 @@ struct snd_soc_dai tlv320aic23_dai = { | |||
610 | .formats = AIC23_FORMATS,}, | 607 | .formats = AIC23_FORMATS,}, |
611 | .ops = &tlv320aic23_dai_ops, | 608 | .ops = &tlv320aic23_dai_ops, |
612 | }; | 609 | }; |
613 | EXPORT_SYMBOL_GPL(tlv320aic23_dai); | ||
614 | 610 | ||
615 | static int tlv320aic23_suspend(struct platform_device *pdev, | 611 | static int tlv320aic23_suspend(struct snd_soc_codec *codec, |
616 | pm_message_t state) | 612 | pm_message_t state) |
617 | { | 613 | { |
618 | struct snd_soc_device *socdev = platform_get_drvdata(pdev); | ||
619 | struct snd_soc_codec *codec = socdev->card->codec; | ||
620 | |||
621 | tlv320aic23_set_bias_level(codec, SND_SOC_BIAS_OFF); | 614 | tlv320aic23_set_bias_level(codec, SND_SOC_BIAS_OFF); |
622 | 615 | ||
623 | return 0; | 616 | return 0; |
624 | } | 617 | } |
625 | 618 | ||
626 | static int tlv320aic23_resume(struct platform_device *pdev) | 619 | static int tlv320aic23_resume(struct snd_soc_codec *codec) |
627 | { | 620 | { |
628 | struct snd_soc_device *socdev = platform_get_drvdata(pdev); | ||
629 | struct snd_soc_codec *codec = socdev->card->codec; | ||
630 | u16 reg; | 621 | u16 reg; |
631 | 622 | ||
632 | /* Sync reg_cache with the hardware */ | 623 | /* Sync reg_cache with the hardware */ |
@@ -639,39 +630,19 @@ static int tlv320aic23_resume(struct platform_device *pdev) | |||
639 | return 0; | 630 | return 0; |
640 | } | 631 | } |
641 | 632 | ||
642 | /* | 633 | static int tlv320aic23_probe(struct snd_soc_codec *codec) |
643 | * initialise the AIC23 driver | ||
644 | * register the mixer and dsp interfaces with the kernel | ||
645 | */ | ||
646 | static int tlv320aic23_init(struct snd_soc_device *socdev) | ||
647 | { | 634 | { |
648 | struct snd_soc_codec *codec = socdev->card->codec; | 635 | struct aic23 *aic23 = snd_soc_codec_get_drvdata(codec); |
649 | int ret = 0; | 636 | int reg; |
650 | u16 reg; | ||
651 | 637 | ||
652 | codec->name = "tlv320aic23"; | 638 | printk(KERN_INFO "AIC23 Audio Codec %s\n", AIC23_VERSION); |
653 | codec->owner = THIS_MODULE; | 639 | codec->control_data = aic23->control_data; |
654 | codec->read = tlv320aic23_read_reg_cache; | 640 | codec->hw_write = (hw_write_t)i2c_master_send; |
655 | codec->write = tlv320aic23_write; | 641 | codec->hw_read = NULL; |
656 | codec->set_bias_level = tlv320aic23_set_bias_level; | ||
657 | codec->dai = &tlv320aic23_dai; | ||
658 | codec->num_dai = 1; | ||
659 | codec->reg_cache_size = ARRAY_SIZE(tlv320aic23_reg); | ||
660 | codec->reg_cache = | ||
661 | kmemdup(tlv320aic23_reg, sizeof(tlv320aic23_reg), GFP_KERNEL); | ||
662 | if (codec->reg_cache == NULL) | ||
663 | return -ENOMEM; | ||
664 | 642 | ||
665 | /* Reset codec */ | 643 | /* Reset codec */ |
666 | tlv320aic23_write(codec, TLV320AIC23_RESET, 0); | 644 | tlv320aic23_write(codec, TLV320AIC23_RESET, 0); |
667 | 645 | ||
668 | /* register pcms */ | ||
669 | ret = snd_soc_new_pcms(socdev, SNDRV_DEFAULT_IDX1, SNDRV_DEFAULT_STR1); | ||
670 | if (ret < 0) { | ||
671 | printk(KERN_ERR "tlv320aic23: failed to create pcms\n"); | ||
672 | goto pcm_err; | ||
673 | } | ||
674 | |||
675 | /* power on device */ | 646 | /* power on device */ |
676 | tlv320aic23_set_bias_level(codec, SND_SOC_BIAS_STANDBY); | 647 | tlv320aic23_set_bias_level(codec, SND_SOC_BIAS_STANDBY); |
677 | 648 | ||
@@ -707,13 +678,27 @@ static int tlv320aic23_init(struct snd_soc_device *socdev) | |||
707 | ARRAY_SIZE(tlv320aic23_snd_controls)); | 678 | ARRAY_SIZE(tlv320aic23_snd_controls)); |
708 | tlv320aic23_add_widgets(codec); | 679 | tlv320aic23_add_widgets(codec); |
709 | 680 | ||
710 | return ret; | 681 | return 0; |
682 | } | ||
711 | 683 | ||
712 | pcm_err: | 684 | static int tlv320aic23_remove(struct snd_soc_codec *codec) |
713 | kfree(codec->reg_cache); | 685 | { |
714 | return ret; | 686 | tlv320aic23_set_bias_level(codec, SND_SOC_BIAS_OFF); |
687 | return 0; | ||
715 | } | 688 | } |
716 | static struct snd_soc_device *tlv320aic23_socdev; | 689 | |
690 | static struct snd_soc_codec_driver soc_codec_dev_tlv320aic23 = { | ||
691 | .reg_cache_size = ARRAY_SIZE(tlv320aic23_reg), | ||
692 | .reg_word_size = sizeof(u16), | ||
693 | .reg_cache_default = tlv320aic23_reg, | ||
694 | .probe = tlv320aic23_probe, | ||
695 | .remove = tlv320aic23_remove, | ||
696 | .suspend = tlv320aic23_suspend, | ||
697 | .resume = tlv320aic23_resume, | ||
698 | .read = tlv320aic23_read_reg_cache, | ||
699 | .write = tlv320aic23_write, | ||
700 | .set_bias_level = tlv320aic23_set_bias_level, | ||
701 | }; | ||
717 | 702 | ||
718 | #if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE) | 703 | #if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE) |
719 | /* | 704 | /* |
@@ -723,31 +708,30 @@ static struct snd_soc_device *tlv320aic23_socdev; | |||
723 | static int tlv320aic23_codec_probe(struct i2c_client *i2c, | 708 | static int tlv320aic23_codec_probe(struct i2c_client *i2c, |
724 | const struct i2c_device_id *i2c_id) | 709 | const struct i2c_device_id *i2c_id) |
725 | { | 710 | { |
726 | struct snd_soc_device *socdev = tlv320aic23_socdev; | 711 | struct aic23 *aic23; |
727 | struct snd_soc_codec *codec = socdev->card->codec; | ||
728 | int ret; | 712 | int ret; |
729 | 713 | ||
730 | if (!i2c_check_functionality(i2c->adapter, I2C_FUNC_SMBUS_BYTE_DATA)) | 714 | if (!i2c_check_functionality(i2c->adapter, I2C_FUNC_SMBUS_BYTE_DATA)) |
731 | return -EINVAL; | 715 | return -EINVAL; |
732 | 716 | ||
733 | i2c_set_clientdata(i2c, codec); | 717 | aic23 = kzalloc(sizeof(struct aic23), GFP_KERNEL); |
734 | codec->control_data = i2c; | 718 | if (aic23 == NULL) |
719 | return -ENOMEM; | ||
735 | 720 | ||
736 | ret = tlv320aic23_init(socdev); | 721 | i2c_set_clientdata(i2c, aic23); |
737 | if (ret < 0) { | 722 | aic23->control_data = i2c; |
738 | printk(KERN_ERR "tlv320aic23: failed to initialise AIC23\n"); | 723 | aic23->control_type = SND_SOC_I2C; |
739 | goto err; | ||
740 | } | ||
741 | return ret; | ||
742 | 724 | ||
743 | err: | 725 | ret = snd_soc_register_codec(&i2c->dev, |
744 | kfree(codec); | 726 | &soc_codec_dev_tlv320aic23, &tlv320aic23_dai, 1); |
745 | kfree(i2c); | 727 | if (ret < 0) |
728 | kfree(aic23); | ||
746 | return ret; | 729 | return ret; |
747 | } | 730 | } |
748 | static int __exit tlv320aic23_i2c_remove(struct i2c_client *i2c) | 731 | static int __exit tlv320aic23_i2c_remove(struct i2c_client *i2c) |
749 | { | 732 | { |
750 | put_device(&i2c->dev); | 733 | snd_soc_unregister_codec(&i2c->dev); |
734 | kfree(i2c_get_clientdata(i2c)); | ||
751 | return 0; | 735 | return 0; |
752 | } | 736 | } |
753 | 737 | ||
@@ -760,7 +744,7 @@ MODULE_DEVICE_TABLE(i2c, tlv320aic23_id); | |||
760 | 744 | ||
761 | static struct i2c_driver tlv320aic23_i2c_driver = { | 745 | static struct i2c_driver tlv320aic23_i2c_driver = { |
762 | .driver = { | 746 | .driver = { |
763 | .name = "tlv320aic23", | 747 | .name = "tlv320aic23-codec", |
764 | }, | 748 | }, |
765 | .probe = tlv320aic23_codec_probe, | 749 | .probe = tlv320aic23_codec_probe, |
766 | .remove = __exit_p(tlv320aic23_i2c_remove), | 750 | .remove = __exit_p(tlv320aic23_i2c_remove), |
@@ -769,71 +753,25 @@ static struct i2c_driver tlv320aic23_i2c_driver = { | |||
769 | 753 | ||
770 | #endif | 754 | #endif |
771 | 755 | ||
772 | static int tlv320aic23_probe(struct platform_device *pdev) | 756 | static int __init tlv320aic23_modinit(void) |
773 | { | 757 | { |
774 | struct snd_soc_device *socdev = platform_get_drvdata(pdev); | 758 | int ret; |
775 | struct snd_soc_codec *codec; | ||
776 | struct aic23 *aic23; | ||
777 | int ret = 0; | ||
778 | |||
779 | printk(KERN_INFO "AIC23 Audio Codec %s\n", AIC23_VERSION); | ||
780 | |||
781 | aic23 = kzalloc(sizeof(struct aic23), GFP_KERNEL); | ||
782 | if (aic23 == NULL) | ||
783 | return -ENOMEM; | ||
784 | codec = &aic23->codec; | ||
785 | socdev->card->codec = codec; | ||
786 | mutex_init(&codec->mutex); | ||
787 | INIT_LIST_HEAD(&codec->dapm_widgets); | ||
788 | INIT_LIST_HEAD(&codec->dapm_paths); | ||
789 | |||
790 | tlv320aic23_socdev = socdev; | ||
791 | #if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE) | 759 | #if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE) |
792 | codec->hw_write = (hw_write_t) i2c_master_send; | ||
793 | codec->hw_read = NULL; | ||
794 | ret = i2c_add_driver(&tlv320aic23_i2c_driver); | 760 | ret = i2c_add_driver(&tlv320aic23_i2c_driver); |
795 | if (ret != 0) | 761 | if (ret != 0) { |
796 | printk(KERN_ERR "can't add i2c driver"); | 762 | printk(KERN_ERR "Failed to register TLV320AIC23 I2C driver: %d\n", |
763 | ret); | ||
764 | } | ||
797 | #endif | 765 | #endif |
798 | return ret; | 766 | return ret; |
799 | } | 767 | } |
768 | module_init(tlv320aic23_modinit); | ||
800 | 769 | ||
801 | static int tlv320aic23_remove(struct platform_device *pdev) | 770 | static void __exit tlv320aic23_exit(void) |
802 | { | 771 | { |
803 | struct snd_soc_device *socdev = platform_get_drvdata(pdev); | ||
804 | struct snd_soc_codec *codec = socdev->card->codec; | ||
805 | struct aic23 *aic23 = container_of(codec, struct aic23, codec); | ||
806 | |||
807 | if (codec->control_data) | ||
808 | tlv320aic23_set_bias_level(codec, SND_SOC_BIAS_OFF); | ||
809 | |||
810 | snd_soc_free_pcms(socdev); | ||
811 | snd_soc_dapm_free(socdev); | ||
812 | #if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE) | 772 | #if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE) |
813 | i2c_del_driver(&tlv320aic23_i2c_driver); | 773 | i2c_del_driver(&tlv320aic23_i2c_driver); |
814 | #endif | 774 | #endif |
815 | kfree(codec->reg_cache); | ||
816 | kfree(aic23); | ||
817 | |||
818 | return 0; | ||
819 | } | ||
820 | struct snd_soc_codec_device soc_codec_dev_tlv320aic23 = { | ||
821 | .probe = tlv320aic23_probe, | ||
822 | .remove = tlv320aic23_remove, | ||
823 | .suspend = tlv320aic23_suspend, | ||
824 | .resume = tlv320aic23_resume, | ||
825 | }; | ||
826 | EXPORT_SYMBOL_GPL(soc_codec_dev_tlv320aic23); | ||
827 | |||
828 | static int __init tlv320aic23_modinit(void) | ||
829 | { | ||
830 | return snd_soc_register_dai(&tlv320aic23_dai); | ||
831 | } | ||
832 | module_init(tlv320aic23_modinit); | ||
833 | |||
834 | static void __exit tlv320aic23_exit(void) | ||
835 | { | ||
836 | snd_soc_unregister_dai(&tlv320aic23_dai); | ||
837 | } | 775 | } |
838 | module_exit(tlv320aic23_exit); | 776 | module_exit(tlv320aic23_exit); |
839 | 777 | ||
diff --git a/sound/soc/codecs/tlv320aic23.h b/sound/soc/codecs/tlv320aic23.h index 79d1faf8e570..e804120bd3da 100644 --- a/sound/soc/codecs/tlv320aic23.h +++ b/sound/soc/codecs/tlv320aic23.h | |||
@@ -116,7 +116,4 @@ | |||
116 | #define TLV320AIC23_SIDETONE_12 0x080 | 116 | #define TLV320AIC23_SIDETONE_12 0x080 |
117 | #define TLV320AIC23_SIDETONE_18 0x0c0 | 117 | #define TLV320AIC23_SIDETONE_18 0x0c0 |
118 | 118 | ||
119 | extern struct snd_soc_dai tlv320aic23_dai; | ||
120 | extern struct snd_soc_codec_device soc_codec_dev_tlv320aic23; | ||
121 | |||
122 | #endif /* _TLV320AIC23_H */ | 119 | #endif /* _TLV320AIC23_H */ |
diff --git a/sound/soc/codecs/tlv320aic26.c b/sound/soc/codecs/tlv320aic26.c index f0e00fd4b435..6b7d71ec0004 100644 --- a/sound/soc/codecs/tlv320aic26.c +++ b/sound/soc/codecs/tlv320aic26.c | |||
@@ -19,7 +19,6 @@ | |||
19 | #include <sound/pcm_params.h> | 19 | #include <sound/pcm_params.h> |
20 | #include <sound/soc.h> | 20 | #include <sound/soc.h> |
21 | #include <sound/soc-dapm.h> | 21 | #include <sound/soc-dapm.h> |
22 | #include <sound/soc-of-simple.h> | ||
23 | #include <sound/initval.h> | 22 | #include <sound/initval.h> |
24 | 23 | ||
25 | #include "tlv320aic26.h" | 24 | #include "tlv320aic26.h" |
@@ -130,8 +129,7 @@ static int aic26_hw_params(struct snd_pcm_substream *substream, | |||
130 | struct snd_soc_dai *dai) | 129 | struct snd_soc_dai *dai) |
131 | { | 130 | { |
132 | struct snd_soc_pcm_runtime *rtd = substream->private_data; | 131 | struct snd_soc_pcm_runtime *rtd = substream->private_data; |
133 | struct snd_soc_device *socdev = rtd->socdev; | 132 | struct snd_soc_codec *codec = rtd->codec; |
134 | struct snd_soc_codec *codec = socdev->card->codec; | ||
135 | struct aic26 *aic26 = snd_soc_codec_get_drvdata(codec); | 133 | struct aic26 *aic26 = snd_soc_codec_get_drvdata(codec); |
136 | int fsref, divisor, wlen, pval, jval, dval, qval; | 134 | int fsref, divisor, wlen, pval, jval, dval, qval; |
137 | u16 reg; | 135 | u16 reg; |
@@ -278,8 +276,8 @@ static struct snd_soc_dai_ops aic26_dai_ops = { | |||
278 | .set_fmt = aic26_set_fmt, | 276 | .set_fmt = aic26_set_fmt, |
279 | }; | 277 | }; |
280 | 278 | ||
281 | struct snd_soc_dai aic26_dai = { | 279 | static struct snd_soc_dai_driver aic26_dai = { |
282 | .name = "tlv320aic26", | 280 | .name = "tlv320aic26-hifi", |
283 | .playback = { | 281 | .playback = { |
284 | .stream_name = "Playback", | 282 | .stream_name = "Playback", |
285 | .channels_min = 2, | 283 | .channels_min = 2, |
@@ -296,7 +294,6 @@ struct snd_soc_dai aic26_dai = { | |||
296 | }, | 294 | }, |
297 | .ops = &aic26_dai_ops, | 295 | .ops = &aic26_dai_ops, |
298 | }; | 296 | }; |
299 | EXPORT_SYMBOL_GPL(aic26_dai); | ||
300 | 297 | ||
301 | /* --------------------------------------------------------------------- | 298 | /* --------------------------------------------------------------------- |
302 | * ALSA controls | 299 | * ALSA controls |
@@ -319,61 +316,6 @@ static const struct snd_kcontrol_new aic26_snd_controls[] = { | |||
319 | }; | 316 | }; |
320 | 317 | ||
321 | /* --------------------------------------------------------------------- | 318 | /* --------------------------------------------------------------------- |
322 | * SoC CODEC portion of driver: probe and release routines | ||
323 | */ | ||
324 | static int aic26_probe(struct platform_device *pdev) | ||
325 | { | ||
326 | struct snd_soc_device *socdev = platform_get_drvdata(pdev); | ||
327 | struct snd_soc_codec *codec; | ||
328 | struct aic26 *aic26; | ||
329 | int ret, err; | ||
330 | |||
331 | dev_info(&pdev->dev, "Probing AIC26 SoC CODEC driver\n"); | ||
332 | dev_dbg(&pdev->dev, "socdev=%p\n", socdev); | ||
333 | dev_dbg(&pdev->dev, "codec_data=%p\n", socdev->codec_data); | ||
334 | |||
335 | /* Fetch the relevant aic26 private data here (it's already been | ||
336 | * stored in the .codec pointer) */ | ||
337 | aic26 = socdev->codec_data; | ||
338 | if (aic26 == NULL) { | ||
339 | dev_err(&pdev->dev, "aic26: missing codec pointer\n"); | ||
340 | return -ENODEV; | ||
341 | } | ||
342 | codec = &aic26->codec; | ||
343 | socdev->card->codec = codec; | ||
344 | |||
345 | dev_dbg(&pdev->dev, "Registering PCMs, dev=%p, socdev->dev=%p\n", | ||
346 | &pdev->dev, socdev->dev); | ||
347 | /* register pcms */ | ||
348 | ret = snd_soc_new_pcms(socdev, SNDRV_DEFAULT_IDX1, SNDRV_DEFAULT_STR1); | ||
349 | if (ret < 0) { | ||
350 | dev_err(&pdev->dev, "aic26: failed to create pcms\n"); | ||
351 | return -ENODEV; | ||
352 | } | ||
353 | |||
354 | /* register controls */ | ||
355 | dev_dbg(&pdev->dev, "Registering controls\n"); | ||
356 | err = snd_soc_add_controls(codec, aic26_snd_controls, | ||
357 | ARRAY_SIZE(aic26_snd_controls)); | ||
358 | WARN_ON(err < 0); | ||
359 | |||
360 | return 0; | ||
361 | } | ||
362 | |||
363 | static int aic26_remove(struct platform_device *pdev) | ||
364 | { | ||
365 | struct snd_soc_device *socdev = platform_get_drvdata(pdev); | ||
366 | snd_soc_free_pcms(socdev); | ||
367 | return 0; | ||
368 | } | ||
369 | |||
370 | struct snd_soc_codec_device aic26_soc_codec_dev = { | ||
371 | .probe = aic26_probe, | ||
372 | .remove = aic26_remove, | ||
373 | }; | ||
374 | EXPORT_SYMBOL_GPL(aic26_soc_codec_dev); | ||
375 | |||
376 | /* --------------------------------------------------------------------- | ||
377 | * SPI device portion of driver: sysfs files for debugging | 319 | * SPI device portion of driver: sysfs files for debugging |
378 | */ | 320 | */ |
379 | 321 | ||
@@ -409,95 +351,95 @@ static ssize_t aic26_keyclick_set(struct device *dev, | |||
409 | static DEVICE_ATTR(keyclick, 0644, aic26_keyclick_show, aic26_keyclick_set); | 351 | static DEVICE_ATTR(keyclick, 0644, aic26_keyclick_show, aic26_keyclick_set); |
410 | 352 | ||
411 | /* --------------------------------------------------------------------- | 353 | /* --------------------------------------------------------------------- |
412 | * SPI device portion of driver: probe and release routines and SPI | 354 | * SoC CODEC portion of driver: probe and release routines |
413 | * driver registration. | ||
414 | */ | 355 | */ |
415 | static int aic26_spi_probe(struct spi_device *spi) | 356 | static int aic26_probe(struct snd_soc_codec *codec) |
416 | { | 357 | { |
417 | struct aic26 *aic26; | 358 | struct aic26 *aic26 = snd_soc_codec_get_drvdata(codec); |
418 | int ret, i, reg; | 359 | int ret, err, i, reg; |
419 | |||
420 | dev_dbg(&spi->dev, "probing tlv320aic26 spi device\n"); | ||
421 | |||
422 | /* Allocate driver data */ | ||
423 | aic26 = kzalloc(sizeof *aic26, GFP_KERNEL); | ||
424 | if (!aic26) | ||
425 | return -ENOMEM; | ||
426 | |||
427 | /* Initialize the driver data */ | ||
428 | aic26->spi = spi; | ||
429 | dev_set_drvdata(&spi->dev, aic26); | ||
430 | 360 | ||
431 | /* Setup what we can in the codec structure so that the register | 361 | dev_info(codec->dev, "Probing AIC26 SoC CODEC driver\n"); |
432 | * access functions will work as expected. More will be filled | ||
433 | * out when it is probed by the SoC CODEC part of this driver */ | ||
434 | snd_soc_codec_set_drvdata(&aic26->codec, aic26); | ||
435 | aic26->codec.name = "aic26"; | ||
436 | aic26->codec.owner = THIS_MODULE; | ||
437 | aic26->codec.dai = &aic26_dai; | ||
438 | aic26->codec.num_dai = 1; | ||
439 | aic26->codec.read = aic26_reg_read; | ||
440 | aic26->codec.write = aic26_reg_write; | ||
441 | aic26->master = 1; | ||
442 | mutex_init(&aic26->codec.mutex); | ||
443 | INIT_LIST_HEAD(&aic26->codec.dapm_widgets); | ||
444 | INIT_LIST_HEAD(&aic26->codec.dapm_paths); | ||
445 | aic26->codec.reg_cache_size = AIC26_NUM_REGS; | ||
446 | aic26->codec.reg_cache = aic26->reg_cache; | ||
447 | |||
448 | aic26_dai.dev = &spi->dev; | ||
449 | ret = snd_soc_register_dai(&aic26_dai); | ||
450 | if (ret != 0) { | ||
451 | dev_err(&spi->dev, "Failed to register DAI: %d\n", ret); | ||
452 | kfree(aic26); | ||
453 | return ret; | ||
454 | } | ||
455 | 362 | ||
456 | /* Reset the codec to power on defaults */ | 363 | /* Reset the codec to power on defaults */ |
457 | aic26_reg_write(&aic26->codec, AIC26_REG_RESET, 0xBB00); | 364 | aic26_reg_write(codec, AIC26_REG_RESET, 0xBB00); |
458 | 365 | ||
459 | /* Power up CODEC */ | 366 | /* Power up CODEC */ |
460 | aic26_reg_write(&aic26->codec, AIC26_REG_POWER_CTRL, 0); | 367 | aic26_reg_write(codec, AIC26_REG_POWER_CTRL, 0); |
461 | 368 | ||
462 | /* Audio Control 3 (master mode, fsref rate) */ | 369 | /* Audio Control 3 (master mode, fsref rate) */ |
463 | reg = aic26_reg_read(&aic26->codec, AIC26_REG_AUDIO_CTRL3); | 370 | reg = aic26_reg_read(codec, AIC26_REG_AUDIO_CTRL3); |
464 | reg &= ~0xf800; | 371 | reg &= ~0xf800; |
465 | reg |= 0x0800; /* set master mode */ | 372 | reg |= 0x0800; /* set master mode */ |
466 | aic26_reg_write(&aic26->codec, AIC26_REG_AUDIO_CTRL3, reg); | 373 | aic26_reg_write(codec, AIC26_REG_AUDIO_CTRL3, reg); |
467 | 374 | ||
468 | /* Fill register cache */ | 375 | /* Fill register cache */ |
469 | for (i = 0; i < ARRAY_SIZE(aic26->reg_cache); i++) | 376 | for (i = 0; i < ARRAY_SIZE(aic26->reg_cache); i++) |
470 | aic26_reg_read(&aic26->codec, i); | 377 | aic26_reg_read(codec, i); |
471 | 378 | ||
472 | /* Register the sysfs files for debugging */ | 379 | /* Register the sysfs files for debugging */ |
473 | /* Create SysFS files */ | 380 | /* Create SysFS files */ |
474 | ret = device_create_file(&spi->dev, &dev_attr_keyclick); | 381 | ret = device_create_file(codec->dev, &dev_attr_keyclick); |
475 | if (ret) | 382 | if (ret) |
476 | dev_info(&spi->dev, "error creating sysfs files\n"); | 383 | dev_info(codec->dev, "error creating sysfs files\n"); |
477 | 384 | ||
478 | #if defined(CONFIG_SND_SOC_OF_SIMPLE) | 385 | /* register controls */ |
479 | /* Tell the of_soc helper about this codec */ | 386 | dev_dbg(codec->dev, "Registering controls\n"); |
480 | of_snd_soc_register_codec(&aic26_soc_codec_dev, aic26, &aic26_dai, | 387 | err = snd_soc_add_controls(codec, aic26_snd_controls, |
481 | spi->dev.archdata.of_node); | 388 | ARRAY_SIZE(aic26_snd_controls)); |
482 | #endif | 389 | WARN_ON(err < 0); |
483 | 390 | ||
484 | dev_dbg(&spi->dev, "SPI device initialized\n"); | ||
485 | return 0; | 391 | return 0; |
486 | } | 392 | } |
487 | 393 | ||
488 | static int aic26_spi_remove(struct spi_device *spi) | 394 | static struct snd_soc_codec_driver aic26_soc_codec_dev = { |
395 | .probe = aic26_probe, | ||
396 | .read = aic26_reg_read, | ||
397 | .write = aic26_reg_write, | ||
398 | .reg_cache_size = AIC26_NUM_REGS, | ||
399 | .reg_word_size = sizeof(u16), | ||
400 | }; | ||
401 | |||
402 | /* --------------------------------------------------------------------- | ||
403 | * SPI device portion of driver: probe and release routines and SPI | ||
404 | * driver registration. | ||
405 | */ | ||
406 | static int aic26_spi_probe(struct spi_device *spi) | ||
489 | { | 407 | { |
490 | struct aic26 *aic26 = dev_get_drvdata(&spi->dev); | 408 | struct aic26 *aic26; |
409 | int ret; | ||
491 | 410 | ||
492 | snd_soc_unregister_dai(&aic26_dai); | 411 | dev_dbg(&spi->dev, "probing tlv320aic26 spi device\n"); |
493 | kfree(aic26); | 412 | |
413 | /* Allocate driver data */ | ||
414 | aic26 = kzalloc(sizeof *aic26, GFP_KERNEL); | ||
415 | if (!aic26) | ||
416 | return -ENOMEM; | ||
494 | 417 | ||
418 | /* Initialize the driver data */ | ||
419 | aic26->spi = spi; | ||
420 | dev_set_drvdata(&spi->dev, aic26); | ||
421 | aic26->master = 1; | ||
422 | |||
423 | ret = snd_soc_register_codec(&spi->dev, | ||
424 | &aic26_soc_codec_dev, &aic26_dai, 1); | ||
425 | if (ret < 0) | ||
426 | kfree(aic26); | ||
427 | return ret; | ||
428 | |||
429 | dev_dbg(&spi->dev, "SPI device initialized\n"); | ||
430 | return 0; | ||
431 | } | ||
432 | |||
433 | static int aic26_spi_remove(struct spi_device *spi) | ||
434 | { | ||
435 | snd_soc_unregister_codec(&spi->dev); | ||
436 | kfree(spi_get_drvdata(spi)); | ||
495 | return 0; | 437 | return 0; |
496 | } | 438 | } |
497 | 439 | ||
498 | static struct spi_driver aic26_spi = { | 440 | static struct spi_driver aic26_spi = { |
499 | .driver = { | 441 | .driver = { |
500 | .name = "tlv320aic26", | 442 | .name = "tlv320aic26-codec", |
501 | .owner = THIS_MODULE, | 443 | .owner = THIS_MODULE, |
502 | }, | 444 | }, |
503 | .probe = aic26_spi_probe, | 445 | .probe = aic26_spi_probe, |
diff --git a/sound/soc/codecs/tlv320aic26.h b/sound/soc/codecs/tlv320aic26.h index 786ba16c945f..62b1f2261429 100644 --- a/sound/soc/codecs/tlv320aic26.h +++ b/sound/soc/codecs/tlv320aic26.h | |||
@@ -90,7 +90,4 @@ enum aic26_wlen { | |||
90 | AIC26_WLEN_32 = 3 << 10, | 90 | AIC26_WLEN_32 = 3 << 10, |
91 | }; | 91 | }; |
92 | 92 | ||
93 | extern struct snd_soc_dai aic26_dai; | ||
94 | extern struct snd_soc_codec_device aic26_soc_codec_dev; | ||
95 | |||
96 | #endif /* _TLV320AIC16_H_ */ | 93 | #endif /* _TLV320AIC16_H_ */ |
diff --git a/sound/soc/codecs/tlv320aic3x.c b/sound/soc/codecs/tlv320aic3x.c index 71a69908ccf6..43fd9c171742 100644 --- a/sound/soc/codecs/tlv320aic3x.c +++ b/sound/soc/codecs/tlv320aic3x.c | |||
@@ -63,8 +63,10 @@ static const char *aic3x_supply_names[AIC3X_NUM_SUPPLIES] = { | |||
63 | 63 | ||
64 | /* codec private data */ | 64 | /* codec private data */ |
65 | struct aic3x_priv { | 65 | struct aic3x_priv { |
66 | struct snd_soc_codec codec; | ||
67 | struct regulator_bulk_data supplies[AIC3X_NUM_SUPPLIES]; | 66 | struct regulator_bulk_data supplies[AIC3X_NUM_SUPPLIES]; |
67 | enum snd_soc_control_type control_type; | ||
68 | struct aic3x_setup_data *setup; | ||
69 | void *control_data; | ||
68 | unsigned int sysclk; | 70 | unsigned int sysclk; |
69 | int master; | 71 | int master; |
70 | int gpio_reset; | 72 | int gpio_reset; |
@@ -773,8 +775,7 @@ static int aic3x_hw_params(struct snd_pcm_substream *substream, | |||
773 | struct snd_soc_dai *dai) | 775 | struct snd_soc_dai *dai) |
774 | { | 776 | { |
775 | struct snd_soc_pcm_runtime *rtd = substream->private_data; | 777 | struct snd_soc_pcm_runtime *rtd = substream->private_data; |
776 | struct snd_soc_device *socdev = rtd->socdev; | 778 | struct snd_soc_codec *codec =rtd->codec; |
777 | struct snd_soc_codec *codec = socdev->card->codec; | ||
778 | struct aic3x_priv *aic3x = snd_soc_codec_get_drvdata(codec); | 779 | struct aic3x_priv *aic3x = snd_soc_codec_get_drvdata(codec); |
779 | int codec_clk = 0, bypass_pll = 0, fsref, last_clk = 0; | 780 | int codec_clk = 0, bypass_pll = 0, fsref, last_clk = 0; |
780 | u8 data, j, r, p, pll_q, pll_p = 1, pll_r = 1, pll_j = 1; | 781 | u8 data, j, r, p, pll_q, pll_p = 1, pll_r = 1, pll_j = 1; |
@@ -1101,8 +1102,8 @@ static struct snd_soc_dai_ops aic3x_dai_ops = { | |||
1101 | .set_fmt = aic3x_set_dai_fmt, | 1102 | .set_fmt = aic3x_set_dai_fmt, |
1102 | }; | 1103 | }; |
1103 | 1104 | ||
1104 | struct snd_soc_dai aic3x_dai = { | 1105 | static struct snd_soc_dai_driver aic3x_dai = { |
1105 | .name = "tlv320aic3x", | 1106 | .name = "tlv320aic3x-hifi", |
1106 | .playback = { | 1107 | .playback = { |
1107 | .stream_name = "Playback", | 1108 | .stream_name = "Playback", |
1108 | .channels_min = 1, | 1109 | .channels_min = 1, |
@@ -1117,22 +1118,16 @@ struct snd_soc_dai aic3x_dai = { | |||
1117 | .formats = AIC3X_FORMATS,}, | 1118 | .formats = AIC3X_FORMATS,}, |
1118 | .ops = &aic3x_dai_ops, | 1119 | .ops = &aic3x_dai_ops, |
1119 | }; | 1120 | }; |
1120 | EXPORT_SYMBOL_GPL(aic3x_dai); | ||
1121 | 1121 | ||
1122 | static int aic3x_suspend(struct platform_device *pdev, pm_message_t state) | 1122 | static int aic3x_suspend(struct snd_soc_codec *codec, pm_message_t state) |
1123 | { | 1123 | { |
1124 | struct snd_soc_device *socdev = platform_get_drvdata(pdev); | ||
1125 | struct snd_soc_codec *codec = socdev->card->codec; | ||
1126 | |||
1127 | aic3x_set_bias_level(codec, SND_SOC_BIAS_OFF); | 1124 | aic3x_set_bias_level(codec, SND_SOC_BIAS_OFF); |
1128 | 1125 | ||
1129 | return 0; | 1126 | return 0; |
1130 | } | 1127 | } |
1131 | 1128 | ||
1132 | static int aic3x_resume(struct platform_device *pdev) | 1129 | static int aic3x_resume(struct snd_soc_codec *codec) |
1133 | { | 1130 | { |
1134 | struct snd_soc_device *socdev = platform_get_drvdata(pdev); | ||
1135 | struct snd_soc_codec *codec = socdev->card->codec; | ||
1136 | int i; | 1131 | int i; |
1137 | u8 data[2]; | 1132 | u8 data[2]; |
1138 | u8 *cache = codec->reg_cache; | 1133 | u8 *cache = codec->reg_cache; |
@@ -1157,22 +1152,6 @@ static int aic3x_init(struct snd_soc_codec *codec) | |||
1157 | { | 1152 | { |
1158 | int reg; | 1153 | int reg; |
1159 | 1154 | ||
1160 | mutex_init(&codec->mutex); | ||
1161 | INIT_LIST_HEAD(&codec->dapm_widgets); | ||
1162 | INIT_LIST_HEAD(&codec->dapm_paths); | ||
1163 | |||
1164 | codec->name = "tlv320aic3x"; | ||
1165 | codec->owner = THIS_MODULE; | ||
1166 | codec->read = aic3x_read_reg_cache; | ||
1167 | codec->write = aic3x_write; | ||
1168 | codec->set_bias_level = aic3x_set_bias_level; | ||
1169 | codec->dai = &aic3x_dai; | ||
1170 | codec->num_dai = 1; | ||
1171 | codec->reg_cache_size = ARRAY_SIZE(aic3x_reg); | ||
1172 | codec->reg_cache = kmemdup(aic3x_reg, sizeof(aic3x_reg), GFP_KERNEL); | ||
1173 | if (codec->reg_cache == NULL) | ||
1174 | return -ENOMEM; | ||
1175 | |||
1176 | aic3x_write(codec, AIC3X_PAGE_SELECT, PAGE0_SELECT); | 1155 | aic3x_write(codec, AIC3X_PAGE_SELECT, PAGE0_SELECT); |
1177 | aic3x_write(codec, AIC3X_RESET, SOFT_RESET); | 1156 | aic3x_write(codec, AIC3X_RESET, SOFT_RESET); |
1178 | 1157 | ||
@@ -1245,56 +1224,50 @@ static int aic3x_init(struct snd_soc_codec *codec) | |||
1245 | return 0; | 1224 | return 0; |
1246 | } | 1225 | } |
1247 | 1226 | ||
1248 | static struct snd_soc_codec *aic3x_codec; | 1227 | static int aic3x_probe(struct snd_soc_codec *codec) |
1249 | |||
1250 | static int aic3x_register(struct snd_soc_codec *codec) | ||
1251 | { | 1228 | { |
1252 | int ret; | 1229 | struct aic3x_priv *aic3x = snd_soc_codec_get_drvdata(codec); |
1230 | |||
1231 | codec->hw_write = (hw_write_t) i2c_master_send; | ||
1232 | codec->control_data = aic3x->control_data; | ||
1253 | 1233 | ||
1254 | ret = aic3x_init(codec); | 1234 | if (aic3x->setup) { |
1255 | if (ret < 0) { | 1235 | /* setup GPIO functions */ |
1256 | dev_err(codec->dev, "Failed to initialise device\n"); | 1236 | aic3x_write(codec, AIC3X_GPIO1_REG, |
1257 | return ret; | 1237 | (aic3x->setup->gpio_func[0] & 0xf) << 4); |
1238 | aic3x_write(codec, AIC3X_GPIO2_REG, | ||
1239 | (aic3x->setup->gpio_func[1] & 0xf) << 4); | ||
1258 | } | 1240 | } |
1259 | 1241 | ||
1260 | aic3x_codec = codec; | 1242 | aic3x_init(codec); |
1261 | 1243 | ||
1262 | ret = snd_soc_register_codec(codec); | 1244 | snd_soc_add_controls(codec, aic3x_snd_controls, |
1263 | if (ret) { | 1245 | ARRAY_SIZE(aic3x_snd_controls)); |
1264 | dev_err(codec->dev, "Failed to register codec\n"); | ||
1265 | return ret; | ||
1266 | } | ||
1267 | 1246 | ||
1268 | ret = snd_soc_register_dai(&aic3x_dai); | 1247 | aic3x_add_widgets(codec); |
1269 | if (ret) { | ||
1270 | dev_err(codec->dev, "Failed to register dai\n"); | ||
1271 | snd_soc_unregister_codec(codec); | ||
1272 | return ret; | ||
1273 | } | ||
1274 | 1248 | ||
1275 | return 0; | 1249 | return 0; |
1276 | } | 1250 | } |
1277 | 1251 | ||
1278 | static int aic3x_unregister(struct aic3x_priv *aic3x) | 1252 | static int aic3x_remove(struct snd_soc_codec *codec) |
1279 | { | 1253 | { |
1280 | aic3x_set_bias_level(&aic3x->codec, SND_SOC_BIAS_OFF); | 1254 | aic3x_set_bias_level(codec, SND_SOC_BIAS_OFF); |
1281 | |||
1282 | snd_soc_unregister_dai(&aic3x_dai); | ||
1283 | snd_soc_unregister_codec(&aic3x->codec); | ||
1284 | |||
1285 | if (aic3x->gpio_reset >= 0) { | ||
1286 | gpio_set_value(aic3x->gpio_reset, 0); | ||
1287 | gpio_free(aic3x->gpio_reset); | ||
1288 | } | ||
1289 | regulator_bulk_disable(ARRAY_SIZE(aic3x->supplies), aic3x->supplies); | ||
1290 | regulator_bulk_free(ARRAY_SIZE(aic3x->supplies), aic3x->supplies); | ||
1291 | |||
1292 | kfree(aic3x); | ||
1293 | aic3x_codec = NULL; | ||
1294 | |||
1295 | return 0; | 1255 | return 0; |
1296 | } | 1256 | } |
1297 | 1257 | ||
1258 | static struct snd_soc_codec_driver soc_codec_dev_aic3x = { | ||
1259 | .read = aic3x_read_reg_cache, | ||
1260 | .write = aic3x_write, | ||
1261 | .set_bias_level = aic3x_set_bias_level, | ||
1262 | .reg_cache_size = ARRAY_SIZE(aic3x_reg), | ||
1263 | .reg_word_size = sizeof(u8), | ||
1264 | .reg_cache_default = aic3x_reg, | ||
1265 | .probe = aic3x_probe, | ||
1266 | .remove = aic3x_remove, | ||
1267 | .suspend = aic3x_suspend, | ||
1268 | .resume = aic3x_resume, | ||
1269 | }; | ||
1270 | |||
1298 | #if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE) | 1271 | #if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE) |
1299 | /* | 1272 | /* |
1300 | * AIC3X 2 wire address can be up to 4 devices with device addresses | 1273 | * AIC3X 2 wire address can be up to 4 devices with device addresses |
@@ -1308,9 +1281,9 @@ static int aic3x_unregister(struct aic3x_priv *aic3x) | |||
1308 | static int aic3x_i2c_probe(struct i2c_client *i2c, | 1281 | static int aic3x_i2c_probe(struct i2c_client *i2c, |
1309 | const struct i2c_device_id *id) | 1282 | const struct i2c_device_id *id) |
1310 | { | 1283 | { |
1311 | struct snd_soc_codec *codec; | ||
1312 | struct aic3x_priv *aic3x; | ||
1313 | struct aic3x_pdata *pdata = i2c->dev.platform_data; | 1284 | struct aic3x_pdata *pdata = i2c->dev.platform_data; |
1285 | struct aic3x_setup_data *setup = pdata->setup; | ||
1286 | struct aic3x_priv *aic3x; | ||
1314 | int ret, i; | 1287 | int ret, i; |
1315 | 1288 | ||
1316 | aic3x = kzalloc(sizeof(struct aic3x_priv), GFP_KERNEL); | 1289 | aic3x = kzalloc(sizeof(struct aic3x_priv), GFP_KERNEL); |
@@ -1319,12 +1292,8 @@ static int aic3x_i2c_probe(struct i2c_client *i2c, | |||
1319 | return -ENOMEM; | 1292 | return -ENOMEM; |
1320 | } | 1293 | } |
1321 | 1294 | ||
1322 | codec = &aic3x->codec; | 1295 | aic3x->control_data = i2c; |
1323 | codec->dev = &i2c->dev; | 1296 | aic3x->setup = setup; |
1324 | snd_soc_codec_set_drvdata(codec, aic3x); | ||
1325 | codec->control_data = i2c; | ||
1326 | codec->hw_write = (hw_write_t) i2c_master_send; | ||
1327 | |||
1328 | i2c_set_clientdata(i2c, aic3x); | 1297 | i2c_set_clientdata(i2c, aic3x); |
1329 | 1298 | ||
1330 | aic3x->gpio_reset = -1; | 1299 | aic3x->gpio_reset = -1; |
@@ -1339,17 +1308,17 @@ static int aic3x_i2c_probe(struct i2c_client *i2c, | |||
1339 | for (i = 0; i < ARRAY_SIZE(aic3x->supplies); i++) | 1308 | for (i = 0; i < ARRAY_SIZE(aic3x->supplies); i++) |
1340 | aic3x->supplies[i].supply = aic3x_supply_names[i]; | 1309 | aic3x->supplies[i].supply = aic3x_supply_names[i]; |
1341 | 1310 | ||
1342 | ret = regulator_bulk_get(codec->dev, ARRAY_SIZE(aic3x->supplies), | 1311 | ret = regulator_bulk_get(&i2c->dev, ARRAY_SIZE(aic3x->supplies), |
1343 | aic3x->supplies); | 1312 | aic3x->supplies); |
1344 | if (ret != 0) { | 1313 | if (ret != 0) { |
1345 | dev_err(codec->dev, "Failed to request supplies: %d\n", ret); | 1314 | dev_err(&i2c->dev, "Failed to request supplies: %d\n", ret); |
1346 | goto err_get; | 1315 | goto err_get; |
1347 | } | 1316 | } |
1348 | 1317 | ||
1349 | ret = regulator_bulk_enable(ARRAY_SIZE(aic3x->supplies), | 1318 | ret = regulator_bulk_enable(ARRAY_SIZE(aic3x->supplies), |
1350 | aic3x->supplies); | 1319 | aic3x->supplies); |
1351 | if (ret != 0) { | 1320 | if (ret != 0) { |
1352 | dev_err(codec->dev, "Failed to enable supplies: %d\n", ret); | 1321 | dev_err(&i2c->dev, "Failed to enable supplies: %d\n", ret); |
1353 | goto err_enable; | 1322 | goto err_enable; |
1354 | } | 1323 | } |
1355 | 1324 | ||
@@ -1358,7 +1327,11 @@ static int aic3x_i2c_probe(struct i2c_client *i2c, | |||
1358 | gpio_set_value(aic3x->gpio_reset, 1); | 1327 | gpio_set_value(aic3x->gpio_reset, 1); |
1359 | } | 1328 | } |
1360 | 1329 | ||
1361 | return aic3x_register(codec); | 1330 | ret = snd_soc_register_codec(&i2c->dev, |
1331 | &soc_codec_dev_aic3x, &aic3x_dai, 1); | ||
1332 | if (ret < 0) | ||
1333 | goto err_enable; | ||
1334 | return ret; | ||
1362 | 1335 | ||
1363 | err_enable: | 1336 | err_enable: |
1364 | regulator_bulk_free(ARRAY_SIZE(aic3x->supplies), aic3x->supplies); | 1337 | regulator_bulk_free(ARRAY_SIZE(aic3x->supplies), aic3x->supplies); |
@@ -1374,7 +1347,16 @@ static int aic3x_i2c_remove(struct i2c_client *client) | |||
1374 | { | 1347 | { |
1375 | struct aic3x_priv *aic3x = i2c_get_clientdata(client); | 1348 | struct aic3x_priv *aic3x = i2c_get_clientdata(client); |
1376 | 1349 | ||
1377 | return aic3x_unregister(aic3x); | 1350 | if (aic3x->gpio_reset >= 0) { |
1351 | gpio_set_value(aic3x->gpio_reset, 0); | ||
1352 | gpio_free(aic3x->gpio_reset); | ||
1353 | } | ||
1354 | regulator_bulk_disable(ARRAY_SIZE(aic3x->supplies), aic3x->supplies); | ||
1355 | regulator_bulk_free(ARRAY_SIZE(aic3x->supplies), aic3x->supplies); | ||
1356 | |||
1357 | snd_soc_unregister_codec(&client->dev); | ||
1358 | kfree(i2c_get_clientdata(client)); | ||
1359 | return 0; | ||
1378 | } | 1360 | } |
1379 | 1361 | ||
1380 | static const struct i2c_device_id aic3x_i2c_id[] = { | 1362 | static const struct i2c_device_id aic3x_i2c_id[] = { |
@@ -1387,7 +1369,7 @@ MODULE_DEVICE_TABLE(i2c, aic3x_i2c_id); | |||
1387 | /* machine i2c codec control layer */ | 1369 | /* machine i2c codec control layer */ |
1388 | static struct i2c_driver aic3x_i2c_driver = { | 1370 | static struct i2c_driver aic3x_i2c_driver = { |
1389 | .driver = { | 1371 | .driver = { |
1390 | .name = "aic3x I2C Codec", | 1372 | .name = "tlv320aic3x-codec", |
1391 | .owner = THIS_MODULE, | 1373 | .owner = THIS_MODULE, |
1392 | }, | 1374 | }, |
1393 | .probe = aic3x_i2c_probe, | 1375 | .probe = aic3x_i2c_probe, |
@@ -1409,90 +1391,27 @@ static inline void aic3x_i2c_exit(void) | |||
1409 | { | 1391 | { |
1410 | i2c_del_driver(&aic3x_i2c_driver); | 1392 | i2c_del_driver(&aic3x_i2c_driver); |
1411 | } | 1393 | } |
1412 | #else | ||
1413 | static inline void aic3x_i2c_init(void) { } | ||
1414 | static inline void aic3x_i2c_exit(void) { } | ||
1415 | #endif | 1394 | #endif |
1416 | 1395 | ||
1417 | static int aic3x_probe(struct platform_device *pdev) | 1396 | static int __init aic3x_modinit(void) |
1418 | { | 1397 | { |
1419 | struct snd_soc_device *socdev = platform_get_drvdata(pdev); | ||
1420 | struct aic3x_setup_data *setup; | ||
1421 | struct snd_soc_codec *codec; | ||
1422 | int ret = 0; | 1398 | int ret = 0; |
1423 | 1399 | #if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE) | |
1424 | codec = aic3x_codec; | 1400 | ret = i2c_add_driver(&aic3x_i2c_driver); |
1425 | if (!codec) { | 1401 | if (ret != 0) { |
1426 | dev_err(&pdev->dev, "Codec not registered\n"); | 1402 | printk(KERN_ERR "Failed to register TLV320AIC3x I2C driver: %d\n", |
1427 | return -ENODEV; | 1403 | ret); |
1428 | } | ||
1429 | |||
1430 | socdev->card->codec = codec; | ||
1431 | setup = socdev->codec_data; | ||
1432 | |||
1433 | if (setup) { | ||
1434 | /* setup GPIO functions */ | ||
1435 | aic3x_write(codec, AIC3X_GPIO1_REG, | ||
1436 | (setup->gpio_func[0] & 0xf) << 4); | ||
1437 | aic3x_write(codec, AIC3X_GPIO2_REG, | ||
1438 | (setup->gpio_func[1] & 0xf) << 4); | ||
1439 | } | ||
1440 | |||
1441 | /* register pcms */ | ||
1442 | ret = snd_soc_new_pcms(socdev, SNDRV_DEFAULT_IDX1, SNDRV_DEFAULT_STR1); | ||
1443 | if (ret < 0) { | ||
1444 | printk(KERN_ERR "aic3x: failed to create pcms\n"); | ||
1445 | goto pcm_err; | ||
1446 | } | 1404 | } |
1447 | 1405 | #endif | |
1448 | snd_soc_add_controls(codec, aic3x_snd_controls, | ||
1449 | ARRAY_SIZE(aic3x_snd_controls)); | ||
1450 | |||
1451 | aic3x_add_widgets(codec); | ||
1452 | |||
1453 | return ret; | ||
1454 | |||
1455 | pcm_err: | ||
1456 | kfree(codec->reg_cache); | ||
1457 | return ret; | 1406 | return ret; |
1458 | } | 1407 | } |
1459 | |||
1460 | static int aic3x_remove(struct platform_device *pdev) | ||
1461 | { | ||
1462 | struct snd_soc_device *socdev = platform_get_drvdata(pdev); | ||
1463 | struct snd_soc_codec *codec = socdev->card->codec; | ||
1464 | |||
1465 | /* power down chip */ | ||
1466 | if (codec->control_data) | ||
1467 | aic3x_set_bias_level(codec, SND_SOC_BIAS_OFF); | ||
1468 | |||
1469 | snd_soc_free_pcms(socdev); | ||
1470 | snd_soc_dapm_free(socdev); | ||
1471 | |||
1472 | kfree(codec->reg_cache); | ||
1473 | |||
1474 | return 0; | ||
1475 | } | ||
1476 | |||
1477 | struct snd_soc_codec_device soc_codec_dev_aic3x = { | ||
1478 | .probe = aic3x_probe, | ||
1479 | .remove = aic3x_remove, | ||
1480 | .suspend = aic3x_suspend, | ||
1481 | .resume = aic3x_resume, | ||
1482 | }; | ||
1483 | EXPORT_SYMBOL_GPL(soc_codec_dev_aic3x); | ||
1484 | |||
1485 | static int __init aic3x_modinit(void) | ||
1486 | { | ||
1487 | aic3x_i2c_init(); | ||
1488 | |||
1489 | return 0; | ||
1490 | } | ||
1491 | module_init(aic3x_modinit); | 1408 | module_init(aic3x_modinit); |
1492 | 1409 | ||
1493 | static void __exit aic3x_exit(void) | 1410 | static void __exit aic3x_exit(void) |
1494 | { | 1411 | { |
1495 | aic3x_i2c_exit(); | 1412 | #if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE) |
1413 | i2c_del_driver(&aic3x_i2c_driver); | ||
1414 | #endif | ||
1496 | } | 1415 | } |
1497 | module_exit(aic3x_exit); | 1416 | module_exit(aic3x_exit); |
1498 | 1417 | ||
diff --git a/sound/soc/codecs/tlv320aic3x.h b/sound/soc/codecs/tlv320aic3x.h index 9af1c886213c..f6e3d9b42daf 100644 --- a/sound/soc/codecs/tlv320aic3x.h +++ b/sound/soc/codecs/tlv320aic3x.h | |||
@@ -199,42 +199,6 @@ | |||
199 | /* Default input volume */ | 199 | /* Default input volume */ |
200 | #define DEFAULT_GAIN 0x20 | 200 | #define DEFAULT_GAIN 0x20 |
201 | 201 | ||
202 | /* GPIO API */ | ||
203 | enum { | ||
204 | AIC3X_GPIO1_FUNC_DISABLED = 0, | ||
205 | AIC3X_GPIO1_FUNC_AUDIO_WORDCLK_ADC = 1, | ||
206 | AIC3X_GPIO1_FUNC_CLOCK_MUX = 2, | ||
207 | AIC3X_GPIO1_FUNC_CLOCK_MUX_DIV2 = 3, | ||
208 | AIC3X_GPIO1_FUNC_CLOCK_MUX_DIV4 = 4, | ||
209 | AIC3X_GPIO1_FUNC_CLOCK_MUX_DIV8 = 5, | ||
210 | AIC3X_GPIO1_FUNC_SHORT_CIRCUIT_IRQ = 6, | ||
211 | AIC3X_GPIO1_FUNC_AGC_NOISE_IRQ = 7, | ||
212 | AIC3X_GPIO1_FUNC_INPUT = 8, | ||
213 | AIC3X_GPIO1_FUNC_OUTPUT = 9, | ||
214 | AIC3X_GPIO1_FUNC_DIGITAL_MIC_MODCLK = 10, | ||
215 | AIC3X_GPIO1_FUNC_AUDIO_WORDCLK = 11, | ||
216 | AIC3X_GPIO1_FUNC_BUTTON_IRQ = 12, | ||
217 | AIC3X_GPIO1_FUNC_HEADSET_DETECT_IRQ = 13, | ||
218 | AIC3X_GPIO1_FUNC_HEADSET_DETECT_OR_BUTTON_IRQ = 14, | ||
219 | AIC3X_GPIO1_FUNC_ALL_IRQ = 16 | ||
220 | }; | ||
221 | |||
222 | enum { | ||
223 | AIC3X_GPIO2_FUNC_DISABLED = 0, | ||
224 | AIC3X_GPIO2_FUNC_HEADSET_DETECT_IRQ = 2, | ||
225 | AIC3X_GPIO2_FUNC_INPUT = 3, | ||
226 | AIC3X_GPIO2_FUNC_OUTPUT = 4, | ||
227 | AIC3X_GPIO2_FUNC_DIGITAL_MIC_INPUT = 5, | ||
228 | AIC3X_GPIO2_FUNC_AUDIO_BITCLK = 8, | ||
229 | AIC3X_GPIO2_FUNC_HEADSET_DETECT_OR_BUTTON_IRQ = 9, | ||
230 | AIC3X_GPIO2_FUNC_ALL_IRQ = 10, | ||
231 | AIC3X_GPIO2_FUNC_SHORT_CIRCUIT_OR_AGC_IRQ = 11, | ||
232 | AIC3X_GPIO2_FUNC_HEADSET_OR_BUTTON_PRESS_OR_SHORT_CIRCUIT_IRQ = 12, | ||
233 | AIC3X_GPIO2_FUNC_SHORT_CIRCUIT_IRQ = 13, | ||
234 | AIC3X_GPIO2_FUNC_AGC_NOISE_IRQ = 14, | ||
235 | AIC3X_GPIO2_FUNC_BUTTON_PRESS_IRQ = 15 | ||
236 | }; | ||
237 | |||
238 | void aic3x_set_gpio(struct snd_soc_codec *codec, int gpio, int state); | 202 | void aic3x_set_gpio(struct snd_soc_codec *codec, int gpio, int state); |
239 | int aic3x_get_gpio(struct snd_soc_codec *codec, int gpio); | 203 | int aic3x_get_gpio(struct snd_soc_codec *codec, int gpio); |
240 | 204 | ||
@@ -281,11 +245,4 @@ void aic3x_set_headset_detection(struct snd_soc_codec *codec, int detect, | |||
281 | int aic3x_headset_detected(struct snd_soc_codec *codec); | 245 | int aic3x_headset_detected(struct snd_soc_codec *codec); |
282 | int aic3x_button_pressed(struct snd_soc_codec *codec); | 246 | int aic3x_button_pressed(struct snd_soc_codec *codec); |
283 | 247 | ||
284 | struct aic3x_setup_data { | ||
285 | unsigned int gpio_func[2]; | ||
286 | }; | ||
287 | |||
288 | extern struct snd_soc_dai aic3x_dai; | ||
289 | extern struct snd_soc_codec_device soc_codec_dev_aic3x; | ||
290 | |||
291 | #endif /* _AIC3X_H */ | 248 | #endif /* _AIC3X_H */ |
diff --git a/sound/soc/codecs/tlv320dac33.c b/sound/soc/codecs/tlv320dac33.c index 8651b01ed223..a3c5b521da6a 100644 --- a/sound/soc/codecs/tlv320dac33.c +++ b/sound/soc/codecs/tlv320dac33.c | |||
@@ -66,8 +66,6 @@ | |||
66 | static void dac33_calculate_times(struct snd_pcm_substream *substream); | 66 | static void dac33_calculate_times(struct snd_pcm_substream *substream); |
67 | static int dac33_prepare_chip(struct snd_pcm_substream *substream); | 67 | static int dac33_prepare_chip(struct snd_pcm_substream *substream); |
68 | 68 | ||
69 | static struct snd_soc_codec *tlv320dac33_codec; | ||
70 | |||
71 | enum dac33_state { | 69 | enum dac33_state { |
72 | DAC33_IDLE = 0, | 70 | DAC33_IDLE = 0, |
73 | DAC33_PREFILL, | 71 | DAC33_PREFILL, |
@@ -93,7 +91,7 @@ struct tlv320dac33_priv { | |||
93 | struct mutex mutex; | 91 | struct mutex mutex; |
94 | struct workqueue_struct *dac33_wq; | 92 | struct workqueue_struct *dac33_wq; |
95 | struct work_struct work; | 93 | struct work_struct work; |
96 | struct snd_soc_codec codec; | 94 | struct snd_soc_codec *codec; |
97 | struct regulator_bulk_data supplies[DAC33_NUM_SUPPLIES]; | 95 | struct regulator_bulk_data supplies[DAC33_NUM_SUPPLIES]; |
98 | struct snd_pcm_substream *substream; | 96 | struct snd_pcm_substream *substream; |
99 | int power_gpio; | 97 | int power_gpio; |
@@ -128,6 +126,8 @@ struct tlv320dac33_priv { | |||
128 | unsigned int uthr; | 126 | unsigned int uthr; |
129 | 127 | ||
130 | enum dac33_state state; | 128 | enum dac33_state state; |
129 | enum snd_soc_control_type control_type; | ||
130 | void *control_data; | ||
131 | }; | 131 | }; |
132 | 132 | ||
133 | static const u8 dac33_reg[DAC33_CACHEREGNUM] = { | 133 | static const u8 dac33_reg[DAC33_CACHEREGNUM] = { |
@@ -650,9 +650,7 @@ static int dac33_set_bias_level(struct snd_soc_codec *codec, | |||
650 | 650 | ||
651 | static inline void dac33_prefill_handler(struct tlv320dac33_priv *dac33) | 651 | static inline void dac33_prefill_handler(struct tlv320dac33_priv *dac33) |
652 | { | 652 | { |
653 | struct snd_soc_codec *codec; | 653 | struct snd_soc_codec *codec = dac33->codec; |
654 | |||
655 | codec = &dac33->codec; | ||
656 | 654 | ||
657 | switch (dac33->fifo_mode) { | 655 | switch (dac33->fifo_mode) { |
658 | case DAC33_FIFO_MODE1: | 656 | case DAC33_FIFO_MODE1: |
@@ -695,9 +693,7 @@ static inline void dac33_prefill_handler(struct tlv320dac33_priv *dac33) | |||
695 | 693 | ||
696 | static inline void dac33_playback_handler(struct tlv320dac33_priv *dac33) | 694 | static inline void dac33_playback_handler(struct tlv320dac33_priv *dac33) |
697 | { | 695 | { |
698 | struct snd_soc_codec *codec; | 696 | struct snd_soc_codec *codec = dac33->codec; |
699 | |||
700 | codec = &dac33->codec; | ||
701 | 697 | ||
702 | switch (dac33->fifo_mode) { | 698 | switch (dac33->fifo_mode) { |
703 | case DAC33_FIFO_MODE1: | 699 | case DAC33_FIFO_MODE1: |
@@ -726,7 +722,7 @@ static void dac33_work(struct work_struct *work) | |||
726 | u8 reg; | 722 | u8 reg; |
727 | 723 | ||
728 | dac33 = container_of(work, struct tlv320dac33_priv, work); | 724 | dac33 = container_of(work, struct tlv320dac33_priv, work); |
729 | codec = &dac33->codec; | 725 | codec = dac33->codec; |
730 | 726 | ||
731 | mutex_lock(&dac33->mutex); | 727 | mutex_lock(&dac33->mutex); |
732 | switch (dac33->state) { | 728 | switch (dac33->state) { |
@@ -787,8 +783,7 @@ static int dac33_startup(struct snd_pcm_substream *substream, | |||
787 | struct snd_soc_dai *dai) | 783 | struct snd_soc_dai *dai) |
788 | { | 784 | { |
789 | struct snd_soc_pcm_runtime *rtd = substream->private_data; | 785 | struct snd_soc_pcm_runtime *rtd = substream->private_data; |
790 | struct snd_soc_device *socdev = rtd->socdev; | 786 | struct snd_soc_codec *codec = rtd->codec; |
791 | struct snd_soc_codec *codec = socdev->card->codec; | ||
792 | struct tlv320dac33_priv *dac33 = snd_soc_codec_get_drvdata(codec); | 787 | struct tlv320dac33_priv *dac33 = snd_soc_codec_get_drvdata(codec); |
793 | 788 | ||
794 | /* Stream started, save the substream pointer */ | 789 | /* Stream started, save the substream pointer */ |
@@ -801,8 +796,7 @@ static void dac33_shutdown(struct snd_pcm_substream *substream, | |||
801 | struct snd_soc_dai *dai) | 796 | struct snd_soc_dai *dai) |
802 | { | 797 | { |
803 | struct snd_soc_pcm_runtime *rtd = substream->private_data; | 798 | struct snd_soc_pcm_runtime *rtd = substream->private_data; |
804 | struct snd_soc_device *socdev = rtd->socdev; | 799 | struct snd_soc_codec *codec = rtd->codec; |
805 | struct snd_soc_codec *codec = socdev->card->codec; | ||
806 | struct tlv320dac33_priv *dac33 = snd_soc_codec_get_drvdata(codec); | 800 | struct tlv320dac33_priv *dac33 = snd_soc_codec_get_drvdata(codec); |
807 | 801 | ||
808 | dac33->substream = NULL; | 802 | dac33->substream = NULL; |
@@ -817,8 +811,7 @@ static int dac33_hw_params(struct snd_pcm_substream *substream, | |||
817 | struct snd_soc_dai *dai) | 811 | struct snd_soc_dai *dai) |
818 | { | 812 | { |
819 | struct snd_soc_pcm_runtime *rtd = substream->private_data; | 813 | struct snd_soc_pcm_runtime *rtd = substream->private_data; |
820 | struct snd_soc_device *socdev = rtd->socdev; | 814 | struct snd_soc_codec *codec = rtd->codec; |
821 | struct snd_soc_codec *codec = socdev->card->codec; | ||
822 | 815 | ||
823 | /* Check parameters for validity */ | 816 | /* Check parameters for validity */ |
824 | switch (params_rate(params)) { | 817 | switch (params_rate(params)) { |
@@ -856,8 +849,7 @@ static int dac33_hw_params(struct snd_pcm_substream *substream, | |||
856 | static int dac33_prepare_chip(struct snd_pcm_substream *substream) | 849 | static int dac33_prepare_chip(struct snd_pcm_substream *substream) |
857 | { | 850 | { |
858 | struct snd_soc_pcm_runtime *rtd = substream->private_data; | 851 | struct snd_soc_pcm_runtime *rtd = substream->private_data; |
859 | struct snd_soc_device *socdev = rtd->socdev; | 852 | struct snd_soc_codec *codec = rtd->codec; |
860 | struct snd_soc_codec *codec = socdev->card->codec; | ||
861 | struct tlv320dac33_priv *dac33 = snd_soc_codec_get_drvdata(codec); | 853 | struct tlv320dac33_priv *dac33 = snd_soc_codec_get_drvdata(codec); |
862 | unsigned int oscset, ratioset, pwr_ctrl, reg_tmp; | 854 | unsigned int oscset, ratioset, pwr_ctrl, reg_tmp; |
863 | u8 aictrl_a, aictrl_b, fifoctrl_a; | 855 | u8 aictrl_a, aictrl_b, fifoctrl_a; |
@@ -1049,8 +1041,7 @@ static int dac33_prepare_chip(struct snd_pcm_substream *substream) | |||
1049 | static void dac33_calculate_times(struct snd_pcm_substream *substream) | 1041 | static void dac33_calculate_times(struct snd_pcm_substream *substream) |
1050 | { | 1042 | { |
1051 | struct snd_soc_pcm_runtime *rtd = substream->private_data; | 1043 | struct snd_soc_pcm_runtime *rtd = substream->private_data; |
1052 | struct snd_soc_device *socdev = rtd->socdev; | 1044 | struct snd_soc_codec *codec = rtd->codec; |
1053 | struct snd_soc_codec *codec = socdev->card->codec; | ||
1054 | struct tlv320dac33_priv *dac33 = snd_soc_codec_get_drvdata(codec); | 1045 | struct tlv320dac33_priv *dac33 = snd_soc_codec_get_drvdata(codec); |
1055 | unsigned int period_size = substream->runtime->period_size; | 1046 | unsigned int period_size = substream->runtime->period_size; |
1056 | unsigned int rate = substream->runtime->rate; | 1047 | unsigned int rate = substream->runtime->rate; |
@@ -1129,8 +1120,7 @@ static int dac33_pcm_trigger(struct snd_pcm_substream *substream, int cmd, | |||
1129 | struct snd_soc_dai *dai) | 1120 | struct snd_soc_dai *dai) |
1130 | { | 1121 | { |
1131 | struct snd_soc_pcm_runtime *rtd = substream->private_data; | 1122 | struct snd_soc_pcm_runtime *rtd = substream->private_data; |
1132 | struct snd_soc_device *socdev = rtd->socdev; | 1123 | struct snd_soc_codec *codec = rtd->codec; |
1133 | struct snd_soc_codec *codec = socdev->card->codec; | ||
1134 | struct tlv320dac33_priv *dac33 = snd_soc_codec_get_drvdata(codec); | 1124 | struct tlv320dac33_priv *dac33 = snd_soc_codec_get_drvdata(codec); |
1135 | int ret = 0; | 1125 | int ret = 0; |
1136 | 1126 | ||
@@ -1163,8 +1153,7 @@ static snd_pcm_sframes_t dac33_dai_delay( | |||
1163 | struct snd_soc_dai *dai) | 1153 | struct snd_soc_dai *dai) |
1164 | { | 1154 | { |
1165 | struct snd_soc_pcm_runtime *rtd = substream->private_data; | 1155 | struct snd_soc_pcm_runtime *rtd = substream->private_data; |
1166 | struct snd_soc_device *socdev = rtd->socdev; | 1156 | struct snd_soc_codec *codec = rtd->codec; |
1167 | struct snd_soc_codec *codec = socdev->card->codec; | ||
1168 | struct tlv320dac33_priv *dac33 = snd_soc_codec_get_drvdata(codec); | 1157 | struct tlv320dac33_priv *dac33 = snd_soc_codec_get_drvdata(codec); |
1169 | unsigned long long t0, t1, t_now; | 1158 | unsigned long long t0, t1, t_now; |
1170 | unsigned int time_delta, uthr; | 1159 | unsigned int time_delta, uthr; |
@@ -1389,24 +1378,47 @@ static int dac33_set_dai_fmt(struct snd_soc_dai *codec_dai, | |||
1389 | return 0; | 1378 | return 0; |
1390 | } | 1379 | } |
1391 | 1380 | ||
1392 | static int dac33_soc_probe(struct platform_device *pdev) | 1381 | static int dac33_soc_probe(struct snd_soc_codec *codec) |
1393 | { | 1382 | { |
1394 | struct snd_soc_device *socdev = platform_get_drvdata(pdev); | 1383 | struct tlv320dac33_priv *dac33 = snd_soc_codec_get_drvdata(codec); |
1395 | struct snd_soc_codec *codec; | ||
1396 | struct tlv320dac33_priv *dac33; | ||
1397 | int ret = 0; | 1384 | int ret = 0; |
1398 | 1385 | ||
1399 | BUG_ON(!tlv320dac33_codec); | 1386 | codec->control_data = dac33->control_data; |
1387 | codec->hw_write = (hw_write_t) i2c_master_send; | ||
1388 | codec->bias_level = SND_SOC_BIAS_OFF; | ||
1389 | codec->idle_bias_off = 1; | ||
1390 | dac33->codec = codec; | ||
1400 | 1391 | ||
1401 | codec = tlv320dac33_codec; | 1392 | /* Read the tlv320dac33 ID registers */ |
1402 | socdev->card->codec = codec; | 1393 | ret = dac33_hard_power(codec, 1); |
1403 | dac33 = snd_soc_codec_get_drvdata(codec); | 1394 | if (ret != 0) { |
1395 | dev_err(codec->dev, "Failed to power up codec: %d\n", ret); | ||
1396 | goto err_power; | ||
1397 | } | ||
1398 | dac33_read_id(codec); | ||
1399 | dac33_hard_power(codec, 0); | ||
1404 | 1400 | ||
1405 | /* register pcms */ | 1401 | /* Check if the IRQ number is valid and request it */ |
1406 | ret = snd_soc_new_pcms(socdev, SNDRV_DEFAULT_IDX1, SNDRV_DEFAULT_STR1); | 1402 | if (dac33->irq >= 0) { |
1407 | if (ret < 0) { | 1403 | ret = request_irq(dac33->irq, dac33_interrupt_handler, |
1408 | dev_err(codec->dev, "failed to create pcms\n"); | 1404 | IRQF_TRIGGER_RISING | IRQF_DISABLED, |
1409 | goto pcm_err; | 1405 | codec->name, codec); |
1406 | if (ret < 0) { | ||
1407 | dev_err(codec->dev, "Could not request IRQ%d (%d)\n", | ||
1408 | dac33->irq, ret); | ||
1409 | dac33->irq = -1; | ||
1410 | } | ||
1411 | if (dac33->irq != -1) { | ||
1412 | /* Setup work queue */ | ||
1413 | dac33->dac33_wq = | ||
1414 | create_singlethread_workqueue("tlv320dac33"); | ||
1415 | if (dac33->dac33_wq == NULL) { | ||
1416 | free_irq(dac33->irq, codec); | ||
1417 | return -ENOMEM; | ||
1418 | } | ||
1419 | |||
1420 | INIT_WORK(&dac33->work, dac33_work); | ||
1421 | } | ||
1410 | } | 1422 | } |
1411 | 1423 | ||
1412 | snd_soc_add_controls(codec, dac33_snd_controls, | 1424 | snd_soc_add_controls(codec, dac33_snd_controls, |
@@ -1420,56 +1432,51 @@ static int dac33_soc_probe(struct platform_device *pdev) | |||
1420 | snd_soc_add_controls(codec, dac33_fifo_snd_controls, | 1432 | snd_soc_add_controls(codec, dac33_fifo_snd_controls, |
1421 | ARRAY_SIZE(dac33_fifo_snd_controls)); | 1433 | ARRAY_SIZE(dac33_fifo_snd_controls)); |
1422 | } | 1434 | } |
1423 | |||
1424 | dac33_add_widgets(codec); | 1435 | dac33_add_widgets(codec); |
1425 | 1436 | ||
1426 | return 0; | 1437 | err_power: |
1427 | |||
1428 | pcm_err: | ||
1429 | dac33_hard_power(codec, 0); | ||
1430 | return ret; | 1438 | return ret; |
1431 | } | 1439 | } |
1432 | 1440 | ||
1433 | static int dac33_soc_remove(struct platform_device *pdev) | 1441 | static int dac33_soc_remove(struct snd_soc_codec *codec) |
1434 | { | 1442 | { |
1435 | struct snd_soc_device *socdev = platform_get_drvdata(pdev); | 1443 | struct tlv320dac33_priv *dac33 = snd_soc_codec_get_drvdata(codec); |
1436 | struct snd_soc_codec *codec = socdev->card->codec; | ||
1437 | 1444 | ||
1438 | dac33_set_bias_level(codec, SND_SOC_BIAS_OFF); | 1445 | dac33_set_bias_level(codec, SND_SOC_BIAS_OFF); |
1439 | 1446 | ||
1440 | snd_soc_free_pcms(socdev); | 1447 | if (dac33->irq >= 0) { |
1441 | snd_soc_dapm_free(socdev); | 1448 | free_irq(dac33->irq, dac33->codec); |
1442 | 1449 | destroy_workqueue(dac33->dac33_wq); | |
1450 | } | ||
1443 | return 0; | 1451 | return 0; |
1444 | } | 1452 | } |
1445 | 1453 | ||
1446 | static int dac33_soc_suspend(struct platform_device *pdev, pm_message_t state) | 1454 | static int dac33_soc_suspend(struct snd_soc_codec *codec, pm_message_t state) |
1447 | { | 1455 | { |
1448 | struct snd_soc_device *socdev = platform_get_drvdata(pdev); | ||
1449 | struct snd_soc_codec *codec = socdev->card->codec; | ||
1450 | |||
1451 | dac33_set_bias_level(codec, SND_SOC_BIAS_OFF); | 1456 | dac33_set_bias_level(codec, SND_SOC_BIAS_OFF); |
1452 | 1457 | ||
1453 | return 0; | 1458 | return 0; |
1454 | } | 1459 | } |
1455 | 1460 | ||
1456 | static int dac33_soc_resume(struct platform_device *pdev) | 1461 | static int dac33_soc_resume(struct snd_soc_codec *codec) |
1457 | { | 1462 | { |
1458 | struct snd_soc_device *socdev = platform_get_drvdata(pdev); | ||
1459 | struct snd_soc_codec *codec = socdev->card->codec; | ||
1460 | |||
1461 | dac33_set_bias_level(codec, SND_SOC_BIAS_STANDBY); | 1463 | dac33_set_bias_level(codec, SND_SOC_BIAS_STANDBY); |
1462 | 1464 | ||
1463 | return 0; | 1465 | return 0; |
1464 | } | 1466 | } |
1465 | 1467 | ||
1466 | struct snd_soc_codec_device soc_codec_dev_tlv320dac33 = { | 1468 | static struct snd_soc_codec_driver soc_codec_dev_tlv320dac33 = { |
1469 | .read = dac33_read_reg_cache, | ||
1470 | .write = dac33_write_locked, | ||
1471 | .set_bias_level = dac33_set_bias_level, | ||
1472 | .reg_cache_size = ARRAY_SIZE(dac33_reg), | ||
1473 | .reg_word_size = sizeof(u8), | ||
1474 | .reg_cache_default = dac33_reg, | ||
1467 | .probe = dac33_soc_probe, | 1475 | .probe = dac33_soc_probe, |
1468 | .remove = dac33_soc_remove, | 1476 | .remove = dac33_soc_remove, |
1469 | .suspend = dac33_soc_suspend, | 1477 | .suspend = dac33_soc_suspend, |
1470 | .resume = dac33_soc_resume, | 1478 | .resume = dac33_soc_resume, |
1471 | }; | 1479 | }; |
1472 | EXPORT_SYMBOL_GPL(soc_codec_dev_tlv320dac33); | ||
1473 | 1480 | ||
1474 | #define DAC33_RATES (SNDRV_PCM_RATE_44100 | \ | 1481 | #define DAC33_RATES (SNDRV_PCM_RATE_44100 | \ |
1475 | SNDRV_PCM_RATE_48000) | 1482 | SNDRV_PCM_RATE_48000) |
@@ -1485,8 +1492,8 @@ static struct snd_soc_dai_ops dac33_dai_ops = { | |||
1485 | .set_fmt = dac33_set_dai_fmt, | 1492 | .set_fmt = dac33_set_dai_fmt, |
1486 | }; | 1493 | }; |
1487 | 1494 | ||
1488 | struct snd_soc_dai dac33_dai = { | 1495 | static struct snd_soc_dai_driver dac33_dai = { |
1489 | .name = "tlv320dac33", | 1496 | .name = "tlv320dac33-hifi", |
1490 | .playback = { | 1497 | .playback = { |
1491 | .stream_name = "Playback", | 1498 | .stream_name = "Playback", |
1492 | .channels_min = 2, | 1499 | .channels_min = 2, |
@@ -1495,14 +1502,12 @@ struct snd_soc_dai dac33_dai = { | |||
1495 | .formats = DAC33_FORMATS,}, | 1502 | .formats = DAC33_FORMATS,}, |
1496 | .ops = &dac33_dai_ops, | 1503 | .ops = &dac33_dai_ops, |
1497 | }; | 1504 | }; |
1498 | EXPORT_SYMBOL_GPL(dac33_dai); | ||
1499 | 1505 | ||
1500 | static int __devinit dac33_i2c_probe(struct i2c_client *client, | 1506 | static int __devinit dac33_i2c_probe(struct i2c_client *client, |
1501 | const struct i2c_device_id *id) | 1507 | const struct i2c_device_id *id) |
1502 | { | 1508 | { |
1503 | struct tlv320dac33_platform_data *pdata; | 1509 | struct tlv320dac33_platform_data *pdata; |
1504 | struct tlv320dac33_priv *dac33; | 1510 | struct tlv320dac33_priv *dac33; |
1505 | struct snd_soc_codec *codec; | ||
1506 | int ret, i; | 1511 | int ret, i; |
1507 | 1512 | ||
1508 | if (client->dev.platform_data == NULL) { | 1513 | if (client->dev.platform_data == NULL) { |
@@ -1515,33 +1520,9 @@ static int __devinit dac33_i2c_probe(struct i2c_client *client, | |||
1515 | if (dac33 == NULL) | 1520 | if (dac33 == NULL) |
1516 | return -ENOMEM; | 1521 | return -ENOMEM; |
1517 | 1522 | ||
1518 | codec = &dac33->codec; | 1523 | dac33->control_data = client; |
1519 | snd_soc_codec_set_drvdata(codec, dac33); | ||
1520 | codec->control_data = client; | ||
1521 | |||
1522 | mutex_init(&codec->mutex); | ||
1523 | mutex_init(&dac33->mutex); | 1524 | mutex_init(&dac33->mutex); |
1524 | spin_lock_init(&dac33->lock); | 1525 | spin_lock_init(&dac33->lock); |
1525 | INIT_LIST_HEAD(&codec->dapm_widgets); | ||
1526 | INIT_LIST_HEAD(&codec->dapm_paths); | ||
1527 | |||
1528 | codec->name = "tlv320dac33"; | ||
1529 | codec->owner = THIS_MODULE; | ||
1530 | codec->read = dac33_read_reg_cache; | ||
1531 | codec->write = dac33_write_locked; | ||
1532 | codec->hw_write = (hw_write_t) i2c_master_send; | ||
1533 | codec->bias_level = SND_SOC_BIAS_OFF; | ||
1534 | codec->set_bias_level = dac33_set_bias_level; | ||
1535 | codec->idle_bias_off = 1; | ||
1536 | codec->dai = &dac33_dai; | ||
1537 | codec->num_dai = 1; | ||
1538 | codec->reg_cache_size = ARRAY_SIZE(dac33_reg); | ||
1539 | codec->reg_cache = kmemdup(dac33_reg, ARRAY_SIZE(dac33_reg), | ||
1540 | GFP_KERNEL); | ||
1541 | if (codec->reg_cache == NULL) { | ||
1542 | ret = -ENOMEM; | ||
1543 | goto error_reg; | ||
1544 | } | ||
1545 | 1526 | ||
1546 | i2c_set_clientdata(client, dac33); | 1527 | i2c_set_clientdata(client, dac33); |
1547 | 1528 | ||
@@ -1561,125 +1542,59 @@ static int __devinit dac33_i2c_probe(struct i2c_client *client, | |||
1561 | /* Disable FIFO use by default */ | 1542 | /* Disable FIFO use by default */ |
1562 | dac33->fifo_mode = DAC33_FIFO_BYPASS; | 1543 | dac33->fifo_mode = DAC33_FIFO_BYPASS; |
1563 | 1544 | ||
1564 | tlv320dac33_codec = codec; | ||
1565 | |||
1566 | codec->dev = &client->dev; | ||
1567 | dac33_dai.dev = codec->dev; | ||
1568 | |||
1569 | /* Check if the reset GPIO number is valid and request it */ | 1545 | /* Check if the reset GPIO number is valid and request it */ |
1570 | if (dac33->power_gpio >= 0) { | 1546 | if (dac33->power_gpio >= 0) { |
1571 | ret = gpio_request(dac33->power_gpio, "tlv320dac33 reset"); | 1547 | ret = gpio_request(dac33->power_gpio, "tlv320dac33 reset"); |
1572 | if (ret < 0) { | 1548 | if (ret < 0) { |
1573 | dev_err(codec->dev, | 1549 | dev_err(&client->dev, |
1574 | "Failed to request reset GPIO (%d)\n", | 1550 | "Failed to request reset GPIO (%d)\n", |
1575 | dac33->power_gpio); | 1551 | dac33->power_gpio); |
1576 | snd_soc_unregister_dai(&dac33_dai); | 1552 | goto err_gpio; |
1577 | snd_soc_unregister_codec(codec); | ||
1578 | goto error_gpio; | ||
1579 | } | 1553 | } |
1580 | gpio_direction_output(dac33->power_gpio, 0); | 1554 | gpio_direction_output(dac33->power_gpio, 0); |
1581 | } | 1555 | } |
1582 | 1556 | ||
1583 | /* Check if the IRQ number is valid and request it */ | ||
1584 | if (dac33->irq >= 0) { | ||
1585 | ret = request_irq(dac33->irq, dac33_interrupt_handler, | ||
1586 | IRQF_TRIGGER_RISING | IRQF_DISABLED, | ||
1587 | codec->name, codec); | ||
1588 | if (ret < 0) { | ||
1589 | dev_err(codec->dev, "Could not request IRQ%d (%d)\n", | ||
1590 | dac33->irq, ret); | ||
1591 | dac33->irq = -1; | ||
1592 | } | ||
1593 | if (dac33->irq != -1) { | ||
1594 | /* Setup work queue */ | ||
1595 | dac33->dac33_wq = | ||
1596 | create_singlethread_workqueue("tlv320dac33"); | ||
1597 | if (dac33->dac33_wq == NULL) { | ||
1598 | free_irq(dac33->irq, &dac33->codec); | ||
1599 | ret = -ENOMEM; | ||
1600 | goto error_wq; | ||
1601 | } | ||
1602 | |||
1603 | INIT_WORK(&dac33->work, dac33_work); | ||
1604 | } | ||
1605 | } | ||
1606 | |||
1607 | for (i = 0; i < ARRAY_SIZE(dac33->supplies); i++) | 1557 | for (i = 0; i < ARRAY_SIZE(dac33->supplies); i++) |
1608 | dac33->supplies[i].supply = dac33_supply_names[i]; | 1558 | dac33->supplies[i].supply = dac33_supply_names[i]; |
1609 | 1559 | ||
1610 | ret = regulator_bulk_get(codec->dev, ARRAY_SIZE(dac33->supplies), | 1560 | ret = regulator_bulk_get(&client->dev, ARRAY_SIZE(dac33->supplies), |
1611 | dac33->supplies); | 1561 | dac33->supplies); |
1612 | 1562 | ||
1613 | if (ret != 0) { | 1563 | if (ret != 0) { |
1614 | dev_err(codec->dev, "Failed to request supplies: %d\n", ret); | 1564 | dev_err(&client->dev, "Failed to request supplies: %d\n", ret); |
1615 | goto err_get; | 1565 | goto err_get; |
1616 | } | 1566 | } |
1617 | 1567 | ||
1618 | /* Read the tlv320dac33 ID registers */ | 1568 | ret = snd_soc_register_codec(&client->dev, |
1619 | ret = dac33_hard_power(codec, 1); | 1569 | &soc_codec_dev_tlv320dac33, &dac33_dai, 1); |
1620 | if (ret != 0) { | 1570 | if (ret < 0) |
1621 | dev_err(codec->dev, "Failed to power up codec: %d\n", ret); | 1571 | goto err_register; |
1622 | goto error_codec; | ||
1623 | } | ||
1624 | dac33_read_id(codec); | ||
1625 | dac33_hard_power(codec, 0); | ||
1626 | |||
1627 | ret = snd_soc_register_codec(codec); | ||
1628 | if (ret != 0) { | ||
1629 | dev_err(codec->dev, "Failed to register codec: %d\n", ret); | ||
1630 | goto error_codec; | ||
1631 | } | ||
1632 | |||
1633 | ret = snd_soc_register_dai(&dac33_dai); | ||
1634 | if (ret != 0) { | ||
1635 | dev_err(codec->dev, "Failed to register DAI: %d\n", ret); | ||
1636 | snd_soc_unregister_codec(codec); | ||
1637 | goto error_codec; | ||
1638 | } | ||
1639 | 1572 | ||
1640 | return ret; | 1573 | return ret; |
1641 | 1574 | err_register: | |
1642 | error_codec: | ||
1643 | regulator_bulk_free(ARRAY_SIZE(dac33->supplies), dac33->supplies); | 1575 | regulator_bulk_free(ARRAY_SIZE(dac33->supplies), dac33->supplies); |
1644 | err_get: | 1576 | err_get: |
1645 | if (dac33->irq >= 0) { | ||
1646 | free_irq(dac33->irq, &dac33->codec); | ||
1647 | destroy_workqueue(dac33->dac33_wq); | ||
1648 | } | ||
1649 | error_wq: | ||
1650 | if (dac33->power_gpio >= 0) | 1577 | if (dac33->power_gpio >= 0) |
1651 | gpio_free(dac33->power_gpio); | 1578 | gpio_free(dac33->power_gpio); |
1652 | error_gpio: | 1579 | err_gpio: |
1653 | kfree(codec->reg_cache); | ||
1654 | error_reg: | ||
1655 | tlv320dac33_codec = NULL; | ||
1656 | kfree(dac33); | 1580 | kfree(dac33); |
1657 | |||
1658 | return ret; | 1581 | return ret; |
1659 | } | 1582 | } |
1660 | 1583 | ||
1661 | static int __devexit dac33_i2c_remove(struct i2c_client *client) | 1584 | static int __devexit dac33_i2c_remove(struct i2c_client *client) |
1662 | { | 1585 | { |
1663 | struct tlv320dac33_priv *dac33; | 1586 | struct tlv320dac33_priv *dac33 = i2c_get_clientdata(client); |
1664 | |||
1665 | dac33 = i2c_get_clientdata(client); | ||
1666 | 1587 | ||
1667 | if (unlikely(dac33->chip_power)) | 1588 | if (unlikely(dac33->chip_power)) |
1668 | dac33_hard_power(&dac33->codec, 0); | 1589 | dac33_hard_power(dac33->codec, 0); |
1669 | 1590 | ||
1670 | if (dac33->power_gpio >= 0) | 1591 | if (dac33->power_gpio >= 0) |
1671 | gpio_free(dac33->power_gpio); | 1592 | gpio_free(dac33->power_gpio); |
1672 | if (dac33->irq >= 0) | ||
1673 | free_irq(dac33->irq, &dac33->codec); | ||
1674 | 1593 | ||
1675 | regulator_bulk_free(ARRAY_SIZE(dac33->supplies), dac33->supplies); | 1594 | regulator_bulk_free(ARRAY_SIZE(dac33->supplies), dac33->supplies); |
1676 | 1595 | ||
1677 | destroy_workqueue(dac33->dac33_wq); | 1596 | snd_soc_unregister_codec(&client->dev); |
1678 | snd_soc_unregister_dai(&dac33_dai); | ||
1679 | snd_soc_unregister_codec(&dac33->codec); | ||
1680 | kfree(dac33->codec.reg_cache); | ||
1681 | kfree(dac33); | 1597 | kfree(dac33); |
1682 | tlv320dac33_codec = NULL; | ||
1683 | 1598 | ||
1684 | return 0; | 1599 | return 0; |
1685 | } | 1600 | } |
@@ -1694,7 +1609,7 @@ static const struct i2c_device_id tlv320dac33_i2c_id[] = { | |||
1694 | 1609 | ||
1695 | static struct i2c_driver tlv320dac33_i2c_driver = { | 1610 | static struct i2c_driver tlv320dac33_i2c_driver = { |
1696 | .driver = { | 1611 | .driver = { |
1697 | .name = "tlv320dac33", | 1612 | .name = "tlv320dac33-codec", |
1698 | .owner = THIS_MODULE, | 1613 | .owner = THIS_MODULE, |
1699 | }, | 1614 | }, |
1700 | .probe = dac33_i2c_probe, | 1615 | .probe = dac33_i2c_probe, |
diff --git a/sound/soc/codecs/tlv320dac33.h b/sound/soc/codecs/tlv320dac33.h index eb8ae07f0bd2..7c318b5da437 100644 --- a/sound/soc/codecs/tlv320dac33.h +++ b/sound/soc/codecs/tlv320dac33.h | |||
@@ -261,7 +261,4 @@ | |||
261 | #define TLV320DAC33_MCLK 0 | 261 | #define TLV320DAC33_MCLK 0 |
262 | #define TLV320DAC33_SLEEPCLK 1 | 262 | #define TLV320DAC33_SLEEPCLK 1 |
263 | 263 | ||
264 | extern struct snd_soc_dai dac33_dai; | ||
265 | extern struct snd_soc_codec_device soc_codec_dev_tlv320dac33; | ||
266 | |||
267 | #endif /* __TLV320DAC33_H */ | 264 | #endif /* __TLV320DAC33_H */ |
diff --git a/sound/soc/codecs/twl4030.c b/sound/soc/codecs/twl4030.c index 7b618bbff884..c7ee1a4c9d99 100644 --- a/sound/soc/codecs/twl4030.c +++ b/sound/soc/codecs/twl4030.c | |||
@@ -36,7 +36,16 @@ | |||
36 | #include <sound/initval.h> | 36 | #include <sound/initval.h> |
37 | #include <sound/tlv.h> | 37 | #include <sound/tlv.h> |
38 | 38 | ||
39 | #include "twl4030.h" | 39 | /* Register descriptions are here */ |
40 | #include <linux/mfd/twl4030-codec.h> | ||
41 | |||
42 | /* Shadow register used by the audio driver */ | ||
43 | #define TWL4030_REG_SW_SHADOW 0x4A | ||
44 | #define TWL4030_CACHEREGNUM (TWL4030_REG_SW_SHADOW + 1) | ||
45 | |||
46 | /* TWL4030_REG_SW_SHADOW (0x4A) Fields */ | ||
47 | #define TWL4030_HFL_EN 0x01 | ||
48 | #define TWL4030_HFR_EN 0x02 | ||
40 | 49 | ||
41 | /* | 50 | /* |
42 | * twl4030 register cache & default register settings | 51 | * twl4030 register cache & default register settings |
@@ -277,21 +286,19 @@ static inline void twl4030_reset_registers(struct snd_soc_codec *codec) | |||
277 | 286 | ||
278 | } | 287 | } |
279 | 288 | ||
280 | static void twl4030_init_chip(struct platform_device *pdev) | 289 | static void twl4030_init_chip(struct snd_soc_codec *codec) |
281 | { | 290 | { |
282 | struct snd_soc_device *socdev = platform_get_drvdata(pdev); | 291 | struct twl4030_codec_audio_data *pdata = dev_get_platdata(codec->dev); |
283 | struct twl4030_setup_data *setup = socdev->codec_data; | ||
284 | struct snd_soc_codec *codec = socdev->card->codec; | ||
285 | struct twl4030_priv *twl4030 = snd_soc_codec_get_drvdata(codec); | 292 | struct twl4030_priv *twl4030 = snd_soc_codec_get_drvdata(codec); |
286 | u8 reg, byte; | 293 | u8 reg, byte; |
287 | int i = 0; | 294 | int i = 0; |
288 | 295 | ||
289 | /* Check defaults, if instructed before anything else */ | 296 | /* Check defaults, if instructed before anything else */ |
290 | if (setup && setup->check_defaults) | 297 | if (pdata && pdata->check_defaults) |
291 | twl4030_check_defaults(codec); | 298 | twl4030_check_defaults(codec); |
292 | 299 | ||
293 | /* Reset registers, if no setup data or if instructed to do so */ | 300 | /* Reset registers, if no setup data or if instructed to do so */ |
294 | if (!setup || (setup && setup->reset_registers)) | 301 | if (!pdata || (pdata && pdata->reset_registers)) |
295 | twl4030_reset_registers(codec); | 302 | twl4030_reset_registers(codec); |
296 | 303 | ||
297 | /* Refresh APLL_CTL register from HW */ | 304 | /* Refresh APLL_CTL register from HW */ |
@@ -312,20 +319,14 @@ static void twl4030_init_chip(struct platform_device *pdev) | |||
312 | twl4030_write(codec, TWL4030_REG_ARXR2_APGA_CTL, 0x32); | 319 | twl4030_write(codec, TWL4030_REG_ARXR2_APGA_CTL, 0x32); |
313 | 320 | ||
314 | /* Machine dependent setup */ | 321 | /* Machine dependent setup */ |
315 | if (!setup) | 322 | if (!pdata) |
316 | return; | 323 | return; |
317 | 324 | ||
318 | twl4030->digimic_delay = setup->digimic_delay; | 325 | twl4030->digimic_delay = pdata->digimic_delay; |
319 | |||
320 | /* Configuration for headset ramp delay from setup data */ | ||
321 | if (setup->sysclk != twl4030->sysclk) | ||
322 | dev_warn(codec->dev, | ||
323 | "Mismatch in APLL mclk: %u (configured: %u)\n", | ||
324 | setup->sysclk, twl4030->sysclk); | ||
325 | 326 | ||
326 | reg = twl4030_read_reg_cache(codec, TWL4030_REG_HS_POPN_SET); | 327 | reg = twl4030_read_reg_cache(codec, TWL4030_REG_HS_POPN_SET); |
327 | reg &= ~TWL4030_RAMP_DELAY; | 328 | reg &= ~TWL4030_RAMP_DELAY; |
328 | reg |= (setup->ramp_delay_value << 2); | 329 | reg |= (pdata->ramp_delay_value << 2); |
329 | twl4030_write_reg_cache(codec, TWL4030_REG_HS_POPN_SET, reg); | 330 | twl4030_write_reg_cache(codec, TWL4030_REG_HS_POPN_SET, reg); |
330 | 331 | ||
331 | /* initiate offset cancellation */ | 332 | /* initiate offset cancellation */ |
@@ -333,7 +334,7 @@ static void twl4030_init_chip(struct platform_device *pdev) | |||
333 | 334 | ||
334 | reg = twl4030_read_reg_cache(codec, TWL4030_REG_ANAMICL); | 335 | reg = twl4030_read_reg_cache(codec, TWL4030_REG_ANAMICL); |
335 | reg &= ~TWL4030_OFFSET_CNCL_SEL; | 336 | reg &= ~TWL4030_OFFSET_CNCL_SEL; |
336 | reg |= setup->offset_cncl_path; | 337 | reg |= pdata->offset_cncl_path; |
337 | twl4030_write(codec, TWL4030_REG_ANAMICL, | 338 | twl4030_write(codec, TWL4030_REG_ANAMICL, |
338 | reg | TWL4030_CNCL_OFFSET_START); | 339 | reg | TWL4030_CNCL_OFFSET_START); |
339 | 340 | ||
@@ -718,9 +719,7 @@ static int aif_event(struct snd_soc_dapm_widget *w, | |||
718 | 719 | ||
719 | static void headset_ramp(struct snd_soc_codec *codec, int ramp) | 720 | static void headset_ramp(struct snd_soc_codec *codec, int ramp) |
720 | { | 721 | { |
721 | struct snd_soc_device *socdev = codec->socdev; | 722 | struct twl4030_codec_audio_data *pdata = codec->dev->platform_data; |
722 | struct twl4030_setup_data *setup = socdev->codec_data; | ||
723 | |||
724 | unsigned char hs_gain, hs_pop; | 723 | unsigned char hs_gain, hs_pop; |
725 | struct twl4030_priv *twl4030 = snd_soc_codec_get_drvdata(codec); | 724 | struct twl4030_priv *twl4030 = snd_soc_codec_get_drvdata(codec); |
726 | /* Base values for ramp delay calculation: 2^19 - 2^26 */ | 725 | /* Base values for ramp delay calculation: 2^19 - 2^26 */ |
@@ -732,9 +731,9 @@ static void headset_ramp(struct snd_soc_codec *codec, int ramp) | |||
732 | 731 | ||
733 | /* Enable external mute control, this dramatically reduces | 732 | /* Enable external mute control, this dramatically reduces |
734 | * the pop-noise */ | 733 | * the pop-noise */ |
735 | if (setup && setup->hs_extmute) { | 734 | if (pdata && pdata->hs_extmute) { |
736 | if (setup->set_hs_extmute) { | 735 | if (pdata->set_hs_extmute) { |
737 | setup->set_hs_extmute(1); | 736 | pdata->set_hs_extmute(1); |
738 | } else { | 737 | } else { |
739 | hs_pop |= TWL4030_EXTMUTE; | 738 | hs_pop |= TWL4030_EXTMUTE; |
740 | twl4030_write(codec, TWL4030_REG_HS_POPN_SET, hs_pop); | 739 | twl4030_write(codec, TWL4030_REG_HS_POPN_SET, hs_pop); |
@@ -772,9 +771,9 @@ static void headset_ramp(struct snd_soc_codec *codec, int ramp) | |||
772 | } | 771 | } |
773 | 772 | ||
774 | /* Disable external mute */ | 773 | /* Disable external mute */ |
775 | if (setup && setup->hs_extmute) { | 774 | if (pdata && pdata->hs_extmute) { |
776 | if (setup->set_hs_extmute) { | 775 | if (pdata->set_hs_extmute) { |
777 | setup->set_hs_extmute(0); | 776 | pdata->set_hs_extmute(0); |
778 | } else { | 777 | } else { |
779 | hs_pop &= ~TWL4030_EXTMUTE; | 778 | hs_pop &= ~TWL4030_EXTMUTE; |
780 | twl4030_write(codec, TWL4030_REG_HS_POPN_SET, hs_pop); | 779 | twl4030_write(codec, TWL4030_REG_HS_POPN_SET, hs_pop); |
@@ -1707,8 +1706,7 @@ static int twl4030_startup(struct snd_pcm_substream *substream, | |||
1707 | struct snd_soc_dai *dai) | 1706 | struct snd_soc_dai *dai) |
1708 | { | 1707 | { |
1709 | struct snd_soc_pcm_runtime *rtd = substream->private_data; | 1708 | struct snd_soc_pcm_runtime *rtd = substream->private_data; |
1710 | struct snd_soc_device *socdev = rtd->socdev; | 1709 | struct snd_soc_codec *codec = rtd->codec; |
1711 | struct snd_soc_codec *codec = socdev->card->codec; | ||
1712 | struct twl4030_priv *twl4030 = snd_soc_codec_get_drvdata(codec); | 1710 | struct twl4030_priv *twl4030 = snd_soc_codec_get_drvdata(codec); |
1713 | 1711 | ||
1714 | if (twl4030->master_substream) { | 1712 | if (twl4030->master_substream) { |
@@ -1738,8 +1736,7 @@ static void twl4030_shutdown(struct snd_pcm_substream *substream, | |||
1738 | struct snd_soc_dai *dai) | 1736 | struct snd_soc_dai *dai) |
1739 | { | 1737 | { |
1740 | struct snd_soc_pcm_runtime *rtd = substream->private_data; | 1738 | struct snd_soc_pcm_runtime *rtd = substream->private_data; |
1741 | struct snd_soc_device *socdev = rtd->socdev; | 1739 | struct snd_soc_codec *codec = rtd->codec; |
1742 | struct snd_soc_codec *codec = socdev->card->codec; | ||
1743 | struct twl4030_priv *twl4030 = snd_soc_codec_get_drvdata(codec); | 1740 | struct twl4030_priv *twl4030 = snd_soc_codec_get_drvdata(codec); |
1744 | 1741 | ||
1745 | if (twl4030->master_substream == substream) | 1742 | if (twl4030->master_substream == substream) |
@@ -1764,8 +1761,7 @@ static int twl4030_hw_params(struct snd_pcm_substream *substream, | |||
1764 | struct snd_soc_dai *dai) | 1761 | struct snd_soc_dai *dai) |
1765 | { | 1762 | { |
1766 | struct snd_soc_pcm_runtime *rtd = substream->private_data; | 1763 | struct snd_soc_pcm_runtime *rtd = substream->private_data; |
1767 | struct snd_soc_device *socdev = rtd->socdev; | 1764 | struct snd_soc_codec *codec = rtd->codec; |
1768 | struct snd_soc_codec *codec = socdev->card->codec; | ||
1769 | struct twl4030_priv *twl4030 = snd_soc_codec_get_drvdata(codec); | 1765 | struct twl4030_priv *twl4030 = snd_soc_codec_get_drvdata(codec); |
1770 | u8 mode, old_mode, format, old_format; | 1766 | u8 mode, old_mode, format, old_format; |
1771 | 1767 | ||
@@ -1999,8 +1995,7 @@ static int twl4030_voice_startup(struct snd_pcm_substream *substream, | |||
1999 | struct snd_soc_dai *dai) | 1995 | struct snd_soc_dai *dai) |
2000 | { | 1996 | { |
2001 | struct snd_soc_pcm_runtime *rtd = substream->private_data; | 1997 | struct snd_soc_pcm_runtime *rtd = substream->private_data; |
2002 | struct snd_soc_device *socdev = rtd->socdev; | 1998 | struct snd_soc_codec *codec = rtd->codec; |
2003 | struct snd_soc_codec *codec = socdev->card->codec; | ||
2004 | struct twl4030_priv *twl4030 = snd_soc_codec_get_drvdata(codec); | 1999 | struct twl4030_priv *twl4030 = snd_soc_codec_get_drvdata(codec); |
2005 | u8 mode; | 2000 | u8 mode; |
2006 | 2001 | ||
@@ -2033,8 +2028,7 @@ static void twl4030_voice_shutdown(struct snd_pcm_substream *substream, | |||
2033 | struct snd_soc_dai *dai) | 2028 | struct snd_soc_dai *dai) |
2034 | { | 2029 | { |
2035 | struct snd_soc_pcm_runtime *rtd = substream->private_data; | 2030 | struct snd_soc_pcm_runtime *rtd = substream->private_data; |
2036 | struct snd_soc_device *socdev = rtd->socdev; | 2031 | struct snd_soc_codec *codec = rtd->codec; |
2037 | struct snd_soc_codec *codec = socdev->card->codec; | ||
2038 | 2032 | ||
2039 | /* Enable voice digital filters */ | 2033 | /* Enable voice digital filters */ |
2040 | twl4030_voice_enable(codec, substream->stream, 0); | 2034 | twl4030_voice_enable(codec, substream->stream, 0); |
@@ -2044,8 +2038,7 @@ static int twl4030_voice_hw_params(struct snd_pcm_substream *substream, | |||
2044 | struct snd_pcm_hw_params *params, struct snd_soc_dai *dai) | 2038 | struct snd_pcm_hw_params *params, struct snd_soc_dai *dai) |
2045 | { | 2039 | { |
2046 | struct snd_soc_pcm_runtime *rtd = substream->private_data; | 2040 | struct snd_soc_pcm_runtime *rtd = substream->private_data; |
2047 | struct snd_soc_device *socdev = rtd->socdev; | 2041 | struct snd_soc_codec *codec = rtd->codec; |
2048 | struct snd_soc_codec *codec = socdev->card->codec; | ||
2049 | struct twl4030_priv *twl4030 = snd_soc_codec_get_drvdata(codec); | 2042 | struct twl4030_priv *twl4030 = snd_soc_codec_get_drvdata(codec); |
2050 | u8 old_mode, mode; | 2043 | u8 old_mode, mode; |
2051 | 2044 | ||
@@ -2175,7 +2168,7 @@ static int twl4030_voice_set_tristate(struct snd_soc_dai *dai, int tristate) | |||
2175 | #define TWL4030_RATES (SNDRV_PCM_RATE_8000_48000) | 2168 | #define TWL4030_RATES (SNDRV_PCM_RATE_8000_48000) |
2176 | #define TWL4030_FORMATS (SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FORMAT_S24_LE) | 2169 | #define TWL4030_FORMATS (SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FORMAT_S24_LE) |
2177 | 2170 | ||
2178 | static struct snd_soc_dai_ops twl4030_dai_ops = { | 2171 | static struct snd_soc_dai_ops twl4030_dai_hifi_ops = { |
2179 | .startup = twl4030_startup, | 2172 | .startup = twl4030_startup, |
2180 | .shutdown = twl4030_shutdown, | 2173 | .shutdown = twl4030_shutdown, |
2181 | .hw_params = twl4030_hw_params, | 2174 | .hw_params = twl4030_hw_params, |
@@ -2193,9 +2186,9 @@ static struct snd_soc_dai_ops twl4030_dai_voice_ops = { | |||
2193 | .set_tristate = twl4030_voice_set_tristate, | 2186 | .set_tristate = twl4030_voice_set_tristate, |
2194 | }; | 2187 | }; |
2195 | 2188 | ||
2196 | struct snd_soc_dai twl4030_dai[] = { | 2189 | static struct snd_soc_dai_driver twl4030_dai[] = { |
2197 | { | 2190 | { |
2198 | .name = "twl4030", | 2191 | .name = "twl4030-hifi", |
2199 | .playback = { | 2192 | .playback = { |
2200 | .stream_name = "HiFi Playback", | 2193 | .stream_name = "HiFi Playback", |
2201 | .channels_min = 2, | 2194 | .channels_min = 2, |
@@ -2208,10 +2201,10 @@ struct snd_soc_dai twl4030_dai[] = { | |||
2208 | .channels_max = 4, | 2201 | .channels_max = 4, |
2209 | .rates = TWL4030_RATES, | 2202 | .rates = TWL4030_RATES, |
2210 | .formats = TWL4030_FORMATS,}, | 2203 | .formats = TWL4030_FORMATS,}, |
2211 | .ops = &twl4030_dai_ops, | 2204 | .ops = &twl4030_dai_hifi_ops, |
2212 | }, | 2205 | }, |
2213 | { | 2206 | { |
2214 | .name = "twl4030 Voice", | 2207 | .name = "twl4030-voice", |
2215 | .playback = { | 2208 | .playback = { |
2216 | .stream_name = "Voice Playback", | 2209 | .stream_name = "Voice Playback", |
2217 | .channels_min = 1, | 2210 | .channels_min = 1, |
@@ -2227,164 +2220,92 @@ struct snd_soc_dai twl4030_dai[] = { | |||
2227 | .ops = &twl4030_dai_voice_ops, | 2220 | .ops = &twl4030_dai_voice_ops, |
2228 | }, | 2221 | }, |
2229 | }; | 2222 | }; |
2230 | EXPORT_SYMBOL_GPL(twl4030_dai); | ||
2231 | 2223 | ||
2232 | static int twl4030_soc_suspend(struct platform_device *pdev, pm_message_t state) | 2224 | static int twl4030_soc_suspend(struct snd_soc_codec *codec, pm_message_t state) |
2233 | { | 2225 | { |
2234 | struct snd_soc_device *socdev = platform_get_drvdata(pdev); | ||
2235 | struct snd_soc_codec *codec = socdev->card->codec; | ||
2236 | |||
2237 | twl4030_set_bias_level(codec, SND_SOC_BIAS_OFF); | 2226 | twl4030_set_bias_level(codec, SND_SOC_BIAS_OFF); |
2238 | |||
2239 | return 0; | 2227 | return 0; |
2240 | } | 2228 | } |
2241 | 2229 | ||
2242 | static int twl4030_soc_resume(struct platform_device *pdev) | 2230 | static int twl4030_soc_resume(struct snd_soc_codec *codec) |
2243 | { | 2231 | { |
2244 | struct snd_soc_device *socdev = platform_get_drvdata(pdev); | ||
2245 | struct snd_soc_codec *codec = socdev->card->codec; | ||
2246 | |||
2247 | twl4030_set_bias_level(codec, SND_SOC_BIAS_STANDBY); | 2232 | twl4030_set_bias_level(codec, SND_SOC_BIAS_STANDBY); |
2248 | return 0; | 2233 | return 0; |
2249 | } | 2234 | } |
2250 | 2235 | ||
2251 | static struct snd_soc_codec *twl4030_codec; | 2236 | static int twl4030_soc_probe(struct snd_soc_codec *codec) |
2252 | |||
2253 | static int twl4030_soc_probe(struct platform_device *pdev) | ||
2254 | { | 2237 | { |
2255 | struct snd_soc_device *socdev = platform_get_drvdata(pdev); | 2238 | struct twl4030_priv *twl4030; |
2256 | struct snd_soc_codec *codec; | ||
2257 | int ret; | ||
2258 | |||
2259 | BUG_ON(!twl4030_codec); | ||
2260 | |||
2261 | codec = twl4030_codec; | ||
2262 | socdev->card->codec = codec; | ||
2263 | |||
2264 | twl4030_init_chip(pdev); | ||
2265 | 2239 | ||
2266 | /* register pcms */ | 2240 | twl4030 = kzalloc(sizeof(struct twl4030_priv), GFP_KERNEL); |
2267 | ret = snd_soc_new_pcms(socdev, SNDRV_DEFAULT_IDX1, SNDRV_DEFAULT_STR1); | 2241 | if (twl4030 == NULL) { |
2268 | if (ret < 0) { | 2242 | printk("Can not allocate memroy\n"); |
2269 | dev_err(&pdev->dev, "failed to create pcms\n"); | 2243 | return -ENOMEM; |
2270 | return ret; | ||
2271 | } | 2244 | } |
2245 | snd_soc_codec_set_drvdata(codec, twl4030); | ||
2246 | /* Set the defaults, and power up the codec */ | ||
2247 | twl4030->sysclk = twl4030_codec_get_mclk() / 1000; | ||
2248 | codec->bias_level = SND_SOC_BIAS_OFF; | ||
2249 | codec->idle_bias_off = 1; | ||
2250 | |||
2251 | twl4030_init_chip(codec); | ||
2272 | 2252 | ||
2273 | snd_soc_add_controls(codec, twl4030_snd_controls, | 2253 | snd_soc_add_controls(codec, twl4030_snd_controls, |
2274 | ARRAY_SIZE(twl4030_snd_controls)); | 2254 | ARRAY_SIZE(twl4030_snd_controls)); |
2275 | twl4030_add_widgets(codec); | 2255 | twl4030_add_widgets(codec); |
2276 | |||
2277 | return 0; | 2256 | return 0; |
2278 | } | 2257 | } |
2279 | 2258 | ||
2280 | static int twl4030_soc_remove(struct platform_device *pdev) | 2259 | static int twl4030_soc_remove(struct snd_soc_codec *codec) |
2281 | { | 2260 | { |
2282 | struct snd_soc_device *socdev = platform_get_drvdata(pdev); | ||
2283 | struct snd_soc_codec *codec = socdev->card->codec; | ||
2284 | |||
2285 | /* Reset registers to their chip default before leaving */ | 2261 | /* Reset registers to their chip default before leaving */ |
2286 | twl4030_reset_registers(codec); | 2262 | twl4030_reset_registers(codec); |
2287 | twl4030_set_bias_level(codec, SND_SOC_BIAS_OFF); | 2263 | twl4030_set_bias_level(codec, SND_SOC_BIAS_OFF); |
2288 | snd_soc_free_pcms(socdev); | ||
2289 | snd_soc_dapm_free(socdev); | ||
2290 | |||
2291 | return 0; | 2264 | return 0; |
2292 | } | 2265 | } |
2293 | 2266 | ||
2267 | static struct snd_soc_codec_driver soc_codec_dev_twl4030 = { | ||
2268 | .probe = twl4030_soc_probe, | ||
2269 | .remove = twl4030_soc_remove, | ||
2270 | .suspend = twl4030_soc_suspend, | ||
2271 | .resume = twl4030_soc_resume, | ||
2272 | .read = twl4030_read_reg_cache, | ||
2273 | .write = twl4030_write, | ||
2274 | .set_bias_level = twl4030_set_bias_level, | ||
2275 | .reg_cache_size = sizeof(twl4030_reg), | ||
2276 | .reg_word_size = sizeof(u8), | ||
2277 | .reg_cache_default = twl4030_reg, | ||
2278 | }; | ||
2279 | |||
2294 | static int __devinit twl4030_codec_probe(struct platform_device *pdev) | 2280 | static int __devinit twl4030_codec_probe(struct platform_device *pdev) |
2295 | { | 2281 | { |
2296 | struct twl4030_codec_audio_data *pdata = pdev->dev.platform_data; | 2282 | struct twl4030_codec_audio_data *pdata = pdev->dev.platform_data; |
2297 | struct snd_soc_codec *codec; | ||
2298 | struct twl4030_priv *twl4030; | ||
2299 | int ret; | ||
2300 | 2283 | ||
2301 | if (!pdata) { | 2284 | if (!pdata) { |
2302 | dev_err(&pdev->dev, "platform_data is missing\n"); | 2285 | dev_err(&pdev->dev, "platform_data is missing\n"); |
2303 | return -EINVAL; | 2286 | return -EINVAL; |
2304 | } | 2287 | } |
2305 | 2288 | ||
2306 | twl4030 = kzalloc(sizeof(struct twl4030_priv), GFP_KERNEL); | 2289 | return snd_soc_register_codec(&pdev->dev, &soc_codec_dev_twl4030, |
2307 | if (twl4030 == NULL) { | 2290 | twl4030_dai, ARRAY_SIZE(twl4030_dai)); |
2308 | dev_err(&pdev->dev, "Can not allocate memroy\n"); | ||
2309 | return -ENOMEM; | ||
2310 | } | ||
2311 | |||
2312 | codec = &twl4030->codec; | ||
2313 | snd_soc_codec_set_drvdata(codec, twl4030); | ||
2314 | codec->dev = &pdev->dev; | ||
2315 | twl4030_dai[0].dev = &pdev->dev; | ||
2316 | twl4030_dai[1].dev = &pdev->dev; | ||
2317 | |||
2318 | mutex_init(&codec->mutex); | ||
2319 | INIT_LIST_HEAD(&codec->dapm_widgets); | ||
2320 | INIT_LIST_HEAD(&codec->dapm_paths); | ||
2321 | |||
2322 | codec->name = "twl4030"; | ||
2323 | codec->owner = THIS_MODULE; | ||
2324 | codec->read = twl4030_read_reg_cache; | ||
2325 | codec->write = twl4030_write; | ||
2326 | codec->set_bias_level = twl4030_set_bias_level; | ||
2327 | codec->idle_bias_off = 1; | ||
2328 | codec->dai = twl4030_dai; | ||
2329 | codec->num_dai = ARRAY_SIZE(twl4030_dai); | ||
2330 | codec->reg_cache_size = sizeof(twl4030_reg); | ||
2331 | codec->reg_cache = kmemdup(twl4030_reg, sizeof(twl4030_reg), | ||
2332 | GFP_KERNEL); | ||
2333 | if (codec->reg_cache == NULL) { | ||
2334 | ret = -ENOMEM; | ||
2335 | goto error_cache; | ||
2336 | } | ||
2337 | |||
2338 | platform_set_drvdata(pdev, twl4030); | ||
2339 | twl4030_codec = codec; | ||
2340 | |||
2341 | /* Set the defaults, and power up the codec */ | ||
2342 | twl4030->sysclk = twl4030_codec_get_mclk() / 1000; | ||
2343 | codec->bias_level = SND_SOC_BIAS_OFF; | ||
2344 | |||
2345 | ret = snd_soc_register_codec(codec); | ||
2346 | if (ret != 0) { | ||
2347 | dev_err(codec->dev, "Failed to register codec: %d\n", ret); | ||
2348 | goto error_codec; | ||
2349 | } | ||
2350 | |||
2351 | ret = snd_soc_register_dais(&twl4030_dai[0], ARRAY_SIZE(twl4030_dai)); | ||
2352 | if (ret != 0) { | ||
2353 | dev_err(codec->dev, "Failed to register DAIs: %d\n", ret); | ||
2354 | snd_soc_unregister_codec(codec); | ||
2355 | goto error_codec; | ||
2356 | } | ||
2357 | |||
2358 | return 0; | ||
2359 | |||
2360 | error_codec: | ||
2361 | twl4030_codec_enable(codec, 0); | ||
2362 | kfree(codec->reg_cache); | ||
2363 | error_cache: | ||
2364 | kfree(twl4030); | ||
2365 | return ret; | ||
2366 | } | 2291 | } |
2367 | 2292 | ||
2368 | static int __devexit twl4030_codec_remove(struct platform_device *pdev) | 2293 | static int __devexit twl4030_codec_remove(struct platform_device *pdev) |
2369 | { | 2294 | { |
2370 | struct twl4030_priv *twl4030 = platform_get_drvdata(pdev); | 2295 | struct twl4030_priv *twl4030 = dev_get_drvdata(&pdev->dev); |
2371 | 2296 | ||
2372 | snd_soc_unregister_dais(&twl4030_dai[0], ARRAY_SIZE(twl4030_dai)); | 2297 | snd_soc_unregister_codec(&pdev->dev); |
2373 | snd_soc_unregister_codec(&twl4030->codec); | ||
2374 | kfree(twl4030->codec.reg_cache); | ||
2375 | kfree(twl4030); | 2298 | kfree(twl4030); |
2376 | |||
2377 | twl4030_codec = NULL; | ||
2378 | return 0; | 2299 | return 0; |
2379 | } | 2300 | } |
2380 | 2301 | ||
2381 | MODULE_ALIAS("platform:twl4030_codec_audio"); | 2302 | MODULE_ALIAS("platform:twl4030-codec"); |
2382 | 2303 | ||
2383 | static struct platform_driver twl4030_codec_driver = { | 2304 | static struct platform_driver twl4030_codec_driver = { |
2384 | .probe = twl4030_codec_probe, | 2305 | .probe = twl4030_codec_probe, |
2385 | .remove = __devexit_p(twl4030_codec_remove), | 2306 | .remove = __devexit_p(twl4030_codec_remove), |
2386 | .driver = { | 2307 | .driver = { |
2387 | .name = "twl4030_codec_audio", | 2308 | .name = "twl4030-codec", |
2388 | .owner = THIS_MODULE, | 2309 | .owner = THIS_MODULE, |
2389 | }, | 2310 | }, |
2390 | }; | 2311 | }; |
@@ -2401,14 +2322,6 @@ static void __exit twl4030_exit(void) | |||
2401 | } | 2322 | } |
2402 | module_exit(twl4030_exit); | 2323 | module_exit(twl4030_exit); |
2403 | 2324 | ||
2404 | struct snd_soc_codec_device soc_codec_dev_twl4030 = { | ||
2405 | .probe = twl4030_soc_probe, | ||
2406 | .remove = twl4030_soc_remove, | ||
2407 | .suspend = twl4030_soc_suspend, | ||
2408 | .resume = twl4030_soc_resume, | ||
2409 | }; | ||
2410 | EXPORT_SYMBOL_GPL(soc_codec_dev_twl4030); | ||
2411 | |||
2412 | MODULE_DESCRIPTION("ASoC TWL4030 codec driver"); | 2325 | MODULE_DESCRIPTION("ASoC TWL4030 codec driver"); |
2413 | MODULE_AUTHOR("Steve Sakoman"); | 2326 | MODULE_AUTHOR("Steve Sakoman"); |
2414 | MODULE_LICENSE("GPL"); | 2327 | MODULE_LICENSE("GPL"); |
diff --git a/sound/soc/codecs/twl4030.h b/sound/soc/codecs/twl4030.h deleted file mode 100644 index 6c57430f6e24..000000000000 --- a/sound/soc/codecs/twl4030.h +++ /dev/null | |||
@@ -1,55 +0,0 @@ | |||
1 | /* | ||
2 | * ALSA SoC TWL4030 codec driver | ||
3 | * | ||
4 | * Author: Steve Sakoman <steve@sakoman.com> | ||
5 | * | ||
6 | * This program is free software; you can redistribute it and/or | ||
7 | * modify it under the terms of the GNU General Public License | ||
8 | * version 2 as published by the Free Software Foundation. | ||
9 | * | ||
10 | * This program is distributed in the hope that it will be useful, but | ||
11 | * WITHOUT ANY WARRANTY; without even the implied warranty of | ||
12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | ||
13 | * General Public License for more details. | ||
14 | * | ||
15 | * You should have received a copy of the GNU General Public License | ||
16 | * along with this program; if not, write to the Free Software | ||
17 | * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA | ||
18 | * 02110-1301 USA | ||
19 | * | ||
20 | */ | ||
21 | |||
22 | #ifndef __TWL4030_AUDIO_H__ | ||
23 | #define __TWL4030_AUDIO_H__ | ||
24 | |||
25 | /* Register descriptions are here */ | ||
26 | #include <linux/mfd/twl4030-codec.h> | ||
27 | |||
28 | /* Shadow register used by the audio driver */ | ||
29 | #define TWL4030_REG_SW_SHADOW 0x4A | ||
30 | #define TWL4030_CACHEREGNUM (TWL4030_REG_SW_SHADOW + 1) | ||
31 | |||
32 | /* TWL4030_REG_SW_SHADOW (0x4A) Fields */ | ||
33 | #define TWL4030_HFL_EN 0x01 | ||
34 | #define TWL4030_HFR_EN 0x02 | ||
35 | |||
36 | #define TWL4030_DAI_HIFI 0 | ||
37 | #define TWL4030_DAI_VOICE 1 | ||
38 | |||
39 | extern struct snd_soc_dai twl4030_dai[2]; | ||
40 | extern struct snd_soc_codec_device soc_codec_dev_twl4030; | ||
41 | |||
42 | struct twl4030_setup_data { | ||
43 | unsigned int ramp_delay_value; | ||
44 | unsigned int digimic_delay; /* in ms */ | ||
45 | unsigned int sysclk; | ||
46 | unsigned int offset_cncl_path; | ||
47 | unsigned int check_defaults:1; | ||
48 | unsigned int reset_registers:1; | ||
49 | unsigned int hs_extmute:1; | ||
50 | void (*set_hs_extmute)(int mute); | ||
51 | }; | ||
52 | |||
53 | #endif /* End of __TWL4030_AUDIO_H__ */ | ||
54 | |||
55 | |||
diff --git a/sound/soc/codecs/twl6040.c b/sound/soc/codecs/twl6040.c index 64a807f1a8a1..10f6e5214511 100644 --- a/sound/soc/codecs/twl6040.c +++ b/sound/soc/codecs/twl6040.c | |||
@@ -45,7 +45,6 @@ | |||
45 | 45 | ||
46 | /* codec private data */ | 46 | /* codec private data */ |
47 | struct twl6040_data { | 47 | struct twl6040_data { |
48 | struct snd_soc_codec codec; | ||
49 | int audpwron; | 48 | int audpwron; |
50 | int naudint; | 49 | int naudint; |
51 | int codec_powered; | 50 | int codec_powered; |
@@ -770,8 +769,7 @@ static int twl6040_startup(struct snd_pcm_substream *substream, | |||
770 | struct snd_soc_dai *dai) | 769 | struct snd_soc_dai *dai) |
771 | { | 770 | { |
772 | struct snd_soc_pcm_runtime *rtd = substream->private_data; | 771 | struct snd_soc_pcm_runtime *rtd = substream->private_data; |
773 | struct snd_soc_device *socdev = rtd->socdev; | 772 | struct snd_soc_codec *codec = rtd->codec; |
774 | struct snd_soc_codec *codec = socdev->card->codec; | ||
775 | struct twl6040_data *priv = snd_soc_codec_get_drvdata(codec); | 773 | struct twl6040_data *priv = snd_soc_codec_get_drvdata(codec); |
776 | 774 | ||
777 | if (!priv->sysclk) { | 775 | if (!priv->sysclk) { |
@@ -803,8 +801,7 @@ static int twl6040_hw_params(struct snd_pcm_substream *substream, | |||
803 | struct snd_soc_dai *dai) | 801 | struct snd_soc_dai *dai) |
804 | { | 802 | { |
805 | struct snd_soc_pcm_runtime *rtd = substream->private_data; | 803 | struct snd_soc_pcm_runtime *rtd = substream->private_data; |
806 | struct snd_soc_device *socdev = rtd->socdev; | 804 | struct snd_soc_codec *codec = rtd->codec; |
807 | struct snd_soc_codec *codec = socdev->card->codec; | ||
808 | struct twl6040_data *priv = snd_soc_codec_get_drvdata(codec); | 805 | struct twl6040_data *priv = snd_soc_codec_get_drvdata(codec); |
809 | u8 lppllctl; | 806 | u8 lppllctl; |
810 | int rate; | 807 | int rate; |
@@ -839,8 +836,7 @@ static int twl6040_trigger(struct snd_pcm_substream *substream, | |||
839 | int cmd, struct snd_soc_dai *dai) | 836 | int cmd, struct snd_soc_dai *dai) |
840 | { | 837 | { |
841 | struct snd_soc_pcm_runtime *rtd = substream->private_data; | 838 | struct snd_soc_pcm_runtime *rtd = substream->private_data; |
842 | struct snd_soc_device *socdev = rtd->socdev; | 839 | struct snd_soc_codec *codec = rtd->codec; |
843 | struct snd_soc_codec *codec = socdev->card->codec; | ||
844 | struct twl6040_data *priv = snd_soc_codec_get_drvdata(codec); | 840 | struct twl6040_data *priv = snd_soc_codec_get_drvdata(codec); |
845 | 841 | ||
846 | switch (cmd) { | 842 | switch (cmd) { |
@@ -978,8 +974,8 @@ static struct snd_soc_dai_ops twl6040_dai_ops = { | |||
978 | .set_sysclk = twl6040_set_dai_sysclk, | 974 | .set_sysclk = twl6040_set_dai_sysclk, |
979 | }; | 975 | }; |
980 | 976 | ||
981 | struct snd_soc_dai twl6040_dai = { | 977 | static struct snd_soc_dai_driver twl6040_dai = { |
982 | .name = "twl6040", | 978 | .name = "twl6040-hifi", |
983 | .playback = { | 979 | .playback = { |
984 | .stream_name = "Playback", | 980 | .stream_name = "Playback", |
985 | .channels_min = 1, | 981 | .channels_min = 1, |
@@ -996,24 +992,17 @@ struct snd_soc_dai twl6040_dai = { | |||
996 | }, | 992 | }, |
997 | .ops = &twl6040_dai_ops, | 993 | .ops = &twl6040_dai_ops, |
998 | }; | 994 | }; |
999 | EXPORT_SYMBOL_GPL(twl6040_dai); | ||
1000 | 995 | ||
1001 | #ifdef CONFIG_PM | 996 | #ifdef CONFIG_PM |
1002 | static int twl6040_suspend(struct platform_device *pdev, pm_message_t state) | 997 | static int twl6040_suspend(struct snd_soc_codec *codec, pm_message_t state) |
1003 | { | 998 | { |
1004 | struct snd_soc_device *socdev = platform_get_drvdata(pdev); | ||
1005 | struct snd_soc_codec *codec = socdev->card->codec; | ||
1006 | |||
1007 | twl6040_set_bias_level(codec, SND_SOC_BIAS_OFF); | 999 | twl6040_set_bias_level(codec, SND_SOC_BIAS_OFF); |
1008 | 1000 | ||
1009 | return 0; | 1001 | return 0; |
1010 | } | 1002 | } |
1011 | 1003 | ||
1012 | static int twl6040_resume(struct platform_device *pdev) | 1004 | static int twl6040_resume(struct snd_soc_codec *codec) |
1013 | { | 1005 | { |
1014 | struct snd_soc_device *socdev = platform_get_drvdata(pdev); | ||
1015 | struct snd_soc_codec *codec = socdev->card->codec; | ||
1016 | |||
1017 | twl6040_set_bias_level(codec, SND_SOC_BIAS_STANDBY); | 1006 | twl6040_set_bias_level(codec, SND_SOC_BIAS_STANDBY); |
1018 | 1007 | ||
1019 | return 0; | 1008 | return 0; |
@@ -1023,68 +1012,9 @@ static int twl6040_resume(struct platform_device *pdev) | |||
1023 | #define twl6040_resume NULL | 1012 | #define twl6040_resume NULL |
1024 | #endif | 1013 | #endif |
1025 | 1014 | ||
1026 | static struct snd_soc_codec *twl6040_codec; | 1015 | static int twl6040_probe(struct snd_soc_codec *codec) |
1027 | |||
1028 | static int twl6040_probe(struct platform_device *pdev) | ||
1029 | { | ||
1030 | struct snd_soc_device *socdev = platform_get_drvdata(pdev); | ||
1031 | struct snd_soc_codec *codec; | ||
1032 | int ret = 0; | ||
1033 | |||
1034 | BUG_ON(!twl6040_codec); | ||
1035 | |||
1036 | codec = twl6040_codec; | ||
1037 | socdev->card->codec = codec; | ||
1038 | |||
1039 | /* register pcms */ | ||
1040 | ret = snd_soc_new_pcms(socdev, SNDRV_DEFAULT_IDX1, SNDRV_DEFAULT_STR1); | ||
1041 | if (ret < 0) { | ||
1042 | dev_err(&pdev->dev, "failed to create pcms\n"); | ||
1043 | return ret; | ||
1044 | } | ||
1045 | |||
1046 | snd_soc_add_controls(codec, twl6040_snd_controls, | ||
1047 | ARRAY_SIZE(twl6040_snd_controls)); | ||
1048 | twl6040_add_widgets(codec); | ||
1049 | |||
1050 | if (ret < 0) { | ||
1051 | dev_err(&pdev->dev, "failed to register card\n"); | ||
1052 | goto card_err; | ||
1053 | } | ||
1054 | |||
1055 | return ret; | ||
1056 | |||
1057 | card_err: | ||
1058 | snd_soc_free_pcms(socdev); | ||
1059 | snd_soc_dapm_free(socdev); | ||
1060 | return ret; | ||
1061 | } | ||
1062 | |||
1063 | static int twl6040_remove(struct platform_device *pdev) | ||
1064 | { | ||
1065 | struct snd_soc_device *socdev = platform_get_drvdata(pdev); | ||
1066 | struct snd_soc_codec *codec = socdev->card->codec; | ||
1067 | |||
1068 | twl6040_set_bias_level(codec, SND_SOC_BIAS_OFF); | ||
1069 | snd_soc_free_pcms(socdev); | ||
1070 | snd_soc_dapm_free(socdev); | ||
1071 | kfree(codec); | ||
1072 | |||
1073 | return 0; | ||
1074 | } | ||
1075 | |||
1076 | struct snd_soc_codec_device soc_codec_dev_twl6040 = { | ||
1077 | .probe = twl6040_probe, | ||
1078 | .remove = twl6040_remove, | ||
1079 | .suspend = twl6040_suspend, | ||
1080 | .resume = twl6040_resume, | ||
1081 | }; | ||
1082 | EXPORT_SYMBOL_GPL(soc_codec_dev_twl6040); | ||
1083 | |||
1084 | static int __devinit twl6040_codec_probe(struct platform_device *pdev) | ||
1085 | { | 1016 | { |
1086 | struct twl4030_codec_data *twl_codec = pdev->dev.platform_data; | 1017 | struct twl4030_codec_data *twl_codec = codec->dev->platform_data; |
1087 | struct snd_soc_codec *codec; | ||
1088 | struct twl6040_data *priv; | 1018 | struct twl6040_data *priv; |
1089 | int audpwron, naudint; | 1019 | int audpwron, naudint; |
1090 | int ret = 0; | 1020 | int ret = 0; |
@@ -1092,6 +1022,7 @@ static int __devinit twl6040_codec_probe(struct platform_device *pdev) | |||
1092 | priv = kzalloc(sizeof(struct twl6040_data), GFP_KERNEL); | 1022 | priv = kzalloc(sizeof(struct twl6040_data), GFP_KERNEL); |
1093 | if (priv == NULL) | 1023 | if (priv == NULL) |
1094 | return -ENOMEM; | 1024 | return -ENOMEM; |
1025 | snd_soc_codec_set_drvdata(codec, priv); | ||
1095 | 1026 | ||
1096 | if (twl_codec) { | 1027 | if (twl_codec) { |
1097 | audpwron = twl_codec->audpwron_gpio; | 1028 | audpwron = twl_codec->audpwron_gpio; |
@@ -1104,29 +1035,6 @@ static int __devinit twl6040_codec_probe(struct platform_device *pdev) | |||
1104 | priv->audpwron = audpwron; | 1035 | priv->audpwron = audpwron; |
1105 | priv->naudint = naudint; | 1036 | priv->naudint = naudint; |
1106 | 1037 | ||
1107 | codec = &priv->codec; | ||
1108 | codec->dev = &pdev->dev; | ||
1109 | twl6040_dai.dev = &pdev->dev; | ||
1110 | |||
1111 | codec->name = "twl6040"; | ||
1112 | codec->owner = THIS_MODULE; | ||
1113 | codec->read = twl6040_read_reg_cache; | ||
1114 | codec->write = twl6040_write; | ||
1115 | codec->set_bias_level = twl6040_set_bias_level; | ||
1116 | snd_soc_codec_set_drvdata(codec, priv); | ||
1117 | codec->dai = &twl6040_dai; | ||
1118 | codec->num_dai = 1; | ||
1119 | codec->reg_cache_size = ARRAY_SIZE(twl6040_reg); | ||
1120 | codec->reg_cache = kmemdup(twl6040_reg, sizeof(twl6040_reg), | ||
1121 | GFP_KERNEL); | ||
1122 | if (codec->reg_cache == NULL) { | ||
1123 | ret = -ENOMEM; | ||
1124 | goto cache_err; | ||
1125 | } | ||
1126 | |||
1127 | mutex_init(&codec->mutex); | ||
1128 | INIT_LIST_HEAD(&codec->dapm_widgets); | ||
1129 | INIT_LIST_HEAD(&codec->dapm_paths); | ||
1130 | init_completion(&priv->ready); | 1038 | init_completion(&priv->ready); |
1131 | 1039 | ||
1132 | if (gpio_is_valid(audpwron)) { | 1040 | if (gpio_is_valid(audpwron)) { |
@@ -1169,23 +1077,12 @@ static int __devinit twl6040_codec_probe(struct platform_device *pdev) | |||
1169 | if (ret) | 1077 | if (ret) |
1170 | goto irq_err; | 1078 | goto irq_err; |
1171 | 1079 | ||
1172 | ret = snd_soc_register_codec(codec); | 1080 | snd_soc_add_controls(codec, twl6040_snd_controls, |
1173 | if (ret) | 1081 | ARRAY_SIZE(twl6040_snd_controls)); |
1174 | goto reg_err; | 1082 | twl6040_add_widgets(codec); |
1175 | |||
1176 | twl6040_codec = codec; | ||
1177 | |||
1178 | ret = snd_soc_register_dai(&twl6040_dai); | ||
1179 | if (ret) | ||
1180 | goto dai_err; | ||
1181 | 1083 | ||
1182 | return 0; | 1084 | return 0; |
1183 | 1085 | ||
1184 | dai_err: | ||
1185 | snd_soc_unregister_codec(codec); | ||
1186 | twl6040_codec = NULL; | ||
1187 | reg_err: | ||
1188 | twl6040_set_bias_level(codec, SND_SOC_BIAS_OFF); | ||
1189 | irq_err: | 1086 | irq_err: |
1190 | if (naudint) | 1087 | if (naudint) |
1191 | free_irq(naudint, codec); | 1088 | free_irq(naudint, codec); |
@@ -1193,36 +1090,57 @@ gpio2_err: | |||
1193 | if (gpio_is_valid(audpwron)) | 1090 | if (gpio_is_valid(audpwron)) |
1194 | gpio_free(audpwron); | 1091 | gpio_free(audpwron); |
1195 | gpio1_err: | 1092 | gpio1_err: |
1196 | kfree(codec->reg_cache); | ||
1197 | cache_err: | ||
1198 | kfree(priv); | 1093 | kfree(priv); |
1199 | return ret; | 1094 | return ret; |
1200 | } | 1095 | } |
1201 | 1096 | ||
1202 | static int __devexit twl6040_codec_remove(struct platform_device *pdev) | 1097 | static int twl6040_remove(struct snd_soc_codec *codec) |
1203 | { | 1098 | { |
1204 | struct twl6040_data *priv = snd_soc_codec_get_drvdata(twl6040_codec); | 1099 | struct twl6040_data *priv = snd_soc_codec_get_drvdata(codec); |
1205 | int audpwron = priv->audpwron; | 1100 | int audpwron = priv->audpwron; |
1206 | int naudint = priv->naudint; | 1101 | int naudint = priv->naudint; |
1207 | 1102 | ||
1103 | twl6040_set_bias_level(codec, SND_SOC_BIAS_OFF); | ||
1104 | |||
1208 | if (gpio_is_valid(audpwron)) | 1105 | if (gpio_is_valid(audpwron)) |
1209 | gpio_free(audpwron); | 1106 | gpio_free(audpwron); |
1210 | 1107 | ||
1211 | if (naudint) | 1108 | if (naudint) |
1212 | free_irq(naudint, twl6040_codec); | 1109 | free_irq(naudint, codec); |
1213 | 1110 | ||
1214 | snd_soc_unregister_dai(&twl6040_dai); | 1111 | kfree(priv); |
1215 | snd_soc_unregister_codec(twl6040_codec); | ||
1216 | 1112 | ||
1217 | kfree(twl6040_codec); | 1113 | return 0; |
1218 | twl6040_codec = NULL; | 1114 | } |
1219 | 1115 | ||
1116 | static struct snd_soc_codec_driver soc_codec_dev_twl6040 = { | ||
1117 | .probe = twl6040_probe, | ||
1118 | .remove = twl6040_remove, | ||
1119 | .suspend = twl6040_suspend, | ||
1120 | .resume = twl6040_resume, | ||
1121 | .read = twl6040_read_reg_cache, | ||
1122 | .write = twl6040_write, | ||
1123 | .set_bias_level = twl6040_set_bias_level, | ||
1124 | .reg_cache_size = ARRAY_SIZE(twl6040_reg), | ||
1125 | .reg_word_size = sizeof(u8), | ||
1126 | .reg_cache_default = twl6040_reg, | ||
1127 | }; | ||
1128 | |||
1129 | static int __devinit twl6040_codec_probe(struct platform_device *pdev) | ||
1130 | { | ||
1131 | return snd_soc_register_codec(&pdev->dev, | ||
1132 | &soc_codec_dev_twl6040, &twl6040_dai, 1); | ||
1133 | } | ||
1134 | |||
1135 | static int __devexit twl6040_codec_remove(struct platform_device *pdev) | ||
1136 | { | ||
1137 | snd_soc_unregister_codec(&pdev->dev); | ||
1220 | return 0; | 1138 | return 0; |
1221 | } | 1139 | } |
1222 | 1140 | ||
1223 | static struct platform_driver twl6040_codec_driver = { | 1141 | static struct platform_driver twl6040_codec_driver = { |
1224 | .driver = { | 1142 | .driver = { |
1225 | .name = "twl6040_codec", | 1143 | .name = "twl6040-codec", |
1226 | .owner = THIS_MODULE, | 1144 | .owner = THIS_MODULE, |
1227 | }, | 1145 | }, |
1228 | .probe = twl6040_codec_probe, | 1146 | .probe = twl6040_codec_probe, |
diff --git a/sound/soc/codecs/twl6040.h b/sound/soc/codecs/twl6040.h index c472070a1da2..f7c77fa58a3c 100644 --- a/sound/soc/codecs/twl6040.h +++ b/sound/soc/codecs/twl6040.h | |||
@@ -135,7 +135,4 @@ | |||
135 | #define TWL6040_HPPLL_ID 1 | 135 | #define TWL6040_HPPLL_ID 1 |
136 | #define TWL6040_LPPLL_ID 2 | 136 | #define TWL6040_LPPLL_ID 2 |
137 | 137 | ||
138 | extern struct snd_soc_dai twl6040_dai; | ||
139 | extern struct snd_soc_codec_device soc_codec_dev_twl6040; | ||
140 | |||
141 | #endif /* End of __TWL6040_H__ */ | 138 | #endif /* End of __TWL6040_H__ */ |
diff --git a/sound/soc/codecs/uda134x.c b/sound/soc/codecs/uda134x.c index f3b4c1d6a82d..7540a509a6f5 100644 --- a/sound/soc/codecs/uda134x.c +++ b/sound/soc/codecs/uda134x.c | |||
@@ -161,8 +161,7 @@ static int uda134x_startup(struct snd_pcm_substream *substream, | |||
161 | struct snd_soc_dai *dai) | 161 | struct snd_soc_dai *dai) |
162 | { | 162 | { |
163 | struct snd_soc_pcm_runtime *rtd = substream->private_data; | 163 | struct snd_soc_pcm_runtime *rtd = substream->private_data; |
164 | struct snd_soc_device *socdev = rtd->socdev; | 164 | struct snd_soc_codec *codec =rtd->codec; |
165 | struct snd_soc_codec *codec = socdev->card->codec; | ||
166 | struct uda134x_priv *uda134x = snd_soc_codec_get_drvdata(codec); | 165 | struct uda134x_priv *uda134x = snd_soc_codec_get_drvdata(codec); |
167 | struct snd_pcm_runtime *master_runtime; | 166 | struct snd_pcm_runtime *master_runtime; |
168 | 167 | ||
@@ -194,8 +193,7 @@ static void uda134x_shutdown(struct snd_pcm_substream *substream, | |||
194 | struct snd_soc_dai *dai) | 193 | struct snd_soc_dai *dai) |
195 | { | 194 | { |
196 | struct snd_soc_pcm_runtime *rtd = substream->private_data; | 195 | struct snd_soc_pcm_runtime *rtd = substream->private_data; |
197 | struct snd_soc_device *socdev = rtd->socdev; | 196 | struct snd_soc_codec *codec = rtd->codec; |
198 | struct snd_soc_codec *codec = socdev->card->codec; | ||
199 | struct uda134x_priv *uda134x = snd_soc_codec_get_drvdata(codec); | 197 | struct uda134x_priv *uda134x = snd_soc_codec_get_drvdata(codec); |
200 | 198 | ||
201 | if (uda134x->master_substream == substream) | 199 | if (uda134x->master_substream == substream) |
@@ -209,8 +207,7 @@ static int uda134x_hw_params(struct snd_pcm_substream *substream, | |||
209 | struct snd_soc_dai *dai) | 207 | struct snd_soc_dai *dai) |
210 | { | 208 | { |
211 | struct snd_soc_pcm_runtime *rtd = substream->private_data; | 209 | struct snd_soc_pcm_runtime *rtd = substream->private_data; |
212 | struct snd_soc_device *socdev = rtd->socdev; | 210 | struct snd_soc_codec *codec = rtd->codec; |
213 | struct snd_soc_codec *codec = socdev->card->codec; | ||
214 | struct uda134x_priv *uda134x = snd_soc_codec_get_drvdata(codec); | 211 | struct uda134x_priv *uda134x = snd_soc_codec_get_drvdata(codec); |
215 | u8 hw_params; | 212 | u8 hw_params; |
216 | 213 | ||
@@ -364,7 +361,7 @@ static int uda134x_set_bias_level(struct snd_soc_codec *codec, | |||
364 | pd->power(1); | 361 | pd->power(1); |
365 | /* Sync reg_cache with the hardware */ | 362 | /* Sync reg_cache with the hardware */ |
366 | for (i = 0; i < ARRAY_SIZE(uda134x_reg); i++) | 363 | for (i = 0; i < ARRAY_SIZE(uda134x_reg); i++) |
367 | codec->write(codec, i, *cache++); | 364 | codec->driver->write(codec, i, *cache++); |
368 | } | 365 | } |
369 | break; | 366 | break; |
370 | case SND_SOC_BIAS_STANDBY: | 367 | case SND_SOC_BIAS_STANDBY: |
@@ -465,8 +462,8 @@ static struct snd_soc_dai_ops uda134x_dai_ops = { | |||
465 | .set_fmt = uda134x_set_dai_fmt, | 462 | .set_fmt = uda134x_set_dai_fmt, |
466 | }; | 463 | }; |
467 | 464 | ||
468 | struct snd_soc_dai uda134x_dai = { | 465 | static struct snd_soc_dai_driver uda134x_dai = { |
469 | .name = "UDA134X", | 466 | .name = "uda134x-hifi", |
470 | /* playback capabilities */ | 467 | /* playback capabilities */ |
471 | .playback = { | 468 | .playback = { |
472 | .stream_name = "Playback", | 469 | .stream_name = "Playback", |
@@ -486,27 +483,21 @@ struct snd_soc_dai uda134x_dai = { | |||
486 | /* pcm operations */ | 483 | /* pcm operations */ |
487 | .ops = &uda134x_dai_ops, | 484 | .ops = &uda134x_dai_ops, |
488 | }; | 485 | }; |
489 | EXPORT_SYMBOL(uda134x_dai); | ||
490 | 486 | ||
491 | 487 | static int uda134x_soc_probe(struct snd_soc_codec *codec) | |
492 | static int uda134x_soc_probe(struct platform_device *pdev) | ||
493 | { | 488 | { |
494 | struct snd_soc_device *socdev = platform_get_drvdata(pdev); | ||
495 | struct snd_soc_codec *codec; | ||
496 | struct uda134x_priv *uda134x; | 489 | struct uda134x_priv *uda134x; |
497 | void *codec_setup_data = socdev->codec_data; | 490 | struct uda134x_platform_data *pd = dev_get_drvdata(codec->card->dev); |
498 | int ret = -ENOMEM; | 491 | int ret; |
499 | struct uda134x_platform_data *pd; | ||
500 | 492 | ||
501 | printk(KERN_INFO "UDA134X SoC Audio Codec\n"); | 493 | printk(KERN_INFO "UDA134X SoC Audio Codec\n"); |
502 | 494 | ||
503 | if (!codec_setup_data) { | 495 | if (!pd) { |
504 | printk(KERN_ERR "UDA134X SoC codec: " | 496 | printk(KERN_ERR "UDA134X SoC codec: " |
505 | "missing L3 bitbang function\n"); | 497 | "missing L3 bitbang function\n"); |
506 | return -ENODEV; | 498 | return -ENODEV; |
507 | } | 499 | } |
508 | 500 | ||
509 | pd = codec_setup_data; | ||
510 | switch (pd->model) { | 501 | switch (pd->model) { |
511 | case UDA134X_UDA1340: | 502 | case UDA134X_UDA1340: |
512 | case UDA134X_UDA1341: | 503 | case UDA134X_UDA1341: |
@@ -520,58 +511,22 @@ static int uda134x_soc_probe(struct platform_device *pdev) | |||
520 | return -EINVAL; | 511 | return -EINVAL; |
521 | } | 512 | } |
522 | 513 | ||
523 | socdev->card->codec = kzalloc(sizeof(struct snd_soc_codec), GFP_KERNEL); | ||
524 | if (socdev->card->codec == NULL) | ||
525 | return ret; | ||
526 | |||
527 | codec = socdev->card->codec; | ||
528 | |||
529 | uda134x = kzalloc(sizeof(struct uda134x_priv), GFP_KERNEL); | 514 | uda134x = kzalloc(sizeof(struct uda134x_priv), GFP_KERNEL); |
530 | if (uda134x == NULL) | 515 | if (uda134x == NULL) |
531 | goto priv_err; | 516 | return -ENOMEM; |
532 | snd_soc_codec_set_drvdata(codec, uda134x); | 517 | snd_soc_codec_set_drvdata(codec, uda134x); |
533 | 518 | ||
534 | codec->reg_cache = kmemdup(uda134x_reg, sizeof(uda134x_reg), | 519 | codec->control_data = pd; |
535 | GFP_KERNEL); | ||
536 | if (codec->reg_cache == NULL) | ||
537 | goto reg_err; | ||
538 | |||
539 | mutex_init(&codec->mutex); | ||
540 | |||
541 | codec->reg_cache_size = sizeof(uda134x_reg); | ||
542 | codec->reg_cache_step = 1; | ||
543 | |||
544 | codec->name = "UDA134X"; | ||
545 | codec->owner = THIS_MODULE; | ||
546 | codec->dai = &uda134x_dai; | ||
547 | codec->num_dai = 1; | ||
548 | codec->read = uda134x_read_reg_cache; | ||
549 | codec->write = uda134x_write; | ||
550 | |||
551 | INIT_LIST_HEAD(&codec->dapm_widgets); | ||
552 | INIT_LIST_HEAD(&codec->dapm_paths); | ||
553 | |||
554 | codec->control_data = codec_setup_data; | ||
555 | 520 | ||
556 | if (pd->power) | 521 | if (pd->power) |
557 | pd->power(1); | 522 | pd->power(1); |
558 | 523 | ||
559 | uda134x_reset(codec); | 524 | uda134x_reset(codec); |
560 | 525 | ||
561 | if (pd->is_powered_on_standby) { | 526 | if (pd->is_powered_on_standby) |
562 | codec->set_bias_level = NULL; | ||
563 | uda134x_set_bias_level(codec, SND_SOC_BIAS_ON); | 527 | uda134x_set_bias_level(codec, SND_SOC_BIAS_ON); |
564 | } else { | 528 | else |
565 | codec->set_bias_level = uda134x_set_bias_level; | ||
566 | uda134x_set_bias_level(codec, SND_SOC_BIAS_STANDBY); | 529 | uda134x_set_bias_level(codec, SND_SOC_BIAS_STANDBY); |
567 | } | ||
568 | |||
569 | /* register pcms */ | ||
570 | ret = snd_soc_new_pcms(socdev, SNDRV_DEFAULT_IDX1, SNDRV_DEFAULT_STR1); | ||
571 | if (ret < 0) { | ||
572 | printk(KERN_ERR "UDA134X: failed to register pcms\n"); | ||
573 | goto pcm_err; | ||
574 | } | ||
575 | 530 | ||
576 | switch (pd->model) { | 531 | switch (pd->model) { |
577 | case UDA134X_UDA1340: | 532 | case UDA134X_UDA1340: |
@@ -590,61 +545,42 @@ static int uda134x_soc_probe(struct platform_device *pdev) | |||
590 | default: | 545 | default: |
591 | printk(KERN_ERR "%s unknown codec type: %d", | 546 | printk(KERN_ERR "%s unknown codec type: %d", |
592 | __func__, pd->model); | 547 | __func__, pd->model); |
593 | return -EINVAL; | 548 | kfree(uda134x); |
549 | return -EINVAL; | ||
594 | } | 550 | } |
595 | 551 | ||
596 | if (ret < 0) { | 552 | if (ret < 0) { |
597 | printk(KERN_ERR "UDA134X: failed to register controls\n"); | 553 | printk(KERN_ERR "UDA134X: failed to register controls\n"); |
598 | goto pcm_err; | 554 | kfree(uda134x); |
555 | return ret; | ||
599 | } | 556 | } |
600 | 557 | ||
601 | return 0; | 558 | return 0; |
602 | |||
603 | pcm_err: | ||
604 | kfree(codec->reg_cache); | ||
605 | reg_err: | ||
606 | kfree(snd_soc_codec_get_drvdata(codec)); | ||
607 | priv_err: | ||
608 | kfree(codec); | ||
609 | return ret; | ||
610 | } | 559 | } |
611 | 560 | ||
612 | /* power down chip */ | 561 | /* power down chip */ |
613 | static int uda134x_soc_remove(struct platform_device *pdev) | 562 | static int uda134x_soc_remove(struct snd_soc_codec *codec) |
614 | { | 563 | { |
615 | struct snd_soc_device *socdev = platform_get_drvdata(pdev); | 564 | struct uda134x_priv *uda134x = snd_soc_codec_get_drvdata(codec); |
616 | struct snd_soc_codec *codec = socdev->card->codec; | ||
617 | 565 | ||
618 | uda134x_set_bias_level(codec, SND_SOC_BIAS_STANDBY); | 566 | uda134x_set_bias_level(codec, SND_SOC_BIAS_STANDBY); |
619 | uda134x_set_bias_level(codec, SND_SOC_BIAS_OFF); | 567 | uda134x_set_bias_level(codec, SND_SOC_BIAS_OFF); |
620 | 568 | ||
621 | snd_soc_free_pcms(socdev); | 569 | kfree(uda134x); |
622 | snd_soc_dapm_free(socdev); | ||
623 | |||
624 | kfree(snd_soc_codec_get_drvdata(codec)); | ||
625 | kfree(codec->reg_cache); | ||
626 | kfree(codec); | ||
627 | |||
628 | return 0; | 570 | return 0; |
629 | } | 571 | } |
630 | 572 | ||
631 | #if defined(CONFIG_PM) | 573 | #if defined(CONFIG_PM) |
632 | static int uda134x_soc_suspend(struct platform_device *pdev, | 574 | static int uda134x_soc_suspend(struct snd_soc_codec *codec, |
633 | pm_message_t state) | 575 | pm_message_t state) |
634 | { | 576 | { |
635 | struct snd_soc_device *socdev = platform_get_drvdata(pdev); | ||
636 | struct snd_soc_codec *codec = socdev->card->codec; | ||
637 | |||
638 | uda134x_set_bias_level(codec, SND_SOC_BIAS_STANDBY); | 577 | uda134x_set_bias_level(codec, SND_SOC_BIAS_STANDBY); |
639 | uda134x_set_bias_level(codec, SND_SOC_BIAS_OFF); | 578 | uda134x_set_bias_level(codec, SND_SOC_BIAS_OFF); |
640 | return 0; | 579 | return 0; |
641 | } | 580 | } |
642 | 581 | ||
643 | static int uda134x_soc_resume(struct platform_device *pdev) | 582 | static int uda134x_soc_resume(struct snd_soc_codec *codec) |
644 | { | 583 | { |
645 | struct snd_soc_device *socdev = platform_get_drvdata(pdev); | ||
646 | struct snd_soc_codec *codec = socdev->card->codec; | ||
647 | |||
648 | uda134x_set_bias_level(codec, SND_SOC_BIAS_PREPARE); | 584 | uda134x_set_bias_level(codec, SND_SOC_BIAS_PREPARE); |
649 | uda134x_set_bias_level(codec, SND_SOC_BIAS_ON); | 585 | uda134x_set_bias_level(codec, SND_SOC_BIAS_ON); |
650 | return 0; | 586 | return 0; |
@@ -654,25 +590,53 @@ static int uda134x_soc_resume(struct platform_device *pdev) | |||
654 | #define uda134x_soc_resume NULL | 590 | #define uda134x_soc_resume NULL |
655 | #endif /* CONFIG_PM */ | 591 | #endif /* CONFIG_PM */ |
656 | 592 | ||
657 | struct snd_soc_codec_device soc_codec_dev_uda134x = { | 593 | static struct snd_soc_codec_driver soc_codec_dev_uda134x = { |
658 | .probe = uda134x_soc_probe, | 594 | .probe = uda134x_soc_probe, |
659 | .remove = uda134x_soc_remove, | 595 | .remove = uda134x_soc_remove, |
660 | .suspend = uda134x_soc_suspend, | 596 | .suspend = uda134x_soc_suspend, |
661 | .resume = uda134x_soc_resume, | 597 | .resume = uda134x_soc_resume, |
598 | .reg_cache_size = sizeof(uda134x_reg), | ||
599 | .reg_word_size = sizeof(u8), | ||
600 | .reg_cache_step = 1, | ||
601 | .read = uda134x_read_reg_cache, | ||
602 | .write = uda134x_write, | ||
603 | #ifdef POWER_OFF_ON_STANDBY | ||
604 | .set_bias_level = uda134x_set_bias_level, | ||
605 | #endif | ||
606 | }; | ||
607 | |||
608 | static int __devinit uda134x_codec_probe(struct platform_device *pdev) | ||
609 | { | ||
610 | return snd_soc_register_codec(&pdev->dev, | ||
611 | &soc_codec_dev_uda134x, &uda134x_dai, 1); | ||
612 | } | ||
613 | |||
614 | static int __devexit uda134x_codec_remove(struct platform_device *pdev) | ||
615 | { | ||
616 | snd_soc_unregister_codec(&pdev->dev); | ||
617 | return 0; | ||
618 | } | ||
619 | |||
620 | static struct platform_driver uda134x_codec_driver = { | ||
621 | .driver = { | ||
622 | .name = "uda134x-codec", | ||
623 | .owner = THIS_MODULE, | ||
624 | }, | ||
625 | .probe = uda134x_codec_probe, | ||
626 | .remove = __devexit_p(uda134x_codec_remove), | ||
662 | }; | 627 | }; |
663 | EXPORT_SYMBOL_GPL(soc_codec_dev_uda134x); | ||
664 | 628 | ||
665 | static int __init uda134x_init(void) | 629 | static int __init uda134x_codec_init(void) |
666 | { | 630 | { |
667 | return snd_soc_register_dai(&uda134x_dai); | 631 | return platform_driver_register(&uda134x_codec_driver); |
668 | } | 632 | } |
669 | module_init(uda134x_init); | 633 | module_init(uda134x_codec_init); |
670 | 634 | ||
671 | static void __exit uda134x_exit(void) | 635 | static void __exit uda134x_codec_exit(void) |
672 | { | 636 | { |
673 | snd_soc_unregister_dai(&uda134x_dai); | 637 | platform_driver_unregister(&uda134x_codec_driver); |
674 | } | 638 | } |
675 | module_exit(uda134x_exit); | 639 | module_exit(uda134x_codec_exit); |
676 | 640 | ||
677 | MODULE_DESCRIPTION("UDA134X ALSA soc codec driver"); | 641 | MODULE_DESCRIPTION("UDA134X ALSA soc codec driver"); |
678 | MODULE_AUTHOR("Zoltan Devai, Christian Pellegrin <chripell@evolware.org>"); | 642 | MODULE_AUTHOR("Zoltan Devai, Christian Pellegrin <chripell@evolware.org>"); |
diff --git a/sound/soc/codecs/uda134x.h b/sound/soc/codecs/uda134x.h index 205f03b3eaf8..9faae06972b3 100644 --- a/sound/soc/codecs/uda134x.h +++ b/sound/soc/codecs/uda134x.h | |||
@@ -31,7 +31,4 @@ | |||
31 | #define STATUS0_DAIFMT_MASK (~(7<<1)) | 31 | #define STATUS0_DAIFMT_MASK (~(7<<1)) |
32 | #define STATUS0_SYSCLK_MASK (~(3<<4)) | 32 | #define STATUS0_SYSCLK_MASK (~(3<<4)) |
33 | 33 | ||
34 | extern struct snd_soc_dai uda134x_dai; | ||
35 | extern struct snd_soc_codec_device soc_codec_dev_uda134x; | ||
36 | |||
37 | #endif | 34 | #endif |
diff --git a/sound/soc/codecs/uda1380.c b/sound/soc/codecs/uda1380.c index 2f925a27dcde..1a51c816e542 100644 --- a/sound/soc/codecs/uda1380.c +++ b/sound/soc/codecs/uda1380.c | |||
@@ -33,11 +33,9 @@ | |||
33 | 33 | ||
34 | #include "uda1380.h" | 34 | #include "uda1380.h" |
35 | 35 | ||
36 | static struct snd_soc_codec *uda1380_codec; | ||
37 | |||
38 | /* codec private data */ | 36 | /* codec private data */ |
39 | struct uda1380_priv { | 37 | struct uda1380_priv { |
40 | struct snd_soc_codec codec; | 38 | struct snd_soc_codec *codec; |
41 | u16 reg_cache[UDA1380_CACHEREGNUM]; | 39 | u16 reg_cache[UDA1380_CACHEREGNUM]; |
42 | unsigned int dac_clk; | 40 | unsigned int dac_clk; |
43 | struct work_struct work; | 41 | struct work_struct work; |
@@ -135,6 +133,8 @@ static int uda1380_write(struct snd_soc_codec *codec, unsigned int reg, | |||
135 | 133 | ||
136 | static void uda1380_flush_work(struct work_struct *work) | 134 | static void uda1380_flush_work(struct work_struct *work) |
137 | { | 135 | { |
136 | struct uda1380_priv *uda1380 = container_of(work, struct uda1380_priv, work); | ||
137 | struct snd_soc_codec *uda1380_codec = uda1380->codec; | ||
138 | int bit, reg; | 138 | int bit, reg; |
139 | 139 | ||
140 | for_each_set_bit(bit, &uda1380_cache_dirty, UDA1380_CACHEREGNUM - 0x10) { | 140 | for_each_set_bit(bit, &uda1380_cache_dirty, UDA1380_CACHEREGNUM - 0x10) { |
@@ -145,6 +145,7 @@ static void uda1380_flush_work(struct work_struct *work) | |||
145 | uda1380_read_reg_cache(uda1380_codec, reg)); | 145 | uda1380_read_reg_cache(uda1380_codec, reg)); |
146 | clear_bit(bit, &uda1380_cache_dirty); | 146 | clear_bit(bit, &uda1380_cache_dirty); |
147 | } | 147 | } |
148 | |||
148 | } | 149 | } |
149 | 150 | ||
150 | /* declarations of ALSA reg_elem_REAL controls */ | 151 | /* declarations of ALSA reg_elem_REAL controls */ |
@@ -474,8 +475,7 @@ static int uda1380_trigger(struct snd_pcm_substream *substream, int cmd, | |||
474 | struct snd_soc_dai *dai) | 475 | struct snd_soc_dai *dai) |
475 | { | 476 | { |
476 | struct snd_soc_pcm_runtime *rtd = substream->private_data; | 477 | struct snd_soc_pcm_runtime *rtd = substream->private_data; |
477 | struct snd_soc_device *socdev = rtd->socdev; | 478 | struct snd_soc_codec *codec = rtd->codec; |
478 | struct snd_soc_codec *codec = socdev->card->codec; | ||
479 | struct uda1380_priv *uda1380 = snd_soc_codec_get_drvdata(codec); | 479 | struct uda1380_priv *uda1380 = snd_soc_codec_get_drvdata(codec); |
480 | int mixer = uda1380_read_reg_cache(codec, UDA1380_MIXER); | 480 | int mixer = uda1380_read_reg_cache(codec, UDA1380_MIXER); |
481 | 481 | ||
@@ -501,8 +501,7 @@ static int uda1380_pcm_hw_params(struct snd_pcm_substream *substream, | |||
501 | struct snd_soc_dai *dai) | 501 | struct snd_soc_dai *dai) |
502 | { | 502 | { |
503 | struct snd_soc_pcm_runtime *rtd = substream->private_data; | 503 | struct snd_soc_pcm_runtime *rtd = substream->private_data; |
504 | struct snd_soc_device *socdev = rtd->socdev; | 504 | struct snd_soc_codec *codec = rtd->codec; |
505 | struct snd_soc_codec *codec = socdev->card->codec; | ||
506 | u16 clk = uda1380_read_reg_cache(codec, UDA1380_CLK); | 505 | u16 clk = uda1380_read_reg_cache(codec, UDA1380_CLK); |
507 | 506 | ||
508 | /* set WSPLL power and divider if running from this clock */ | 507 | /* set WSPLL power and divider if running from this clock */ |
@@ -540,8 +539,7 @@ static void uda1380_pcm_shutdown(struct snd_pcm_substream *substream, | |||
540 | struct snd_soc_dai *dai) | 539 | struct snd_soc_dai *dai) |
541 | { | 540 | { |
542 | struct snd_soc_pcm_runtime *rtd = substream->private_data; | 541 | struct snd_soc_pcm_runtime *rtd = substream->private_data; |
543 | struct snd_soc_device *socdev = rtd->socdev; | 542 | struct snd_soc_codec *codec = rtd->codec; |
544 | struct snd_soc_codec *codec = socdev->card->codec; | ||
545 | u16 clk = uda1380_read_reg_cache(codec, UDA1380_CLK); | 543 | u16 clk = uda1380_read_reg_cache(codec, UDA1380_CLK); |
546 | 544 | ||
547 | /* shut down WSPLL power if running from this clock */ | 545 | /* shut down WSPLL power if running from this clock */ |
@@ -604,9 +602,9 @@ static struct snd_soc_dai_ops uda1380_dai_ops_capture = { | |||
604 | .set_fmt = uda1380_set_dai_fmt_capture, | 602 | .set_fmt = uda1380_set_dai_fmt_capture, |
605 | }; | 603 | }; |
606 | 604 | ||
607 | struct snd_soc_dai uda1380_dai[] = { | 605 | static struct snd_soc_dai_driver uda1380_dai[] = { |
608 | { | 606 | { |
609 | .name = "UDA1380", | 607 | .name = "uda1380-hifi", |
610 | .playback = { | 608 | .playback = { |
611 | .stream_name = "Playback", | 609 | .stream_name = "Playback", |
612 | .channels_min = 1, | 610 | .channels_min = 1, |
@@ -622,7 +620,7 @@ struct snd_soc_dai uda1380_dai[] = { | |||
622 | .ops = &uda1380_dai_ops, | 620 | .ops = &uda1380_dai_ops, |
623 | }, | 621 | }, |
624 | { /* playback only - dual interface */ | 622 | { /* playback only - dual interface */ |
625 | .name = "UDA1380", | 623 | .name = "uda1380-hifi-playback", |
626 | .playback = { | 624 | .playback = { |
627 | .stream_name = "Playback", | 625 | .stream_name = "Playback", |
628 | .channels_min = 1, | 626 | .channels_min = 1, |
@@ -633,7 +631,7 @@ struct snd_soc_dai uda1380_dai[] = { | |||
633 | .ops = &uda1380_dai_ops_playback, | 631 | .ops = &uda1380_dai_ops_playback, |
634 | }, | 632 | }, |
635 | { /* capture only - dual interface*/ | 633 | { /* capture only - dual interface*/ |
636 | .name = "UDA1380", | 634 | .name = "uda1380-hifi-capture", |
637 | .capture = { | 635 | .capture = { |
638 | .stream_name = "Capture", | 636 | .stream_name = "Capture", |
639 | .channels_min = 1, | 637 | .channels_min = 1, |
@@ -644,21 +642,15 @@ struct snd_soc_dai uda1380_dai[] = { | |||
644 | .ops = &uda1380_dai_ops_capture, | 642 | .ops = &uda1380_dai_ops_capture, |
645 | }, | 643 | }, |
646 | }; | 644 | }; |
647 | EXPORT_SYMBOL_GPL(uda1380_dai); | ||
648 | 645 | ||
649 | static int uda1380_suspend(struct platform_device *pdev, pm_message_t state) | 646 | static int uda1380_suspend(struct snd_soc_codec *codec, pm_message_t state) |
650 | { | 647 | { |
651 | struct snd_soc_device *socdev = platform_get_drvdata(pdev); | ||
652 | struct snd_soc_codec *codec = socdev->card->codec; | ||
653 | |||
654 | uda1380_set_bias_level(codec, SND_SOC_BIAS_OFF); | 648 | uda1380_set_bias_level(codec, SND_SOC_BIAS_OFF); |
655 | return 0; | 649 | return 0; |
656 | } | 650 | } |
657 | 651 | ||
658 | static int uda1380_resume(struct platform_device *pdev) | 652 | static int uda1380_resume(struct snd_soc_codec *codec) |
659 | { | 653 | { |
660 | struct snd_soc_device *socdev = platform_get_drvdata(pdev); | ||
661 | struct snd_soc_codec *codec = socdev->card->codec; | ||
662 | int i; | 654 | int i; |
663 | u8 data[2]; | 655 | u8 data[2]; |
664 | u16 *cache = codec->reg_cache; | 656 | u16 *cache = codec->reg_cache; |
@@ -673,91 +665,20 @@ static int uda1380_resume(struct platform_device *pdev) | |||
673 | return 0; | 665 | return 0; |
674 | } | 666 | } |
675 | 667 | ||
676 | static int uda1380_probe(struct platform_device *pdev) | 668 | static int uda1380_probe(struct snd_soc_codec *codec) |
677 | { | ||
678 | struct snd_soc_device *socdev = platform_get_drvdata(pdev); | ||
679 | struct snd_soc_codec *codec; | ||
680 | struct uda1380_platform_data *pdata; | ||
681 | int ret = 0; | ||
682 | |||
683 | if (uda1380_codec == NULL) { | ||
684 | dev_err(&pdev->dev, "Codec device not registered\n"); | ||
685 | return -ENODEV; | ||
686 | } | ||
687 | |||
688 | socdev->card->codec = uda1380_codec; | ||
689 | codec = uda1380_codec; | ||
690 | pdata = codec->dev->platform_data; | ||
691 | |||
692 | /* register pcms */ | ||
693 | ret = snd_soc_new_pcms(socdev, SNDRV_DEFAULT_IDX1, SNDRV_DEFAULT_STR1); | ||
694 | if (ret < 0) { | ||
695 | dev_err(codec->dev, "failed to create pcms: %d\n", ret); | ||
696 | goto pcm_err; | ||
697 | } | ||
698 | |||
699 | /* power on device */ | ||
700 | uda1380_set_bias_level(codec, SND_SOC_BIAS_STANDBY); | ||
701 | /* set clock input */ | ||
702 | switch (pdata->dac_clk) { | ||
703 | case UDA1380_DAC_CLK_SYSCLK: | ||
704 | uda1380_write(codec, UDA1380_CLK, 0); | ||
705 | break; | ||
706 | case UDA1380_DAC_CLK_WSPLL: | ||
707 | uda1380_write(codec, UDA1380_CLK, R00_DAC_CLK); | ||
708 | break; | ||
709 | } | ||
710 | |||
711 | snd_soc_add_controls(codec, uda1380_snd_controls, | ||
712 | ARRAY_SIZE(uda1380_snd_controls)); | ||
713 | uda1380_add_widgets(codec); | ||
714 | |||
715 | return ret; | ||
716 | |||
717 | pcm_err: | ||
718 | return ret; | ||
719 | } | ||
720 | |||
721 | /* power down chip */ | ||
722 | static int uda1380_remove(struct platform_device *pdev) | ||
723 | { | ||
724 | struct snd_soc_device *socdev = platform_get_drvdata(pdev); | ||
725 | struct snd_soc_codec *codec = socdev->card->codec; | ||
726 | |||
727 | if (codec->control_data) | ||
728 | uda1380_set_bias_level(codec, SND_SOC_BIAS_OFF); | ||
729 | |||
730 | snd_soc_free_pcms(socdev); | ||
731 | snd_soc_dapm_free(socdev); | ||
732 | |||
733 | return 0; | ||
734 | } | ||
735 | |||
736 | struct snd_soc_codec_device soc_codec_dev_uda1380 = { | ||
737 | .probe = uda1380_probe, | ||
738 | .remove = uda1380_remove, | ||
739 | .suspend = uda1380_suspend, | ||
740 | .resume = uda1380_resume, | ||
741 | }; | ||
742 | EXPORT_SYMBOL_GPL(soc_codec_dev_uda1380); | ||
743 | |||
744 | static int uda1380_register(struct uda1380_priv *uda1380) | ||
745 | { | 669 | { |
746 | int ret, i; | 670 | struct uda1380_platform_data *pdata =codec->dev->platform_data; |
747 | struct snd_soc_codec *codec = &uda1380->codec; | 671 | struct uda1380_priv *uda1380 = snd_soc_codec_get_drvdata(codec); |
748 | struct uda1380_platform_data *pdata = codec->dev->platform_data; | 672 | int ret; |
749 | 673 | ||
750 | if (uda1380_codec) { | 674 | codec->hw_write = (hw_write_t)i2c_master_send; |
751 | dev_err(codec->dev, "Another UDA1380 is registered\n"); | ||
752 | return -EINVAL; | ||
753 | } | ||
754 | 675 | ||
755 | if (!pdata || !pdata->gpio_power || !pdata->gpio_reset) | 676 | if (!pdata || !pdata->gpio_power || !pdata->gpio_reset) |
756 | return -EINVAL; | 677 | return -EINVAL; |
757 | 678 | ||
758 | ret = gpio_request(pdata->gpio_power, "uda1380 power"); | 679 | ret = gpio_request(pdata->gpio_power, "uda1380 power"); |
759 | if (ret) | 680 | if (ret) |
760 | goto err_out; | 681 | return ret; |
761 | ret = gpio_request(pdata->gpio_reset, "uda1380 reset"); | 682 | ret = gpio_request(pdata->gpio_reset, "uda1380 reset"); |
762 | if (ret) | 683 | if (ret) |
763 | goto err_gpio; | 684 | goto err_gpio; |
@@ -769,25 +690,6 @@ static int uda1380_register(struct uda1380_priv *uda1380) | |||
769 | udelay(5); | 690 | udelay(5); |
770 | gpio_set_value(pdata->gpio_reset, 0); | 691 | gpio_set_value(pdata->gpio_reset, 0); |
771 | 692 | ||
772 | mutex_init(&codec->mutex); | ||
773 | INIT_LIST_HEAD(&codec->dapm_widgets); | ||
774 | INIT_LIST_HEAD(&codec->dapm_paths); | ||
775 | |||
776 | snd_soc_codec_set_drvdata(codec, uda1380); | ||
777 | codec->name = "UDA1380"; | ||
778 | codec->owner = THIS_MODULE; | ||
779 | codec->read = uda1380_read_reg_cache; | ||
780 | codec->write = uda1380_write; | ||
781 | codec->bias_level = SND_SOC_BIAS_OFF; | ||
782 | codec->set_bias_level = uda1380_set_bias_level; | ||
783 | codec->dai = uda1380_dai; | ||
784 | codec->num_dai = ARRAY_SIZE(uda1380_dai); | ||
785 | codec->reg_cache_size = ARRAY_SIZE(uda1380_reg); | ||
786 | codec->reg_cache = &uda1380->reg_cache; | ||
787 | codec->reg_cache_step = 1; | ||
788 | |||
789 | memcpy(codec->reg_cache, uda1380_reg, sizeof(uda1380_reg)); | ||
790 | |||
791 | ret = uda1380_reset(codec); | 693 | ret = uda1380_reset(codec); |
792 | if (ret < 0) { | 694 | if (ret < 0) { |
793 | dev_err(codec->dev, "Failed to issue reset\n"); | 695 | dev_err(codec->dev, "Failed to issue reset\n"); |
@@ -796,83 +698,84 @@ static int uda1380_register(struct uda1380_priv *uda1380) | |||
796 | 698 | ||
797 | INIT_WORK(&uda1380->work, uda1380_flush_work); | 699 | INIT_WORK(&uda1380->work, uda1380_flush_work); |
798 | 700 | ||
799 | for (i = 0; i < ARRAY_SIZE(uda1380_dai); i++) | 701 | /* power on device */ |
800 | uda1380_dai[i].dev = codec->dev; | 702 | uda1380_set_bias_level(codec, SND_SOC_BIAS_STANDBY); |
801 | 703 | /* set clock input */ | |
802 | uda1380_codec = codec; | 704 | switch (pdata->dac_clk) { |
803 | 705 | case UDA1380_DAC_CLK_SYSCLK: | |
804 | ret = snd_soc_register_codec(codec); | 706 | uda1380_write(codec, UDA1380_CLK, 0); |
805 | if (ret != 0) { | 707 | break; |
806 | dev_err(codec->dev, "Failed to register codec: %d\n", ret); | 708 | case UDA1380_DAC_CLK_WSPLL: |
807 | goto err_reset; | 709 | uda1380_write(codec, UDA1380_CLK, R00_DAC_CLK); |
710 | break; | ||
808 | } | 711 | } |
809 | 712 | ||
810 | ret = snd_soc_register_dais(uda1380_dai, ARRAY_SIZE(uda1380_dai)); | 713 | snd_soc_add_controls(codec, uda1380_snd_controls, |
811 | if (ret != 0) { | 714 | ARRAY_SIZE(uda1380_snd_controls)); |
812 | dev_err(codec->dev, "Failed to register DAIs: %d\n", ret); | 715 | uda1380_add_widgets(codec); |
813 | goto err_dai; | ||
814 | } | ||
815 | 716 | ||
816 | return 0; | 717 | return 0; |
817 | 718 | ||
818 | err_dai: | ||
819 | snd_soc_unregister_codec(codec); | ||
820 | err_reset: | 719 | err_reset: |
821 | gpio_set_value(pdata->gpio_power, 0); | 720 | gpio_set_value(pdata->gpio_power, 0); |
822 | gpio_free(pdata->gpio_reset); | 721 | gpio_free(pdata->gpio_reset); |
823 | err_gpio: | 722 | err_gpio: |
824 | gpio_free(pdata->gpio_power); | 723 | gpio_free(pdata->gpio_power); |
825 | err_out: | ||
826 | return ret; | 724 | return ret; |
827 | } | 725 | } |
828 | 726 | ||
829 | static void uda1380_unregister(struct uda1380_priv *uda1380) | 727 | /* power down chip */ |
728 | static int uda1380_remove(struct snd_soc_codec *codec) | ||
830 | { | 729 | { |
831 | struct snd_soc_codec *codec = &uda1380->codec; | 730 | struct uda1380_platform_data *pdata =codec->dev->platform_data; |
832 | struct uda1380_platform_data *pdata = codec->dev->platform_data; | ||
833 | 731 | ||
834 | snd_soc_unregister_dais(uda1380_dai, ARRAY_SIZE(uda1380_dai)); | 732 | uda1380_set_bias_level(codec, SND_SOC_BIAS_OFF); |
835 | snd_soc_unregister_codec(&uda1380->codec); | ||
836 | 733 | ||
837 | gpio_set_value(pdata->gpio_power, 0); | 734 | gpio_set_value(pdata->gpio_power, 0); |
838 | gpio_free(pdata->gpio_reset); | 735 | gpio_free(pdata->gpio_reset); |
839 | gpio_free(pdata->gpio_power); | 736 | gpio_free(pdata->gpio_power); |
840 | 737 | ||
841 | kfree(uda1380); | 738 | return 0; |
842 | uda1380_codec = NULL; | ||
843 | } | 739 | } |
844 | 740 | ||
741 | static struct snd_soc_codec_driver soc_codec_dev_uda1380 = { | ||
742 | .probe = uda1380_probe, | ||
743 | .remove = uda1380_remove, | ||
744 | .suspend = uda1380_suspend, | ||
745 | .resume = uda1380_resume, | ||
746 | .read = uda1380_read_reg_cache, | ||
747 | .write = uda1380_write, | ||
748 | .set_bias_level = uda1380_set_bias_level, | ||
749 | .reg_cache_size = ARRAY_SIZE(uda1380_reg), | ||
750 | .reg_word_size = sizeof(u16), | ||
751 | .reg_cache_default = uda1380_reg, | ||
752 | .reg_cache_step = 1, | ||
753 | }; | ||
754 | |||
845 | #if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE) | 755 | #if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE) |
846 | static __devinit int uda1380_i2c_probe(struct i2c_client *i2c, | 756 | static __devinit int uda1380_i2c_probe(struct i2c_client *i2c, |
847 | const struct i2c_device_id *id) | 757 | const struct i2c_device_id *id) |
848 | { | 758 | { |
849 | struct uda1380_priv *uda1380; | 759 | struct uda1380_priv *uda1380; |
850 | struct snd_soc_codec *codec; | ||
851 | int ret; | 760 | int ret; |
852 | 761 | ||
853 | uda1380 = kzalloc(sizeof(struct uda1380_priv), GFP_KERNEL); | 762 | uda1380 = kzalloc(sizeof(struct uda1380_priv), GFP_KERNEL); |
854 | if (uda1380 == NULL) | 763 | if (uda1380 == NULL) |
855 | return -ENOMEM; | 764 | return -ENOMEM; |
856 | 765 | ||
857 | codec = &uda1380->codec; | ||
858 | codec->hw_write = (hw_write_t)i2c_master_send; | ||
859 | |||
860 | i2c_set_clientdata(i2c, uda1380); | 766 | i2c_set_clientdata(i2c, uda1380); |
861 | codec->control_data = i2c; | ||
862 | |||
863 | codec->dev = &i2c->dev; | ||
864 | 767 | ||
865 | ret = uda1380_register(uda1380); | 768 | ret = snd_soc_register_codec(&i2c->dev, |
866 | if (ret != 0) | 769 | &soc_codec_dev_uda1380, uda1380_dai, ARRAY_SIZE(uda1380_dai)); |
770 | if (ret < 0) | ||
867 | kfree(uda1380); | 771 | kfree(uda1380); |
868 | |||
869 | return ret; | 772 | return ret; |
870 | } | 773 | } |
871 | 774 | ||
872 | static int __devexit uda1380_i2c_remove(struct i2c_client *i2c) | 775 | static int __devexit uda1380_i2c_remove(struct i2c_client *i2c) |
873 | { | 776 | { |
874 | struct uda1380_priv *uda1380 = i2c_get_clientdata(i2c); | 777 | snd_soc_unregister_codec(&i2c->dev); |
875 | uda1380_unregister(uda1380); | 778 | kfree(i2c_get_clientdata(i2c)); |
876 | return 0; | 779 | return 0; |
877 | } | 780 | } |
878 | 781 | ||
@@ -884,7 +787,7 @@ MODULE_DEVICE_TABLE(i2c, uda1380_i2c_id); | |||
884 | 787 | ||
885 | static struct i2c_driver uda1380_i2c_driver = { | 788 | static struct i2c_driver uda1380_i2c_driver = { |
886 | .driver = { | 789 | .driver = { |
887 | .name = "UDA1380 I2C Codec", | 790 | .name = "uda1380-codec", |
888 | .owner = THIS_MODULE, | 791 | .owner = THIS_MODULE, |
889 | }, | 792 | }, |
890 | .probe = uda1380_i2c_probe, | 793 | .probe = uda1380_i2c_probe, |
diff --git a/sound/soc/codecs/uda1380.h b/sound/soc/codecs/uda1380.h index 9cefa8a54770..942e3927c72b 100644 --- a/sound/soc/codecs/uda1380.h +++ b/sound/soc/codecs/uda1380.h | |||
@@ -76,7 +76,4 @@ | |||
76 | #define UDA1380_DAI_PLAYBACK 1 /* playback DAI */ | 76 | #define UDA1380_DAI_PLAYBACK 1 /* playback DAI */ |
77 | #define UDA1380_DAI_CAPTURE 2 /* capture DAI */ | 77 | #define UDA1380_DAI_CAPTURE 2 /* capture DAI */ |
78 | 78 | ||
79 | extern struct snd_soc_dai uda1380_dai[3]; | ||
80 | extern struct snd_soc_codec_device soc_codec_dev_uda1380; | ||
81 | |||
82 | #endif /* _UDA1380_H */ | 79 | #endif /* _UDA1380_H */ |
diff --git a/sound/soc/codecs/wm2000.h b/sound/soc/codecs/wm2000.h index c18e261c3c7f..0b6f056f73cc 100644 --- a/sound/soc/codecs/wm2000.h +++ b/sound/soc/codecs/wm2000.h | |||
@@ -16,9 +16,6 @@ struct wm2000_setup_data { | |||
16 | 16 | ||
17 | extern int wm2000_add_controls(struct snd_soc_codec *codec); | 17 | extern int wm2000_add_controls(struct snd_soc_codec *codec); |
18 | 18 | ||
19 | extern struct snd_soc_dai wm2000_dai; | ||
20 | extern struct snd_soc_codec_device soc_codec_dev_wm2000; | ||
21 | |||
22 | #define WM2000_REG_SYS_START 0x8000 | 19 | #define WM2000_REG_SYS_START 0x8000 |
23 | #define WM2000_REG_SPEECH_CLARITY 0x8fef | 20 | #define WM2000_REG_SPEECH_CLARITY 0x8fef |
24 | #define WM2000_REG_SYS_WATCHDOG 0x8ff6 | 21 | #define WM2000_REG_SYS_WATCHDOG 0x8ff6 |
diff --git a/sound/soc/codecs/wm8350.c b/sound/soc/codecs/wm8350.c index 0221ca79b3ae..f4f1fba38eb9 100644 --- a/sound/soc/codecs/wm8350.c +++ b/sound/soc/codecs/wm8350.c | |||
@@ -1321,20 +1321,14 @@ static int wm8350_set_bias_level(struct snd_soc_codec *codec, | |||
1321 | return 0; | 1321 | return 0; |
1322 | } | 1322 | } |
1323 | 1323 | ||
1324 | static int wm8350_suspend(struct platform_device *pdev, pm_message_t state) | 1324 | static int wm8350_suspend(struct snd_soc_codec *codec, pm_message_t state) |
1325 | { | 1325 | { |
1326 | struct snd_soc_device *socdev = platform_get_drvdata(pdev); | ||
1327 | struct snd_soc_codec *codec = socdev->card->codec; | ||
1328 | |||
1329 | wm8350_set_bias_level(codec, SND_SOC_BIAS_OFF); | 1326 | wm8350_set_bias_level(codec, SND_SOC_BIAS_OFF); |
1330 | return 0; | 1327 | return 0; |
1331 | } | 1328 | } |
1332 | 1329 | ||
1333 | static int wm8350_resume(struct platform_device *pdev) | 1330 | static int wm8350_resume(struct snd_soc_codec *codec) |
1334 | { | 1331 | { |
1335 | struct snd_soc_device *socdev = platform_get_drvdata(pdev); | ||
1336 | struct snd_soc_codec *codec = socdev->card->codec; | ||
1337 | |||
1338 | wm8350_set_bias_level(codec, SND_SOC_BIAS_STANDBY); | 1332 | wm8350_set_bias_level(codec, SND_SOC_BIAS_STANDBY); |
1339 | 1333 | ||
1340 | return 0; | 1334 | return 0; |
@@ -1489,24 +1483,74 @@ int wm8350_mic_jack_detect(struct snd_soc_codec *codec, | |||
1489 | } | 1483 | } |
1490 | EXPORT_SYMBOL_GPL(wm8350_mic_jack_detect); | 1484 | EXPORT_SYMBOL_GPL(wm8350_mic_jack_detect); |
1491 | 1485 | ||
1492 | static struct snd_soc_codec *wm8350_codec; | 1486 | #define WM8350_RATES (SNDRV_PCM_RATE_8000_96000) |
1487 | |||
1488 | #define WM8350_FORMATS (SNDRV_PCM_FMTBIT_S16_LE |\ | ||
1489 | SNDRV_PCM_FMTBIT_S20_3LE |\ | ||
1490 | SNDRV_PCM_FMTBIT_S24_LE) | ||
1491 | |||
1492 | static struct snd_soc_dai_ops wm8350_dai_ops = { | ||
1493 | .hw_params = wm8350_pcm_hw_params, | ||
1494 | .digital_mute = wm8350_mute, | ||
1495 | .trigger = wm8350_pcm_trigger, | ||
1496 | .set_fmt = wm8350_set_dai_fmt, | ||
1497 | .set_sysclk = wm8350_set_dai_sysclk, | ||
1498 | .set_pll = wm8350_set_fll, | ||
1499 | .set_clkdiv = wm8350_set_clkdiv, | ||
1500 | }; | ||
1501 | |||
1502 | static struct snd_soc_dai_driver wm8350_dai = { | ||
1503 | .name = "wm8350-hifi", | ||
1504 | .playback = { | ||
1505 | .stream_name = "Playback", | ||
1506 | .channels_min = 1, | ||
1507 | .channels_max = 2, | ||
1508 | .rates = WM8350_RATES, | ||
1509 | .formats = WM8350_FORMATS, | ||
1510 | }, | ||
1511 | .capture = { | ||
1512 | .stream_name = "Capture", | ||
1513 | .channels_min = 1, | ||
1514 | .channels_max = 2, | ||
1515 | .rates = WM8350_RATES, | ||
1516 | .formats = WM8350_FORMATS, | ||
1517 | }, | ||
1518 | .ops = &wm8350_dai_ops, | ||
1519 | }; | ||
1493 | 1520 | ||
1494 | static int wm8350_probe(struct platform_device *pdev) | 1521 | static int wm8350_codec_probe(struct snd_soc_codec *codec) |
1495 | { | 1522 | { |
1496 | struct snd_soc_device *socdev = platform_get_drvdata(pdev); | 1523 | struct wm8350 *wm8350 = dev_get_platdata(codec->dev); |
1497 | struct snd_soc_codec *codec; | ||
1498 | struct wm8350 *wm8350; | ||
1499 | struct wm8350_data *priv; | 1524 | struct wm8350_data *priv; |
1500 | int ret; | ||
1501 | struct wm8350_output *out1; | 1525 | struct wm8350_output *out1; |
1502 | struct wm8350_output *out2; | 1526 | struct wm8350_output *out2; |
1527 | int ret, i; | ||
1503 | 1528 | ||
1504 | BUG_ON(!wm8350_codec); | 1529 | if (wm8350->codec.platform_data == NULL) { |
1530 | dev_err(codec->dev, "No audio platform data supplied\n"); | ||
1531 | return -EINVAL; | ||
1532 | } | ||
1533 | |||
1534 | priv = kzalloc(sizeof(struct wm8350_data), GFP_KERNEL); | ||
1535 | if (priv == NULL) | ||
1536 | return -ENOMEM; | ||
1537 | snd_soc_codec_set_drvdata(codec, priv); | ||
1538 | |||
1539 | for (i = 0; i < ARRAY_SIZE(supply_names); i++) | ||
1540 | priv->supplies[i].supply = supply_names[i]; | ||
1541 | |||
1542 | ret = regulator_bulk_get(wm8350->dev, ARRAY_SIZE(priv->supplies), | ||
1543 | priv->supplies); | ||
1544 | if (ret != 0) | ||
1545 | goto err_priv; | ||
1546 | |||
1547 | wm8350->codec.codec = codec; | ||
1548 | codec->control_data = wm8350; | ||
1505 | 1549 | ||
1506 | socdev->card->codec = wm8350_codec; | 1550 | /* Put the codec into reset if it wasn't already */ |
1507 | codec = socdev->card->codec; | 1551 | wm8350_clear_bits(wm8350, WM8350_POWER_MGMT_5, WM8350_CODEC_ENA); |
1508 | wm8350 = codec->control_data; | 1552 | |
1509 | priv = snd_soc_codec_get_drvdata(codec); | 1553 | INIT_DELAYED_WORK(&codec->delayed_work, wm8350_pga_work); |
1510 | 1554 | ||
1511 | /* Enable the codec */ | 1555 | /* Enable the codec */ |
1512 | wm8350_set_bits(wm8350, WM8350_POWER_MGMT_5, WM8350_CODEC_ENA); | 1556 | wm8350_set_bits(wm8350, WM8350_POWER_MGMT_5, WM8350_CODEC_ENA); |
@@ -1557,11 +1601,6 @@ static int wm8350_probe(struct platform_device *pdev) | |||
1557 | wm8350_register_irq(wm8350, WM8350_IRQ_CODEC_MICD, | 1601 | wm8350_register_irq(wm8350, WM8350_IRQ_CODEC_MICD, |
1558 | wm8350_mic_handler, 0, "Microphone detect", priv); | 1602 | wm8350_mic_handler, 0, "Microphone detect", priv); |
1559 | 1603 | ||
1560 | ret = snd_soc_new_pcms(socdev, SNDRV_DEFAULT_IDX1, SNDRV_DEFAULT_STR1); | ||
1561 | if (ret < 0) { | ||
1562 | dev_err(&pdev->dev, "failed to create pcms\n"); | ||
1563 | return ret; | ||
1564 | } | ||
1565 | 1604 | ||
1566 | snd_soc_add_controls(codec, wm8350_snd_controls, | 1605 | snd_soc_add_controls(codec, wm8350_snd_controls, |
1567 | ARRAY_SIZE(wm8350_snd_controls)); | 1606 | ARRAY_SIZE(wm8350_snd_controls)); |
@@ -1570,14 +1609,16 @@ static int wm8350_probe(struct platform_device *pdev) | |||
1570 | wm8350_set_bias_level(codec, SND_SOC_BIAS_STANDBY); | 1609 | wm8350_set_bias_level(codec, SND_SOC_BIAS_STANDBY); |
1571 | 1610 | ||
1572 | return 0; | 1611 | return 0; |
1612 | |||
1613 | err_priv: | ||
1614 | kfree(priv); | ||
1615 | return ret; | ||
1573 | } | 1616 | } |
1574 | 1617 | ||
1575 | static int wm8350_remove(struct platform_device *pdev) | 1618 | static int wm8350_codec_remove(struct snd_soc_codec *codec) |
1576 | { | 1619 | { |
1577 | struct snd_soc_device *socdev = platform_get_drvdata(pdev); | ||
1578 | struct snd_soc_codec *codec = socdev->card->codec; | ||
1579 | struct wm8350 *wm8350 = codec->control_data; | ||
1580 | struct wm8350_data *priv = snd_soc_codec_get_drvdata(codec); | 1620 | struct wm8350_data *priv = snd_soc_codec_get_drvdata(codec); |
1621 | struct wm8350 *wm8350 = dev_get_platdata(codec->dev); | ||
1581 | int ret; | 1622 | int ret; |
1582 | 1623 | ||
1583 | wm8350_clear_bits(wm8350, WM8350_JACK_DETECT, | 1624 | wm8350_clear_bits(wm8350, WM8350_JACK_DETECT, |
@@ -1607,134 +1648,30 @@ static int wm8350_remove(struct platform_device *pdev) | |||
1607 | 1648 | ||
1608 | wm8350_clear_bits(wm8350, WM8350_POWER_MGMT_5, WM8350_CODEC_ENA); | 1649 | wm8350_clear_bits(wm8350, WM8350_POWER_MGMT_5, WM8350_CODEC_ENA); |
1609 | 1650 | ||
1651 | regulator_bulk_free(ARRAY_SIZE(priv->supplies), priv->supplies); | ||
1652 | kfree(priv); | ||
1610 | return 0; | 1653 | return 0; |
1611 | } | 1654 | } |
1612 | 1655 | ||
1613 | #define WM8350_RATES (SNDRV_PCM_RATE_8000_96000) | 1656 | static struct snd_soc_codec_driver soc_codec_dev_wm8350 = { |
1614 | 1657 | .probe = wm8350_codec_probe, | |
1615 | #define WM8350_FORMATS (SNDRV_PCM_FMTBIT_S16_LE |\ | 1658 | .remove = wm8350_codec_remove, |
1616 | SNDRV_PCM_FMTBIT_S20_3LE |\ | ||
1617 | SNDRV_PCM_FMTBIT_S24_LE) | ||
1618 | |||
1619 | static struct snd_soc_dai_ops wm8350_dai_ops = { | ||
1620 | .hw_params = wm8350_pcm_hw_params, | ||
1621 | .digital_mute = wm8350_mute, | ||
1622 | .trigger = wm8350_pcm_trigger, | ||
1623 | .set_fmt = wm8350_set_dai_fmt, | ||
1624 | .set_sysclk = wm8350_set_dai_sysclk, | ||
1625 | .set_pll = wm8350_set_fll, | ||
1626 | .set_clkdiv = wm8350_set_clkdiv, | ||
1627 | }; | ||
1628 | |||
1629 | struct snd_soc_dai wm8350_dai = { | ||
1630 | .name = "WM8350", | ||
1631 | .playback = { | ||
1632 | .stream_name = "Playback", | ||
1633 | .channels_min = 1, | ||
1634 | .channels_max = 2, | ||
1635 | .rates = WM8350_RATES, | ||
1636 | .formats = WM8350_FORMATS, | ||
1637 | }, | ||
1638 | .capture = { | ||
1639 | .stream_name = "Capture", | ||
1640 | .channels_min = 1, | ||
1641 | .channels_max = 2, | ||
1642 | .rates = WM8350_RATES, | ||
1643 | .formats = WM8350_FORMATS, | ||
1644 | }, | ||
1645 | .ops = &wm8350_dai_ops, | ||
1646 | }; | ||
1647 | EXPORT_SYMBOL_GPL(wm8350_dai); | ||
1648 | |||
1649 | struct snd_soc_codec_device soc_codec_dev_wm8350 = { | ||
1650 | .probe = wm8350_probe, | ||
1651 | .remove = wm8350_remove, | ||
1652 | .suspend = wm8350_suspend, | 1659 | .suspend = wm8350_suspend, |
1653 | .resume = wm8350_resume, | 1660 | .resume = wm8350_resume, |
1661 | .read = wm8350_codec_read, | ||
1662 | .write = wm8350_codec_write, | ||
1663 | .set_bias_level = wm8350_set_bias_level, | ||
1654 | }; | 1664 | }; |
1655 | EXPORT_SYMBOL_GPL(soc_codec_dev_wm8350); | ||
1656 | 1665 | ||
1657 | static __devinit int wm8350_codec_probe(struct platform_device *pdev) | 1666 | static int __devinit wm8350_probe(struct platform_device *pdev) |
1658 | { | 1667 | { |
1659 | struct wm8350 *wm8350 = platform_get_drvdata(pdev); | 1668 | return snd_soc_register_codec(&pdev->dev, &soc_codec_dev_wm8350, |
1660 | struct wm8350_data *priv; | 1669 | &wm8350_dai, 1); |
1661 | struct snd_soc_codec *codec; | ||
1662 | int ret, i; | ||
1663 | |||
1664 | if (wm8350->codec.platform_data == NULL) { | ||
1665 | dev_err(&pdev->dev, "No audio platform data supplied\n"); | ||
1666 | return -EINVAL; | ||
1667 | } | ||
1668 | |||
1669 | priv = kzalloc(sizeof(struct wm8350_data), GFP_KERNEL); | ||
1670 | if (priv == NULL) | ||
1671 | return -ENOMEM; | ||
1672 | |||
1673 | for (i = 0; i < ARRAY_SIZE(supply_names); i++) | ||
1674 | priv->supplies[i].supply = supply_names[i]; | ||
1675 | |||
1676 | ret = regulator_bulk_get(wm8350->dev, ARRAY_SIZE(priv->supplies), | ||
1677 | priv->supplies); | ||
1678 | if (ret != 0) | ||
1679 | goto err_priv; | ||
1680 | |||
1681 | codec = &priv->codec; | ||
1682 | wm8350->codec.codec = codec; | ||
1683 | |||
1684 | wm8350_dai.dev = &pdev->dev; | ||
1685 | |||
1686 | mutex_init(&codec->mutex); | ||
1687 | INIT_LIST_HEAD(&codec->dapm_widgets); | ||
1688 | INIT_LIST_HEAD(&codec->dapm_paths); | ||
1689 | codec->dev = &pdev->dev; | ||
1690 | codec->name = "WM8350"; | ||
1691 | codec->owner = THIS_MODULE; | ||
1692 | codec->read = wm8350_codec_read; | ||
1693 | codec->write = wm8350_codec_write; | ||
1694 | codec->bias_level = SND_SOC_BIAS_OFF; | ||
1695 | codec->set_bias_level = wm8350_set_bias_level; | ||
1696 | codec->dai = &wm8350_dai; | ||
1697 | codec->num_dai = 1; | ||
1698 | codec->reg_cache_size = WM8350_MAX_REGISTER; | ||
1699 | snd_soc_codec_set_drvdata(codec, priv); | ||
1700 | codec->control_data = wm8350; | ||
1701 | |||
1702 | /* Put the codec into reset if it wasn't already */ | ||
1703 | wm8350_clear_bits(wm8350, WM8350_POWER_MGMT_5, WM8350_CODEC_ENA); | ||
1704 | |||
1705 | INIT_DELAYED_WORK(&codec->delayed_work, wm8350_pga_work); | ||
1706 | ret = snd_soc_register_codec(codec); | ||
1707 | if (ret != 0) | ||
1708 | goto err_supply; | ||
1709 | |||
1710 | wm8350_codec = codec; | ||
1711 | |||
1712 | ret = snd_soc_register_dai(&wm8350_dai); | ||
1713 | if (ret != 0) | ||
1714 | goto err_codec; | ||
1715 | return 0; | ||
1716 | |||
1717 | err_codec: | ||
1718 | snd_soc_unregister_codec(codec); | ||
1719 | err_supply: | ||
1720 | regulator_bulk_free(ARRAY_SIZE(priv->supplies), priv->supplies); | ||
1721 | err_priv: | ||
1722 | kfree(priv); | ||
1723 | wm8350_codec = NULL; | ||
1724 | return ret; | ||
1725 | } | 1670 | } |
1726 | 1671 | ||
1727 | static int __devexit wm8350_codec_remove(struct platform_device *pdev) | 1672 | static int __devexit wm8350_remove(struct platform_device *pdev) |
1728 | { | 1673 | { |
1729 | struct wm8350 *wm8350 = platform_get_drvdata(pdev); | 1674 | snd_soc_unregister_codec(&pdev->dev); |
1730 | struct snd_soc_codec *codec = wm8350->codec.codec; | ||
1731 | struct wm8350_data *priv = snd_soc_codec_get_drvdata(codec); | ||
1732 | |||
1733 | snd_soc_unregister_dai(&wm8350_dai); | ||
1734 | snd_soc_unregister_codec(codec); | ||
1735 | regulator_bulk_free(ARRAY_SIZE(priv->supplies), priv->supplies); | ||
1736 | kfree(priv); | ||
1737 | wm8350_codec = NULL; | ||
1738 | return 0; | 1675 | return 0; |
1739 | } | 1676 | } |
1740 | 1677 | ||
@@ -1743,8 +1680,8 @@ static struct platform_driver wm8350_codec_driver = { | |||
1743 | .name = "wm8350-codec", | 1680 | .name = "wm8350-codec", |
1744 | .owner = THIS_MODULE, | 1681 | .owner = THIS_MODULE, |
1745 | }, | 1682 | }, |
1746 | .probe = wm8350_codec_probe, | 1683 | .probe = wm8350_probe, |
1747 | .remove = __devexit_p(wm8350_codec_remove), | 1684 | .remove = __devexit_p(wm8350_remove), |
1748 | }; | 1685 | }; |
1749 | 1686 | ||
1750 | static __init int wm8350_init(void) | 1687 | static __init int wm8350_init(void) |
diff --git a/sound/soc/codecs/wm8350.h b/sound/soc/codecs/wm8350.h index 9ed0467c71db..74108eb82938 100644 --- a/sound/soc/codecs/wm8350.h +++ b/sound/soc/codecs/wm8350.h | |||
@@ -15,9 +15,6 @@ | |||
15 | #include <sound/soc.h> | 15 | #include <sound/soc.h> |
16 | #include <linux/mfd/wm8350/audio.h> | 16 | #include <linux/mfd/wm8350/audio.h> |
17 | 17 | ||
18 | extern struct snd_soc_dai wm8350_dai; | ||
19 | extern struct snd_soc_codec_device soc_codec_dev_wm8350; | ||
20 | |||
21 | enum wm8350_jack { | 18 | enum wm8350_jack { |
22 | WM8350_JDL = 1, | 19 | WM8350_JDL = 1, |
23 | WM8350_JDR = 2, | 20 | WM8350_JDR = 2, |
diff --git a/sound/soc/codecs/wm8400.c b/sound/soc/codecs/wm8400.c index 8f294066b0ed..850299786e02 100644 --- a/sound/soc/codecs/wm8400.c +++ b/sound/soc/codecs/wm8400.c | |||
@@ -65,7 +65,7 @@ static struct regulator_bulk_data power[] = { | |||
65 | 65 | ||
66 | /* codec private data */ | 66 | /* codec private data */ |
67 | struct wm8400_priv { | 67 | struct wm8400_priv { |
68 | struct snd_soc_codec codec; | 68 | struct snd_soc_codec *codec; |
69 | struct wm8400 *wm8400; | 69 | struct wm8400 *wm8400; |
70 | u16 fake_register; | 70 | u16 fake_register; |
71 | unsigned int sysclk; | 71 | unsigned int sysclk; |
@@ -1163,8 +1163,7 @@ static int wm8400_hw_params(struct snd_pcm_substream *substream, | |||
1163 | struct snd_soc_dai *dai) | 1163 | struct snd_soc_dai *dai) |
1164 | { | 1164 | { |
1165 | struct snd_soc_pcm_runtime *rtd = substream->private_data; | 1165 | struct snd_soc_pcm_runtime *rtd = substream->private_data; |
1166 | struct snd_soc_device *socdev = rtd->socdev; | 1166 | struct snd_soc_codec *codec = rtd->codec; |
1167 | struct snd_soc_codec *codec = socdev->card->codec; | ||
1168 | u16 audio1 = wm8400_read(codec, WM8400_AUDIO_INTERFACE_1); | 1167 | u16 audio1 = wm8400_read(codec, WM8400_AUDIO_INTERFACE_1); |
1169 | 1168 | ||
1170 | audio1 &= ~WM8400_AIF_WL_MASK; | 1169 | audio1 &= ~WM8400_AIF_WL_MASK; |
@@ -1332,10 +1331,9 @@ static struct snd_soc_dai_ops wm8400_dai_ops = { | |||
1332 | * 1. ADC/DAC on Primary Interface | 1331 | * 1. ADC/DAC on Primary Interface |
1333 | * 2. ADC on Primary Interface/DAC on secondary | 1332 | * 2. ADC on Primary Interface/DAC on secondary |
1334 | */ | 1333 | */ |
1335 | struct snd_soc_dai wm8400_dai = { | 1334 | static struct snd_soc_dai_driver wm8400_dai = { |
1336 | /* ADC/DAC on primary */ | 1335 | /* ADC/DAC on primary */ |
1337 | .name = "WM8400 ADC/DAC Primary", | 1336 | .name = "wm8400-hifi", |
1338 | .id = 1, | ||
1339 | .playback = { | 1337 | .playback = { |
1340 | .stream_name = "Playback", | 1338 | .stream_name = "Playback", |
1341 | .channels_min = 1, | 1339 | .channels_min = 1, |
@@ -1352,147 +1350,53 @@ struct snd_soc_dai wm8400_dai = { | |||
1352 | }, | 1350 | }, |
1353 | .ops = &wm8400_dai_ops, | 1351 | .ops = &wm8400_dai_ops, |
1354 | }; | 1352 | }; |
1355 | EXPORT_SYMBOL_GPL(wm8400_dai); | ||
1356 | 1353 | ||
1357 | static int wm8400_suspend(struct platform_device *pdev, pm_message_t state) | 1354 | static int wm8400_suspend(struct snd_soc_codec *codec, pm_message_t state) |
1358 | { | 1355 | { |
1359 | struct snd_soc_device *socdev = platform_get_drvdata(pdev); | ||
1360 | struct snd_soc_codec *codec = socdev->card->codec; | ||
1361 | |||
1362 | wm8400_set_bias_level(codec, SND_SOC_BIAS_OFF); | 1356 | wm8400_set_bias_level(codec, SND_SOC_BIAS_OFF); |
1363 | 1357 | ||
1364 | return 0; | 1358 | return 0; |
1365 | } | 1359 | } |
1366 | 1360 | ||
1367 | static int wm8400_resume(struct platform_device *pdev) | 1361 | static int wm8400_resume(struct snd_soc_codec *codec) |
1368 | { | 1362 | { |
1369 | struct snd_soc_device *socdev = platform_get_drvdata(pdev); | ||
1370 | struct snd_soc_codec *codec = socdev->card->codec; | ||
1371 | |||
1372 | wm8400_set_bias_level(codec, SND_SOC_BIAS_STANDBY); | 1363 | wm8400_set_bias_level(codec, SND_SOC_BIAS_STANDBY); |
1373 | 1364 | ||
1374 | return 0; | 1365 | return 0; |
1375 | } | 1366 | } |
1376 | 1367 | ||
1377 | static struct snd_soc_codec *wm8400_codec; | ||
1378 | |||
1379 | static int wm8400_probe(struct platform_device *pdev) | ||
1380 | { | ||
1381 | struct snd_soc_device *socdev = platform_get_drvdata(pdev); | ||
1382 | struct snd_soc_codec *codec; | ||
1383 | int ret; | ||
1384 | |||
1385 | if (!wm8400_codec) { | ||
1386 | dev_err(&pdev->dev, "wm8400 not yet discovered\n"); | ||
1387 | return -ENODEV; | ||
1388 | } | ||
1389 | codec = wm8400_codec; | ||
1390 | |||
1391 | socdev->card->codec = codec; | ||
1392 | |||
1393 | /* register pcms */ | ||
1394 | ret = snd_soc_new_pcms(socdev, SNDRV_DEFAULT_IDX1, SNDRV_DEFAULT_STR1); | ||
1395 | if (ret < 0) { | ||
1396 | dev_err(&pdev->dev, "failed to create pcms\n"); | ||
1397 | goto pcm_err; | ||
1398 | } | ||
1399 | |||
1400 | wm8400_add_controls(codec); | ||
1401 | wm8400_add_widgets(codec); | ||
1402 | |||
1403 | pcm_err: | ||
1404 | return ret; | ||
1405 | } | ||
1406 | |||
1407 | /* power down chip */ | ||
1408 | static int wm8400_remove(struct platform_device *pdev) | ||
1409 | { | ||
1410 | struct snd_soc_device *socdev = platform_get_drvdata(pdev); | ||
1411 | |||
1412 | snd_soc_free_pcms(socdev); | ||
1413 | snd_soc_dapm_free(socdev); | ||
1414 | |||
1415 | return 0; | ||
1416 | } | ||
1417 | |||
1418 | struct snd_soc_codec_device soc_codec_dev_wm8400 = { | ||
1419 | .probe = wm8400_probe, | ||
1420 | .remove = wm8400_remove, | ||
1421 | .suspend = wm8400_suspend, | ||
1422 | .resume = wm8400_resume, | ||
1423 | }; | ||
1424 | |||
1425 | static void wm8400_probe_deferred(struct work_struct *work) | 1368 | static void wm8400_probe_deferred(struct work_struct *work) |
1426 | { | 1369 | { |
1427 | struct wm8400_priv *priv = container_of(work, struct wm8400_priv, | 1370 | struct wm8400_priv *priv = container_of(work, struct wm8400_priv, |
1428 | work); | 1371 | work); |
1429 | struct snd_soc_codec *codec = &priv->codec; | 1372 | struct snd_soc_codec *codec = priv->codec; |
1430 | int ret; | ||
1431 | 1373 | ||
1432 | /* charge output caps */ | 1374 | /* charge output caps */ |
1433 | wm8400_set_bias_level(codec, SND_SOC_BIAS_STANDBY); | 1375 | wm8400_set_bias_level(codec, SND_SOC_BIAS_STANDBY); |
1434 | |||
1435 | /* We're done, tell the subsystem. */ | ||
1436 | ret = snd_soc_register_codec(codec); | ||
1437 | if (ret != 0) { | ||
1438 | dev_err(priv->wm8400->dev, | ||
1439 | "Failed to register codec: %d\n", ret); | ||
1440 | goto err; | ||
1441 | } | ||
1442 | |||
1443 | ret = snd_soc_register_dai(&wm8400_dai); | ||
1444 | if (ret != 0) { | ||
1445 | dev_err(priv->wm8400->dev, | ||
1446 | "Failed to register DAI: %d\n", ret); | ||
1447 | goto err_codec; | ||
1448 | } | ||
1449 | |||
1450 | return; | ||
1451 | |||
1452 | err_codec: | ||
1453 | snd_soc_unregister_codec(codec); | ||
1454 | err: | ||
1455 | wm8400_set_bias_level(codec, SND_SOC_BIAS_OFF); | ||
1456 | } | 1376 | } |
1457 | 1377 | ||
1458 | static int wm8400_codec_probe(struct platform_device *dev) | 1378 | static int wm8400_codec_probe(struct snd_soc_codec *codec) |
1459 | { | 1379 | { |
1380 | struct wm8400 *wm8400 = dev_get_platdata(codec->dev); | ||
1460 | struct wm8400_priv *priv; | 1381 | struct wm8400_priv *priv; |
1461 | int ret; | 1382 | int ret; |
1462 | u16 reg; | 1383 | u16 reg; |
1463 | struct snd_soc_codec *codec; | ||
1464 | 1384 | ||
1465 | priv = kzalloc(sizeof(struct wm8400_priv), GFP_KERNEL); | 1385 | priv = kzalloc(sizeof(struct wm8400_priv), GFP_KERNEL); |
1466 | if (priv == NULL) | 1386 | if (priv == NULL) |
1467 | return -ENOMEM; | 1387 | return -ENOMEM; |
1468 | 1388 | ||
1469 | codec = &priv->codec; | ||
1470 | snd_soc_codec_set_drvdata(codec, priv); | 1389 | snd_soc_codec_set_drvdata(codec, priv); |
1471 | codec->control_data = dev_get_drvdata(&dev->dev); | 1390 | codec->control_data = priv->wm8400 = wm8400; |
1472 | priv->wm8400 = dev_get_drvdata(&dev->dev); | 1391 | priv->codec = codec; |
1473 | 1392 | ||
1474 | ret = regulator_bulk_get(priv->wm8400->dev, | 1393 | ret = regulator_bulk_get(wm8400->dev, |
1475 | ARRAY_SIZE(power), &power[0]); | 1394 | ARRAY_SIZE(power), &power[0]); |
1476 | if (ret != 0) { | 1395 | if (ret != 0) { |
1477 | dev_err(&dev->dev, "Failed to get regulators: %d\n", ret); | 1396 | dev_err(codec->dev, "Failed to get regulators: %d\n", ret); |
1478 | goto err; | 1397 | goto err; |
1479 | } | 1398 | } |
1480 | 1399 | ||
1481 | codec->dev = &dev->dev; | ||
1482 | wm8400_dai.dev = &dev->dev; | ||
1483 | |||
1484 | codec->name = "WM8400"; | ||
1485 | codec->owner = THIS_MODULE; | ||
1486 | codec->read = wm8400_read; | ||
1487 | codec->write = wm8400_write; | ||
1488 | codec->bias_level = SND_SOC_BIAS_OFF; | ||
1489 | codec->set_bias_level = wm8400_set_bias_level; | ||
1490 | codec->dai = &wm8400_dai; | ||
1491 | codec->num_dai = 1; | ||
1492 | codec->reg_cache_size = WM8400_REGISTER_COUNT; | ||
1493 | mutex_init(&codec->mutex); | ||
1494 | INIT_LIST_HEAD(&codec->dapm_widgets); | ||
1495 | INIT_LIST_HEAD(&codec->dapm_paths); | ||
1496 | INIT_WORK(&priv->work, wm8400_probe_deferred); | 1400 | INIT_WORK(&priv->work, wm8400_probe_deferred); |
1497 | 1401 | ||
1498 | wm8400_codec_reset(codec); | 1402 | wm8400_codec_reset(codec); |
@@ -1511,65 +1415,78 @@ static int wm8400_codec_probe(struct platform_device *dev) | |||
1511 | wm8400_write(codec, WM8400_LEFT_OUTPUT_VOLUME, 0x50 | (1<<8)); | 1415 | wm8400_write(codec, WM8400_LEFT_OUTPUT_VOLUME, 0x50 | (1<<8)); |
1512 | wm8400_write(codec, WM8400_RIGHT_OUTPUT_VOLUME, 0x50 | (1<<8)); | 1416 | wm8400_write(codec, WM8400_RIGHT_OUTPUT_VOLUME, 0x50 | (1<<8)); |
1513 | 1417 | ||
1514 | wm8400_codec = codec; | ||
1515 | |||
1516 | if (!schedule_work(&priv->work)) { | 1418 | if (!schedule_work(&priv->work)) { |
1517 | ret = -EINVAL; | 1419 | ret = -EINVAL; |
1518 | goto err_regulator; | 1420 | goto err_regulator; |
1519 | } | 1421 | } |
1520 | 1422 | wm8400_add_controls(codec); | |
1423 | wm8400_add_widgets(codec); | ||
1521 | return 0; | 1424 | return 0; |
1522 | 1425 | ||
1523 | err_regulator: | 1426 | err_regulator: |
1524 | wm8400_codec = NULL; | ||
1525 | regulator_bulk_free(ARRAY_SIZE(power), power); | 1427 | regulator_bulk_free(ARRAY_SIZE(power), power); |
1526 | err: | 1428 | err: |
1527 | kfree(priv); | 1429 | kfree(priv); |
1528 | return ret; | 1430 | return ret; |
1529 | } | 1431 | } |
1530 | 1432 | ||
1531 | static int __exit wm8400_codec_remove(struct platform_device *dev) | 1433 | static int wm8400_codec_remove(struct snd_soc_codec *codec) |
1532 | { | 1434 | { |
1533 | struct wm8400_priv *priv = snd_soc_codec_get_drvdata(wm8400_codec); | 1435 | struct wm8400_priv *priv = snd_soc_codec_get_drvdata(codec); |
1534 | u16 reg; | 1436 | u16 reg; |
1535 | 1437 | ||
1536 | snd_soc_unregister_dai(&wm8400_dai); | 1438 | reg = wm8400_read(codec, WM8400_POWER_MANAGEMENT_1); |
1537 | snd_soc_unregister_codec(wm8400_codec); | 1439 | wm8400_write(codec, WM8400_POWER_MANAGEMENT_1, |
1538 | |||
1539 | reg = wm8400_read(wm8400_codec, WM8400_POWER_MANAGEMENT_1); | ||
1540 | wm8400_write(wm8400_codec, WM8400_POWER_MANAGEMENT_1, | ||
1541 | reg & (~WM8400_CODEC_ENA)); | 1440 | reg & (~WM8400_CODEC_ENA)); |
1542 | 1441 | ||
1543 | regulator_bulk_free(ARRAY_SIZE(power), power); | 1442 | regulator_bulk_free(ARRAY_SIZE(power), power); |
1544 | kfree(priv); | 1443 | kfree(priv); |
1545 | 1444 | ||
1546 | wm8400_codec = NULL; | 1445 | return 0; |
1446 | } | ||
1447 | |||
1448 | static struct snd_soc_codec_driver soc_codec_dev_wm8400 = { | ||
1449 | .probe = wm8400_codec_probe, | ||
1450 | .remove = wm8400_codec_remove, | ||
1451 | .suspend = wm8400_suspend, | ||
1452 | .resume = wm8400_resume, | ||
1453 | .read = wm8400_read, | ||
1454 | .write = wm8400_write, | ||
1455 | .set_bias_level = wm8400_set_bias_level, | ||
1456 | }; | ||
1457 | |||
1458 | static int __devinit wm8400_probe(struct platform_device *pdev) | ||
1459 | { | ||
1460 | return snd_soc_register_codec(&pdev->dev, &soc_codec_dev_wm8400, | ||
1461 | &wm8400_dai, 1); | ||
1462 | } | ||
1547 | 1463 | ||
1464 | static int __devexit wm8400_remove(struct platform_device *pdev) | ||
1465 | { | ||
1466 | snd_soc_unregister_codec(&pdev->dev); | ||
1548 | return 0; | 1467 | return 0; |
1549 | } | 1468 | } |
1550 | 1469 | ||
1551 | static struct platform_driver wm8400_codec_driver = { | 1470 | static struct platform_driver wm8400_codec_driver = { |
1552 | .driver = { | 1471 | .driver = { |
1553 | .name = "wm8400-codec", | 1472 | .name = "wm8400-codec", |
1554 | .owner = THIS_MODULE, | 1473 | .owner = THIS_MODULE, |
1555 | }, | 1474 | }, |
1556 | .probe = wm8400_codec_probe, | 1475 | .probe = wm8400_probe, |
1557 | .remove = __exit_p(wm8400_codec_remove), | 1476 | .remove = __devexit_p(wm8400_remove), |
1558 | }; | 1477 | }; |
1559 | 1478 | ||
1560 | static int __init wm8400_codec_init(void) | 1479 | static __init int wm8400_init(void) |
1561 | { | 1480 | { |
1562 | return platform_driver_register(&wm8400_codec_driver); | 1481 | return platform_driver_register(&wm8400_codec_driver); |
1563 | } | 1482 | } |
1564 | module_init(wm8400_codec_init); | 1483 | module_init(wm8400_init); |
1565 | 1484 | ||
1566 | static void __exit wm8400_codec_exit(void) | 1485 | static __exit void wm8400_exit(void) |
1567 | { | 1486 | { |
1568 | platform_driver_unregister(&wm8400_codec_driver); | 1487 | platform_driver_unregister(&wm8400_codec_driver); |
1569 | } | 1488 | } |
1570 | module_exit(wm8400_codec_exit); | 1489 | module_exit(wm8400_exit); |
1571 | |||
1572 | EXPORT_SYMBOL_GPL(soc_codec_dev_wm8400); | ||
1573 | 1490 | ||
1574 | MODULE_DESCRIPTION("ASoC WM8400 driver"); | 1491 | MODULE_DESCRIPTION("ASoC WM8400 driver"); |
1575 | MODULE_AUTHOR("Mark Brown"); | 1492 | MODULE_AUTHOR("Mark Brown"); |
diff --git a/sound/soc/codecs/wm8400.h b/sound/soc/codecs/wm8400.h index 79c5934d4776..521adb193870 100644 --- a/sound/soc/codecs/wm8400.h +++ b/sound/soc/codecs/wm8400.h | |||
@@ -56,7 +56,4 @@ | |||
56 | #define WM8400_BCLK_DIV_44 (0xE << 1) | 56 | #define WM8400_BCLK_DIV_44 (0xE << 1) |
57 | #define WM8400_BCLK_DIV_48 (0xF << 1) | 57 | #define WM8400_BCLK_DIV_48 (0xF << 1) |
58 | 58 | ||
59 | extern struct snd_soc_dai wm8400_dai; | ||
60 | extern struct snd_soc_codec_device soc_codec_dev_wm8400; | ||
61 | |||
62 | #endif | 59 | #endif |
diff --git a/sound/soc/codecs/wm8510.c b/sound/soc/codecs/wm8510.c index 0f7bcb61071a..d00da2001a12 100644 --- a/sound/soc/codecs/wm8510.c +++ b/sound/soc/codecs/wm8510.c | |||
@@ -29,10 +29,6 @@ | |||
29 | 29 | ||
30 | #include "wm8510.h" | 30 | #include "wm8510.h" |
31 | 31 | ||
32 | #define WM8510_VERSION "0.6" | ||
33 | |||
34 | struct snd_soc_codec_device soc_codec_dev_wm8510; | ||
35 | |||
36 | /* | 32 | /* |
37 | * wm8510 register cache | 33 | * wm8510 register cache |
38 | * We can't read the WM8510 register space when we are | 34 | * We can't read the WM8510 register space when we are |
@@ -61,6 +57,11 @@ static const u16 wm8510_reg[WM8510_CACHEREGNUM] = { | |||
61 | 57 | ||
62 | #define wm8510_reset(c) snd_soc_write(c, WM8510_RESET, 0) | 58 | #define wm8510_reset(c) snd_soc_write(c, WM8510_RESET, 0) |
63 | 59 | ||
60 | /* codec private data */ | ||
61 | struct wm8510_priv { | ||
62 | enum snd_soc_control_type control_type; | ||
63 | }; | ||
64 | |||
64 | static const char *wm8510_companding[] = { "Off", "NC", "u-law", "A-law" }; | 65 | static const char *wm8510_companding[] = { "Off", "NC", "u-law", "A-law" }; |
65 | static const char *wm8510_deemp[] = { "None", "32kHz", "44.1kHz", "48kHz" }; | 66 | static const char *wm8510_deemp[] = { "None", "32kHz", "44.1kHz", "48kHz" }; |
66 | static const char *wm8510_alc[] = { "ALC", "Limiter" }; | 67 | static const char *wm8510_alc[] = { "ALC", "Limiter" }; |
@@ -403,8 +404,7 @@ static int wm8510_pcm_hw_params(struct snd_pcm_substream *substream, | |||
403 | struct snd_soc_dai *dai) | 404 | struct snd_soc_dai *dai) |
404 | { | 405 | { |
405 | struct snd_soc_pcm_runtime *rtd = substream->private_data; | 406 | struct snd_soc_pcm_runtime *rtd = substream->private_data; |
406 | struct snd_soc_device *socdev = rtd->socdev; | 407 | struct snd_soc_codec *codec = rtd->codec; |
407 | struct snd_soc_codec *codec = socdev->card->codec; | ||
408 | u16 iface = snd_soc_read(codec, WM8510_IFACE) & 0x19f; | 408 | u16 iface = snd_soc_read(codec, WM8510_IFACE) & 0x19f; |
409 | u16 adn = snd_soc_read(codec, WM8510_ADD) & 0x1f1; | 409 | u16 adn = snd_soc_read(codec, WM8510_ADD) & 0x1f1; |
410 | 410 | ||
@@ -514,8 +514,8 @@ static struct snd_soc_dai_ops wm8510_dai_ops = { | |||
514 | .set_pll = wm8510_set_dai_pll, | 514 | .set_pll = wm8510_set_dai_pll, |
515 | }; | 515 | }; |
516 | 516 | ||
517 | struct snd_soc_dai wm8510_dai = { | 517 | static struct snd_soc_dai_driver wm8510_dai = { |
518 | .name = "WM8510 HiFi", | 518 | .name = "wm8510-hifi", |
519 | .playback = { | 519 | .playback = { |
520 | .stream_name = "Playback", | 520 | .stream_name = "Playback", |
521 | .channels_min = 2, | 521 | .channels_min = 2, |
@@ -531,21 +531,15 @@ struct snd_soc_dai wm8510_dai = { | |||
531 | .ops = &wm8510_dai_ops, | 531 | .ops = &wm8510_dai_ops, |
532 | .symmetric_rates = 1, | 532 | .symmetric_rates = 1, |
533 | }; | 533 | }; |
534 | EXPORT_SYMBOL_GPL(wm8510_dai); | ||
535 | 534 | ||
536 | static int wm8510_suspend(struct platform_device *pdev, pm_message_t state) | 535 | static int wm8510_suspend(struct snd_soc_codec *codec, pm_message_t state) |
537 | { | 536 | { |
538 | struct snd_soc_device *socdev = platform_get_drvdata(pdev); | ||
539 | struct snd_soc_codec *codec = socdev->card->codec; | ||
540 | |||
541 | wm8510_set_bias_level(codec, SND_SOC_BIAS_OFF); | 537 | wm8510_set_bias_level(codec, SND_SOC_BIAS_OFF); |
542 | return 0; | 538 | return 0; |
543 | } | 539 | } |
544 | 540 | ||
545 | static int wm8510_resume(struct platform_device *pdev) | 541 | static int wm8510_resume(struct snd_soc_codec *codec) |
546 | { | 542 | { |
547 | struct snd_soc_device *socdev = platform_get_drvdata(pdev); | ||
548 | struct snd_soc_codec *codec = socdev->card->codec; | ||
549 | int i; | 543 | int i; |
550 | u8 data[2]; | 544 | u8 data[2]; |
551 | u16 *cache = codec->reg_cache; | 545 | u16 *cache = codec->reg_cache; |
@@ -561,43 +555,19 @@ static int wm8510_resume(struct platform_device *pdev) | |||
561 | return 0; | 555 | return 0; |
562 | } | 556 | } |
563 | 557 | ||
564 | /* | 558 | static int wm8510_probe(struct snd_soc_codec *codec) |
565 | * initialise the WM8510 driver | ||
566 | * register the mixer and dsp interfaces with the kernel | ||
567 | */ | ||
568 | static int wm8510_init(struct snd_soc_device *socdev, | ||
569 | enum snd_soc_control_type control) | ||
570 | { | 559 | { |
571 | struct snd_soc_codec *codec = socdev->card->codec; | 560 | struct wm8510_priv *wm8510 = snd_soc_codec_get_drvdata(codec); |
572 | int ret = 0; | 561 | int ret; |
573 | |||
574 | codec->name = "WM8510"; | ||
575 | codec->owner = THIS_MODULE; | ||
576 | codec->set_bias_level = wm8510_set_bias_level; | ||
577 | codec->dai = &wm8510_dai; | ||
578 | codec->num_dai = 1; | ||
579 | codec->reg_cache_size = ARRAY_SIZE(wm8510_reg); | ||
580 | codec->reg_cache = kmemdup(wm8510_reg, sizeof(wm8510_reg), GFP_KERNEL); | ||
581 | |||
582 | if (codec->reg_cache == NULL) | ||
583 | return -ENOMEM; | ||
584 | 562 | ||
585 | ret = snd_soc_codec_set_cache_io(codec, 7, 9, control); | 563 | ret = snd_soc_codec_set_cache_io(codec, 7, 9, wm8510->control_type); |
586 | if (ret < 0) { | 564 | if (ret < 0) { |
587 | printk(KERN_ERR "wm8510: failed to set cache I/O: %d\n", | 565 | printk(KERN_ERR "wm8510: failed to set cache I/O: %d\n", ret); |
588 | ret); | 566 | return ret; |
589 | goto err; | ||
590 | } | 567 | } |
591 | 568 | ||
592 | wm8510_reset(codec); | 569 | wm8510_reset(codec); |
593 | 570 | ||
594 | /* register pcms */ | ||
595 | ret = snd_soc_new_pcms(socdev, SNDRV_DEFAULT_IDX1, SNDRV_DEFAULT_STR1); | ||
596 | if (ret < 0) { | ||
597 | printk(KERN_ERR "wm8510: failed to create pcms\n"); | ||
598 | goto err; | ||
599 | } | ||
600 | |||
601 | /* power on device */ | 571 | /* power on device */ |
602 | codec->bias_level = SND_SOC_BIAS_OFF; | 572 | codec->bias_level = SND_SOC_BIAS_OFF; |
603 | wm8510_set_bias_level(codec, SND_SOC_BIAS_STANDBY); | 573 | wm8510_set_bias_level(codec, SND_SOC_BIAS_STANDBY); |
@@ -606,119 +576,52 @@ static int wm8510_init(struct snd_soc_device *socdev, | |||
606 | wm8510_add_widgets(codec); | 576 | wm8510_add_widgets(codec); |
607 | 577 | ||
608 | return ret; | 578 | return ret; |
609 | |||
610 | err: | ||
611 | kfree(codec->reg_cache); | ||
612 | return ret; | ||
613 | } | 579 | } |
614 | 580 | ||
615 | static struct snd_soc_device *wm8510_socdev; | 581 | /* power down chip */ |
616 | 582 | static int wm8510_remove(struct snd_soc_codec *codec) | |
617 | #if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE) | ||
618 | |||
619 | /* | ||
620 | * WM8510 2 wire address is 0x1a | ||
621 | */ | ||
622 | |||
623 | static int wm8510_i2c_probe(struct i2c_client *i2c, | ||
624 | const struct i2c_device_id *id) | ||
625 | { | 583 | { |
626 | struct snd_soc_device *socdev = wm8510_socdev; | 584 | struct wm8510_priv *wm8510 = snd_soc_codec_get_drvdata(codec); |
627 | struct snd_soc_codec *codec = socdev->card->codec; | ||
628 | int ret; | ||
629 | |||
630 | i2c_set_clientdata(i2c, codec); | ||
631 | codec->control_data = i2c; | ||
632 | 585 | ||
633 | ret = wm8510_init(socdev, SND_SOC_I2C); | 586 | wm8510_set_bias_level(codec, SND_SOC_BIAS_OFF); |
634 | if (ret < 0) | 587 | kfree(wm8510); |
635 | pr_err("failed to initialise WM8510\n"); | ||
636 | |||
637 | return ret; | ||
638 | } | ||
639 | |||
640 | static int wm8510_i2c_remove(struct i2c_client *client) | ||
641 | { | ||
642 | struct snd_soc_codec *codec = i2c_get_clientdata(client); | ||
643 | kfree(codec->reg_cache); | ||
644 | return 0; | 588 | return 0; |
645 | } | 589 | } |
646 | 590 | ||
647 | static const struct i2c_device_id wm8510_i2c_id[] = { | 591 | static struct snd_soc_codec_driver soc_codec_dev_wm8510 = { |
648 | { "wm8510", 0 }, | 592 | .probe = wm8510_probe, |
649 | { } | 593 | .remove = wm8510_remove, |
650 | }; | 594 | .suspend = wm8510_suspend, |
651 | MODULE_DEVICE_TABLE(i2c, wm8510_i2c_id); | 595 | .resume = wm8510_resume, |
652 | 596 | .set_bias_level = wm8510_set_bias_level, | |
653 | static struct i2c_driver wm8510_i2c_driver = { | 597 | .reg_cache_size = ARRAY_SIZE(wm8510_reg), |
654 | .driver = { | 598 | .reg_word_size = sizeof(u16), |
655 | .name = "WM8510 I2C Codec", | 599 | .reg_cache_default =wm8510_reg, |
656 | .owner = THIS_MODULE, | ||
657 | }, | ||
658 | .probe = wm8510_i2c_probe, | ||
659 | .remove = wm8510_i2c_remove, | ||
660 | .id_table = wm8510_i2c_id, | ||
661 | }; | 600 | }; |
662 | 601 | ||
663 | static int wm8510_add_i2c_device(struct platform_device *pdev, | ||
664 | const struct wm8510_setup_data *setup) | ||
665 | { | ||
666 | struct i2c_board_info info; | ||
667 | struct i2c_adapter *adapter; | ||
668 | struct i2c_client *client; | ||
669 | int ret; | ||
670 | |||
671 | ret = i2c_add_driver(&wm8510_i2c_driver); | ||
672 | if (ret != 0) { | ||
673 | dev_err(&pdev->dev, "can't add i2c driver\n"); | ||
674 | return ret; | ||
675 | } | ||
676 | |||
677 | memset(&info, 0, sizeof(struct i2c_board_info)); | ||
678 | info.addr = setup->i2c_address; | ||
679 | strlcpy(info.type, "wm8510", I2C_NAME_SIZE); | ||
680 | |||
681 | adapter = i2c_get_adapter(setup->i2c_bus); | ||
682 | if (!adapter) { | ||
683 | dev_err(&pdev->dev, "can't get i2c adapter %d\n", | ||
684 | setup->i2c_bus); | ||
685 | goto err_driver; | ||
686 | } | ||
687 | |||
688 | client = i2c_new_device(adapter, &info); | ||
689 | i2c_put_adapter(adapter); | ||
690 | if (!client) { | ||
691 | dev_err(&pdev->dev, "can't add i2c device at 0x%x\n", | ||
692 | (unsigned int)info.addr); | ||
693 | goto err_driver; | ||
694 | } | ||
695 | |||
696 | return 0; | ||
697 | |||
698 | err_driver: | ||
699 | i2c_del_driver(&wm8510_i2c_driver); | ||
700 | return -ENODEV; | ||
701 | } | ||
702 | #endif | ||
703 | |||
704 | #if defined(CONFIG_SPI_MASTER) | 602 | #if defined(CONFIG_SPI_MASTER) |
705 | static int __devinit wm8510_spi_probe(struct spi_device *spi) | 603 | static int __devinit wm8510_spi_probe(struct spi_device *spi) |
706 | { | 604 | { |
707 | struct snd_soc_device *socdev = wm8510_socdev; | 605 | struct wm8510_priv *wm8510; |
708 | struct snd_soc_codec *codec = socdev->card->codec; | ||
709 | int ret; | 606 | int ret; |
710 | 607 | ||
711 | codec->control_data = spi; | 608 | wm8510 = kzalloc(sizeof(struct wm8510_priv), GFP_KERNEL); |
609 | if (wm8510 == NULL) | ||
610 | return -ENOMEM; | ||
712 | 611 | ||
713 | ret = wm8510_init(socdev, SND_SOC_SPI); | 612 | wm8510->control_type = SND_SOC_SPI; |
714 | if (ret < 0) | 613 | spi_set_drvdata(spi, wm8510); |
715 | dev_err(&spi->dev, "failed to initialise WM8510\n"); | ||
716 | 614 | ||
615 | ret = snd_soc_register_codec(&spi->dev, | ||
616 | &soc_codec_dev_wm8510, &wm8510_dai, 1); | ||
617 | if (ret < 0) | ||
618 | kfree(wm8510); | ||
717 | return ret; | 619 | return ret; |
718 | } | 620 | } |
719 | 621 | ||
720 | static int __devexit wm8510_spi_remove(struct spi_device *spi) | 622 | static int __devexit wm8510_spi_remove(struct spi_device *spi) |
721 | { | 623 | { |
624 | snd_soc_unregister_codec(&spi->dev); | ||
722 | return 0; | 625 | return 0; |
723 | } | 626 | } |
724 | 627 | ||
@@ -733,84 +636,79 @@ static struct spi_driver wm8510_spi_driver = { | |||
733 | }; | 636 | }; |
734 | #endif /* CONFIG_SPI_MASTER */ | 637 | #endif /* CONFIG_SPI_MASTER */ |
735 | 638 | ||
736 | static int wm8510_probe(struct platform_device *pdev) | 639 | #if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE) |
640 | static __devinit int wm8510_i2c_probe(struct i2c_client *i2c, | ||
641 | const struct i2c_device_id *id) | ||
737 | { | 642 | { |
738 | struct snd_soc_device *socdev = platform_get_drvdata(pdev); | 643 | struct wm8510_priv *wm8510; |
739 | struct wm8510_setup_data *setup; | 644 | int ret; |
740 | struct snd_soc_codec *codec; | ||
741 | int ret = 0; | ||
742 | |||
743 | pr_info("WM8510 Audio Codec %s", WM8510_VERSION); | ||
744 | 645 | ||
745 | setup = socdev->codec_data; | 646 | wm8510 = kzalloc(sizeof(struct wm8510_priv), GFP_KERNEL); |
746 | codec = kzalloc(sizeof(struct snd_soc_codec), GFP_KERNEL); | 647 | if (wm8510 == NULL) |
747 | if (codec == NULL) | ||
748 | return -ENOMEM; | 648 | return -ENOMEM; |
749 | 649 | ||
750 | socdev->card->codec = codec; | 650 | i2c_set_clientdata(i2c, wm8510); |
751 | mutex_init(&codec->mutex); | 651 | wm8510->control_type = SND_SOC_I2C; |
752 | INIT_LIST_HEAD(&codec->dapm_widgets); | ||
753 | INIT_LIST_HEAD(&codec->dapm_paths); | ||
754 | 652 | ||
755 | wm8510_socdev = socdev; | 653 | ret = snd_soc_register_codec(&i2c->dev, |
756 | #if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE) | 654 | &soc_codec_dev_wm8510, &wm8510_dai, 1); |
757 | if (setup->i2c_address) { | 655 | if (ret < 0) |
758 | ret = wm8510_add_i2c_device(pdev, setup); | 656 | kfree(wm8510); |
759 | } | ||
760 | #endif | ||
761 | #if defined(CONFIG_SPI_MASTER) | ||
762 | if (setup->spi) { | ||
763 | ret = spi_register_driver(&wm8510_spi_driver); | ||
764 | if (ret != 0) | ||
765 | printk(KERN_ERR "can't add spi driver"); | ||
766 | } | ||
767 | #endif | ||
768 | |||
769 | if (ret != 0) | ||
770 | kfree(codec); | ||
771 | return ret; | 657 | return ret; |
772 | } | 658 | } |
773 | 659 | ||
774 | /* power down chip */ | 660 | static __devexit int wm8510_i2c_remove(struct i2c_client *client) |
775 | static int wm8510_remove(struct platform_device *pdev) | ||
776 | { | 661 | { |
777 | struct snd_soc_device *socdev = platform_get_drvdata(pdev); | 662 | snd_soc_unregister_codec(&client->dev); |
778 | struct snd_soc_codec *codec = socdev->card->codec; | ||
779 | |||
780 | if (codec->control_data) | ||
781 | wm8510_set_bias_level(codec, SND_SOC_BIAS_OFF); | ||
782 | |||
783 | snd_soc_free_pcms(socdev); | ||
784 | snd_soc_dapm_free(socdev); | ||
785 | #if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE) | ||
786 | i2c_unregister_device(codec->control_data); | ||
787 | i2c_del_driver(&wm8510_i2c_driver); | ||
788 | #endif | ||
789 | #if defined(CONFIG_SPI_MASTER) | ||
790 | spi_unregister_driver(&wm8510_spi_driver); | ||
791 | #endif | ||
792 | kfree(codec); | ||
793 | |||
794 | return 0; | 663 | return 0; |
795 | } | 664 | } |
796 | 665 | ||
797 | struct snd_soc_codec_device soc_codec_dev_wm8510 = { | 666 | static const struct i2c_device_id wm8510_i2c_id[] = { |
798 | .probe = wm8510_probe, | 667 | { "wm8510", 0 }, |
799 | .remove = wm8510_remove, | 668 | { } |
800 | .suspend = wm8510_suspend, | 669 | }; |
801 | .resume = wm8510_resume, | 670 | MODULE_DEVICE_TABLE(i2c, wm8510_i2c_id); |
671 | |||
672 | static struct i2c_driver wm8510_i2c_driver = { | ||
673 | .driver = { | ||
674 | .name = "wm8510-codec", | ||
675 | .owner = THIS_MODULE, | ||
676 | }, | ||
677 | .probe = wm8510_i2c_probe, | ||
678 | .remove = __devexit_p(wm8510_i2c_remove), | ||
679 | .id_table = wm8510_i2c_id, | ||
802 | }; | 680 | }; |
803 | EXPORT_SYMBOL_GPL(soc_codec_dev_wm8510); | 681 | #endif |
804 | 682 | ||
805 | static int __init wm8510_modinit(void) | 683 | static int __init wm8510_modinit(void) |
806 | { | 684 | { |
807 | return snd_soc_register_dai(&wm8510_dai); | 685 | int ret = 0; |
686 | #if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE) | ||
687 | ret = i2c_add_driver(&wm8510_i2c_driver); | ||
688 | if (ret != 0) { | ||
689 | printk(KERN_ERR "Failed to register WM8510 I2C driver: %d\n", | ||
690 | ret); | ||
691 | } | ||
692 | #endif | ||
693 | #if defined(CONFIG_SPI_MASTER) | ||
694 | ret = spi_register_driver(&wm8510_spi_driver); | ||
695 | if (ret != 0) { | ||
696 | printk(KERN_ERR "Failed to register WM8510 SPI driver: %d\n", | ||
697 | ret); | ||
698 | } | ||
699 | #endif | ||
700 | return ret; | ||
808 | } | 701 | } |
809 | module_init(wm8510_modinit); | 702 | module_init(wm8510_modinit); |
810 | 703 | ||
811 | static void __exit wm8510_exit(void) | 704 | static void __exit wm8510_exit(void) |
812 | { | 705 | { |
813 | snd_soc_unregister_dai(&wm8510_dai); | 706 | #if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE) |
707 | i2c_del_driver(&wm8510_i2c_driver); | ||
708 | #endif | ||
709 | #if defined(CONFIG_SPI_MASTER) | ||
710 | spi_unregister_driver(&wm8510_spi_driver); | ||
711 | #endif | ||
814 | } | 712 | } |
815 | module_exit(wm8510_exit); | 713 | module_exit(wm8510_exit); |
816 | 714 | ||
diff --git a/sound/soc/codecs/wm8510.h b/sound/soc/codecs/wm8510.h index bdefcf5c69ff..b3e26ed9f2d0 100644 --- a/sound/soc/codecs/wm8510.h +++ b/sound/soc/codecs/wm8510.h | |||
@@ -99,7 +99,4 @@ struct wm8510_setup_data { | |||
99 | unsigned short i2c_address; | 99 | unsigned short i2c_address; |
100 | }; | 100 | }; |
101 | 101 | ||
102 | extern struct snd_soc_dai wm8510_dai; | ||
103 | extern struct snd_soc_codec_device soc_codec_dev_wm8510; | ||
104 | |||
105 | #endif | 102 | #endif |
diff --git a/sound/soc/codecs/wm8523.c b/sound/soc/codecs/wm8523.c index 0ad039b4adf5..712ef7c76f90 100644 --- a/sound/soc/codecs/wm8523.c +++ b/sound/soc/codecs/wm8523.c | |||
@@ -30,9 +30,6 @@ | |||
30 | 30 | ||
31 | #include "wm8523.h" | 31 | #include "wm8523.h" |
32 | 32 | ||
33 | static struct snd_soc_codec *wm8523_codec; | ||
34 | struct snd_soc_codec_device soc_codec_dev_wm8523; | ||
35 | |||
36 | #define WM8523_NUM_SUPPLIES 2 | 33 | #define WM8523_NUM_SUPPLIES 2 |
37 | static const char *wm8523_supply_names[WM8523_NUM_SUPPLIES] = { | 34 | static const char *wm8523_supply_names[WM8523_NUM_SUPPLIES] = { |
38 | "AVDD", | 35 | "AVDD", |
@@ -43,7 +40,7 @@ static const char *wm8523_supply_names[WM8523_NUM_SUPPLIES] = { | |||
43 | 40 | ||
44 | /* codec private data */ | 41 | /* codec private data */ |
45 | struct wm8523_priv { | 42 | struct wm8523_priv { |
46 | struct snd_soc_codec codec; | 43 | enum snd_soc_control_type control_type; |
47 | u16 reg_cache[WM8523_REGISTER_COUNT]; | 44 | u16 reg_cache[WM8523_REGISTER_COUNT]; |
48 | struct regulator_bulk_data supplies[WM8523_NUM_SUPPLIES]; | 45 | struct regulator_bulk_data supplies[WM8523_NUM_SUPPLIES]; |
49 | unsigned int sysclk; | 46 | unsigned int sysclk; |
@@ -162,8 +159,7 @@ static int wm8523_hw_params(struct snd_pcm_substream *substream, | |||
162 | struct snd_soc_dai *dai) | 159 | struct snd_soc_dai *dai) |
163 | { | 160 | { |
164 | struct snd_soc_pcm_runtime *rtd = substream->private_data; | 161 | struct snd_soc_pcm_runtime *rtd = substream->private_data; |
165 | struct snd_soc_device *socdev = rtd->socdev; | 162 | struct snd_soc_codec *codec = rtd->codec; |
166 | struct snd_soc_codec *codec = socdev->card->codec; | ||
167 | struct wm8523_priv *wm8523 = snd_soc_codec_get_drvdata(codec); | 163 | struct wm8523_priv *wm8523 = snd_soc_codec_get_drvdata(codec); |
168 | int i; | 164 | int i; |
169 | u16 aifctrl1 = snd_soc_read(codec, WM8523_AIF_CTRL1); | 165 | u16 aifctrl1 = snd_soc_read(codec, WM8523_AIF_CTRL1); |
@@ -387,8 +383,8 @@ static struct snd_soc_dai_ops wm8523_dai_ops = { | |||
387 | .set_fmt = wm8523_set_dai_fmt, | 383 | .set_fmt = wm8523_set_dai_fmt, |
388 | }; | 384 | }; |
389 | 385 | ||
390 | struct snd_soc_dai wm8523_dai = { | 386 | static struct snd_soc_dai_driver wm8523_dai = { |
391 | .name = "WM8523", | 387 | .name = "wm8523-hifi", |
392 | .playback = { | 388 | .playback = { |
393 | .stream_name = "Playback", | 389 | .stream_name = "Playback", |
394 | .channels_min = 2, /* Mono modes not yet supported */ | 390 | .channels_min = 2, /* Mono modes not yet supported */ |
@@ -398,25 +394,17 @@ struct snd_soc_dai wm8523_dai = { | |||
398 | }, | 394 | }, |
399 | .ops = &wm8523_dai_ops, | 395 | .ops = &wm8523_dai_ops, |
400 | }; | 396 | }; |
401 | EXPORT_SYMBOL_GPL(wm8523_dai); | ||
402 | 397 | ||
403 | #ifdef CONFIG_PM | 398 | #ifdef CONFIG_PM |
404 | static int wm8523_suspend(struct platform_device *pdev, pm_message_t state) | 399 | static int wm8523_suspend(struct snd_soc_codec *codec, pm_message_t state) |
405 | { | 400 | { |
406 | struct snd_soc_device *socdev = platform_get_drvdata(pdev); | ||
407 | struct snd_soc_codec *codec = socdev->card->codec; | ||
408 | |||
409 | wm8523_set_bias_level(codec, SND_SOC_BIAS_OFF); | 401 | wm8523_set_bias_level(codec, SND_SOC_BIAS_OFF); |
410 | return 0; | 402 | return 0; |
411 | } | 403 | } |
412 | 404 | ||
413 | static int wm8523_resume(struct platform_device *pdev) | 405 | static int wm8523_resume(struct snd_soc_codec *codec) |
414 | { | 406 | { |
415 | struct snd_soc_device *socdev = platform_get_drvdata(pdev); | ||
416 | struct snd_soc_codec *codec = socdev->card->codec; | ||
417 | |||
418 | wm8523_set_bias_level(codec, SND_SOC_BIAS_STANDBY); | 407 | wm8523_set_bias_level(codec, SND_SOC_BIAS_STANDBY); |
419 | |||
420 | return 0; | 408 | return 0; |
421 | } | 409 | } |
422 | #else | 410 | #else |
@@ -424,93 +412,20 @@ static int wm8523_resume(struct platform_device *pdev) | |||
424 | #define wm8523_resume NULL | 412 | #define wm8523_resume NULL |
425 | #endif | 413 | #endif |
426 | 414 | ||
427 | static int wm8523_probe(struct platform_device *pdev) | 415 | static int wm8523_probe(struct snd_soc_codec *codec) |
428 | { | ||
429 | struct snd_soc_device *socdev = platform_get_drvdata(pdev); | ||
430 | struct snd_soc_codec *codec; | ||
431 | int ret = 0; | ||
432 | |||
433 | if (wm8523_codec == NULL) { | ||
434 | dev_err(&pdev->dev, "Codec device not registered\n"); | ||
435 | return -ENODEV; | ||
436 | } | ||
437 | |||
438 | socdev->card->codec = wm8523_codec; | ||
439 | codec = wm8523_codec; | ||
440 | |||
441 | /* register pcms */ | ||
442 | ret = snd_soc_new_pcms(socdev, SNDRV_DEFAULT_IDX1, SNDRV_DEFAULT_STR1); | ||
443 | if (ret < 0) { | ||
444 | dev_err(codec->dev, "failed to create pcms: %d\n", ret); | ||
445 | goto pcm_err; | ||
446 | } | ||
447 | |||
448 | snd_soc_add_controls(codec, wm8523_snd_controls, | ||
449 | ARRAY_SIZE(wm8523_snd_controls)); | ||
450 | wm8523_add_widgets(codec); | ||
451 | |||
452 | return ret; | ||
453 | |||
454 | pcm_err: | ||
455 | return ret; | ||
456 | } | ||
457 | |||
458 | static int wm8523_remove(struct platform_device *pdev) | ||
459 | { | ||
460 | struct snd_soc_device *socdev = platform_get_drvdata(pdev); | ||
461 | |||
462 | snd_soc_free_pcms(socdev); | ||
463 | snd_soc_dapm_free(socdev); | ||
464 | |||
465 | return 0; | ||
466 | } | ||
467 | |||
468 | struct snd_soc_codec_device soc_codec_dev_wm8523 = { | ||
469 | .probe = wm8523_probe, | ||
470 | .remove = wm8523_remove, | ||
471 | .suspend = wm8523_suspend, | ||
472 | .resume = wm8523_resume, | ||
473 | }; | ||
474 | EXPORT_SYMBOL_GPL(soc_codec_dev_wm8523); | ||
475 | |||
476 | static int wm8523_register(struct wm8523_priv *wm8523, | ||
477 | enum snd_soc_control_type control) | ||
478 | { | 416 | { |
479 | int ret; | 417 | struct wm8523_priv *wm8523 = snd_soc_codec_get_drvdata(codec); |
480 | struct snd_soc_codec *codec = &wm8523->codec; | 418 | int ret, i; |
481 | int i; | ||
482 | |||
483 | if (wm8523_codec) { | ||
484 | dev_err(codec->dev, "Another WM8523 is registered\n"); | ||
485 | ret = -EINVAL; | ||
486 | goto err; | ||
487 | } | ||
488 | |||
489 | mutex_init(&codec->mutex); | ||
490 | INIT_LIST_HEAD(&codec->dapm_widgets); | ||
491 | INIT_LIST_HEAD(&codec->dapm_paths); | ||
492 | |||
493 | snd_soc_codec_set_drvdata(codec, wm8523); | ||
494 | codec->name = "WM8523"; | ||
495 | codec->owner = THIS_MODULE; | ||
496 | codec->bias_level = SND_SOC_BIAS_OFF; | ||
497 | codec->set_bias_level = wm8523_set_bias_level; | ||
498 | codec->dai = &wm8523_dai; | ||
499 | codec->num_dai = 1; | ||
500 | codec->reg_cache_size = WM8523_REGISTER_COUNT; | ||
501 | codec->reg_cache = &wm8523->reg_cache; | ||
502 | codec->volatile_register = wm8523_volatile_register; | ||
503 | 419 | ||
420 | codec->hw_write = (hw_write_t)i2c_master_send; | ||
504 | wm8523->rate_constraint.list = &wm8523->rate_constraint_list[0]; | 421 | wm8523->rate_constraint.list = &wm8523->rate_constraint_list[0]; |
505 | wm8523->rate_constraint.count = | 422 | wm8523->rate_constraint.count = |
506 | ARRAY_SIZE(wm8523->rate_constraint_list); | 423 | ARRAY_SIZE(wm8523->rate_constraint_list); |
507 | 424 | ||
508 | memcpy(codec->reg_cache, wm8523_reg, sizeof(wm8523_reg)); | 425 | ret = snd_soc_codec_set_cache_io(codec, 8, 16, wm8523->control_type); |
509 | |||
510 | ret = snd_soc_codec_set_cache_io(codec, 8, 16, control); | ||
511 | if (ret != 0) { | 426 | if (ret != 0) { |
512 | dev_err(codec->dev, "Failed to set cache I/O: %d\n", ret); | 427 | dev_err(codec->dev, "Failed to set cache I/O: %d\n", ret); |
513 | goto err; | 428 | return ret; |
514 | } | 429 | } |
515 | 430 | ||
516 | for (i = 0; i < ARRAY_SIZE(wm8523->supplies); i++) | 431 | for (i = 0; i < ARRAY_SIZE(wm8523->supplies); i++) |
@@ -520,7 +435,7 @@ static int wm8523_register(struct wm8523_priv *wm8523, | |||
520 | wm8523->supplies); | 435 | wm8523->supplies); |
521 | if (ret != 0) { | 436 | if (ret != 0) { |
522 | dev_err(codec->dev, "Failed to request supplies: %d\n", ret); | 437 | dev_err(codec->dev, "Failed to request supplies: %d\n", ret); |
523 | goto err; | 438 | return ret; |
524 | } | 439 | } |
525 | 440 | ||
526 | ret = regulator_bulk_enable(ARRAY_SIZE(wm8523->supplies), | 441 | ret = regulator_bulk_enable(ARRAY_SIZE(wm8523->supplies), |
@@ -555,8 +470,6 @@ static int wm8523_register(struct wm8523_priv *wm8523, | |||
555 | goto err_enable; | 470 | goto err_enable; |
556 | } | 471 | } |
557 | 472 | ||
558 | wm8523_dai.dev = codec->dev; | ||
559 | |||
560 | /* Change some default settings - latch VU and enable ZC */ | 473 | /* Change some default settings - latch VU and enable ZC */ |
561 | wm8523->reg_cache[WM8523_DAC_GAINR] |= WM8523_DACR_VU; | 474 | wm8523->reg_cache[WM8523_DAC_GAINR] |= WM8523_DACR_VU; |
562 | wm8523->reg_cache[WM8523_DAC_CTRL3] |= WM8523_ZC; | 475 | wm8523->reg_cache[WM8523_DAC_CTRL3] |= WM8523_ZC; |
@@ -566,69 +479,67 @@ static int wm8523_register(struct wm8523_priv *wm8523, | |||
566 | /* Bias level configuration will have done an extra enable */ | 479 | /* Bias level configuration will have done an extra enable */ |
567 | regulator_bulk_disable(ARRAY_SIZE(wm8523->supplies), wm8523->supplies); | 480 | regulator_bulk_disable(ARRAY_SIZE(wm8523->supplies), wm8523->supplies); |
568 | 481 | ||
569 | wm8523_codec = codec; | 482 | snd_soc_add_controls(codec, wm8523_snd_controls, |
570 | 483 | ARRAY_SIZE(wm8523_snd_controls)); | |
571 | ret = snd_soc_register_codec(codec); | 484 | wm8523_add_widgets(codec); |
572 | if (ret != 0) { | ||
573 | dev_err(codec->dev, "Failed to register codec: %d\n", ret); | ||
574 | goto err_enable; | ||
575 | } | ||
576 | |||
577 | ret = snd_soc_register_dai(&wm8523_dai); | ||
578 | if (ret != 0) { | ||
579 | dev_err(codec->dev, "Failed to register DAI: %d\n", ret); | ||
580 | goto err_codec; | ||
581 | } | ||
582 | 485 | ||
583 | return 0; | 486 | return 0; |
584 | 487 | ||
585 | err_codec: | ||
586 | snd_soc_unregister_codec(codec); | ||
587 | err_enable: | 488 | err_enable: |
588 | regulator_bulk_disable(ARRAY_SIZE(wm8523->supplies), wm8523->supplies); | 489 | regulator_bulk_disable(ARRAY_SIZE(wm8523->supplies), wm8523->supplies); |
589 | err_get: | 490 | err_get: |
590 | regulator_bulk_free(ARRAY_SIZE(wm8523->supplies), wm8523->supplies); | 491 | regulator_bulk_free(ARRAY_SIZE(wm8523->supplies), wm8523->supplies); |
591 | err: | 492 | |
592 | kfree(wm8523); | ||
593 | return ret; | 493 | return ret; |
594 | } | 494 | } |
595 | 495 | ||
596 | static void wm8523_unregister(struct wm8523_priv *wm8523) | 496 | static int wm8523_remove(struct snd_soc_codec *codec) |
597 | { | 497 | { |
598 | wm8523_set_bias_level(&wm8523->codec, SND_SOC_BIAS_OFF); | 498 | struct wm8523_priv *wm8523 = snd_soc_codec_get_drvdata(codec); |
499 | |||
500 | wm8523_set_bias_level(codec, SND_SOC_BIAS_OFF); | ||
599 | regulator_bulk_free(ARRAY_SIZE(wm8523->supplies), wm8523->supplies); | 501 | regulator_bulk_free(ARRAY_SIZE(wm8523->supplies), wm8523->supplies); |
600 | snd_soc_unregister_dai(&wm8523_dai); | 502 | return 0; |
601 | snd_soc_unregister_codec(&wm8523->codec); | ||
602 | kfree(wm8523); | ||
603 | wm8523_codec = NULL; | ||
604 | } | 503 | } |
605 | 504 | ||
505 | static struct snd_soc_codec_driver soc_codec_dev_wm8523 = { | ||
506 | .probe = wm8523_probe, | ||
507 | .remove = wm8523_remove, | ||
508 | .suspend = wm8523_suspend, | ||
509 | .resume = wm8523_resume, | ||
510 | .set_bias_level = wm8523_set_bias_level, | ||
511 | .reg_cache_size = WM8523_REGISTER_COUNT, | ||
512 | .reg_word_size = sizeof(u16), | ||
513 | .reg_cache_default = wm8523_reg, | ||
514 | .volatile_register = wm8523_volatile_register, | ||
515 | }; | ||
516 | |||
606 | #if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE) | 517 | #if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE) |
607 | static __devinit int wm8523_i2c_probe(struct i2c_client *i2c, | 518 | static __devinit int wm8523_i2c_probe(struct i2c_client *i2c, |
608 | const struct i2c_device_id *id) | 519 | const struct i2c_device_id *id) |
609 | { | 520 | { |
610 | struct wm8523_priv *wm8523; | 521 | struct wm8523_priv *wm8523; |
611 | struct snd_soc_codec *codec; | 522 | int ret; |
612 | 523 | ||
613 | wm8523 = kzalloc(sizeof(struct wm8523_priv), GFP_KERNEL); | 524 | wm8523 = kzalloc(sizeof(struct wm8523_priv), GFP_KERNEL); |
614 | if (wm8523 == NULL) | 525 | if (wm8523 == NULL) |
615 | return -ENOMEM; | 526 | return -ENOMEM; |
616 | 527 | ||
617 | codec = &wm8523->codec; | ||
618 | codec->hw_write = (hw_write_t)i2c_master_send; | ||
619 | |||
620 | i2c_set_clientdata(i2c, wm8523); | 528 | i2c_set_clientdata(i2c, wm8523); |
621 | codec->control_data = i2c; | 529 | wm8523->control_type = SND_SOC_I2C; |
622 | 530 | ||
623 | codec->dev = &i2c->dev; | 531 | ret = snd_soc_register_codec(&i2c->dev, |
532 | &soc_codec_dev_wm8523, &wm8523_dai, 1); | ||
533 | if (ret < 0) | ||
534 | kfree(wm8523); | ||
535 | return ret; | ||
624 | 536 | ||
625 | return wm8523_register(wm8523, SND_SOC_I2C); | ||
626 | } | 537 | } |
627 | 538 | ||
628 | static __devexit int wm8523_i2c_remove(struct i2c_client *client) | 539 | static __devexit int wm8523_i2c_remove(struct i2c_client *client) |
629 | { | 540 | { |
630 | struct wm8523_priv *wm8523 = i2c_get_clientdata(client); | 541 | snd_soc_unregister_codec(&client->dev); |
631 | wm8523_unregister(wm8523); | 542 | kfree(i2c_get_clientdata(client)); |
632 | return 0; | 543 | return 0; |
633 | } | 544 | } |
634 | 545 | ||
@@ -640,7 +551,7 @@ MODULE_DEVICE_TABLE(i2c, wm8523_i2c_id); | |||
640 | 551 | ||
641 | static struct i2c_driver wm8523_i2c_driver = { | 552 | static struct i2c_driver wm8523_i2c_driver = { |
642 | .driver = { | 553 | .driver = { |
643 | .name = "WM8523", | 554 | .name = "wm8523-codec", |
644 | .owner = THIS_MODULE, | 555 | .owner = THIS_MODULE, |
645 | }, | 556 | }, |
646 | .probe = wm8523_i2c_probe, | 557 | .probe = wm8523_i2c_probe, |
diff --git a/sound/soc/codecs/wm8523.h b/sound/soc/codecs/wm8523.h index 1aa9ce3e1357..4d5b1eb8f2fc 100644 --- a/sound/soc/codecs/wm8523.h +++ b/sound/soc/codecs/wm8523.h | |||
@@ -154,7 +154,4 @@ | |||
154 | #define WM8523_ZD_COUNT_SHIFT 0 /* ZD_COUNT - [1:0] */ | 154 | #define WM8523_ZD_COUNT_SHIFT 0 /* ZD_COUNT - [1:0] */ |
155 | #define WM8523_ZD_COUNT_WIDTH 2 /* ZD_COUNT - [1:0] */ | 155 | #define WM8523_ZD_COUNT_WIDTH 2 /* ZD_COUNT - [1:0] */ |
156 | 156 | ||
157 | extern struct snd_soc_dai wm8523_dai; | ||
158 | extern struct snd_soc_codec_device soc_codec_dev_wm8523; | ||
159 | |||
160 | #endif | 157 | #endif |
diff --git a/sound/soc/codecs/wm8580.c b/sound/soc/codecs/wm8580.c index 1881b16bc248..b1a80e5ff8b5 100644 --- a/sound/soc/codecs/wm8580.c +++ b/sound/soc/codecs/wm8580.c | |||
@@ -199,7 +199,7 @@ static const char *wm8580_supply_names[WM8580_NUM_SUPPLIES] = { | |||
199 | 199 | ||
200 | /* codec private data */ | 200 | /* codec private data */ |
201 | struct wm8580_priv { | 201 | struct wm8580_priv { |
202 | struct snd_soc_codec codec; | 202 | enum snd_soc_control_type control_type; |
203 | struct regulator_bulk_data supplies[WM8580_NUM_SUPPLIES]; | 203 | struct regulator_bulk_data supplies[WM8580_NUM_SUPPLIES]; |
204 | u16 reg_cache[WM8580_MAX_REGISTER + 1]; | 204 | u16 reg_cache[WM8580_MAX_REGISTER + 1]; |
205 | struct pll_state a; | 205 | struct pll_state a; |
@@ -484,9 +484,8 @@ static int wm8580_paif_hw_params(struct snd_pcm_substream *substream, | |||
484 | struct snd_soc_dai *dai) | 484 | struct snd_soc_dai *dai) |
485 | { | 485 | { |
486 | struct snd_soc_pcm_runtime *rtd = substream->private_data; | 486 | struct snd_soc_pcm_runtime *rtd = substream->private_data; |
487 | struct snd_soc_device *socdev = rtd->socdev; | 487 | struct snd_soc_codec *codec = rtd->codec; |
488 | struct snd_soc_codec *codec = socdev->card->codec; | 488 | u16 paifb = snd_soc_read(codec, WM8580_PAIF3 + dai->driver->id); |
489 | u16 paifb = snd_soc_read(codec, WM8580_PAIF3 + dai->id); | ||
490 | 489 | ||
491 | paifb &= ~WM8580_AIF_LENGTH_MASK; | 490 | paifb &= ~WM8580_AIF_LENGTH_MASK; |
492 | /* bit size */ | 491 | /* bit size */ |
@@ -506,7 +505,7 @@ static int wm8580_paif_hw_params(struct snd_pcm_substream *substream, | |||
506 | return -EINVAL; | 505 | return -EINVAL; |
507 | } | 506 | } |
508 | 507 | ||
509 | snd_soc_write(codec, WM8580_PAIF3 + dai->id, paifb); | 508 | snd_soc_write(codec, WM8580_PAIF3 + dai->driver->id, paifb); |
510 | return 0; | 509 | return 0; |
511 | } | 510 | } |
512 | 511 | ||
@@ -518,8 +517,8 @@ static int wm8580_set_paif_dai_fmt(struct snd_soc_dai *codec_dai, | |||
518 | unsigned int aifb; | 517 | unsigned int aifb; |
519 | int can_invert_lrclk; | 518 | int can_invert_lrclk; |
520 | 519 | ||
521 | aifa = snd_soc_read(codec, WM8580_PAIF1 + codec_dai->id); | 520 | aifa = snd_soc_read(codec, WM8580_PAIF1 + codec_dai->driver->id); |
522 | aifb = snd_soc_read(codec, WM8580_PAIF3 + codec_dai->id); | 521 | aifb = snd_soc_read(codec, WM8580_PAIF3 + codec_dai->driver->id); |
523 | 522 | ||
524 | aifb &= ~(WM8580_AIF_FMT_MASK | WM8580_AIF_LRP | WM8580_AIF_BCP); | 523 | aifb &= ~(WM8580_AIF_FMT_MASK | WM8580_AIF_LRP | WM8580_AIF_BCP); |
525 | 524 | ||
@@ -585,8 +584,8 @@ static int wm8580_set_paif_dai_fmt(struct snd_soc_dai *codec_dai, | |||
585 | return -EINVAL; | 584 | return -EINVAL; |
586 | } | 585 | } |
587 | 586 | ||
588 | snd_soc_write(codec, WM8580_PAIF1 + codec_dai->id, aifa); | 587 | snd_soc_write(codec, WM8580_PAIF1 + codec_dai->driver->id, aifa); |
589 | snd_soc_write(codec, WM8580_PAIF3 + codec_dai->id, aifb); | 588 | snd_soc_write(codec, WM8580_PAIF3 + codec_dai->driver->id, aifb); |
590 | 589 | ||
591 | return 0; | 590 | return 0; |
592 | } | 591 | } |
@@ -746,10 +745,10 @@ static struct snd_soc_dai_ops wm8580_dai_ops_capture = { | |||
746 | .set_pll = wm8580_set_dai_pll, | 745 | .set_pll = wm8580_set_dai_pll, |
747 | }; | 746 | }; |
748 | 747 | ||
749 | struct snd_soc_dai wm8580_dai[] = { | 748 | static struct snd_soc_dai_driver wm8580_dai[] = { |
750 | { | 749 | { |
751 | .name = "WM8580 PAIFRX", | 750 | .name = "wm8580-hifi-playback", |
752 | .id = 0, | 751 | .id = WM8580_DAI_PAIFRX, |
753 | .playback = { | 752 | .playback = { |
754 | .stream_name = "Playback", | 753 | .stream_name = "Playback", |
755 | .channels_min = 1, | 754 | .channels_min = 1, |
@@ -760,8 +759,8 @@ struct snd_soc_dai wm8580_dai[] = { | |||
760 | .ops = &wm8580_dai_ops_playback, | 759 | .ops = &wm8580_dai_ops_playback, |
761 | }, | 760 | }, |
762 | { | 761 | { |
763 | .name = "WM8580 PAIFTX", | 762 | .name = "wm8580-hifi-capture", |
764 | .id = 1, | 763 | .id = WM8580_DAI_PAIFTX, |
765 | .capture = { | 764 | .capture = { |
766 | .stream_name = "Capture", | 765 | .stream_name = "Capture", |
767 | .channels_min = 2, | 766 | .channels_min = 2, |
@@ -772,90 +771,16 @@ struct snd_soc_dai wm8580_dai[] = { | |||
772 | .ops = &wm8580_dai_ops_capture, | 771 | .ops = &wm8580_dai_ops_capture, |
773 | }, | 772 | }, |
774 | }; | 773 | }; |
775 | EXPORT_SYMBOL_GPL(wm8580_dai); | ||
776 | 774 | ||
777 | static struct snd_soc_codec *wm8580_codec; | 775 | static int wm8580_probe(struct snd_soc_codec *codec) |
778 | |||
779 | static int wm8580_probe(struct platform_device *pdev) | ||
780 | { | 776 | { |
781 | struct snd_soc_device *socdev = platform_get_drvdata(pdev); | 777 | struct wm8580_priv *wm8580 = snd_soc_codec_get_drvdata(codec); |
782 | struct snd_soc_codec *codec; | 778 | int ret = 0,i; |
783 | int ret = 0; | ||
784 | |||
785 | if (wm8580_codec == NULL) { | ||
786 | dev_err(&pdev->dev, "Codec device not registered\n"); | ||
787 | return -ENODEV; | ||
788 | } | ||
789 | |||
790 | socdev->card->codec = wm8580_codec; | ||
791 | codec = wm8580_codec; | ||
792 | |||
793 | /* register pcms */ | ||
794 | ret = snd_soc_new_pcms(socdev, SNDRV_DEFAULT_IDX1, SNDRV_DEFAULT_STR1); | ||
795 | if (ret < 0) { | ||
796 | dev_err(codec->dev, "failed to create pcms: %d\n", ret); | ||
797 | goto pcm_err; | ||
798 | } | ||
799 | |||
800 | snd_soc_add_controls(codec, wm8580_snd_controls, | ||
801 | ARRAY_SIZE(wm8580_snd_controls)); | ||
802 | wm8580_add_widgets(codec); | ||
803 | |||
804 | return ret; | ||
805 | |||
806 | pcm_err: | ||
807 | return ret; | ||
808 | } | ||
809 | |||
810 | /* power down chip */ | ||
811 | static int wm8580_remove(struct platform_device *pdev) | ||
812 | { | ||
813 | struct snd_soc_device *socdev = platform_get_drvdata(pdev); | ||
814 | |||
815 | snd_soc_free_pcms(socdev); | ||
816 | snd_soc_dapm_free(socdev); | ||
817 | |||
818 | return 0; | ||
819 | } | ||
820 | |||
821 | struct snd_soc_codec_device soc_codec_dev_wm8580 = { | ||
822 | .probe = wm8580_probe, | ||
823 | .remove = wm8580_remove, | ||
824 | }; | ||
825 | EXPORT_SYMBOL_GPL(soc_codec_dev_wm8580); | ||
826 | |||
827 | static int wm8580_register(struct wm8580_priv *wm8580, | ||
828 | enum snd_soc_control_type control) | ||
829 | { | ||
830 | int ret, i; | ||
831 | struct snd_soc_codec *codec = &wm8580->codec; | ||
832 | |||
833 | if (wm8580_codec) { | ||
834 | dev_err(codec->dev, "Another WM8580 is registered\n"); | ||
835 | ret = -EINVAL; | ||
836 | goto err; | ||
837 | } | ||
838 | |||
839 | mutex_init(&codec->mutex); | ||
840 | INIT_LIST_HEAD(&codec->dapm_widgets); | ||
841 | INIT_LIST_HEAD(&codec->dapm_paths); | ||
842 | |||
843 | snd_soc_codec_set_drvdata(codec, wm8580); | ||
844 | codec->name = "WM8580"; | ||
845 | codec->owner = THIS_MODULE; | ||
846 | codec->bias_level = SND_SOC_BIAS_OFF; | ||
847 | codec->set_bias_level = wm8580_set_bias_level; | ||
848 | codec->dai = wm8580_dai; | ||
849 | codec->num_dai = ARRAY_SIZE(wm8580_dai); | ||
850 | codec->reg_cache_size = ARRAY_SIZE(wm8580->reg_cache); | ||
851 | codec->reg_cache = &wm8580->reg_cache; | ||
852 | |||
853 | memcpy(codec->reg_cache, wm8580_reg, sizeof(wm8580_reg)); | ||
854 | 779 | ||
855 | ret = snd_soc_codec_set_cache_io(codec, 7, 9, control); | 780 | ret = snd_soc_codec_set_cache_io(codec, 7, 9, wm8580->control_type); |
856 | if (ret < 0) { | 781 | if (ret < 0) { |
857 | dev_err(codec->dev, "Failed to set cache I/O: %d\n", ret); | 782 | dev_err(codec->dev, "Failed to set cache I/O: %d\n", ret); |
858 | goto err; | 783 | return ret; |
859 | } | 784 | } |
860 | 785 | ||
861 | for (i = 0; i < ARRAY_SIZE(wm8580->supplies); i++) | 786 | for (i = 0; i < ARRAY_SIZE(wm8580->supplies); i++) |
@@ -865,7 +790,7 @@ static int wm8580_register(struct wm8580_priv *wm8580, | |||
865 | wm8580->supplies); | 790 | wm8580->supplies); |
866 | if (ret != 0) { | 791 | if (ret != 0) { |
867 | dev_err(codec->dev, "Failed to request supplies: %d\n", ret); | 792 | dev_err(codec->dev, "Failed to request supplies: %d\n", ret); |
868 | goto err; | 793 | return ret; |
869 | } | 794 | } |
870 | 795 | ||
871 | ret = regulator_bulk_enable(ARRAY_SIZE(wm8580->supplies), | 796 | ret = regulator_bulk_enable(ARRAY_SIZE(wm8580->supplies), |
@@ -882,74 +807,68 @@ static int wm8580_register(struct wm8580_priv *wm8580, | |||
882 | goto err_regulator_enable; | 807 | goto err_regulator_enable; |
883 | } | 808 | } |
884 | 809 | ||
885 | for (i = 0; i < ARRAY_SIZE(wm8580_dai); i++) | ||
886 | wm8580_dai[i].dev = codec->dev; | ||
887 | |||
888 | wm8580_set_bias_level(codec, SND_SOC_BIAS_STANDBY); | 810 | wm8580_set_bias_level(codec, SND_SOC_BIAS_STANDBY); |
889 | 811 | ||
890 | wm8580_codec = codec; | 812 | snd_soc_add_controls(codec, wm8580_snd_controls, |
891 | 813 | ARRAY_SIZE(wm8580_snd_controls)); | |
892 | ret = snd_soc_register_codec(codec); | 814 | wm8580_add_widgets(codec); |
893 | if (ret != 0) { | ||
894 | dev_err(codec->dev, "Failed to register codec: %d\n", ret); | ||
895 | goto err_regulator_enable; | ||
896 | } | ||
897 | |||
898 | ret = snd_soc_register_dais(wm8580_dai, ARRAY_SIZE(wm8580_dai)); | ||
899 | if (ret != 0) { | ||
900 | dev_err(codec->dev, "Failed to register DAI: %d\n", ret); | ||
901 | goto err_codec; | ||
902 | } | ||
903 | 815 | ||
904 | return 0; | 816 | return 0; |
905 | 817 | ||
906 | err_codec: | ||
907 | snd_soc_unregister_codec(codec); | ||
908 | err_regulator_enable: | 818 | err_regulator_enable: |
909 | regulator_bulk_disable(ARRAY_SIZE(wm8580->supplies), wm8580->supplies); | 819 | regulator_bulk_disable(ARRAY_SIZE(wm8580->supplies), wm8580->supplies); |
910 | err_regulator_get: | 820 | err_regulator_get: |
911 | regulator_bulk_free(ARRAY_SIZE(wm8580->supplies), wm8580->supplies); | 821 | regulator_bulk_free(ARRAY_SIZE(wm8580->supplies), wm8580->supplies); |
912 | err: | ||
913 | kfree(wm8580); | ||
914 | return ret; | 822 | return ret; |
915 | } | 823 | } |
916 | 824 | ||
917 | static void wm8580_unregister(struct wm8580_priv *wm8580) | 825 | /* power down chip */ |
826 | static int wm8580_remove(struct snd_soc_codec *codec) | ||
918 | { | 827 | { |
919 | wm8580_set_bias_level(&wm8580->codec, SND_SOC_BIAS_OFF); | 828 | struct wm8580_priv *wm8580 = snd_soc_codec_get_drvdata(codec); |
920 | snd_soc_unregister_dais(wm8580_dai, ARRAY_SIZE(wm8580_dai)); | 829 | |
921 | snd_soc_unregister_codec(&wm8580->codec); | 830 | wm8580_set_bias_level(codec, SND_SOC_BIAS_OFF); |
831 | |||
922 | regulator_bulk_disable(ARRAY_SIZE(wm8580->supplies), wm8580->supplies); | 832 | regulator_bulk_disable(ARRAY_SIZE(wm8580->supplies), wm8580->supplies); |
923 | regulator_bulk_free(ARRAY_SIZE(wm8580->supplies), wm8580->supplies); | 833 | regulator_bulk_free(ARRAY_SIZE(wm8580->supplies), wm8580->supplies); |
924 | kfree(wm8580); | 834 | |
925 | wm8580_codec = NULL; | 835 | return 0; |
926 | } | 836 | } |
927 | 837 | ||
838 | static struct snd_soc_codec_driver soc_codec_dev_wm8580 = { | ||
839 | .probe = wm8580_probe, | ||
840 | .remove = wm8580_remove, | ||
841 | .set_bias_level = wm8580_set_bias_level, | ||
842 | .reg_cache_size = sizeof(wm8580_reg), | ||
843 | .reg_word_size = sizeof(u16), | ||
844 | .reg_cache_default = &wm8580_reg, | ||
845 | }; | ||
846 | |||
928 | #if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE) | 847 | #if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE) |
929 | static int wm8580_i2c_probe(struct i2c_client *i2c, | 848 | static int wm8580_i2c_probe(struct i2c_client *i2c, |
930 | const struct i2c_device_id *id) | 849 | const struct i2c_device_id *id) |
931 | { | 850 | { |
932 | struct wm8580_priv *wm8580; | 851 | struct wm8580_priv *wm8580; |
933 | struct snd_soc_codec *codec; | 852 | int ret; |
934 | 853 | ||
935 | wm8580 = kzalloc(sizeof(struct wm8580_priv), GFP_KERNEL); | 854 | wm8580 = kzalloc(sizeof(struct wm8580_priv), GFP_KERNEL); |
936 | if (wm8580 == NULL) | 855 | if (wm8580 == NULL) |
937 | return -ENOMEM; | 856 | return -ENOMEM; |
938 | 857 | ||
939 | codec = &wm8580->codec; | ||
940 | |||
941 | i2c_set_clientdata(i2c, wm8580); | 858 | i2c_set_clientdata(i2c, wm8580); |
942 | codec->control_data = i2c; | 859 | wm8580->control_type = SND_SOC_I2C; |
943 | |||
944 | codec->dev = &i2c->dev; | ||
945 | 860 | ||
946 | return wm8580_register(wm8580, SND_SOC_I2C); | 861 | ret = snd_soc_register_codec(&i2c->dev, |
862 | &soc_codec_dev_wm8580, wm8580_dai, ARRAY_SIZE(wm8580_dai)); | ||
863 | if (ret < 0) | ||
864 | kfree(wm8580); | ||
865 | return ret; | ||
947 | } | 866 | } |
948 | 867 | ||
949 | static int wm8580_i2c_remove(struct i2c_client *client) | 868 | static int wm8580_i2c_remove(struct i2c_client *client) |
950 | { | 869 | { |
951 | struct wm8580_priv *wm8580 = i2c_get_clientdata(client); | 870 | snd_soc_unregister_codec(&client->dev); |
952 | wm8580_unregister(wm8580); | 871 | kfree(i2c_get_clientdata(client)); |
953 | return 0; | 872 | return 0; |
954 | } | 873 | } |
955 | 874 | ||
@@ -961,7 +880,7 @@ MODULE_DEVICE_TABLE(i2c, wm8580_i2c_id); | |||
961 | 880 | ||
962 | static struct i2c_driver wm8580_i2c_driver = { | 881 | static struct i2c_driver wm8580_i2c_driver = { |
963 | .driver = { | 882 | .driver = { |
964 | .name = "wm8580", | 883 | .name = "wm8580-codec", |
965 | .owner = THIS_MODULE, | 884 | .owner = THIS_MODULE, |
966 | }, | 885 | }, |
967 | .probe = wm8580_i2c_probe, | 886 | .probe = wm8580_i2c_probe, |
@@ -972,7 +891,7 @@ static struct i2c_driver wm8580_i2c_driver = { | |||
972 | 891 | ||
973 | static int __init wm8580_modinit(void) | 892 | static int __init wm8580_modinit(void) |
974 | { | 893 | { |
975 | int ret; | 894 | int ret = 0; |
976 | 895 | ||
977 | #if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE) | 896 | #if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE) |
978 | ret = i2c_add_driver(&wm8580_i2c_driver); | 897 | ret = i2c_add_driver(&wm8580_i2c_driver); |
@@ -981,7 +900,7 @@ static int __init wm8580_modinit(void) | |||
981 | } | 900 | } |
982 | #endif | 901 | #endif |
983 | 902 | ||
984 | return 0; | 903 | return ret; |
985 | } | 904 | } |
986 | module_init(wm8580_modinit); | 905 | module_init(wm8580_modinit); |
987 | 906 | ||
diff --git a/sound/soc/codecs/wm8580.h b/sound/soc/codecs/wm8580.h index 0dfb5ddde6a2..8328ef667593 100644 --- a/sound/soc/codecs/wm8580.h +++ b/sound/soc/codecs/wm8580.h | |||
@@ -31,8 +31,5 @@ | |||
31 | #define WM8580_DAI_PAIFRX 0 | 31 | #define WM8580_DAI_PAIFRX 0 |
32 | #define WM8580_DAI_PAIFTX 1 | 32 | #define WM8580_DAI_PAIFTX 1 |
33 | 33 | ||
34 | extern struct snd_soc_dai wm8580_dai[]; | ||
35 | extern struct snd_soc_codec_device soc_codec_dev_wm8580; | ||
36 | |||
37 | #endif | 34 | #endif |
38 | 35 | ||
diff --git a/sound/soc/codecs/wm8711.c b/sound/soc/codecs/wm8711.c index e2dba07f0260..f8d9c60e7fad 100644 --- a/sound/soc/codecs/wm8711.c +++ b/sound/soc/codecs/wm8711.c | |||
@@ -31,11 +31,9 @@ | |||
31 | 31 | ||
32 | #include "wm8711.h" | 32 | #include "wm8711.h" |
33 | 33 | ||
34 | static struct snd_soc_codec *wm8711_codec; | ||
35 | |||
36 | /* codec private data */ | 34 | /* codec private data */ |
37 | struct wm8711_priv { | 35 | struct wm8711_priv { |
38 | struct snd_soc_codec codec; | 36 | enum snd_soc_control_type bus_type; |
39 | u16 reg_cache[WM8711_CACHEREGNUM]; | 37 | u16 reg_cache[WM8711_CACHEREGNUM]; |
40 | unsigned int sysclk; | 38 | unsigned int sysclk; |
41 | }; | 39 | }; |
@@ -163,7 +161,7 @@ static int wm8711_hw_params(struct snd_pcm_substream *substream, | |||
163 | struct snd_soc_dai *dai) | 161 | struct snd_soc_dai *dai) |
164 | { | 162 | { |
165 | struct snd_soc_codec *codec = dai->codec; | 163 | struct snd_soc_codec *codec = dai->codec; |
166 | struct wm8711_priv *wm8711 = snd_soc_codec_get_drvdata(codec); | 164 | struct wm8711_priv *wm8711 = snd_soc_codec_get_drvdata(codec); |
167 | u16 iface = snd_soc_read(codec, WM8711_IFACE) & 0xfffc; | 165 | u16 iface = snd_soc_read(codec, WM8711_IFACE) & 0xfffc; |
168 | int i = get_coeff(wm8711->sysclk, params_rate(params)); | 166 | int i = get_coeff(wm8711->sysclk, params_rate(params)); |
169 | u16 srate = (coeff_div[i].sr << 2) | | 167 | u16 srate = (coeff_div[i].sr << 2) | |
@@ -227,7 +225,7 @@ static int wm8711_set_dai_sysclk(struct snd_soc_dai *codec_dai, | |||
227 | int clk_id, unsigned int freq, int dir) | 225 | int clk_id, unsigned int freq, int dir) |
228 | { | 226 | { |
229 | struct snd_soc_codec *codec = codec_dai->codec; | 227 | struct snd_soc_codec *codec = codec_dai->codec; |
230 | struct wm8711_priv *wm8711 = snd_soc_codec_get_drvdata(codec); | 228 | struct wm8711_priv *wm8711 = snd_soc_codec_get_drvdata(codec); |
231 | 229 | ||
232 | switch (freq) { | 230 | switch (freq) { |
233 | case 11289600: | 231 | case 11289600: |
@@ -338,8 +336,8 @@ static struct snd_soc_dai_ops wm8711_ops = { | |||
338 | .set_fmt = wm8711_set_dai_fmt, | 336 | .set_fmt = wm8711_set_dai_fmt, |
339 | }; | 337 | }; |
340 | 338 | ||
341 | struct snd_soc_dai wm8711_dai = { | 339 | static struct snd_soc_dai_driver wm8711_dai = { |
342 | .name = "WM8711", | 340 | .name = "wm8711-hifi", |
343 | .playback = { | 341 | .playback = { |
344 | .stream_name = "Playback", | 342 | .stream_name = "Playback", |
345 | .channels_min = 1, | 343 | .channels_min = 1, |
@@ -349,22 +347,16 @@ struct snd_soc_dai wm8711_dai = { | |||
349 | }, | 347 | }, |
350 | .ops = &wm8711_ops, | 348 | .ops = &wm8711_ops, |
351 | }; | 349 | }; |
352 | EXPORT_SYMBOL_GPL(wm8711_dai); | ||
353 | 350 | ||
354 | static int wm8711_suspend(struct platform_device *pdev, pm_message_t state) | 351 | static int wm8711_suspend(struct snd_soc_codec *codec, pm_message_t state) |
355 | { | 352 | { |
356 | struct snd_soc_device *socdev = platform_get_drvdata(pdev); | ||
357 | struct snd_soc_codec *codec = socdev->card->codec; | ||
358 | |||
359 | snd_soc_write(codec, WM8711_ACTIVE, 0x0); | 353 | snd_soc_write(codec, WM8711_ACTIVE, 0x0); |
360 | wm8711_set_bias_level(codec, SND_SOC_BIAS_OFF); | 354 | wm8711_set_bias_level(codec, SND_SOC_BIAS_OFF); |
361 | return 0; | 355 | return 0; |
362 | } | 356 | } |
363 | 357 | ||
364 | static int wm8711_resume(struct platform_device *pdev) | 358 | static int wm8711_resume(struct snd_soc_codec *codec) |
365 | { | 359 | { |
366 | struct snd_soc_device *socdev = platform_get_drvdata(pdev); | ||
367 | struct snd_soc_codec *codec = socdev->card->codec; | ||
368 | int i; | 360 | int i; |
369 | u8 data[2]; | 361 | u8 data[2]; |
370 | u16 *cache = codec->reg_cache; | 362 | u16 *cache = codec->reg_cache; |
@@ -380,99 +372,23 @@ static int wm8711_resume(struct platform_device *pdev) | |||
380 | return 0; | 372 | return 0; |
381 | } | 373 | } |
382 | 374 | ||
383 | static int wm8711_probe(struct platform_device *pdev) | 375 | static int wm8711_probe(struct snd_soc_codec *codec) |
384 | { | 376 | { |
385 | struct snd_soc_device *socdev = platform_get_drvdata(pdev); | 377 | struct wm8711_priv *wm8711 = snd_soc_codec_get_drvdata(codec); |
386 | struct snd_soc_codec *codec; | 378 | int ret, reg; |
387 | int ret = 0; | ||
388 | |||
389 | if (wm8711_codec == NULL) { | ||
390 | dev_err(&pdev->dev, "Codec device not registered\n"); | ||
391 | return -ENODEV; | ||
392 | } | ||
393 | |||
394 | socdev->card->codec = wm8711_codec; | ||
395 | codec = wm8711_codec; | ||
396 | |||
397 | /* register pcms */ | ||
398 | ret = snd_soc_new_pcms(socdev, SNDRV_DEFAULT_IDX1, SNDRV_DEFAULT_STR1); | ||
399 | if (ret < 0) { | ||
400 | dev_err(codec->dev, "failed to create pcms: %d\n", ret); | ||
401 | goto pcm_err; | ||
402 | } | ||
403 | |||
404 | snd_soc_add_controls(codec, wm8711_snd_controls, | ||
405 | ARRAY_SIZE(wm8711_snd_controls)); | ||
406 | wm8711_add_widgets(codec); | ||
407 | |||
408 | return ret; | ||
409 | |||
410 | pcm_err: | ||
411 | return ret; | ||
412 | } | ||
413 | |||
414 | /* power down chip */ | ||
415 | static int wm8711_remove(struct platform_device *pdev) | ||
416 | { | ||
417 | struct snd_soc_device *socdev = platform_get_drvdata(pdev); | ||
418 | |||
419 | snd_soc_free_pcms(socdev); | ||
420 | snd_soc_dapm_free(socdev); | ||
421 | |||
422 | return 0; | ||
423 | } | ||
424 | |||
425 | struct snd_soc_codec_device soc_codec_dev_wm8711 = { | ||
426 | .probe = wm8711_probe, | ||
427 | .remove = wm8711_remove, | ||
428 | .suspend = wm8711_suspend, | ||
429 | .resume = wm8711_resume, | ||
430 | }; | ||
431 | EXPORT_SYMBOL_GPL(soc_codec_dev_wm8711); | ||
432 | |||
433 | static int wm8711_register(struct wm8711_priv *wm8711, | ||
434 | enum snd_soc_control_type control) | ||
435 | { | ||
436 | int ret; | ||
437 | struct snd_soc_codec *codec = &wm8711->codec; | ||
438 | u16 reg; | ||
439 | |||
440 | if (wm8711_codec) { | ||
441 | dev_err(codec->dev, "Another WM8711 is registered\n"); | ||
442 | ret = -EINVAL; | ||
443 | goto err; | ||
444 | } | ||
445 | |||
446 | mutex_init(&codec->mutex); | ||
447 | INIT_LIST_HEAD(&codec->dapm_widgets); | ||
448 | INIT_LIST_HEAD(&codec->dapm_paths); | ||
449 | |||
450 | snd_soc_codec_set_drvdata(codec, wm8711); | ||
451 | codec->name = "WM8711"; | ||
452 | codec->owner = THIS_MODULE; | ||
453 | codec->bias_level = SND_SOC_BIAS_OFF; | ||
454 | codec->set_bias_level = wm8711_set_bias_level; | ||
455 | codec->dai = &wm8711_dai; | ||
456 | codec->num_dai = 1; | ||
457 | codec->reg_cache_size = WM8711_CACHEREGNUM; | ||
458 | codec->reg_cache = &wm8711->reg_cache; | ||
459 | |||
460 | memcpy(codec->reg_cache, wm8711_reg, sizeof(wm8711_reg)); | ||
461 | 379 | ||
462 | ret = snd_soc_codec_set_cache_io(codec, 7, 9, control); | 380 | ret = snd_soc_codec_set_cache_io(codec, 7, 9, wm8711->bus_type); |
463 | if (ret < 0) { | 381 | if (ret < 0) { |
464 | dev_err(codec->dev, "Failed to set cache I/O: %d\n", ret); | 382 | dev_err(codec->dev, "Failed to set cache I/O: %d\n", ret); |
465 | goto err; | 383 | return ret; |
466 | } | 384 | } |
467 | 385 | ||
468 | ret = wm8711_reset(codec); | 386 | ret = wm8711_reset(codec); |
469 | if (ret < 0) { | 387 | if (ret < 0) { |
470 | dev_err(codec->dev, "Failed to issue reset\n"); | 388 | dev_err(codec->dev, "Failed to issue reset\n"); |
471 | goto err; | 389 | return ret; |
472 | } | 390 | } |
473 | 391 | ||
474 | wm8711_dai.dev = codec->dev; | ||
475 | |||
476 | wm8711_set_bias_level(codec, SND_SOC_BIAS_STANDBY); | 392 | wm8711_set_bias_level(codec, SND_SOC_BIAS_STANDBY); |
477 | 393 | ||
478 | /* Latch the update bits */ | 394 | /* Latch the update bits */ |
@@ -481,69 +397,62 @@ static int wm8711_register(struct wm8711_priv *wm8711, | |||
481 | reg = snd_soc_read(codec, WM8711_ROUT1V); | 397 | reg = snd_soc_read(codec, WM8711_ROUT1V); |
482 | snd_soc_write(codec, WM8711_ROUT1V, reg | 0x0100); | 398 | snd_soc_write(codec, WM8711_ROUT1V, reg | 0x0100); |
483 | 399 | ||
484 | wm8711_codec = codec; | 400 | snd_soc_add_controls(codec, wm8711_snd_controls, |
485 | 401 | ARRAY_SIZE(wm8711_snd_controls)); | |
486 | ret = snd_soc_register_codec(codec); | 402 | wm8711_add_widgets(codec); |
487 | if (ret != 0) { | ||
488 | dev_err(codec->dev, "Failed to register codec: %d\n", ret); | ||
489 | goto err; | ||
490 | } | ||
491 | |||
492 | ret = snd_soc_register_dai(&wm8711_dai); | ||
493 | if (ret != 0) { | ||
494 | dev_err(codec->dev, "Failed to register DAI: %d\n", ret); | ||
495 | goto err_codec; | ||
496 | } | ||
497 | |||
498 | return 0; | ||
499 | 403 | ||
500 | err_codec: | ||
501 | snd_soc_unregister_codec(codec); | ||
502 | err: | ||
503 | kfree(wm8711); | ||
504 | return ret; | 404 | return ret; |
405 | |||
505 | } | 406 | } |
506 | 407 | ||
507 | static void wm8711_unregister(struct wm8711_priv *wm8711) | 408 | /* power down chip */ |
409 | static int wm8711_remove(struct snd_soc_codec *codec) | ||
508 | { | 410 | { |
509 | wm8711_set_bias_level(&wm8711->codec, SND_SOC_BIAS_OFF); | 411 | wm8711_set_bias_level(codec, SND_SOC_BIAS_OFF); |
510 | snd_soc_unregister_dai(&wm8711_dai); | 412 | return 0; |
511 | snd_soc_unregister_codec(&wm8711->codec); | ||
512 | kfree(wm8711); | ||
513 | wm8711_codec = NULL; | ||
514 | } | 413 | } |
515 | 414 | ||
415 | static struct snd_soc_codec_driver soc_codec_dev_wm8711 = { | ||
416 | .probe = wm8711_probe, | ||
417 | .remove = wm8711_remove, | ||
418 | .suspend = wm8711_suspend, | ||
419 | .resume = wm8711_resume, | ||
420 | .set_bias_level = wm8711_set_bias_level, | ||
421 | .reg_cache_size = sizeof(wm8711_reg), | ||
422 | .reg_word_size = sizeof(u16), | ||
423 | .reg_cache_default = wm8711_reg, | ||
424 | }; | ||
425 | |||
516 | #if defined(CONFIG_SPI_MASTER) | 426 | #if defined(CONFIG_SPI_MASTER) |
517 | static int __devinit wm8711_spi_probe(struct spi_device *spi) | 427 | static int __devinit wm8711_spi_probe(struct spi_device *spi) |
518 | { | 428 | { |
519 | struct snd_soc_codec *codec; | ||
520 | struct wm8711_priv *wm8711; | 429 | struct wm8711_priv *wm8711; |
430 | int ret; | ||
521 | 431 | ||
522 | wm8711 = kzalloc(sizeof(struct wm8711_priv), GFP_KERNEL); | 432 | wm8711 = kzalloc(sizeof(struct wm8711_priv), GFP_KERNEL); |
523 | if (wm8711 == NULL) | 433 | if (wm8711 == NULL) |
524 | return -ENOMEM; | 434 | return -ENOMEM; |
525 | 435 | ||
526 | codec = &wm8711->codec; | 436 | spi_set_drvdata(spi, wm8711); |
527 | codec->control_data = spi; | 437 | wm8711->bus_type = SND_SOC_SPI; |
528 | codec->dev = &spi->dev; | ||
529 | 438 | ||
530 | dev_set_drvdata(&spi->dev, wm8711); | 439 | ret = snd_soc_register_codec(&spi->dev, |
531 | 440 | &soc_codec_dev_wm8711, &wm8711_dai, 1); | |
532 | return wm8711_register(wm8711, SND_SOC_SPI); | 441 | if (ret < 0) |
442 | kfree(wm8711); | ||
443 | return ret; | ||
533 | } | 444 | } |
534 | 445 | ||
535 | static int __devexit wm8711_spi_remove(struct spi_device *spi) | 446 | static int __devexit wm8711_spi_remove(struct spi_device *spi) |
536 | { | 447 | { |
537 | struct wm8711_priv *wm8711 = dev_get_drvdata(&spi->dev); | 448 | snd_soc_unregister_codec(&spi->dev); |
538 | 449 | kfree(spi_get_drvdata(spi)); | |
539 | wm8711_unregister(wm8711); | ||
540 | |||
541 | return 0; | 450 | return 0; |
542 | } | 451 | } |
543 | 452 | ||
544 | static struct spi_driver wm8711_spi_driver = { | 453 | static struct spi_driver wm8711_spi_driver = { |
545 | .driver = { | 454 | .driver = { |
546 | .name = "wm8711", | 455 | .name = "wm8711-codec", |
547 | .bus = &spi_bus_type, | 456 | .bus = &spi_bus_type, |
548 | .owner = THIS_MODULE, | 457 | .owner = THIS_MODULE, |
549 | }, | 458 | }, |
@@ -553,31 +462,30 @@ static struct spi_driver wm8711_spi_driver = { | |||
553 | #endif /* CONFIG_SPI_MASTER */ | 462 | #endif /* CONFIG_SPI_MASTER */ |
554 | 463 | ||
555 | #if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE) | 464 | #if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE) |
556 | static __devinit int wm8711_i2c_probe(struct i2c_client *i2c, | 465 | static __devinit int wm8711_i2c_probe(struct i2c_client *client, |
557 | const struct i2c_device_id *id) | 466 | const struct i2c_device_id *id) |
558 | { | 467 | { |
559 | struct wm8711_priv *wm8711; | 468 | struct wm8711_priv *wm8711; |
560 | struct snd_soc_codec *codec; | 469 | int ret; |
561 | 470 | ||
562 | wm8711 = kzalloc(sizeof(struct wm8711_priv), GFP_KERNEL); | 471 | wm8711 = kzalloc(sizeof(struct wm8711_priv), GFP_KERNEL); |
563 | if (wm8711 == NULL) | 472 | if (wm8711 == NULL) |
564 | return -ENOMEM; | 473 | return -ENOMEM; |
565 | 474 | ||
566 | codec = &wm8711->codec; | 475 | i2c_set_clientdata(client, wm8711); |
567 | codec->hw_write = (hw_write_t)i2c_master_send; | 476 | wm8711->bus_type = SND_SOC_I2C; |
568 | |||
569 | i2c_set_clientdata(i2c, wm8711); | ||
570 | codec->control_data = i2c; | ||
571 | 477 | ||
572 | codec->dev = &i2c->dev; | 478 | ret = snd_soc_register_codec(&client->dev, |
573 | 479 | &soc_codec_dev_wm8711, &wm8711_dai, 1); | |
574 | return wm8711_register(wm8711, SND_SOC_I2C); | 480 | if (ret < 0) |
481 | kfree(wm8711); | ||
482 | return ret; | ||
575 | } | 483 | } |
576 | 484 | ||
577 | static __devexit int wm8711_i2c_remove(struct i2c_client *client) | 485 | static __devexit int wm8711_i2c_remove(struct i2c_client *client) |
578 | { | 486 | { |
579 | struct wm8711_priv *wm8711 = i2c_get_clientdata(client); | 487 | snd_soc_unregister_codec(&client->dev); |
580 | wm8711_unregister(wm8711); | 488 | kfree(i2c_get_clientdata(client)); |
581 | return 0; | 489 | return 0; |
582 | } | 490 | } |
583 | 491 | ||
@@ -589,7 +497,7 @@ MODULE_DEVICE_TABLE(i2c, wm8711_i2c_id); | |||
589 | 497 | ||
590 | static struct i2c_driver wm8711_i2c_driver = { | 498 | static struct i2c_driver wm8711_i2c_driver = { |
591 | .driver = { | 499 | .driver = { |
592 | .name = "WM8711 I2C Codec", | 500 | .name = "wm8711-codec", |
593 | .owner = THIS_MODULE, | 501 | .owner = THIS_MODULE, |
594 | }, | 502 | }, |
595 | .probe = wm8711_i2c_probe, | 503 | .probe = wm8711_i2c_probe, |
diff --git a/sound/soc/codecs/wm8711.h b/sound/soc/codecs/wm8711.h index 381e84a43816..a61db985499f 100644 --- a/sound/soc/codecs/wm8711.h +++ b/sound/soc/codecs/wm8711.h | |||
@@ -36,7 +36,4 @@ struct wm8711_setup_data { | |||
36 | unsigned short i2c_address; | 36 | unsigned short i2c_address; |
37 | }; | 37 | }; |
38 | 38 | ||
39 | extern struct snd_soc_dai wm8711_dai; | ||
40 | extern struct snd_soc_codec_device soc_codec_dev_wm8711; | ||
41 | |||
42 | #endif | 39 | #endif |
diff --git a/sound/soc/codecs/wm8727.c b/sound/soc/codecs/wm8727.c index 9d1df2628136..6a40080ba701 100644 --- a/sound/soc/codecs/wm8727.c +++ b/sound/soc/codecs/wm8727.c | |||
@@ -23,7 +23,6 @@ | |||
23 | #include <sound/initval.h> | 23 | #include <sound/initval.h> |
24 | #include <sound/soc.h> | 24 | #include <sound/soc.h> |
25 | 25 | ||
26 | #include "wm8727.h" | ||
27 | /* | 26 | /* |
28 | * Note this is a simple chip with no configuration interface, sample rate is | 27 | * Note this is a simple chip with no configuration interface, sample rate is |
29 | * determined automatically by examining the Master clock and Bit clock ratios | 28 | * determined automatically by examining the Master clock and Bit clock ratios |
@@ -33,8 +32,8 @@ | |||
33 | SNDRV_PCM_RATE_192000) | 32 | SNDRV_PCM_RATE_192000) |
34 | 33 | ||
35 | 34 | ||
36 | struct snd_soc_dai wm8727_dai = { | 35 | static struct snd_soc_dai_driver wm8727_dai = { |
37 | .name = "WM8727", | 36 | .name = "wm8727-hifi", |
38 | .playback = { | 37 | .playback = { |
39 | .stream_name = "Playback", | 38 | .stream_name = "Playback", |
40 | .channels_min = 2, | 39 | .channels_min = 2, |
@@ -43,103 +42,18 @@ struct snd_soc_dai wm8727_dai = { | |||
43 | .formats = SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S24_LE, | 42 | .formats = SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S24_LE, |
44 | }, | 43 | }, |
45 | }; | 44 | }; |
46 | EXPORT_SYMBOL_GPL(wm8727_dai); | ||
47 | 45 | ||
48 | static struct snd_soc_codec *wm8727_codec; | 46 | struct snd_soc_codec_driver soc_codec_dev_wm8727; |
49 | 47 | ||
50 | static int wm8727_soc_probe(struct platform_device *pdev) | 48 | static __devinit int wm8727_probe(struct platform_device *pdev) |
51 | { | 49 | { |
52 | struct snd_soc_device *socdev = platform_get_drvdata(pdev); | 50 | return snd_soc_register_codec(&pdev->dev, |
53 | int ret = 0; | 51 | &soc_codec_dev_wm8727, &wm8727_dai, 1); |
54 | |||
55 | BUG_ON(!wm8727_codec); | ||
56 | |||
57 | socdev->card->codec = wm8727_codec; | ||
58 | |||
59 | /* register pcms */ | ||
60 | ret = snd_soc_new_pcms(socdev, SNDRV_DEFAULT_IDX1, SNDRV_DEFAULT_STR1); | ||
61 | if (ret < 0) { | ||
62 | printk(KERN_ERR "wm8727: failed to create pcms\n"); | ||
63 | goto pcm_err; | ||
64 | } | ||
65 | |||
66 | return ret; | ||
67 | |||
68 | pcm_err: | ||
69 | kfree(socdev->card->codec); | ||
70 | socdev->card->codec = NULL; | ||
71 | return ret; | ||
72 | } | ||
73 | |||
74 | static int wm8727_soc_remove(struct platform_device *pdev) | ||
75 | { | ||
76 | struct snd_soc_device *socdev = platform_get_drvdata(pdev); | ||
77 | |||
78 | snd_soc_free_pcms(socdev); | ||
79 | |||
80 | return 0; | ||
81 | } | ||
82 | |||
83 | struct snd_soc_codec_device soc_codec_dev_wm8727 = { | ||
84 | .probe = wm8727_soc_probe, | ||
85 | .remove = wm8727_soc_remove, | ||
86 | }; | ||
87 | EXPORT_SYMBOL_GPL(soc_codec_dev_wm8727); | ||
88 | |||
89 | |||
90 | static __devinit int wm8727_platform_probe(struct platform_device *pdev) | ||
91 | { | ||
92 | struct snd_soc_codec *codec; | ||
93 | int ret; | ||
94 | |||
95 | if (wm8727_codec) { | ||
96 | dev_err(&pdev->dev, "Another WM8727 is registered\n"); | ||
97 | return -EBUSY; | ||
98 | } | ||
99 | |||
100 | codec = kzalloc(sizeof(struct snd_soc_codec), GFP_KERNEL); | ||
101 | if (codec == NULL) | ||
102 | return -ENOMEM; | ||
103 | wm8727_codec = codec; | ||
104 | |||
105 | platform_set_drvdata(pdev, codec); | ||
106 | |||
107 | mutex_init(&codec->mutex); | ||
108 | codec->dev = &pdev->dev; | ||
109 | codec->name = "WM8727"; | ||
110 | codec->owner = THIS_MODULE; | ||
111 | codec->dai = &wm8727_dai; | ||
112 | codec->num_dai = 1; | ||
113 | INIT_LIST_HEAD(&codec->dapm_widgets); | ||
114 | INIT_LIST_HEAD(&codec->dapm_paths); | ||
115 | |||
116 | wm8727_dai.dev = &pdev->dev; | ||
117 | |||
118 | ret = snd_soc_register_codec(codec); | ||
119 | if (ret != 0) { | ||
120 | dev_err(&pdev->dev, "Failed to register CODEC: %d\n", ret); | ||
121 | goto err; | ||
122 | } | ||
123 | |||
124 | ret = snd_soc_register_dai(&wm8727_dai); | ||
125 | if (ret != 0) { | ||
126 | dev_err(&pdev->dev, "Failed to register DAI: %d\n", ret); | ||
127 | goto err_codec; | ||
128 | } | ||
129 | |||
130 | return 0; | ||
131 | |||
132 | err_codec: | ||
133 | snd_soc_unregister_codec(codec); | ||
134 | err: | ||
135 | kfree(codec); | ||
136 | return ret; | ||
137 | } | 52 | } |
138 | 53 | ||
139 | static int __devexit wm8727_platform_remove(struct platform_device *pdev) | 54 | static int __devexit wm8727_remove(struct platform_device *pdev) |
140 | { | 55 | { |
141 | snd_soc_unregister_dai(&wm8727_dai); | 56 | snd_soc_unregister_codec(&pdev->dev); |
142 | snd_soc_unregister_codec(platform_get_drvdata(pdev)); | ||
143 | return 0; | 57 | return 0; |
144 | } | 58 | } |
145 | 59 | ||
@@ -149,8 +63,8 @@ static struct platform_driver wm8727_codec_driver = { | |||
149 | .owner = THIS_MODULE, | 63 | .owner = THIS_MODULE, |
150 | }, | 64 | }, |
151 | 65 | ||
152 | .probe = wm8727_platform_probe, | 66 | .probe = wm8727_probe, |
153 | .remove = __devexit_p(wm8727_platform_remove), | 67 | .remove = __devexit_p(wm8727_remove), |
154 | }; | 68 | }; |
155 | 69 | ||
156 | static int __init wm8727_init(void) | 70 | static int __init wm8727_init(void) |
diff --git a/sound/soc/codecs/wm8727.h b/sound/soc/codecs/wm8727.h deleted file mode 100644 index ee19aa71bcdc..000000000000 --- a/sound/soc/codecs/wm8727.h +++ /dev/null | |||
@@ -1,21 +0,0 @@ | |||
1 | /* | ||
2 | * wm8727.h | ||
3 | * | ||
4 | * Created on: 15-Oct-2009 | ||
5 | * Author: neil.jones@imgtec.com | ||
6 | * | ||
7 | * Copyright (C) 2009 Imagination Technologies Ltd. | ||
8 | * | ||
9 | * This program is free software; you can redistribute it and/or modify it | ||
10 | * under the terms of the GNU General Public License as published by the | ||
11 | * Free Software Foundation; either version 2 of the License, or (at your | ||
12 | * option) any later version. | ||
13 | */ | ||
14 | |||
15 | #ifndef WM8727_H_ | ||
16 | #define WM8727_H_ | ||
17 | |||
18 | extern struct snd_soc_dai wm8727_dai; | ||
19 | extern struct snd_soc_codec_device soc_codec_dev_wm8727; | ||
20 | |||
21 | #endif /* WM8727_H_ */ | ||
diff --git a/sound/soc/codecs/wm8728.c b/sound/soc/codecs/wm8728.c index 34be2d2b69ef..5e5a1625194c 100644 --- a/sound/soc/codecs/wm8728.c +++ b/sound/soc/codecs/wm8728.c | |||
@@ -29,8 +29,6 @@ | |||
29 | 29 | ||
30 | #include "wm8728.h" | 30 | #include "wm8728.h" |
31 | 31 | ||
32 | struct snd_soc_codec_device soc_codec_dev_wm8728; | ||
33 | |||
34 | /* | 32 | /* |
35 | * We can't read the WM8728 register space so we cache them instead. | 33 | * We can't read the WM8728 register space so we cache them instead. |
36 | * Note that the defaults here aren't the physical defaults, we latch | 34 | * Note that the defaults here aren't the physical defaults, we latch |
@@ -44,6 +42,11 @@ static const u16 wm8728_reg_defaults[] = { | |||
44 | 0x100, | 42 | 0x100, |
45 | }; | 43 | }; |
46 | 44 | ||
45 | /* codec private data */ | ||
46 | struct wm8728_priv { | ||
47 | enum snd_soc_control_type control_type; | ||
48 | }; | ||
49 | |||
47 | static const DECLARE_TLV_DB_SCALE(wm8728_tlv, -12750, 50, 1); | 50 | static const DECLARE_TLV_DB_SCALE(wm8728_tlv, -12750, 50, 1); |
48 | 51 | ||
49 | static const struct snd_kcontrol_new wm8728_snd_controls[] = { | 52 | static const struct snd_kcontrol_new wm8728_snd_controls[] = { |
@@ -96,8 +99,7 @@ static int wm8728_hw_params(struct snd_pcm_substream *substream, | |||
96 | struct snd_soc_dai *dai) | 99 | struct snd_soc_dai *dai) |
97 | { | 100 | { |
98 | struct snd_soc_pcm_runtime *rtd = substream->private_data; | 101 | struct snd_soc_pcm_runtime *rtd = substream->private_data; |
99 | struct snd_soc_device *socdev = rtd->socdev; | 102 | struct snd_soc_codec *codec = rtd->codec; |
100 | struct snd_soc_codec *codec = socdev->card->codec; | ||
101 | u16 dac = snd_soc_read(codec, WM8728_DACCTL); | 103 | u16 dac = snd_soc_read(codec, WM8728_DACCTL); |
102 | 104 | ||
103 | dac &= ~0x18; | 105 | dac &= ~0x18; |
@@ -210,8 +212,8 @@ static struct snd_soc_dai_ops wm8728_dai_ops = { | |||
210 | .set_fmt = wm8728_set_dai_fmt, | 212 | .set_fmt = wm8728_set_dai_fmt, |
211 | }; | 213 | }; |
212 | 214 | ||
213 | struct snd_soc_dai wm8728_dai = { | 215 | static struct snd_soc_dai_driver wm8728_dai = { |
214 | .name = "WM8728", | 216 | .name = "wm8728-hifi", |
215 | .playback = { | 217 | .playback = { |
216 | .stream_name = "Playback", | 218 | .stream_name = "Playback", |
217 | .channels_min = 2, | 219 | .channels_min = 2, |
@@ -221,63 +223,31 @@ struct snd_soc_dai wm8728_dai = { | |||
221 | }, | 223 | }, |
222 | .ops = &wm8728_dai_ops, | 224 | .ops = &wm8728_dai_ops, |
223 | }; | 225 | }; |
224 | EXPORT_SYMBOL_GPL(wm8728_dai); | ||
225 | 226 | ||
226 | static int wm8728_suspend(struct platform_device *pdev, pm_message_t state) | 227 | static int wm8728_suspend(struct snd_soc_codec *codec, pm_message_t state) |
227 | { | 228 | { |
228 | struct snd_soc_device *socdev = platform_get_drvdata(pdev); | ||
229 | struct snd_soc_codec *codec = socdev->card->codec; | ||
230 | |||
231 | wm8728_set_bias_level(codec, SND_SOC_BIAS_OFF); | 229 | wm8728_set_bias_level(codec, SND_SOC_BIAS_OFF); |
232 | 230 | ||
233 | return 0; | 231 | return 0; |
234 | } | 232 | } |
235 | 233 | ||
236 | static int wm8728_resume(struct platform_device *pdev) | 234 | static int wm8728_resume(struct snd_soc_codec *codec) |
237 | { | 235 | { |
238 | struct snd_soc_device *socdev = platform_get_drvdata(pdev); | ||
239 | struct snd_soc_codec *codec = socdev->card->codec; | ||
240 | |||
241 | wm8728_set_bias_level(codec, SND_SOC_BIAS_STANDBY); | 236 | wm8728_set_bias_level(codec, SND_SOC_BIAS_STANDBY); |
242 | 237 | ||
243 | return 0; | 238 | return 0; |
244 | } | 239 | } |
245 | 240 | ||
246 | /* | 241 | static int wm8728_probe(struct snd_soc_codec *codec) |
247 | * initialise the WM8728 driver | ||
248 | * register the mixer and dsp interfaces with the kernel | ||
249 | */ | ||
250 | static int wm8728_init(struct snd_soc_device *socdev, | ||
251 | enum snd_soc_control_type control) | ||
252 | { | 242 | { |
253 | struct snd_soc_codec *codec = socdev->card->codec; | 243 | struct wm8728_priv *wm8728 = snd_soc_codec_get_drvdata(codec); |
254 | int ret = 0; | 244 | int ret; |
255 | |||
256 | codec->name = "WM8728"; | ||
257 | codec->owner = THIS_MODULE; | ||
258 | codec->set_bias_level = wm8728_set_bias_level; | ||
259 | codec->dai = &wm8728_dai; | ||
260 | codec->num_dai = 1; | ||
261 | codec->bias_level = SND_SOC_BIAS_OFF; | ||
262 | codec->reg_cache_size = ARRAY_SIZE(wm8728_reg_defaults); | ||
263 | codec->reg_cache = kmemdup(wm8728_reg_defaults, | ||
264 | sizeof(wm8728_reg_defaults), | ||
265 | GFP_KERNEL); | ||
266 | if (codec->reg_cache == NULL) | ||
267 | return -ENOMEM; | ||
268 | 245 | ||
269 | ret = snd_soc_codec_set_cache_io(codec, 7, 9, control); | 246 | ret = snd_soc_codec_set_cache_io(codec, 7, 9, wm8728->control_type); |
270 | if (ret < 0) { | 247 | if (ret < 0) { |
271 | printk(KERN_ERR "wm8728: failed to configure cache I/O: %d\n", | 248 | printk(KERN_ERR "wm8728: failed to configure cache I/O: %d\n", |
272 | ret); | 249 | ret); |
273 | goto err; | 250 | return ret; |
274 | } | ||
275 | |||
276 | /* register pcms */ | ||
277 | ret = snd_soc_new_pcms(socdev, SNDRV_DEFAULT_IDX1, SNDRV_DEFAULT_STR1); | ||
278 | if (ret < 0) { | ||
279 | printk(KERN_ERR "wm8728: failed to create pcms\n"); | ||
280 | goto err; | ||
281 | } | 251 | } |
282 | 252 | ||
283 | /* power on device */ | 253 | /* power on device */ |
@@ -288,128 +258,55 @@ static int wm8728_init(struct snd_soc_device *socdev, | |||
288 | wm8728_add_widgets(codec); | 258 | wm8728_add_widgets(codec); |
289 | 259 | ||
290 | return ret; | 260 | return ret; |
291 | |||
292 | err: | ||
293 | kfree(codec->reg_cache); | ||
294 | return ret; | ||
295 | } | 261 | } |
296 | 262 | ||
297 | static struct snd_soc_device *wm8728_socdev; | 263 | static int wm8728_remove(struct snd_soc_codec *codec) |
298 | |||
299 | #if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE) | ||
300 | |||
301 | /* | ||
302 | * WM8728 2 wire address is determined by GPIO5 | ||
303 | * state during powerup. | ||
304 | * low = 0x1a | ||
305 | * high = 0x1b | ||
306 | */ | ||
307 | |||
308 | static int wm8728_i2c_probe(struct i2c_client *i2c, | ||
309 | const struct i2c_device_id *id) | ||
310 | { | 264 | { |
311 | struct snd_soc_device *socdev = wm8728_socdev; | 265 | wm8728_set_bias_level(codec, SND_SOC_BIAS_OFF); |
312 | struct snd_soc_codec *codec = socdev->card->codec; | ||
313 | int ret; | ||
314 | |||
315 | i2c_set_clientdata(i2c, codec); | ||
316 | codec->control_data = i2c; | ||
317 | |||
318 | ret = wm8728_init(socdev, SND_SOC_I2C); | ||
319 | if (ret < 0) | ||
320 | pr_err("failed to initialise WM8728\n"); | ||
321 | |||
322 | return ret; | ||
323 | } | ||
324 | |||
325 | static int wm8728_i2c_remove(struct i2c_client *client) | ||
326 | { | ||
327 | struct snd_soc_codec *codec = i2c_get_clientdata(client); | ||
328 | kfree(codec->reg_cache); | ||
329 | return 0; | 266 | return 0; |
330 | } | 267 | } |
331 | 268 | ||
332 | static const struct i2c_device_id wm8728_i2c_id[] = { | 269 | static struct snd_soc_codec_driver soc_codec_dev_wm8728 = { |
333 | { "wm8728", 0 }, | 270 | .probe = wm8728_probe, |
334 | { } | 271 | .remove = wm8728_remove, |
335 | }; | 272 | .suspend = wm8728_suspend, |
336 | MODULE_DEVICE_TABLE(i2c, wm8728_i2c_id); | 273 | .resume = wm8728_resume, |
337 | 274 | .set_bias_level = wm8728_set_bias_level, | |
338 | static struct i2c_driver wm8728_i2c_driver = { | 275 | .reg_cache_size = sizeof(wm8728_reg_defaults), |
339 | .driver = { | 276 | .reg_word_size = sizeof(u16), |
340 | .name = "WM8728 I2C Codec", | 277 | .reg_cache_default = wm8728_reg_defaults, |
341 | .owner = THIS_MODULE, | ||
342 | }, | ||
343 | .probe = wm8728_i2c_probe, | ||
344 | .remove = wm8728_i2c_remove, | ||
345 | .id_table = wm8728_i2c_id, | ||
346 | }; | 278 | }; |
347 | 279 | ||
348 | static int wm8728_add_i2c_device(struct platform_device *pdev, | ||
349 | const struct wm8728_setup_data *setup) | ||
350 | { | ||
351 | struct i2c_board_info info; | ||
352 | struct i2c_adapter *adapter; | ||
353 | struct i2c_client *client; | ||
354 | int ret; | ||
355 | |||
356 | ret = i2c_add_driver(&wm8728_i2c_driver); | ||
357 | if (ret != 0) { | ||
358 | dev_err(&pdev->dev, "can't add i2c driver\n"); | ||
359 | return ret; | ||
360 | } | ||
361 | |||
362 | memset(&info, 0, sizeof(struct i2c_board_info)); | ||
363 | info.addr = setup->i2c_address; | ||
364 | strlcpy(info.type, "wm8728", I2C_NAME_SIZE); | ||
365 | |||
366 | adapter = i2c_get_adapter(setup->i2c_bus); | ||
367 | if (!adapter) { | ||
368 | dev_err(&pdev->dev, "can't get i2c adapter %d\n", | ||
369 | setup->i2c_bus); | ||
370 | goto err_driver; | ||
371 | } | ||
372 | |||
373 | client = i2c_new_device(adapter, &info); | ||
374 | i2c_put_adapter(adapter); | ||
375 | if (!client) { | ||
376 | dev_err(&pdev->dev, "can't add i2c device at 0x%x\n", | ||
377 | (unsigned int)info.addr); | ||
378 | goto err_driver; | ||
379 | } | ||
380 | |||
381 | return 0; | ||
382 | |||
383 | err_driver: | ||
384 | i2c_del_driver(&wm8728_i2c_driver); | ||
385 | return -ENODEV; | ||
386 | } | ||
387 | #endif | ||
388 | |||
389 | #if defined(CONFIG_SPI_MASTER) | 280 | #if defined(CONFIG_SPI_MASTER) |
390 | static int __devinit wm8728_spi_probe(struct spi_device *spi) | 281 | static int __devinit wm8728_spi_probe(struct spi_device *spi) |
391 | { | 282 | { |
392 | struct snd_soc_device *socdev = wm8728_socdev; | 283 | struct wm8728_priv *wm8728; |
393 | struct snd_soc_codec *codec = socdev->card->codec; | ||
394 | int ret; | 284 | int ret; |
395 | 285 | ||
396 | codec->control_data = spi; | 286 | wm8728 = kzalloc(sizeof(struct wm8728_priv), GFP_KERNEL); |
287 | if (wm8728 == NULL) | ||
288 | return -ENOMEM; | ||
397 | 289 | ||
398 | ret = wm8728_init(socdev, SND_SOC_SPI); | 290 | wm8728->control_type = SND_SOC_SPI; |
399 | if (ret < 0) | 291 | spi_set_drvdata(spi, wm8728); |
400 | dev_err(&spi->dev, "failed to initialise WM8728\n"); | ||
401 | 292 | ||
293 | ret = snd_soc_register_codec(&spi->dev, | ||
294 | &soc_codec_dev_wm8728, &wm8728_dai, 1); | ||
295 | if (ret < 0) | ||
296 | kfree(wm8728); | ||
402 | return ret; | 297 | return ret; |
403 | } | 298 | } |
404 | 299 | ||
405 | static int __devexit wm8728_spi_remove(struct spi_device *spi) | 300 | static int __devexit wm8728_spi_remove(struct spi_device *spi) |
406 | { | 301 | { |
302 | snd_soc_unregister_codec(&spi->dev); | ||
303 | kfree(spi_get_drvdata(spi)); | ||
407 | return 0; | 304 | return 0; |
408 | } | 305 | } |
409 | 306 | ||
410 | static struct spi_driver wm8728_spi_driver = { | 307 | static struct spi_driver wm8728_spi_driver = { |
411 | .driver = { | 308 | .driver = { |
412 | .name = "wm8728", | 309 | .name = "wm8728-codec", |
413 | .bus = &spi_bus_type, | 310 | .bus = &spi_bus_type, |
414 | .owner = THIS_MODULE, | 311 | .owner = THIS_MODULE, |
415 | }, | 312 | }, |
@@ -418,85 +315,80 @@ static struct spi_driver wm8728_spi_driver = { | |||
418 | }; | 315 | }; |
419 | #endif /* CONFIG_SPI_MASTER */ | 316 | #endif /* CONFIG_SPI_MASTER */ |
420 | 317 | ||
421 | static int wm8728_probe(struct platform_device *pdev) | 318 | #if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE) |
319 | static __devinit int wm8728_i2c_probe(struct i2c_client *i2c, | ||
320 | const struct i2c_device_id *id) | ||
422 | { | 321 | { |
423 | struct snd_soc_device *socdev = platform_get_drvdata(pdev); | 322 | struct wm8728_priv *wm8728; |
424 | struct wm8728_setup_data *setup; | 323 | int ret; |
425 | struct snd_soc_codec *codec; | ||
426 | int ret = 0; | ||
427 | 324 | ||
428 | setup = socdev->codec_data; | 325 | wm8728 = kzalloc(sizeof(struct wm8728_priv), GFP_KERNEL); |
429 | codec = kzalloc(sizeof(struct snd_soc_codec), GFP_KERNEL); | 326 | if (wm8728 == NULL) |
430 | if (codec == NULL) | ||
431 | return -ENOMEM; | 327 | return -ENOMEM; |
432 | 328 | ||
433 | socdev->card->codec = codec; | 329 | i2c_set_clientdata(i2c, wm8728); |
434 | mutex_init(&codec->mutex); | 330 | wm8728->control_type = SND_SOC_I2C; |
435 | INIT_LIST_HEAD(&codec->dapm_widgets); | 331 | |
436 | INIT_LIST_HEAD(&codec->dapm_paths); | 332 | ret = snd_soc_register_codec(&i2c->dev, |
333 | &soc_codec_dev_wm8728, &wm8728_dai, 1); | ||
334 | if (ret < 0) | ||
335 | kfree(wm8728); | ||
336 | return ret; | ||
337 | } | ||
338 | |||
339 | static __devexit int wm8728_i2c_remove(struct i2c_client *client) | ||
340 | { | ||
341 | snd_soc_unregister_codec(&client->dev); | ||
342 | kfree(i2c_get_clientdata(client)); | ||
343 | return 0; | ||
344 | } | ||
437 | 345 | ||
438 | wm8728_socdev = socdev; | 346 | static const struct i2c_device_id wm8728_i2c_id[] = { |
439 | ret = -ENODEV; | 347 | { "wm8728", 0 }, |
348 | { } | ||
349 | }; | ||
350 | MODULE_DEVICE_TABLE(i2c, wm8728_i2c_id); | ||
351 | |||
352 | static struct i2c_driver wm8728_i2c_driver = { | ||
353 | .driver = { | ||
354 | .name = "wm8728-codec", | ||
355 | .owner = THIS_MODULE, | ||
356 | }, | ||
357 | .probe = wm8728_i2c_probe, | ||
358 | .remove = __devexit_p(wm8728_i2c_remove), | ||
359 | .id_table = wm8728_i2c_id, | ||
360 | }; | ||
361 | #endif | ||
440 | 362 | ||
363 | static int __init wm8728_modinit(void) | ||
364 | { | ||
365 | int ret = 0; | ||
441 | #if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE) | 366 | #if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE) |
442 | if (setup->i2c_address) { | 367 | ret = i2c_add_driver(&wm8728_i2c_driver); |
443 | ret = wm8728_add_i2c_device(pdev, setup); | 368 | if (ret != 0) { |
369 | printk(KERN_ERR "Failed to register wm8728 I2C driver: %d\n", | ||
370 | ret); | ||
444 | } | 371 | } |
445 | #endif | 372 | #endif |
446 | #if defined(CONFIG_SPI_MASTER) | 373 | #if defined(CONFIG_SPI_MASTER) |
447 | if (setup->spi) { | 374 | ret = spi_register_driver(&wm8728_spi_driver); |
448 | ret = spi_register_driver(&wm8728_spi_driver); | 375 | if (ret != 0) { |
449 | if (ret != 0) | 376 | printk(KERN_ERR "Failed to register wm8728 SPI driver: %d\n", |
450 | printk(KERN_ERR "can't add spi driver"); | 377 | ret); |
451 | } | 378 | } |
452 | #endif | 379 | #endif |
453 | |||
454 | if (ret != 0) | ||
455 | kfree(codec); | ||
456 | |||
457 | return ret; | 380 | return ret; |
458 | } | 381 | } |
382 | module_init(wm8728_modinit); | ||
459 | 383 | ||
460 | /* power down chip */ | 384 | static void __exit wm8728_exit(void) |
461 | static int wm8728_remove(struct platform_device *pdev) | ||
462 | { | 385 | { |
463 | struct snd_soc_device *socdev = platform_get_drvdata(pdev); | ||
464 | struct snd_soc_codec *codec = socdev->card->codec; | ||
465 | |||
466 | if (codec->control_data) | ||
467 | wm8728_set_bias_level(codec, SND_SOC_BIAS_OFF); | ||
468 | |||
469 | snd_soc_free_pcms(socdev); | ||
470 | snd_soc_dapm_free(socdev); | ||
471 | #if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE) | 386 | #if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE) |
472 | i2c_unregister_device(codec->control_data); | ||
473 | i2c_del_driver(&wm8728_i2c_driver); | 387 | i2c_del_driver(&wm8728_i2c_driver); |
474 | #endif | 388 | #endif |
475 | #if defined(CONFIG_SPI_MASTER) | 389 | #if defined(CONFIG_SPI_MASTER) |
476 | spi_unregister_driver(&wm8728_spi_driver); | 390 | spi_unregister_driver(&wm8728_spi_driver); |
477 | #endif | 391 | #endif |
478 | kfree(codec); | ||
479 | |||
480 | return 0; | ||
481 | } | ||
482 | |||
483 | struct snd_soc_codec_device soc_codec_dev_wm8728 = { | ||
484 | .probe = wm8728_probe, | ||
485 | .remove = wm8728_remove, | ||
486 | .suspend = wm8728_suspend, | ||
487 | .resume = wm8728_resume, | ||
488 | }; | ||
489 | EXPORT_SYMBOL_GPL(soc_codec_dev_wm8728); | ||
490 | |||
491 | static int __init wm8728_modinit(void) | ||
492 | { | ||
493 | return snd_soc_register_dai(&wm8728_dai); | ||
494 | } | ||
495 | module_init(wm8728_modinit); | ||
496 | |||
497 | static void __exit wm8728_exit(void) | ||
498 | { | ||
499 | snd_soc_unregister_dai(&wm8728_dai); | ||
500 | } | 392 | } |
501 | module_exit(wm8728_exit); | 393 | module_exit(wm8728_exit); |
502 | 394 | ||
diff --git a/sound/soc/codecs/wm8728.h b/sound/soc/codecs/wm8728.h index d269c132474b..8aea362ffd47 100644 --- a/sound/soc/codecs/wm8728.h +++ b/sound/soc/codecs/wm8728.h | |||
@@ -18,13 +18,4 @@ | |||
18 | #define WM8728_DACCTL 0x02 | 18 | #define WM8728_DACCTL 0x02 |
19 | #define WM8728_IFCTL 0x03 | 19 | #define WM8728_IFCTL 0x03 |
20 | 20 | ||
21 | struct wm8728_setup_data { | ||
22 | int spi; | ||
23 | int i2c_bus; | ||
24 | unsigned short i2c_address; | ||
25 | }; | ||
26 | |||
27 | extern struct snd_soc_dai wm8728_dai; | ||
28 | extern struct snd_soc_codec_device soc_codec_dev_wm8728; | ||
29 | |||
30 | #endif | 21 | #endif |
diff --git a/sound/soc/codecs/wm8731.c b/sound/soc/codecs/wm8731.c index 0ab9b6355297..19844fc8cb1d 100644 --- a/sound/soc/codecs/wm8731.c +++ b/sound/soc/codecs/wm8731.c | |||
@@ -32,9 +32,6 @@ | |||
32 | 32 | ||
33 | #include "wm8731.h" | 33 | #include "wm8731.h" |
34 | 34 | ||
35 | static struct snd_soc_codec *wm8731_codec; | ||
36 | struct snd_soc_codec_device soc_codec_dev_wm8731; | ||
37 | |||
38 | #define WM8731_NUM_SUPPLIES 4 | 35 | #define WM8731_NUM_SUPPLIES 4 |
39 | static const char *wm8731_supply_names[WM8731_NUM_SUPPLIES] = { | 36 | static const char *wm8731_supply_names[WM8731_NUM_SUPPLIES] = { |
40 | "AVDD", | 37 | "AVDD", |
@@ -45,7 +42,7 @@ static const char *wm8731_supply_names[WM8731_NUM_SUPPLIES] = { | |||
45 | 42 | ||
46 | /* codec private data */ | 43 | /* codec private data */ |
47 | struct wm8731_priv { | 44 | struct wm8731_priv { |
48 | struct snd_soc_codec codec; | 45 | enum snd_soc_control_type control_type; |
49 | struct regulator_bulk_data supplies[WM8731_NUM_SUPPLIES]; | 46 | struct regulator_bulk_data supplies[WM8731_NUM_SUPPLIES]; |
50 | u16 reg_cache[WM8731_CACHEREGNUM]; | 47 | u16 reg_cache[WM8731_CACHEREGNUM]; |
51 | unsigned int sysclk; | 48 | unsigned int sysclk; |
@@ -222,9 +219,7 @@ static int wm8731_hw_params(struct snd_pcm_substream *substream, | |||
222 | struct snd_pcm_hw_params *params, | 219 | struct snd_pcm_hw_params *params, |
223 | struct snd_soc_dai *dai) | 220 | struct snd_soc_dai *dai) |
224 | { | 221 | { |
225 | struct snd_soc_pcm_runtime *rtd = substream->private_data; | 222 | struct snd_soc_codec *codec = dai->codec; |
226 | struct snd_soc_device *socdev = rtd->socdev; | ||
227 | struct snd_soc_codec *codec = socdev->card->codec; | ||
228 | struct wm8731_priv *wm8731 = snd_soc_codec_get_drvdata(codec); | 223 | struct wm8731_priv *wm8731 = snd_soc_codec_get_drvdata(codec); |
229 | u16 iface = snd_soc_read(codec, WM8731_IFACE) & 0xfff3; | 224 | u16 iface = snd_soc_read(codec, WM8731_IFACE) & 0xfff3; |
230 | int i = get_coeff(wm8731->sysclk, params_rate(params)); | 225 | int i = get_coeff(wm8731->sysclk, params_rate(params)); |
@@ -252,9 +247,7 @@ static int wm8731_hw_params(struct snd_pcm_substream *substream, | |||
252 | static int wm8731_pcm_prepare(struct snd_pcm_substream *substream, | 247 | static int wm8731_pcm_prepare(struct snd_pcm_substream *substream, |
253 | struct snd_soc_dai *dai) | 248 | struct snd_soc_dai *dai) |
254 | { | 249 | { |
255 | struct snd_soc_pcm_runtime *rtd = substream->private_data; | 250 | struct snd_soc_codec *codec = dai->codec; |
256 | struct snd_soc_device *socdev = rtd->socdev; | ||
257 | struct snd_soc_codec *codec = socdev->card->codec; | ||
258 | 251 | ||
259 | /* set active */ | 252 | /* set active */ |
260 | snd_soc_write(codec, WM8731_ACTIVE, 0x0001); | 253 | snd_soc_write(codec, WM8731_ACTIVE, 0x0001); |
@@ -265,9 +258,7 @@ static int wm8731_pcm_prepare(struct snd_pcm_substream *substream, | |||
265 | static void wm8731_shutdown(struct snd_pcm_substream *substream, | 258 | static void wm8731_shutdown(struct snd_pcm_substream *substream, |
266 | struct snd_soc_dai *dai) | 259 | struct snd_soc_dai *dai) |
267 | { | 260 | { |
268 | struct snd_soc_pcm_runtime *rtd = substream->private_data; | 261 | struct snd_soc_codec *codec = dai->codec; |
269 | struct snd_soc_device *socdev = rtd->socdev; | ||
270 | struct snd_soc_codec *codec = socdev->card->codec; | ||
271 | 262 | ||
272 | /* deactivate */ | 263 | /* deactivate */ |
273 | if (!codec->active) { | 264 | if (!codec->active) { |
@@ -428,8 +419,8 @@ static struct snd_soc_dai_ops wm8731_dai_ops = { | |||
428 | .set_fmt = wm8731_set_dai_fmt, | 419 | .set_fmt = wm8731_set_dai_fmt, |
429 | }; | 420 | }; |
430 | 421 | ||
431 | struct snd_soc_dai wm8731_dai = { | 422 | static struct snd_soc_dai_driver wm8731_dai = { |
432 | .name = "WM8731", | 423 | .name = "wm8731-hifi", |
433 | .playback = { | 424 | .playback = { |
434 | .stream_name = "Playback", | 425 | .stream_name = "Playback", |
435 | .channels_min = 1, | 426 | .channels_min = 1, |
@@ -445,24 +436,17 @@ struct snd_soc_dai wm8731_dai = { | |||
445 | .ops = &wm8731_dai_ops, | 436 | .ops = &wm8731_dai_ops, |
446 | .symmetric_rates = 1, | 437 | .symmetric_rates = 1, |
447 | }; | 438 | }; |
448 | EXPORT_SYMBOL_GPL(wm8731_dai); | ||
449 | 439 | ||
450 | #ifdef CONFIG_PM | 440 | #ifdef CONFIG_PM |
451 | static int wm8731_suspend(struct platform_device *pdev, pm_message_t state) | 441 | static int wm8731_suspend(struct snd_soc_codec *codec, pm_message_t state) |
452 | { | 442 | { |
453 | struct snd_soc_device *socdev = platform_get_drvdata(pdev); | ||
454 | struct snd_soc_codec *codec = socdev->card->codec; | ||
455 | |||
456 | wm8731_set_bias_level(codec, SND_SOC_BIAS_OFF); | 443 | wm8731_set_bias_level(codec, SND_SOC_BIAS_OFF); |
457 | 444 | ||
458 | return 0; | 445 | return 0; |
459 | } | 446 | } |
460 | 447 | ||
461 | static int wm8731_resume(struct platform_device *pdev) | 448 | static int wm8731_resume(struct snd_soc_codec *codec) |
462 | { | 449 | { |
463 | struct snd_soc_device *socdev = platform_get_drvdata(pdev); | ||
464 | struct snd_soc_codec *codec = socdev->card->codec; | ||
465 | |||
466 | wm8731_set_bias_level(codec, SND_SOC_BIAS_STANDBY); | 450 | wm8731_set_bias_level(codec, SND_SOC_BIAS_STANDBY); |
467 | 451 | ||
468 | return 0; | 452 | return 0; |
@@ -472,88 +456,17 @@ static int wm8731_resume(struct platform_device *pdev) | |||
472 | #define wm8731_resume NULL | 456 | #define wm8731_resume NULL |
473 | #endif | 457 | #endif |
474 | 458 | ||
475 | static int wm8731_probe(struct platform_device *pdev) | 459 | static int wm8731_probe(struct snd_soc_codec *codec) |
476 | { | ||
477 | struct snd_soc_device *socdev = platform_get_drvdata(pdev); | ||
478 | struct snd_soc_codec *codec; | ||
479 | int ret = 0; | ||
480 | |||
481 | if (wm8731_codec == NULL) { | ||
482 | dev_err(&pdev->dev, "Codec device not registered\n"); | ||
483 | return -ENODEV; | ||
484 | } | ||
485 | |||
486 | socdev->card->codec = wm8731_codec; | ||
487 | codec = wm8731_codec; | ||
488 | |||
489 | /* register pcms */ | ||
490 | ret = snd_soc_new_pcms(socdev, SNDRV_DEFAULT_IDX1, SNDRV_DEFAULT_STR1); | ||
491 | if (ret < 0) { | ||
492 | dev_err(codec->dev, "failed to create pcms: %d\n", ret); | ||
493 | goto pcm_err; | ||
494 | } | ||
495 | |||
496 | snd_soc_add_controls(codec, wm8731_snd_controls, | ||
497 | ARRAY_SIZE(wm8731_snd_controls)); | ||
498 | wm8731_add_widgets(codec); | ||
499 | |||
500 | return ret; | ||
501 | |||
502 | pcm_err: | ||
503 | return ret; | ||
504 | } | ||
505 | |||
506 | /* power down chip */ | ||
507 | static int wm8731_remove(struct platform_device *pdev) | ||
508 | { | 460 | { |
509 | struct snd_soc_device *socdev = platform_get_drvdata(pdev); | 461 | struct wm8731_priv *wm8731 = snd_soc_codec_get_drvdata(codec); |
510 | 462 | int ret = 0, i; | |
511 | snd_soc_free_pcms(socdev); | ||
512 | snd_soc_dapm_free(socdev); | ||
513 | |||
514 | return 0; | ||
515 | } | ||
516 | |||
517 | struct snd_soc_codec_device soc_codec_dev_wm8731 = { | ||
518 | .probe = wm8731_probe, | ||
519 | .remove = wm8731_remove, | ||
520 | .suspend = wm8731_suspend, | ||
521 | .resume = wm8731_resume, | ||
522 | }; | ||
523 | EXPORT_SYMBOL_GPL(soc_codec_dev_wm8731); | ||
524 | |||
525 | static int wm8731_register(struct wm8731_priv *wm8731, | ||
526 | enum snd_soc_control_type control) | ||
527 | { | ||
528 | int ret, i; | ||
529 | struct snd_soc_codec *codec = &wm8731->codec; | ||
530 | |||
531 | if (wm8731_codec) { | ||
532 | dev_err(codec->dev, "Another WM8731 is registered\n"); | ||
533 | ret = -EINVAL; | ||
534 | goto err; | ||
535 | } | ||
536 | |||
537 | mutex_init(&codec->mutex); | ||
538 | INIT_LIST_HEAD(&codec->dapm_widgets); | ||
539 | INIT_LIST_HEAD(&codec->dapm_paths); | ||
540 | |||
541 | snd_soc_codec_set_drvdata(codec, wm8731); | ||
542 | codec->name = "WM8731"; | ||
543 | codec->owner = THIS_MODULE; | ||
544 | codec->bias_level = SND_SOC_BIAS_OFF; | ||
545 | codec->set_bias_level = wm8731_set_bias_level; | ||
546 | codec->dai = &wm8731_dai; | ||
547 | codec->num_dai = 1; | ||
548 | codec->reg_cache_size = WM8731_CACHEREGNUM; | ||
549 | codec->reg_cache = &wm8731->reg_cache; | ||
550 | 463 | ||
551 | memcpy(codec->reg_cache, wm8731_reg, sizeof(wm8731_reg)); | 464 | codec->bias_level = SND_SOC_BIAS_OFF, |
552 | 465 | ||
553 | ret = snd_soc_codec_set_cache_io(codec, 7, 9, control); | 466 | ret = snd_soc_codec_set_cache_io(codec, 7, 9, wm8731->control_type); |
554 | if (ret < 0) { | 467 | if (ret < 0) { |
555 | dev_err(codec->dev, "Failed to set cache I/O: %d\n", ret); | 468 | dev_err(codec->dev, "Failed to set cache I/O: %d\n", ret); |
556 | goto err; | 469 | return ret; |
557 | } | 470 | } |
558 | 471 | ||
559 | for (i = 0; i < ARRAY_SIZE(wm8731->supplies); i++) | 472 | for (i = 0; i < ARRAY_SIZE(wm8731->supplies); i++) |
@@ -563,7 +476,7 @@ static int wm8731_register(struct wm8731_priv *wm8731, | |||
563 | wm8731->supplies); | 476 | wm8731->supplies); |
564 | if (ret != 0) { | 477 | if (ret != 0) { |
565 | dev_err(codec->dev, "Failed to request supplies: %d\n", ret); | 478 | dev_err(codec->dev, "Failed to request supplies: %d\n", ret); |
566 | goto err; | 479 | return ret; |
567 | } | 480 | } |
568 | 481 | ||
569 | ret = regulator_bulk_enable(ARRAY_SIZE(wm8731->supplies), | 482 | ret = regulator_bulk_enable(ARRAY_SIZE(wm8731->supplies), |
@@ -579,8 +492,6 @@ static int wm8731_register(struct wm8731_priv *wm8731, | |||
579 | goto err_regulator_enable; | 492 | goto err_regulator_enable; |
580 | } | 493 | } |
581 | 494 | ||
582 | wm8731_dai.dev = codec->dev; | ||
583 | |||
584 | wm8731_set_bias_level(codec, SND_SOC_BIAS_STANDBY); | 495 | wm8731_set_bias_level(codec, SND_SOC_BIAS_STANDBY); |
585 | 496 | ||
586 | /* Latch the update bits */ | 497 | /* Latch the update bits */ |
@@ -592,78 +503,78 @@ static int wm8731_register(struct wm8731_priv *wm8731, | |||
592 | /* Disable bypass path by default */ | 503 | /* Disable bypass path by default */ |
593 | snd_soc_update_bits(codec, WM8731_APANA, 0x4, 0); | 504 | snd_soc_update_bits(codec, WM8731_APANA, 0x4, 0); |
594 | 505 | ||
595 | wm8731_codec = codec; | 506 | snd_soc_add_controls(codec, wm8731_snd_controls, |
596 | 507 | ARRAY_SIZE(wm8731_snd_controls)); | |
597 | ret = snd_soc_register_codec(codec); | 508 | wm8731_add_widgets(codec); |
598 | if (ret != 0) { | ||
599 | dev_err(codec->dev, "Failed to register codec: %d\n", ret); | ||
600 | goto err_regulator_enable; | ||
601 | } | ||
602 | |||
603 | ret = snd_soc_register_dai(&wm8731_dai); | ||
604 | if (ret != 0) { | ||
605 | dev_err(codec->dev, "Failed to register DAI: %d\n", ret); | ||
606 | snd_soc_unregister_codec(codec); | ||
607 | goto err_codec; | ||
608 | } | ||
609 | 509 | ||
610 | /* Regulators will have been enabled by bias management */ | 510 | /* Regulators will have been enabled by bias management */ |
611 | regulator_bulk_disable(ARRAY_SIZE(wm8731->supplies), wm8731->supplies); | 511 | regulator_bulk_disable(ARRAY_SIZE(wm8731->supplies), wm8731->supplies); |
612 | 512 | ||
613 | return 0; | 513 | return 0; |
614 | 514 | ||
615 | err_codec: | ||
616 | snd_soc_unregister_codec(codec); | ||
617 | err_regulator_enable: | 515 | err_regulator_enable: |
618 | regulator_bulk_disable(ARRAY_SIZE(wm8731->supplies), wm8731->supplies); | 516 | regulator_bulk_disable(ARRAY_SIZE(wm8731->supplies), wm8731->supplies); |
619 | err_regulator_get: | 517 | err_regulator_get: |
620 | regulator_bulk_free(ARRAY_SIZE(wm8731->supplies), wm8731->supplies); | 518 | regulator_bulk_free(ARRAY_SIZE(wm8731->supplies), wm8731->supplies); |
621 | err: | 519 | |
622 | kfree(wm8731); | 520 | kfree(wm8731); |
623 | return ret; | 521 | return ret; |
624 | } | 522 | } |
625 | 523 | ||
626 | static void wm8731_unregister(struct wm8731_priv *wm8731) | 524 | /* power down chip */ |
525 | static int wm8731_remove(struct snd_soc_codec *codec) | ||
627 | { | 526 | { |
628 | wm8731_set_bias_level(&wm8731->codec, SND_SOC_BIAS_OFF); | 527 | struct wm8731_priv *wm8731 = snd_soc_codec_get_drvdata(codec); |
629 | snd_soc_unregister_dai(&wm8731_dai); | 528 | |
630 | snd_soc_unregister_codec(&wm8731->codec); | 529 | wm8731_set_bias_level(codec, SND_SOC_BIAS_OFF); |
530 | |||
531 | regulator_bulk_disable(ARRAY_SIZE(wm8731->supplies), wm8731->supplies); | ||
631 | regulator_bulk_free(ARRAY_SIZE(wm8731->supplies), wm8731->supplies); | 532 | regulator_bulk_free(ARRAY_SIZE(wm8731->supplies), wm8731->supplies); |
632 | kfree(wm8731); | 533 | |
633 | wm8731_codec = NULL; | 534 | return 0; |
634 | } | 535 | } |
635 | 536 | ||
537 | static struct snd_soc_codec_driver soc_codec_dev_wm8731 = { | ||
538 | .probe = wm8731_probe, | ||
539 | .remove = wm8731_remove, | ||
540 | .suspend = wm8731_suspend, | ||
541 | .resume = wm8731_resume, | ||
542 | .set_bias_level = wm8731_set_bias_level, | ||
543 | .reg_cache_size = sizeof(wm8731_reg), | ||
544 | .reg_word_size = sizeof(u16), | ||
545 | .reg_cache_default = wm8731_reg, | ||
546 | }; | ||
547 | |||
636 | #if defined(CONFIG_SPI_MASTER) | 548 | #if defined(CONFIG_SPI_MASTER) |
637 | static int __devinit wm8731_spi_probe(struct spi_device *spi) | 549 | static int __devinit wm8731_spi_probe(struct spi_device *spi) |
638 | { | 550 | { |
639 | struct snd_soc_codec *codec; | ||
640 | struct wm8731_priv *wm8731; | 551 | struct wm8731_priv *wm8731; |
552 | int ret; | ||
641 | 553 | ||
642 | wm8731 = kzalloc(sizeof(struct wm8731_priv), GFP_KERNEL); | 554 | wm8731 = kzalloc(sizeof(struct wm8731_priv), GFP_KERNEL); |
643 | if (wm8731 == NULL) | 555 | if (wm8731 == NULL) |
644 | return -ENOMEM; | 556 | return -ENOMEM; |
645 | 557 | ||
646 | codec = &wm8731->codec; | 558 | wm8731->control_type = SND_SOC_SPI; |
647 | codec->control_data = spi; | 559 | spi_set_drvdata(spi, wm8731); |
648 | codec->dev = &spi->dev; | ||
649 | |||
650 | dev_set_drvdata(&spi->dev, wm8731); | ||
651 | 560 | ||
652 | return wm8731_register(wm8731, SND_SOC_SPI); | 561 | ret = snd_soc_register_codec(&spi->dev, |
562 | &soc_codec_dev_wm8731, &wm8731_dai, 1); | ||
563 | if (ret < 0) | ||
564 | kfree(wm8731); | ||
565 | return ret; | ||
653 | } | 566 | } |
654 | 567 | ||
655 | static int __devexit wm8731_spi_remove(struct spi_device *spi) | 568 | static int __devexit wm8731_spi_remove(struct spi_device *spi) |
656 | { | 569 | { |
657 | struct wm8731_priv *wm8731 = dev_get_drvdata(&spi->dev); | 570 | snd_soc_unregister_codec(&spi->dev); |
658 | 571 | kfree(spi_get_drvdata(spi)); | |
659 | wm8731_unregister(wm8731); | ||
660 | |||
661 | return 0; | 572 | return 0; |
662 | } | 573 | } |
663 | 574 | ||
664 | static struct spi_driver wm8731_spi_driver = { | 575 | static struct spi_driver wm8731_spi_driver = { |
665 | .driver = { | 576 | .driver = { |
666 | .name = "wm8731", | 577 | .name = "wm8731-codec", |
667 | .bus = &spi_bus_type, | 578 | .bus = &spi_bus_type, |
668 | .owner = THIS_MODULE, | 579 | .owner = THIS_MODULE, |
669 | }, | 580 | }, |
@@ -677,26 +588,26 @@ static __devinit int wm8731_i2c_probe(struct i2c_client *i2c, | |||
677 | const struct i2c_device_id *id) | 588 | const struct i2c_device_id *id) |
678 | { | 589 | { |
679 | struct wm8731_priv *wm8731; | 590 | struct wm8731_priv *wm8731; |
680 | struct snd_soc_codec *codec; | 591 | int ret; |
681 | 592 | ||
682 | wm8731 = kzalloc(sizeof(struct wm8731_priv), GFP_KERNEL); | 593 | wm8731 = kzalloc(sizeof(struct wm8731_priv), GFP_KERNEL); |
683 | if (wm8731 == NULL) | 594 | if (wm8731 == NULL) |
684 | return -ENOMEM; | 595 | return -ENOMEM; |
685 | 596 | ||
686 | codec = &wm8731->codec; | ||
687 | |||
688 | i2c_set_clientdata(i2c, wm8731); | 597 | i2c_set_clientdata(i2c, wm8731); |
689 | codec->control_data = i2c; | 598 | wm8731->control_type = SND_SOC_I2C; |
690 | 599 | ||
691 | codec->dev = &i2c->dev; | 600 | ret = snd_soc_register_codec(&i2c->dev, |
692 | 601 | &soc_codec_dev_wm8731, &wm8731_dai, 1); | |
693 | return wm8731_register(wm8731, SND_SOC_I2C); | 602 | if (ret < 0) |
603 | kfree(wm8731); | ||
604 | return ret; | ||
694 | } | 605 | } |
695 | 606 | ||
696 | static __devexit int wm8731_i2c_remove(struct i2c_client *client) | 607 | static __devexit int wm8731_i2c_remove(struct i2c_client *client) |
697 | { | 608 | { |
698 | struct wm8731_priv *wm8731 = i2c_get_clientdata(client); | 609 | snd_soc_unregister_codec(&client->dev); |
699 | wm8731_unregister(wm8731); | 610 | kfree(i2c_get_clientdata(client)); |
700 | return 0; | 611 | return 0; |
701 | } | 612 | } |
702 | 613 | ||
@@ -708,7 +619,7 @@ MODULE_DEVICE_TABLE(i2c, wm8731_i2c_id); | |||
708 | 619 | ||
709 | static struct i2c_driver wm8731_i2c_driver = { | 620 | static struct i2c_driver wm8731_i2c_driver = { |
710 | .driver = { | 621 | .driver = { |
711 | .name = "wm8731", | 622 | .name = "wm8731-codec", |
712 | .owner = THIS_MODULE, | 623 | .owner = THIS_MODULE, |
713 | }, | 624 | }, |
714 | .probe = wm8731_i2c_probe, | 625 | .probe = wm8731_i2c_probe, |
@@ -719,7 +630,7 @@ static struct i2c_driver wm8731_i2c_driver = { | |||
719 | 630 | ||
720 | static int __init wm8731_modinit(void) | 631 | static int __init wm8731_modinit(void) |
721 | { | 632 | { |
722 | int ret; | 633 | int ret = 0; |
723 | #if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE) | 634 | #if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE) |
724 | ret = i2c_add_driver(&wm8731_i2c_driver); | 635 | ret = i2c_add_driver(&wm8731_i2c_driver); |
725 | if (ret != 0) { | 636 | if (ret != 0) { |
@@ -734,7 +645,7 @@ static int __init wm8731_modinit(void) | |||
734 | ret); | 645 | ret); |
735 | } | 646 | } |
736 | #endif | 647 | #endif |
737 | return 0; | 648 | return ret; |
738 | } | 649 | } |
739 | module_init(wm8731_modinit); | 650 | module_init(wm8731_modinit); |
740 | 651 | ||
diff --git a/sound/soc/codecs/wm8731.h b/sound/soc/codecs/wm8731.h index cd7b806e8ad0..73a70e206ba9 100644 --- a/sound/soc/codecs/wm8731.h +++ b/sound/soc/codecs/wm8731.h | |||
@@ -34,7 +34,4 @@ | |||
34 | #define WM8731_SYSCLK 0 | 34 | #define WM8731_SYSCLK 0 |
35 | #define WM8731_DAI 0 | 35 | #define WM8731_DAI 0 |
36 | 36 | ||
37 | extern struct snd_soc_dai wm8731_dai; | ||
38 | extern struct snd_soc_codec_device soc_codec_dev_wm8731; | ||
39 | |||
40 | #endif | 37 | #endif |
diff --git a/sound/soc/codecs/wm8741.c b/sound/soc/codecs/wm8741.c index b9ea8904ad4b..782fe539662b 100644 --- a/sound/soc/codecs/wm8741.c +++ b/sound/soc/codecs/wm8741.c | |||
@@ -30,9 +30,6 @@ | |||
30 | 30 | ||
31 | #include "wm8741.h" | 31 | #include "wm8741.h" |
32 | 32 | ||
33 | static struct snd_soc_codec *wm8741_codec; | ||
34 | struct snd_soc_codec_device soc_codec_dev_wm8741; | ||
35 | |||
36 | #define WM8741_NUM_SUPPLIES 2 | 33 | #define WM8741_NUM_SUPPLIES 2 |
37 | static const char *wm8741_supply_names[WM8741_NUM_SUPPLIES] = { | 34 | static const char *wm8741_supply_names[WM8741_NUM_SUPPLIES] = { |
38 | "AVDD", | 35 | "AVDD", |
@@ -43,7 +40,7 @@ static const char *wm8741_supply_names[WM8741_NUM_SUPPLIES] = { | |||
43 | 40 | ||
44 | /* codec private data */ | 41 | /* codec private data */ |
45 | struct wm8741_priv { | 42 | struct wm8741_priv { |
46 | struct snd_soc_codec codec; | 43 | enum snd_soc_control_type control_type; |
47 | u16 reg_cache[WM8741_REGISTER_COUNT]; | 44 | u16 reg_cache[WM8741_REGISTER_COUNT]; |
48 | struct regulator_bulk_data supplies[WM8741_NUM_SUPPLIES]; | 45 | struct regulator_bulk_data supplies[WM8741_NUM_SUPPLIES]; |
49 | unsigned int sysclk; | 46 | unsigned int sysclk; |
@@ -145,8 +142,7 @@ static int wm8741_hw_params(struct snd_pcm_substream *substream, | |||
145 | struct snd_soc_dai *dai) | 142 | struct snd_soc_dai *dai) |
146 | { | 143 | { |
147 | struct snd_soc_pcm_runtime *rtd = substream->private_data; | 144 | struct snd_soc_pcm_runtime *rtd = substream->private_data; |
148 | struct snd_soc_device *socdev = rtd->socdev; | 145 | struct snd_soc_codec *codec = rtd->codec; |
149 | struct snd_soc_codec *codec = socdev->card->codec; | ||
150 | struct wm8741_priv *wm8741 = snd_soc_codec_get_drvdata(codec); | 146 | struct wm8741_priv *wm8741 = snd_soc_codec_get_drvdata(codec); |
151 | u16 iface = snd_soc_read(codec, WM8741_FORMAT_CONTROL) & 0x1FC; | 147 | u16 iface = snd_soc_read(codec, WM8741_FORMAT_CONTROL) & 0x1FC; |
152 | int i; | 148 | int i; |
@@ -314,7 +310,7 @@ static struct snd_soc_dai_ops wm8741_dai_ops = { | |||
314 | .set_fmt = wm8741_set_dai_fmt, | 310 | .set_fmt = wm8741_set_dai_fmt, |
315 | }; | 311 | }; |
316 | 312 | ||
317 | struct snd_soc_dai wm8741_dai = { | 313 | static struct snd_soc_dai_driver wm8741_dai = { |
318 | .name = "WM8741", | 314 | .name = "WM8741", |
319 | .playback = { | 315 | .playback = { |
320 | .stream_name = "Playback", | 316 | .stream_name = "Playback", |
@@ -325,13 +321,10 @@ struct snd_soc_dai wm8741_dai = { | |||
325 | }, | 321 | }, |
326 | .ops = &wm8741_dai_ops, | 322 | .ops = &wm8741_dai_ops, |
327 | }; | 323 | }; |
328 | EXPORT_SYMBOL_GPL(wm8741_dai); | ||
329 | 324 | ||
330 | #ifdef CONFIG_PM | 325 | #ifdef CONFIG_PM |
331 | static int wm8741_resume(struct platform_device *pdev) | 326 | static int wm8741_resume(struct snd_soc_codec *codec) |
332 | { | 327 | { |
333 | struct snd_soc_device *socdev = platform_get_drvdata(pdev); | ||
334 | struct snd_soc_codec *codec = socdev->card->codec; | ||
335 | u16 *cache = codec->reg_cache; | 328 | u16 *cache = codec->reg_cache; |
336 | int i; | 329 | int i; |
337 | 330 | ||
@@ -348,189 +341,103 @@ static int wm8741_resume(struct platform_device *pdev) | |||
348 | #define wm8741_resume NULL | 341 | #define wm8741_resume NULL |
349 | #endif | 342 | #endif |
350 | 343 | ||
351 | static int wm8741_probe(struct platform_device *pdev) | 344 | static int wm8741_probe(struct snd_soc_codec *codec) |
352 | { | 345 | { |
353 | struct snd_soc_device *socdev = platform_get_drvdata(pdev); | 346 | struct wm8741_priv *wm8741 = snd_soc_codec_get_drvdata(codec); |
354 | struct snd_soc_codec *codec; | ||
355 | int ret = 0; | 347 | int ret = 0; |
356 | 348 | ||
357 | if (wm8741_codec == NULL) { | 349 | ret = snd_soc_codec_set_cache_io(codec, 7, 9, wm8741->control_type); |
358 | dev_err(&pdev->dev, "Codec device not registered\n"); | 350 | if (ret != 0) { |
359 | return -ENODEV; | 351 | dev_err(codec->dev, "Failed to set cache I/O: %d\n", ret); |
352 | return ret; | ||
360 | } | 353 | } |
361 | 354 | ||
362 | socdev->card->codec = wm8741_codec; | 355 | ret = wm8741_reset(codec); |
363 | codec = wm8741_codec; | ||
364 | |||
365 | /* register pcms */ | ||
366 | ret = snd_soc_new_pcms(socdev, SNDRV_DEFAULT_IDX1, SNDRV_DEFAULT_STR1); | ||
367 | if (ret < 0) { | 356 | if (ret < 0) { |
368 | dev_err(codec->dev, "failed to create pcms: %d\n", ret); | 357 | dev_err(codec->dev, "Failed to issue reset\n"); |
369 | goto pcm_err; | 358 | return ret; |
370 | } | 359 | } |
371 | 360 | ||
361 | /* Change some default settings - latch VU */ | ||
362 | wm8741->reg_cache[WM8741_DACLLSB_ATTENUATION] |= WM8741_UPDATELL; | ||
363 | wm8741->reg_cache[WM8741_DACLMSB_ATTENUATION] |= WM8741_UPDATELM; | ||
364 | wm8741->reg_cache[WM8741_DACRLSB_ATTENUATION] |= WM8741_UPDATERL; | ||
365 | wm8741->reg_cache[WM8741_DACRLSB_ATTENUATION] |= WM8741_UPDATERM; | ||
366 | |||
372 | snd_soc_add_controls(codec, wm8741_snd_controls, | 367 | snd_soc_add_controls(codec, wm8741_snd_controls, |
373 | ARRAY_SIZE(wm8741_snd_controls)); | 368 | ARRAY_SIZE(wm8741_snd_controls)); |
374 | wm8741_add_widgets(codec); | 369 | wm8741_add_widgets(codec); |
375 | 370 | ||
371 | dev_dbg(codec->dev, "Successful registration\n"); | ||
376 | return ret; | 372 | return ret; |
377 | |||
378 | pcm_err: | ||
379 | return ret; | ||
380 | } | ||
381 | |||
382 | static int wm8741_remove(struct platform_device *pdev) | ||
383 | { | ||
384 | struct snd_soc_device *socdev = platform_get_drvdata(pdev); | ||
385 | |||
386 | snd_soc_free_pcms(socdev); | ||
387 | snd_soc_dapm_free(socdev); | ||
388 | |||
389 | return 0; | ||
390 | } | 373 | } |
391 | 374 | ||
392 | struct snd_soc_codec_device soc_codec_dev_wm8741 = { | 375 | static struct snd_soc_codec_driver soc_codec_dev_wm8741 = { |
393 | .probe = wm8741_probe, | 376 | .probe = wm8741_probe, |
394 | .remove = wm8741_remove, | ||
395 | .resume = wm8741_resume, | 377 | .resume = wm8741_resume, |
378 | .reg_cache_size = sizeof(wm8741_reg_defaults), | ||
379 | .reg_word_size = sizeof(u16), | ||
380 | .reg_cache_default = &wm8741_reg_defaults, | ||
396 | }; | 381 | }; |
397 | EXPORT_SYMBOL_GPL(soc_codec_dev_wm8741); | ||
398 | 382 | ||
399 | static int wm8741_register(struct wm8741_priv *wm8741, | 383 | #if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE) |
400 | enum snd_soc_control_type control) | 384 | static int wm8741_i2c_probe(struct i2c_client *i2c, |
385 | const struct i2c_device_id *id) | ||
401 | { | 386 | { |
402 | int ret; | 387 | struct wm8741_priv *wm8741; |
403 | struct snd_soc_codec *codec = &wm8741->codec; | 388 | int ret, i; |
404 | int i; | ||
405 | |||
406 | if (wm8741_codec) { | ||
407 | dev_err(codec->dev, "Another WM8741 is registered\n"); | ||
408 | return -EINVAL; | ||
409 | } | ||
410 | |||
411 | mutex_init(&codec->mutex); | ||
412 | INIT_LIST_HEAD(&codec->dapm_widgets); | ||
413 | INIT_LIST_HEAD(&codec->dapm_paths); | ||
414 | 389 | ||
415 | snd_soc_codec_set_drvdata(codec, wm8741); | 390 | wm8741 = kzalloc(sizeof(struct wm8741_priv), GFP_KERNEL); |
416 | codec->name = "WM8741"; | 391 | if (wm8741 == NULL) |
417 | codec->owner = THIS_MODULE; | 392 | return -ENOMEM; |
418 | codec->bias_level = SND_SOC_BIAS_OFF; | ||
419 | codec->set_bias_level = NULL; | ||
420 | codec->dai = &wm8741_dai; | ||
421 | codec->num_dai = 1; | ||
422 | codec->reg_cache_size = WM8741_REGISTER_COUNT; | ||
423 | codec->reg_cache = &wm8741->reg_cache; | ||
424 | 393 | ||
425 | wm8741->rate_constraint.list = &wm8741->rate_constraint_list[0]; | 394 | wm8741->rate_constraint.list = &wm8741->rate_constraint_list[0]; |
426 | wm8741->rate_constraint.count = | 395 | wm8741->rate_constraint.count = |
427 | ARRAY_SIZE(wm8741->rate_constraint_list); | 396 | ARRAY_SIZE(wm8741->rate_constraint_list); |
428 | 397 | ||
429 | memcpy(codec->reg_cache, wm8741_reg_defaults, | ||
430 | sizeof(wm8741->reg_cache)); | ||
431 | |||
432 | ret = snd_soc_codec_set_cache_io(codec, 7, 9, control); | ||
433 | if (ret != 0) { | ||
434 | dev_err(codec->dev, "Failed to set cache I/O: %d\n", ret); | ||
435 | goto err; | ||
436 | } | ||
437 | |||
438 | for (i = 0; i < ARRAY_SIZE(wm8741->supplies); i++) | 398 | for (i = 0; i < ARRAY_SIZE(wm8741->supplies); i++) |
439 | wm8741->supplies[i].supply = wm8741_supply_names[i]; | 399 | wm8741->supplies[i].supply = wm8741_supply_names[i]; |
440 | 400 | ||
441 | ret = regulator_bulk_get(codec->dev, ARRAY_SIZE(wm8741->supplies), | 401 | ret = regulator_bulk_get(&i2c->dev, ARRAY_SIZE(wm8741->supplies), |
442 | wm8741->supplies); | 402 | wm8741->supplies); |
443 | if (ret != 0) { | 403 | if (ret != 0) { |
444 | dev_err(codec->dev, "Failed to request supplies: %d\n", ret); | 404 | dev_err(&i2c->dev, "Failed to request supplies: %d\n", ret); |
445 | goto err; | 405 | goto err; |
446 | } | 406 | } |
447 | 407 | ||
448 | ret = regulator_bulk_enable(ARRAY_SIZE(wm8741->supplies), | 408 | ret = regulator_bulk_enable(ARRAY_SIZE(wm8741->supplies), |
449 | wm8741->supplies); | 409 | wm8741->supplies); |
450 | if (ret != 0) { | 410 | if (ret != 0) { |
451 | dev_err(codec->dev, "Failed to enable supplies: %d\n", ret); | 411 | dev_err(&i2c->dev, "Failed to enable supplies: %d\n", ret); |
452 | goto err_get; | 412 | goto err_get; |
453 | } | 413 | } |
454 | 414 | ||
455 | ret = wm8741_reset(codec); | 415 | i2c_set_clientdata(i2c, wm8741); |
456 | if (ret < 0) { | 416 | wm8741->control_type = SND_SOC_I2C; |
457 | dev_err(codec->dev, "Failed to issue reset\n"); | ||
458 | goto err_enable; | ||
459 | } | ||
460 | |||
461 | wm8741_dai.dev = codec->dev; | ||
462 | |||
463 | /* Change some default settings - latch VU */ | ||
464 | wm8741->reg_cache[WM8741_DACLLSB_ATTENUATION] |= WM8741_UPDATELL; | ||
465 | wm8741->reg_cache[WM8741_DACLMSB_ATTENUATION] |= WM8741_UPDATELM; | ||
466 | wm8741->reg_cache[WM8741_DACRLSB_ATTENUATION] |= WM8741_UPDATERL; | ||
467 | wm8741->reg_cache[WM8741_DACRLSB_ATTENUATION] |= WM8741_UPDATERM; | ||
468 | |||
469 | wm8741_codec = codec; | ||
470 | |||
471 | ret = snd_soc_register_codec(codec); | ||
472 | if (ret != 0) { | ||
473 | dev_err(codec->dev, "Failed to register codec: %d\n", ret); | ||
474 | return ret; | ||
475 | } | ||
476 | |||
477 | ret = snd_soc_register_dai(&wm8741_dai); | ||
478 | if (ret != 0) { | ||
479 | dev_err(codec->dev, "Failed to register DAI: %d\n", ret); | ||
480 | snd_soc_unregister_codec(codec); | ||
481 | return ret; | ||
482 | } | ||
483 | 417 | ||
484 | dev_dbg(codec->dev, "Successful registration\n"); | 418 | ret = snd_soc_register_codec(&i2c->dev, |
485 | return 0; | 419 | &soc_codec_dev_wm8741, &wm8741_dai, 1); |
420 | if (ret < 0) | ||
421 | goto err_enable; | ||
422 | return ret; | ||
486 | 423 | ||
487 | err_enable: | 424 | err_enable: |
488 | regulator_bulk_disable(ARRAY_SIZE(wm8741->supplies), wm8741->supplies); | 425 | regulator_bulk_disable(ARRAY_SIZE(wm8741->supplies), wm8741->supplies); |
489 | 426 | ||
490 | err_get: | 427 | err_get: |
491 | regulator_bulk_free(ARRAY_SIZE(wm8741->supplies), wm8741->supplies); | 428 | regulator_bulk_free(ARRAY_SIZE(wm8741->supplies), wm8741->supplies); |
492 | |||
493 | err: | 429 | err: |
494 | kfree(wm8741); | 430 | kfree(wm8741); |
495 | return ret; | 431 | return ret; |
496 | } | 432 | } |
497 | 433 | ||
498 | static void wm8741_unregister(struct wm8741_priv *wm8741) | 434 | static int wm8741_i2c_remove(struct i2c_client *client) |
499 | { | ||
500 | regulator_bulk_free(ARRAY_SIZE(wm8741->supplies), wm8741->supplies); | ||
501 | |||
502 | snd_soc_unregister_dai(&wm8741_dai); | ||
503 | snd_soc_unregister_codec(&wm8741->codec); | ||
504 | kfree(wm8741); | ||
505 | wm8741_codec = NULL; | ||
506 | } | ||
507 | |||
508 | #if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE) | ||
509 | static __devinit int wm8741_i2c_probe(struct i2c_client *i2c, | ||
510 | const struct i2c_device_id *id) | ||
511 | { | ||
512 | struct wm8741_priv *wm8741; | ||
513 | struct snd_soc_codec *codec; | ||
514 | |||
515 | wm8741 = kzalloc(sizeof(struct wm8741_priv), GFP_KERNEL); | ||
516 | if (wm8741 == NULL) | ||
517 | return -ENOMEM; | ||
518 | |||
519 | codec = &wm8741->codec; | ||
520 | codec->hw_write = (hw_write_t)i2c_master_send; | ||
521 | |||
522 | i2c_set_clientdata(i2c, wm8741); | ||
523 | codec->control_data = i2c; | ||
524 | |||
525 | codec->dev = &i2c->dev; | ||
526 | |||
527 | return wm8741_register(wm8741, SND_SOC_I2C); | ||
528 | } | ||
529 | |||
530 | static __devexit int wm8741_i2c_remove(struct i2c_client *client) | ||
531 | { | 435 | { |
532 | struct wm8741_priv *wm8741 = i2c_get_clientdata(client); | 436 | struct wm8741_priv *wm8741 = i2c_get_clientdata(client); |
533 | wm8741_unregister(wm8741); | 437 | |
438 | snd_soc_unregister_codec(&client->dev); | ||
439 | regulator_bulk_free(ARRAY_SIZE(wm8741->supplies), wm8741->supplies); | ||
440 | kfree(i2c_get_clientdata(client)); | ||
534 | return 0; | 441 | return 0; |
535 | } | 442 | } |
536 | 443 | ||
@@ -540,29 +447,29 @@ static const struct i2c_device_id wm8741_i2c_id[] = { | |||
540 | }; | 447 | }; |
541 | MODULE_DEVICE_TABLE(i2c, wm8741_i2c_id); | 448 | MODULE_DEVICE_TABLE(i2c, wm8741_i2c_id); |
542 | 449 | ||
543 | |||
544 | static struct i2c_driver wm8741_i2c_driver = { | 450 | static struct i2c_driver wm8741_i2c_driver = { |
545 | .driver = { | 451 | .driver = { |
546 | .name = "WM8741", | 452 | .name = "wm8741-codec", |
547 | .owner = THIS_MODULE, | 453 | .owner = THIS_MODULE, |
548 | }, | 454 | }, |
549 | .probe = wm8741_i2c_probe, | 455 | .probe = wm8741_i2c_probe, |
550 | .remove = __devexit_p(wm8741_i2c_remove), | 456 | .remove = wm8741_i2c_remove, |
551 | .id_table = wm8741_i2c_id, | 457 | .id_table = wm8741_i2c_id, |
552 | }; | 458 | }; |
553 | #endif | 459 | #endif |
554 | 460 | ||
555 | static int __init wm8741_modinit(void) | 461 | static int __init wm8741_modinit(void) |
556 | { | 462 | { |
557 | int ret; | 463 | int ret = 0; |
464 | |||
558 | #if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE) | 465 | #if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE) |
559 | ret = i2c_add_driver(&wm8741_i2c_driver); | 466 | ret = i2c_add_driver(&wm8741_i2c_driver); |
560 | if (ret != 0) { | 467 | if (ret != 0) { |
561 | printk(KERN_ERR "Failed to register WM8741 I2C driver: %d\n", | 468 | pr_err("Failed to register WM8741 I2C driver: %d\n", ret); |
562 | ret); | ||
563 | } | 469 | } |
564 | #endif | 470 | #endif |
565 | return 0; | 471 | |
472 | return ret; | ||
566 | } | 473 | } |
567 | module_init(wm8741_modinit); | 474 | module_init(wm8741_modinit); |
568 | 475 | ||
diff --git a/sound/soc/codecs/wm8741.h b/sound/soc/codecs/wm8741.h index fdef6ecd1f6f..56c1b1d4a681 100644 --- a/sound/soc/codecs/wm8741.h +++ b/sound/soc/codecs/wm8741.h | |||
@@ -208,7 +208,4 @@ | |||
208 | 208 | ||
209 | #define WM8741_SYSCLK 0 | 209 | #define WM8741_SYSCLK 0 |
210 | 210 | ||
211 | extern struct snd_soc_dai wm8741_dai; | ||
212 | extern struct snd_soc_codec_device soc_codec_dev_wm8741; | ||
213 | |||
214 | #endif | 211 | #endif |
diff --git a/sound/soc/codecs/wm8750.c b/sound/soc/codecs/wm8750.c index e2c05e3e323a..92d4b2aef93b 100644 --- a/sound/soc/codecs/wm8750.c +++ b/sound/soc/codecs/wm8750.c | |||
@@ -52,7 +52,7 @@ static const u16 wm8750_reg[] = { | |||
52 | /* codec private data */ | 52 | /* codec private data */ |
53 | struct wm8750_priv { | 53 | struct wm8750_priv { |
54 | unsigned int sysclk; | 54 | unsigned int sysclk; |
55 | struct snd_soc_codec codec; | 55 | enum snd_soc_control_type control_type; |
56 | u16 reg_cache[ARRAY_SIZE(wm8750_reg)]; | 56 | u16 reg_cache[ARRAY_SIZE(wm8750_reg)]; |
57 | }; | 57 | }; |
58 | 58 | ||
@@ -560,8 +560,7 @@ static int wm8750_pcm_hw_params(struct snd_pcm_substream *substream, | |||
560 | struct snd_soc_dai *dai) | 560 | struct snd_soc_dai *dai) |
561 | { | 561 | { |
562 | struct snd_soc_pcm_runtime *rtd = substream->private_data; | 562 | struct snd_soc_pcm_runtime *rtd = substream->private_data; |
563 | struct snd_soc_device *socdev = rtd->socdev; | 563 | struct snd_soc_codec *codec = rtd->codec; |
564 | struct snd_soc_codec *codec = socdev->card->codec; | ||
565 | struct wm8750_priv *wm8750 = snd_soc_codec_get_drvdata(codec); | 564 | struct wm8750_priv *wm8750 = snd_soc_codec_get_drvdata(codec); |
566 | u16 iface = snd_soc_read(codec, WM8750_IFACE) & 0x1f3; | 565 | u16 iface = snd_soc_read(codec, WM8750_IFACE) & 0x1f3; |
567 | u16 srate = snd_soc_read(codec, WM8750_SRATE) & 0x1c0; | 566 | u16 srate = snd_soc_read(codec, WM8750_SRATE) & 0x1c0; |
@@ -649,8 +648,8 @@ static struct snd_soc_dai_ops wm8750_dai_ops = { | |||
649 | .set_sysclk = wm8750_set_dai_sysclk, | 648 | .set_sysclk = wm8750_set_dai_sysclk, |
650 | }; | 649 | }; |
651 | 650 | ||
652 | struct snd_soc_dai wm8750_dai = { | 651 | static struct snd_soc_dai_driver wm8750_dai = { |
653 | .name = "WM8750", | 652 | .name = "wm8750-hifi", |
654 | .playback = { | 653 | .playback = { |
655 | .stream_name = "Playback", | 654 | .stream_name = "Playback", |
656 | .channels_min = 1, | 655 | .channels_min = 1, |
@@ -665,21 +664,15 @@ struct snd_soc_dai wm8750_dai = { | |||
665 | .formats = WM8750_FORMATS,}, | 664 | .formats = WM8750_FORMATS,}, |
666 | .ops = &wm8750_dai_ops, | 665 | .ops = &wm8750_dai_ops, |
667 | }; | 666 | }; |
668 | EXPORT_SYMBOL_GPL(wm8750_dai); | ||
669 | 667 | ||
670 | static int wm8750_suspend(struct platform_device *pdev, pm_message_t state) | 668 | static int wm8750_suspend(struct snd_soc_codec *codec, pm_message_t state) |
671 | { | 669 | { |
672 | struct snd_soc_device *socdev = platform_get_drvdata(pdev); | ||
673 | struct snd_soc_codec *codec = socdev->card->codec; | ||
674 | |||
675 | wm8750_set_bias_level(codec, SND_SOC_BIAS_OFF); | 670 | wm8750_set_bias_level(codec, SND_SOC_BIAS_OFF); |
676 | return 0; | 671 | return 0; |
677 | } | 672 | } |
678 | 673 | ||
679 | static int wm8750_resume(struct platform_device *pdev) | 674 | static int wm8750_resume(struct snd_soc_codec *codec) |
680 | { | 675 | { |
681 | struct snd_soc_device *socdev = platform_get_drvdata(pdev); | ||
682 | struct snd_soc_codec *codec = socdev->card->codec; | ||
683 | int i; | 676 | int i; |
684 | u8 data[2]; | 677 | u8 data[2]; |
685 | u16 *cache = codec->reg_cache; | 678 | u16 *cache = codec->reg_cache; |
@@ -698,100 +691,21 @@ static int wm8750_resume(struct platform_device *pdev) | |||
698 | return 0; | 691 | return 0; |
699 | } | 692 | } |
700 | 693 | ||
701 | static struct snd_soc_codec *wm8750_codec; | 694 | static int wm8750_probe(struct snd_soc_codec *codec) |
702 | |||
703 | static int wm8750_probe(struct platform_device *pdev) | ||
704 | { | 695 | { |
705 | struct snd_soc_device *socdev = platform_get_drvdata(pdev); | 696 | struct wm8750_priv *wm8750 = snd_soc_codec_get_drvdata(codec); |
706 | struct snd_soc_codec *codec; | 697 | int reg, ret; |
707 | int ret = 0; | ||
708 | |||
709 | if (!wm8750_codec) { | ||
710 | dev_err(&pdev->dev, "WM8750 codec not yet registered\n"); | ||
711 | return -EINVAL; | ||
712 | } | ||
713 | |||
714 | socdev->card->codec = wm8750_codec; | ||
715 | codec = wm8750_codec; | ||
716 | |||
717 | /* register pcms */ | ||
718 | ret = snd_soc_new_pcms(socdev, SNDRV_DEFAULT_IDX1, SNDRV_DEFAULT_STR1); | ||
719 | if (ret < 0) { | ||
720 | printk(KERN_ERR "wm8750: failed to create pcms\n"); | ||
721 | goto err; | ||
722 | } | ||
723 | |||
724 | snd_soc_add_controls(codec, wm8750_snd_controls, | ||
725 | ARRAY_SIZE(wm8750_snd_controls)); | ||
726 | wm8750_add_widgets(codec); | ||
727 | |||
728 | return 0; | ||
729 | |||
730 | err: | ||
731 | return ret; | ||
732 | } | ||
733 | |||
734 | /* power down chip */ | ||
735 | static int wm8750_remove(struct platform_device *pdev) | ||
736 | { | ||
737 | struct snd_soc_device *socdev = platform_get_drvdata(pdev); | ||
738 | |||
739 | snd_soc_free_pcms(socdev); | ||
740 | snd_soc_dapm_free(socdev); | ||
741 | |||
742 | return 0; | ||
743 | } | ||
744 | |||
745 | struct snd_soc_codec_device soc_codec_dev_wm8750 = { | ||
746 | .probe = wm8750_probe, | ||
747 | .remove = wm8750_remove, | ||
748 | .suspend = wm8750_suspend, | ||
749 | .resume = wm8750_resume, | ||
750 | }; | ||
751 | EXPORT_SYMBOL_GPL(soc_codec_dev_wm8750); | ||
752 | |||
753 | /* | ||
754 | * initialise the WM8750 driver | ||
755 | * register the mixer and dsp interfaces with the kernel | ||
756 | */ | ||
757 | static int wm8750_register(struct wm8750_priv *wm8750, | ||
758 | enum snd_soc_control_type control) | ||
759 | { | ||
760 | struct snd_soc_codec *codec = &wm8750->codec; | ||
761 | int reg, ret = 0; | ||
762 | |||
763 | if (wm8750_codec) { | ||
764 | dev_err(codec->dev, "Multiple WM8750 devices not supported\n"); | ||
765 | ret = -EINVAL; | ||
766 | goto err; | ||
767 | } | ||
768 | |||
769 | mutex_init(&codec->mutex); | ||
770 | INIT_LIST_HEAD(&codec->dapm_widgets); | ||
771 | INIT_LIST_HEAD(&codec->dapm_paths); | ||
772 | |||
773 | codec->name = "WM8750"; | ||
774 | codec->owner = THIS_MODULE; | ||
775 | codec->bias_level = SND_SOC_BIAS_STANDBY; | ||
776 | codec->set_bias_level = wm8750_set_bias_level; | ||
777 | codec->dai = &wm8750_dai; | ||
778 | codec->num_dai = 1; | ||
779 | codec->reg_cache_size = ARRAY_SIZE(wm8750->reg_cache) + 1; | ||
780 | codec->reg_cache = &wm8750->reg_cache; | ||
781 | snd_soc_codec_set_drvdata(codec, wm8750); | ||
782 | |||
783 | memcpy(codec->reg_cache, wm8750_reg, sizeof(wm8750->reg_cache)); | ||
784 | 698 | ||
785 | ret = snd_soc_codec_set_cache_io(codec, 7, 9, control); | 699 | ret = snd_soc_codec_set_cache_io(codec, 7, 9, wm8750->control_type); |
786 | if (ret < 0) { | 700 | if (ret < 0) { |
787 | printk(KERN_ERR "wm8750: failed to set cache I/O: %d\n", ret); | 701 | printk(KERN_ERR "wm8750: failed to set cache I/O: %d\n", ret); |
788 | goto err; | 702 | return ret; |
789 | } | 703 | } |
790 | 704 | ||
791 | ret = wm8750_reset(codec); | 705 | ret = wm8750_reset(codec); |
792 | if (ret < 0) { | 706 | if (ret < 0) { |
793 | printk(KERN_ERR "wm8750: failed to reset: %d\n", ret); | 707 | printk(KERN_ERR "wm8750: failed to reset: %d\n", ret); |
794 | goto err; | 708 | return ret; |
795 | } | 709 | } |
796 | 710 | ||
797 | /* charge output caps */ | 711 | /* charge output caps */ |
@@ -815,150 +729,131 @@ static int wm8750_register(struct wm8750_priv *wm8750, | |||
815 | reg = snd_soc_read(codec, WM8750_RINVOL); | 729 | reg = snd_soc_read(codec, WM8750_RINVOL); |
816 | snd_soc_write(codec, WM8750_RINVOL, reg | 0x0100); | 730 | snd_soc_write(codec, WM8750_RINVOL, reg | 0x0100); |
817 | 731 | ||
818 | wm8750_codec = codec; | 732 | snd_soc_add_controls(codec, wm8750_snd_controls, |
819 | 733 | ARRAY_SIZE(wm8750_snd_controls)); | |
820 | ret = snd_soc_register_codec(codec); | 734 | wm8750_add_widgets(codec); |
821 | if (ret != 0) { | ||
822 | dev_err(codec->dev, "Failed to register codec: %d\n", ret); | ||
823 | goto err; | ||
824 | } | ||
825 | |||
826 | ret = snd_soc_register_dais(&wm8750_dai, 1); | ||
827 | if (ret != 0) { | ||
828 | dev_err(codec->dev, "Failed to register DAIs: %d\n", ret); | ||
829 | goto err_codec; | ||
830 | } | ||
831 | |||
832 | return 0; | ||
833 | |||
834 | err_codec: | ||
835 | snd_soc_unregister_codec(codec); | ||
836 | err: | ||
837 | kfree(wm8750); | ||
838 | return ret; | 735 | return ret; |
839 | } | 736 | } |
840 | 737 | ||
841 | static void wm8750_unregister(struct wm8750_priv *wm8750) | 738 | static int wm8750_remove(struct snd_soc_codec *codec) |
842 | { | 739 | { |
843 | wm8750_set_bias_level(&wm8750->codec, SND_SOC_BIAS_OFF); | 740 | wm8750_set_bias_level(codec, SND_SOC_BIAS_OFF); |
844 | snd_soc_unregister_dais(&wm8750_dai, 1); | 741 | return 0; |
845 | snd_soc_unregister_codec(&wm8750->codec); | ||
846 | kfree(wm8750); | ||
847 | wm8750_codec = NULL; | ||
848 | } | 742 | } |
849 | 743 | ||
850 | #if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE) | 744 | static struct snd_soc_codec_driver soc_codec_dev_wm8750 = { |
851 | 745 | .probe = wm8750_probe, | |
852 | /* | 746 | .remove = wm8750_remove, |
853 | * WM8750 2 wire address is determined by GPIO5 | 747 | .suspend = wm8750_suspend, |
854 | * state during powerup. | 748 | .resume = wm8750_resume, |
855 | * low = 0x1a | 749 | .set_bias_level = wm8750_set_bias_level, |
856 | * high = 0x1b | 750 | .reg_cache_size = sizeof(wm8750_reg), |
857 | */ | 751 | .reg_word_size = sizeof(u16), |
752 | .reg_cache_default = wm8750_reg, | ||
753 | }; | ||
858 | 754 | ||
859 | static int wm8750_i2c_probe(struct i2c_client *i2c, | 755 | #if defined(CONFIG_SPI_MASTER) |
860 | const struct i2c_device_id *id) | 756 | static int __devinit wm8750_spi_probe(struct spi_device *spi) |
861 | { | 757 | { |
862 | struct snd_soc_codec *codec; | ||
863 | struct wm8750_priv *wm8750; | 758 | struct wm8750_priv *wm8750; |
759 | int ret; | ||
864 | 760 | ||
865 | wm8750 = kzalloc(sizeof(struct wm8750_priv), GFP_KERNEL); | 761 | wm8750 = kzalloc(sizeof(struct wm8750_priv), GFP_KERNEL); |
866 | if (wm8750 == NULL) | 762 | if (wm8750 == NULL) |
867 | return -ENOMEM; | 763 | return -ENOMEM; |
868 | 764 | ||
869 | codec = &wm8750->codec; | 765 | wm8750->control_type = SND_SOC_SPI; |
870 | codec->control_data = i2c; | 766 | spi_set_drvdata(spi, wm8750); |
871 | i2c_set_clientdata(i2c, wm8750); | ||
872 | |||
873 | codec->dev = &i2c->dev; | ||
874 | 767 | ||
875 | return wm8750_register(wm8750, SND_SOC_I2C); | 768 | ret = snd_soc_register_codec(&spi->dev, |
769 | &soc_codec_dev_wm8750, &wm8750_dai, 1); | ||
770 | if (ret < 0) | ||
771 | kfree(wm8750); | ||
772 | return ret; | ||
876 | } | 773 | } |
877 | 774 | ||
878 | static int wm8750_i2c_remove(struct i2c_client *client) | 775 | static int __devexit wm8750_spi_remove(struct spi_device *spi) |
879 | { | 776 | { |
880 | struct wm8750_priv *wm8750 = i2c_get_clientdata(client); | 777 | snd_soc_unregister_codec(&spi->dev); |
881 | wm8750_unregister(wm8750); | 778 | kfree(spi_get_drvdata(spi)); |
882 | return 0; | 779 | return 0; |
883 | } | 780 | } |
884 | 781 | ||
885 | static const struct i2c_device_id wm8750_i2c_id[] = { | 782 | static struct spi_driver wm8750_spi_driver = { |
886 | { "wm8750", 0 }, | ||
887 | { "wm8987", 0 }, /* WM8987 is register compatible with WM8750 */ | ||
888 | { } | ||
889 | }; | ||
890 | MODULE_DEVICE_TABLE(i2c, wm8750_i2c_id); | ||
891 | |||
892 | static struct i2c_driver wm8750_i2c_driver = { | ||
893 | .driver = { | 783 | .driver = { |
894 | .name = "WM8750 I2C Codec", | 784 | .name = "wm8750-codec", |
895 | .owner = THIS_MODULE, | 785 | .bus = &spi_bus_type, |
786 | .owner = THIS_MODULE, | ||
896 | }, | 787 | }, |
897 | .probe = wm8750_i2c_probe, | 788 | .probe = wm8750_spi_probe, |
898 | .remove = wm8750_i2c_remove, | 789 | .remove = __devexit_p(wm8750_spi_remove), |
899 | .id_table = wm8750_i2c_id, | ||
900 | }; | 790 | }; |
901 | #endif | 791 | #endif /* CONFIG_SPI_MASTER */ |
902 | 792 | ||
903 | #if defined(CONFIG_SPI_MASTER) | 793 | #if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE) |
904 | static int __devinit wm8750_spi_probe(struct spi_device *spi) | 794 | static __devinit int wm8750_i2c_probe(struct i2c_client *i2c, |
795 | const struct i2c_device_id *id) | ||
905 | { | 796 | { |
906 | struct snd_soc_codec *codec; | ||
907 | struct wm8750_priv *wm8750; | 797 | struct wm8750_priv *wm8750; |
798 | int ret; | ||
908 | 799 | ||
909 | wm8750 = kzalloc(sizeof(struct wm8750_priv), GFP_KERNEL); | 800 | wm8750 = kzalloc(sizeof(struct wm8750_priv), GFP_KERNEL); |
910 | if (wm8750 == NULL) | 801 | if (wm8750 == NULL) |
911 | return -ENOMEM; | 802 | return -ENOMEM; |
912 | 803 | ||
913 | codec = &wm8750->codec; | 804 | i2c_set_clientdata(i2c, wm8750); |
914 | codec->control_data = spi; | 805 | wm8750->control_type = SND_SOC_I2C; |
915 | codec->dev = &spi->dev; | ||
916 | |||
917 | dev_set_drvdata(&spi->dev, wm8750); | ||
918 | 806 | ||
919 | return wm8750_register(wm8750, SND_SOC_SPI); | 807 | ret = snd_soc_register_codec(&i2c->dev, |
808 | &soc_codec_dev_wm8750, &wm8750_dai, 1); | ||
809 | if (ret < 0) | ||
810 | kfree(wm8750); | ||
811 | return ret; | ||
920 | } | 812 | } |
921 | 813 | ||
922 | static int __devexit wm8750_spi_remove(struct spi_device *spi) | 814 | static __devexit int wm8750_i2c_remove(struct i2c_client *client) |
923 | { | 815 | { |
924 | struct wm8750_priv *wm8750 = dev_get_drvdata(&spi->dev); | 816 | snd_soc_unregister_codec(&client->dev); |
925 | wm8750_unregister(wm8750); | 817 | kfree(i2c_get_clientdata(client)); |
926 | return 0; | 818 | return 0; |
927 | } | 819 | } |
928 | 820 | ||
929 | static const struct spi_device_id wm8750_spi_id[] = { | 821 | static const struct i2c_device_id wm8750_i2c_id[] = { |
930 | { "wm8750", 0 }, | 822 | { "wm8750", 0 }, |
931 | { "wm8987", 0 }, | 823 | { "wm8987", 0 }, |
932 | { } | 824 | { } |
933 | }; | 825 | }; |
934 | MODULE_DEVICE_TABLE(spi, wm8750_spi_id); | 826 | MODULE_DEVICE_TABLE(i2c, wm8750_i2c_id); |
935 | 827 | ||
936 | static struct spi_driver wm8750_spi_driver = { | 828 | static struct i2c_driver wm8750_i2c_driver = { |
937 | .driver = { | 829 | .driver = { |
938 | .name = "WM8750 SPI Codec", | 830 | .name = "wm8750-codec", |
939 | .bus = &spi_bus_type, | 831 | .owner = THIS_MODULE, |
940 | .owner = THIS_MODULE, | ||
941 | }, | 832 | }, |
942 | .probe = wm8750_spi_probe, | 833 | .probe = wm8750_i2c_probe, |
943 | .remove = __devexit_p(wm8750_spi_remove), | 834 | .remove = __devexit_p(wm8750_i2c_remove), |
944 | .id_table = wm8750_spi_id, | 835 | .id_table = wm8750_i2c_id, |
945 | }; | 836 | }; |
946 | #endif | 837 | #endif |
947 | 838 | ||
948 | static int __init wm8750_modinit(void) | 839 | static int __init wm8750_modinit(void) |
949 | { | 840 | { |
950 | int ret; | 841 | int ret = 0; |
951 | #if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE) | 842 | #if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE) |
952 | ret = i2c_add_driver(&wm8750_i2c_driver); | 843 | ret = i2c_add_driver(&wm8750_i2c_driver); |
953 | if (ret != 0) | 844 | if (ret != 0) { |
954 | pr_err("Failed to register WM8750 I2C driver: %d\n", ret); | 845 | printk(KERN_ERR "Failed to register wm8750 I2C driver: %d\n", |
846 | ret); | ||
847 | } | ||
955 | #endif | 848 | #endif |
956 | #if defined(CONFIG_SPI_MASTER) | 849 | #if defined(CONFIG_SPI_MASTER) |
957 | ret = spi_register_driver(&wm8750_spi_driver); | 850 | ret = spi_register_driver(&wm8750_spi_driver); |
958 | if (ret != 0) | 851 | if (ret != 0) { |
959 | pr_err("Failed to register WM8750 SPI driver: %d\n", ret); | 852 | printk(KERN_ERR "Failed to register wm8750 SPI driver: %d\n", |
853 | ret); | ||
854 | } | ||
960 | #endif | 855 | #endif |
961 | return 0; | 856 | return ret; |
962 | } | 857 | } |
963 | module_init(wm8750_modinit); | 858 | module_init(wm8750_modinit); |
964 | 859 | ||
diff --git a/sound/soc/codecs/wm8750.h b/sound/soc/codecs/wm8750.h index 1dc100e19cfe..121427c047fb 100644 --- a/sound/soc/codecs/wm8750.h +++ b/sound/soc/codecs/wm8750.h | |||
@@ -57,13 +57,4 @@ | |||
57 | 57 | ||
58 | #define WM8750_SYSCLK 0 | 58 | #define WM8750_SYSCLK 0 |
59 | 59 | ||
60 | struct wm8750_setup_data { | ||
61 | int spi; | ||
62 | int i2c_bus; | ||
63 | unsigned short i2c_address; | ||
64 | }; | ||
65 | |||
66 | extern struct snd_soc_dai wm8750_dai; | ||
67 | extern struct snd_soc_codec_device soc_codec_dev_wm8750; | ||
68 | |||
69 | #endif | 60 | #endif |
diff --git a/sound/soc/codecs/wm8753.c b/sound/soc/codecs/wm8753.c index b59f349c5218..484423248c26 100644 --- a/sound/soc/codecs/wm8753.c +++ b/sound/soc/codecs/wm8753.c | |||
@@ -57,7 +57,7 @@ module_param(caps_charge, int, 0); | |||
57 | MODULE_PARM_DESC(caps_charge, "WM8753 cap charge time (msecs)"); | 57 | MODULE_PARM_DESC(caps_charge, "WM8753 cap charge time (msecs)"); |
58 | 58 | ||
59 | static void wm8753_set_dai_mode(struct snd_soc_codec *codec, | 59 | static void wm8753_set_dai_mode(struct snd_soc_codec *codec, |
60 | unsigned int mode); | 60 | struct snd_soc_dai *dai, unsigned int hifi); |
61 | 61 | ||
62 | /* | 62 | /* |
63 | * wm8753 register cache | 63 | * wm8753 register cache |
@@ -85,10 +85,11 @@ static const u16 wm8753_reg[] = { | |||
85 | 85 | ||
86 | /* codec private data */ | 86 | /* codec private data */ |
87 | struct wm8753_priv { | 87 | struct wm8753_priv { |
88 | enum snd_soc_control_type control_type; | ||
88 | unsigned int sysclk; | 89 | unsigned int sysclk; |
89 | unsigned int pcmclk; | 90 | unsigned int pcmclk; |
90 | struct snd_soc_codec codec; | ||
91 | u16 reg_cache[ARRAY_SIZE(wm8753_reg)]; | 91 | u16 reg_cache[ARRAY_SIZE(wm8753_reg)]; |
92 | int dai_func; | ||
92 | }; | 93 | }; |
93 | 94 | ||
94 | /* | 95 | /* |
@@ -228,6 +229,7 @@ static int wm8753_set_dai(struct snd_kcontrol *kcontrol, | |||
228 | { | 229 | { |
229 | struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol); | 230 | struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol); |
230 | int mode = wm8753_read_reg_cache(codec, WM8753_IOCTL); | 231 | int mode = wm8753_read_reg_cache(codec, WM8753_IOCTL); |
232 | struct wm8753_priv *wm8753 = snd_soc_codec_get_drvdata(codec); | ||
231 | 233 | ||
232 | if (((mode & 0xc) >> 2) == ucontrol->value.integer.value[0]) | 234 | if (((mode & 0xc) >> 2) == ucontrol->value.integer.value[0]) |
233 | return 0; | 235 | return 0; |
@@ -235,8 +237,7 @@ static int wm8753_set_dai(struct snd_kcontrol *kcontrol, | |||
235 | mode &= 0xfff3; | 237 | mode &= 0xfff3; |
236 | mode |= (ucontrol->value.integer.value[0] << 2); | 238 | mode |= (ucontrol->value.integer.value[0] << 2); |
237 | 239 | ||
238 | wm8753_write(codec, WM8753_IOCTL, mode); | 240 | wm8753->dai_func = ucontrol->value.integer.value[0]; |
239 | wm8753_set_dai_mode(codec, ucontrol->value.integer.value[0]); | ||
240 | return 1; | 241 | return 1; |
241 | } | 242 | } |
242 | 243 | ||
@@ -904,6 +905,13 @@ static int wm8753_vdac_adc_set_dai_fmt(struct snd_soc_dai *codec_dai, | |||
904 | return 0; | 905 | return 0; |
905 | } | 906 | } |
906 | 907 | ||
908 | static int wm8753_pcm_startup(struct snd_pcm_substream *substream, | ||
909 | struct snd_soc_dai *dai) | ||
910 | { | ||
911 | wm8753_set_dai_mode(dai->codec, dai, 0); | ||
912 | return 0; | ||
913 | } | ||
914 | |||
907 | /* | 915 | /* |
908 | * Set PCM DAI bit size and sample rate. | 916 | * Set PCM DAI bit size and sample rate. |
909 | */ | 917 | */ |
@@ -912,8 +920,7 @@ static int wm8753_pcm_hw_params(struct snd_pcm_substream *substream, | |||
912 | struct snd_soc_dai *dai) | 920 | struct snd_soc_dai *dai) |
913 | { | 921 | { |
914 | struct snd_soc_pcm_runtime *rtd = substream->private_data; | 922 | struct snd_soc_pcm_runtime *rtd = substream->private_data; |
915 | struct snd_soc_device *socdev = rtd->socdev; | 923 | struct snd_soc_codec *codec = rtd->codec; |
916 | struct snd_soc_codec *codec = socdev->card->codec; | ||
917 | struct wm8753_priv *wm8753 = snd_soc_codec_get_drvdata(codec); | 924 | struct wm8753_priv *wm8753 = snd_soc_codec_get_drvdata(codec); |
918 | u16 voice = wm8753_read_reg_cache(codec, WM8753_PCM) & 0x01f3; | 925 | u16 voice = wm8753_read_reg_cache(codec, WM8753_PCM) & 0x01f3; |
919 | u16 srate = wm8753_read_reg_cache(codec, WM8753_SRATE1) & 0x017f; | 926 | u16 srate = wm8753_read_reg_cache(codec, WM8753_SRATE1) & 0x017f; |
@@ -1138,6 +1145,13 @@ static int wm8753_i2s_set_dai_fmt(struct snd_soc_dai *codec_dai, | |||
1138 | return 0; | 1145 | return 0; |
1139 | } | 1146 | } |
1140 | 1147 | ||
1148 | static int wm8753_i2s_startup(struct snd_pcm_substream *substream, | ||
1149 | struct snd_soc_dai *dai) | ||
1150 | { | ||
1151 | wm8753_set_dai_mode(dai->codec, dai, 1); | ||
1152 | return 0; | ||
1153 | } | ||
1154 | |||
1141 | /* | 1155 | /* |
1142 | * Set PCM DAI bit size and sample rate. | 1156 | * Set PCM DAI bit size and sample rate. |
1143 | */ | 1157 | */ |
@@ -1146,8 +1160,7 @@ static int wm8753_i2s_hw_params(struct snd_pcm_substream *substream, | |||
1146 | struct snd_soc_dai *dai) | 1160 | struct snd_soc_dai *dai) |
1147 | { | 1161 | { |
1148 | struct snd_soc_pcm_runtime *rtd = substream->private_data; | 1162 | struct snd_soc_pcm_runtime *rtd = substream->private_data; |
1149 | struct snd_soc_device *socdev = rtd->socdev; | 1163 | struct snd_soc_codec *codec = rtd->codec; |
1150 | struct snd_soc_codec *codec = socdev->card->codec; | ||
1151 | struct wm8753_priv *wm8753 = snd_soc_codec_get_drvdata(codec); | 1164 | struct wm8753_priv *wm8753 = snd_soc_codec_get_drvdata(codec); |
1152 | u16 srate = wm8753_read_reg_cache(codec, WM8753_SRATE1) & 0x01c0; | 1165 | u16 srate = wm8753_read_reg_cache(codec, WM8753_SRATE1) & 0x01c0; |
1153 | u16 hifi = wm8753_read_reg_cache(codec, WM8753_HIFI) & 0x01f3; | 1166 | u16 hifi = wm8753_read_reg_cache(codec, WM8753_HIFI) & 0x01f3; |
@@ -1240,12 +1253,12 @@ static int wm8753_mute(struct snd_soc_dai *dai, int mute) | |||
1240 | { | 1253 | { |
1241 | struct snd_soc_codec *codec = dai->codec; | 1254 | struct snd_soc_codec *codec = dai->codec; |
1242 | u16 mute_reg = wm8753_read_reg_cache(codec, WM8753_DAC) & 0xfff7; | 1255 | u16 mute_reg = wm8753_read_reg_cache(codec, WM8753_DAC) & 0xfff7; |
1256 | struct wm8753_priv *wm8753 = snd_soc_codec_get_drvdata(codec); | ||
1243 | 1257 | ||
1244 | /* the digital mute covers the HiFi and Voice DAC's on the WM8753. | 1258 | /* the digital mute covers the HiFi and Voice DAC's on the WM8753. |
1245 | * make sure we check if they are not both active when we mute */ | 1259 | * make sure we check if they are not both active when we mute */ |
1246 | if (mute && dai->id == 1) { | 1260 | if (mute && wm8753->dai_func == 1) { |
1247 | if (!wm8753_dai[WM8753_DAI_VOICE].playback.active || | 1261 | if (!codec->active) |
1248 | !wm8753_dai[WM8753_DAI_HIFI].playback.active) | ||
1249 | wm8753_write(codec, WM8753_DAC, mute_reg | 0x8); | 1262 | wm8753_write(codec, WM8753_DAC, mute_reg | 0x8); |
1250 | } else { | 1263 | } else { |
1251 | if (mute) | 1264 | if (mute) |
@@ -1303,6 +1316,7 @@ static int wm8753_set_bias_level(struct snd_soc_codec *codec, | |||
1303 | * 4. Voice disabled - HIFI over HIFI, uses voice DAI LRC for capture | 1316 | * 4. Voice disabled - HIFI over HIFI, uses voice DAI LRC for capture |
1304 | */ | 1317 | */ |
1305 | static struct snd_soc_dai_ops wm8753_dai_ops_hifi_mode1 = { | 1318 | static struct snd_soc_dai_ops wm8753_dai_ops_hifi_mode1 = { |
1319 | .startup = wm8753_i2s_startup, | ||
1306 | .hw_params = wm8753_i2s_hw_params, | 1320 | .hw_params = wm8753_i2s_hw_params, |
1307 | .digital_mute = wm8753_mute, | 1321 | .digital_mute = wm8753_mute, |
1308 | .set_fmt = wm8753_mode1h_set_dai_fmt, | 1322 | .set_fmt = wm8753_mode1h_set_dai_fmt, |
@@ -1312,6 +1326,7 @@ static struct snd_soc_dai_ops wm8753_dai_ops_hifi_mode1 = { | |||
1312 | }; | 1326 | }; |
1313 | 1327 | ||
1314 | static struct snd_soc_dai_ops wm8753_dai_ops_voice_mode1 = { | 1328 | static struct snd_soc_dai_ops wm8753_dai_ops_voice_mode1 = { |
1329 | .startup = wm8753_pcm_startup, | ||
1315 | .hw_params = wm8753_pcm_hw_params, | 1330 | .hw_params = wm8753_pcm_hw_params, |
1316 | .digital_mute = wm8753_mute, | 1331 | .digital_mute = wm8753_mute, |
1317 | .set_fmt = wm8753_mode1v_set_dai_fmt, | 1332 | .set_fmt = wm8753_mode1v_set_dai_fmt, |
@@ -1321,6 +1336,7 @@ static struct snd_soc_dai_ops wm8753_dai_ops_voice_mode1 = { | |||
1321 | }; | 1336 | }; |
1322 | 1337 | ||
1323 | static struct snd_soc_dai_ops wm8753_dai_ops_voice_mode2 = { | 1338 | static struct snd_soc_dai_ops wm8753_dai_ops_voice_mode2 = { |
1339 | .startup = wm8753_pcm_startup, | ||
1324 | .hw_params = wm8753_pcm_hw_params, | 1340 | .hw_params = wm8753_pcm_hw_params, |
1325 | .digital_mute = wm8753_mute, | 1341 | .digital_mute = wm8753_mute, |
1326 | .set_fmt = wm8753_mode2_set_dai_fmt, | 1342 | .set_fmt = wm8753_mode2_set_dai_fmt, |
@@ -1330,6 +1346,7 @@ static struct snd_soc_dai_ops wm8753_dai_ops_voice_mode2 = { | |||
1330 | }; | 1346 | }; |
1331 | 1347 | ||
1332 | static struct snd_soc_dai_ops wm8753_dai_ops_hifi_mode3 = { | 1348 | static struct snd_soc_dai_ops wm8753_dai_ops_hifi_mode3 = { |
1349 | .startup = wm8753_i2s_startup, | ||
1333 | .hw_params = wm8753_i2s_hw_params, | 1350 | .hw_params = wm8753_i2s_hw_params, |
1334 | .digital_mute = wm8753_mute, | 1351 | .digital_mute = wm8753_mute, |
1335 | .set_fmt = wm8753_mode3_4_set_dai_fmt, | 1352 | .set_fmt = wm8753_mode3_4_set_dai_fmt, |
@@ -1339,6 +1356,7 @@ static struct snd_soc_dai_ops wm8753_dai_ops_hifi_mode3 = { | |||
1339 | }; | 1356 | }; |
1340 | 1357 | ||
1341 | static struct snd_soc_dai_ops wm8753_dai_ops_hifi_mode4 = { | 1358 | static struct snd_soc_dai_ops wm8753_dai_ops_hifi_mode4 = { |
1359 | .startup = wm8753_i2s_startup, | ||
1342 | .hw_params = wm8753_i2s_hw_params, | 1360 | .hw_params = wm8753_i2s_hw_params, |
1343 | .digital_mute = wm8753_mute, | 1361 | .digital_mute = wm8753_mute, |
1344 | .set_fmt = wm8753_mode3_4_set_dai_fmt, | 1362 | .set_fmt = wm8753_mode3_4_set_dai_fmt, |
@@ -1347,10 +1365,9 @@ static struct snd_soc_dai_ops wm8753_dai_ops_hifi_mode4 = { | |||
1347 | .set_sysclk = wm8753_set_dai_sysclk, | 1365 | .set_sysclk = wm8753_set_dai_sysclk, |
1348 | }; | 1366 | }; |
1349 | 1367 | ||
1350 | static const struct snd_soc_dai wm8753_all_dai[] = { | 1368 | static struct snd_soc_dai_driver wm8753_all_dai[] = { |
1351 | /* DAI HiFi mode 1 */ | 1369 | /* DAI HiFi mode 1 */ |
1352 | { .name = "WM8753 HiFi", | 1370 | { .name = "wm8753-hifi", |
1353 | .id = 1, | ||
1354 | .playback = { | 1371 | .playback = { |
1355 | .stream_name = "HiFi Playback", | 1372 | .stream_name = "HiFi Playback", |
1356 | .channels_min = 1, | 1373 | .channels_min = 1, |
@@ -1366,8 +1383,7 @@ static const struct snd_soc_dai wm8753_all_dai[] = { | |||
1366 | .ops = &wm8753_dai_ops_hifi_mode1, | 1383 | .ops = &wm8753_dai_ops_hifi_mode1, |
1367 | }, | 1384 | }, |
1368 | /* DAI Voice mode 1 */ | 1385 | /* DAI Voice mode 1 */ |
1369 | { .name = "WM8753 Voice", | 1386 | { .name = "wm8753-voice", |
1370 | .id = 1, | ||
1371 | .playback = { | 1387 | .playback = { |
1372 | .stream_name = "Voice Playback", | 1388 | .stream_name = "Voice Playback", |
1373 | .channels_min = 1, | 1389 | .channels_min = 1, |
@@ -1383,12 +1399,10 @@ static const struct snd_soc_dai wm8753_all_dai[] = { | |||
1383 | .ops = &wm8753_dai_ops_voice_mode1, | 1399 | .ops = &wm8753_dai_ops_voice_mode1, |
1384 | }, | 1400 | }, |
1385 | /* DAI HiFi mode 2 - dummy */ | 1401 | /* DAI HiFi mode 2 - dummy */ |
1386 | { .name = "WM8753 HiFi", | 1402 | { .name = "wm8753-hifi", |
1387 | .id = 2, | ||
1388 | }, | 1403 | }, |
1389 | /* DAI Voice mode 2 */ | 1404 | /* DAI Voice mode 2 */ |
1390 | { .name = "WM8753 Voice", | 1405 | { .name = "wm8753-voice", |
1391 | .id = 2, | ||
1392 | .playback = { | 1406 | .playback = { |
1393 | .stream_name = "Voice Playback", | 1407 | .stream_name = "Voice Playback", |
1394 | .channels_min = 1, | 1408 | .channels_min = 1, |
@@ -1404,8 +1418,7 @@ static const struct snd_soc_dai wm8753_all_dai[] = { | |||
1404 | .ops = &wm8753_dai_ops_voice_mode2, | 1418 | .ops = &wm8753_dai_ops_voice_mode2, |
1405 | }, | 1419 | }, |
1406 | /* DAI HiFi mode 3 */ | 1420 | /* DAI HiFi mode 3 */ |
1407 | { .name = "WM8753 HiFi", | 1421 | { .name = "wm8753-hifi", |
1408 | .id = 3, | ||
1409 | .playback = { | 1422 | .playback = { |
1410 | .stream_name = "HiFi Playback", | 1423 | .stream_name = "HiFi Playback", |
1411 | .channels_min = 1, | 1424 | .channels_min = 1, |
@@ -1421,12 +1434,10 @@ static const struct snd_soc_dai wm8753_all_dai[] = { | |||
1421 | .ops = &wm8753_dai_ops_hifi_mode3, | 1434 | .ops = &wm8753_dai_ops_hifi_mode3, |
1422 | }, | 1435 | }, |
1423 | /* DAI Voice mode 3 - dummy */ | 1436 | /* DAI Voice mode 3 - dummy */ |
1424 | { .name = "WM8753 Voice", | 1437 | { .name = "wm8753-voice", |
1425 | .id = 3, | ||
1426 | }, | 1438 | }, |
1427 | /* DAI HiFi mode 4 */ | 1439 | /* DAI HiFi mode 4 */ |
1428 | { .name = "WM8753 HiFi", | 1440 | { .name = "wm8753-hifi", |
1429 | .id = 4, | ||
1430 | .playback = { | 1441 | .playback = { |
1431 | .stream_name = "HiFi Playback", | 1442 | .stream_name = "HiFi Playback", |
1432 | .channels_min = 1, | 1443 | .channels_min = 1, |
@@ -1442,58 +1453,31 @@ static const struct snd_soc_dai wm8753_all_dai[] = { | |||
1442 | .ops = &wm8753_dai_ops_hifi_mode4, | 1453 | .ops = &wm8753_dai_ops_hifi_mode4, |
1443 | }, | 1454 | }, |
1444 | /* DAI Voice mode 4 - dummy */ | 1455 | /* DAI Voice mode 4 - dummy */ |
1445 | { .name = "WM8753 Voice", | 1456 | { .name = "wm8753-voice", |
1446 | .id = 4, | ||
1447 | }, | 1457 | }, |
1448 | }; | 1458 | }; |
1449 | 1459 | ||
1450 | struct snd_soc_dai wm8753_dai[] = { | 1460 | static struct snd_soc_dai_driver wm8753_dai[] = { |
1451 | { | 1461 | { |
1452 | .name = "WM8753 DAI 0", | 1462 | .name = "wm8753-aif0", |
1453 | }, | 1463 | }, |
1454 | { | 1464 | { |
1455 | .name = "WM8753 DAI 1", | 1465 | .name = "wm8753-aif1", |
1456 | }, | 1466 | }, |
1457 | }; | 1467 | }; |
1458 | EXPORT_SYMBOL_GPL(wm8753_dai); | ||
1459 | 1468 | ||
1460 | static void wm8753_set_dai_mode(struct snd_soc_codec *codec, unsigned int mode) | 1469 | static void wm8753_set_dai_mode(struct snd_soc_codec *codec, |
1470 | struct snd_soc_dai *dai, unsigned int hifi) | ||
1461 | { | 1471 | { |
1462 | if (mode < 4) { | 1472 | struct wm8753_priv *wm8753 = snd_soc_codec_get_drvdata(codec); |
1463 | int playback_active, capture_active, codec_active, pop_wait; | 1473 | |
1464 | void *private_data; | 1474 | if (wm8753->dai_func < 4) { |
1465 | struct list_head list; | 1475 | if (hifi) |
1466 | 1476 | dai->driver = &wm8753_all_dai[wm8753->dai_func << 1]; | |
1467 | playback_active = wm8753_dai[0].playback.active; | 1477 | else |
1468 | capture_active = wm8753_dai[0].capture.active; | 1478 | dai->driver = &wm8753_all_dai[(wm8753->dai_func << 1) + 1]; |
1469 | codec_active = wm8753_dai[0].active; | ||
1470 | private_data = wm8753_dai[0].private_data; | ||
1471 | pop_wait = wm8753_dai[0].pop_wait; | ||
1472 | list = wm8753_dai[0].list; | ||
1473 | wm8753_dai[0] = wm8753_all_dai[mode << 1]; | ||
1474 | wm8753_dai[0].playback.active = playback_active; | ||
1475 | wm8753_dai[0].capture.active = capture_active; | ||
1476 | wm8753_dai[0].active = codec_active; | ||
1477 | wm8753_dai[0].private_data = private_data; | ||
1478 | wm8753_dai[0].pop_wait = pop_wait; | ||
1479 | wm8753_dai[0].list = list; | ||
1480 | |||
1481 | playback_active = wm8753_dai[1].playback.active; | ||
1482 | capture_active = wm8753_dai[1].capture.active; | ||
1483 | codec_active = wm8753_dai[1].active; | ||
1484 | private_data = wm8753_dai[1].private_data; | ||
1485 | pop_wait = wm8753_dai[1].pop_wait; | ||
1486 | list = wm8753_dai[1].list; | ||
1487 | wm8753_dai[1] = wm8753_all_dai[(mode << 1) + 1]; | ||
1488 | wm8753_dai[1].playback.active = playback_active; | ||
1489 | wm8753_dai[1].capture.active = capture_active; | ||
1490 | wm8753_dai[1].active = codec_active; | ||
1491 | wm8753_dai[1].private_data = private_data; | ||
1492 | wm8753_dai[1].pop_wait = pop_wait; | ||
1493 | wm8753_dai[1].list = list; | ||
1494 | } | 1479 | } |
1495 | wm8753_dai[0].codec = codec; | 1480 | wm8753_write(codec, WM8753_IOCTL, wm8753->dai_func); |
1496 | wm8753_dai[1].codec = codec; | ||
1497 | } | 1481 | } |
1498 | 1482 | ||
1499 | static void wm8753_work(struct work_struct *work) | 1483 | static void wm8753_work(struct work_struct *work) |
@@ -1503,19 +1487,14 @@ static void wm8753_work(struct work_struct *work) | |||
1503 | wm8753_set_bias_level(codec, codec->bias_level); | 1487 | wm8753_set_bias_level(codec, codec->bias_level); |
1504 | } | 1488 | } |
1505 | 1489 | ||
1506 | static int wm8753_suspend(struct platform_device *pdev, pm_message_t state) | 1490 | static int wm8753_suspend(struct snd_soc_codec *codec, pm_message_t state) |
1507 | { | 1491 | { |
1508 | struct snd_soc_device *socdev = platform_get_drvdata(pdev); | ||
1509 | struct snd_soc_codec *codec = socdev->card->codec; | ||
1510 | |||
1511 | wm8753_set_bias_level(codec, SND_SOC_BIAS_OFF); | 1492 | wm8753_set_bias_level(codec, SND_SOC_BIAS_OFF); |
1512 | return 0; | 1493 | return 0; |
1513 | } | 1494 | } |
1514 | 1495 | ||
1515 | static int wm8753_resume(struct platform_device *pdev) | 1496 | static int wm8753_resume(struct snd_soc_codec *codec) |
1516 | { | 1497 | { |
1517 | struct snd_soc_device *socdev = platform_get_drvdata(pdev); | ||
1518 | struct snd_soc_codec *codec = socdev->card->codec; | ||
1519 | int i; | 1498 | int i; |
1520 | u8 data[2]; | 1499 | u8 data[2]; |
1521 | u16 *cache = codec->reg_cache; | 1500 | u16 *cache = codec->reg_cache; |
@@ -1547,41 +1526,6 @@ static int wm8753_resume(struct platform_device *pdev) | |||
1547 | return 0; | 1526 | return 0; |
1548 | } | 1527 | } |
1549 | 1528 | ||
1550 | static struct snd_soc_codec *wm8753_codec; | ||
1551 | |||
1552 | static int wm8753_probe(struct platform_device *pdev) | ||
1553 | { | ||
1554 | struct snd_soc_device *socdev = platform_get_drvdata(pdev); | ||
1555 | struct snd_soc_codec *codec; | ||
1556 | int ret = 0; | ||
1557 | |||
1558 | if (!wm8753_codec) { | ||
1559 | dev_err(&pdev->dev, "WM8753 codec not yet registered\n"); | ||
1560 | return -EINVAL; | ||
1561 | } | ||
1562 | |||
1563 | socdev->card->codec = wm8753_codec; | ||
1564 | codec = wm8753_codec; | ||
1565 | |||
1566 | wm8753_set_dai_mode(codec, 0); | ||
1567 | |||
1568 | /* register pcms */ | ||
1569 | ret = snd_soc_new_pcms(socdev, SNDRV_DEFAULT_IDX1, SNDRV_DEFAULT_STR1); | ||
1570 | if (ret < 0) { | ||
1571 | printk(KERN_ERR "wm8753: failed to create pcms\n"); | ||
1572 | goto pcm_err; | ||
1573 | } | ||
1574 | |||
1575 | snd_soc_add_controls(codec, wm8753_snd_controls, | ||
1576 | ARRAY_SIZE(wm8753_snd_controls)); | ||
1577 | wm8753_add_widgets(codec); | ||
1578 | |||
1579 | return 0; | ||
1580 | |||
1581 | pcm_err: | ||
1582 | return ret; | ||
1583 | } | ||
1584 | |||
1585 | /* | 1529 | /* |
1586 | * This function forces any delayed work to be queued and run. | 1530 | * This function forces any delayed work to be queued and run. |
1587 | */ | 1531 | */ |
@@ -1601,62 +1545,29 @@ static int run_delayed_work(struct delayed_work *dwork) | |||
1601 | return ret; | 1545 | return ret; |
1602 | } | 1546 | } |
1603 | 1547 | ||
1604 | /* power down chip */ | 1548 | static int wm8753_probe(struct snd_soc_codec *codec) |
1605 | static int wm8753_remove(struct platform_device *pdev) | ||
1606 | { | 1549 | { |
1607 | struct snd_soc_device *socdev = platform_get_drvdata(pdev); | 1550 | struct wm8753_priv *wm8753 = snd_soc_codec_get_drvdata(codec); |
1608 | 1551 | int ret = 0, reg; | |
1609 | snd_soc_free_pcms(socdev); | ||
1610 | snd_soc_dapm_free(socdev); | ||
1611 | |||
1612 | return 0; | ||
1613 | } | ||
1614 | |||
1615 | struct snd_soc_codec_device soc_codec_dev_wm8753 = { | ||
1616 | .probe = wm8753_probe, | ||
1617 | .remove = wm8753_remove, | ||
1618 | .suspend = wm8753_suspend, | ||
1619 | .resume = wm8753_resume, | ||
1620 | }; | ||
1621 | EXPORT_SYMBOL_GPL(soc_codec_dev_wm8753); | ||
1622 | 1552 | ||
1623 | static int wm8753_register(struct wm8753_priv *wm8753) | 1553 | codec->bias_level = SND_SOC_BIAS_OFF; |
1624 | { | 1554 | INIT_DELAYED_WORK(&codec->delayed_work, wm8753_work); |
1625 | int ret, i; | ||
1626 | struct snd_soc_codec *codec = &wm8753->codec; | ||
1627 | u16 reg; | ||
1628 | 1555 | ||
1629 | if (wm8753_codec) { | 1556 | ret = snd_soc_codec_set_cache_io(codec, 7, 9, wm8753->control_type); |
1630 | dev_err(codec->dev, "Multiple WM8753 devices not supported\n"); | 1557 | if (ret < 0) { |
1631 | ret = -EINVAL; | 1558 | dev_err(codec->dev, "Failed to set cache I/O: %d\n", ret); |
1632 | goto err; | 1559 | return ret; |
1633 | } | 1560 | } |
1634 | 1561 | ||
1635 | mutex_init(&codec->mutex); | ||
1636 | INIT_LIST_HEAD(&codec->dapm_widgets); | ||
1637 | INIT_LIST_HEAD(&codec->dapm_paths); | ||
1638 | |||
1639 | codec->name = "WM8753"; | ||
1640 | codec->owner = THIS_MODULE; | ||
1641 | codec->read = wm8753_read_reg_cache; | ||
1642 | codec->write = wm8753_write; | ||
1643 | codec->bias_level = SND_SOC_BIAS_STANDBY; | ||
1644 | codec->set_bias_level = wm8753_set_bias_level; | ||
1645 | codec->dai = wm8753_dai; | ||
1646 | codec->num_dai = 2; | ||
1647 | codec->reg_cache_size = ARRAY_SIZE(wm8753->reg_cache) + 1; | ||
1648 | codec->reg_cache = &wm8753->reg_cache; | ||
1649 | snd_soc_codec_set_drvdata(codec, wm8753); | ||
1650 | |||
1651 | memcpy(codec->reg_cache, wm8753_reg, sizeof(wm8753->reg_cache)); | ||
1652 | INIT_DELAYED_WORK(&codec->delayed_work, wm8753_work); | ||
1653 | |||
1654 | ret = wm8753_reset(codec); | 1562 | ret = wm8753_reset(codec); |
1655 | if (ret < 0) { | 1563 | if (ret < 0) { |
1656 | dev_err(codec->dev, "Failed to issue reset\n"); | 1564 | dev_err(codec->dev, "Failed to issue reset: %d\n", ret); |
1657 | goto err; | 1565 | return ret; |
1658 | } | 1566 | } |
1659 | 1567 | ||
1568 | wm8753_set_bias_level(codec, SND_SOC_BIAS_STANDBY); | ||
1569 | wm8753->dai_func = 0; | ||
1570 | |||
1660 | /* charge output caps */ | 1571 | /* charge output caps */ |
1661 | wm8753_set_bias_level(codec, SND_SOC_BIAS_PREPARE); | 1572 | wm8753_set_bias_level(codec, SND_SOC_BIAS_PREPARE); |
1662 | schedule_delayed_work(&codec->delayed_work, | 1573 | schedule_delayed_work(&codec->delayed_work, |
@@ -1684,165 +1595,137 @@ static int wm8753_register(struct wm8753_priv *wm8753) | |||
1684 | reg = wm8753_read_reg_cache(codec, WM8753_RINVOL); | 1595 | reg = wm8753_read_reg_cache(codec, WM8753_RINVOL); |
1685 | wm8753_write(codec, WM8753_RINVOL, reg | 0x0100); | 1596 | wm8753_write(codec, WM8753_RINVOL, reg | 0x0100); |
1686 | 1597 | ||
1687 | wm8753_codec = codec; | 1598 | snd_soc_add_controls(codec, wm8753_snd_controls, |
1688 | 1599 | ARRAY_SIZE(wm8753_snd_controls)); | |
1689 | for (i = 0; i < ARRAY_SIZE(wm8753_dai); i++) | 1600 | wm8753_add_widgets(codec); |
1690 | wm8753_dai[i].dev = codec->dev; | ||
1691 | |||
1692 | ret = snd_soc_register_codec(codec); | ||
1693 | if (ret != 0) { | ||
1694 | dev_err(codec->dev, "Failed to register codec: %d\n", ret); | ||
1695 | goto err; | ||
1696 | } | ||
1697 | |||
1698 | ret = snd_soc_register_dais(&wm8753_dai[0], ARRAY_SIZE(wm8753_dai)); | ||
1699 | if (ret != 0) { | ||
1700 | dev_err(codec->dev, "Failed to register DAIs: %d\n", ret); | ||
1701 | goto err_codec; | ||
1702 | } | ||
1703 | 1601 | ||
1704 | return 0; | 1602 | return 0; |
1705 | 1603 | ||
1706 | err_codec: | ||
1707 | run_delayed_work(&codec->delayed_work); | 1604 | run_delayed_work(&codec->delayed_work); |
1708 | snd_soc_unregister_codec(codec); | ||
1709 | err: | ||
1710 | kfree(wm8753); | ||
1711 | return ret; | 1605 | return ret; |
1712 | } | 1606 | } |
1713 | 1607 | ||
1714 | static void wm8753_unregister(struct wm8753_priv *wm8753) | 1608 | /* power down chip */ |
1609 | static int wm8753_remove(struct snd_soc_codec *codec) | ||
1715 | { | 1610 | { |
1716 | wm8753_set_bias_level(&wm8753->codec, SND_SOC_BIAS_OFF); | 1611 | run_delayed_work(&codec->delayed_work); |
1717 | run_delayed_work(&wm8753->codec.delayed_work); | 1612 | wm8753_set_bias_level(codec, SND_SOC_BIAS_OFF); |
1718 | snd_soc_unregister_dais(&wm8753_dai[0], ARRAY_SIZE(wm8753_dai)); | 1613 | |
1719 | snd_soc_unregister_codec(&wm8753->codec); | 1614 | return 0; |
1720 | kfree(wm8753); | ||
1721 | wm8753_codec = NULL; | ||
1722 | } | 1615 | } |
1723 | 1616 | ||
1724 | #if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE) | 1617 | static struct snd_soc_codec_driver soc_codec_dev_wm8753 = { |
1618 | .probe = wm8753_probe, | ||
1619 | .remove = wm8753_remove, | ||
1620 | .suspend = wm8753_suspend, | ||
1621 | .resume = wm8753_resume, | ||
1622 | .set_bias_level = wm8753_set_bias_level, | ||
1623 | .reg_cache_size = sizeof(wm8753_reg), | ||
1624 | .reg_word_size = sizeof(u16), | ||
1625 | .reg_cache_default = wm8753_reg, | ||
1626 | }; | ||
1725 | 1627 | ||
1726 | static int wm8753_i2c_probe(struct i2c_client *i2c, | 1628 | #if defined(CONFIG_SPI_MASTER) |
1727 | const struct i2c_device_id *id) | 1629 | static int __devinit wm8753_spi_probe(struct spi_device *spi) |
1728 | { | 1630 | { |
1729 | struct snd_soc_codec *codec; | ||
1730 | struct wm8753_priv *wm8753; | 1631 | struct wm8753_priv *wm8753; |
1632 | int ret; | ||
1731 | 1633 | ||
1732 | wm8753 = kzalloc(sizeof(struct wm8753_priv), GFP_KERNEL); | 1634 | wm8753 = kzalloc(sizeof(struct wm8753_priv), GFP_KERNEL); |
1733 | if (wm8753 == NULL) | 1635 | if (wm8753 == NULL) |
1734 | return -ENOMEM; | 1636 | return -ENOMEM; |
1735 | 1637 | ||
1736 | codec = &wm8753->codec; | 1638 | wm8753->control_type = SND_SOC_SPI; |
1737 | codec->hw_write = (hw_write_t)i2c_master_send; | 1639 | spi_set_drvdata(spi, wm8753); |
1738 | codec->control_data = i2c; | ||
1739 | i2c_set_clientdata(i2c, wm8753); | ||
1740 | |||
1741 | codec->dev = &i2c->dev; | ||
1742 | 1640 | ||
1743 | return wm8753_register(wm8753); | 1641 | ret = snd_soc_register_codec(&spi->dev, |
1642 | &soc_codec_dev_wm8753, wm8753_dai, ARRAY_SIZE(wm8753_dai)); | ||
1643 | if (ret < 0) | ||
1644 | kfree(wm8753); | ||
1645 | return ret; | ||
1744 | } | 1646 | } |
1745 | 1647 | ||
1746 | static int wm8753_i2c_remove(struct i2c_client *client) | 1648 | static int __devexit wm8753_spi_remove(struct spi_device *spi) |
1747 | { | 1649 | { |
1748 | struct wm8753_priv *wm8753 = i2c_get_clientdata(client); | 1650 | snd_soc_unregister_codec(&spi->dev); |
1749 | wm8753_unregister(wm8753); | 1651 | kfree(spi_get_drvdata(spi)); |
1750 | return 0; | 1652 | return 0; |
1751 | } | 1653 | } |
1752 | 1654 | ||
1753 | static const struct i2c_device_id wm8753_i2c_id[] = { | 1655 | static struct spi_driver wm8753_spi_driver = { |
1754 | { "wm8753", 0 }, | ||
1755 | { } | ||
1756 | }; | ||
1757 | MODULE_DEVICE_TABLE(i2c, wm8753_i2c_id); | ||
1758 | |||
1759 | static struct i2c_driver wm8753_i2c_driver = { | ||
1760 | .driver = { | 1656 | .driver = { |
1761 | .name = "wm8753", | 1657 | .name = "wm8753-codec", |
1762 | .owner = THIS_MODULE, | 1658 | .bus = &spi_bus_type, |
1659 | .owner = THIS_MODULE, | ||
1763 | }, | 1660 | }, |
1764 | .probe = wm8753_i2c_probe, | 1661 | .probe = wm8753_spi_probe, |
1765 | .remove = wm8753_i2c_remove, | 1662 | .remove = __devexit_p(wm8753_spi_remove), |
1766 | .id_table = wm8753_i2c_id, | ||
1767 | }; | 1663 | }; |
1768 | #endif | 1664 | #endif /* CONFIG_SPI_MASTER */ |
1769 | |||
1770 | #if defined(CONFIG_SPI_MASTER) | ||
1771 | static int wm8753_spi_write(struct spi_device *spi, const char *data, int len) | ||
1772 | { | ||
1773 | struct spi_transfer t; | ||
1774 | struct spi_message m; | ||
1775 | u8 msg[2]; | ||
1776 | |||
1777 | if (len <= 0) | ||
1778 | return 0; | ||
1779 | |||
1780 | msg[0] = data[0]; | ||
1781 | msg[1] = data[1]; | ||
1782 | 1665 | ||
1783 | spi_message_init(&m); | 1666 | #if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE) |
1784 | memset(&t, 0, (sizeof t)); | 1667 | static __devinit int wm8753_i2c_probe(struct i2c_client *i2c, |
1785 | 1668 | const struct i2c_device_id *id) | |
1786 | t.tx_buf = &msg[0]; | ||
1787 | t.len = len; | ||
1788 | |||
1789 | spi_message_add_tail(&t, &m); | ||
1790 | spi_sync(spi, &m); | ||
1791 | |||
1792 | return len; | ||
1793 | } | ||
1794 | |||
1795 | static int __devinit wm8753_spi_probe(struct spi_device *spi) | ||
1796 | { | 1669 | { |
1797 | struct snd_soc_codec *codec; | ||
1798 | struct wm8753_priv *wm8753; | 1670 | struct wm8753_priv *wm8753; |
1671 | int ret; | ||
1799 | 1672 | ||
1800 | wm8753 = kzalloc(sizeof(struct wm8753_priv), GFP_KERNEL); | 1673 | wm8753 = kzalloc(sizeof(struct wm8753_priv), GFP_KERNEL); |
1801 | if (wm8753 == NULL) | 1674 | if (wm8753 == NULL) |
1802 | return -ENOMEM; | 1675 | return -ENOMEM; |
1803 | 1676 | ||
1804 | codec = &wm8753->codec; | 1677 | i2c_set_clientdata(i2c, wm8753); |
1805 | codec->control_data = spi; | 1678 | wm8753->control_type = SND_SOC_I2C; |
1806 | codec->hw_write = (hw_write_t)wm8753_spi_write; | ||
1807 | codec->dev = &spi->dev; | ||
1808 | |||
1809 | dev_set_drvdata(&spi->dev, wm8753); | ||
1810 | 1679 | ||
1811 | return wm8753_register(wm8753); | 1680 | ret = snd_soc_register_codec(&i2c->dev, |
1681 | &soc_codec_dev_wm8753, wm8753_dai, ARRAY_SIZE(wm8753_dai)); | ||
1682 | if (ret < 0) | ||
1683 | kfree(wm8753); | ||
1684 | return ret; | ||
1812 | } | 1685 | } |
1813 | 1686 | ||
1814 | static int __devexit wm8753_spi_remove(struct spi_device *spi) | 1687 | static __devexit int wm8753_i2c_remove(struct i2c_client *client) |
1815 | { | 1688 | { |
1816 | struct wm8753_priv *wm8753 = dev_get_drvdata(&spi->dev); | 1689 | snd_soc_unregister_codec(&client->dev); |
1817 | wm8753_unregister(wm8753); | 1690 | kfree(i2c_get_clientdata(client)); |
1818 | return 0; | 1691 | return 0; |
1819 | } | 1692 | } |
1820 | 1693 | ||
1821 | static struct spi_driver wm8753_spi_driver = { | 1694 | static const struct i2c_device_id wm8753_i2c_id[] = { |
1695 | { "wm8753", 0 }, | ||
1696 | { } | ||
1697 | }; | ||
1698 | MODULE_DEVICE_TABLE(i2c, wm8753_i2c_id); | ||
1699 | |||
1700 | static struct i2c_driver wm8753_i2c_driver = { | ||
1822 | .driver = { | 1701 | .driver = { |
1823 | .name = "wm8753", | 1702 | .name = "wm8753-codec", |
1824 | .bus = &spi_bus_type, | 1703 | .owner = THIS_MODULE, |
1825 | .owner = THIS_MODULE, | ||
1826 | }, | 1704 | }, |
1827 | .probe = wm8753_spi_probe, | 1705 | .probe = wm8753_i2c_probe, |
1828 | .remove = __devexit_p(wm8753_spi_remove), | 1706 | .remove = __devexit_p(wm8753_i2c_remove), |
1707 | .id_table = wm8753_i2c_id, | ||
1829 | }; | 1708 | }; |
1830 | #endif | 1709 | #endif |
1831 | 1710 | ||
1832 | static int __init wm8753_modinit(void) | 1711 | static int __init wm8753_modinit(void) |
1833 | { | 1712 | { |
1834 | int ret; | 1713 | int ret = 0; |
1835 | #if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE) | 1714 | #if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE) |
1836 | ret = i2c_add_driver(&wm8753_i2c_driver); | 1715 | ret = i2c_add_driver(&wm8753_i2c_driver); |
1837 | if (ret != 0) | 1716 | if (ret != 0) { |
1838 | pr_err("Failed to register WM8753 I2C driver: %d\n", ret); | 1717 | printk(KERN_ERR "Failed to register wm8753 I2C driver: %d\n", |
1718 | ret); | ||
1719 | } | ||
1839 | #endif | 1720 | #endif |
1840 | #if defined(CONFIG_SPI_MASTER) | 1721 | #if defined(CONFIG_SPI_MASTER) |
1841 | ret = spi_register_driver(&wm8753_spi_driver); | 1722 | ret = spi_register_driver(&wm8753_spi_driver); |
1842 | if (ret != 0) | 1723 | if (ret != 0) { |
1843 | pr_err("Failed to register WM8753 SPI driver: %d\n", ret); | 1724 | printk(KERN_ERR "Failed to register wm8753 SPI driver: %d\n", |
1725 | ret); | ||
1726 | } | ||
1844 | #endif | 1727 | #endif |
1845 | return 0; | 1728 | return ret; |
1846 | } | 1729 | } |
1847 | module_init(wm8753_modinit); | 1730 | module_init(wm8753_modinit); |
1848 | 1731 | ||
diff --git a/sound/soc/codecs/wm8753.h b/sound/soc/codecs/wm8753.h index 57b2ba244040..94edac144bcb 100644 --- a/sound/soc/codecs/wm8753.h +++ b/sound/soc/codecs/wm8753.h | |||
@@ -115,7 +115,4 @@ | |||
115 | #define WM8753_DAI_HIFI 0 | 115 | #define WM8753_DAI_HIFI 0 |
116 | #define WM8753_DAI_VOICE 1 | 116 | #define WM8753_DAI_VOICE 1 |
117 | 117 | ||
118 | extern struct snd_soc_dai wm8753_dai[2]; | ||
119 | extern struct snd_soc_codec_device soc_codec_dev_wm8753; | ||
120 | |||
121 | #endif | 118 | #endif |
diff --git a/sound/soc/codecs/wm8776.c b/sound/soc/codecs/wm8776.c index 4e212ed62ea6..053030679c1a 100644 --- a/sound/soc/codecs/wm8776.c +++ b/sound/soc/codecs/wm8776.c | |||
@@ -31,20 +31,13 @@ | |||
31 | 31 | ||
32 | #include "wm8776.h" | 32 | #include "wm8776.h" |
33 | 33 | ||
34 | static struct snd_soc_codec *wm8776_codec; | ||
35 | struct snd_soc_codec_device soc_codec_dev_wm8776; | ||
36 | |||
37 | /* codec private data */ | 34 | /* codec private data */ |
38 | struct wm8776_priv { | 35 | struct wm8776_priv { |
39 | struct snd_soc_codec codec; | 36 | enum snd_soc_control_type control_type; |
40 | u16 reg_cache[WM8776_CACHEREGNUM]; | 37 | u16 reg_cache[WM8776_CACHEREGNUM]; |
41 | int sysclk[2]; | 38 | int sysclk[2]; |
42 | }; | 39 | }; |
43 | 40 | ||
44 | #ifdef CONFIG_SPI_MASTER | ||
45 | static int wm8776_spi_write(struct spi_device *spi, const char *data, int len); | ||
46 | #endif | ||
47 | |||
48 | static const u16 wm8776_reg[WM8776_CACHEREGNUM] = { | 41 | static const u16 wm8776_reg[WM8776_CACHEREGNUM] = { |
49 | 0x79, 0x79, 0x79, 0xff, 0xff, /* 4 */ | 42 | 0x79, 0x79, 0x79, 0xff, 0xff, /* 4 */ |
50 | 0xff, 0x00, 0x90, 0x00, 0x00, /* 9 */ | 43 | 0xff, 0x00, 0x90, 0x00, 0x00, /* 9 */ |
@@ -144,7 +137,7 @@ static int wm8776_set_fmt(struct snd_soc_dai *dai, unsigned int fmt) | |||
144 | struct snd_soc_codec *codec = dai->codec; | 137 | struct snd_soc_codec *codec = dai->codec; |
145 | int reg, iface, master; | 138 | int reg, iface, master; |
146 | 139 | ||
147 | switch (dai->id) { | 140 | switch (dai->driver->id) { |
148 | case WM8776_DAI_DAC: | 141 | case WM8776_DAI_DAC: |
149 | reg = WM8776_DACIFCTRL; | 142 | reg = WM8776_DACIFCTRL; |
150 | master = 0x80; | 143 | master = 0x80; |
@@ -233,7 +226,7 @@ static int wm8776_hw_params(struct snd_pcm_substream *substream, | |||
233 | 226 | ||
234 | iface = 0; | 227 | iface = 0; |
235 | 228 | ||
236 | switch (dai->id) { | 229 | switch (dai->driver->id) { |
237 | case WM8776_DAI_DAC: | 230 | case WM8776_DAI_DAC: |
238 | iface_reg = WM8776_DACIFCTRL; | 231 | iface_reg = WM8776_DACIFCTRL; |
239 | master = 0x80; | 232 | master = 0x80; |
@@ -267,7 +260,7 @@ static int wm8776_hw_params(struct snd_pcm_substream *substream, | |||
267 | /* Only need to set MCLK/LRCLK ratio if we're master */ | 260 | /* Only need to set MCLK/LRCLK ratio if we're master */ |
268 | if (snd_soc_read(codec, WM8776_MSTRCTRL) & master) { | 261 | if (snd_soc_read(codec, WM8776_MSTRCTRL) & master) { |
269 | for (i = 0; i < ARRAY_SIZE(mclk_ratios); i++) { | 262 | for (i = 0; i < ARRAY_SIZE(mclk_ratios); i++) { |
270 | if (wm8776->sysclk[dai->id] / params_rate(params) | 263 | if (wm8776->sysclk[dai->driver->id] / params_rate(params) |
271 | == mclk_ratios[i]) | 264 | == mclk_ratios[i]) |
272 | break; | 265 | break; |
273 | } | 266 | } |
@@ -275,7 +268,7 @@ static int wm8776_hw_params(struct snd_pcm_substream *substream, | |||
275 | if (i == ARRAY_SIZE(mclk_ratios)) { | 268 | if (i == ARRAY_SIZE(mclk_ratios)) { |
276 | dev_err(codec->dev, | 269 | dev_err(codec->dev, |
277 | "Unable to configure MCLK ratio %d/%d\n", | 270 | "Unable to configure MCLK ratio %d/%d\n", |
278 | wm8776->sysclk[dai->id], params_rate(params)); | 271 | wm8776->sysclk[dai->driver->id], params_rate(params)); |
279 | return -EINVAL; | 272 | return -EINVAL; |
280 | } | 273 | } |
281 | 274 | ||
@@ -305,9 +298,9 @@ static int wm8776_set_sysclk(struct snd_soc_dai *dai, | |||
305 | struct snd_soc_codec *codec = dai->codec; | 298 | struct snd_soc_codec *codec = dai->codec; |
306 | struct wm8776_priv *wm8776 = snd_soc_codec_get_drvdata(codec); | 299 | struct wm8776_priv *wm8776 = snd_soc_codec_get_drvdata(codec); |
307 | 300 | ||
308 | BUG_ON(dai->id >= ARRAY_SIZE(wm8776->sysclk)); | 301 | BUG_ON(dai->driver->id >= ARRAY_SIZE(wm8776->sysclk)); |
309 | 302 | ||
310 | wm8776->sysclk[dai->id] = freq; | 303 | wm8776->sysclk[dai->driver->id] = freq; |
311 | 304 | ||
312 | return 0; | 305 | return 0; |
313 | } | 306 | } |
@@ -357,10 +350,10 @@ static struct snd_soc_dai_ops wm8776_adc_ops = { | |||
357 | .set_sysclk = wm8776_set_sysclk, | 350 | .set_sysclk = wm8776_set_sysclk, |
358 | }; | 351 | }; |
359 | 352 | ||
360 | struct snd_soc_dai wm8776_dai[] = { | 353 | static struct snd_soc_dai_driver wm8776_dai[] = { |
361 | { | 354 | { |
362 | .name = "WM8776 Playback", | 355 | .name = "wm8776-hifi-playback", |
363 | .id = WM8776_DAI_DAC, | 356 | .id = WM8776_DAI_DAC, |
364 | .playback = { | 357 | .playback = { |
365 | .stream_name = "Playback", | 358 | .stream_name = "Playback", |
366 | .channels_min = 2, | 359 | .channels_min = 2, |
@@ -371,8 +364,8 @@ struct snd_soc_dai wm8776_dai[] = { | |||
371 | .ops = &wm8776_dac_ops, | 364 | .ops = &wm8776_dac_ops, |
372 | }, | 365 | }, |
373 | { | 366 | { |
374 | .name = "WM8776 Capture", | 367 | .name = "wm8776-hifi-capture", |
375 | .id = WM8776_DAI_ADC, | 368 | .id = WM8776_DAI_ADC, |
376 | .capture = { | 369 | .capture = { |
377 | .stream_name = "Capture", | 370 | .stream_name = "Capture", |
378 | .channels_min = 2, | 371 | .channels_min = 2, |
@@ -383,23 +376,17 @@ struct snd_soc_dai wm8776_dai[] = { | |||
383 | .ops = &wm8776_adc_ops, | 376 | .ops = &wm8776_adc_ops, |
384 | }, | 377 | }, |
385 | }; | 378 | }; |
386 | EXPORT_SYMBOL_GPL(wm8776_dai); | ||
387 | 379 | ||
388 | #ifdef CONFIG_PM | 380 | #ifdef CONFIG_PM |
389 | static int wm8776_suspend(struct platform_device *pdev, pm_message_t state) | 381 | static int wm8776_suspend(struct snd_soc_codec *codec, pm_message_t state) |
390 | { | 382 | { |
391 | struct snd_soc_device *socdev = platform_get_drvdata(pdev); | ||
392 | struct snd_soc_codec *codec = socdev->card->codec; | ||
393 | |||
394 | wm8776_set_bias_level(codec, SND_SOC_BIAS_OFF); | 383 | wm8776_set_bias_level(codec, SND_SOC_BIAS_OFF); |
395 | 384 | ||
396 | return 0; | 385 | return 0; |
397 | } | 386 | } |
398 | 387 | ||
399 | static int wm8776_resume(struct platform_device *pdev) | 388 | static int wm8776_resume(struct snd_soc_codec *codec) |
400 | { | 389 | { |
401 | struct snd_soc_device *socdev = platform_get_drvdata(pdev); | ||
402 | struct snd_soc_codec *codec = socdev->card->codec; | ||
403 | int i; | 390 | int i; |
404 | u8 data[2]; | 391 | u8 data[2]; |
405 | u16 *cache = codec->reg_cache; | 392 | u16 *cache = codec->reg_cache; |
@@ -422,27 +409,30 @@ static int wm8776_resume(struct platform_device *pdev) | |||
422 | #define wm8776_resume NULL | 409 | #define wm8776_resume NULL |
423 | #endif | 410 | #endif |
424 | 411 | ||
425 | static int wm8776_probe(struct platform_device *pdev) | 412 | static int wm8776_probe(struct snd_soc_codec *codec) |
426 | { | 413 | { |
427 | struct snd_soc_device *socdev = platform_get_drvdata(pdev); | 414 | struct wm8776_priv *wm8776 = snd_soc_codec_get_drvdata(codec); |
428 | struct snd_soc_codec *codec; | ||
429 | int ret = 0; | 415 | int ret = 0; |
430 | 416 | ||
431 | if (wm8776_codec == NULL) { | 417 | ret = snd_soc_codec_set_cache_io(codec, 7, 9, wm8776->control_type); |
432 | dev_err(&pdev->dev, "Codec device not registered\n"); | 418 | if (ret < 0) { |
433 | return -ENODEV; | 419 | dev_err(codec->dev, "Failed to set cache I/O: %d\n", ret); |
420 | return ret; | ||
434 | } | 421 | } |
435 | 422 | ||
436 | socdev->card->codec = wm8776_codec; | 423 | ret = wm8776_reset(codec); |
437 | codec = wm8776_codec; | ||
438 | |||
439 | /* register pcms */ | ||
440 | ret = snd_soc_new_pcms(socdev, SNDRV_DEFAULT_IDX1, SNDRV_DEFAULT_STR1); | ||
441 | if (ret < 0) { | 424 | if (ret < 0) { |
442 | dev_err(codec->dev, "failed to create pcms: %d\n", ret); | 425 | dev_err(codec->dev, "Failed to issue reset: %d\n", ret); |
443 | goto pcm_err; | 426 | return ret; |
444 | } | 427 | } |
445 | 428 | ||
429 | wm8776_set_bias_level(codec, SND_SOC_BIAS_STANDBY); | ||
430 | |||
431 | /* Latch the update bits; right channel only since we always | ||
432 | * update both. */ | ||
433 | snd_soc_update_bits(codec, WM8776_HPRVOL, 0x100, 0x100); | ||
434 | snd_soc_update_bits(codec, WM8776_DACRVOL, 0x100, 0x100); | ||
435 | |||
446 | snd_soc_add_controls(codec, wm8776_snd_controls, | 436 | snd_soc_add_controls(codec, wm8776_snd_controls, |
447 | ARRAY_SIZE(wm8776_snd_controls)); | 437 | ARRAY_SIZE(wm8776_snd_controls)); |
448 | snd_soc_dapm_new_controls(codec, wm8776_dapm_widgets, | 438 | snd_soc_dapm_new_controls(codec, wm8776_dapm_widgets, |
@@ -450,168 +440,56 @@ static int wm8776_probe(struct platform_device *pdev) | |||
450 | snd_soc_dapm_add_routes(codec, routes, ARRAY_SIZE(routes)); | 440 | snd_soc_dapm_add_routes(codec, routes, ARRAY_SIZE(routes)); |
451 | 441 | ||
452 | return ret; | 442 | return ret; |
453 | |||
454 | pcm_err: | ||
455 | return ret; | ||
456 | } | 443 | } |
457 | 444 | ||
458 | /* power down chip */ | 445 | /* power down chip */ |
459 | static int wm8776_remove(struct platform_device *pdev) | 446 | static int wm8776_remove(struct snd_soc_codec *codec) |
460 | { | 447 | { |
461 | struct snd_soc_device *socdev = platform_get_drvdata(pdev); | 448 | wm8776_set_bias_level(codec, SND_SOC_BIAS_OFF); |
462 | |||
463 | snd_soc_free_pcms(socdev); | ||
464 | snd_soc_dapm_free(socdev); | ||
465 | |||
466 | return 0; | 449 | return 0; |
467 | } | 450 | } |
468 | 451 | ||
469 | struct snd_soc_codec_device soc_codec_dev_wm8776 = { | 452 | static struct snd_soc_codec_driver soc_codec_dev_wm8776 = { |
470 | .probe = wm8776_probe, | 453 | .probe = wm8776_probe, |
471 | .remove = wm8776_remove, | 454 | .remove = wm8776_remove, |
472 | .suspend = wm8776_suspend, | 455 | .suspend = wm8776_suspend, |
473 | .resume = wm8776_resume, | 456 | .resume = wm8776_resume, |
457 | .set_bias_level = wm8776_set_bias_level, | ||
458 | .reg_cache_size = sizeof(wm8776_reg), | ||
459 | .reg_word_size = sizeof(u16), | ||
460 | .reg_cache_default = wm8776_reg, | ||
474 | }; | 461 | }; |
475 | EXPORT_SYMBOL_GPL(soc_codec_dev_wm8776); | ||
476 | |||
477 | static int wm8776_register(struct wm8776_priv *wm8776, | ||
478 | enum snd_soc_control_type control) | ||
479 | { | ||
480 | int ret, i; | ||
481 | struct snd_soc_codec *codec = &wm8776->codec; | ||
482 | |||
483 | if (wm8776_codec) { | ||
484 | dev_err(codec->dev, "Another WM8776 is registered\n"); | ||
485 | ret = -EINVAL; | ||
486 | goto err; | ||
487 | } | ||
488 | |||
489 | mutex_init(&codec->mutex); | ||
490 | INIT_LIST_HEAD(&codec->dapm_widgets); | ||
491 | INIT_LIST_HEAD(&codec->dapm_paths); | ||
492 | |||
493 | snd_soc_codec_set_drvdata(codec, wm8776); | ||
494 | codec->name = "WM8776"; | ||
495 | codec->owner = THIS_MODULE; | ||
496 | codec->bias_level = SND_SOC_BIAS_OFF; | ||
497 | codec->set_bias_level = wm8776_set_bias_level; | ||
498 | codec->dai = wm8776_dai; | ||
499 | codec->num_dai = ARRAY_SIZE(wm8776_dai); | ||
500 | codec->reg_cache_size = WM8776_CACHEREGNUM; | ||
501 | codec->reg_cache = &wm8776->reg_cache; | ||
502 | |||
503 | memcpy(codec->reg_cache, wm8776_reg, sizeof(wm8776_reg)); | ||
504 | |||
505 | ret = snd_soc_codec_set_cache_io(codec, 7, 9, control); | ||
506 | if (ret < 0) { | ||
507 | dev_err(codec->dev, "Failed to set cache I/O: %d\n", ret); | ||
508 | goto err; | ||
509 | } | ||
510 | |||
511 | for (i = 0; i < ARRAY_SIZE(wm8776_dai); i++) | ||
512 | wm8776_dai[i].dev = codec->dev; | ||
513 | |||
514 | ret = wm8776_reset(codec); | ||
515 | if (ret < 0) { | ||
516 | dev_err(codec->dev, "Failed to issue reset: %d\n", ret); | ||
517 | goto err; | ||
518 | } | ||
519 | |||
520 | wm8776_set_bias_level(codec, SND_SOC_BIAS_STANDBY); | ||
521 | |||
522 | /* Latch the update bits; right channel only since we always | ||
523 | * update both. */ | ||
524 | snd_soc_update_bits(codec, WM8776_HPRVOL, 0x100, 0x100); | ||
525 | snd_soc_update_bits(codec, WM8776_DACRVOL, 0x100, 0x100); | ||
526 | |||
527 | wm8776_codec = codec; | ||
528 | |||
529 | ret = snd_soc_register_codec(codec); | ||
530 | if (ret != 0) { | ||
531 | dev_err(codec->dev, "Failed to register codec: %d\n", ret); | ||
532 | goto err; | ||
533 | } | ||
534 | |||
535 | ret = snd_soc_register_dais(wm8776_dai, ARRAY_SIZE(wm8776_dai)); | ||
536 | if (ret != 0) { | ||
537 | dev_err(codec->dev, "Failed to register DAIs: %d\n", ret); | ||
538 | goto err_codec; | ||
539 | } | ||
540 | |||
541 | return 0; | ||
542 | |||
543 | err_codec: | ||
544 | snd_soc_unregister_codec(codec); | ||
545 | err: | ||
546 | kfree(wm8776); | ||
547 | return ret; | ||
548 | } | ||
549 | |||
550 | static void wm8776_unregister(struct wm8776_priv *wm8776) | ||
551 | { | ||
552 | wm8776_set_bias_level(&wm8776->codec, SND_SOC_BIAS_OFF); | ||
553 | snd_soc_unregister_dais(wm8776_dai, ARRAY_SIZE(wm8776_dai)); | ||
554 | snd_soc_unregister_codec(&wm8776->codec); | ||
555 | kfree(wm8776); | ||
556 | wm8776_codec = NULL; | ||
557 | } | ||
558 | 462 | ||
559 | #if defined(CONFIG_SPI_MASTER) | 463 | #if defined(CONFIG_SPI_MASTER) |
560 | static int wm8776_spi_write(struct spi_device *spi, const char *data, int len) | ||
561 | { | ||
562 | struct spi_transfer t; | ||
563 | struct spi_message m; | ||
564 | u8 msg[2]; | ||
565 | |||
566 | if (len <= 0) | ||
567 | return 0; | ||
568 | |||
569 | msg[0] = data[0]; | ||
570 | msg[1] = data[1]; | ||
571 | |||
572 | spi_message_init(&m); | ||
573 | memset(&t, 0, (sizeof t)); | ||
574 | |||
575 | t.tx_buf = &msg[0]; | ||
576 | t.len = len; | ||
577 | |||
578 | spi_message_add_tail(&t, &m); | ||
579 | spi_sync(spi, &m); | ||
580 | |||
581 | return len; | ||
582 | } | ||
583 | |||
584 | static int __devinit wm8776_spi_probe(struct spi_device *spi) | 464 | static int __devinit wm8776_spi_probe(struct spi_device *spi) |
585 | { | 465 | { |
586 | struct snd_soc_codec *codec; | ||
587 | struct wm8776_priv *wm8776; | 466 | struct wm8776_priv *wm8776; |
467 | int ret; | ||
588 | 468 | ||
589 | wm8776 = kzalloc(sizeof(struct wm8776_priv), GFP_KERNEL); | 469 | wm8776 = kzalloc(sizeof(struct wm8776_priv), GFP_KERNEL); |
590 | if (wm8776 == NULL) | 470 | if (wm8776 == NULL) |
591 | return -ENOMEM; | 471 | return -ENOMEM; |
592 | 472 | ||
593 | codec = &wm8776->codec; | 473 | wm8776->control_type = SND_SOC_SPI; |
594 | codec->control_data = spi; | 474 | spi_set_drvdata(spi, wm8776); |
595 | codec->hw_write = (hw_write_t)wm8776_spi_write; | ||
596 | codec->dev = &spi->dev; | ||
597 | 475 | ||
598 | dev_set_drvdata(&spi->dev, wm8776); | 476 | ret = snd_soc_register_codec(&spi->dev, |
599 | 477 | &soc_codec_dev_wm8776, wm8776_dai, ARRAY_SIZE(wm8776_dai)); | |
600 | return wm8776_register(wm8776, SND_SOC_SPI); | 478 | if (ret < 0) |
479 | kfree(wm8776); | ||
480 | return ret; | ||
601 | } | 481 | } |
602 | 482 | ||
603 | static int __devexit wm8776_spi_remove(struct spi_device *spi) | 483 | static int __devexit wm8776_spi_remove(struct spi_device *spi) |
604 | { | 484 | { |
605 | struct wm8776_priv *wm8776 = dev_get_drvdata(&spi->dev); | 485 | snd_soc_unregister_codec(&spi->dev); |
606 | 486 | kfree(spi_get_drvdata(spi)); | |
607 | wm8776_unregister(wm8776); | ||
608 | |||
609 | return 0; | 487 | return 0; |
610 | } | 488 | } |
611 | 489 | ||
612 | static struct spi_driver wm8776_spi_driver = { | 490 | static struct spi_driver wm8776_spi_driver = { |
613 | .driver = { | 491 | .driver = { |
614 | .name = "wm8776", | 492 | .name = "wm8776-codec", |
615 | .bus = &spi_bus_type, | 493 | .bus = &spi_bus_type, |
616 | .owner = THIS_MODULE, | 494 | .owner = THIS_MODULE, |
617 | }, | 495 | }, |
@@ -625,27 +503,26 @@ static __devinit int wm8776_i2c_probe(struct i2c_client *i2c, | |||
625 | const struct i2c_device_id *id) | 503 | const struct i2c_device_id *id) |
626 | { | 504 | { |
627 | struct wm8776_priv *wm8776; | 505 | struct wm8776_priv *wm8776; |
628 | struct snd_soc_codec *codec; | 506 | int ret; |
629 | 507 | ||
630 | wm8776 = kzalloc(sizeof(struct wm8776_priv), GFP_KERNEL); | 508 | wm8776 = kzalloc(sizeof(struct wm8776_priv), GFP_KERNEL); |
631 | if (wm8776 == NULL) | 509 | if (wm8776 == NULL) |
632 | return -ENOMEM; | 510 | return -ENOMEM; |
633 | 511 | ||
634 | codec = &wm8776->codec; | ||
635 | codec->hw_write = (hw_write_t)i2c_master_send; | ||
636 | |||
637 | i2c_set_clientdata(i2c, wm8776); | 512 | i2c_set_clientdata(i2c, wm8776); |
638 | codec->control_data = i2c; | 513 | wm8776->control_type = SND_SOC_I2C; |
639 | |||
640 | codec->dev = &i2c->dev; | ||
641 | 514 | ||
642 | return wm8776_register(wm8776, SND_SOC_I2C); | 515 | ret = snd_soc_register_codec(&i2c->dev, |
516 | &soc_codec_dev_wm8776, wm8776_dai, ARRAY_SIZE(wm8776_dai)); | ||
517 | if (ret < 0) | ||
518 | kfree(wm8776); | ||
519 | return ret; | ||
643 | } | 520 | } |
644 | 521 | ||
645 | static __devexit int wm8776_i2c_remove(struct i2c_client *client) | 522 | static __devexit int wm8776_i2c_remove(struct i2c_client *client) |
646 | { | 523 | { |
647 | struct wm8776_priv *wm8776 = i2c_get_clientdata(client); | 524 | snd_soc_unregister_codec(&client->dev); |
648 | wm8776_unregister(wm8776); | 525 | kfree(i2c_get_clientdata(client)); |
649 | return 0; | 526 | return 0; |
650 | } | 527 | } |
651 | 528 | ||
@@ -657,7 +534,7 @@ MODULE_DEVICE_TABLE(i2c, wm8776_i2c_id); | |||
657 | 534 | ||
658 | static struct i2c_driver wm8776_i2c_driver = { | 535 | static struct i2c_driver wm8776_i2c_driver = { |
659 | .driver = { | 536 | .driver = { |
660 | .name = "wm8776", | 537 | .name = "wm8776-codec", |
661 | .owner = THIS_MODULE, | 538 | .owner = THIS_MODULE, |
662 | }, | 539 | }, |
663 | .probe = wm8776_i2c_probe, | 540 | .probe = wm8776_i2c_probe, |
@@ -668,22 +545,22 @@ static struct i2c_driver wm8776_i2c_driver = { | |||
668 | 545 | ||
669 | static int __init wm8776_modinit(void) | 546 | static int __init wm8776_modinit(void) |
670 | { | 547 | { |
671 | int ret; | 548 | int ret = 0; |
672 | #if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE) | 549 | #if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE) |
673 | ret = i2c_add_driver(&wm8776_i2c_driver); | 550 | ret = i2c_add_driver(&wm8776_i2c_driver); |
674 | if (ret != 0) { | 551 | if (ret != 0) { |
675 | printk(KERN_ERR "Failed to register WM8776 I2C driver: %d\n", | 552 | printk(KERN_ERR "Failed to register wm8776 I2C driver: %d\n", |
676 | ret); | 553 | ret); |
677 | } | 554 | } |
678 | #endif | 555 | #endif |
679 | #if defined(CONFIG_SPI_MASTER) | 556 | #if defined(CONFIG_SPI_MASTER) |
680 | ret = spi_register_driver(&wm8776_spi_driver); | 557 | ret = spi_register_driver(&wm8776_spi_driver); |
681 | if (ret != 0) { | 558 | if (ret != 0) { |
682 | printk(KERN_ERR "Failed to register WM8776 SPI driver: %d\n", | 559 | printk(KERN_ERR "Failed to register wm8776 SPI driver: %d\n", |
683 | ret); | 560 | ret); |
684 | } | 561 | } |
685 | #endif | 562 | #endif |
686 | return 0; | 563 | return ret; |
687 | } | 564 | } |
688 | module_init(wm8776_modinit); | 565 | module_init(wm8776_modinit); |
689 | 566 | ||
diff --git a/sound/soc/codecs/wm8776.h b/sound/soc/codecs/wm8776.h index 6606d25d2d83..4cf1c8e0bfc9 100644 --- a/sound/soc/codecs/wm8776.h +++ b/sound/soc/codecs/wm8776.h | |||
@@ -45,7 +45,4 @@ | |||
45 | #define WM8776_DAI_DAC 0 | 45 | #define WM8776_DAI_DAC 0 |
46 | #define WM8776_DAI_ADC 1 | 46 | #define WM8776_DAI_ADC 1 |
47 | 47 | ||
48 | extern struct snd_soc_dai wm8776_dai[]; | ||
49 | extern struct snd_soc_codec_device soc_codec_dev_wm8776; | ||
50 | |||
51 | #endif | 48 | #endif |
diff --git a/sound/soc/codecs/wm8900.c b/sound/soc/codecs/wm8900.c index 5da17a704e5a..1378aab5ca75 100644 --- a/sound/soc/codecs/wm8900.c +++ b/sound/soc/codecs/wm8900.c | |||
@@ -23,6 +23,7 @@ | |||
23 | #include <linux/delay.h> | 23 | #include <linux/delay.h> |
24 | #include <linux/pm.h> | 24 | #include <linux/pm.h> |
25 | #include <linux/i2c.h> | 25 | #include <linux/i2c.h> |
26 | #include <linux/spi/spi.h> | ||
26 | #include <linux/platform_device.h> | 27 | #include <linux/platform_device.h> |
27 | #include <linux/slab.h> | 28 | #include <linux/slab.h> |
28 | #include <sound/core.h> | 29 | #include <sound/core.h> |
@@ -137,11 +138,8 @@ | |||
137 | 138 | ||
138 | #define WM8900_LRC_MASK 0xfc00 | 139 | #define WM8900_LRC_MASK 0xfc00 |
139 | 140 | ||
140 | struct snd_soc_codec_device soc_codec_dev_wm8900; | ||
141 | |||
142 | struct wm8900_priv { | 141 | struct wm8900_priv { |
143 | struct snd_soc_codec codec; | 142 | enum snd_soc_control_type control_type; |
144 | |||
145 | u16 reg_cache[WM8900_MAXREG]; | 143 | u16 reg_cache[WM8900_MAXREG]; |
146 | 144 | ||
147 | u32 fll_in; /* FLL input frequency */ | 145 | u32 fll_in; /* FLL input frequency */ |
@@ -627,8 +625,7 @@ static int wm8900_hw_params(struct snd_pcm_substream *substream, | |||
627 | struct snd_soc_dai *dai) | 625 | struct snd_soc_dai *dai) |
628 | { | 626 | { |
629 | struct snd_soc_pcm_runtime *rtd = substream->private_data; | 627 | struct snd_soc_pcm_runtime *rtd = substream->private_data; |
630 | struct snd_soc_device *socdev = rtd->socdev; | 628 | struct snd_soc_codec *codec = rtd->codec; |
631 | struct snd_soc_codec *codec = socdev->card->codec; | ||
632 | u16 reg; | 629 | u16 reg; |
633 | 630 | ||
634 | reg = snd_soc_read(codec, WM8900_REG_AUDIO1) & ~0x60; | 631 | reg = snd_soc_read(codec, WM8900_REG_AUDIO1) & ~0x60; |
@@ -1015,8 +1012,8 @@ static struct snd_soc_dai_ops wm8900_dai_ops = { | |||
1015 | .digital_mute = wm8900_digital_mute, | 1012 | .digital_mute = wm8900_digital_mute, |
1016 | }; | 1013 | }; |
1017 | 1014 | ||
1018 | struct snd_soc_dai wm8900_dai = { | 1015 | static struct snd_soc_dai_driver wm8900_dai = { |
1019 | .name = "WM8900 HiFi", | 1016 | .name = "wm8900-hifi", |
1020 | .playback = { | 1017 | .playback = { |
1021 | .stream_name = "HiFi Playback", | 1018 | .stream_name = "HiFi Playback", |
1022 | .channels_min = 1, | 1019 | .channels_min = 1, |
@@ -1033,7 +1030,6 @@ struct snd_soc_dai wm8900_dai = { | |||
1033 | }, | 1030 | }, |
1034 | .ops = &wm8900_dai_ops, | 1031 | .ops = &wm8900_dai_ops, |
1035 | }; | 1032 | }; |
1036 | EXPORT_SYMBOL_GPL(wm8900_dai); | ||
1037 | 1033 | ||
1038 | static int wm8900_set_bias_level(struct snd_soc_codec *codec, | 1034 | static int wm8900_set_bias_level(struct snd_soc_codec *codec, |
1039 | enum snd_soc_bias_level level) | 1035 | enum snd_soc_bias_level level) |
@@ -1128,10 +1124,8 @@ static int wm8900_set_bias_level(struct snd_soc_codec *codec, | |||
1128 | return 0; | 1124 | return 0; |
1129 | } | 1125 | } |
1130 | 1126 | ||
1131 | static int wm8900_suspend(struct platform_device *pdev, pm_message_t state) | 1127 | static int wm8900_suspend(struct snd_soc_codec *codec, pm_message_t state) |
1132 | { | 1128 | { |
1133 | struct snd_soc_device *socdev = platform_get_drvdata(pdev); | ||
1134 | struct snd_soc_codec *codec = socdev->card->codec; | ||
1135 | struct wm8900_priv *wm8900 = snd_soc_codec_get_drvdata(codec); | 1129 | struct wm8900_priv *wm8900 = snd_soc_codec_get_drvdata(codec); |
1136 | int fll_out = wm8900->fll_out; | 1130 | int fll_out = wm8900->fll_out; |
1137 | int fll_in = wm8900->fll_in; | 1131 | int fll_in = wm8900->fll_in; |
@@ -1140,7 +1134,7 @@ static int wm8900_suspend(struct platform_device *pdev, pm_message_t state) | |||
1140 | /* Stop the FLL in an orderly fashion */ | 1134 | /* Stop the FLL in an orderly fashion */ |
1141 | ret = wm8900_set_fll(codec, 0, 0, 0); | 1135 | ret = wm8900_set_fll(codec, 0, 0, 0); |
1142 | if (ret != 0) { | 1136 | if (ret != 0) { |
1143 | dev_err(&pdev->dev, "Failed to stop FLL\n"); | 1137 | dev_err(codec->dev, "Failed to stop FLL\n"); |
1144 | return ret; | 1138 | return ret; |
1145 | } | 1139 | } |
1146 | 1140 | ||
@@ -1152,10 +1146,8 @@ static int wm8900_suspend(struct platform_device *pdev, pm_message_t state) | |||
1152 | return 0; | 1146 | return 0; |
1153 | } | 1147 | } |
1154 | 1148 | ||
1155 | static int wm8900_resume(struct platform_device *pdev) | 1149 | static int wm8900_resume(struct snd_soc_codec *codec) |
1156 | { | 1150 | { |
1157 | struct snd_soc_device *socdev = platform_get_drvdata(pdev); | ||
1158 | struct snd_soc_codec *codec = socdev->card->codec; | ||
1159 | struct wm8900_priv *wm8900 = snd_soc_codec_get_drvdata(codec); | 1151 | struct wm8900_priv *wm8900 = snd_soc_codec_get_drvdata(codec); |
1160 | u16 *cache; | 1152 | u16 *cache; |
1161 | int i, ret; | 1153 | int i, ret; |
@@ -1176,7 +1168,7 @@ static int wm8900_resume(struct platform_device *pdev) | |||
1176 | 1168 | ||
1177 | ret = wm8900_set_fll(codec, 0, fll_in, fll_out); | 1169 | ret = wm8900_set_fll(codec, 0, fll_in, fll_out); |
1178 | if (ret != 0) { | 1170 | if (ret != 0) { |
1179 | dev_err(&pdev->dev, "Failed to restart FLL\n"); | 1171 | dev_err(codec->dev, "Failed to restart FLL\n"); |
1180 | return ret; | 1172 | return ret; |
1181 | } | 1173 | } |
1182 | } | 1174 | } |
@@ -1186,60 +1178,32 @@ static int wm8900_resume(struct platform_device *pdev) | |||
1186 | snd_soc_write(codec, i, cache[i]); | 1178 | snd_soc_write(codec, i, cache[i]); |
1187 | kfree(cache); | 1179 | kfree(cache); |
1188 | } else | 1180 | } else |
1189 | dev_err(&pdev->dev, "Unable to allocate register cache\n"); | 1181 | dev_err(codec->dev, "Unable to allocate register cache\n"); |
1190 | 1182 | ||
1191 | return 0; | 1183 | return 0; |
1192 | } | 1184 | } |
1193 | 1185 | ||
1194 | static struct snd_soc_codec *wm8900_codec; | 1186 | static int wm8900_probe(struct snd_soc_codec *codec) |
1195 | |||
1196 | static __devinit int wm8900_i2c_probe(struct i2c_client *i2c, | ||
1197 | const struct i2c_device_id *id) | ||
1198 | { | 1187 | { |
1199 | struct wm8900_priv *wm8900; | 1188 | struct wm8900_priv *wm8900 = snd_soc_codec_get_drvdata(codec); |
1200 | struct snd_soc_codec *codec; | 1189 | int ret = 0, reg; |
1201 | unsigned int reg; | ||
1202 | int ret; | ||
1203 | |||
1204 | wm8900 = kzalloc(sizeof(struct wm8900_priv), GFP_KERNEL); | ||
1205 | if (wm8900 == NULL) | ||
1206 | return -ENOMEM; | ||
1207 | 1190 | ||
1208 | codec = &wm8900->codec; | 1191 | ret = snd_soc_codec_set_cache_io(codec, 8, 16, wm8900->control_type); |
1209 | snd_soc_codec_set_drvdata(codec, wm8900); | ||
1210 | codec->reg_cache = &wm8900->reg_cache[0]; | ||
1211 | codec->reg_cache_size = WM8900_MAXREG; | ||
1212 | |||
1213 | mutex_init(&codec->mutex); | ||
1214 | INIT_LIST_HEAD(&codec->dapm_widgets); | ||
1215 | INIT_LIST_HEAD(&codec->dapm_paths); | ||
1216 | |||
1217 | codec->name = "WM8900"; | ||
1218 | codec->owner = THIS_MODULE; | ||
1219 | codec->dai = &wm8900_dai; | ||
1220 | codec->num_dai = 1; | ||
1221 | codec->control_data = i2c; | ||
1222 | codec->set_bias_level = wm8900_set_bias_level; | ||
1223 | codec->volatile_register = wm8900_volatile_register; | ||
1224 | codec->dev = &i2c->dev; | ||
1225 | |||
1226 | ret = snd_soc_codec_set_cache_io(codec, 8, 16, SND_SOC_I2C); | ||
1227 | if (ret != 0) { | 1192 | if (ret != 0) { |
1228 | dev_err(&i2c->dev, "Failed to set cache I/O: %d\n", ret); | 1193 | dev_err(codec->dev, "Failed to set cache I/O: %d\n", ret); |
1229 | goto err; | 1194 | return ret; |
1230 | } | 1195 | } |
1231 | 1196 | ||
1232 | reg = snd_soc_read(codec, WM8900_REG_ID); | 1197 | reg = snd_soc_read(codec, WM8900_REG_ID); |
1233 | if (reg != 0x8900) { | 1198 | if (reg != 0x8900) { |
1234 | dev_err(&i2c->dev, "Device is not a WM8900 - ID %x\n", reg); | 1199 | dev_err(codec->dev, "Device is not a WM8900 - ID %x\n", reg); |
1235 | ret = -ENODEV; | 1200 | return -ENODEV; |
1236 | goto err; | ||
1237 | } | 1201 | } |
1238 | 1202 | ||
1239 | /* Read back from the chip */ | 1203 | /* Read back from the chip */ |
1240 | reg = snd_soc_read(codec, WM8900_REG_POWER1); | 1204 | reg = snd_soc_read(codec, WM8900_REG_POWER1); |
1241 | reg = (reg >> 12) & 0xf; | 1205 | reg = (reg >> 12) & 0xf; |
1242 | dev_info(&i2c->dev, "WM8900 revision %d\n", reg); | 1206 | dev_info(codec->dev, "WM8900 revision %d\n", reg); |
1243 | 1207 | ||
1244 | wm8900_reset(codec); | 1208 | wm8900_reset(codec); |
1245 | 1209 | ||
@@ -1271,43 +1235,95 @@ static __devinit int wm8900_i2c_probe(struct i2c_client *i2c, | |||
1271 | /* Set the DAC and mixer output bias */ | 1235 | /* Set the DAC and mixer output bias */ |
1272 | snd_soc_write(codec, WM8900_REG_OUTBIASCTL, 0x81); | 1236 | snd_soc_write(codec, WM8900_REG_OUTBIASCTL, 0x81); |
1273 | 1237 | ||
1274 | wm8900_dai.dev = &i2c->dev; | 1238 | snd_soc_add_controls(codec, wm8900_snd_controls, |
1239 | ARRAY_SIZE(wm8900_snd_controls)); | ||
1240 | wm8900_add_widgets(codec); | ||
1275 | 1241 | ||
1276 | wm8900_codec = codec; | 1242 | return 0; |
1243 | } | ||
1277 | 1244 | ||
1278 | ret = snd_soc_register_codec(codec); | 1245 | /* power down chip */ |
1279 | if (ret != 0) { | 1246 | static int wm8900_remove(struct snd_soc_codec *codec) |
1280 | dev_err(&i2c->dev, "Failed to register codec: %d\n", ret); | 1247 | { |
1281 | goto err; | 1248 | wm8900_set_bias_level(codec, SND_SOC_BIAS_OFF); |
1282 | } | 1249 | return 0; |
1250 | } | ||
1283 | 1251 | ||
1284 | ret = snd_soc_register_dai(&wm8900_dai); | 1252 | static struct snd_soc_codec_driver soc_codec_dev_wm8900 = { |
1285 | if (ret != 0) { | 1253 | .probe = wm8900_probe, |
1286 | dev_err(&i2c->dev, "Failed to register DAI: %d\n", ret); | 1254 | .remove = wm8900_remove, |
1287 | goto err_codec; | 1255 | .suspend = wm8900_suspend, |
1288 | } | 1256 | .resume = wm8900_resume, |
1257 | .set_bias_level = wm8900_set_bias_level, | ||
1258 | .volatile_register = wm8900_volatile_register, | ||
1259 | .reg_cache_size = sizeof(wm8900_reg_defaults), | ||
1260 | .reg_word_size = sizeof(u16), | ||
1261 | .reg_cache_default = wm8900_reg_defaults, | ||
1262 | }; | ||
1289 | 1263 | ||
1290 | return ret; | 1264 | #if defined(CONFIG_SPI_MASTER) |
1265 | static int __devinit wm8900_spi_probe(struct spi_device *spi) | ||
1266 | { | ||
1267 | struct wm8900_priv *wm8900; | ||
1268 | int ret; | ||
1269 | |||
1270 | wm8900 = kzalloc(sizeof(struct wm8900_priv), GFP_KERNEL); | ||
1271 | if (wm8900 == NULL) | ||
1272 | return -ENOMEM; | ||
1291 | 1273 | ||
1292 | err_codec: | 1274 | wm8900->control_type = SND_SOC_SPI; |
1293 | snd_soc_unregister_codec(codec); | 1275 | spi_set_drvdata(spi, wm8900); |
1294 | err: | 1276 | |
1295 | kfree(wm8900); | 1277 | ret = snd_soc_register_codec(&spi->dev, |
1296 | wm8900_codec = NULL; | 1278 | &soc_codec_dev_wm8900, &wm8900_dai, 1); |
1279 | if (ret < 0) | ||
1280 | kfree(wm8900); | ||
1297 | return ret; | 1281 | return ret; |
1298 | } | 1282 | } |
1299 | 1283 | ||
1300 | static __devexit int wm8900_i2c_remove(struct i2c_client *client) | 1284 | static int __devexit wm8900_spi_remove(struct spi_device *spi) |
1301 | { | 1285 | { |
1302 | snd_soc_unregister_dai(&wm8900_dai); | 1286 | snd_soc_unregister_codec(&spi->dev); |
1303 | snd_soc_unregister_codec(wm8900_codec); | 1287 | kfree(spi_get_drvdata(spi)); |
1288 | return 0; | ||
1289 | } | ||
1304 | 1290 | ||
1305 | wm8900_set_bias_level(wm8900_codec, SND_SOC_BIAS_OFF); | 1291 | static struct spi_driver wm8900_spi_driver = { |
1292 | .driver = { | ||
1293 | .name = "wm8900-codec", | ||
1294 | .bus = &spi_bus_type, | ||
1295 | .owner = THIS_MODULE, | ||
1296 | }, | ||
1297 | .probe = wm8900_spi_probe, | ||
1298 | .remove = __devexit_p(wm8900_spi_remove), | ||
1299 | }; | ||
1300 | #endif /* CONFIG_SPI_MASTER */ | ||
1301 | |||
1302 | #if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE) | ||
1303 | static __devinit int wm8900_i2c_probe(struct i2c_client *i2c, | ||
1304 | const struct i2c_device_id *id) | ||
1305 | { | ||
1306 | struct wm8900_priv *wm8900; | ||
1307 | int ret; | ||
1308 | |||
1309 | wm8900 = kzalloc(sizeof(struct wm8900_priv), GFP_KERNEL); | ||
1310 | if (wm8900 == NULL) | ||
1311 | return -ENOMEM; | ||
1312 | |||
1313 | i2c_set_clientdata(i2c, wm8900); | ||
1314 | wm8900->control_type = SND_SOC_I2C; | ||
1306 | 1315 | ||
1307 | wm8900_dai.dev = NULL; | 1316 | ret = snd_soc_register_codec(&i2c->dev, |
1308 | kfree(snd_soc_codec_get_drvdata(wm8900_codec)); | 1317 | &soc_codec_dev_wm8900, &wm8900_dai, 1); |
1309 | wm8900_codec = NULL; | 1318 | if (ret < 0) |
1319 | kfree(wm8900); | ||
1320 | return ret; | ||
1321 | } | ||
1310 | 1322 | ||
1323 | static __devexit int wm8900_i2c_remove(struct i2c_client *client) | ||
1324 | { | ||
1325 | snd_soc_unregister_codec(&client->dev); | ||
1326 | kfree(i2c_get_clientdata(client)); | ||
1311 | return 0; | 1327 | return 0; |
1312 | } | 1328 | } |
1313 | 1329 | ||
@@ -1319,71 +1335,44 @@ MODULE_DEVICE_TABLE(i2c, wm8900_i2c_id); | |||
1319 | 1335 | ||
1320 | static struct i2c_driver wm8900_i2c_driver = { | 1336 | static struct i2c_driver wm8900_i2c_driver = { |
1321 | .driver = { | 1337 | .driver = { |
1322 | .name = "WM8900", | 1338 | .name = "wm8900-codec", |
1323 | .owner = THIS_MODULE, | 1339 | .owner = THIS_MODULE, |
1324 | }, | 1340 | }, |
1325 | .probe = wm8900_i2c_probe, | 1341 | .probe = wm8900_i2c_probe, |
1326 | .remove = __devexit_p(wm8900_i2c_remove), | 1342 | .remove = __devexit_p(wm8900_i2c_remove), |
1327 | .id_table = wm8900_i2c_id, | 1343 | .id_table = wm8900_i2c_id, |
1328 | }; | 1344 | }; |
1345 | #endif | ||
1329 | 1346 | ||
1330 | static int wm8900_probe(struct platform_device *pdev) | 1347 | static int __init wm8900_modinit(void) |
1331 | { | 1348 | { |
1332 | struct snd_soc_device *socdev = platform_get_drvdata(pdev); | ||
1333 | struct snd_soc_codec *codec; | ||
1334 | int ret = 0; | 1349 | int ret = 0; |
1335 | 1350 | #if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE) | |
1336 | if (!wm8900_codec) { | 1351 | ret = i2c_add_driver(&wm8900_i2c_driver); |
1337 | dev_err(&pdev->dev, "I2C client not yet instantiated\n"); | 1352 | if (ret != 0) { |
1338 | return -ENODEV; | 1353 | printk(KERN_ERR "Failed to register wm8900 I2C driver: %d\n", |
1354 | ret); | ||
1339 | } | 1355 | } |
1340 | 1356 | #endif | |
1341 | codec = wm8900_codec; | 1357 | #if defined(CONFIG_SPI_MASTER) |
1342 | socdev->card->codec = codec; | 1358 | ret = spi_register_driver(&wm8900_spi_driver); |
1343 | 1359 | if (ret != 0) { | |
1344 | /* Register pcms */ | 1360 | printk(KERN_ERR "Failed to register wm8900 SPI driver: %d\n", |
1345 | ret = snd_soc_new_pcms(socdev, SNDRV_DEFAULT_IDX1, SNDRV_DEFAULT_STR1); | 1361 | ret); |
1346 | if (ret < 0) { | ||
1347 | dev_err(&pdev->dev, "Failed to register new PCMs\n"); | ||
1348 | goto pcm_err; | ||
1349 | } | 1362 | } |
1350 | 1363 | #endif | |
1351 | snd_soc_add_controls(codec, wm8900_snd_controls, | ||
1352 | ARRAY_SIZE(wm8900_snd_controls)); | ||
1353 | wm8900_add_widgets(codec); | ||
1354 | |||
1355 | pcm_err: | ||
1356 | return ret; | 1364 | return ret; |
1357 | } | 1365 | } |
1358 | |||
1359 | /* power down chip */ | ||
1360 | static int wm8900_remove(struct platform_device *pdev) | ||
1361 | { | ||
1362 | struct snd_soc_device *socdev = platform_get_drvdata(pdev); | ||
1363 | |||
1364 | snd_soc_free_pcms(socdev); | ||
1365 | snd_soc_dapm_free(socdev); | ||
1366 | |||
1367 | return 0; | ||
1368 | } | ||
1369 | |||
1370 | struct snd_soc_codec_device soc_codec_dev_wm8900 = { | ||
1371 | .probe = wm8900_probe, | ||
1372 | .remove = wm8900_remove, | ||
1373 | .suspend = wm8900_suspend, | ||
1374 | .resume = wm8900_resume, | ||
1375 | }; | ||
1376 | EXPORT_SYMBOL_GPL(soc_codec_dev_wm8900); | ||
1377 | |||
1378 | static int __init wm8900_modinit(void) | ||
1379 | { | ||
1380 | return i2c_add_driver(&wm8900_i2c_driver); | ||
1381 | } | ||
1382 | module_init(wm8900_modinit); | 1366 | module_init(wm8900_modinit); |
1383 | 1367 | ||
1384 | static void __exit wm8900_exit(void) | 1368 | static void __exit wm8900_exit(void) |
1385 | { | 1369 | { |
1370 | #if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE) | ||
1386 | i2c_del_driver(&wm8900_i2c_driver); | 1371 | i2c_del_driver(&wm8900_i2c_driver); |
1372 | #endif | ||
1373 | #if defined(CONFIG_SPI_MASTER) | ||
1374 | spi_unregister_driver(&wm8900_spi_driver); | ||
1375 | #endif | ||
1387 | } | 1376 | } |
1388 | module_exit(wm8900_exit); | 1377 | module_exit(wm8900_exit); |
1389 | 1378 | ||
diff --git a/sound/soc/codecs/wm8900.h b/sound/soc/codecs/wm8900.h index fd15007d10c7..583f257e799b 100644 --- a/sound/soc/codecs/wm8900.h +++ b/sound/soc/codecs/wm8900.h | |||
@@ -52,7 +52,4 @@ | |||
52 | #define WM8900_DAC_CLKDIV_5_5 0x14 | 52 | #define WM8900_DAC_CLKDIV_5_5 0x14 |
53 | #define WM8900_DAC_CLKDIV_6 0x18 | 53 | #define WM8900_DAC_CLKDIV_6 0x18 |
54 | 54 | ||
55 | extern struct snd_soc_dai wm8900_dai; | ||
56 | extern struct snd_soc_codec_device soc_codec_dev_wm8900; | ||
57 | |||
58 | #endif | 55 | #endif |
diff --git a/sound/soc/codecs/wm8903.c b/sound/soc/codecs/wm8903.c index bf08282d5ee5..622b60238a82 100644 --- a/sound/soc/codecs/wm8903.c +++ b/sound/soc/codecs/wm8903.c | |||
@@ -213,10 +213,11 @@ static u16 wm8903_reg_defaults[] = { | |||
213 | }; | 213 | }; |
214 | 214 | ||
215 | struct wm8903_priv { | 215 | struct wm8903_priv { |
216 | struct snd_soc_codec codec; | 216 | |
217 | u16 reg_cache[ARRAY_SIZE(wm8903_reg_defaults)]; | 217 | u16 reg_cache[ARRAY_SIZE(wm8903_reg_defaults)]; |
218 | 218 | ||
219 | int sysclk; | 219 | int sysclk; |
220 | int irq; | ||
220 | 221 | ||
221 | /* Reference counts */ | 222 | /* Reference counts */ |
222 | int class_w_users; | 223 | int class_w_users; |
@@ -252,7 +253,6 @@ static int wm8903_volatile_register(unsigned int reg) | |||
252 | static int wm8903_run_sequence(struct snd_soc_codec *codec, unsigned int start) | 253 | static int wm8903_run_sequence(struct snd_soc_codec *codec, unsigned int start) |
253 | { | 254 | { |
254 | u16 reg[5]; | 255 | u16 reg[5]; |
255 | struct i2c_client *i2c = codec->control_data; | ||
256 | struct wm8903_priv *wm8903 = snd_soc_codec_get_drvdata(codec); | 256 | struct wm8903_priv *wm8903 = snd_soc_codec_get_drvdata(codec); |
257 | 257 | ||
258 | BUG_ON(start > 48); | 258 | BUG_ON(start > 48); |
@@ -262,7 +262,7 @@ static int wm8903_run_sequence(struct snd_soc_codec *codec, unsigned int start) | |||
262 | snd_soc_write(codec, WM8903_WRITE_SEQUENCER_0, | 262 | snd_soc_write(codec, WM8903_WRITE_SEQUENCER_0, |
263 | reg[0] | WM8903_WSEQ_ENA); | 263 | reg[0] | WM8903_WSEQ_ENA); |
264 | 264 | ||
265 | dev_dbg(&i2c->dev, "Starting sequence at %d\n", start); | 265 | dev_dbg(codec->dev, "Starting sequence at %d\n", start); |
266 | 266 | ||
267 | snd_soc_write(codec, WM8903_WRITE_SEQUENCER_3, | 267 | snd_soc_write(codec, WM8903_WRITE_SEQUENCER_3, |
268 | start | WM8903_WSEQ_START); | 268 | start | WM8903_WSEQ_START); |
@@ -277,7 +277,7 @@ static int wm8903_run_sequence(struct snd_soc_codec *codec, unsigned int start) | |||
277 | reg[4] = snd_soc_read(codec, WM8903_WRITE_SEQUENCER_4); | 277 | reg[4] = snd_soc_read(codec, WM8903_WRITE_SEQUENCER_4); |
278 | } while (reg[4] & WM8903_WSEQ_BUSY); | 278 | } while (reg[4] & WM8903_WSEQ_BUSY); |
279 | 279 | ||
280 | dev_dbg(&i2c->dev, "Sequence complete\n"); | 280 | dev_dbg(codec->dev, "Sequence complete\n"); |
281 | 281 | ||
282 | /* Disable the sequencer again if we enabled it */ | 282 | /* Disable the sequencer again if we enabled it */ |
283 | snd_soc_write(codec, WM8903_WRITE_SEQUENCER_0, reg[0]); | 283 | snd_soc_write(codec, WM8903_WRITE_SEQUENCER_0, reg[0]); |
@@ -422,7 +422,6 @@ static int wm8903_class_w_put(struct snd_kcontrol *kcontrol, | |||
422 | struct snd_soc_dapm_widget *widget = snd_kcontrol_chip(kcontrol); | 422 | struct snd_soc_dapm_widget *widget = snd_kcontrol_chip(kcontrol); |
423 | struct snd_soc_codec *codec = widget->codec; | 423 | struct snd_soc_codec *codec = widget->codec; |
424 | struct wm8903_priv *wm8903 = snd_soc_codec_get_drvdata(codec); | 424 | struct wm8903_priv *wm8903 = snd_soc_codec_get_drvdata(codec); |
425 | struct i2c_client *i2c = codec->control_data; | ||
426 | u16 reg; | 425 | u16 reg; |
427 | int ret; | 426 | int ret; |
428 | 427 | ||
@@ -431,7 +430,7 @@ static int wm8903_class_w_put(struct snd_kcontrol *kcontrol, | |||
431 | /* Turn it off if we're about to enable bypass */ | 430 | /* Turn it off if we're about to enable bypass */ |
432 | if (ucontrol->value.integer.value[0]) { | 431 | if (ucontrol->value.integer.value[0]) { |
433 | if (wm8903->class_w_users == 0) { | 432 | if (wm8903->class_w_users == 0) { |
434 | dev_dbg(&i2c->dev, "Disabling Class W\n"); | 433 | dev_dbg(codec->dev, "Disabling Class W\n"); |
435 | snd_soc_write(codec, WM8903_CLASS_W_0, reg & | 434 | snd_soc_write(codec, WM8903_CLASS_W_0, reg & |
436 | ~(WM8903_CP_DYN_FREQ | WM8903_CP_DYN_V)); | 435 | ~(WM8903_CP_DYN_FREQ | WM8903_CP_DYN_V)); |
437 | } | 436 | } |
@@ -444,14 +443,14 @@ static int wm8903_class_w_put(struct snd_kcontrol *kcontrol, | |||
444 | /* If we've just disabled the last bypass path turn Class W on */ | 443 | /* If we've just disabled the last bypass path turn Class W on */ |
445 | if (!ucontrol->value.integer.value[0]) { | 444 | if (!ucontrol->value.integer.value[0]) { |
446 | if (wm8903->class_w_users == 1) { | 445 | if (wm8903->class_w_users == 1) { |
447 | dev_dbg(&i2c->dev, "Enabling Class W\n"); | 446 | dev_dbg(codec->dev, "Enabling Class W\n"); |
448 | snd_soc_write(codec, WM8903_CLASS_W_0, reg | | 447 | snd_soc_write(codec, WM8903_CLASS_W_0, reg | |
449 | WM8903_CP_DYN_FREQ | WM8903_CP_DYN_V); | 448 | WM8903_CP_DYN_FREQ | WM8903_CP_DYN_V); |
450 | } | 449 | } |
451 | wm8903->class_w_users--; | 450 | wm8903->class_w_users--; |
452 | } | 451 | } |
453 | 452 | ||
454 | dev_dbg(&i2c->dev, "Bypass use count now %d\n", | 453 | dev_dbg(codec->dev, "Bypass use count now %d\n", |
455 | wm8903->class_w_users); | 454 | wm8903->class_w_users); |
456 | 455 | ||
457 | return ret; | 456 | return ret; |
@@ -935,7 +934,6 @@ static int wm8903_add_widgets(struct snd_soc_codec *codec) | |||
935 | static int wm8903_set_bias_level(struct snd_soc_codec *codec, | 934 | static int wm8903_set_bias_level(struct snd_soc_codec *codec, |
936 | enum snd_soc_bias_level level) | 935 | enum snd_soc_bias_level level) |
937 | { | 936 | { |
938 | struct i2c_client *i2c = codec->control_data; | ||
939 | u16 reg, reg2; | 937 | u16 reg, reg2; |
940 | 938 | ||
941 | switch (level) { | 939 | switch (level) { |
@@ -974,7 +972,7 @@ static int wm8903_set_bias_level(struct snd_soc_codec *codec, | |||
974 | /* By default no bypass paths are enabled so | 972 | /* By default no bypass paths are enabled so |
975 | * enable Class W support. | 973 | * enable Class W support. |
976 | */ | 974 | */ |
977 | dev_dbg(&i2c->dev, "Enabling Class W\n"); | 975 | dev_dbg(codec->dev, "Enabling Class W\n"); |
978 | snd_soc_write(codec, WM8903_CLASS_W_0, reg | | 976 | snd_soc_write(codec, WM8903_CLASS_W_0, reg | |
979 | WM8903_CP_DYN_FREQ | WM8903_CP_DYN_V); | 977 | WM8903_CP_DYN_FREQ | WM8903_CP_DYN_V); |
980 | } | 978 | } |
@@ -1228,10 +1226,8 @@ static int wm8903_startup(struct snd_pcm_substream *substream, | |||
1228 | struct snd_soc_dai *dai) | 1226 | struct snd_soc_dai *dai) |
1229 | { | 1227 | { |
1230 | struct snd_soc_pcm_runtime *rtd = substream->private_data; | 1228 | struct snd_soc_pcm_runtime *rtd = substream->private_data; |
1231 | struct snd_soc_device *socdev = rtd->socdev; | 1229 | struct snd_soc_codec *codec = rtd->codec; |
1232 | struct snd_soc_codec *codec = socdev->card->codec; | ||
1233 | struct wm8903_priv *wm8903 = snd_soc_codec_get_drvdata(codec); | 1230 | struct wm8903_priv *wm8903 = snd_soc_codec_get_drvdata(codec); |
1234 | struct i2c_client *i2c = codec->control_data; | ||
1235 | struct snd_pcm_runtime *master_runtime; | 1231 | struct snd_pcm_runtime *master_runtime; |
1236 | 1232 | ||
1237 | if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) | 1233 | if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) |
@@ -1245,7 +1241,7 @@ static int wm8903_startup(struct snd_pcm_substream *substream, | |||
1245 | if (wm8903->master_substream) { | 1241 | if (wm8903->master_substream) { |
1246 | master_runtime = wm8903->master_substream->runtime; | 1242 | master_runtime = wm8903->master_substream->runtime; |
1247 | 1243 | ||
1248 | dev_dbg(&i2c->dev, "Constraining to %d bits\n", | 1244 | dev_dbg(codec->dev, "Constraining to %d bits\n", |
1249 | master_runtime->sample_bits); | 1245 | master_runtime->sample_bits); |
1250 | 1246 | ||
1251 | snd_pcm_hw_constraint_minmax(substream->runtime, | 1247 | snd_pcm_hw_constraint_minmax(substream->runtime, |
@@ -1264,8 +1260,7 @@ static void wm8903_shutdown(struct snd_pcm_substream *substream, | |||
1264 | struct snd_soc_dai *dai) | 1260 | struct snd_soc_dai *dai) |
1265 | { | 1261 | { |
1266 | struct snd_soc_pcm_runtime *rtd = substream->private_data; | 1262 | struct snd_soc_pcm_runtime *rtd = substream->private_data; |
1267 | struct snd_soc_device *socdev = rtd->socdev; | 1263 | struct snd_soc_codec *codec = rtd->codec; |
1268 | struct snd_soc_codec *codec = socdev->card->codec; | ||
1269 | struct wm8903_priv *wm8903 = snd_soc_codec_get_drvdata(codec); | 1264 | struct wm8903_priv *wm8903 = snd_soc_codec_get_drvdata(codec); |
1270 | 1265 | ||
1271 | if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) | 1266 | if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) |
@@ -1284,10 +1279,8 @@ static int wm8903_hw_params(struct snd_pcm_substream *substream, | |||
1284 | struct snd_soc_dai *dai) | 1279 | struct snd_soc_dai *dai) |
1285 | { | 1280 | { |
1286 | struct snd_soc_pcm_runtime *rtd = substream->private_data; | 1281 | struct snd_soc_pcm_runtime *rtd = substream->private_data; |
1287 | struct snd_soc_device *socdev = rtd->socdev; | 1282 | struct snd_soc_codec *codec =rtd->codec; |
1288 | struct snd_soc_codec *codec = socdev->card->codec; | ||
1289 | struct wm8903_priv *wm8903 = snd_soc_codec_get_drvdata(codec); | 1283 | struct wm8903_priv *wm8903 = snd_soc_codec_get_drvdata(codec); |
1290 | struct i2c_client *i2c = codec->control_data; | ||
1291 | int fs = params_rate(params); | 1284 | int fs = params_rate(params); |
1292 | int bclk; | 1285 | int bclk; |
1293 | int bclk_div; | 1286 | int bclk_div; |
@@ -1306,7 +1299,7 @@ static int wm8903_hw_params(struct snd_pcm_substream *substream, | |||
1306 | u16 dac_digital1 = snd_soc_read(codec, WM8903_DAC_DIGITAL_1); | 1299 | u16 dac_digital1 = snd_soc_read(codec, WM8903_DAC_DIGITAL_1); |
1307 | 1300 | ||
1308 | if (substream == wm8903->slave_substream) { | 1301 | if (substream == wm8903->slave_substream) { |
1309 | dev_dbg(&i2c->dev, "Ignoring hw_params for slave substream\n"); | 1302 | dev_dbg(codec->dev, "Ignoring hw_params for slave substream\n"); |
1310 | return 0; | 1303 | return 0; |
1311 | } | 1304 | } |
1312 | 1305 | ||
@@ -1332,7 +1325,7 @@ static int wm8903_hw_params(struct snd_pcm_substream *substream, | |||
1332 | switch (sample_rates[dsp_config].rate) { | 1325 | switch (sample_rates[dsp_config].rate) { |
1333 | case 88200: | 1326 | case 88200: |
1334 | case 96000: | 1327 | case 96000: |
1335 | dev_err(&i2c->dev, "%dHz unsupported by ADC\n", | 1328 | dev_err(codec->dev, "%dHz unsupported by ADC\n", |
1336 | fs); | 1329 | fs); |
1337 | return -EINVAL; | 1330 | return -EINVAL; |
1338 | 1331 | ||
@@ -1340,7 +1333,7 @@ static int wm8903_hw_params(struct snd_pcm_substream *substream, | |||
1340 | break; | 1333 | break; |
1341 | } | 1334 | } |
1342 | 1335 | ||
1343 | dev_dbg(&i2c->dev, "DSP fs = %dHz\n", sample_rates[dsp_config].rate); | 1336 | dev_dbg(codec->dev, "DSP fs = %dHz\n", sample_rates[dsp_config].rate); |
1344 | clock1 &= ~WM8903_SAMPLE_RATE_MASK; | 1337 | clock1 &= ~WM8903_SAMPLE_RATE_MASK; |
1345 | clock1 |= sample_rates[dsp_config].value; | 1338 | clock1 |= sample_rates[dsp_config].value; |
1346 | 1339 | ||
@@ -1366,7 +1359,7 @@ static int wm8903_hw_params(struct snd_pcm_substream *substream, | |||
1366 | return -EINVAL; | 1359 | return -EINVAL; |
1367 | } | 1360 | } |
1368 | 1361 | ||
1369 | dev_dbg(&i2c->dev, "MCLK = %dHz, target sample rate = %dHz\n", | 1362 | dev_dbg(codec->dev, "MCLK = %dHz, target sample rate = %dHz\n", |
1370 | wm8903->sysclk, fs); | 1363 | wm8903->sysclk, fs); |
1371 | 1364 | ||
1372 | /* We may not have an MCLK which allows us to generate exactly | 1365 | /* We may not have an MCLK which allows us to generate exactly |
@@ -1401,12 +1394,12 @@ static int wm8903_hw_params(struct snd_pcm_substream *substream, | |||
1401 | clock1 |= clk_sys_ratios[clk_config].rate << WM8903_CLK_SYS_RATE_SHIFT; | 1394 | clock1 |= clk_sys_ratios[clk_config].rate << WM8903_CLK_SYS_RATE_SHIFT; |
1402 | clock1 |= clk_sys_ratios[clk_config].mode << WM8903_CLK_SYS_MODE_SHIFT; | 1395 | clock1 |= clk_sys_ratios[clk_config].mode << WM8903_CLK_SYS_MODE_SHIFT; |
1403 | 1396 | ||
1404 | dev_dbg(&i2c->dev, "CLK_SYS_RATE=%x, CLK_SYS_MODE=%x div=%d\n", | 1397 | dev_dbg(codec->dev, "CLK_SYS_RATE=%x, CLK_SYS_MODE=%x div=%d\n", |
1405 | clk_sys_ratios[clk_config].rate, | 1398 | clk_sys_ratios[clk_config].rate, |
1406 | clk_sys_ratios[clk_config].mode, | 1399 | clk_sys_ratios[clk_config].mode, |
1407 | clk_sys_ratios[clk_config].div); | 1400 | clk_sys_ratios[clk_config].div); |
1408 | 1401 | ||
1409 | dev_dbg(&i2c->dev, "Actual CLK_SYS = %dHz\n", clk_sys); | 1402 | dev_dbg(codec->dev, "Actual CLK_SYS = %dHz\n", clk_sys); |
1410 | 1403 | ||
1411 | /* We may not get quite the right frequency if using | 1404 | /* We may not get quite the right frequency if using |
1412 | * approximate clocks so look for the closest match that is | 1405 | * approximate clocks so look for the closest match that is |
@@ -1428,7 +1421,7 @@ static int wm8903_hw_params(struct snd_pcm_substream *substream, | |||
1428 | aif2 &= ~WM8903_BCLK_DIV_MASK; | 1421 | aif2 &= ~WM8903_BCLK_DIV_MASK; |
1429 | aif3 &= ~WM8903_LRCLK_RATE_MASK; | 1422 | aif3 &= ~WM8903_LRCLK_RATE_MASK; |
1430 | 1423 | ||
1431 | dev_dbg(&i2c->dev, "BCLK ratio %d for %dHz - actual BCLK = %dHz\n", | 1424 | dev_dbg(codec->dev, "BCLK ratio %d for %dHz - actual BCLK = %dHz\n", |
1432 | bclk_divs[bclk_div].ratio / 10, bclk, | 1425 | bclk_divs[bclk_div].ratio / 10, bclk, |
1433 | (clk_sys * 10) / bclk_divs[bclk_div].ratio); | 1426 | (clk_sys * 10) / bclk_divs[bclk_div].ratio); |
1434 | 1427 | ||
@@ -1504,8 +1497,8 @@ EXPORT_SYMBOL_GPL(wm8903_mic_detect); | |||
1504 | 1497 | ||
1505 | static irqreturn_t wm8903_irq(int irq, void *data) | 1498 | static irqreturn_t wm8903_irq(int irq, void *data) |
1506 | { | 1499 | { |
1507 | struct wm8903_priv *wm8903 = data; | 1500 | struct snd_soc_codec *codec = data; |
1508 | struct snd_soc_codec *codec = &wm8903->codec; | 1501 | struct wm8903_priv *wm8903 = snd_soc_codec_get_drvdata(codec); |
1509 | int mic_report; | 1502 | int mic_report; |
1510 | int int_pol; | 1503 | int int_pol; |
1511 | int int_val = 0; | 1504 | int int_val = 0; |
@@ -1586,8 +1579,8 @@ static struct snd_soc_dai_ops wm8903_dai_ops = { | |||
1586 | .set_sysclk = wm8903_set_dai_sysclk, | 1579 | .set_sysclk = wm8903_set_dai_sysclk, |
1587 | }; | 1580 | }; |
1588 | 1581 | ||
1589 | struct snd_soc_dai wm8903_dai = { | 1582 | static struct snd_soc_dai_driver wm8903_dai = { |
1590 | .name = "WM8903", | 1583 | .name = "wm8903-hifi", |
1591 | .playback = { | 1584 | .playback = { |
1592 | .stream_name = "Playback", | 1585 | .stream_name = "Playback", |
1593 | .channels_min = 2, | 1586 | .channels_min = 2, |
@@ -1605,23 +1598,16 @@ struct snd_soc_dai wm8903_dai = { | |||
1605 | .ops = &wm8903_dai_ops, | 1598 | .ops = &wm8903_dai_ops, |
1606 | .symmetric_rates = 1, | 1599 | .symmetric_rates = 1, |
1607 | }; | 1600 | }; |
1608 | EXPORT_SYMBOL_GPL(wm8903_dai); | ||
1609 | 1601 | ||
1610 | static int wm8903_suspend(struct platform_device *pdev, pm_message_t state) | 1602 | static int wm8903_suspend(struct snd_soc_codec *codec, pm_message_t state) |
1611 | { | 1603 | { |
1612 | struct snd_soc_device *socdev = platform_get_drvdata(pdev); | ||
1613 | struct snd_soc_codec *codec = socdev->card->codec; | ||
1614 | |||
1615 | wm8903_set_bias_level(codec, SND_SOC_BIAS_OFF); | 1604 | wm8903_set_bias_level(codec, SND_SOC_BIAS_OFF); |
1616 | 1605 | ||
1617 | return 0; | 1606 | return 0; |
1618 | } | 1607 | } |
1619 | 1608 | ||
1620 | static int wm8903_resume(struct platform_device *pdev) | 1609 | static int wm8903_resume(struct snd_soc_codec *codec) |
1621 | { | 1610 | { |
1622 | struct snd_soc_device *socdev = platform_get_drvdata(pdev); | ||
1623 | struct snd_soc_codec *codec = socdev->card->codec; | ||
1624 | struct i2c_client *i2c = codec->control_data; | ||
1625 | int i; | 1611 | int i; |
1626 | u16 *reg_cache = codec->reg_cache; | 1612 | u16 *reg_cache = codec->reg_cache; |
1627 | u16 *tmp_cache = kmemdup(reg_cache, sizeof(wm8903_reg_defaults), | 1613 | u16 *tmp_cache = kmemdup(reg_cache, sizeof(wm8903_reg_defaults), |
@@ -1637,65 +1623,37 @@ static int wm8903_resume(struct platform_device *pdev) | |||
1637 | snd_soc_write(codec, i, tmp_cache[i]); | 1623 | snd_soc_write(codec, i, tmp_cache[i]); |
1638 | kfree(tmp_cache); | 1624 | kfree(tmp_cache); |
1639 | } else { | 1625 | } else { |
1640 | dev_err(&i2c->dev, "Failed to allocate temporary cache\n"); | 1626 | dev_err(codec->dev, "Failed to allocate temporary cache\n"); |
1641 | } | 1627 | } |
1642 | 1628 | ||
1643 | return 0; | 1629 | return 0; |
1644 | } | 1630 | } |
1645 | 1631 | ||
1646 | static struct snd_soc_codec *wm8903_codec; | 1632 | static int wm8903_probe(struct snd_soc_codec *codec) |
1647 | |||
1648 | static __devinit int wm8903_i2c_probe(struct i2c_client *i2c, | ||
1649 | const struct i2c_device_id *id) | ||
1650 | { | 1633 | { |
1651 | struct wm8903_platform_data *pdata = dev_get_platdata(&i2c->dev); | 1634 | struct wm8903_platform_data *pdata = dev_get_platdata(codec->dev); |
1652 | struct wm8903_priv *wm8903; | 1635 | struct wm8903_priv *wm8903 = snd_soc_codec_get_drvdata(codec); |
1653 | struct snd_soc_codec *codec; | ||
1654 | int ret, i; | 1636 | int ret, i; |
1655 | int trigger, irq_pol; | 1637 | int trigger, irq_pol; |
1656 | u16 val; | 1638 | u16 val; |
1657 | 1639 | ||
1658 | wm8903 = kzalloc(sizeof(struct wm8903_priv), GFP_KERNEL); | ||
1659 | if (wm8903 == NULL) | ||
1660 | return -ENOMEM; | ||
1661 | |||
1662 | codec = &wm8903->codec; | ||
1663 | |||
1664 | mutex_init(&codec->mutex); | ||
1665 | INIT_LIST_HEAD(&codec->dapm_widgets); | ||
1666 | INIT_LIST_HEAD(&codec->dapm_paths); | ||
1667 | |||
1668 | codec->dev = &i2c->dev; | ||
1669 | codec->name = "WM8903"; | ||
1670 | codec->owner = THIS_MODULE; | ||
1671 | codec->bias_level = SND_SOC_BIAS_OFF; | ||
1672 | codec->set_bias_level = wm8903_set_bias_level; | ||
1673 | codec->dai = &wm8903_dai; | ||
1674 | codec->num_dai = 1; | ||
1675 | codec->reg_cache_size = ARRAY_SIZE(wm8903->reg_cache); | ||
1676 | codec->reg_cache = &wm8903->reg_cache[0]; | ||
1677 | snd_soc_codec_set_drvdata(codec, wm8903); | ||
1678 | codec->volatile_register = wm8903_volatile_register; | ||
1679 | init_completion(&wm8903->wseq); | 1640 | init_completion(&wm8903->wseq); |
1680 | 1641 | ||
1681 | i2c_set_clientdata(i2c, codec); | ||
1682 | codec->control_data = i2c; | ||
1683 | |||
1684 | ret = snd_soc_codec_set_cache_io(codec, 8, 16, SND_SOC_I2C); | 1642 | ret = snd_soc_codec_set_cache_io(codec, 8, 16, SND_SOC_I2C); |
1685 | if (ret != 0) { | 1643 | if (ret != 0) { |
1686 | dev_err(&i2c->dev, "Failed to set cache I/O: %d\n", ret); | 1644 | dev_err(codec->dev, "Failed to set cache I/O: %d\n", ret); |
1687 | goto err; | 1645 | return ret; |
1688 | } | 1646 | } |
1689 | 1647 | ||
1690 | val = snd_soc_read(codec, WM8903_SW_RESET_AND_ID); | 1648 | val = snd_soc_read(codec, WM8903_SW_RESET_AND_ID); |
1691 | if (val != wm8903_reg_defaults[WM8903_SW_RESET_AND_ID]) { | 1649 | if (val != wm8903_reg_defaults[WM8903_SW_RESET_AND_ID]) { |
1692 | dev_err(&i2c->dev, | 1650 | dev_err(codec->dev, |
1693 | "Device with ID register %x is not a WM8903\n", val); | 1651 | "Device with ID register %x is not a WM8903\n", val); |
1694 | return -ENODEV; | 1652 | return -ENODEV; |
1695 | } | 1653 | } |
1696 | 1654 | ||
1697 | val = snd_soc_read(codec, WM8903_REVISION_NUMBER); | 1655 | val = snd_soc_read(codec, WM8903_REVISION_NUMBER); |
1698 | dev_info(&i2c->dev, "WM8903 revision %d\n", | 1656 | dev_info(codec->dev, "WM8903 revision %d\n", |
1699 | val & WM8903_CHIP_REV_MASK); | 1657 | val & WM8903_CHIP_REV_MASK); |
1700 | 1658 | ||
1701 | wm8903_reset(codec); | 1659 | wm8903_reset(codec); |
@@ -1721,7 +1679,7 @@ static __devinit int wm8903_i2c_probe(struct i2c_client *i2c, | |||
1721 | wm8903->mic_delay = pdata->micdet_delay; | 1679 | wm8903->mic_delay = pdata->micdet_delay; |
1722 | } | 1680 | } |
1723 | 1681 | ||
1724 | if (i2c->irq) { | 1682 | if (wm8903->irq) { |
1725 | if (pdata && pdata->irq_active_low) { | 1683 | if (pdata && pdata->irq_active_low) { |
1726 | trigger = IRQF_TRIGGER_LOW; | 1684 | trigger = IRQF_TRIGGER_LOW; |
1727 | irq_pol = WM8903_IRQ_POL; | 1685 | irq_pol = WM8903_IRQ_POL; |
@@ -1733,13 +1691,13 @@ static __devinit int wm8903_i2c_probe(struct i2c_client *i2c, | |||
1733 | snd_soc_update_bits(codec, WM8903_INTERRUPT_CONTROL, | 1691 | snd_soc_update_bits(codec, WM8903_INTERRUPT_CONTROL, |
1734 | WM8903_IRQ_POL, irq_pol); | 1692 | WM8903_IRQ_POL, irq_pol); |
1735 | 1693 | ||
1736 | ret = request_threaded_irq(i2c->irq, NULL, wm8903_irq, | 1694 | ret = request_threaded_irq(wm8903->irq, NULL, wm8903_irq, |
1737 | trigger | IRQF_ONESHOT, | 1695 | trigger | IRQF_ONESHOT, |
1738 | "wm8903", wm8903); | 1696 | "wm8903", codec); |
1739 | if (ret != 0) { | 1697 | if (ret != 0) { |
1740 | dev_err(&i2c->dev, "Failed to request IRQ: %d\n", | 1698 | dev_err(codec->dev, "Failed to request IRQ: %d\n", |
1741 | ret); | 1699 | ret); |
1742 | goto err; | 1700 | return ret; |
1743 | } | 1701 | } |
1744 | 1702 | ||
1745 | /* Enable write sequencer interrupts */ | 1703 | /* Enable write sequencer interrupts */ |
@@ -1781,133 +1739,96 @@ static __devinit int wm8903_i2c_probe(struct i2c_client *i2c, | |||
1781 | val |= WM8903_DAC_MUTEMODE; | 1739 | val |= WM8903_DAC_MUTEMODE; |
1782 | snd_soc_write(codec, WM8903_DAC_DIGITAL_1, val); | 1740 | snd_soc_write(codec, WM8903_DAC_DIGITAL_1, val); |
1783 | 1741 | ||
1784 | wm8903_dai.dev = &i2c->dev; | 1742 | snd_soc_add_controls(codec, wm8903_snd_controls, |
1785 | wm8903_codec = codec; | 1743 | ARRAY_SIZE(wm8903_snd_controls)); |
1786 | 1744 | wm8903_add_widgets(codec); | |
1787 | ret = snd_soc_register_codec(codec); | ||
1788 | if (ret != 0) { | ||
1789 | dev_err(&i2c->dev, "Failed to register codec: %d\n", ret); | ||
1790 | goto err_irq; | ||
1791 | } | ||
1792 | |||
1793 | ret = snd_soc_register_dai(&wm8903_dai); | ||
1794 | if (ret != 0) { | ||
1795 | dev_err(&i2c->dev, "Failed to register DAI: %d\n", ret); | ||
1796 | goto err_codec; | ||
1797 | } | ||
1798 | |||
1799 | return ret; | ||
1800 | 1745 | ||
1801 | err_codec: | ||
1802 | snd_soc_unregister_codec(codec); | ||
1803 | err_irq: | ||
1804 | if (i2c->irq) | ||
1805 | free_irq(i2c->irq, wm8903); | ||
1806 | err: | ||
1807 | wm8903_codec = NULL; | ||
1808 | kfree(wm8903); | ||
1809 | return ret; | 1746 | return ret; |
1810 | } | 1747 | } |
1811 | 1748 | ||
1812 | static __devexit int wm8903_i2c_remove(struct i2c_client *client) | 1749 | /* power down chip */ |
1750 | static int wm8903_remove(struct snd_soc_codec *codec) | ||
1813 | { | 1751 | { |
1814 | struct snd_soc_codec *codec = i2c_get_clientdata(client); | 1752 | wm8903_set_bias_level(codec, SND_SOC_BIAS_OFF); |
1815 | struct wm8903_priv *priv = snd_soc_codec_get_drvdata(codec); | 1753 | return 0; |
1754 | } | ||
1816 | 1755 | ||
1817 | snd_soc_unregister_dai(&wm8903_dai); | 1756 | static struct snd_soc_codec_driver soc_codec_dev_wm8903 = { |
1818 | snd_soc_unregister_codec(codec); | 1757 | .probe = wm8903_probe, |
1758 | .remove = wm8903_remove, | ||
1759 | .suspend = wm8903_suspend, | ||
1760 | .resume = wm8903_resume, | ||
1761 | .set_bias_level = wm8903_set_bias_level, | ||
1762 | .reg_cache_size = ARRAY_SIZE(wm8903_reg_defaults), | ||
1763 | .reg_word_size = sizeof(u16), | ||
1764 | .reg_cache_default = wm8903_reg_defaults, | ||
1765 | .volatile_register = wm8903_volatile_register, | ||
1766 | }; | ||
1819 | 1767 | ||
1820 | wm8903_set_bias_level(codec, SND_SOC_BIAS_OFF); | 1768 | #if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE) |
1769 | static __devinit int wm8903_i2c_probe(struct i2c_client *i2c, | ||
1770 | const struct i2c_device_id *id) | ||
1771 | { | ||
1772 | struct wm8903_priv *wm8903; | ||
1773 | int ret; | ||
1821 | 1774 | ||
1822 | if (client->irq) | 1775 | wm8903 = kzalloc(sizeof(struct wm8903_priv), GFP_KERNEL); |
1823 | free_irq(client->irq, priv); | 1776 | if (wm8903 == NULL) |
1777 | return -ENOMEM; | ||
1824 | 1778 | ||
1825 | kfree(priv); | 1779 | i2c_set_clientdata(i2c, wm8903); |
1780 | wm8903->irq = i2c->irq; | ||
1826 | 1781 | ||
1827 | wm8903_codec = NULL; | 1782 | ret = snd_soc_register_codec(&i2c->dev, |
1828 | wm8903_dai.dev = NULL; | 1783 | &soc_codec_dev_wm8903, &wm8903_dai, 1); |
1784 | if (ret < 0) | ||
1785 | kfree(wm8903); | ||
1786 | return ret; | ||
1787 | } | ||
1829 | 1788 | ||
1789 | static __devexit int wm8903_i2c_remove(struct i2c_client *client) | ||
1790 | { | ||
1791 | snd_soc_unregister_codec(&client->dev); | ||
1792 | kfree(i2c_get_clientdata(client)); | ||
1830 | return 0; | 1793 | return 0; |
1831 | } | 1794 | } |
1832 | 1795 | ||
1833 | /* i2c codec control layer */ | ||
1834 | static const struct i2c_device_id wm8903_i2c_id[] = { | 1796 | static const struct i2c_device_id wm8903_i2c_id[] = { |
1835 | { "wm8903", 0 }, | 1797 | { "wm8903", 0 }, |
1836 | { } | 1798 | { } |
1837 | }; | 1799 | }; |
1838 | MODULE_DEVICE_TABLE(i2c, wm8903_i2c_id); | 1800 | MODULE_DEVICE_TABLE(i2c, wm8903_i2c_id); |
1839 | 1801 | ||
1840 | static struct i2c_driver wm8903_i2c_driver = { | 1802 | static struct i2c_driver wm8903_i2c_driver = { |
1841 | .driver = { | 1803 | .driver = { |
1842 | .name = "WM8903", | 1804 | .name = "wm8903-codec", |
1843 | .owner = THIS_MODULE, | 1805 | .owner = THIS_MODULE, |
1844 | }, | 1806 | }, |
1845 | .probe = wm8903_i2c_probe, | 1807 | .probe = wm8903_i2c_probe, |
1846 | .remove = __devexit_p(wm8903_i2c_remove), | 1808 | .remove = __devexit_p(wm8903_i2c_remove), |
1847 | .id_table = wm8903_i2c_id, | 1809 | .id_table = wm8903_i2c_id, |
1848 | }; | 1810 | }; |
1811 | #endif | ||
1849 | 1812 | ||
1850 | static int wm8903_probe(struct platform_device *pdev) | 1813 | static int __init wm8903_modinit(void) |
1851 | { | 1814 | { |
1852 | struct snd_soc_device *socdev = platform_get_drvdata(pdev); | ||
1853 | int ret = 0; | 1815 | int ret = 0; |
1854 | 1816 | #if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE) | |
1855 | if (!wm8903_codec) { | 1817 | ret = i2c_add_driver(&wm8903_i2c_driver); |
1856 | dev_err(&pdev->dev, "I2C device not yet probed\n"); | 1818 | if (ret != 0) { |
1857 | goto err; | 1819 | printk(KERN_ERR "Failed to register wm8903 I2C driver: %d\n", |
1858 | } | 1820 | ret); |
1859 | |||
1860 | socdev->card->codec = wm8903_codec; | ||
1861 | |||
1862 | /* register pcms */ | ||
1863 | ret = snd_soc_new_pcms(socdev, SNDRV_DEFAULT_IDX1, SNDRV_DEFAULT_STR1); | ||
1864 | if (ret < 0) { | ||
1865 | dev_err(&pdev->dev, "failed to create pcms\n"); | ||
1866 | goto err; | ||
1867 | } | 1821 | } |
1868 | 1822 | #endif | |
1869 | snd_soc_add_controls(socdev->card->codec, wm8903_snd_controls, | ||
1870 | ARRAY_SIZE(wm8903_snd_controls)); | ||
1871 | wm8903_add_widgets(socdev->card->codec); | ||
1872 | |||
1873 | return ret; | 1823 | return ret; |
1874 | |||
1875 | err: | ||
1876 | return ret; | ||
1877 | } | ||
1878 | |||
1879 | /* power down chip */ | ||
1880 | static int wm8903_remove(struct platform_device *pdev) | ||
1881 | { | ||
1882 | struct snd_soc_device *socdev = platform_get_drvdata(pdev); | ||
1883 | struct snd_soc_codec *codec = socdev->card->codec; | ||
1884 | |||
1885 | if (codec->control_data) | ||
1886 | wm8903_set_bias_level(codec, SND_SOC_BIAS_OFF); | ||
1887 | |||
1888 | snd_soc_free_pcms(socdev); | ||
1889 | snd_soc_dapm_free(socdev); | ||
1890 | |||
1891 | return 0; | ||
1892 | } | ||
1893 | |||
1894 | struct snd_soc_codec_device soc_codec_dev_wm8903 = { | ||
1895 | .probe = wm8903_probe, | ||
1896 | .remove = wm8903_remove, | ||
1897 | .suspend = wm8903_suspend, | ||
1898 | .resume = wm8903_resume, | ||
1899 | }; | ||
1900 | EXPORT_SYMBOL_GPL(soc_codec_dev_wm8903); | ||
1901 | |||
1902 | static int __init wm8903_modinit(void) | ||
1903 | { | ||
1904 | return i2c_add_driver(&wm8903_i2c_driver); | ||
1905 | } | 1824 | } |
1906 | module_init(wm8903_modinit); | 1825 | module_init(wm8903_modinit); |
1907 | 1826 | ||
1908 | static void __exit wm8903_exit(void) | 1827 | static void __exit wm8903_exit(void) |
1909 | { | 1828 | { |
1829 | #if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE) | ||
1910 | i2c_del_driver(&wm8903_i2c_driver); | 1830 | i2c_del_driver(&wm8903_i2c_driver); |
1831 | #endif | ||
1911 | } | 1832 | } |
1912 | module_exit(wm8903_exit); | 1833 | module_exit(wm8903_exit); |
1913 | 1834 | ||
diff --git a/sound/soc/codecs/wm8903.h b/sound/soc/codecs/wm8903.h index ce384a2ad820..996435e681e5 100644 --- a/sound/soc/codecs/wm8903.h +++ b/sound/soc/codecs/wm8903.h | |||
@@ -15,9 +15,6 @@ | |||
15 | 15 | ||
16 | #include <linux/i2c.h> | 16 | #include <linux/i2c.h> |
17 | 17 | ||
18 | extern struct snd_soc_dai wm8903_dai; | ||
19 | extern struct snd_soc_codec_device soc_codec_dev_wm8903; | ||
20 | |||
21 | extern int wm8903_mic_detect(struct snd_soc_codec *codec, | 18 | extern int wm8903_mic_detect(struct snd_soc_codec *codec, |
22 | struct snd_soc_jack *jack, | 19 | struct snd_soc_jack *jack, |
23 | int det, int shrt); | 20 | int det, int shrt); |
diff --git a/sound/soc/codecs/wm8904.c b/sound/soc/codecs/wm8904.c index f7dcabf6283c..33be84e506ea 100644 --- a/sound/soc/codecs/wm8904.c +++ b/sound/soc/codecs/wm8904.c | |||
@@ -31,9 +31,6 @@ | |||
31 | 31 | ||
32 | #include "wm8904.h" | 32 | #include "wm8904.h" |
33 | 33 | ||
34 | static struct snd_soc_codec *wm8904_codec; | ||
35 | struct snd_soc_codec_device soc_codec_dev_wm8904; | ||
36 | |||
37 | enum wm8904_type { | 34 | enum wm8904_type { |
38 | WM8904, | 35 | WM8904, |
39 | WM8912, | 36 | WM8912, |
@@ -52,10 +49,11 @@ static const char *wm8904_supply_names[WM8904_NUM_SUPPLIES] = { | |||
52 | 49 | ||
53 | /* codec private data */ | 50 | /* codec private data */ |
54 | struct wm8904_priv { | 51 | struct wm8904_priv { |
55 | struct snd_soc_codec codec; | 52 | |
56 | u16 reg_cache[WM8904_MAX_REGISTER + 1]; | 53 | u16 reg_cache[WM8904_MAX_REGISTER + 1]; |
57 | 54 | ||
58 | enum wm8904_type devtype; | 55 | enum wm8904_type devtype; |
56 | void *control_data; | ||
59 | 57 | ||
60 | struct regulator_bulk_data supplies[WM8904_NUM_SUPPLIES]; | 58 | struct regulator_bulk_data supplies[WM8904_NUM_SUPPLIES]; |
61 | 59 | ||
@@ -689,7 +687,7 @@ static int wm8904_put_drc_enum(struct snd_kcontrol *kcontrol, | |||
689 | struct snd_ctl_elem_value *ucontrol) | 687 | struct snd_ctl_elem_value *ucontrol) |
690 | { | 688 | { |
691 | struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol); | 689 | struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol); |
692 | struct wm8904_priv *wm8904 = snd_soc_codec_get_drvdata(codec); | 690 | struct wm8904_priv *wm8904 = snd_soc_codec_get_drvdata(codec); |
693 | struct wm8904_pdata *pdata = wm8904->pdata; | 691 | struct wm8904_pdata *pdata = wm8904->pdata; |
694 | int value = ucontrol->value.integer.value[0]; | 692 | int value = ucontrol->value.integer.value[0]; |
695 | 693 | ||
@@ -760,7 +758,7 @@ static int wm8904_put_retune_mobile_enum(struct snd_kcontrol *kcontrol, | |||
760 | struct snd_ctl_elem_value *ucontrol) | 758 | struct snd_ctl_elem_value *ucontrol) |
761 | { | 759 | { |
762 | struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol); | 760 | struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol); |
763 | struct wm8904_priv *wm8904 = snd_soc_codec_get_drvdata(codec); | 761 | struct wm8904_priv *wm8904 = snd_soc_codec_get_drvdata(codec); |
764 | struct wm8904_pdata *pdata = wm8904->pdata; | 762 | struct wm8904_pdata *pdata = wm8904->pdata; |
765 | int value = ucontrol->value.integer.value[0]; | 763 | int value = ucontrol->value.integer.value[0]; |
766 | 764 | ||
@@ -2218,8 +2216,8 @@ static struct snd_soc_dai_ops wm8904_dai_ops = { | |||
2218 | .digital_mute = wm8904_digital_mute, | 2216 | .digital_mute = wm8904_digital_mute, |
2219 | }; | 2217 | }; |
2220 | 2218 | ||
2221 | struct snd_soc_dai wm8904_dai = { | 2219 | static struct snd_soc_dai_driver wm8904_dai = { |
2222 | .name = "WM8904", | 2220 | .name = "wm8904-hifi", |
2223 | .playback = { | 2221 | .playback = { |
2224 | .stream_name = "Playback", | 2222 | .stream_name = "Playback", |
2225 | .channels_min = 2, | 2223 | .channels_min = 2, |
@@ -2237,24 +2235,17 @@ struct snd_soc_dai wm8904_dai = { | |||
2237 | .ops = &wm8904_dai_ops, | 2235 | .ops = &wm8904_dai_ops, |
2238 | .symmetric_rates = 1, | 2236 | .symmetric_rates = 1, |
2239 | }; | 2237 | }; |
2240 | EXPORT_SYMBOL_GPL(wm8904_dai); | ||
2241 | 2238 | ||
2242 | #ifdef CONFIG_PM | 2239 | #ifdef CONFIG_PM |
2243 | static int wm8904_suspend(struct platform_device *pdev, pm_message_t state) | 2240 | static int wm8904_suspend(struct snd_soc_codec *codec, pm_message_t state) |
2244 | { | 2241 | { |
2245 | struct snd_soc_device *socdev = platform_get_drvdata(pdev); | ||
2246 | struct snd_soc_codec *codec = socdev->card->codec; | ||
2247 | |||
2248 | wm8904_set_bias_level(codec, SND_SOC_BIAS_OFF); | 2242 | wm8904_set_bias_level(codec, SND_SOC_BIAS_OFF); |
2249 | 2243 | ||
2250 | return 0; | 2244 | return 0; |
2251 | } | 2245 | } |
2252 | 2246 | ||
2253 | static int wm8904_resume(struct platform_device *pdev) | 2247 | static int wm8904_resume(struct snd_soc_codec *codec) |
2254 | { | 2248 | { |
2255 | struct snd_soc_device *socdev = platform_get_drvdata(pdev); | ||
2256 | struct snd_soc_codec *codec = socdev->card->codec; | ||
2257 | |||
2258 | wm8904_set_bias_level(codec, SND_SOC_BIAS_STANDBY); | 2249 | wm8904_set_bias_level(codec, SND_SOC_BIAS_STANDBY); |
2259 | 2250 | ||
2260 | return 0; | 2251 | return 0; |
@@ -2264,9 +2255,9 @@ static int wm8904_resume(struct platform_device *pdev) | |||
2264 | #define wm8904_resume NULL | 2255 | #define wm8904_resume NULL |
2265 | #endif | 2256 | #endif |
2266 | 2257 | ||
2267 | static void wm8904_handle_retune_mobile_pdata(struct wm8904_priv *wm8904) | 2258 | static void wm8904_handle_retune_mobile_pdata(struct snd_soc_codec *codec) |
2268 | { | 2259 | { |
2269 | struct snd_soc_codec *codec = &wm8904->codec; | 2260 | struct wm8904_priv *wm8904 = snd_soc_codec_get_drvdata(codec); |
2270 | struct wm8904_pdata *pdata = wm8904->pdata; | 2261 | struct wm8904_pdata *pdata = wm8904->pdata; |
2271 | struct snd_kcontrol_new control = | 2262 | struct snd_kcontrol_new control = |
2272 | SOC_ENUM_EXT("EQ Mode", | 2263 | SOC_ENUM_EXT("EQ Mode", |
@@ -2315,20 +2306,20 @@ static void wm8904_handle_retune_mobile_pdata(struct wm8904_priv *wm8904) | |||
2315 | wm8904->retune_mobile_enum.max = wm8904->num_retune_mobile_texts; | 2306 | wm8904->retune_mobile_enum.max = wm8904->num_retune_mobile_texts; |
2316 | wm8904->retune_mobile_enum.texts = wm8904->retune_mobile_texts; | 2307 | wm8904->retune_mobile_enum.texts = wm8904->retune_mobile_texts; |
2317 | 2308 | ||
2318 | ret = snd_soc_add_controls(&wm8904->codec, &control, 1); | 2309 | ret = snd_soc_add_controls(codec, &control, 1); |
2319 | if (ret != 0) | 2310 | if (ret != 0) |
2320 | dev_err(wm8904->codec.dev, | 2311 | dev_err(codec->dev, |
2321 | "Failed to add ReTune Mobile control: %d\n", ret); | 2312 | "Failed to add ReTune Mobile control: %d\n", ret); |
2322 | } | 2313 | } |
2323 | 2314 | ||
2324 | static void wm8904_handle_pdata(struct wm8904_priv *wm8904) | 2315 | static void wm8904_handle_pdata(struct snd_soc_codec *codec) |
2325 | { | 2316 | { |
2326 | struct snd_soc_codec *codec = &wm8904->codec; | 2317 | struct wm8904_priv *wm8904 = snd_soc_codec_get_drvdata(codec); |
2327 | struct wm8904_pdata *pdata = wm8904->pdata; | 2318 | struct wm8904_pdata *pdata = wm8904->pdata; |
2328 | int ret, i; | 2319 | int ret, i; |
2329 | 2320 | ||
2330 | if (!pdata) { | 2321 | if (!pdata) { |
2331 | snd_soc_add_controls(&wm8904->codec, wm8904_eq_controls, | 2322 | snd_soc_add_controls(codec, wm8904_eq_controls, |
2332 | ARRAY_SIZE(wm8904_eq_controls)); | 2323 | ARRAY_SIZE(wm8904_eq_controls)); |
2333 | return; | 2324 | return; |
2334 | } | 2325 | } |
@@ -2344,7 +2335,7 @@ static void wm8904_handle_pdata(struct wm8904_priv *wm8904) | |||
2344 | wm8904->drc_texts = kmalloc(sizeof(char *) | 2335 | wm8904->drc_texts = kmalloc(sizeof(char *) |
2345 | * pdata->num_drc_cfgs, GFP_KERNEL); | 2336 | * pdata->num_drc_cfgs, GFP_KERNEL); |
2346 | if (!wm8904->drc_texts) { | 2337 | if (!wm8904->drc_texts) { |
2347 | dev_err(wm8904->codec.dev, | 2338 | dev_err(codec->dev, |
2348 | "Failed to allocate %d DRC config texts\n", | 2339 | "Failed to allocate %d DRC config texts\n", |
2349 | pdata->num_drc_cfgs); | 2340 | pdata->num_drc_cfgs); |
2350 | return; | 2341 | return; |
@@ -2356,9 +2347,9 @@ static void wm8904_handle_pdata(struct wm8904_priv *wm8904) | |||
2356 | wm8904->drc_enum.max = pdata->num_drc_cfgs; | 2347 | wm8904->drc_enum.max = pdata->num_drc_cfgs; |
2357 | wm8904->drc_enum.texts = wm8904->drc_texts; | 2348 | wm8904->drc_enum.texts = wm8904->drc_texts; |
2358 | 2349 | ||
2359 | ret = snd_soc_add_controls(&wm8904->codec, &control, 1); | 2350 | ret = snd_soc_add_controls(codec, &control, 1); |
2360 | if (ret != 0) | 2351 | if (ret != 0) |
2361 | dev_err(wm8904->codec.dev, | 2352 | dev_err(codec->dev, |
2362 | "Failed to add DRC mode control: %d\n", ret); | 2353 | "Failed to add DRC mode control: %d\n", ret); |
2363 | 2354 | ||
2364 | wm8904_set_drc(codec); | 2355 | wm8904_set_drc(codec); |
@@ -2368,89 +2359,19 @@ static void wm8904_handle_pdata(struct wm8904_priv *wm8904) | |||
2368 | pdata->num_retune_mobile_cfgs); | 2359 | pdata->num_retune_mobile_cfgs); |
2369 | 2360 | ||
2370 | if (pdata->num_retune_mobile_cfgs) | 2361 | if (pdata->num_retune_mobile_cfgs) |
2371 | wm8904_handle_retune_mobile_pdata(wm8904); | 2362 | wm8904_handle_retune_mobile_pdata(codec); |
2372 | else | 2363 | else |
2373 | snd_soc_add_controls(&wm8904->codec, wm8904_eq_controls, | 2364 | snd_soc_add_controls(codec, wm8904_eq_controls, |
2374 | ARRAY_SIZE(wm8904_eq_controls)); | 2365 | ARRAY_SIZE(wm8904_eq_controls)); |
2375 | } | 2366 | } |
2376 | 2367 | ||
2377 | static int wm8904_probe(struct platform_device *pdev) | ||
2378 | { | ||
2379 | struct snd_soc_device *socdev = platform_get_drvdata(pdev); | ||
2380 | struct snd_soc_codec *codec; | ||
2381 | int ret = 0; | ||
2382 | |||
2383 | if (wm8904_codec == NULL) { | ||
2384 | dev_err(&pdev->dev, "Codec device not registered\n"); | ||
2385 | return -ENODEV; | ||
2386 | } | ||
2387 | 2368 | ||
2388 | socdev->card->codec = wm8904_codec; | 2369 | static int wm8904_probe(struct snd_soc_codec *codec) |
2389 | codec = wm8904_codec; | ||
2390 | |||
2391 | /* register pcms */ | ||
2392 | ret = snd_soc_new_pcms(socdev, SNDRV_DEFAULT_IDX1, SNDRV_DEFAULT_STR1); | ||
2393 | if (ret < 0) { | ||
2394 | dev_err(codec->dev, "failed to create pcms: %d\n", ret); | ||
2395 | goto pcm_err; | ||
2396 | } | ||
2397 | |||
2398 | wm8904_handle_pdata(snd_soc_codec_get_drvdata(codec)); | ||
2399 | |||
2400 | wm8904_add_widgets(codec); | ||
2401 | |||
2402 | return ret; | ||
2403 | |||
2404 | pcm_err: | ||
2405 | return ret; | ||
2406 | } | ||
2407 | |||
2408 | static int wm8904_remove(struct platform_device *pdev) | ||
2409 | { | ||
2410 | struct snd_soc_device *socdev = platform_get_drvdata(pdev); | ||
2411 | |||
2412 | snd_soc_free_pcms(socdev); | ||
2413 | snd_soc_dapm_free(socdev); | ||
2414 | |||
2415 | return 0; | ||
2416 | } | ||
2417 | |||
2418 | struct snd_soc_codec_device soc_codec_dev_wm8904 = { | ||
2419 | .probe = wm8904_probe, | ||
2420 | .remove = wm8904_remove, | ||
2421 | .suspend = wm8904_suspend, | ||
2422 | .resume = wm8904_resume, | ||
2423 | }; | ||
2424 | EXPORT_SYMBOL_GPL(soc_codec_dev_wm8904); | ||
2425 | |||
2426 | static int wm8904_register(struct wm8904_priv *wm8904, | ||
2427 | enum snd_soc_control_type control) | ||
2428 | { | 2370 | { |
2371 | struct wm8904_priv *wm8904 = snd_soc_codec_get_drvdata(codec); | ||
2429 | struct wm8904_pdata *pdata = wm8904->pdata; | 2372 | struct wm8904_pdata *pdata = wm8904->pdata; |
2430 | int ret; | 2373 | int ret, i; |
2431 | struct snd_soc_codec *codec = &wm8904->codec; | ||
2432 | int i; | ||
2433 | |||
2434 | if (wm8904_codec) { | ||
2435 | dev_err(codec->dev, "Another WM8904 is registered\n"); | ||
2436 | ret = -EINVAL; | ||
2437 | goto err; | ||
2438 | } | ||
2439 | 2374 | ||
2440 | mutex_init(&codec->mutex); | ||
2441 | INIT_LIST_HEAD(&codec->dapm_widgets); | ||
2442 | INIT_LIST_HEAD(&codec->dapm_paths); | ||
2443 | |||
2444 | snd_soc_codec_set_drvdata(codec, wm8904); | ||
2445 | codec->name = "WM8904"; | ||
2446 | codec->owner = THIS_MODULE; | ||
2447 | codec->bias_level = SND_SOC_BIAS_OFF; | ||
2448 | codec->set_bias_level = wm8904_set_bias_level; | ||
2449 | codec->dai = &wm8904_dai; | ||
2450 | codec->num_dai = 1; | ||
2451 | codec->reg_cache_size = WM8904_MAX_REGISTER; | ||
2452 | codec->reg_cache = &wm8904->reg_cache; | ||
2453 | codec->volatile_register = wm8904_volatile_register; | ||
2454 | codec->cache_sync = 1; | 2375 | codec->cache_sync = 1; |
2455 | codec->idle_bias_off = 1; | 2376 | codec->idle_bias_off = 1; |
2456 | 2377 | ||
@@ -2463,16 +2384,13 @@ static int wm8904_register(struct wm8904_priv *wm8904, | |||
2463 | default: | 2384 | default: |
2464 | dev_err(codec->dev, "Unknown device type %d\n", | 2385 | dev_err(codec->dev, "Unknown device type %d\n", |
2465 | wm8904->devtype); | 2386 | wm8904->devtype); |
2466 | ret = -EINVAL; | 2387 | return -EINVAL; |
2467 | goto err; | ||
2468 | } | 2388 | } |
2469 | 2389 | ||
2470 | memcpy(codec->reg_cache, wm8904_reg, sizeof(wm8904_reg)); | 2390 | ret = snd_soc_codec_set_cache_io(codec, 8, 16, SND_SOC_I2C); |
2471 | |||
2472 | ret = snd_soc_codec_set_cache_io(codec, 8, 16, control); | ||
2473 | if (ret != 0) { | 2391 | if (ret != 0) { |
2474 | dev_err(codec->dev, "Failed to set cache I/O: %d\n", ret); | 2392 | dev_err(codec->dev, "Failed to set cache I/O: %d\n", ret); |
2475 | goto err; | 2393 | return ret; |
2476 | } | 2394 | } |
2477 | 2395 | ||
2478 | for (i = 0; i < ARRAY_SIZE(wm8904->supplies); i++) | 2396 | for (i = 0; i < ARRAY_SIZE(wm8904->supplies); i++) |
@@ -2482,7 +2400,7 @@ static int wm8904_register(struct wm8904_priv *wm8904, | |||
2482 | wm8904->supplies); | 2400 | wm8904->supplies); |
2483 | if (ret != 0) { | 2401 | if (ret != 0) { |
2484 | dev_err(codec->dev, "Failed to request supplies: %d\n", ret); | 2402 | dev_err(codec->dev, "Failed to request supplies: %d\n", ret); |
2485 | goto err; | 2403 | return ret; |
2486 | } | 2404 | } |
2487 | 2405 | ||
2488 | ret = regulator_bulk_enable(ARRAY_SIZE(wm8904->supplies), | 2406 | ret = regulator_bulk_enable(ARRAY_SIZE(wm8904->supplies), |
@@ -2517,8 +2435,6 @@ static int wm8904_register(struct wm8904_priv *wm8904, | |||
2517 | goto err_enable; | 2435 | goto err_enable; |
2518 | } | 2436 | } |
2519 | 2437 | ||
2520 | wm8904_dai.dev = codec->dev; | ||
2521 | |||
2522 | /* Change some default settings - latch VU and enable ZC */ | 2438 | /* Change some default settings - latch VU and enable ZC */ |
2523 | wm8904->reg_cache[WM8904_ADC_DIGITAL_VOLUME_LEFT] |= WM8904_ADC_VU; | 2439 | wm8904->reg_cache[WM8904_ADC_DIGITAL_VOLUME_LEFT] |= WM8904_ADC_VU; |
2524 | wm8904->reg_cache[WM8904_ADC_DIGITAL_VOLUME_RIGHT] |= WM8904_ADC_VU; | 2440 | wm8904->reg_cache[WM8904_ADC_DIGITAL_VOLUME_RIGHT] |= WM8904_ADC_VU; |
@@ -2563,72 +2479,68 @@ static int wm8904_register(struct wm8904_priv *wm8904, | |||
2563 | /* Bias level configuration will have done an extra enable */ | 2479 | /* Bias level configuration will have done an extra enable */ |
2564 | regulator_bulk_disable(ARRAY_SIZE(wm8904->supplies), wm8904->supplies); | 2480 | regulator_bulk_disable(ARRAY_SIZE(wm8904->supplies), wm8904->supplies); |
2565 | 2481 | ||
2566 | wm8904_codec = codec; | 2482 | wm8904_handle_pdata(codec); |
2567 | 2483 | ||
2568 | ret = snd_soc_register_codec(codec); | 2484 | wm8904_add_widgets(codec); |
2569 | if (ret != 0) { | ||
2570 | dev_err(codec->dev, "Failed to register codec: %d\n", ret); | ||
2571 | goto err_enable; | ||
2572 | } | ||
2573 | |||
2574 | ret = snd_soc_register_dai(&wm8904_dai); | ||
2575 | if (ret != 0) { | ||
2576 | dev_err(codec->dev, "Failed to register DAI: %d\n", ret); | ||
2577 | goto err_codec; | ||
2578 | } | ||
2579 | 2485 | ||
2580 | return 0; | 2486 | return 0; |
2581 | 2487 | ||
2582 | err_codec: | ||
2583 | snd_soc_unregister_codec(codec); | ||
2584 | err_enable: | 2488 | err_enable: |
2585 | regulator_bulk_disable(ARRAY_SIZE(wm8904->supplies), wm8904->supplies); | 2489 | regulator_bulk_disable(ARRAY_SIZE(wm8904->supplies), wm8904->supplies); |
2586 | err_get: | 2490 | err_get: |
2587 | regulator_bulk_free(ARRAY_SIZE(wm8904->supplies), wm8904->supplies); | 2491 | regulator_bulk_free(ARRAY_SIZE(wm8904->supplies), wm8904->supplies); |
2588 | err: | ||
2589 | kfree(wm8904); | ||
2590 | return ret; | 2492 | return ret; |
2591 | } | 2493 | } |
2592 | 2494 | ||
2593 | static void wm8904_unregister(struct wm8904_priv *wm8904) | 2495 | static int wm8904_remove(struct snd_soc_codec *codec) |
2594 | { | 2496 | { |
2595 | wm8904_set_bias_level(&wm8904->codec, SND_SOC_BIAS_OFF); | 2497 | struct wm8904_priv *wm8904 = snd_soc_codec_get_drvdata(codec); |
2498 | |||
2499 | wm8904_set_bias_level(codec, SND_SOC_BIAS_OFF); | ||
2596 | regulator_bulk_free(ARRAY_SIZE(wm8904->supplies), wm8904->supplies); | 2500 | regulator_bulk_free(ARRAY_SIZE(wm8904->supplies), wm8904->supplies); |
2597 | snd_soc_unregister_dai(&wm8904_dai); | 2501 | |
2598 | snd_soc_unregister_codec(&wm8904->codec); | 2502 | return 0; |
2599 | kfree(wm8904); | ||
2600 | wm8904_codec = NULL; | ||
2601 | } | 2503 | } |
2602 | 2504 | ||
2505 | static struct snd_soc_codec_driver soc_codec_dev_wm8904 = { | ||
2506 | .probe = wm8904_probe, | ||
2507 | .remove = wm8904_remove, | ||
2508 | .suspend = wm8904_suspend, | ||
2509 | .resume = wm8904_resume, | ||
2510 | .set_bias_level = wm8904_set_bias_level, | ||
2511 | .reg_cache_size = ARRAY_SIZE(wm8904_reg), | ||
2512 | .reg_word_size = sizeof(u16), | ||
2513 | .reg_cache_default = wm8904_reg, | ||
2514 | .volatile_register = wm8904_volatile_register, | ||
2515 | }; | ||
2516 | |||
2603 | #if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE) | 2517 | #if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE) |
2604 | static __devinit int wm8904_i2c_probe(struct i2c_client *i2c, | 2518 | static __devinit int wm8904_i2c_probe(struct i2c_client *i2c, |
2605 | const struct i2c_device_id *id) | 2519 | const struct i2c_device_id *id) |
2606 | { | 2520 | { |
2607 | struct wm8904_priv *wm8904; | 2521 | struct wm8904_priv *wm8904; |
2608 | struct snd_soc_codec *codec; | 2522 | int ret; |
2609 | 2523 | ||
2610 | wm8904 = kzalloc(sizeof(struct wm8904_priv), GFP_KERNEL); | 2524 | wm8904 = kzalloc(sizeof(struct wm8904_priv), GFP_KERNEL); |
2611 | if (wm8904 == NULL) | 2525 | if (wm8904 == NULL) |
2612 | return -ENOMEM; | 2526 | return -ENOMEM; |
2613 | 2527 | ||
2614 | codec = &wm8904->codec; | ||
2615 | codec->hw_write = (hw_write_t)i2c_master_send; | ||
2616 | |||
2617 | wm8904->devtype = id->driver_data; | 2528 | wm8904->devtype = id->driver_data; |
2618 | |||
2619 | i2c_set_clientdata(i2c, wm8904); | 2529 | i2c_set_clientdata(i2c, wm8904); |
2620 | codec->control_data = i2c; | 2530 | wm8904->control_data = i2c; |
2621 | wm8904->pdata = i2c->dev.platform_data; | 2531 | wm8904->pdata = i2c->dev.platform_data; |
2622 | 2532 | ||
2623 | codec->dev = &i2c->dev; | 2533 | ret = snd_soc_register_codec(&i2c->dev, |
2624 | 2534 | &soc_codec_dev_wm8904, &wm8904_dai, 1); | |
2625 | return wm8904_register(wm8904, SND_SOC_I2C); | 2535 | if (ret < 0) |
2536 | kfree(wm8904); | ||
2537 | return ret; | ||
2626 | } | 2538 | } |
2627 | 2539 | ||
2628 | static __devexit int wm8904_i2c_remove(struct i2c_client *client) | 2540 | static __devexit int wm8904_i2c_remove(struct i2c_client *client) |
2629 | { | 2541 | { |
2630 | struct wm8904_priv *wm8904 = i2c_get_clientdata(client); | 2542 | snd_soc_unregister_codec(&client->dev); |
2631 | wm8904_unregister(wm8904); | 2543 | kfree(i2c_get_clientdata(client)); |
2632 | return 0; | 2544 | return 0; |
2633 | } | 2545 | } |
2634 | 2546 | ||
@@ -2641,7 +2553,7 @@ MODULE_DEVICE_TABLE(i2c, wm8904_i2c_id); | |||
2641 | 2553 | ||
2642 | static struct i2c_driver wm8904_i2c_driver = { | 2554 | static struct i2c_driver wm8904_i2c_driver = { |
2643 | .driver = { | 2555 | .driver = { |
2644 | .name = "WM8904", | 2556 | .name = "wm8904-codec", |
2645 | .owner = THIS_MODULE, | 2557 | .owner = THIS_MODULE, |
2646 | }, | 2558 | }, |
2647 | .probe = wm8904_i2c_probe, | 2559 | .probe = wm8904_i2c_probe, |
@@ -2652,15 +2564,15 @@ static struct i2c_driver wm8904_i2c_driver = { | |||
2652 | 2564 | ||
2653 | static int __init wm8904_modinit(void) | 2565 | static int __init wm8904_modinit(void) |
2654 | { | 2566 | { |
2655 | int ret; | 2567 | int ret = 0; |
2656 | #if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE) | 2568 | #if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE) |
2657 | ret = i2c_add_driver(&wm8904_i2c_driver); | 2569 | ret = i2c_add_driver(&wm8904_i2c_driver); |
2658 | if (ret != 0) { | 2570 | if (ret != 0) { |
2659 | printk(KERN_ERR "Failed to register WM8904 I2C driver: %d\n", | 2571 | printk(KERN_ERR "Failed to register wm8904 I2C driver: %d\n", |
2660 | ret); | 2572 | ret); |
2661 | } | 2573 | } |
2662 | #endif | 2574 | #endif |
2663 | return 0; | 2575 | return ret; |
2664 | } | 2576 | } |
2665 | module_init(wm8904_modinit); | 2577 | module_init(wm8904_modinit); |
2666 | 2578 | ||
diff --git a/sound/soc/codecs/wm8904.h b/sound/soc/codecs/wm8904.h index abe5059b3004..9e8c84188ba7 100644 --- a/sound/soc/codecs/wm8904.h +++ b/sound/soc/codecs/wm8904.h | |||
@@ -21,9 +21,6 @@ | |||
21 | #define WM8904_FLL_LRCLK 3 | 21 | #define WM8904_FLL_LRCLK 3 |
22 | #define WM8904_FLL_FREE_RUNNING 4 | 22 | #define WM8904_FLL_FREE_RUNNING 4 |
23 | 23 | ||
24 | extern struct snd_soc_dai wm8904_dai; | ||
25 | extern struct snd_soc_codec_device soc_codec_dev_wm8904; | ||
26 | |||
27 | /* | 24 | /* |
28 | * Register values. | 25 | * Register values. |
29 | */ | 26 | */ |
diff --git a/sound/soc/codecs/wm8940.c b/sound/soc/codecs/wm8940.c index f0c11138e610..d28bf0dfdb1d 100644 --- a/sound/soc/codecs/wm8940.c +++ b/sound/soc/codecs/wm8940.c | |||
@@ -44,7 +44,8 @@ | |||
44 | struct wm8940_priv { | 44 | struct wm8940_priv { |
45 | unsigned int sysclk; | 45 | unsigned int sysclk; |
46 | u16 reg_cache[WM8940_CACHEREGNUM]; | 46 | u16 reg_cache[WM8940_CACHEREGNUM]; |
47 | struct snd_soc_codec codec; | 47 | enum snd_soc_control_type control_type; |
48 | void *control_data; | ||
48 | }; | 49 | }; |
49 | 50 | ||
50 | static u16 wm8940_reg_defaults[] = { | 51 | static u16 wm8940_reg_defaults[] = { |
@@ -365,8 +366,7 @@ static int wm8940_i2s_hw_params(struct snd_pcm_substream *substream, | |||
365 | struct snd_soc_dai *dai) | 366 | struct snd_soc_dai *dai) |
366 | { | 367 | { |
367 | struct snd_soc_pcm_runtime *rtd = substream->private_data; | 368 | struct snd_soc_pcm_runtime *rtd = substream->private_data; |
368 | struct snd_soc_device *socdev = rtd->socdev; | 369 | struct snd_soc_codec *codec = rtd->codec; |
369 | struct snd_soc_codec *codec = socdev->card->codec; | ||
370 | u16 iface = snd_soc_read(codec, WM8940_IFACE) & 0xFD9F; | 370 | u16 iface = snd_soc_read(codec, WM8940_IFACE) & 0xFD9F; |
371 | u16 addcntrl = snd_soc_read(codec, WM8940_ADDCNTRL) & 0xFFF1; | 371 | u16 addcntrl = snd_soc_read(codec, WM8940_ADDCNTRL) & 0xFFF1; |
372 | u16 companding = snd_soc_read(codec, | 372 | u16 companding = snd_soc_read(codec, |
@@ -636,8 +636,8 @@ static struct snd_soc_dai_ops wm8940_dai_ops = { | |||
636 | .set_pll = wm8940_set_dai_pll, | 636 | .set_pll = wm8940_set_dai_pll, |
637 | }; | 637 | }; |
638 | 638 | ||
639 | struct snd_soc_dai wm8940_dai = { | 639 | static struct snd_soc_dai_driver wm8940_dai = { |
640 | .name = "WM8940", | 640 | .name = "wm8940-hifi", |
641 | .playback = { | 641 | .playback = { |
642 | .stream_name = "Playback", | 642 | .stream_name = "Playback", |
643 | .channels_min = 1, | 643 | .channels_min = 1, |
@@ -655,20 +655,14 @@ struct snd_soc_dai wm8940_dai = { | |||
655 | .ops = &wm8940_dai_ops, | 655 | .ops = &wm8940_dai_ops, |
656 | .symmetric_rates = 1, | 656 | .symmetric_rates = 1, |
657 | }; | 657 | }; |
658 | EXPORT_SYMBOL_GPL(wm8940_dai); | ||
659 | 658 | ||
660 | static int wm8940_suspend(struct platform_device *pdev, pm_message_t state) | 659 | static int wm8940_suspend(struct snd_soc_codec *codec, pm_message_t state) |
661 | { | 660 | { |
662 | struct snd_soc_device *socdev = platform_get_drvdata(pdev); | ||
663 | struct snd_soc_codec *codec = socdev->card->codec; | ||
664 | |||
665 | return wm8940_set_bias_level(codec, SND_SOC_BIAS_OFF); | 661 | return wm8940_set_bias_level(codec, SND_SOC_BIAS_OFF); |
666 | } | 662 | } |
667 | 663 | ||
668 | static int wm8940_resume(struct platform_device *pdev) | 664 | static int wm8940_resume(struct snd_soc_codec *codec) |
669 | { | 665 | { |
670 | struct snd_soc_device *socdev = platform_get_drvdata(pdev); | ||
671 | struct snd_soc_codec *codec = socdev->card->codec; | ||
672 | int i; | 666 | int i; |
673 | int ret; | 667 | int ret; |
674 | u8 data[3]; | 668 | u8 data[3]; |
@@ -697,108 +691,26 @@ error_ret: | |||
697 | return ret; | 691 | return ret; |
698 | } | 692 | } |
699 | 693 | ||
700 | static struct snd_soc_codec *wm8940_codec; | 694 | static int wm8940_probe(struct snd_soc_codec *codec) |
701 | |||
702 | static int wm8940_probe(struct platform_device *pdev) | ||
703 | { | ||
704 | struct snd_soc_device *socdev = platform_get_drvdata(pdev); | ||
705 | struct snd_soc_codec *codec; | ||
706 | |||
707 | int ret = 0; | ||
708 | |||
709 | if (wm8940_codec == NULL) { | ||
710 | dev_err(&pdev->dev, "Codec device not registered\n"); | ||
711 | return -ENODEV; | ||
712 | } | ||
713 | |||
714 | socdev->card->codec = wm8940_codec; | ||
715 | codec = wm8940_codec; | ||
716 | |||
717 | mutex_init(&codec->mutex); | ||
718 | /* register pcms */ | ||
719 | ret = snd_soc_new_pcms(socdev, SNDRV_DEFAULT_IDX1, SNDRV_DEFAULT_STR1); | ||
720 | if (ret < 0) { | ||
721 | dev_err(codec->dev, "failed to create pcms: %d\n", ret); | ||
722 | goto pcm_err; | ||
723 | } | ||
724 | |||
725 | ret = snd_soc_add_controls(codec, wm8940_snd_controls, | ||
726 | ARRAY_SIZE(wm8940_snd_controls)); | ||
727 | if (ret) | ||
728 | goto error_free_pcms; | ||
729 | ret = wm8940_add_widgets(codec); | ||
730 | if (ret) | ||
731 | goto error_free_pcms; | ||
732 | |||
733 | return ret; | ||
734 | |||
735 | error_free_pcms: | ||
736 | snd_soc_free_pcms(socdev); | ||
737 | snd_soc_dapm_free(socdev); | ||
738 | pcm_err: | ||
739 | return ret; | ||
740 | } | ||
741 | |||
742 | static int wm8940_remove(struct platform_device *pdev) | ||
743 | { | ||
744 | struct snd_soc_device *socdev = platform_get_drvdata(pdev); | ||
745 | |||
746 | snd_soc_free_pcms(socdev); | ||
747 | snd_soc_dapm_free(socdev); | ||
748 | |||
749 | return 0; | ||
750 | } | ||
751 | |||
752 | struct snd_soc_codec_device soc_codec_dev_wm8940 = { | ||
753 | .probe = wm8940_probe, | ||
754 | .remove = wm8940_remove, | ||
755 | .suspend = wm8940_suspend, | ||
756 | .resume = wm8940_resume, | ||
757 | }; | ||
758 | EXPORT_SYMBOL_GPL(soc_codec_dev_wm8940); | ||
759 | |||
760 | static int wm8940_register(struct wm8940_priv *wm8940, | ||
761 | enum snd_soc_control_type control) | ||
762 | { | 695 | { |
763 | struct wm8940_setup_data *pdata = wm8940->codec.dev->platform_data; | 696 | struct wm8940_priv *wm8940 = snd_soc_codec_get_drvdata(codec); |
764 | struct snd_soc_codec *codec = &wm8940->codec; | 697 | struct wm8940_setup_data *pdata = codec->dev->platform_data; |
765 | int ret; | 698 | int ret; |
766 | u16 reg; | 699 | u16 reg; |
767 | if (wm8940_codec) { | ||
768 | dev_err(codec->dev, "Another WM8940 is registered\n"); | ||
769 | return -EINVAL; | ||
770 | } | ||
771 | |||
772 | INIT_LIST_HEAD(&codec->dapm_widgets); | ||
773 | INIT_LIST_HEAD(&codec->dapm_paths); | ||
774 | |||
775 | snd_soc_codec_set_drvdata(codec, wm8940); | ||
776 | codec->name = "WM8940"; | ||
777 | codec->owner = THIS_MODULE; | ||
778 | codec->bias_level = SND_SOC_BIAS_OFF; | ||
779 | codec->set_bias_level = wm8940_set_bias_level; | ||
780 | codec->dai = &wm8940_dai; | ||
781 | codec->num_dai = 1; | ||
782 | codec->reg_cache_size = ARRAY_SIZE(wm8940_reg_defaults); | ||
783 | codec->reg_cache = &wm8940->reg_cache; | ||
784 | 700 | ||
785 | ret = snd_soc_codec_set_cache_io(codec, 8, 16, control); | 701 | codec->control_data = wm8940->control_data; |
702 | ret = snd_soc_codec_set_cache_io(codec, 8, 16, wm8940->control_type); | ||
786 | if (ret < 0) { | 703 | if (ret < 0) { |
787 | dev_err(codec->dev, "Failed to set cache I/O: %d\n", ret); | 704 | dev_err(codec->dev, "Failed to set cache I/O: %d\n", ret); |
788 | return ret; | 705 | return ret; |
789 | } | 706 | } |
790 | 707 | ||
791 | memcpy(codec->reg_cache, wm8940_reg_defaults, | ||
792 | sizeof(wm8940_reg_defaults)); | ||
793 | |||
794 | ret = wm8940_reset(codec); | 708 | ret = wm8940_reset(codec); |
795 | if (ret < 0) { | 709 | if (ret < 0) { |
796 | dev_err(codec->dev, "Failed to issue reset\n"); | 710 | dev_err(codec->dev, "Failed to issue reset\n"); |
797 | return ret; | 711 | return ret; |
798 | } | 712 | } |
799 | 713 | ||
800 | wm8940_dai.dev = codec->dev; | ||
801 | |||
802 | wm8940_set_bias_level(codec, SND_SOC_BIAS_STANDBY); | 714 | wm8940_set_bias_level(codec, SND_SOC_BIAS_STANDBY); |
803 | 715 | ||
804 | ret = snd_soc_write(codec, WM8940_POWER1, 0x180); | 716 | ret = snd_soc_write(codec, WM8940_POWER1, 0x180); |
@@ -814,64 +726,60 @@ static int wm8940_register(struct wm8940_priv *wm8940, | |||
814 | return ret; | 726 | return ret; |
815 | } | 727 | } |
816 | 728 | ||
817 | 729 | ret = snd_soc_add_controls(codec, wm8940_snd_controls, | |
818 | wm8940_codec = codec; | 730 | ARRAY_SIZE(wm8940_snd_controls)); |
819 | 731 | if (ret) | |
820 | ret = snd_soc_register_codec(codec); | ||
821 | if (ret) { | ||
822 | dev_err(codec->dev, "Failed to register codec: %d\n", ret); | ||
823 | return ret; | 732 | return ret; |
824 | } | 733 | ret = wm8940_add_widgets(codec); |
825 | 734 | if (ret) | |
826 | ret = snd_soc_register_dai(&wm8940_dai); | ||
827 | if (ret) { | ||
828 | dev_err(codec->dev, "Failed to register DAI: %d\n", ret); | ||
829 | snd_soc_unregister_codec(codec); | ||
830 | return ret; | 735 | return ret; |
831 | } | ||
832 | 736 | ||
833 | return 0; | 737 | return ret; |
738 | ; | ||
834 | } | 739 | } |
835 | 740 | ||
836 | static void wm8940_unregister(struct wm8940_priv *wm8940) | 741 | static int wm8940_remove(struct snd_soc_codec *codec) |
837 | { | 742 | { |
838 | wm8940_set_bias_level(&wm8940->codec, SND_SOC_BIAS_OFF); | 743 | wm8940_set_bias_level(codec, SND_SOC_BIAS_OFF); |
839 | snd_soc_unregister_dai(&wm8940_dai); | 744 | return 0; |
840 | snd_soc_unregister_codec(&wm8940->codec); | ||
841 | kfree(wm8940); | ||
842 | wm8940_codec = NULL; | ||
843 | } | 745 | } |
844 | 746 | ||
845 | static int wm8940_i2c_probe(struct i2c_client *i2c, | 747 | static struct snd_soc_codec_driver soc_codec_dev_wm8940 = { |
846 | const struct i2c_device_id *id) | 748 | .probe = wm8940_probe, |
749 | .remove = wm8940_remove, | ||
750 | .suspend = wm8940_suspend, | ||
751 | .resume = wm8940_resume, | ||
752 | .set_bias_level = wm8940_set_bias_level, | ||
753 | .reg_cache_size = sizeof(wm8940_reg_defaults), | ||
754 | .reg_word_size = sizeof(u16), | ||
755 | .reg_cache_default = wm8940_reg_defaults, | ||
756 | }; | ||
757 | |||
758 | #if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE) | ||
759 | static __devinit int wm8940_i2c_probe(struct i2c_client *i2c, | ||
760 | const struct i2c_device_id *id) | ||
847 | { | 761 | { |
848 | int ret; | ||
849 | struct wm8940_priv *wm8940; | 762 | struct wm8940_priv *wm8940; |
850 | struct snd_soc_codec *codec; | 763 | int ret; |
851 | 764 | ||
852 | wm8940 = kzalloc(sizeof *wm8940, GFP_KERNEL); | 765 | wm8940 = kzalloc(sizeof(struct wm8940_priv), GFP_KERNEL); |
853 | if (wm8940 == NULL) | 766 | if (wm8940 == NULL) |
854 | return -ENOMEM; | 767 | return -ENOMEM; |
855 | 768 | ||
856 | codec = &wm8940->codec; | ||
857 | codec->hw_write = (hw_write_t)i2c_master_send; | ||
858 | i2c_set_clientdata(i2c, wm8940); | 769 | i2c_set_clientdata(i2c, wm8940); |
859 | codec->control_data = i2c; | 770 | wm8940->control_data = i2c; |
860 | codec->dev = &i2c->dev; | ||
861 | 771 | ||
862 | ret = wm8940_register(wm8940, SND_SOC_I2C); | 772 | ret = snd_soc_register_codec(&i2c->dev, |
773 | &soc_codec_dev_wm8940, &wm8940_dai, 1); | ||
863 | if (ret < 0) | 774 | if (ret < 0) |
864 | kfree(wm8940); | 775 | kfree(wm8940); |
865 | |||
866 | return ret; | 776 | return ret; |
867 | } | 777 | } |
868 | 778 | ||
869 | static int __devexit wm8940_i2c_remove(struct i2c_client *client) | 779 | static __devexit int wm8940_i2c_remove(struct i2c_client *client) |
870 | { | 780 | { |
871 | struct wm8940_priv *wm8940 = i2c_get_clientdata(client); | 781 | snd_soc_unregister_codec(&client->dev); |
872 | 782 | kfree(i2c_get_clientdata(client)); | |
873 | wm8940_unregister(wm8940); | ||
874 | |||
875 | return 0; | 783 | return 0; |
876 | } | 784 | } |
877 | 785 | ||
@@ -883,29 +791,34 @@ MODULE_DEVICE_TABLE(i2c, wm8940_i2c_id); | |||
883 | 791 | ||
884 | static struct i2c_driver wm8940_i2c_driver = { | 792 | static struct i2c_driver wm8940_i2c_driver = { |
885 | .driver = { | 793 | .driver = { |
886 | .name = "WM8940 I2C Codec", | 794 | .name = "wm8940-codec", |
887 | .owner = THIS_MODULE, | 795 | .owner = THIS_MODULE, |
888 | }, | 796 | }, |
889 | .probe = wm8940_i2c_probe, | 797 | .probe = wm8940_i2c_probe, |
890 | .remove = __devexit_p(wm8940_i2c_remove), | 798 | .remove = __devexit_p(wm8940_i2c_remove), |
891 | .id_table = wm8940_i2c_id, | 799 | .id_table = wm8940_i2c_id, |
892 | }; | 800 | }; |
801 | #endif | ||
893 | 802 | ||
894 | static int __init wm8940_modinit(void) | 803 | static int __init wm8940_modinit(void) |
895 | { | 804 | { |
896 | int ret; | 805 | int ret = 0; |
897 | 806 | #if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE) | |
898 | ret = i2c_add_driver(&wm8940_i2c_driver); | 807 | ret = i2c_add_driver(&wm8940_i2c_driver); |
899 | if (ret) | 808 | if (ret != 0) { |
900 | printk(KERN_ERR "Failed to register WM8940 I2C driver: %d\n", | 809 | printk(KERN_ERR "Failed to register wm8940 I2C driver: %d\n", |
901 | ret); | 810 | ret); |
811 | } | ||
812 | #endif | ||
902 | return ret; | 813 | return ret; |
903 | } | 814 | } |
904 | module_init(wm8940_modinit); | 815 | module_init(wm8940_modinit); |
905 | 816 | ||
906 | static void __exit wm8940_exit(void) | 817 | static void __exit wm8940_exit(void) |
907 | { | 818 | { |
819 | #if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE) | ||
908 | i2c_del_driver(&wm8940_i2c_driver); | 820 | i2c_del_driver(&wm8940_i2c_driver); |
821 | #endif | ||
909 | } | 822 | } |
910 | module_exit(wm8940_exit); | 823 | module_exit(wm8940_exit); |
911 | 824 | ||
diff --git a/sound/soc/codecs/wm8940.h b/sound/soc/codecs/wm8940.h index 8410eed3ef84..907fe192e9e0 100644 --- a/sound/soc/codecs/wm8940.h +++ b/sound/soc/codecs/wm8940.h | |||
@@ -15,8 +15,6 @@ struct wm8940_setup_data { | |||
15 | #define WM8940_VROI_30K 1 | 15 | #define WM8940_VROI_30K 1 |
16 | unsigned int vroi:1; | 16 | unsigned int vroi:1; |
17 | }; | 17 | }; |
18 | extern struct snd_soc_dai wm8940_dai; | ||
19 | extern struct snd_soc_codec_device soc_codec_dev_wm8940; | ||
20 | 18 | ||
21 | /* WM8940 register space */ | 19 | /* WM8940 register space */ |
22 | #define WM8940_SOFTRESET 0x00 | 20 | #define WM8940_SOFTRESET 0x00 |
diff --git a/sound/soc/codecs/wm8955.c b/sound/soc/codecs/wm8955.c index 5f025593d84d..f89ad6c9a80b 100644 --- a/sound/soc/codecs/wm8955.c +++ b/sound/soc/codecs/wm8955.c | |||
@@ -30,9 +30,6 @@ | |||
30 | 30 | ||
31 | #include "wm8955.h" | 31 | #include "wm8955.h" |
32 | 32 | ||
33 | static struct snd_soc_codec *wm8955_codec; | ||
34 | struct snd_soc_codec_device soc_codec_dev_wm8955; | ||
35 | |||
36 | #define WM8955_NUM_SUPPLIES 4 | 33 | #define WM8955_NUM_SUPPLIES 4 |
37 | static const char *wm8955_supply_names[WM8955_NUM_SUPPLIES] = { | 34 | static const char *wm8955_supply_names[WM8955_NUM_SUPPLIES] = { |
38 | "DCVDD", | 35 | "DCVDD", |
@@ -43,7 +40,8 @@ static const char *wm8955_supply_names[WM8955_NUM_SUPPLIES] = { | |||
43 | 40 | ||
44 | /* codec private data */ | 41 | /* codec private data */ |
45 | struct wm8955_priv { | 42 | struct wm8955_priv { |
46 | struct snd_soc_codec codec; | 43 | enum snd_soc_control_type control_type; |
44 | |||
47 | u16 reg_cache[WM8955_MAX_REGISTER + 1]; | 45 | u16 reg_cache[WM8955_MAX_REGISTER + 1]; |
48 | 46 | ||
49 | unsigned int mclk_rate; | 47 | unsigned int mclk_rate; |
@@ -52,8 +50,6 @@ struct wm8955_priv { | |||
52 | int fs; | 50 | int fs; |
53 | 51 | ||
54 | struct regulator_bulk_data supplies[WM8955_NUM_SUPPLIES]; | 52 | struct regulator_bulk_data supplies[WM8955_NUM_SUPPLIES]; |
55 | |||
56 | struct wm8955_pdata *pdata; | ||
57 | }; | 53 | }; |
58 | 54 | ||
59 | static const u16 wm8955_reg[WM8955_MAX_REGISTER + 1] = { | 55 | static const u16 wm8955_reg[WM8955_MAX_REGISTER + 1] = { |
@@ -870,8 +866,8 @@ static struct snd_soc_dai_ops wm8955_dai_ops = { | |||
870 | .digital_mute = wm8955_digital_mute, | 866 | .digital_mute = wm8955_digital_mute, |
871 | }; | 867 | }; |
872 | 868 | ||
873 | struct snd_soc_dai wm8955_dai = { | 869 | static struct snd_soc_dai_driver wm8955_dai = { |
874 | .name = "WM8955", | 870 | .name = "wm8955-hifi", |
875 | .playback = { | 871 | .playback = { |
876 | .stream_name = "Playback", | 872 | .stream_name = "Playback", |
877 | .channels_min = 2, | 873 | .channels_min = 2, |
@@ -881,24 +877,17 @@ struct snd_soc_dai wm8955_dai = { | |||
881 | }, | 877 | }, |
882 | .ops = &wm8955_dai_ops, | 878 | .ops = &wm8955_dai_ops, |
883 | }; | 879 | }; |
884 | EXPORT_SYMBOL_GPL(wm8955_dai); | ||
885 | 880 | ||
886 | #ifdef CONFIG_PM | 881 | #ifdef CONFIG_PM |
887 | static int wm8955_suspend(struct platform_device *pdev, pm_message_t state) | 882 | static int wm8955_suspend(struct snd_soc_codec *codec, pm_message_t state) |
888 | { | 883 | { |
889 | struct snd_soc_device *socdev = platform_get_drvdata(pdev); | ||
890 | struct snd_soc_codec *codec = socdev->card->codec; | ||
891 | |||
892 | wm8955_set_bias_level(codec, SND_SOC_BIAS_OFF); | 884 | wm8955_set_bias_level(codec, SND_SOC_BIAS_OFF); |
893 | 885 | ||
894 | return 0; | 886 | return 0; |
895 | } | 887 | } |
896 | 888 | ||
897 | static int wm8955_resume(struct platform_device *pdev) | 889 | static int wm8955_resume(struct snd_soc_codec *codec) |
898 | { | 890 | { |
899 | struct snd_soc_device *socdev = platform_get_drvdata(pdev); | ||
900 | struct snd_soc_codec *codec = socdev->card->codec; | ||
901 | |||
902 | wm8955_set_bias_level(codec, SND_SOC_BIAS_STANDBY); | 891 | wm8955_set_bias_level(codec, SND_SOC_BIAS_STANDBY); |
903 | 892 | ||
904 | return 0; | 893 | return 0; |
@@ -908,86 +897,16 @@ static int wm8955_resume(struct platform_device *pdev) | |||
908 | #define wm8955_resume NULL | 897 | #define wm8955_resume NULL |
909 | #endif | 898 | #endif |
910 | 899 | ||
911 | static int wm8955_probe(struct platform_device *pdev) | 900 | static int wm8955_probe(struct snd_soc_codec *codec) |
912 | { | ||
913 | struct snd_soc_device *socdev = platform_get_drvdata(pdev); | ||
914 | struct snd_soc_codec *codec; | ||
915 | int ret = 0; | ||
916 | |||
917 | if (wm8955_codec == NULL) { | ||
918 | dev_err(&pdev->dev, "Codec device not registered\n"); | ||
919 | return -ENODEV; | ||
920 | } | ||
921 | |||
922 | socdev->card->codec = wm8955_codec; | ||
923 | codec = wm8955_codec; | ||
924 | |||
925 | /* register pcms */ | ||
926 | ret = snd_soc_new_pcms(socdev, SNDRV_DEFAULT_IDX1, SNDRV_DEFAULT_STR1); | ||
927 | if (ret < 0) { | ||
928 | dev_err(codec->dev, "failed to create pcms: %d\n", ret); | ||
929 | goto pcm_err; | ||
930 | } | ||
931 | |||
932 | wm8955_add_widgets(codec); | ||
933 | |||
934 | return ret; | ||
935 | |||
936 | pcm_err: | ||
937 | return ret; | ||
938 | } | ||
939 | |||
940 | static int wm8955_remove(struct platform_device *pdev) | ||
941 | { | 901 | { |
942 | struct snd_soc_device *socdev = platform_get_drvdata(pdev); | 902 | struct wm8955_priv *wm8955 = snd_soc_codec_get_drvdata(codec); |
943 | 903 | struct wm8955_pdata *pdata = dev_get_platdata(codec->dev); | |
944 | snd_soc_free_pcms(socdev); | 904 | int ret, i; |
945 | snd_soc_dapm_free(socdev); | ||
946 | |||
947 | return 0; | ||
948 | } | ||
949 | |||
950 | struct snd_soc_codec_device soc_codec_dev_wm8955 = { | ||
951 | .probe = wm8955_probe, | ||
952 | .remove = wm8955_remove, | ||
953 | .suspend = wm8955_suspend, | ||
954 | .resume = wm8955_resume, | ||
955 | }; | ||
956 | EXPORT_SYMBOL_GPL(soc_codec_dev_wm8955); | ||
957 | |||
958 | static int wm8955_register(struct wm8955_priv *wm8955, | ||
959 | enum snd_soc_control_type control) | ||
960 | { | ||
961 | int ret; | ||
962 | struct snd_soc_codec *codec = &wm8955->codec; | ||
963 | int i; | ||
964 | |||
965 | if (wm8955_codec) { | ||
966 | dev_err(codec->dev, "Another WM8955 is registered\n"); | ||
967 | ret = -EINVAL; | ||
968 | goto err; | ||
969 | } | ||
970 | |||
971 | mutex_init(&codec->mutex); | ||
972 | INIT_LIST_HEAD(&codec->dapm_widgets); | ||
973 | INIT_LIST_HEAD(&codec->dapm_paths); | ||
974 | |||
975 | snd_soc_codec_set_drvdata(codec, wm8955); | ||
976 | codec->name = "WM8955"; | ||
977 | codec->owner = THIS_MODULE; | ||
978 | codec->bias_level = SND_SOC_BIAS_OFF; | ||
979 | codec->set_bias_level = wm8955_set_bias_level; | ||
980 | codec->dai = &wm8955_dai; | ||
981 | codec->num_dai = 1; | ||
982 | codec->reg_cache_size = WM8955_MAX_REGISTER; | ||
983 | codec->reg_cache = &wm8955->reg_cache; | ||
984 | |||
985 | memcpy(codec->reg_cache, wm8955_reg, sizeof(wm8955_reg)); | ||
986 | 905 | ||
987 | ret = snd_soc_codec_set_cache_io(codec, 7, 9, control); | 906 | ret = snd_soc_codec_set_cache_io(codec, 7, 9, wm8955->control_type); |
988 | if (ret != 0) { | 907 | if (ret != 0) { |
989 | dev_err(codec->dev, "Failed to set cache I/O: %d\n", ret); | 908 | dev_err(codec->dev, "Failed to set cache I/O: %d\n", ret); |
990 | goto err; | 909 | return ret; |
991 | } | 910 | } |
992 | 911 | ||
993 | for (i = 0; i < ARRAY_SIZE(wm8955->supplies); i++) | 912 | for (i = 0; i < ARRAY_SIZE(wm8955->supplies); i++) |
@@ -997,7 +916,7 @@ static int wm8955_register(struct wm8955_priv *wm8955, | |||
997 | wm8955->supplies); | 916 | wm8955->supplies); |
998 | if (ret != 0) { | 917 | if (ret != 0) { |
999 | dev_err(codec->dev, "Failed to request supplies: %d\n", ret); | 918 | dev_err(codec->dev, "Failed to request supplies: %d\n", ret); |
1000 | goto err; | 919 | return ret; |
1001 | } | 920 | } |
1002 | 921 | ||
1003 | ret = regulator_bulk_enable(ARRAY_SIZE(wm8955->supplies), | 922 | ret = regulator_bulk_enable(ARRAY_SIZE(wm8955->supplies), |
@@ -1013,8 +932,6 @@ static int wm8955_register(struct wm8955_priv *wm8955, | |||
1013 | goto err_enable; | 932 | goto err_enable; |
1014 | } | 933 | } |
1015 | 934 | ||
1016 | wm8955_dai.dev = codec->dev; | ||
1017 | |||
1018 | /* Change some default settings - latch VU and enable ZC */ | 935 | /* Change some default settings - latch VU and enable ZC */ |
1019 | wm8955->reg_cache[WM8955_LEFT_DAC_VOLUME] |= WM8955_LDVU; | 936 | wm8955->reg_cache[WM8955_LEFT_DAC_VOLUME] |= WM8955_LDVU; |
1020 | wm8955->reg_cache[WM8955_RIGHT_DAC_VOLUME] |= WM8955_RDVU; | 937 | wm8955->reg_cache[WM8955_RIGHT_DAC_VOLUME] |= WM8955_RDVU; |
@@ -1028,12 +945,12 @@ static int wm8955_register(struct wm8955_priv *wm8955, | |||
1028 | wm8955->reg_cache[WM8955_BASS_CONTROL] |= WM8955_BB; | 945 | wm8955->reg_cache[WM8955_BASS_CONTROL] |= WM8955_BB; |
1029 | 946 | ||
1030 | /* Set platform data values */ | 947 | /* Set platform data values */ |
1031 | if (wm8955->pdata) { | 948 | if (pdata) { |
1032 | if (wm8955->pdata->out2_speaker) | 949 | if (pdata->out2_speaker) |
1033 | wm8955->reg_cache[WM8955_ADDITIONAL_CONTROL_2] | 950 | wm8955->reg_cache[WM8955_ADDITIONAL_CONTROL_2] |
1034 | |= WM8955_ROUT2INV; | 951 | |= WM8955_ROUT2INV; |
1035 | 952 | ||
1036 | if (wm8955->pdata->monoin_diff) | 953 | if (pdata->monoin_diff) |
1037 | wm8955->reg_cache[WM8955_MONO_OUT_MIX_1] | 954 | wm8955->reg_cache[WM8955_MONO_OUT_MIX_1] |
1038 | |= WM8955_DMEN; | 955 | |= WM8955_DMEN; |
1039 | } | 956 | } |
@@ -1043,70 +960,60 @@ static int wm8955_register(struct wm8955_priv *wm8955, | |||
1043 | /* Bias level configuration will have done an extra enable */ | 960 | /* Bias level configuration will have done an extra enable */ |
1044 | regulator_bulk_disable(ARRAY_SIZE(wm8955->supplies), wm8955->supplies); | 961 | regulator_bulk_disable(ARRAY_SIZE(wm8955->supplies), wm8955->supplies); |
1045 | 962 | ||
1046 | wm8955_codec = codec; | 963 | wm8955_add_widgets(codec); |
1047 | |||
1048 | ret = snd_soc_register_codec(codec); | ||
1049 | if (ret != 0) { | ||
1050 | dev_err(codec->dev, "Failed to register codec: %d\n", ret); | ||
1051 | goto err_enable; | ||
1052 | } | ||
1053 | |||
1054 | ret = snd_soc_register_dai(&wm8955_dai); | ||
1055 | if (ret != 0) { | ||
1056 | dev_err(codec->dev, "Failed to register DAI: %d\n", ret); | ||
1057 | goto err_codec; | ||
1058 | } | ||
1059 | |||
1060 | return 0; | 964 | return 0; |
1061 | 965 | ||
1062 | err_codec: | ||
1063 | snd_soc_unregister_codec(codec); | ||
1064 | err_enable: | 966 | err_enable: |
1065 | regulator_bulk_disable(ARRAY_SIZE(wm8955->supplies), wm8955->supplies); | 967 | regulator_bulk_disable(ARRAY_SIZE(wm8955->supplies), wm8955->supplies); |
1066 | err_get: | 968 | err_get: |
1067 | regulator_bulk_free(ARRAY_SIZE(wm8955->supplies), wm8955->supplies); | 969 | regulator_bulk_free(ARRAY_SIZE(wm8955->supplies), wm8955->supplies); |
1068 | err: | ||
1069 | kfree(wm8955); | ||
1070 | return ret; | 970 | return ret; |
1071 | } | 971 | } |
1072 | 972 | ||
1073 | static void wm8955_unregister(struct wm8955_priv *wm8955) | 973 | static int wm8955_remove(struct snd_soc_codec *codec) |
1074 | { | 974 | { |
1075 | wm8955_set_bias_level(&wm8955->codec, SND_SOC_BIAS_OFF); | 975 | struct wm8955_priv *wm8955 = snd_soc_codec_get_drvdata(codec); |
976 | |||
977 | wm8955_set_bias_level(codec, SND_SOC_BIAS_OFF); | ||
1076 | regulator_bulk_free(ARRAY_SIZE(wm8955->supplies), wm8955->supplies); | 978 | regulator_bulk_free(ARRAY_SIZE(wm8955->supplies), wm8955->supplies); |
1077 | snd_soc_unregister_dai(&wm8955_dai); | 979 | return 0; |
1078 | snd_soc_unregister_codec(&wm8955->codec); | ||
1079 | kfree(wm8955); | ||
1080 | wm8955_codec = NULL; | ||
1081 | } | 980 | } |
1082 | 981 | ||
982 | static struct snd_soc_codec_driver soc_codec_dev_wm8955 = { | ||
983 | .probe = wm8955_probe, | ||
984 | .remove = wm8955_remove, | ||
985 | .suspend = wm8955_suspend, | ||
986 | .resume = wm8955_resume, | ||
987 | .set_bias_level = wm8955_set_bias_level, | ||
988 | .reg_cache_size = ARRAY_SIZE(wm8955_reg), | ||
989 | .reg_word_size = sizeof(u16), | ||
990 | .reg_cache_default = wm8955_reg, | ||
991 | }; | ||
992 | |||
1083 | #if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE) | 993 | #if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE) |
1084 | static __devinit int wm8955_i2c_probe(struct i2c_client *i2c, | 994 | static __devinit int wm8955_i2c_probe(struct i2c_client *i2c, |
1085 | const struct i2c_device_id *id) | 995 | const struct i2c_device_id *id) |
1086 | { | 996 | { |
1087 | struct wm8955_priv *wm8955; | 997 | struct wm8955_priv *wm8955; |
1088 | struct snd_soc_codec *codec; | 998 | int ret; |
1089 | 999 | ||
1090 | wm8955 = kzalloc(sizeof(struct wm8955_priv), GFP_KERNEL); | 1000 | wm8955 = kzalloc(sizeof(struct wm8955_priv), GFP_KERNEL); |
1091 | if (wm8955 == NULL) | 1001 | if (wm8955 == NULL) |
1092 | return -ENOMEM; | 1002 | return -ENOMEM; |
1093 | 1003 | ||
1094 | codec = &wm8955->codec; | ||
1095 | codec->hw_write = (hw_write_t)i2c_master_send; | ||
1096 | |||
1097 | i2c_set_clientdata(i2c, wm8955); | 1004 | i2c_set_clientdata(i2c, wm8955); |
1098 | codec->control_data = i2c; | ||
1099 | wm8955->pdata = i2c->dev.platform_data; | ||
1100 | |||
1101 | codec->dev = &i2c->dev; | ||
1102 | 1005 | ||
1103 | return wm8955_register(wm8955, SND_SOC_I2C); | 1006 | ret = snd_soc_register_codec(&i2c->dev, |
1007 | &soc_codec_dev_wm8955, &wm8955_dai, 1); | ||
1008 | if (ret < 0) | ||
1009 | kfree(wm8955); | ||
1010 | return ret; | ||
1104 | } | 1011 | } |
1105 | 1012 | ||
1106 | static __devexit int wm8955_i2c_remove(struct i2c_client *client) | 1013 | static __devexit int wm8955_i2c_remove(struct i2c_client *client) |
1107 | { | 1014 | { |
1108 | struct wm8955_priv *wm8955 = i2c_get_clientdata(client); | 1015 | snd_soc_unregister_codec(&client->dev); |
1109 | wm8955_unregister(wm8955); | 1016 | kfree(i2c_get_clientdata(client)); |
1110 | return 0; | 1017 | return 0; |
1111 | } | 1018 | } |
1112 | 1019 | ||
@@ -1118,7 +1025,7 @@ MODULE_DEVICE_TABLE(i2c, wm8955_i2c_id); | |||
1118 | 1025 | ||
1119 | static struct i2c_driver wm8955_i2c_driver = { | 1026 | static struct i2c_driver wm8955_i2c_driver = { |
1120 | .driver = { | 1027 | .driver = { |
1121 | .name = "wm8955", | 1028 | .name = "wm8955-codec", |
1122 | .owner = THIS_MODULE, | 1029 | .owner = THIS_MODULE, |
1123 | }, | 1030 | }, |
1124 | .probe = wm8955_i2c_probe, | 1031 | .probe = wm8955_i2c_probe, |
@@ -1129,7 +1036,7 @@ static struct i2c_driver wm8955_i2c_driver = { | |||
1129 | 1036 | ||
1130 | static int __init wm8955_modinit(void) | 1037 | static int __init wm8955_modinit(void) |
1131 | { | 1038 | { |
1132 | int ret; | 1039 | int ret = 0; |
1133 | #if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE) | 1040 | #if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE) |
1134 | ret = i2c_add_driver(&wm8955_i2c_driver); | 1041 | ret = i2c_add_driver(&wm8955_i2c_driver); |
1135 | if (ret != 0) { | 1042 | if (ret != 0) { |
@@ -1137,7 +1044,7 @@ static int __init wm8955_modinit(void) | |||
1137 | ret); | 1044 | ret); |
1138 | } | 1045 | } |
1139 | #endif | 1046 | #endif |
1140 | return 0; | 1047 | return ret; |
1141 | } | 1048 | } |
1142 | module_init(wm8955_modinit); | 1049 | module_init(wm8955_modinit); |
1143 | 1050 | ||
diff --git a/sound/soc/codecs/wm8955.h b/sound/soc/codecs/wm8955.h index ae349c8531f6..d13fd5c5fa63 100644 --- a/sound/soc/codecs/wm8955.h +++ b/sound/soc/codecs/wm8955.h | |||
@@ -15,9 +15,6 @@ | |||
15 | 15 | ||
16 | #define WM8955_CLK_MCLK 1 | 16 | #define WM8955_CLK_MCLK 1 |
17 | 17 | ||
18 | extern struct snd_soc_dai wm8955_dai; | ||
19 | extern struct snd_soc_codec_device soc_codec_dev_wm8955; | ||
20 | |||
21 | /* | 18 | /* |
22 | * Register values. | 19 | * Register values. |
23 | */ | 20 | */ |
diff --git a/sound/soc/codecs/wm8960.c b/sound/soc/codecs/wm8960.c index 3c6ee61f6c95..8d5efb333c33 100644 --- a/sound/soc/codecs/wm8960.c +++ b/sound/soc/codecs/wm8960.c | |||
@@ -29,8 +29,6 @@ | |||
29 | 29 | ||
30 | #define AUDIO_NAME "wm8960" | 30 | #define AUDIO_NAME "wm8960" |
31 | 31 | ||
32 | struct snd_soc_codec_device soc_codec_dev_wm8960; | ||
33 | |||
34 | /* R25 - Power 1 */ | 32 | /* R25 - Power 1 */ |
35 | #define WM8960_VMID_MASK 0x180 | 33 | #define WM8960_VMID_MASK 0x180 |
36 | #define WM8960_VREF 0x40 | 34 | #define WM8960_VREF 0x40 |
@@ -75,7 +73,10 @@ static const u16 wm8960_reg[WM8960_CACHEREGNUM] = { | |||
75 | 73 | ||
76 | struct wm8960_priv { | 74 | struct wm8960_priv { |
77 | u16 reg_cache[WM8960_CACHEREGNUM]; | 75 | u16 reg_cache[WM8960_CACHEREGNUM]; |
78 | struct snd_soc_codec codec; | 76 | enum snd_soc_control_type control_type; |
77 | void *control_data; | ||
78 | int (*set_bias_level)(struct snd_soc_codec *, | ||
79 | enum snd_soc_bias_level level); | ||
79 | struct snd_soc_dapm_widget *lout1; | 80 | struct snd_soc_dapm_widget *lout1; |
80 | struct snd_soc_dapm_widget *rout1; | 81 | struct snd_soc_dapm_widget *rout1; |
81 | struct snd_soc_dapm_widget *out3; | 82 | struct snd_soc_dapm_widget *out3; |
@@ -507,8 +508,7 @@ static int wm8960_hw_params(struct snd_pcm_substream *substream, | |||
507 | struct snd_soc_dai *dai) | 508 | struct snd_soc_dai *dai) |
508 | { | 509 | { |
509 | struct snd_soc_pcm_runtime *rtd = substream->private_data; | 510 | struct snd_soc_pcm_runtime *rtd = substream->private_data; |
510 | struct snd_soc_device *socdev = rtd->socdev; | 511 | struct snd_soc_codec *codec = rtd->codec; |
511 | struct snd_soc_codec *codec = socdev->card->codec; | ||
512 | struct wm8960_priv *wm8960 = snd_soc_codec_get_drvdata(codec); | 512 | struct wm8960_priv *wm8960 = snd_soc_codec_get_drvdata(codec); |
513 | u16 iface = snd_soc_read(codec, WM8960_IFACE1) & 0xfff3; | 513 | u16 iface = snd_soc_read(codec, WM8960_IFACE1) & 0xfff3; |
514 | int i; | 514 | int i; |
@@ -849,6 +849,14 @@ static int wm8960_set_dai_clkdiv(struct snd_soc_dai *codec_dai, | |||
849 | return 0; | 849 | return 0; |
850 | } | 850 | } |
851 | 851 | ||
852 | static int wm8960_set_bias_level(struct snd_soc_codec *codec, | ||
853 | enum snd_soc_bias_level level) | ||
854 | { | ||
855 | struct wm8960_priv *wm8960 = snd_soc_codec_get_drvdata(codec); | ||
856 | |||
857 | return wm8960->set_bias_level(codec, level); | ||
858 | } | ||
859 | |||
852 | #define WM8960_RATES SNDRV_PCM_RATE_8000_48000 | 860 | #define WM8960_RATES SNDRV_PCM_RATE_8000_48000 |
853 | 861 | ||
854 | #define WM8960_FORMATS \ | 862 | #define WM8960_FORMATS \ |
@@ -863,8 +871,8 @@ static struct snd_soc_dai_ops wm8960_dai_ops = { | |||
863 | .set_pll = wm8960_set_dai_pll, | 871 | .set_pll = wm8960_set_dai_pll, |
864 | }; | 872 | }; |
865 | 873 | ||
866 | struct snd_soc_dai wm8960_dai = { | 874 | static struct snd_soc_dai_driver wm8960_dai = { |
867 | .name = "WM8960", | 875 | .name = "wm8960-hifi", |
868 | .playback = { | 876 | .playback = { |
869 | .stream_name = "Playback", | 877 | .stream_name = "Playback", |
870 | .channels_min = 1, | 878 | .channels_min = 1, |
@@ -880,21 +888,18 @@ struct snd_soc_dai wm8960_dai = { | |||
880 | .ops = &wm8960_dai_ops, | 888 | .ops = &wm8960_dai_ops, |
881 | .symmetric_rates = 1, | 889 | .symmetric_rates = 1, |
882 | }; | 890 | }; |
883 | EXPORT_SYMBOL_GPL(wm8960_dai); | ||
884 | 891 | ||
885 | static int wm8960_suspend(struct platform_device *pdev, pm_message_t state) | 892 | static int wm8960_suspend(struct snd_soc_codec *codec, pm_message_t state) |
886 | { | 893 | { |
887 | struct snd_soc_device *socdev = platform_get_drvdata(pdev); | 894 | struct wm8960_priv *wm8960 = snd_soc_codec_get_drvdata(codec); |
888 | struct snd_soc_codec *codec = socdev->card->codec; | ||
889 | 895 | ||
890 | codec->set_bias_level(codec, SND_SOC_BIAS_OFF); | 896 | wm8960->set_bias_level(codec, SND_SOC_BIAS_OFF); |
891 | return 0; | 897 | return 0; |
892 | } | 898 | } |
893 | 899 | ||
894 | static int wm8960_resume(struct platform_device *pdev) | 900 | static int wm8960_resume(struct snd_soc_codec *codec) |
895 | { | 901 | { |
896 | struct snd_soc_device *socdev = platform_get_drvdata(pdev); | 902 | struct wm8960_priv *wm8960 = snd_soc_codec_get_drvdata(codec); |
897 | struct snd_soc_codec *codec = socdev->card->codec; | ||
898 | int i; | 903 | int i; |
899 | u8 data[2]; | 904 | u8 data[2]; |
900 | u16 *cache = codec->reg_cache; | 905 | u16 *cache = codec->reg_cache; |
@@ -906,78 +911,19 @@ static int wm8960_resume(struct platform_device *pdev) | |||
906 | codec->hw_write(codec->control_data, data, 2); | 911 | codec->hw_write(codec->control_data, data, 2); |
907 | } | 912 | } |
908 | 913 | ||
909 | codec->set_bias_level(codec, SND_SOC_BIAS_STANDBY); | 914 | wm8960->set_bias_level(codec, SND_SOC_BIAS_STANDBY); |
910 | |||
911 | return 0; | 915 | return 0; |
912 | } | 916 | } |
913 | 917 | ||
914 | static struct snd_soc_codec *wm8960_codec; | 918 | static int wm8960_probe(struct snd_soc_codec *codec) |
915 | |||
916 | static int wm8960_probe(struct platform_device *pdev) | ||
917 | { | ||
918 | struct snd_soc_device *socdev = platform_get_drvdata(pdev); | ||
919 | struct snd_soc_codec *codec; | ||
920 | int ret = 0; | ||
921 | |||
922 | if (wm8960_codec == NULL) { | ||
923 | dev_err(&pdev->dev, "Codec device not registered\n"); | ||
924 | return -ENODEV; | ||
925 | } | ||
926 | |||
927 | socdev->card->codec = wm8960_codec; | ||
928 | codec = wm8960_codec; | ||
929 | |||
930 | /* register pcms */ | ||
931 | ret = snd_soc_new_pcms(socdev, SNDRV_DEFAULT_IDX1, SNDRV_DEFAULT_STR1); | ||
932 | if (ret < 0) { | ||
933 | dev_err(codec->dev, "failed to create pcms: %d\n", ret); | ||
934 | goto pcm_err; | ||
935 | } | ||
936 | |||
937 | snd_soc_add_controls(codec, wm8960_snd_controls, | ||
938 | ARRAY_SIZE(wm8960_snd_controls)); | ||
939 | wm8960_add_widgets(codec); | ||
940 | |||
941 | return ret; | ||
942 | |||
943 | pcm_err: | ||
944 | return ret; | ||
945 | } | ||
946 | |||
947 | /* power down chip */ | ||
948 | static int wm8960_remove(struct platform_device *pdev) | ||
949 | { | ||
950 | struct snd_soc_device *socdev = platform_get_drvdata(pdev); | ||
951 | |||
952 | snd_soc_free_pcms(socdev); | ||
953 | snd_soc_dapm_free(socdev); | ||
954 | |||
955 | return 0; | ||
956 | } | ||
957 | |||
958 | struct snd_soc_codec_device soc_codec_dev_wm8960 = { | ||
959 | .probe = wm8960_probe, | ||
960 | .remove = wm8960_remove, | ||
961 | .suspend = wm8960_suspend, | ||
962 | .resume = wm8960_resume, | ||
963 | }; | ||
964 | EXPORT_SYMBOL_GPL(soc_codec_dev_wm8960); | ||
965 | |||
966 | static int wm8960_register(struct wm8960_priv *wm8960, | ||
967 | enum snd_soc_control_type control) | ||
968 | { | 919 | { |
969 | struct wm8960_data *pdata = wm8960->codec.dev->platform_data; | 920 | struct wm8960_priv *wm8960 = snd_soc_codec_get_drvdata(codec); |
970 | struct snd_soc_codec *codec = &wm8960->codec; | 921 | struct wm8960_data *pdata = dev_get_platdata(codec->dev); |
971 | int ret; | 922 | int ret; |
972 | u16 reg; | 923 | u16 reg; |
973 | 924 | ||
974 | if (wm8960_codec) { | 925 | wm8960->set_bias_level = wm8960_set_bias_level_out3; |
975 | dev_err(codec->dev, "Another WM8960 is registered\n"); | 926 | codec->control_data = wm8960->control_data; |
976 | ret = -EINVAL; | ||
977 | goto err; | ||
978 | } | ||
979 | |||
980 | codec->set_bias_level = wm8960_set_bias_level_out3; | ||
981 | 927 | ||
982 | if (!pdata) { | 928 | if (!pdata) { |
983 | dev_warn(codec->dev, "No platform data supplied\n"); | 929 | dev_warn(codec->dev, "No platform data supplied\n"); |
@@ -988,39 +934,22 @@ static int wm8960_register(struct wm8960_priv *wm8960, | |||
988 | } | 934 | } |
989 | 935 | ||
990 | if (pdata->capless) | 936 | if (pdata->capless) |
991 | codec->set_bias_level = wm8960_set_bias_level_capless; | 937 | wm8960->set_bias_level = wm8960_set_bias_level_capless; |
992 | } | 938 | } |
993 | 939 | ||
994 | mutex_init(&codec->mutex); | 940 | ret = snd_soc_codec_set_cache_io(codec, 7, 9, wm8960->control_type); |
995 | INIT_LIST_HEAD(&codec->dapm_widgets); | ||
996 | INIT_LIST_HEAD(&codec->dapm_paths); | ||
997 | |||
998 | snd_soc_codec_set_drvdata(codec, wm8960); | ||
999 | codec->name = "WM8960"; | ||
1000 | codec->owner = THIS_MODULE; | ||
1001 | codec->bias_level = SND_SOC_BIAS_OFF; | ||
1002 | codec->dai = &wm8960_dai; | ||
1003 | codec->num_dai = 1; | ||
1004 | codec->reg_cache_size = WM8960_CACHEREGNUM; | ||
1005 | codec->reg_cache = &wm8960->reg_cache; | ||
1006 | |||
1007 | memcpy(codec->reg_cache, wm8960_reg, sizeof(wm8960_reg)); | ||
1008 | |||
1009 | ret = snd_soc_codec_set_cache_io(codec, 7, 9, control); | ||
1010 | if (ret < 0) { | 941 | if (ret < 0) { |
1011 | dev_err(codec->dev, "Failed to set cache I/O: %d\n", ret); | 942 | dev_err(codec->dev, "Failed to set cache I/O: %d\n", ret); |
1012 | goto err; | 943 | return ret; |
1013 | } | 944 | } |
1014 | 945 | ||
1015 | ret = wm8960_reset(codec); | 946 | ret = wm8960_reset(codec); |
1016 | if (ret < 0) { | 947 | if (ret < 0) { |
1017 | dev_err(codec->dev, "Failed to issue reset\n"); | 948 | dev_err(codec->dev, "Failed to issue reset\n"); |
1018 | goto err; | 949 | return ret; |
1019 | } | 950 | } |
1020 | 951 | ||
1021 | wm8960_dai.dev = codec->dev; | 952 | wm8960->set_bias_level(codec, SND_SOC_BIAS_STANDBY); |
1022 | |||
1023 | codec->set_bias_level(codec, SND_SOC_BIAS_STANDBY); | ||
1024 | 953 | ||
1025 | /* Latch the update bits */ | 954 | /* Latch the update bits */ |
1026 | reg = snd_soc_read(codec, WM8960_LINVOL); | 955 | reg = snd_soc_read(codec, WM8960_LINVOL); |
@@ -1044,62 +973,58 @@ static int wm8960_register(struct wm8960_priv *wm8960, | |||
1044 | reg = snd_soc_read(codec, WM8960_ROUT2); | 973 | reg = snd_soc_read(codec, WM8960_ROUT2); |
1045 | snd_soc_write(codec, WM8960_ROUT2, reg | 0x100); | 974 | snd_soc_write(codec, WM8960_ROUT2, reg | 0x100); |
1046 | 975 | ||
1047 | wm8960_codec = codec; | 976 | snd_soc_add_controls(codec, wm8960_snd_controls, |
1048 | 977 | ARRAY_SIZE(wm8960_snd_controls)); | |
1049 | ret = snd_soc_register_codec(codec); | 978 | wm8960_add_widgets(codec); |
1050 | if (ret != 0) { | ||
1051 | dev_err(codec->dev, "Failed to register codec: %d\n", ret); | ||
1052 | goto err; | ||
1053 | } | ||
1054 | |||
1055 | ret = snd_soc_register_dai(&wm8960_dai); | ||
1056 | if (ret != 0) { | ||
1057 | dev_err(codec->dev, "Failed to register DAI: %d\n", ret); | ||
1058 | goto err_codec; | ||
1059 | } | ||
1060 | 979 | ||
1061 | return 0; | 980 | return 0; |
1062 | |||
1063 | err_codec: | ||
1064 | snd_soc_unregister_codec(codec); | ||
1065 | err: | ||
1066 | kfree(wm8960); | ||
1067 | return ret; | ||
1068 | } | 981 | } |
1069 | 982 | ||
1070 | static void wm8960_unregister(struct wm8960_priv *wm8960) | 983 | /* power down chip */ |
984 | static int wm8960_remove(struct snd_soc_codec *codec) | ||
1071 | { | 985 | { |
1072 | wm8960->codec.set_bias_level(&wm8960->codec, SND_SOC_BIAS_OFF); | 986 | struct wm8960_priv *wm8960 = snd_soc_codec_get_drvdata(codec); |
1073 | snd_soc_unregister_dai(&wm8960_dai); | 987 | |
1074 | snd_soc_unregister_codec(&wm8960->codec); | 988 | wm8960->set_bias_level(codec, SND_SOC_BIAS_OFF); |
1075 | kfree(wm8960); | 989 | return 0; |
1076 | wm8960_codec = NULL; | ||
1077 | } | 990 | } |
1078 | 991 | ||
992 | static struct snd_soc_codec_driver soc_codec_dev_wm8960 = { | ||
993 | .probe = wm8960_probe, | ||
994 | .remove = wm8960_remove, | ||
995 | .suspend = wm8960_suspend, | ||
996 | .resume = wm8960_resume, | ||
997 | .set_bias_level = wm8960_set_bias_level, | ||
998 | .reg_cache_size = ARRAY_SIZE(wm8960_reg), | ||
999 | .reg_word_size = sizeof(u16), | ||
1000 | .reg_cache_default = wm8960_reg, | ||
1001 | }; | ||
1002 | |||
1003 | #if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE) | ||
1079 | static __devinit int wm8960_i2c_probe(struct i2c_client *i2c, | 1004 | static __devinit int wm8960_i2c_probe(struct i2c_client *i2c, |
1080 | const struct i2c_device_id *id) | 1005 | const struct i2c_device_id *id) |
1081 | { | 1006 | { |
1082 | struct wm8960_priv *wm8960; | 1007 | struct wm8960_priv *wm8960; |
1083 | struct snd_soc_codec *codec; | 1008 | int ret; |
1084 | 1009 | ||
1085 | wm8960 = kzalloc(sizeof(struct wm8960_priv), GFP_KERNEL); | 1010 | wm8960 = kzalloc(sizeof(struct wm8960_priv), GFP_KERNEL); |
1086 | if (wm8960 == NULL) | 1011 | if (wm8960 == NULL) |
1087 | return -ENOMEM; | 1012 | return -ENOMEM; |
1088 | 1013 | ||
1089 | codec = &wm8960->codec; | ||
1090 | |||
1091 | i2c_set_clientdata(i2c, wm8960); | 1014 | i2c_set_clientdata(i2c, wm8960); |
1092 | codec->control_data = i2c; | 1015 | wm8960->control_data = i2c; |
1093 | |||
1094 | codec->dev = &i2c->dev; | ||
1095 | 1016 | ||
1096 | return wm8960_register(wm8960, SND_SOC_I2C); | 1017 | ret = snd_soc_register_codec(&i2c->dev, |
1018 | &soc_codec_dev_wm8960, &wm8960_dai, 1); | ||
1019 | if (ret < 0) | ||
1020 | kfree(wm8960); | ||
1021 | return ret; | ||
1097 | } | 1022 | } |
1098 | 1023 | ||
1099 | static __devexit int wm8960_i2c_remove(struct i2c_client *client) | 1024 | static __devexit int wm8960_i2c_remove(struct i2c_client *client) |
1100 | { | 1025 | { |
1101 | struct wm8960_priv *wm8960 = i2c_get_clientdata(client); | 1026 | snd_soc_unregister_codec(&client->dev); |
1102 | wm8960_unregister(wm8960); | 1027 | kfree(i2c_get_clientdata(client)); |
1103 | return 0; | 1028 | return 0; |
1104 | } | 1029 | } |
1105 | 1030 | ||
@@ -1111,35 +1036,37 @@ MODULE_DEVICE_TABLE(i2c, wm8960_i2c_id); | |||
1111 | 1036 | ||
1112 | static struct i2c_driver wm8960_i2c_driver = { | 1037 | static struct i2c_driver wm8960_i2c_driver = { |
1113 | .driver = { | 1038 | .driver = { |
1114 | .name = "wm8960", | 1039 | .name = "wm8960-codec", |
1115 | .owner = THIS_MODULE, | 1040 | .owner = THIS_MODULE, |
1116 | }, | 1041 | }, |
1117 | .probe = wm8960_i2c_probe, | 1042 | .probe = wm8960_i2c_probe, |
1118 | .remove = __devexit_p(wm8960_i2c_remove), | 1043 | .remove = __devexit_p(wm8960_i2c_remove), |
1119 | .id_table = wm8960_i2c_id, | 1044 | .id_table = wm8960_i2c_id, |
1120 | }; | 1045 | }; |
1046 | #endif | ||
1121 | 1047 | ||
1122 | static int __init wm8960_modinit(void) | 1048 | static int __init wm8960_modinit(void) |
1123 | { | 1049 | { |
1124 | int ret; | 1050 | int ret = 0; |
1125 | 1051 | #if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE) | |
1126 | ret = i2c_add_driver(&wm8960_i2c_driver); | 1052 | ret = i2c_add_driver(&wm8960_i2c_driver); |
1127 | if (ret != 0) { | 1053 | if (ret != 0) { |
1128 | printk(KERN_ERR "Failed to register WM8960 I2C driver: %d\n", | 1054 | printk(KERN_ERR "Failed to register WM8960 I2C driver: %d\n", |
1129 | ret); | 1055 | ret); |
1130 | } | 1056 | } |
1131 | 1057 | #endif | |
1132 | return ret; | 1058 | return ret; |
1133 | } | 1059 | } |
1134 | module_init(wm8960_modinit); | 1060 | module_init(wm8960_modinit); |
1135 | 1061 | ||
1136 | static void __exit wm8960_exit(void) | 1062 | static void __exit wm8960_exit(void) |
1137 | { | 1063 | { |
1064 | #if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE) | ||
1138 | i2c_del_driver(&wm8960_i2c_driver); | 1065 | i2c_del_driver(&wm8960_i2c_driver); |
1066 | #endif | ||
1139 | } | 1067 | } |
1140 | module_exit(wm8960_exit); | 1068 | module_exit(wm8960_exit); |
1141 | 1069 | ||
1142 | |||
1143 | MODULE_DESCRIPTION("ASoC WM8960 driver"); | 1070 | MODULE_DESCRIPTION("ASoC WM8960 driver"); |
1144 | MODULE_AUTHOR("Liam Girdwood"); | 1071 | MODULE_AUTHOR("Liam Girdwood"); |
1145 | MODULE_LICENSE("GPL"); | 1072 | MODULE_LICENSE("GPL"); |
diff --git a/sound/soc/codecs/wm8960.h b/sound/soc/codecs/wm8960.h index a5ef65481b86..2d8163d7004b 100644 --- a/sound/soc/codecs/wm8960.h +++ b/sound/soc/codecs/wm8960.h | |||
@@ -110,7 +110,4 @@ | |||
110 | #define WM8960_OPCLK_DIV_5_5 (4 << 0) | 110 | #define WM8960_OPCLK_DIV_5_5 (4 << 0) |
111 | #define WM8960_OPCLK_DIV_6 (5 << 0) | 111 | #define WM8960_OPCLK_DIV_6 (5 << 0) |
112 | 112 | ||
113 | extern struct snd_soc_dai wm8960_dai; | ||
114 | extern struct snd_soc_codec_device soc_codec_dev_wm8960; | ||
115 | |||
116 | #endif | 113 | #endif |
diff --git a/sound/soc/codecs/wm8961.c b/sound/soc/codecs/wm8961.c index 2549d3a297ab..fa36a62972f8 100644 --- a/sound/soc/codecs/wm8961.c +++ b/sound/soc/codecs/wm8961.c | |||
@@ -288,7 +288,7 @@ static u16 wm8961_reg_defaults[] = { | |||
288 | }; | 288 | }; |
289 | 289 | ||
290 | struct wm8961_priv { | 290 | struct wm8961_priv { |
291 | struct snd_soc_codec codec; | 291 | enum snd_soc_control_type control_type; |
292 | int sysclk; | 292 | int sysclk; |
293 | u16 reg_cache[WM8961_MAX_REGISTER]; | 293 | u16 reg_cache[WM8961_MAX_REGISTER]; |
294 | }; | 294 | }; |
@@ -940,8 +940,8 @@ static struct snd_soc_dai_ops wm8961_dai_ops = { | |||
940 | .set_clkdiv = wm8961_set_clkdiv, | 940 | .set_clkdiv = wm8961_set_clkdiv, |
941 | }; | 941 | }; |
942 | 942 | ||
943 | struct snd_soc_dai wm8961_dai = { | 943 | static struct snd_soc_dai_driver wm8961_dai = { |
944 | .name = "WM8961", | 944 | .name = "wm8961-hifi", |
945 | .playback = { | 945 | .playback = { |
946 | .stream_name = "HiFi Playback", | 946 | .stream_name = "HiFi Playback", |
947 | .channels_min = 1, | 947 | .channels_min = 1, |
@@ -956,140 +956,23 @@ struct snd_soc_dai wm8961_dai = { | |||
956 | .formats = WM8961_FORMATS,}, | 956 | .formats = WM8961_FORMATS,}, |
957 | .ops = &wm8961_dai_ops, | 957 | .ops = &wm8961_dai_ops, |
958 | }; | 958 | }; |
959 | EXPORT_SYMBOL_GPL(wm8961_dai); | ||
960 | 959 | ||
961 | 960 | static int wm8961_probe(struct snd_soc_codec *codec) | |
962 | static struct snd_soc_codec *wm8961_codec; | ||
963 | |||
964 | static int wm8961_probe(struct platform_device *pdev) | ||
965 | { | 961 | { |
966 | struct snd_soc_device *socdev = platform_get_drvdata(pdev); | 962 | struct wm8961_priv *wm8961 = snd_soc_codec_get_drvdata(codec); |
967 | struct snd_soc_codec *codec; | ||
968 | int ret = 0; | 963 | int ret = 0; |
969 | |||
970 | if (wm8961_codec == NULL) { | ||
971 | dev_err(&pdev->dev, "Codec device not registered\n"); | ||
972 | return -ENODEV; | ||
973 | } | ||
974 | |||
975 | socdev->card->codec = wm8961_codec; | ||
976 | codec = wm8961_codec; | ||
977 | |||
978 | /* register pcms */ | ||
979 | ret = snd_soc_new_pcms(socdev, SNDRV_DEFAULT_IDX1, SNDRV_DEFAULT_STR1); | ||
980 | if (ret < 0) { | ||
981 | dev_err(codec->dev, "failed to create pcms: %d\n", ret); | ||
982 | goto pcm_err; | ||
983 | } | ||
984 | |||
985 | snd_soc_add_controls(codec, wm8961_snd_controls, | ||
986 | ARRAY_SIZE(wm8961_snd_controls)); | ||
987 | snd_soc_dapm_new_controls(codec, wm8961_dapm_widgets, | ||
988 | ARRAY_SIZE(wm8961_dapm_widgets)); | ||
989 | snd_soc_dapm_add_routes(codec, audio_paths, ARRAY_SIZE(audio_paths)); | ||
990 | |||
991 | return ret; | ||
992 | |||
993 | pcm_err: | ||
994 | return ret; | ||
995 | } | ||
996 | |||
997 | static int wm8961_remove(struct platform_device *pdev) | ||
998 | { | ||
999 | struct snd_soc_device *socdev = platform_get_drvdata(pdev); | ||
1000 | |||
1001 | snd_soc_free_pcms(socdev); | ||
1002 | snd_soc_dapm_free(socdev); | ||
1003 | |||
1004 | return 0; | ||
1005 | } | ||
1006 | |||
1007 | #ifdef CONFIG_PM | ||
1008 | static int wm8961_suspend(struct platform_device *pdev, pm_message_t state) | ||
1009 | { | ||
1010 | struct snd_soc_device *socdev = platform_get_drvdata(pdev); | ||
1011 | struct snd_soc_codec *codec = socdev->card->codec; | ||
1012 | |||
1013 | wm8961_set_bias_level(codec, SND_SOC_BIAS_OFF); | ||
1014 | |||
1015 | return 0; | ||
1016 | } | ||
1017 | |||
1018 | static int wm8961_resume(struct platform_device *pdev) | ||
1019 | { | ||
1020 | struct snd_soc_device *socdev = platform_get_drvdata(pdev); | ||
1021 | struct snd_soc_codec *codec = socdev->card->codec; | ||
1022 | u16 *reg_cache = codec->reg_cache; | ||
1023 | int i; | ||
1024 | |||
1025 | for (i = 0; i < codec->reg_cache_size; i++) { | ||
1026 | if (reg_cache[i] == wm8961_reg_defaults[i]) | ||
1027 | continue; | ||
1028 | |||
1029 | if (i == WM8961_SOFTWARE_RESET) | ||
1030 | continue; | ||
1031 | |||
1032 | snd_soc_write(codec, i, reg_cache[i]); | ||
1033 | } | ||
1034 | |||
1035 | wm8961_set_bias_level(codec, SND_SOC_BIAS_STANDBY); | ||
1036 | |||
1037 | return 0; | ||
1038 | } | ||
1039 | #else | ||
1040 | #define wm8961_suspend NULL | ||
1041 | #define wm8961_resume NULL | ||
1042 | #endif | ||
1043 | |||
1044 | struct snd_soc_codec_device soc_codec_dev_wm8961 = { | ||
1045 | .probe = wm8961_probe, | ||
1046 | .remove = wm8961_remove, | ||
1047 | .suspend = wm8961_suspend, | ||
1048 | .resume = wm8961_resume, | ||
1049 | }; | ||
1050 | EXPORT_SYMBOL_GPL(soc_codec_dev_wm8961); | ||
1051 | |||
1052 | static int wm8961_register(struct wm8961_priv *wm8961) | ||
1053 | { | ||
1054 | struct snd_soc_codec *codec = &wm8961->codec; | ||
1055 | int ret; | ||
1056 | u16 reg; | 964 | u16 reg; |
1057 | 965 | ||
1058 | if (wm8961_codec) { | ||
1059 | dev_err(codec->dev, "Another WM8961 is registered\n"); | ||
1060 | ret = -EINVAL; | ||
1061 | goto err; | ||
1062 | } | ||
1063 | |||
1064 | mutex_init(&codec->mutex); | ||
1065 | INIT_LIST_HEAD(&codec->dapm_widgets); | ||
1066 | INIT_LIST_HEAD(&codec->dapm_paths); | ||
1067 | |||
1068 | snd_soc_codec_set_drvdata(codec, wm8961); | ||
1069 | codec->name = "WM8961"; | ||
1070 | codec->owner = THIS_MODULE; | ||
1071 | codec->dai = &wm8961_dai; | ||
1072 | codec->num_dai = 1; | ||
1073 | codec->reg_cache_size = ARRAY_SIZE(wm8961->reg_cache); | ||
1074 | codec->reg_cache = &wm8961->reg_cache; | ||
1075 | codec->bias_level = SND_SOC_BIAS_OFF; | ||
1076 | codec->set_bias_level = wm8961_set_bias_level; | ||
1077 | codec->volatile_register = wm8961_volatile_register; | ||
1078 | |||
1079 | memcpy(codec->reg_cache, wm8961_reg_defaults, | ||
1080 | sizeof(wm8961_reg_defaults)); | ||
1081 | |||
1082 | ret = snd_soc_codec_set_cache_io(codec, 8, 16, SND_SOC_I2C); | 966 | ret = snd_soc_codec_set_cache_io(codec, 8, 16, SND_SOC_I2C); |
1083 | if (ret != 0) { | 967 | if (ret != 0) { |
1084 | dev_err(codec->dev, "Failed to set cache I/O: %d\n", ret); | 968 | dev_err(codec->dev, "Failed to set cache I/O: %d\n", ret); |
1085 | goto err; | 969 | return ret; |
1086 | } | 970 | } |
1087 | 971 | ||
1088 | reg = snd_soc_read(codec, WM8961_SOFTWARE_RESET); | 972 | reg = snd_soc_read(codec, WM8961_SOFTWARE_RESET); |
1089 | if (reg != 0x1801) { | 973 | if (reg != 0x1801) { |
1090 | dev_err(codec->dev, "Device is not a WM8961: ID=0x%x\n", reg); | 974 | dev_err(codec->dev, "Device is not a WM8961: ID=0x%x\n", reg); |
1091 | ret = -EINVAL; | 975 | return -EINVAL; |
1092 | goto err; | ||
1093 | } | 976 | } |
1094 | 977 | ||
1095 | /* This isn't volatile - readback doesn't correspond to write */ | 978 | /* This isn't volatile - readback doesn't correspond to write */ |
@@ -1102,7 +985,7 @@ static int wm8961_register(struct wm8961_priv *wm8961) | |||
1102 | ret = wm8961_reset(codec); | 985 | ret = wm8961_reset(codec); |
1103 | if (ret < 0) { | 986 | if (ret < 0) { |
1104 | dev_err(codec->dev, "Failed to issue reset\n"); | 987 | dev_err(codec->dev, "Failed to issue reset\n"); |
1105 | goto err; | 988 | return ret; |
1106 | } | 989 | } |
1107 | 990 | ||
1108 | /* Enable class W */ | 991 | /* Enable class W */ |
@@ -1140,64 +1023,89 @@ static int wm8961_register(struct wm8961_priv *wm8961) | |||
1140 | 1023 | ||
1141 | wm8961_set_bias_level(codec, SND_SOC_BIAS_STANDBY); | 1024 | wm8961_set_bias_level(codec, SND_SOC_BIAS_STANDBY); |
1142 | 1025 | ||
1143 | wm8961_dai.dev = codec->dev; | 1026 | snd_soc_add_controls(codec, wm8961_snd_controls, |
1027 | ARRAY_SIZE(wm8961_snd_controls)); | ||
1028 | snd_soc_dapm_new_controls(codec, wm8961_dapm_widgets, | ||
1029 | ARRAY_SIZE(wm8961_dapm_widgets)); | ||
1030 | snd_soc_dapm_add_routes(codec, audio_paths, ARRAY_SIZE(audio_paths)); | ||
1144 | 1031 | ||
1145 | wm8961_codec = codec; | 1032 | return 0; |
1033 | } | ||
1146 | 1034 | ||
1147 | ret = snd_soc_register_codec(codec); | 1035 | static int wm8961_remove(struct snd_soc_codec *codec) |
1148 | if (ret != 0) { | 1036 | { |
1149 | dev_err(codec->dev, "Failed to register codec: %d\n", ret); | 1037 | wm8961_set_bias_level(codec, SND_SOC_BIAS_OFF); |
1150 | goto err; | 1038 | return 0; |
1151 | } | 1039 | } |
1152 | 1040 | ||
1153 | ret = snd_soc_register_dai(&wm8961_dai); | 1041 | #ifdef CONFIG_PM |
1154 | if (ret != 0) { | 1042 | static int wm8961_suspend(struct snd_soc_codec *codec, pm_message_t state) |
1155 | dev_err(codec->dev, "Failed to register DAI: %d\n", ret); | 1043 | { |
1156 | goto err_codec; | 1044 | wm8961_set_bias_level(codec, SND_SOC_BIAS_OFF); |
1157 | } | ||
1158 | 1045 | ||
1159 | return 0; | 1046 | return 0; |
1160 | |||
1161 | err_codec: | ||
1162 | snd_soc_unregister_codec(codec); | ||
1163 | err: | ||
1164 | kfree(wm8961); | ||
1165 | return ret; | ||
1166 | } | 1047 | } |
1167 | 1048 | ||
1168 | static void wm8961_unregister(struct wm8961_priv *wm8961) | 1049 | static int wm8961_resume(struct snd_soc_codec *codec) |
1169 | { | 1050 | { |
1170 | wm8961_set_bias_level(&wm8961->codec, SND_SOC_BIAS_OFF); | 1051 | u16 *reg_cache = codec->reg_cache; |
1171 | snd_soc_unregister_dai(&wm8961_dai); | 1052 | int i; |
1172 | snd_soc_unregister_codec(&wm8961->codec); | 1053 | |
1173 | kfree(wm8961); | 1054 | for (i = 0; i < codec->driver->reg_cache_size; i++) { |
1174 | wm8961_codec = NULL; | 1055 | if (reg_cache[i] == wm8961_reg_defaults[i]) |
1056 | continue; | ||
1057 | |||
1058 | if (i == WM8961_SOFTWARE_RESET) | ||
1059 | continue; | ||
1060 | |||
1061 | snd_soc_write(codec, i, reg_cache[i]); | ||
1062 | } | ||
1063 | |||
1064 | wm8961_set_bias_level(codec, SND_SOC_BIAS_STANDBY); | ||
1065 | |||
1066 | return 0; | ||
1175 | } | 1067 | } |
1068 | #else | ||
1069 | #define wm8961_suspend NULL | ||
1070 | #define wm8961_resume NULL | ||
1071 | #endif | ||
1176 | 1072 | ||
1073 | static struct snd_soc_codec_driver soc_codec_dev_wm8961 = { | ||
1074 | .probe = wm8961_probe, | ||
1075 | .remove = wm8961_remove, | ||
1076 | .suspend = wm8961_suspend, | ||
1077 | .resume = wm8961_resume, | ||
1078 | .set_bias_level = wm8961_set_bias_level, | ||
1079 | .reg_cache_size = sizeof(wm8961_reg_defaults), | ||
1080 | .reg_word_size = sizeof(u16), | ||
1081 | .reg_cache_default = wm8961_reg_defaults, | ||
1082 | .volatile_register = wm8961_volatile_register, | ||
1083 | }; | ||
1084 | |||
1085 | #if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE) | ||
1177 | static __devinit int wm8961_i2c_probe(struct i2c_client *i2c, | 1086 | static __devinit int wm8961_i2c_probe(struct i2c_client *i2c, |
1178 | const struct i2c_device_id *id) | 1087 | const struct i2c_device_id *id) |
1179 | { | 1088 | { |
1180 | struct wm8961_priv *wm8961; | 1089 | struct wm8961_priv *wm8961; |
1181 | struct snd_soc_codec *codec; | 1090 | int ret; |
1182 | 1091 | ||
1183 | wm8961 = kzalloc(sizeof(struct wm8961_priv), GFP_KERNEL); | 1092 | wm8961 = kzalloc(sizeof(struct wm8961_priv), GFP_KERNEL); |
1184 | if (wm8961 == NULL) | 1093 | if (wm8961 == NULL) |
1185 | return -ENOMEM; | 1094 | return -ENOMEM; |
1186 | 1095 | ||
1187 | codec = &wm8961->codec; | ||
1188 | |||
1189 | i2c_set_clientdata(i2c, wm8961); | 1096 | i2c_set_clientdata(i2c, wm8961); |
1190 | codec->control_data = i2c; | ||
1191 | |||
1192 | codec->dev = &i2c->dev; | ||
1193 | 1097 | ||
1194 | return wm8961_register(wm8961); | 1098 | ret = snd_soc_register_codec(&i2c->dev, |
1099 | &soc_codec_dev_wm8961, &wm8961_dai, 1); | ||
1100 | if (ret < 0) | ||
1101 | kfree(wm8961); | ||
1102 | return ret; | ||
1195 | } | 1103 | } |
1196 | 1104 | ||
1197 | static __devexit int wm8961_i2c_remove(struct i2c_client *client) | 1105 | static __devexit int wm8961_i2c_remove(struct i2c_client *client) |
1198 | { | 1106 | { |
1199 | struct wm8961_priv *wm8961 = i2c_get_clientdata(client); | 1107 | snd_soc_unregister_codec(&client->dev); |
1200 | wm8961_unregister(wm8961); | 1108 | kfree(i2c_get_clientdata(client)); |
1201 | return 0; | 1109 | return 0; |
1202 | } | 1110 | } |
1203 | 1111 | ||
@@ -1209,35 +1117,37 @@ MODULE_DEVICE_TABLE(i2c, wm8961_i2c_id); | |||
1209 | 1117 | ||
1210 | static struct i2c_driver wm8961_i2c_driver = { | 1118 | static struct i2c_driver wm8961_i2c_driver = { |
1211 | .driver = { | 1119 | .driver = { |
1212 | .name = "wm8961", | 1120 | .name = "wm8961-codec", |
1213 | .owner = THIS_MODULE, | 1121 | .owner = THIS_MODULE, |
1214 | }, | 1122 | }, |
1215 | .probe = wm8961_i2c_probe, | 1123 | .probe = wm8961_i2c_probe, |
1216 | .remove = __devexit_p(wm8961_i2c_remove), | 1124 | .remove = __devexit_p(wm8961_i2c_remove), |
1217 | .id_table = wm8961_i2c_id, | 1125 | .id_table = wm8961_i2c_id, |
1218 | }; | 1126 | }; |
1127 | #endif | ||
1219 | 1128 | ||
1220 | static int __init wm8961_modinit(void) | 1129 | static int __init wm8961_modinit(void) |
1221 | { | 1130 | { |
1222 | int ret; | 1131 | int ret = 0; |
1223 | 1132 | #if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE) | |
1224 | ret = i2c_add_driver(&wm8961_i2c_driver); | 1133 | ret = i2c_add_driver(&wm8961_i2c_driver); |
1225 | if (ret != 0) { | 1134 | if (ret != 0) { |
1226 | printk(KERN_ERR "Failed to register WM8961 I2C driver: %d\n", | 1135 | printk(KERN_ERR "Failed to register wm8961 I2C driver: %d\n", |
1227 | ret); | 1136 | ret); |
1228 | } | 1137 | } |
1229 | 1138 | #endif | |
1230 | return ret; | 1139 | return ret; |
1231 | } | 1140 | } |
1232 | module_init(wm8961_modinit); | 1141 | module_init(wm8961_modinit); |
1233 | 1142 | ||
1234 | static void __exit wm8961_exit(void) | 1143 | static void __exit wm8961_exit(void) |
1235 | { | 1144 | { |
1145 | #if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE) | ||
1236 | i2c_del_driver(&wm8961_i2c_driver); | 1146 | i2c_del_driver(&wm8961_i2c_driver); |
1147 | #endif | ||
1237 | } | 1148 | } |
1238 | module_exit(wm8961_exit); | 1149 | module_exit(wm8961_exit); |
1239 | 1150 | ||
1240 | |||
1241 | MODULE_DESCRIPTION("ASoC WM8961 driver"); | 1151 | MODULE_DESCRIPTION("ASoC WM8961 driver"); |
1242 | MODULE_AUTHOR("Mark Brown <broonie@opensource.wolfsonmicro.com>"); | 1152 | MODULE_AUTHOR("Mark Brown <broonie@opensource.wolfsonmicro.com>"); |
1243 | MODULE_LICENSE("GPL"); | 1153 | MODULE_LICENSE("GPL"); |
diff --git a/sound/soc/codecs/wm8961.h b/sound/soc/codecs/wm8961.h index 5513bfd720d6..1d736e5701c8 100644 --- a/sound/soc/codecs/wm8961.h +++ b/sound/soc/codecs/wm8961.h | |||
@@ -11,9 +11,6 @@ | |||
11 | 11 | ||
12 | #include <sound/soc.h> | 12 | #include <sound/soc.h> |
13 | 13 | ||
14 | extern struct snd_soc_codec_device soc_codec_dev_wm8961; | ||
15 | extern struct snd_soc_dai wm8961_dai; | ||
16 | |||
17 | #define WM8961_BCLK 1 | 14 | #define WM8961_BCLK 1 |
18 | #define WM8961_LRCLK 2 | 15 | #define WM8961_LRCLK 2 |
19 | 16 | ||
diff --git a/sound/soc/codecs/wm8971.c b/sound/soc/codecs/wm8971.c index a99620f335d2..63f6dbf5d070 100644 --- a/sound/soc/codecs/wm8971.c +++ b/sound/soc/codecs/wm8971.c | |||
@@ -30,14 +30,13 @@ | |||
30 | 30 | ||
31 | #include "wm8971.h" | 31 | #include "wm8971.h" |
32 | 32 | ||
33 | #define WM8971_VERSION "0.9" | ||
34 | |||
35 | #define WM8971_REG_COUNT 43 | 33 | #define WM8971_REG_COUNT 43 |
36 | 34 | ||
37 | static struct workqueue_struct *wm8971_workq = NULL; | 35 | static struct workqueue_struct *wm8971_workq = NULL; |
38 | 36 | ||
39 | /* codec private data */ | 37 | /* codec private data */ |
40 | struct wm8971_priv { | 38 | struct wm8971_priv { |
39 | enum snd_soc_control_type control_type; | ||
41 | unsigned int sysclk; | 40 | unsigned int sysclk; |
42 | }; | 41 | }; |
43 | 42 | ||
@@ -492,8 +491,7 @@ static int wm8971_pcm_hw_params(struct snd_pcm_substream *substream, | |||
492 | struct snd_soc_dai *dai) | 491 | struct snd_soc_dai *dai) |
493 | { | 492 | { |
494 | struct snd_soc_pcm_runtime *rtd = substream->private_data; | 493 | struct snd_soc_pcm_runtime *rtd = substream->private_data; |
495 | struct snd_soc_device *socdev = rtd->socdev; | 494 | struct snd_soc_codec *codec = rtd->codec; |
496 | struct snd_soc_codec *codec = socdev->card->codec; | ||
497 | struct wm8971_priv *wm8971 = snd_soc_codec_get_drvdata(codec); | 495 | struct wm8971_priv *wm8971 = snd_soc_codec_get_drvdata(codec); |
498 | u16 iface = snd_soc_read(codec, WM8971_IFACE) & 0x1f3; | 496 | u16 iface = snd_soc_read(codec, WM8971_IFACE) & 0x1f3; |
499 | u16 srate = snd_soc_read(codec, WM8971_SRATE) & 0x1c0; | 497 | u16 srate = snd_soc_read(codec, WM8971_SRATE) & 0x1c0; |
@@ -573,8 +571,8 @@ static struct snd_soc_dai_ops wm8971_dai_ops = { | |||
573 | .set_sysclk = wm8971_set_dai_sysclk, | 571 | .set_sysclk = wm8971_set_dai_sysclk, |
574 | }; | 572 | }; |
575 | 573 | ||
576 | struct snd_soc_dai wm8971_dai = { | 574 | static struct snd_soc_dai_driver wm8971_dai = { |
577 | .name = "WM8971", | 575 | .name = "wm8971-hifi", |
578 | .playback = { | 576 | .playback = { |
579 | .stream_name = "Playback", | 577 | .stream_name = "Playback", |
580 | .channels_min = 1, | 578 | .channels_min = 1, |
@@ -589,7 +587,6 @@ struct snd_soc_dai wm8971_dai = { | |||
589 | .formats = WM8971_FORMATS,}, | 587 | .formats = WM8971_FORMATS,}, |
590 | .ops = &wm8971_dai_ops, | 588 | .ops = &wm8971_dai_ops, |
591 | }; | 589 | }; |
592 | EXPORT_SYMBOL_GPL(wm8971_dai); | ||
593 | 590 | ||
594 | static void wm8971_work(struct work_struct *work) | 591 | static void wm8971_work(struct work_struct *work) |
595 | { | 592 | { |
@@ -598,19 +595,14 @@ static void wm8971_work(struct work_struct *work) | |||
598 | wm8971_set_bias_level(codec, codec->bias_level); | 595 | wm8971_set_bias_level(codec, codec->bias_level); |
599 | } | 596 | } |
600 | 597 | ||
601 | static int wm8971_suspend(struct platform_device *pdev, pm_message_t state) | 598 | static int wm8971_suspend(struct snd_soc_codec *codec, pm_message_t state) |
602 | { | 599 | { |
603 | struct snd_soc_device *socdev = platform_get_drvdata(pdev); | ||
604 | struct snd_soc_codec *codec = socdev->card->codec; | ||
605 | |||
606 | wm8971_set_bias_level(codec, SND_SOC_BIAS_OFF); | 600 | wm8971_set_bias_level(codec, SND_SOC_BIAS_OFF); |
607 | return 0; | 601 | return 0; |
608 | } | 602 | } |
609 | 603 | ||
610 | static int wm8971_resume(struct platform_device *pdev) | 604 | static int wm8971_resume(struct snd_soc_codec *codec) |
611 | { | 605 | { |
612 | struct snd_soc_device *socdev = platform_get_drvdata(pdev); | ||
613 | struct snd_soc_codec *codec = socdev->card->codec; | ||
614 | int i; | 606 | int i; |
615 | u8 data[2]; | 607 | u8 data[2]; |
616 | u16 *cache = codec->reg_cache; | 608 | u16 *cache = codec->reg_cache; |
@@ -639,37 +631,24 @@ static int wm8971_resume(struct platform_device *pdev) | |||
639 | return 0; | 631 | return 0; |
640 | } | 632 | } |
641 | 633 | ||
642 | static int wm8971_init(struct snd_soc_device *socdev, | 634 | static int wm8971_probe(struct snd_soc_codec *codec) |
643 | enum snd_soc_control_type control) | ||
644 | { | 635 | { |
645 | struct snd_soc_codec *codec = socdev->card->codec; | 636 | struct wm8971_priv *wm8971 = snd_soc_codec_get_drvdata(codec); |
646 | int reg, ret = 0; | 637 | int ret = 0; |
647 | 638 | u16 reg; | |
648 | codec->name = "WM8971"; | ||
649 | codec->owner = THIS_MODULE; | ||
650 | codec->set_bias_level = wm8971_set_bias_level; | ||
651 | codec->dai = &wm8971_dai; | ||
652 | codec->reg_cache_size = ARRAY_SIZE(wm8971_reg); | ||
653 | codec->num_dai = 1; | ||
654 | codec->reg_cache = kmemdup(wm8971_reg, sizeof(wm8971_reg), GFP_KERNEL); | ||
655 | |||
656 | if (codec->reg_cache == NULL) | ||
657 | return -ENOMEM; | ||
658 | 639 | ||
659 | ret = snd_soc_codec_set_cache_io(codec, 7, 9, control); | 640 | ret = snd_soc_codec_set_cache_io(codec, 7, 9, wm8971->control_type); |
660 | if (ret < 0) { | 641 | if (ret < 0) { |
661 | printk(KERN_ERR "wm8971: failed to set cache I/O: %d\n", ret); | 642 | printk(KERN_ERR "wm8971: failed to set cache I/O: %d\n", ret); |
662 | goto err; | 643 | return ret; |
663 | } | 644 | } |
664 | 645 | ||
665 | wm8971_reset(codec); | 646 | INIT_DELAYED_WORK(&codec->delayed_work, wm8971_work); |
647 | wm8971_workq = create_workqueue("wm8971"); | ||
648 | if (wm8971_workq == NULL) | ||
649 | return -ENOMEM; | ||
666 | 650 | ||
667 | /* register pcms */ | 651 | wm8971_reset(codec); |
668 | ret = snd_soc_new_pcms(socdev, SNDRV_DEFAULT_IDX1, SNDRV_DEFAULT_STR1); | ||
669 | if (ret < 0) { | ||
670 | printk(KERN_ERR "wm8971: failed to create pcms\n"); | ||
671 | goto err; | ||
672 | } | ||
673 | 652 | ||
674 | /* charge output caps - set vmid to 5k for quick power up */ | 653 | /* charge output caps - set vmid to 5k for quick power up */ |
675 | reg = snd_soc_read(codec, WM8971_PWR1) & 0xfe3e; | 654 | reg = snd_soc_read(codec, WM8971_PWR1) & 0xfe3e; |
@@ -704,40 +683,54 @@ static int wm8971_init(struct snd_soc_device *socdev, | |||
704 | wm8971_add_widgets(codec); | 683 | wm8971_add_widgets(codec); |
705 | 684 | ||
706 | return ret; | 685 | return ret; |
707 | |||
708 | err: | ||
709 | kfree(codec->reg_cache); | ||
710 | return ret; | ||
711 | } | 686 | } |
712 | 687 | ||
713 | /* If the i2c layer weren't so broken, we could pass this kind of data | ||
714 | around */ | ||
715 | static struct snd_soc_device *wm8971_socdev; | ||
716 | 688 | ||
717 | #if defined (CONFIG_I2C) || defined (CONFIG_I2C_MODULE) | 689 | /* power down chip */ |
690 | static int wm8971_remove(struct snd_soc_codec *codec) | ||
691 | { | ||
692 | wm8971_set_bias_level(codec, SND_SOC_BIAS_OFF); | ||
693 | |||
694 | if (wm8971_workq) | ||
695 | destroy_workqueue(wm8971_workq); | ||
696 | return 0; | ||
697 | } | ||
718 | 698 | ||
719 | static int wm8971_i2c_probe(struct i2c_client *i2c, | 699 | static struct snd_soc_codec_driver soc_codec_dev_wm8971 = { |
720 | const struct i2c_device_id *id) | 700 | .probe = wm8971_probe, |
701 | .remove = wm8971_remove, | ||
702 | .suspend = wm8971_suspend, | ||
703 | .resume = wm8971_resume, | ||
704 | .set_bias_level = wm8971_set_bias_level, | ||
705 | .reg_cache_size = ARRAY_SIZE(wm8971_reg), | ||
706 | .reg_word_size = sizeof(u16), | ||
707 | .reg_cache_default = wm8971_reg, | ||
708 | }; | ||
709 | |||
710 | #if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE) | ||
711 | static __devinit int wm8971_i2c_probe(struct i2c_client *i2c, | ||
712 | const struct i2c_device_id *id) | ||
721 | { | 713 | { |
722 | struct snd_soc_device *socdev = wm8971_socdev; | 714 | struct wm8971_priv *wm8971; |
723 | struct snd_soc_codec *codec = socdev->card->codec; | ||
724 | int ret; | 715 | int ret; |
725 | 716 | ||
726 | i2c_set_clientdata(i2c, codec); | 717 | wm8971 = kzalloc(sizeof(struct wm8971_priv), GFP_KERNEL); |
718 | if (wm8971 == NULL) | ||
719 | return -ENOMEM; | ||
727 | 720 | ||
728 | codec->control_data = i2c; | 721 | i2c_set_clientdata(i2c, wm8971); |
729 | 722 | ||
730 | ret = wm8971_init(socdev, SND_SOC_I2C); | 723 | ret = snd_soc_register_codec(&i2c->dev, |
724 | &soc_codec_dev_wm8971, &wm8971_dai, 1); | ||
731 | if (ret < 0) | 725 | if (ret < 0) |
732 | pr_err("failed to initialise WM8971\n"); | 726 | kfree(wm8971); |
733 | |||
734 | return ret; | 727 | return ret; |
735 | } | 728 | } |
736 | 729 | ||
737 | static int wm8971_i2c_remove(struct i2c_client *client) | 730 | static __devexit int wm8971_i2c_remove(struct i2c_client *client) |
738 | { | 731 | { |
739 | struct snd_soc_codec *codec = i2c_get_clientdata(client); | 732 | snd_soc_unregister_codec(&client->dev); |
740 | kfree(codec->reg_cache); | 733 | kfree(i2c_get_clientdata(client)); |
741 | return 0; | 734 | return 0; |
742 | } | 735 | } |
743 | 736 | ||
@@ -749,148 +742,34 @@ MODULE_DEVICE_TABLE(i2c, wm8971_i2c_id); | |||
749 | 742 | ||
750 | static struct i2c_driver wm8971_i2c_driver = { | 743 | static struct i2c_driver wm8971_i2c_driver = { |
751 | .driver = { | 744 | .driver = { |
752 | .name = "WM8971 I2C Codec", | 745 | .name = "wm8971-codec", |
753 | .owner = THIS_MODULE, | 746 | .owner = THIS_MODULE, |
754 | }, | 747 | }, |
755 | .probe = wm8971_i2c_probe, | 748 | .probe = wm8971_i2c_probe, |
756 | .remove = wm8971_i2c_remove, | 749 | .remove = __devexit_p(wm8971_i2c_remove), |
757 | .id_table = wm8971_i2c_id, | 750 | .id_table = wm8971_i2c_id, |
758 | }; | 751 | }; |
759 | |||
760 | static int wm8971_add_i2c_device(struct platform_device *pdev, | ||
761 | const struct wm8971_setup_data *setup) | ||
762 | { | ||
763 | struct i2c_board_info info; | ||
764 | struct i2c_adapter *adapter; | ||
765 | struct i2c_client *client; | ||
766 | int ret; | ||
767 | |||
768 | ret = i2c_add_driver(&wm8971_i2c_driver); | ||
769 | if (ret != 0) { | ||
770 | dev_err(&pdev->dev, "can't add i2c driver\n"); | ||
771 | return ret; | ||
772 | } | ||
773 | |||
774 | memset(&info, 0, sizeof(struct i2c_board_info)); | ||
775 | info.addr = setup->i2c_address; | ||
776 | strlcpy(info.type, "wm8971", I2C_NAME_SIZE); | ||
777 | |||
778 | adapter = i2c_get_adapter(setup->i2c_bus); | ||
779 | if (!adapter) { | ||
780 | dev_err(&pdev->dev, "can't get i2c adapter %d\n", | ||
781 | setup->i2c_bus); | ||
782 | goto err_driver; | ||
783 | } | ||
784 | |||
785 | client = i2c_new_device(adapter, &info); | ||
786 | i2c_put_adapter(adapter); | ||
787 | if (!client) { | ||
788 | dev_err(&pdev->dev, "can't add i2c device at 0x%x\n", | ||
789 | (unsigned int)info.addr); | ||
790 | goto err_driver; | ||
791 | } | ||
792 | |||
793 | return 0; | ||
794 | |||
795 | err_driver: | ||
796 | i2c_del_driver(&wm8971_i2c_driver); | ||
797 | return -ENODEV; | ||
798 | } | ||
799 | |||
800 | #endif | 752 | #endif |
801 | 753 | ||
802 | static int wm8971_probe(struct platform_device *pdev) | 754 | static int __init wm8971_modinit(void) |
803 | { | 755 | { |
804 | struct snd_soc_device *socdev = platform_get_drvdata(pdev); | ||
805 | struct wm8971_setup_data *setup; | ||
806 | struct snd_soc_codec *codec; | ||
807 | struct wm8971_priv *wm8971; | ||
808 | int ret = 0; | 756 | int ret = 0; |
809 | 757 | #if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE) | |
810 | pr_info("WM8971 Audio Codec %s", WM8971_VERSION); | 758 | ret = i2c_add_driver(&wm8971_i2c_driver); |
811 | |||
812 | setup = socdev->codec_data; | ||
813 | codec = kzalloc(sizeof(struct snd_soc_codec), GFP_KERNEL); | ||
814 | if (codec == NULL) | ||
815 | return -ENOMEM; | ||
816 | |||
817 | wm8971 = kzalloc(sizeof(struct wm8971_priv), GFP_KERNEL); | ||
818 | if (wm8971 == NULL) { | ||
819 | kfree(codec); | ||
820 | return -ENOMEM; | ||
821 | } | ||
822 | |||
823 | snd_soc_codec_set_drvdata(codec, wm8971); | ||
824 | socdev->card->codec = codec; | ||
825 | mutex_init(&codec->mutex); | ||
826 | INIT_LIST_HEAD(&codec->dapm_widgets); | ||
827 | INIT_LIST_HEAD(&codec->dapm_paths); | ||
828 | wm8971_socdev = socdev; | ||
829 | |||
830 | INIT_DELAYED_WORK(&codec->delayed_work, wm8971_work); | ||
831 | wm8971_workq = create_workqueue("wm8971"); | ||
832 | if (wm8971_workq == NULL) { | ||
833 | kfree(snd_soc_codec_get_drvdata(codec)); | ||
834 | kfree(codec); | ||
835 | return -ENOMEM; | ||
836 | } | ||
837 | |||
838 | #if defined (CONFIG_I2C) || defined (CONFIG_I2C_MODULE) | ||
839 | if (setup->i2c_address) { | ||
840 | ret = wm8971_add_i2c_device(pdev, setup); | ||
841 | } | ||
842 | #endif | ||
843 | /* Add other interfaces here */ | ||
844 | |||
845 | if (ret != 0) { | 759 | if (ret != 0) { |
846 | destroy_workqueue(wm8971_workq); | 760 | printk(KERN_ERR "Failed to register WM8971 I2C driver: %d\n", |
847 | kfree(snd_soc_codec_get_drvdata(codec)); | 761 | ret); |
848 | kfree(codec); | ||
849 | } | 762 | } |
850 | |||
851 | return ret; | ||
852 | } | ||
853 | |||
854 | /* power down chip */ | ||
855 | static int wm8971_remove(struct platform_device *pdev) | ||
856 | { | ||
857 | struct snd_soc_device *socdev = platform_get_drvdata(pdev); | ||
858 | struct snd_soc_codec *codec = socdev->card->codec; | ||
859 | |||
860 | if (codec->control_data) | ||
861 | wm8971_set_bias_level(codec, SND_SOC_BIAS_OFF); | ||
862 | if (wm8971_workq) | ||
863 | destroy_workqueue(wm8971_workq); | ||
864 | snd_soc_free_pcms(socdev); | ||
865 | snd_soc_dapm_free(socdev); | ||
866 | #if defined (CONFIG_I2C) || defined (CONFIG_I2C_MODULE) | ||
867 | i2c_unregister_device(codec->control_data); | ||
868 | i2c_del_driver(&wm8971_i2c_driver); | ||
869 | #endif | 763 | #endif |
870 | kfree(snd_soc_codec_get_drvdata(codec)); | 764 | return ret; |
871 | kfree(codec); | ||
872 | |||
873 | return 0; | ||
874 | } | ||
875 | |||
876 | struct snd_soc_codec_device soc_codec_dev_wm8971 = { | ||
877 | .probe = wm8971_probe, | ||
878 | .remove = wm8971_remove, | ||
879 | .suspend = wm8971_suspend, | ||
880 | .resume = wm8971_resume, | ||
881 | }; | ||
882 | |||
883 | EXPORT_SYMBOL_GPL(soc_codec_dev_wm8971); | ||
884 | |||
885 | static int __init wm8971_modinit(void) | ||
886 | { | ||
887 | return snd_soc_register_dai(&wm8971_dai); | ||
888 | } | 765 | } |
889 | module_init(wm8971_modinit); | 766 | module_init(wm8971_modinit); |
890 | 767 | ||
891 | static void __exit wm8971_exit(void) | 768 | static void __exit wm8971_exit(void) |
892 | { | 769 | { |
893 | snd_soc_unregister_dai(&wm8971_dai); | 770 | #if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE) |
771 | i2c_del_driver(&wm8971_i2c_driver); | ||
772 | #endif | ||
894 | } | 773 | } |
895 | module_exit(wm8971_exit); | 774 | module_exit(wm8971_exit); |
896 | 775 | ||
diff --git a/sound/soc/codecs/wm8971.h b/sound/soc/codecs/wm8971.h index ef4f08f9f344..f31c38fddfc4 100644 --- a/sound/soc/codecs/wm8971.h +++ b/sound/soc/codecs/wm8971.h | |||
@@ -53,12 +53,4 @@ | |||
53 | 53 | ||
54 | #define WM8971_SYSCLK 0 | 54 | #define WM8971_SYSCLK 0 |
55 | 55 | ||
56 | struct wm8971_setup_data { | ||
57 | int i2c_bus; | ||
58 | unsigned short i2c_address; | ||
59 | }; | ||
60 | |||
61 | extern struct snd_soc_dai wm8971_dai; | ||
62 | extern struct snd_soc_codec_device soc_codec_dev_wm8971; | ||
63 | |||
64 | #endif | 56 | #endif |
diff --git a/sound/soc/codecs/wm8974.c b/sound/soc/codecs/wm8974.c index 1468fe10cbbe..e61728b7339f 100644 --- a/sound/soc/codecs/wm8974.c +++ b/sound/soc/codecs/wm8974.c | |||
@@ -51,12 +51,10 @@ static const u16 wm8974_reg[WM8974_CACHEREGNUM] = { | |||
51 | #define WM8974_POWER1_BUFIOEN 0x04 | 51 | #define WM8974_POWER1_BUFIOEN 0x04 |
52 | 52 | ||
53 | struct wm8974_priv { | 53 | struct wm8974_priv { |
54 | struct snd_soc_codec codec; | 54 | enum snd_soc_control_type control_type; |
55 | u16 reg_cache[WM8974_CACHEREGNUM]; | 55 | u16 reg_cache[WM8974_CACHEREGNUM]; |
56 | }; | 56 | }; |
57 | 57 | ||
58 | static struct snd_soc_codec *wm8974_codec; | ||
59 | |||
60 | #define wm8974_reset(c) snd_soc_write(c, WM8974_RESET, 0) | 58 | #define wm8974_reset(c) snd_soc_write(c, WM8974_RESET, 0) |
61 | 59 | ||
62 | static const char *wm8974_companding[] = {"Off", "NC", "u-law", "A-law" }; | 60 | static const char *wm8974_companding[] = {"Off", "NC", "u-law", "A-law" }; |
@@ -566,8 +564,8 @@ static struct snd_soc_dai_ops wm8974_ops = { | |||
566 | .set_pll = wm8974_set_dai_pll, | 564 | .set_pll = wm8974_set_dai_pll, |
567 | }; | 565 | }; |
568 | 566 | ||
569 | struct snd_soc_dai wm8974_dai = { | 567 | static struct snd_soc_dai_driver wm8974_dai = { |
570 | .name = "WM8974 HiFi", | 568 | .name = "wm8974-hifi", |
571 | .playback = { | 569 | .playback = { |
572 | .stream_name = "Playback", | 570 | .stream_name = "Playback", |
573 | .channels_min = 1, | 571 | .channels_min = 1, |
@@ -583,21 +581,15 @@ struct snd_soc_dai wm8974_dai = { | |||
583 | .ops = &wm8974_ops, | 581 | .ops = &wm8974_ops, |
584 | .symmetric_rates = 1, | 582 | .symmetric_rates = 1, |
585 | }; | 583 | }; |
586 | EXPORT_SYMBOL_GPL(wm8974_dai); | ||
587 | 584 | ||
588 | static int wm8974_suspend(struct platform_device *pdev, pm_message_t state) | 585 | static int wm8974_suspend(struct snd_soc_codec *codec, pm_message_t state) |
589 | { | 586 | { |
590 | struct snd_soc_device *socdev = platform_get_drvdata(pdev); | ||
591 | struct snd_soc_codec *codec = socdev->card->codec; | ||
592 | |||
593 | wm8974_set_bias_level(codec, SND_SOC_BIAS_OFF); | 587 | wm8974_set_bias_level(codec, SND_SOC_BIAS_OFF); |
594 | return 0; | 588 | return 0; |
595 | } | 589 | } |
596 | 590 | ||
597 | static int wm8974_resume(struct platform_device *pdev) | 591 | static int wm8974_resume(struct snd_soc_codec *codec) |
598 | { | 592 | { |
599 | struct snd_soc_device *socdev = platform_get_drvdata(pdev); | ||
600 | struct snd_soc_codec *codec = socdev->card->codec; | ||
601 | int i; | 593 | int i; |
602 | u8 data[2]; | 594 | u8 data[2]; |
603 | u16 *cache = codec->reg_cache; | 595 | u16 *cache = codec->reg_cache; |
@@ -613,156 +605,73 @@ static int wm8974_resume(struct platform_device *pdev) | |||
613 | return 0; | 605 | return 0; |
614 | } | 606 | } |
615 | 607 | ||
616 | static int wm8974_probe(struct platform_device *pdev) | 608 | static int wm8974_probe(struct snd_soc_codec *codec) |
617 | { | 609 | { |
618 | struct snd_soc_device *socdev = platform_get_drvdata(pdev); | 610 | struct wm8974_priv *wm8974 = snd_soc_codec_get_drvdata(codec); |
619 | struct snd_soc_codec *codec; | ||
620 | int ret = 0; | 611 | int ret = 0; |
621 | 612 | ||
622 | if (wm8974_codec == NULL) { | 613 | ret = snd_soc_codec_set_cache_io(codec, 7, 9, SND_SOC_I2C); |
623 | dev_err(&pdev->dev, "Codec device not registered\n"); | 614 | if (ret < 0) { |
624 | return -ENODEV; | 615 | dev_err(codec->dev, "Failed to set cache I/O: %d\n", ret); |
616 | return ret; | ||
625 | } | 617 | } |
626 | 618 | ||
627 | socdev->card->codec = wm8974_codec; | 619 | ret = wm8974_reset(codec); |
628 | codec = wm8974_codec; | ||
629 | |||
630 | /* register pcms */ | ||
631 | ret = snd_soc_new_pcms(socdev, SNDRV_DEFAULT_IDX1, SNDRV_DEFAULT_STR1); | ||
632 | if (ret < 0) { | 620 | if (ret < 0) { |
633 | dev_err(codec->dev, "failed to create pcms: %d\n", ret); | 621 | dev_err(codec->dev, "Failed to issue reset\n"); |
634 | goto pcm_err; | 622 | return ret; |
635 | } | 623 | } |
636 | 624 | ||
625 | wm8974_set_bias_level(codec, SND_SOC_BIAS_STANDBY); | ||
637 | snd_soc_add_controls(codec, wm8974_snd_controls, | 626 | snd_soc_add_controls(codec, wm8974_snd_controls, |
638 | ARRAY_SIZE(wm8974_snd_controls)); | 627 | ARRAY_SIZE(wm8974_snd_controls)); |
639 | wm8974_add_widgets(codec); | 628 | wm8974_add_widgets(codec); |
640 | 629 | ||
641 | return ret; | 630 | return ret; |
642 | |||
643 | pcm_err: | ||
644 | return ret; | ||
645 | } | 631 | } |
646 | 632 | ||
647 | /* power down chip */ | 633 | /* power down chip */ |
648 | static int wm8974_remove(struct platform_device *pdev) | 634 | static int wm8974_remove(struct snd_soc_codec *codec) |
649 | { | 635 | { |
650 | struct snd_soc_device *socdev = platform_get_drvdata(pdev); | 636 | wm8974_set_bias_level(codec, SND_SOC_BIAS_OFF); |
651 | |||
652 | snd_soc_free_pcms(socdev); | ||
653 | snd_soc_dapm_free(socdev); | ||
654 | |||
655 | return 0; | 637 | return 0; |
656 | } | 638 | } |
657 | 639 | ||
658 | struct snd_soc_codec_device soc_codec_dev_wm8974 = { | 640 | static struct snd_soc_codec_driver soc_codec_dev_wm8974 = { |
659 | .probe = wm8974_probe, | 641 | .probe = wm8974_probe, |
660 | .remove = wm8974_remove, | 642 | .remove = wm8974_remove, |
661 | .suspend = wm8974_suspend, | 643 | .suspend = wm8974_suspend, |
662 | .resume = wm8974_resume, | 644 | .resume = wm8974_resume, |
645 | .set_bias_level = wm8974_set_bias_level, | ||
646 | .reg_cache_size = ARRAY_SIZE(wm8974_reg), | ||
647 | .reg_word_size = sizeof(u16), | ||
648 | .reg_cache_default = wm8974_reg, | ||
663 | }; | 649 | }; |
664 | EXPORT_SYMBOL_GPL(soc_codec_dev_wm8974); | ||
665 | |||
666 | static __devinit int wm8974_register(struct wm8974_priv *wm8974) | ||
667 | { | ||
668 | int ret; | ||
669 | struct snd_soc_codec *codec = &wm8974->codec; | ||
670 | |||
671 | if (wm8974_codec) { | ||
672 | dev_err(codec->dev, "Another WM8974 is registered\n"); | ||
673 | ret = -EINVAL; | ||
674 | goto err; | ||
675 | } | ||
676 | |||
677 | mutex_init(&codec->mutex); | ||
678 | INIT_LIST_HEAD(&codec->dapm_widgets); | ||
679 | INIT_LIST_HEAD(&codec->dapm_paths); | ||
680 | |||
681 | snd_soc_codec_set_drvdata(codec, wm8974); | ||
682 | codec->name = "WM8974"; | ||
683 | codec->owner = THIS_MODULE; | ||
684 | codec->bias_level = SND_SOC_BIAS_OFF; | ||
685 | codec->set_bias_level = wm8974_set_bias_level; | ||
686 | codec->dai = &wm8974_dai; | ||
687 | codec->num_dai = 1; | ||
688 | codec->reg_cache_size = WM8974_CACHEREGNUM; | ||
689 | codec->reg_cache = &wm8974->reg_cache; | ||
690 | |||
691 | ret = snd_soc_codec_set_cache_io(codec, 7, 9, SND_SOC_I2C); | ||
692 | if (ret < 0) { | ||
693 | dev_err(codec->dev, "Failed to set cache I/O: %d\n", ret); | ||
694 | goto err; | ||
695 | } | ||
696 | |||
697 | memcpy(codec->reg_cache, wm8974_reg, sizeof(wm8974_reg)); | ||
698 | |||
699 | ret = wm8974_reset(codec); | ||
700 | if (ret < 0) { | ||
701 | dev_err(codec->dev, "Failed to issue reset\n"); | ||
702 | goto err; | ||
703 | } | ||
704 | |||
705 | wm8974_dai.dev = codec->dev; | ||
706 | |||
707 | wm8974_set_bias_level(codec, SND_SOC_BIAS_STANDBY); | ||
708 | |||
709 | wm8974_codec = codec; | ||
710 | |||
711 | ret = snd_soc_register_codec(codec); | ||
712 | if (ret != 0) { | ||
713 | dev_err(codec->dev, "Failed to register codec: %d\n", ret); | ||
714 | goto err; | ||
715 | } | ||
716 | |||
717 | ret = snd_soc_register_dai(&wm8974_dai); | ||
718 | if (ret != 0) { | ||
719 | dev_err(codec->dev, "Failed to register DAI: %d\n", ret); | ||
720 | goto err_codec; | ||
721 | } | ||
722 | |||
723 | return 0; | ||
724 | |||
725 | err_codec: | ||
726 | snd_soc_unregister_codec(codec); | ||
727 | err: | ||
728 | kfree(wm8974); | ||
729 | return ret; | ||
730 | } | ||
731 | |||
732 | static __devexit void wm8974_unregister(struct wm8974_priv *wm8974) | ||
733 | { | ||
734 | wm8974_set_bias_level(&wm8974->codec, SND_SOC_BIAS_OFF); | ||
735 | snd_soc_unregister_dai(&wm8974_dai); | ||
736 | snd_soc_unregister_codec(&wm8974->codec); | ||
737 | kfree(wm8974); | ||
738 | wm8974_codec = NULL; | ||
739 | } | ||
740 | 650 | ||
651 | #if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE) | ||
741 | static __devinit int wm8974_i2c_probe(struct i2c_client *i2c, | 652 | static __devinit int wm8974_i2c_probe(struct i2c_client *i2c, |
742 | const struct i2c_device_id *id) | 653 | const struct i2c_device_id *id) |
743 | { | 654 | { |
744 | struct wm8974_priv *wm8974; | 655 | struct wm8974_priv *wm8974; |
745 | struct snd_soc_codec *codec; | 656 | int ret; |
746 | 657 | ||
747 | wm8974 = kzalloc(sizeof(struct wm8974_priv), GFP_KERNEL); | 658 | wm8974 = kzalloc(sizeof(struct wm8974_priv), GFP_KERNEL); |
748 | if (wm8974 == NULL) | 659 | if (wm8974 == NULL) |
749 | return -ENOMEM; | 660 | return -ENOMEM; |
750 | 661 | ||
751 | codec = &wm8974->codec; | ||
752 | codec->hw_write = (hw_write_t)i2c_master_send; | ||
753 | |||
754 | i2c_set_clientdata(i2c, wm8974); | 662 | i2c_set_clientdata(i2c, wm8974); |
755 | codec->control_data = i2c; | ||
756 | |||
757 | codec->dev = &i2c->dev; | ||
758 | 663 | ||
759 | return wm8974_register(wm8974); | 664 | ret = snd_soc_register_codec(&i2c->dev, |
665 | &soc_codec_dev_wm8974, &wm8974_dai, 1); | ||
666 | if (ret < 0) | ||
667 | kfree(wm8974); | ||
668 | return ret; | ||
760 | } | 669 | } |
761 | 670 | ||
762 | static __devexit int wm8974_i2c_remove(struct i2c_client *client) | 671 | static __devexit int wm8974_i2c_remove(struct i2c_client *client) |
763 | { | 672 | { |
764 | struct wm8974_priv *wm8974 = i2c_get_clientdata(client); | 673 | snd_soc_unregister_codec(&client->dev); |
765 | wm8974_unregister(wm8974); | 674 | kfree(i2c_get_clientdata(client)); |
766 | return 0; | 675 | return 0; |
767 | } | 676 | } |
768 | 677 | ||
@@ -774,23 +683,34 @@ MODULE_DEVICE_TABLE(i2c, wm8974_i2c_id); | |||
774 | 683 | ||
775 | static struct i2c_driver wm8974_i2c_driver = { | 684 | static struct i2c_driver wm8974_i2c_driver = { |
776 | .driver = { | 685 | .driver = { |
777 | .name = "WM8974", | 686 | .name = "wm8974-codec", |
778 | .owner = THIS_MODULE, | 687 | .owner = THIS_MODULE, |
779 | }, | 688 | }, |
780 | .probe = wm8974_i2c_probe, | 689 | .probe = wm8974_i2c_probe, |
781 | .remove = __devexit_p(wm8974_i2c_remove), | 690 | .remove = __devexit_p(wm8974_i2c_remove), |
782 | .id_table = wm8974_i2c_id, | 691 | .id_table = wm8974_i2c_id, |
783 | }; | 692 | }; |
693 | #endif | ||
784 | 694 | ||
785 | static int __init wm8974_modinit(void) | 695 | static int __init wm8974_modinit(void) |
786 | { | 696 | { |
787 | return i2c_add_driver(&wm8974_i2c_driver); | 697 | int ret = 0; |
698 | #if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE) | ||
699 | ret = i2c_add_driver(&wm8974_i2c_driver); | ||
700 | if (ret != 0) { | ||
701 | printk(KERN_ERR "Failed to register wm8974 I2C driver: %d\n", | ||
702 | ret); | ||
703 | } | ||
704 | #endif | ||
705 | return ret; | ||
788 | } | 706 | } |
789 | module_init(wm8974_modinit); | 707 | module_init(wm8974_modinit); |
790 | 708 | ||
791 | static void __exit wm8974_exit(void) | 709 | static void __exit wm8974_exit(void) |
792 | { | 710 | { |
711 | #if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE) | ||
793 | i2c_del_driver(&wm8974_i2c_driver); | 712 | i2c_del_driver(&wm8974_i2c_driver); |
713 | #endif | ||
794 | } | 714 | } |
795 | module_exit(wm8974_exit); | 715 | module_exit(wm8974_exit); |
796 | 716 | ||
diff --git a/sound/soc/codecs/wm8974.h b/sound/soc/codecs/wm8974.h index 896a7f0f3fc4..3c94e7bb55a6 100644 --- a/sound/soc/codecs/wm8974.h +++ b/sound/soc/codecs/wm8974.h | |||
@@ -83,7 +83,4 @@ | |||
83 | #define WM8974_MCLKDIV_8 (6 << 5) | 83 | #define WM8974_MCLKDIV_8 (6 << 5) |
84 | #define WM8974_MCLKDIV_12 (7 << 5) | 84 | #define WM8974_MCLKDIV_12 (7 << 5) |
85 | 85 | ||
86 | extern struct snd_soc_dai wm8974_dai; | ||
87 | extern struct snd_soc_codec_device soc_codec_dev_wm8974; | ||
88 | |||
89 | #endif | 86 | #endif |
diff --git a/sound/soc/codecs/wm8978.c b/sound/soc/codecs/wm8978.c index 8a1ad778e7e3..676a4306cc87 100644 --- a/sound/soc/codecs/wm8978.c +++ b/sound/soc/codecs/wm8978.c | |||
@@ -31,8 +31,6 @@ | |||
31 | 31 | ||
32 | #include "wm8978.h" | 32 | #include "wm8978.h" |
33 | 33 | ||
34 | static struct snd_soc_codec *wm8978_codec; | ||
35 | |||
36 | /* wm8978 register cache. Note that register 0 is not included in the cache. */ | 34 | /* wm8978 register cache. Note that register 0 is not included in the cache. */ |
37 | static const u16 wm8978_reg[WM8978_CACHEREGNUM] = { | 35 | static const u16 wm8978_reg[WM8978_CACHEREGNUM] = { |
38 | 0x0000, 0x0000, 0x0000, 0x0000, /* 0x00...0x03 */ | 36 | 0x0000, 0x0000, 0x0000, 0x0000, /* 0x00...0x03 */ |
@@ -54,7 +52,8 @@ static const u16 wm8978_reg[WM8978_CACHEREGNUM] = { | |||
54 | 52 | ||
55 | /* codec private data */ | 53 | /* codec private data */ |
56 | struct wm8978_priv { | 54 | struct wm8978_priv { |
57 | struct snd_soc_codec codec; | 55 | enum snd_soc_control_type control_type; |
56 | void *control_data; | ||
58 | unsigned int f_pllout; | 57 | unsigned int f_pllout; |
59 | unsigned int f_mclk; | 58 | unsigned int f_mclk; |
60 | unsigned int f_256fs; | 59 | unsigned int f_256fs; |
@@ -374,8 +373,8 @@ struct wm8978_pll_div { | |||
374 | 373 | ||
375 | #define FIXED_PLL_SIZE (1 << 24) | 374 | #define FIXED_PLL_SIZE (1 << 24) |
376 | 375 | ||
377 | static void pll_factors(struct wm8978_pll_div *pll_div, unsigned int target, | 376 | static void pll_factors(struct snd_soc_codec *codec, |
378 | unsigned int source) | 377 | struct wm8978_pll_div *pll_div, unsigned int target, unsigned int source) |
379 | { | 378 | { |
380 | u64 k_part; | 379 | u64 k_part; |
381 | unsigned int k, n_div, n_mod; | 380 | unsigned int k, n_div, n_mod; |
@@ -390,7 +389,7 @@ static void pll_factors(struct wm8978_pll_div *pll_div, unsigned int target, | |||
390 | } | 389 | } |
391 | 390 | ||
392 | if (n_div < 6 || n_div > 12) | 391 | if (n_div < 6 || n_div > 12) |
393 | dev_warn(wm8978_codec->dev, | 392 | dev_warn(codec->dev, |
394 | "WM8978 N value exceeds recommended range! N = %u\n", | 393 | "WM8978 N value exceeds recommended range! N = %u\n", |
395 | n_div); | 394 | n_div); |
396 | 395 | ||
@@ -505,7 +504,7 @@ static int wm8978_configure_pll(struct snd_soc_codec *codec) | |||
505 | dev_dbg(codec->dev, "%s: f_MCLK=%uHz, f_PLLOUT=%uHz\n", __func__, | 504 | dev_dbg(codec->dev, "%s: f_MCLK=%uHz, f_PLLOUT=%uHz\n", __func__, |
506 | wm8978->f_mclk, wm8978->f_pllout); | 505 | wm8978->f_mclk, wm8978->f_pllout); |
507 | 506 | ||
508 | pll_factors(&pll_div, f2, wm8978->f_mclk); | 507 | pll_factors(codec, &pll_div, f2, wm8978->f_mclk); |
509 | 508 | ||
510 | dev_dbg(codec->dev, "%s: calculated PLL N=0x%x, K=0x%x, div2=%d\n", | 509 | dev_dbg(codec->dev, "%s: calculated PLL N=0x%x, K=0x%x, div2=%d\n", |
511 | __func__, pll_div.n, pll_div.k, pll_div.div2); | 510 | __func__, pll_div.n, pll_div.k, pll_div.div2); |
@@ -690,8 +689,7 @@ static int wm8978_hw_params(struct snd_pcm_substream *substream, | |||
690 | struct snd_soc_dai *dai) | 689 | struct snd_soc_dai *dai) |
691 | { | 690 | { |
692 | struct snd_soc_pcm_runtime *rtd = substream->private_data; | 691 | struct snd_soc_pcm_runtime *rtd = substream->private_data; |
693 | struct snd_soc_device *socdev = rtd->socdev; | 692 | struct snd_soc_codec *codec = rtd->codec; |
694 | struct snd_soc_codec *codec = socdev->card->codec; | ||
695 | struct wm8978_priv *wm8978 = snd_soc_codec_get_drvdata(codec); | 693 | struct wm8978_priv *wm8978 = snd_soc_codec_get_drvdata(codec); |
696 | /* Word length mask = 0x60 */ | 694 | /* Word length mask = 0x60 */ |
697 | u16 iface_ctl = snd_soc_read(codec, WM8978_AUDIO_INTERFACE) & ~0x60; | 695 | u16 iface_ctl = snd_soc_read(codec, WM8978_AUDIO_INTERFACE) & ~0x60; |
@@ -875,9 +873,8 @@ static struct snd_soc_dai_ops wm8978_dai_ops = { | |||
875 | }; | 873 | }; |
876 | 874 | ||
877 | /* Also supports 12kHz */ | 875 | /* Also supports 12kHz */ |
878 | struct snd_soc_dai wm8978_dai = { | 876 | static struct snd_soc_dai_driver wm8978_dai = { |
879 | .name = "WM8978 HiFi", | 877 | .name = "wm8978-hifi", |
880 | .id = 1, | ||
881 | .playback = { | 878 | .playback = { |
882 | .stream_name = "Playback", | 879 | .stream_name = "Playback", |
883 | .channels_min = 1, | 880 | .channels_min = 1, |
@@ -894,13 +891,9 @@ struct snd_soc_dai wm8978_dai = { | |||
894 | }, | 891 | }, |
895 | .ops = &wm8978_dai_ops, | 892 | .ops = &wm8978_dai_ops, |
896 | }; | 893 | }; |
897 | EXPORT_SYMBOL_GPL(wm8978_dai); | ||
898 | 894 | ||
899 | static int wm8978_suspend(struct platform_device *pdev, pm_message_t state) | 895 | static int wm8978_suspend(struct snd_soc_codec *codec, pm_message_t state) |
900 | { | 896 | { |
901 | struct snd_soc_device *socdev = platform_get_drvdata(pdev); | ||
902 | struct snd_soc_codec *codec = socdev->card->codec; | ||
903 | |||
904 | wm8978_set_bias_level(codec, SND_SOC_BIAS_OFF); | 897 | wm8978_set_bias_level(codec, SND_SOC_BIAS_OFF); |
905 | /* Also switch PLL off */ | 898 | /* Also switch PLL off */ |
906 | snd_soc_write(codec, WM8978_POWER_MANAGEMENT_1, 0); | 899 | snd_soc_write(codec, WM8978_POWER_MANAGEMENT_1, 0); |
@@ -908,10 +901,8 @@ static int wm8978_suspend(struct platform_device *pdev, pm_message_t state) | |||
908 | return 0; | 901 | return 0; |
909 | } | 902 | } |
910 | 903 | ||
911 | static int wm8978_resume(struct platform_device *pdev) | 904 | static int wm8978_resume(struct snd_soc_codec *codec) |
912 | { | 905 | { |
913 | struct snd_soc_device *socdev = platform_get_drvdata(pdev); | ||
914 | struct snd_soc_codec *codec = socdev->card->codec; | ||
915 | struct wm8978_priv *wm8978 = snd_soc_codec_get_drvdata(codec); | 906 | struct wm8978_priv *wm8978 = snd_soc_codec_get_drvdata(codec); |
916 | int i; | 907 | int i; |
917 | u16 *cache = codec->reg_cache; | 908 | u16 *cache = codec->reg_cache; |
@@ -933,54 +924,6 @@ static int wm8978_resume(struct platform_device *pdev) | |||
933 | return 0; | 924 | return 0; |
934 | } | 925 | } |
935 | 926 | ||
936 | static int wm8978_probe(struct platform_device *pdev) | ||
937 | { | ||
938 | struct snd_soc_device *socdev = platform_get_drvdata(pdev); | ||
939 | struct snd_soc_codec *codec; | ||
940 | int ret = 0; | ||
941 | |||
942 | if (wm8978_codec == NULL) { | ||
943 | dev_err(&pdev->dev, "Codec device not registered\n"); | ||
944 | return -ENODEV; | ||
945 | } | ||
946 | |||
947 | socdev->card->codec = wm8978_codec; | ||
948 | codec = wm8978_codec; | ||
949 | |||
950 | /* register pcms */ | ||
951 | ret = snd_soc_new_pcms(socdev, SNDRV_DEFAULT_IDX1, SNDRV_DEFAULT_STR1); | ||
952 | if (ret < 0) { | ||
953 | dev_err(codec->dev, "failed to create pcms: %d\n", ret); | ||
954 | goto pcm_err; | ||
955 | } | ||
956 | |||
957 | snd_soc_add_controls(codec, wm8978_snd_controls, | ||
958 | ARRAY_SIZE(wm8978_snd_controls)); | ||
959 | wm8978_add_widgets(codec); | ||
960 | |||
961 | pcm_err: | ||
962 | return ret; | ||
963 | } | ||
964 | |||
965 | /* power down chip */ | ||
966 | static int wm8978_remove(struct platform_device *pdev) | ||
967 | { | ||
968 | struct snd_soc_device *socdev = platform_get_drvdata(pdev); | ||
969 | |||
970 | snd_soc_free_pcms(socdev); | ||
971 | snd_soc_dapm_free(socdev); | ||
972 | |||
973 | return 0; | ||
974 | } | ||
975 | |||
976 | struct snd_soc_codec_device soc_codec_dev_wm8978 = { | ||
977 | .probe = wm8978_probe, | ||
978 | .remove = wm8978_remove, | ||
979 | .suspend = wm8978_suspend, | ||
980 | .resume = wm8978_resume, | ||
981 | }; | ||
982 | EXPORT_SYMBOL_GPL(soc_codec_dev_wm8978); | ||
983 | |||
984 | /* | 927 | /* |
985 | * These registers contain an "update" bit - bit 8. This means, for example, | 928 | * These registers contain an "update" bit - bit 8. This means, for example, |
986 | * that one can write new DAC digital volume for both channels, but only when | 929 | * that one can write new DAC digital volume for both channels, but only when |
@@ -1000,44 +943,23 @@ static const int update_reg[] = { | |||
1000 | WM8978_ROUT2_SPK_CONTROL, | 943 | WM8978_ROUT2_SPK_CONTROL, |
1001 | }; | 944 | }; |
1002 | 945 | ||
1003 | static __devinit int wm8978_register(struct wm8978_priv *wm8978) | 946 | static int wm8978_probe(struct snd_soc_codec *codec) |
1004 | { | 947 | { |
1005 | int ret, i; | 948 | struct wm8978_priv *wm8978 = snd_soc_codec_get_drvdata(codec); |
1006 | struct snd_soc_codec *codec = &wm8978->codec; | 949 | int ret = 0, i; |
1007 | |||
1008 | if (wm8978_codec) { | ||
1009 | dev_err(codec->dev, "Another WM8978 is registered\n"); | ||
1010 | return -EINVAL; | ||
1011 | } | ||
1012 | 950 | ||
1013 | /* | 951 | /* |
1014 | * Set default system clock to PLL, it is more precise, this is also the | 952 | * Set default system clock to PLL, it is more precise, this is also the |
1015 | * default hardware setting | 953 | * default hardware setting |
1016 | */ | 954 | */ |
1017 | wm8978->sysclk = WM8978_PLL; | 955 | wm8978->sysclk = WM8978_PLL; |
1018 | 956 | codec->control_data = wm8978->control_data; | |
1019 | mutex_init(&codec->mutex); | ||
1020 | INIT_LIST_HEAD(&codec->dapm_widgets); | ||
1021 | INIT_LIST_HEAD(&codec->dapm_paths); | ||
1022 | |||
1023 | snd_soc_codec_set_drvdata(codec, wm8978); | ||
1024 | codec->name = "WM8978"; | ||
1025 | codec->owner = THIS_MODULE; | ||
1026 | codec->bias_level = SND_SOC_BIAS_OFF; | ||
1027 | codec->set_bias_level = wm8978_set_bias_level; | ||
1028 | codec->dai = &wm8978_dai; | ||
1029 | codec->num_dai = 1; | ||
1030 | codec->reg_cache_size = WM8978_CACHEREGNUM; | ||
1031 | codec->reg_cache = &wm8978->reg_cache; | ||
1032 | |||
1033 | ret = snd_soc_codec_set_cache_io(codec, 7, 9, SND_SOC_I2C); | 957 | ret = snd_soc_codec_set_cache_io(codec, 7, 9, SND_SOC_I2C); |
1034 | if (ret < 0) { | 958 | if (ret < 0) { |
1035 | dev_err(codec->dev, "Failed to set cache I/O: %d\n", ret); | 959 | dev_err(codec->dev, "Failed to set cache I/O: %d\n", ret); |
1036 | goto err; | 960 | return ret; |
1037 | } | 961 | } |
1038 | 962 | ||
1039 | memcpy(codec->reg_cache, wm8978_reg, sizeof(wm8978_reg)); | ||
1040 | |||
1041 | /* | 963 | /* |
1042 | * Set the update bit in all registers, that have one. This way all | 964 | * Set the update bit in all registers, that have one. This way all |
1043 | * writes to those registers will also cause the update bit to be | 965 | * writes to those registers will also cause the update bit to be |
@@ -1050,74 +972,61 @@ static __devinit int wm8978_register(struct wm8978_priv *wm8978) | |||
1050 | ret = snd_soc_write(codec, WM8978_RESET, 0); | 972 | ret = snd_soc_write(codec, WM8978_RESET, 0); |
1051 | if (ret < 0) { | 973 | if (ret < 0) { |
1052 | dev_err(codec->dev, "Failed to issue reset\n"); | 974 | dev_err(codec->dev, "Failed to issue reset\n"); |
1053 | goto err; | 975 | return ret; |
1054 | } | 976 | } |
1055 | 977 | ||
1056 | wm8978_dai.dev = codec->dev; | ||
1057 | |||
1058 | wm8978_set_bias_level(codec, SND_SOC_BIAS_STANDBY); | 978 | wm8978_set_bias_level(codec, SND_SOC_BIAS_STANDBY); |
1059 | 979 | ||
1060 | wm8978_codec = codec; | 980 | snd_soc_add_controls(codec, wm8978_snd_controls, |
1061 | 981 | ARRAY_SIZE(wm8978_snd_controls)); | |
1062 | ret = snd_soc_register_codec(codec); | 982 | wm8978_add_widgets(codec); |
1063 | if (ret != 0) { | ||
1064 | dev_err(codec->dev, "Failed to register codec: %d\n", ret); | ||
1065 | goto err; | ||
1066 | } | ||
1067 | |||
1068 | ret = snd_soc_register_dai(&wm8978_dai); | ||
1069 | if (ret != 0) { | ||
1070 | dev_err(codec->dev, "Failed to register DAI: %d\n", ret); | ||
1071 | goto err_codec; | ||
1072 | } | ||
1073 | 983 | ||
1074 | return 0; | 984 | return 0; |
1075 | |||
1076 | err_codec: | ||
1077 | snd_soc_unregister_codec(codec); | ||
1078 | err: | ||
1079 | return ret; | ||
1080 | } | 985 | } |
1081 | 986 | ||
1082 | static __devexit void wm8978_unregister(struct wm8978_priv *wm8978) | 987 | /* power down chip */ |
988 | static int wm8978_remove(struct snd_soc_codec *codec) | ||
1083 | { | 989 | { |
1084 | wm8978_set_bias_level(&wm8978->codec, SND_SOC_BIAS_OFF); | 990 | wm8978_set_bias_level(codec, SND_SOC_BIAS_OFF); |
1085 | snd_soc_unregister_dai(&wm8978_dai); | 991 | return 0; |
1086 | snd_soc_unregister_codec(&wm8978->codec); | ||
1087 | wm8978_codec = NULL; | ||
1088 | } | 992 | } |
1089 | 993 | ||
994 | static struct snd_soc_codec_driver soc_codec_dev_wm8978 = { | ||
995 | .probe = wm8978_probe, | ||
996 | .remove = wm8978_remove, | ||
997 | .suspend = wm8978_suspend, | ||
998 | .resume = wm8978_resume, | ||
999 | .set_bias_level = wm8978_set_bias_level, | ||
1000 | .reg_cache_size = ARRAY_SIZE(wm8978_reg), | ||
1001 | .reg_word_size = sizeof(u16), | ||
1002 | .reg_cache_default = wm8978_reg, | ||
1003 | }; | ||
1004 | |||
1005 | #if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE) | ||
1090 | static __devinit int wm8978_i2c_probe(struct i2c_client *i2c, | 1006 | static __devinit int wm8978_i2c_probe(struct i2c_client *i2c, |
1091 | const struct i2c_device_id *id) | 1007 | const struct i2c_device_id *id) |
1092 | { | 1008 | { |
1093 | int ret; | ||
1094 | struct wm8978_priv *wm8978; | 1009 | struct wm8978_priv *wm8978; |
1095 | struct snd_soc_codec *codec; | 1010 | int ret; |
1096 | 1011 | ||
1097 | wm8978 = kzalloc(sizeof(struct wm8978_priv), GFP_KERNEL); | 1012 | wm8978 = kzalloc(sizeof(struct wm8978_priv), GFP_KERNEL); |
1098 | if (wm8978 == NULL) | 1013 | if (wm8978 == NULL) |
1099 | return -ENOMEM; | 1014 | return -ENOMEM; |
1100 | 1015 | ||
1101 | codec = &wm8978->codec; | ||
1102 | codec->hw_write = (hw_write_t)i2c_master_send; | ||
1103 | |||
1104 | i2c_set_clientdata(i2c, wm8978); | 1016 | i2c_set_clientdata(i2c, wm8978); |
1105 | codec->control_data = i2c; | 1017 | wm8978->control_data = i2c; |
1106 | |||
1107 | codec->dev = &i2c->dev; | ||
1108 | 1018 | ||
1109 | ret = wm8978_register(wm8978); | 1019 | ret = snd_soc_register_codec(&i2c->dev, |
1020 | &soc_codec_dev_wm8978, &wm8978_dai, 1); | ||
1110 | if (ret < 0) | 1021 | if (ret < 0) |
1111 | kfree(wm8978); | 1022 | kfree(wm8978); |
1112 | |||
1113 | return ret; | 1023 | return ret; |
1114 | } | 1024 | } |
1115 | 1025 | ||
1116 | static __devexit int wm8978_i2c_remove(struct i2c_client *client) | 1026 | static __devexit int wm8978_i2c_remove(struct i2c_client *client) |
1117 | { | 1027 | { |
1118 | struct wm8978_priv *wm8978 = i2c_get_clientdata(client); | 1028 | snd_soc_unregister_codec(&client->dev); |
1119 | wm8978_unregister(wm8978); | 1029 | kfree(i2c_get_clientdata(client)); |
1120 | kfree(wm8978); | ||
1121 | return 0; | 1030 | return 0; |
1122 | } | 1031 | } |
1123 | 1032 | ||
@@ -1129,23 +1038,34 @@ MODULE_DEVICE_TABLE(i2c, wm8978_i2c_id); | |||
1129 | 1038 | ||
1130 | static struct i2c_driver wm8978_i2c_driver = { | 1039 | static struct i2c_driver wm8978_i2c_driver = { |
1131 | .driver = { | 1040 | .driver = { |
1132 | .name = "WM8978", | 1041 | .name = "WM8978-codec", |
1133 | .owner = THIS_MODULE, | 1042 | .owner = THIS_MODULE, |
1134 | }, | 1043 | }, |
1135 | .probe = wm8978_i2c_probe, | 1044 | .probe = wm8978_i2c_probe, |
1136 | .remove = __devexit_p(wm8978_i2c_remove), | 1045 | .remove = __devexit_p(wm8978_i2c_remove), |
1137 | .id_table = wm8978_i2c_id, | 1046 | .id_table = wm8978_i2c_id, |
1138 | }; | 1047 | }; |
1048 | #endif | ||
1139 | 1049 | ||
1140 | static int __init wm8978_modinit(void) | 1050 | static int __init wm8978_modinit(void) |
1141 | { | 1051 | { |
1142 | return i2c_add_driver(&wm8978_i2c_driver); | 1052 | int ret = 0; |
1053 | #if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE) | ||
1054 | ret = i2c_add_driver(&wm8978_i2c_driver); | ||
1055 | if (ret != 0) { | ||
1056 | printk(KERN_ERR "Failed to register WM8978 I2C driver: %d\n", | ||
1057 | ret); | ||
1058 | } | ||
1059 | #endif | ||
1060 | return ret; | ||
1143 | } | 1061 | } |
1144 | module_init(wm8978_modinit); | 1062 | module_init(wm8978_modinit); |
1145 | 1063 | ||
1146 | static void __exit wm8978_exit(void) | 1064 | static void __exit wm8978_exit(void) |
1147 | { | 1065 | { |
1066 | #if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE) | ||
1148 | i2c_del_driver(&wm8978_i2c_driver); | 1067 | i2c_del_driver(&wm8978_i2c_driver); |
1068 | #endif | ||
1149 | } | 1069 | } |
1150 | module_exit(wm8978_exit); | 1070 | module_exit(wm8978_exit); |
1151 | 1071 | ||
diff --git a/sound/soc/codecs/wm8978.h b/sound/soc/codecs/wm8978.h index 56ec83270917..c75525b7f154 100644 --- a/sound/soc/codecs/wm8978.h +++ b/sound/soc/codecs/wm8978.h | |||
@@ -80,7 +80,4 @@ enum wm8978_sysclk_src { | |||
80 | WM8978_MCLK | 80 | WM8978_MCLK |
81 | }; | 81 | }; |
82 | 82 | ||
83 | extern struct snd_soc_dai wm8978_dai; | ||
84 | extern struct snd_soc_codec_device soc_codec_dev_wm8978; | ||
85 | |||
86 | #endif /* __WM8978_H__ */ | 83 | #endif /* __WM8978_H__ */ |
diff --git a/sound/soc/codecs/wm8988.c b/sound/soc/codecs/wm8988.c index 19ad590ca0b3..d070a58e4f8e 100644 --- a/sound/soc/codecs/wm8988.c +++ b/sound/soc/codecs/wm8988.c | |||
@@ -52,7 +52,7 @@ static const u16 wm8988_reg[] = { | |||
52 | /* codec private data */ | 52 | /* codec private data */ |
53 | struct wm8988_priv { | 53 | struct wm8988_priv { |
54 | unsigned int sysclk; | 54 | unsigned int sysclk; |
55 | struct snd_soc_codec codec; | 55 | enum snd_soc_control_type control_type; |
56 | struct snd_pcm_hw_constraint_list *sysclk_constraints; | 56 | struct snd_pcm_hw_constraint_list *sysclk_constraints; |
57 | u16 reg_cache[WM8988_NUM_REG]; | 57 | u16 reg_cache[WM8988_NUM_REG]; |
58 | }; | 58 | }; |
@@ -608,8 +608,7 @@ static int wm8988_pcm_hw_params(struct snd_pcm_substream *substream, | |||
608 | struct snd_soc_dai *dai) | 608 | struct snd_soc_dai *dai) |
609 | { | 609 | { |
610 | struct snd_soc_pcm_runtime *rtd = substream->private_data; | 610 | struct snd_soc_pcm_runtime *rtd = substream->private_data; |
611 | struct snd_soc_device *socdev = rtd->socdev; | 611 | struct snd_soc_codec *codec = rtd->codec; |
612 | struct snd_soc_codec *codec = socdev->card->codec; | ||
613 | struct wm8988_priv *wm8988 = snd_soc_codec_get_drvdata(codec); | 612 | struct wm8988_priv *wm8988 = snd_soc_codec_get_drvdata(codec); |
614 | u16 iface = snd_soc_read(codec, WM8988_IFACE) & 0x1f3; | 613 | u16 iface = snd_soc_read(codec, WM8988_IFACE) & 0x1f3; |
615 | u16 srate = snd_soc_read(codec, WM8988_SRATE) & 0x180; | 614 | u16 srate = snd_soc_read(codec, WM8988_SRATE) & 0x180; |
@@ -711,8 +710,8 @@ static struct snd_soc_dai_ops wm8988_ops = { | |||
711 | .digital_mute = wm8988_mute, | 710 | .digital_mute = wm8988_mute, |
712 | }; | 711 | }; |
713 | 712 | ||
714 | struct snd_soc_dai wm8988_dai = { | 713 | static struct snd_soc_dai_driver wm8988_dai = { |
715 | .name = "WM8988", | 714 | .name = "wm8988-hifi", |
716 | .playback = { | 715 | .playback = { |
717 | .stream_name = "Playback", | 716 | .stream_name = "Playback", |
718 | .channels_min = 1, | 717 | .channels_min = 1, |
@@ -730,21 +729,15 @@ struct snd_soc_dai wm8988_dai = { | |||
730 | .ops = &wm8988_ops, | 729 | .ops = &wm8988_ops, |
731 | .symmetric_rates = 1, | 730 | .symmetric_rates = 1, |
732 | }; | 731 | }; |
733 | EXPORT_SYMBOL_GPL(wm8988_dai); | ||
734 | 732 | ||
735 | static int wm8988_suspend(struct platform_device *pdev, pm_message_t state) | 733 | static int wm8988_suspend(struct snd_soc_codec *codec, pm_message_t state) |
736 | { | 734 | { |
737 | struct snd_soc_device *socdev = platform_get_drvdata(pdev); | ||
738 | struct snd_soc_codec *codec = socdev->card->codec; | ||
739 | |||
740 | wm8988_set_bias_level(codec, SND_SOC_BIAS_OFF); | 735 | wm8988_set_bias_level(codec, SND_SOC_BIAS_OFF); |
741 | return 0; | 736 | return 0; |
742 | } | 737 | } |
743 | 738 | ||
744 | static int wm8988_resume(struct platform_device *pdev) | 739 | static int wm8988_resume(struct snd_soc_codec *codec) |
745 | { | 740 | { |
746 | struct snd_soc_device *socdev = platform_get_drvdata(pdev); | ||
747 | struct snd_soc_codec *codec = socdev->card->codec; | ||
748 | int i; | 741 | int i; |
749 | u8 data[2]; | 742 | u8 data[2]; |
750 | u16 *cache = codec->reg_cache; | 743 | u16 *cache = codec->reg_cache; |
@@ -763,99 +756,22 @@ static int wm8988_resume(struct platform_device *pdev) | |||
763 | return 0; | 756 | return 0; |
764 | } | 757 | } |
765 | 758 | ||
766 | static struct snd_soc_codec *wm8988_codec; | 759 | static int wm8988_probe(struct snd_soc_codec *codec) |
767 | |||
768 | static int wm8988_probe(struct platform_device *pdev) | ||
769 | { | 760 | { |
770 | struct snd_soc_device *socdev = platform_get_drvdata(pdev); | 761 | struct wm8988_priv *wm8988 = snd_soc_codec_get_drvdata(codec); |
771 | struct snd_soc_codec *codec; | ||
772 | int ret = 0; | 762 | int ret = 0; |
773 | |||
774 | if (wm8988_codec == NULL) { | ||
775 | dev_err(&pdev->dev, "Codec device not registered\n"); | ||
776 | return -ENODEV; | ||
777 | } | ||
778 | |||
779 | socdev->card->codec = wm8988_codec; | ||
780 | codec = wm8988_codec; | ||
781 | |||
782 | /* register pcms */ | ||
783 | ret = snd_soc_new_pcms(socdev, SNDRV_DEFAULT_IDX1, SNDRV_DEFAULT_STR1); | ||
784 | if (ret < 0) { | ||
785 | dev_err(codec->dev, "failed to create pcms: %d\n", ret); | ||
786 | goto pcm_err; | ||
787 | } | ||
788 | |||
789 | snd_soc_add_controls(codec, wm8988_snd_controls, | ||
790 | ARRAY_SIZE(wm8988_snd_controls)); | ||
791 | snd_soc_dapm_new_controls(codec, wm8988_dapm_widgets, | ||
792 | ARRAY_SIZE(wm8988_dapm_widgets)); | ||
793 | snd_soc_dapm_add_routes(codec, audio_map, ARRAY_SIZE(audio_map)); | ||
794 | |||
795 | return ret; | ||
796 | |||
797 | pcm_err: | ||
798 | return ret; | ||
799 | } | ||
800 | |||
801 | static int wm8988_remove(struct platform_device *pdev) | ||
802 | { | ||
803 | struct snd_soc_device *socdev = platform_get_drvdata(pdev); | ||
804 | |||
805 | snd_soc_free_pcms(socdev); | ||
806 | snd_soc_dapm_free(socdev); | ||
807 | |||
808 | return 0; | ||
809 | } | ||
810 | |||
811 | struct snd_soc_codec_device soc_codec_dev_wm8988 = { | ||
812 | .probe = wm8988_probe, | ||
813 | .remove = wm8988_remove, | ||
814 | .suspend = wm8988_suspend, | ||
815 | .resume = wm8988_resume, | ||
816 | }; | ||
817 | EXPORT_SYMBOL_GPL(soc_codec_dev_wm8988); | ||
818 | |||
819 | static int wm8988_register(struct wm8988_priv *wm8988, | ||
820 | enum snd_soc_control_type control) | ||
821 | { | ||
822 | struct snd_soc_codec *codec = &wm8988->codec; | ||
823 | int ret; | ||
824 | u16 reg; | 763 | u16 reg; |
825 | 764 | ||
826 | if (wm8988_codec) { | 765 | ret = snd_soc_codec_set_cache_io(codec, 7, 9, wm8988->control_type); |
827 | dev_err(codec->dev, "Another WM8988 is registered\n"); | ||
828 | ret = -EINVAL; | ||
829 | goto err; | ||
830 | } | ||
831 | |||
832 | mutex_init(&codec->mutex); | ||
833 | INIT_LIST_HEAD(&codec->dapm_widgets); | ||
834 | INIT_LIST_HEAD(&codec->dapm_paths); | ||
835 | |||
836 | snd_soc_codec_set_drvdata(codec, wm8988); | ||
837 | codec->name = "WM8988"; | ||
838 | codec->owner = THIS_MODULE; | ||
839 | codec->dai = &wm8988_dai; | ||
840 | codec->num_dai = 1; | ||
841 | codec->reg_cache_size = ARRAY_SIZE(wm8988->reg_cache); | ||
842 | codec->reg_cache = &wm8988->reg_cache; | ||
843 | codec->bias_level = SND_SOC_BIAS_OFF; | ||
844 | codec->set_bias_level = wm8988_set_bias_level; | ||
845 | |||
846 | memcpy(codec->reg_cache, wm8988_reg, | ||
847 | sizeof(wm8988_reg)); | ||
848 | |||
849 | ret = snd_soc_codec_set_cache_io(codec, 7, 9, control); | ||
850 | if (ret < 0) { | 766 | if (ret < 0) { |
851 | dev_err(codec->dev, "Failed to set cache I/O: %d\n", ret); | 767 | dev_err(codec->dev, "Failed to set cache I/O: %d\n", ret); |
852 | goto err; | 768 | return ret; |
853 | } | 769 | } |
854 | 770 | ||
855 | ret = wm8988_reset(codec); | 771 | ret = wm8988_reset(codec); |
856 | if (ret < 0) { | 772 | if (ret < 0) { |
857 | dev_err(codec->dev, "Failed to issue reset\n"); | 773 | dev_err(codec->dev, "Failed to issue reset\n"); |
858 | goto err; | 774 | return ret; |
859 | } | 775 | } |
860 | 776 | ||
861 | /* set the update bits (we always update left then right) */ | 777 | /* set the update bits (we always update left then right) */ |
@@ -870,139 +786,133 @@ static int wm8988_register(struct wm8988_priv *wm8988, | |||
870 | reg = snd_soc_read(codec, WM8988_RINVOL); | 786 | reg = snd_soc_read(codec, WM8988_RINVOL); |
871 | snd_soc_write(codec, WM8988_RINVOL, reg | 0x0100); | 787 | snd_soc_write(codec, WM8988_RINVOL, reg | 0x0100); |
872 | 788 | ||
873 | wm8988_set_bias_level(&wm8988->codec, SND_SOC_BIAS_STANDBY); | 789 | wm8988_set_bias_level(codec, SND_SOC_BIAS_STANDBY); |
874 | |||
875 | wm8988_dai.dev = codec->dev; | ||
876 | |||
877 | wm8988_codec = codec; | ||
878 | |||
879 | ret = snd_soc_register_codec(codec); | ||
880 | if (ret != 0) { | ||
881 | dev_err(codec->dev, "Failed to register codec: %d\n", ret); | ||
882 | goto err; | ||
883 | } | ||
884 | 790 | ||
885 | ret = snd_soc_register_dai(&wm8988_dai); | 791 | snd_soc_add_controls(codec, wm8988_snd_controls, |
886 | if (ret != 0) { | 792 | ARRAY_SIZE(wm8988_snd_controls)); |
887 | dev_err(codec->dev, "Failed to register DAI: %d\n", ret); | 793 | snd_soc_dapm_new_controls(codec, wm8988_dapm_widgets, |
888 | goto err_codec; | 794 | ARRAY_SIZE(wm8988_dapm_widgets)); |
889 | } | 795 | snd_soc_dapm_add_routes(codec, audio_map, ARRAY_SIZE(audio_map)); |
890 | 796 | ||
891 | return 0; | 797 | return 0; |
892 | |||
893 | err_codec: | ||
894 | snd_soc_unregister_codec(codec); | ||
895 | err: | ||
896 | kfree(wm8988); | ||
897 | return ret; | ||
898 | } | 798 | } |
899 | 799 | ||
900 | static void wm8988_unregister(struct wm8988_priv *wm8988) | 800 | static int wm8988_remove(struct snd_soc_codec *codec) |
901 | { | 801 | { |
902 | wm8988_set_bias_level(&wm8988->codec, SND_SOC_BIAS_OFF); | 802 | wm8988_set_bias_level(codec, SND_SOC_BIAS_OFF); |
903 | snd_soc_unregister_dai(&wm8988_dai); | 803 | return 0; |
904 | snd_soc_unregister_codec(&wm8988->codec); | ||
905 | kfree(wm8988); | ||
906 | wm8988_codec = NULL; | ||
907 | } | 804 | } |
908 | 805 | ||
909 | #if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE) | 806 | static struct snd_soc_codec_driver soc_codec_dev_wm8988 = { |
910 | static int wm8988_i2c_probe(struct i2c_client *i2c, | 807 | .probe = wm8988_probe, |
911 | const struct i2c_device_id *id) | 808 | .remove = wm8988_remove, |
809 | .suspend = wm8988_suspend, | ||
810 | .resume = wm8988_resume, | ||
811 | .set_bias_level = wm8988_set_bias_level, | ||
812 | .reg_cache_size = sizeof(wm8988_reg), | ||
813 | .reg_word_size = sizeof(u16), | ||
814 | .reg_cache_default = wm8988_reg, | ||
815 | }; | ||
816 | |||
817 | #if defined(CONFIG_SPI_MASTER) | ||
818 | static int __devinit wm8988_spi_probe(struct spi_device *spi) | ||
912 | { | 819 | { |
913 | struct wm8988_priv *wm8988; | 820 | struct wm8988_priv *wm8988; |
914 | struct snd_soc_codec *codec; | 821 | int ret; |
915 | 822 | ||
916 | wm8988 = kzalloc(sizeof(struct wm8988_priv), GFP_KERNEL); | 823 | wm8988 = kzalloc(sizeof(struct wm8988_priv), GFP_KERNEL); |
917 | if (wm8988 == NULL) | 824 | if (wm8988 == NULL) |
918 | return -ENOMEM; | 825 | return -ENOMEM; |
919 | 826 | ||
920 | codec = &wm8988->codec; | 827 | wm8988->control_type = SND_SOC_SPI; |
921 | 828 | spi_set_drvdata(spi, wm8988); | |
922 | i2c_set_clientdata(i2c, wm8988); | ||
923 | codec->control_data = i2c; | ||
924 | |||
925 | codec->dev = &i2c->dev; | ||
926 | 829 | ||
927 | return wm8988_register(wm8988, SND_SOC_I2C); | 830 | ret = snd_soc_register_codec(&spi->dev, |
831 | &soc_codec_dev_wm8988, &wm8988_dai, 1); | ||
832 | if (ret < 0) | ||
833 | kfree(wm8988); | ||
834 | return ret; | ||
928 | } | 835 | } |
929 | 836 | ||
930 | static int wm8988_i2c_remove(struct i2c_client *client) | 837 | static int __devexit wm8988_spi_remove(struct spi_device *spi) |
931 | { | 838 | { |
932 | struct wm8988_priv *wm8988 = i2c_get_clientdata(client); | 839 | snd_soc_unregister_codec(&spi->dev); |
933 | wm8988_unregister(wm8988); | 840 | kfree(spi_get_drvdata(spi)); |
934 | return 0; | 841 | return 0; |
935 | } | 842 | } |
936 | 843 | ||
937 | static const struct i2c_device_id wm8988_i2c_id[] = { | 844 | static struct spi_driver wm8988_spi_driver = { |
938 | { "wm8988", 0 }, | ||
939 | { } | ||
940 | }; | ||
941 | MODULE_DEVICE_TABLE(i2c, wm8988_i2c_id); | ||
942 | |||
943 | static struct i2c_driver wm8988_i2c_driver = { | ||
944 | .driver = { | 845 | .driver = { |
945 | .name = "WM8988", | 846 | .name = "wm8988-codec", |
946 | .owner = THIS_MODULE, | 847 | .bus = &spi_bus_type, |
848 | .owner = THIS_MODULE, | ||
947 | }, | 849 | }, |
948 | .probe = wm8988_i2c_probe, | 850 | .probe = wm8988_spi_probe, |
949 | .remove = wm8988_i2c_remove, | 851 | .remove = __devexit_p(wm8988_spi_remove), |
950 | .id_table = wm8988_i2c_id, | ||
951 | }; | 852 | }; |
952 | #endif | 853 | #endif /* CONFIG_SPI_MASTER */ |
953 | 854 | ||
954 | #if defined(CONFIG_SPI_MASTER) | 855 | #if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE) |
955 | static int __devinit wm8988_spi_probe(struct spi_device *spi) | 856 | static __devinit int wm8988_i2c_probe(struct i2c_client *i2c, |
857 | const struct i2c_device_id *id) | ||
956 | { | 858 | { |
957 | struct wm8988_priv *wm8988; | 859 | struct wm8988_priv *wm8988; |
958 | struct snd_soc_codec *codec; | 860 | int ret; |
959 | 861 | ||
960 | wm8988 = kzalloc(sizeof(struct wm8988_priv), GFP_KERNEL); | 862 | wm8988 = kzalloc(sizeof(struct wm8988_priv), GFP_KERNEL); |
961 | if (wm8988 == NULL) | 863 | if (wm8988 == NULL) |
962 | return -ENOMEM; | 864 | return -ENOMEM; |
963 | 865 | ||
964 | codec = &wm8988->codec; | 866 | i2c_set_clientdata(i2c, wm8988); |
965 | codec->control_data = spi; | 867 | wm8988->control_type = SND_SOC_I2C; |
966 | codec->dev = &spi->dev; | ||
967 | |||
968 | dev_set_drvdata(&spi->dev, wm8988); | ||
969 | 868 | ||
970 | return wm8988_register(wm8988, SND_SOC_SPI); | 869 | ret = snd_soc_register_codec(&i2c->dev, |
870 | &soc_codec_dev_wm8988, &wm8988_dai, 1); | ||
871 | if (ret < 0) | ||
872 | kfree(wm8988); | ||
873 | return ret; | ||
971 | } | 874 | } |
972 | 875 | ||
973 | static int __devexit wm8988_spi_remove(struct spi_device *spi) | 876 | static __devexit int wm8988_i2c_remove(struct i2c_client *client) |
974 | { | 877 | { |
975 | struct wm8988_priv *wm8988 = dev_get_drvdata(&spi->dev); | 878 | snd_soc_unregister_codec(&client->dev); |
976 | 879 | kfree(i2c_get_clientdata(client)); | |
977 | wm8988_unregister(wm8988); | ||
978 | |||
979 | return 0; | 880 | return 0; |
980 | } | 881 | } |
981 | 882 | ||
982 | static struct spi_driver wm8988_spi_driver = { | 883 | static const struct i2c_device_id wm8988_i2c_id[] = { |
884 | { "wm8988", 0 }, | ||
885 | { } | ||
886 | }; | ||
887 | MODULE_DEVICE_TABLE(i2c, wm8988_i2c_id); | ||
888 | |||
889 | static struct i2c_driver wm8988_i2c_driver = { | ||
983 | .driver = { | 890 | .driver = { |
984 | .name = "wm8988", | 891 | .name = "wm8988-codec", |
985 | .bus = &spi_bus_type, | 892 | .owner = THIS_MODULE, |
986 | .owner = THIS_MODULE, | ||
987 | }, | 893 | }, |
988 | .probe = wm8988_spi_probe, | 894 | .probe = wm8988_i2c_probe, |
989 | .remove = __devexit_p(wm8988_spi_remove), | 895 | .remove = __devexit_p(wm8988_i2c_remove), |
896 | .id_table = wm8988_i2c_id, | ||
990 | }; | 897 | }; |
991 | #endif | 898 | #endif |
992 | 899 | ||
993 | static int __init wm8988_modinit(void) | 900 | static int __init wm8988_modinit(void) |
994 | { | 901 | { |
995 | int ret; | 902 | int ret = 0; |
996 | |||
997 | #if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE) | 903 | #if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE) |
998 | ret = i2c_add_driver(&wm8988_i2c_driver); | 904 | ret = i2c_add_driver(&wm8988_i2c_driver); |
999 | if (ret != 0) | 905 | if (ret != 0) { |
1000 | pr_err("WM8988: Unable to register I2C driver: %d\n", ret); | 906 | printk(KERN_ERR "Failed to register WM8988 I2C driver: %d\n", |
907 | ret); | ||
908 | } | ||
1001 | #endif | 909 | #endif |
1002 | #if defined(CONFIG_SPI_MASTER) | 910 | #if defined(CONFIG_SPI_MASTER) |
1003 | ret = spi_register_driver(&wm8988_spi_driver); | 911 | ret = spi_register_driver(&wm8988_spi_driver); |
1004 | if (ret != 0) | 912 | if (ret != 0) { |
1005 | pr_err("WM8988: Unable to register SPI driver: %d\n", ret); | 913 | printk(KERN_ERR "Failed to register WM8988 SPI driver: %d\n", |
914 | ret); | ||
915 | } | ||
1006 | #endif | 916 | #endif |
1007 | return ret; | 917 | return ret; |
1008 | } | 918 | } |
diff --git a/sound/soc/codecs/wm8988.h b/sound/soc/codecs/wm8988.h index 4552d37fdd41..5c04024e5f9f 100644 --- a/sound/soc/codecs/wm8988.h +++ b/sound/soc/codecs/wm8988.h | |||
@@ -54,7 +54,4 @@ | |||
54 | 54 | ||
55 | #define WM8988_SYSCLK 0 | 55 | #define WM8988_SYSCLK 0 |
56 | 56 | ||
57 | extern struct snd_soc_dai wm8988_dai; | ||
58 | extern struct snd_soc_codec_device soc_codec_dev_wm8988; | ||
59 | |||
60 | #endif | 57 | #endif |
diff --git a/sound/soc/codecs/wm8990.c b/sound/soc/codecs/wm8990.c index dd8d909788c1..0ffecbd1e33b 100644 --- a/sound/soc/codecs/wm8990.c +++ b/sound/soc/codecs/wm8990.c | |||
@@ -32,6 +32,7 @@ | |||
32 | 32 | ||
33 | /* codec private data */ | 33 | /* codec private data */ |
34 | struct wm8990_priv { | 34 | struct wm8990_priv { |
35 | enum snd_soc_control_type control_type; | ||
35 | unsigned int sysclk; | 36 | unsigned int sysclk; |
36 | unsigned int pcmclk; | 37 | unsigned int pcmclk; |
37 | }; | 38 | }; |
@@ -1114,8 +1115,7 @@ static int wm8990_hw_params(struct snd_pcm_substream *substream, | |||
1114 | struct snd_soc_dai *dai) | 1115 | struct snd_soc_dai *dai) |
1115 | { | 1116 | { |
1116 | struct snd_soc_pcm_runtime *rtd = substream->private_data; | 1117 | struct snd_soc_pcm_runtime *rtd = substream->private_data; |
1117 | struct snd_soc_device *socdev = rtd->socdev; | 1118 | struct snd_soc_codec *codec = rtd->codec; |
1118 | struct snd_soc_codec *codec = socdev->card->codec; | ||
1119 | u16 audio1 = snd_soc_read(codec, WM8990_AUDIO_INTERFACE_1); | 1119 | u16 audio1 = snd_soc_read(codec, WM8990_AUDIO_INTERFACE_1); |
1120 | 1120 | ||
1121 | audio1 &= ~WM8990_AIF_WL_MASK; | 1121 | audio1 &= ~WM8990_AIF_WL_MASK; |
@@ -1293,10 +1293,9 @@ static struct snd_soc_dai_ops wm8990_dai_ops = { | |||
1293 | .set_sysclk = wm8990_set_dai_sysclk, | 1293 | .set_sysclk = wm8990_set_dai_sysclk, |
1294 | }; | 1294 | }; |
1295 | 1295 | ||
1296 | struct snd_soc_dai wm8990_dai = { | 1296 | static struct snd_soc_dai_driver wm8990_dai = { |
1297 | /* ADC/DAC on primary */ | 1297 | /* ADC/DAC on primary */ |
1298 | .name = "WM8990 ADC/DAC Primary", | 1298 | .name = "wm8990-hifi", |
1299 | .id = 1, | ||
1300 | .playback = { | 1299 | .playback = { |
1301 | .stream_name = "Playback", | 1300 | .stream_name = "Playback", |
1302 | .channels_min = 1, | 1301 | .channels_min = 1, |
@@ -1311,21 +1310,15 @@ struct snd_soc_dai wm8990_dai = { | |||
1311 | .formats = WM8990_FORMATS,}, | 1310 | .formats = WM8990_FORMATS,}, |
1312 | .ops = &wm8990_dai_ops, | 1311 | .ops = &wm8990_dai_ops, |
1313 | }; | 1312 | }; |
1314 | EXPORT_SYMBOL_GPL(wm8990_dai); | ||
1315 | 1313 | ||
1316 | static int wm8990_suspend(struct platform_device *pdev, pm_message_t state) | 1314 | static int wm8990_suspend(struct snd_soc_codec *codec, pm_message_t state) |
1317 | { | 1315 | { |
1318 | struct snd_soc_device *socdev = platform_get_drvdata(pdev); | ||
1319 | struct snd_soc_codec *codec = socdev->card->codec; | ||
1320 | |||
1321 | wm8990_set_bias_level(codec, SND_SOC_BIAS_OFF); | 1316 | wm8990_set_bias_level(codec, SND_SOC_BIAS_OFF); |
1322 | return 0; | 1317 | return 0; |
1323 | } | 1318 | } |
1324 | 1319 | ||
1325 | static int wm8990_resume(struct platform_device *pdev) | 1320 | static int wm8990_resume(struct snd_soc_codec *codec) |
1326 | { | 1321 | { |
1327 | struct snd_soc_device *socdev = platform_get_drvdata(pdev); | ||
1328 | struct snd_soc_codec *codec = socdev->card->codec; | ||
1329 | int i; | 1322 | int i; |
1330 | u8 data[2]; | 1323 | u8 data[2]; |
1331 | u16 *cache = codec->reg_cache; | 1324 | u16 *cache = codec->reg_cache; |
@@ -1347,38 +1340,19 @@ static int wm8990_resume(struct platform_device *pdev) | |||
1347 | * initialise the WM8990 driver | 1340 | * initialise the WM8990 driver |
1348 | * register the mixer and dsp interfaces with the kernel | 1341 | * register the mixer and dsp interfaces with the kernel |
1349 | */ | 1342 | */ |
1350 | static int wm8990_init(struct snd_soc_device *socdev) | 1343 | static int wm8990_probe(struct snd_soc_codec *codec) |
1351 | { | 1344 | { |
1352 | struct snd_soc_codec *codec = socdev->card->codec; | 1345 | int ret; |
1353 | u16 reg; | 1346 | u16 reg; |
1354 | int ret = 0; | ||
1355 | |||
1356 | codec->name = "WM8990"; | ||
1357 | codec->owner = THIS_MODULE; | ||
1358 | codec->set_bias_level = wm8990_set_bias_level; | ||
1359 | codec->dai = &wm8990_dai; | ||
1360 | codec->num_dai = 2; | ||
1361 | codec->reg_cache_size = ARRAY_SIZE(wm8990_reg); | ||
1362 | codec->reg_cache = kmemdup(wm8990_reg, sizeof(wm8990_reg), GFP_KERNEL); | ||
1363 | |||
1364 | if (codec->reg_cache == NULL) | ||
1365 | return -ENOMEM; | ||
1366 | 1347 | ||
1367 | ret = snd_soc_codec_set_cache_io(codec, 8, 16, SND_SOC_I2C); | 1348 | ret = snd_soc_codec_set_cache_io(codec, 8, 16, SND_SOC_I2C); |
1368 | if (ret < 0) { | 1349 | if (ret < 0) { |
1369 | printk(KERN_ERR "wm8990: failed to set cache I/O: %d\n", ret); | 1350 | printk(KERN_ERR "wm8990: failed to set cache I/O: %d\n", ret); |
1370 | goto pcm_err; | 1351 | return ret; |
1371 | } | 1352 | } |
1372 | 1353 | ||
1373 | wm8990_reset(codec); | 1354 | wm8990_reset(codec); |
1374 | 1355 | ||
1375 | /* register pcms */ | ||
1376 | ret = snd_soc_new_pcms(socdev, SNDRV_DEFAULT_IDX1, SNDRV_DEFAULT_STR1); | ||
1377 | if (ret < 0) { | ||
1378 | printk(KERN_ERR "wm8990: failed to create pcms\n"); | ||
1379 | goto pcm_err; | ||
1380 | } | ||
1381 | |||
1382 | /* charge output caps */ | 1356 | /* charge output caps */ |
1383 | codec->bias_level = SND_SOC_BIAS_OFF; | 1357 | codec->bias_level = SND_SOC_BIAS_OFF; |
1384 | wm8990_set_bias_level(codec, SND_SOC_BIAS_STANDBY); | 1358 | wm8990_set_bias_level(codec, SND_SOC_BIAS_STANDBY); |
@@ -1400,47 +1374,51 @@ static int wm8990_init(struct snd_soc_device *socdev) | |||
1400 | ARRAY_SIZE(wm8990_snd_controls)); | 1374 | ARRAY_SIZE(wm8990_snd_controls)); |
1401 | wm8990_add_widgets(codec); | 1375 | wm8990_add_widgets(codec); |
1402 | 1376 | ||
1403 | return ret; | 1377 | return 0; |
1378 | } | ||
1404 | 1379 | ||
1405 | pcm_err: | 1380 | /* power down chip */ |
1406 | kfree(codec->reg_cache); | 1381 | static int wm8990_remove(struct snd_soc_codec *codec) |
1407 | return ret; | 1382 | { |
1383 | wm8990_set_bias_level(codec, SND_SOC_BIAS_OFF); | ||
1384 | return 0; | ||
1408 | } | 1385 | } |
1409 | 1386 | ||
1410 | /* If the i2c layer weren't so broken, we could pass this kind of data | 1387 | static struct snd_soc_codec_driver soc_codec_dev_wm8990 = { |
1411 | around */ | 1388 | .probe = wm8990_probe, |
1412 | static struct snd_soc_device *wm8990_socdev; | 1389 | .remove = wm8990_remove, |
1390 | .suspend = wm8990_suspend, | ||
1391 | .resume = wm8990_resume, | ||
1392 | .set_bias_level = wm8990_set_bias_level, | ||
1393 | .reg_cache_size = ARRAY_SIZE(wm8990_reg), | ||
1394 | .reg_word_size = sizeof(u16), | ||
1395 | .reg_cache_default = wm8990_reg, | ||
1396 | }; | ||
1413 | 1397 | ||
1414 | #if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE) | 1398 | #if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE) |
1415 | 1399 | static __devinit int wm8990_i2c_probe(struct i2c_client *i2c, | |
1416 | /* | 1400 | const struct i2c_device_id *id) |
1417 | * WM891 2 wire address is determined by GPIO5 | ||
1418 | * state during powerup. | ||
1419 | * low = 0x34 | ||
1420 | * high = 0x36 | ||
1421 | */ | ||
1422 | |||
1423 | static int wm8990_i2c_probe(struct i2c_client *i2c, | ||
1424 | const struct i2c_device_id *id) | ||
1425 | { | 1401 | { |
1426 | struct snd_soc_device *socdev = wm8990_socdev; | 1402 | struct wm8990_priv *wm8990; |
1427 | struct snd_soc_codec *codec = socdev->card->codec; | ||
1428 | int ret; | 1403 | int ret; |
1429 | 1404 | ||
1430 | i2c_set_clientdata(i2c, codec); | 1405 | wm8990 = kzalloc(sizeof(struct wm8990_priv), GFP_KERNEL); |
1431 | codec->control_data = i2c; | 1406 | if (wm8990 == NULL) |
1407 | return -ENOMEM; | ||
1432 | 1408 | ||
1433 | ret = wm8990_init(socdev); | 1409 | i2c_set_clientdata(i2c, wm8990); |
1434 | if (ret < 0) | ||
1435 | pr_err("failed to initialise WM8990\n"); | ||
1436 | 1410 | ||
1411 | ret = snd_soc_register_codec(&i2c->dev, | ||
1412 | &soc_codec_dev_wm8990, &wm8990_dai, 1); | ||
1413 | if (ret < 0) | ||
1414 | kfree(wm8990); | ||
1437 | return ret; | 1415 | return ret; |
1438 | } | 1416 | } |
1439 | 1417 | ||
1440 | static int wm8990_i2c_remove(struct i2c_client *client) | 1418 | static __devexit int wm8990_i2c_remove(struct i2c_client *client) |
1441 | { | 1419 | { |
1442 | struct snd_soc_codec *codec = i2c_get_clientdata(client); | 1420 | snd_soc_unregister_codec(&client->dev); |
1443 | kfree(codec->reg_cache); | 1421 | kfree(i2c_get_clientdata(client)); |
1444 | return 0; | 1422 | return 0; |
1445 | } | 1423 | } |
1446 | 1424 | ||
@@ -1452,134 +1430,34 @@ MODULE_DEVICE_TABLE(i2c, wm8990_i2c_id); | |||
1452 | 1430 | ||
1453 | static struct i2c_driver wm8990_i2c_driver = { | 1431 | static struct i2c_driver wm8990_i2c_driver = { |
1454 | .driver = { | 1432 | .driver = { |
1455 | .name = "WM8990 I2C Codec", | 1433 | .name = "wm8990-codec", |
1456 | .owner = THIS_MODULE, | 1434 | .owner = THIS_MODULE, |
1457 | }, | 1435 | }, |
1458 | .probe = wm8990_i2c_probe, | 1436 | .probe = wm8990_i2c_probe, |
1459 | .remove = wm8990_i2c_remove, | 1437 | .remove = __devexit_p(wm8990_i2c_remove), |
1460 | .id_table = wm8990_i2c_id, | 1438 | .id_table = wm8990_i2c_id, |
1461 | }; | 1439 | }; |
1462 | |||
1463 | static int wm8990_add_i2c_device(struct platform_device *pdev, | ||
1464 | const struct wm8990_setup_data *setup) | ||
1465 | { | ||
1466 | struct i2c_board_info info; | ||
1467 | struct i2c_adapter *adapter; | ||
1468 | struct i2c_client *client; | ||
1469 | int ret; | ||
1470 | |||
1471 | ret = i2c_add_driver(&wm8990_i2c_driver); | ||
1472 | if (ret != 0) { | ||
1473 | dev_err(&pdev->dev, "can't add i2c driver\n"); | ||
1474 | return ret; | ||
1475 | } | ||
1476 | |||
1477 | memset(&info, 0, sizeof(struct i2c_board_info)); | ||
1478 | info.addr = setup->i2c_address; | ||
1479 | strlcpy(info.type, "wm8990", I2C_NAME_SIZE); | ||
1480 | |||
1481 | adapter = i2c_get_adapter(setup->i2c_bus); | ||
1482 | if (!adapter) { | ||
1483 | dev_err(&pdev->dev, "can't get i2c adapter %d\n", | ||
1484 | setup->i2c_bus); | ||
1485 | goto err_driver; | ||
1486 | } | ||
1487 | |||
1488 | client = i2c_new_device(adapter, &info); | ||
1489 | i2c_put_adapter(adapter); | ||
1490 | if (!client) { | ||
1491 | dev_err(&pdev->dev, "can't add i2c device at 0x%x\n", | ||
1492 | (unsigned int)info.addr); | ||
1493 | goto err_driver; | ||
1494 | } | ||
1495 | |||
1496 | return 0; | ||
1497 | |||
1498 | err_driver: | ||
1499 | i2c_del_driver(&wm8990_i2c_driver); | ||
1500 | return -ENODEV; | ||
1501 | } | ||
1502 | #endif | 1440 | #endif |
1503 | 1441 | ||
1504 | static int wm8990_probe(struct platform_device *pdev) | 1442 | static int __init wm8990_modinit(void) |
1505 | { | 1443 | { |
1506 | struct snd_soc_device *socdev = platform_get_drvdata(pdev); | 1444 | int ret = 0; |
1507 | struct wm8990_setup_data *setup; | ||
1508 | struct snd_soc_codec *codec; | ||
1509 | struct wm8990_priv *wm8990; | ||
1510 | int ret; | ||
1511 | |||
1512 | setup = socdev->codec_data; | ||
1513 | codec = kzalloc(sizeof(struct snd_soc_codec), GFP_KERNEL); | ||
1514 | if (codec == NULL) | ||
1515 | return -ENOMEM; | ||
1516 | |||
1517 | wm8990 = kzalloc(sizeof(struct wm8990_priv), GFP_KERNEL); | ||
1518 | if (wm8990 == NULL) { | ||
1519 | kfree(codec); | ||
1520 | return -ENOMEM; | ||
1521 | } | ||
1522 | |||
1523 | snd_soc_codec_set_drvdata(codec, wm8990); | ||
1524 | socdev->card->codec = codec; | ||
1525 | mutex_init(&codec->mutex); | ||
1526 | INIT_LIST_HEAD(&codec->dapm_widgets); | ||
1527 | INIT_LIST_HEAD(&codec->dapm_paths); | ||
1528 | wm8990_socdev = socdev; | ||
1529 | |||
1530 | ret = -ENODEV; | ||
1531 | |||
1532 | #if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE) | 1445 | #if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE) |
1533 | if (setup->i2c_address) { | 1446 | ret = i2c_add_driver(&wm8990_i2c_driver); |
1534 | codec->hw_write = (hw_write_t)i2c_master_send; | ||
1535 | ret = wm8990_add_i2c_device(pdev, setup); | ||
1536 | } | ||
1537 | #endif | ||
1538 | |||
1539 | if (ret != 0) { | 1447 | if (ret != 0) { |
1540 | kfree(snd_soc_codec_get_drvdata(codec)); | 1448 | printk(KERN_ERR "Failed to register wm8990 I2C driver: %d\n", |
1541 | kfree(codec); | 1449 | ret); |
1542 | } | 1450 | } |
1451 | #endif | ||
1543 | return ret; | 1452 | return ret; |
1544 | } | 1453 | } |
1454 | module_init(wm8990_modinit); | ||
1545 | 1455 | ||
1546 | /* power down chip */ | 1456 | static void __exit wm8990_exit(void) |
1547 | static int wm8990_remove(struct platform_device *pdev) | ||
1548 | { | 1457 | { |
1549 | struct snd_soc_device *socdev = platform_get_drvdata(pdev); | ||
1550 | struct snd_soc_codec *codec = socdev->card->codec; | ||
1551 | |||
1552 | if (codec->control_data) | ||
1553 | wm8990_set_bias_level(codec, SND_SOC_BIAS_OFF); | ||
1554 | snd_soc_free_pcms(socdev); | ||
1555 | snd_soc_dapm_free(socdev); | ||
1556 | #if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE) | 1458 | #if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE) |
1557 | i2c_unregister_device(codec->control_data); | ||
1558 | i2c_del_driver(&wm8990_i2c_driver); | 1459 | i2c_del_driver(&wm8990_i2c_driver); |
1559 | #endif | 1460 | #endif |
1560 | kfree(snd_soc_codec_get_drvdata(codec)); | ||
1561 | kfree(codec); | ||
1562 | |||
1563 | return 0; | ||
1564 | } | ||
1565 | |||
1566 | struct snd_soc_codec_device soc_codec_dev_wm8990 = { | ||
1567 | .probe = wm8990_probe, | ||
1568 | .remove = wm8990_remove, | ||
1569 | .suspend = wm8990_suspend, | ||
1570 | .resume = wm8990_resume, | ||
1571 | }; | ||
1572 | EXPORT_SYMBOL_GPL(soc_codec_dev_wm8990); | ||
1573 | |||
1574 | static int __init wm8990_modinit(void) | ||
1575 | { | ||
1576 | return snd_soc_register_dai(&wm8990_dai); | ||
1577 | } | ||
1578 | module_init(wm8990_modinit); | ||
1579 | |||
1580 | static void __exit wm8990_exit(void) | ||
1581 | { | ||
1582 | snd_soc_unregister_dai(&wm8990_dai); | ||
1583 | } | 1461 | } |
1584 | module_exit(wm8990_exit); | 1462 | module_exit(wm8990_exit); |
1585 | 1463 | ||
diff --git a/sound/soc/codecs/wm8990.h b/sound/soc/codecs/wm8990.h index 7114ddc88b4b..77c98a4bfe9c 100644 --- a/sound/soc/codecs/wm8990.h +++ b/sound/soc/codecs/wm8990.h | |||
@@ -826,18 +826,10 @@ | |||
826 | #define WM8990_INMIXR_PWR_BIT 2 | 826 | #define WM8990_INMIXR_PWR_BIT 2 |
827 | #define WM8990_AINRMUX_PWR_BIT 3 | 827 | #define WM8990_AINRMUX_PWR_BIT 3 |
828 | 828 | ||
829 | struct wm8990_setup_data { | ||
830 | unsigned i2c_bus; | ||
831 | unsigned short i2c_address; | ||
832 | }; | ||
833 | |||
834 | #define WM8990_MCLK_DIV 0 | 829 | #define WM8990_MCLK_DIV 0 |
835 | #define WM8990_DACCLK_DIV 1 | 830 | #define WM8990_DACCLK_DIV 1 |
836 | #define WM8990_ADCCLK_DIV 2 | 831 | #define WM8990_ADCCLK_DIV 2 |
837 | #define WM8990_BCLK_DIV 3 | 832 | #define WM8990_BCLK_DIV 3 |
838 | 833 | ||
839 | extern struct snd_soc_dai wm8990_dai; | ||
840 | extern struct snd_soc_codec_device soc_codec_dev_wm8990; | ||
841 | |||
842 | #endif /* __WM8990REGISTERDEFS_H__ */ | 834 | #endif /* __WM8990REGISTERDEFS_H__ */ |
843 | /*------------------------------ END OF FILE ---------------------------------*/ | 835 | /*------------------------------ END OF FILE ---------------------------------*/ |
diff --git a/sound/soc/codecs/wm8993.c b/sound/soc/codecs/wm8993.c index d8d300c6175f..a3fd6b935804 100644 --- a/sound/soc/codecs/wm8993.c +++ b/sound/soc/codecs/wm8993.c | |||
@@ -229,7 +229,7 @@ struct wm8993_priv { | |||
229 | u16 reg_cache[WM8993_REGISTER_COUNT]; | 229 | u16 reg_cache[WM8993_REGISTER_COUNT]; |
230 | struct regulator_bulk_data supplies[WM8993_NUM_SUPPLIES]; | 230 | struct regulator_bulk_data supplies[WM8993_NUM_SUPPLIES]; |
231 | struct wm8993_platform_data pdata; | 231 | struct wm8993_platform_data pdata; |
232 | struct snd_soc_codec codec; | 232 | enum snd_soc_control_type control_type; |
233 | int master; | 233 | int master; |
234 | int sysclk_source; | 234 | int sysclk_source; |
235 | int tdm_slots; | 235 | int tdm_slots; |
@@ -367,10 +367,9 @@ static int fll_factors(struct _fll_div *fll_div, unsigned int Fref, | |||
367 | return 0; | 367 | return 0; |
368 | } | 368 | } |
369 | 369 | ||
370 | static int wm8993_set_fll(struct snd_soc_dai *dai, int fll_id, int source, | 370 | static int _wm8993_set_fll(struct snd_soc_codec *codec, int fll_id, int source, |
371 | unsigned int Fref, unsigned int Fout) | 371 | unsigned int Fref, unsigned int Fout) |
372 | { | 372 | { |
373 | struct snd_soc_codec *codec = dai->codec; | ||
374 | struct wm8993_priv *wm8993 = snd_soc_codec_get_drvdata(codec); | 373 | struct wm8993_priv *wm8993 = snd_soc_codec_get_drvdata(codec); |
375 | u16 reg1, reg4, reg5; | 374 | u16 reg1, reg4, reg5; |
376 | struct _fll_div fll_div; | 375 | struct _fll_div fll_div; |
@@ -456,6 +455,12 @@ static int wm8993_set_fll(struct snd_soc_dai *dai, int fll_id, int source, | |||
456 | return 0; | 455 | return 0; |
457 | } | 456 | } |
458 | 457 | ||
458 | static int wm8993_set_fll(struct snd_soc_dai *dai, int fll_id, int source, | ||
459 | unsigned int Fref, unsigned int Fout) | ||
460 | { | ||
461 | return _wm8993_set_fll(dai->codec, fll_id, source, Fref, Fout); | ||
462 | } | ||
463 | |||
459 | static int configure_clock(struct snd_soc_codec *codec) | 464 | static int configure_clock(struct snd_soc_codec *codec) |
460 | { | 465 | { |
461 | struct wm8993_priv *wm8993 = snd_soc_codec_get_drvdata(codec); | 466 | struct wm8993_priv *wm8993 = snd_soc_codec_get_drvdata(codec); |
@@ -1394,8 +1399,8 @@ static struct snd_soc_dai_ops wm8993_ops = { | |||
1394 | SNDRV_PCM_FMTBIT_S24_LE |\ | 1399 | SNDRV_PCM_FMTBIT_S24_LE |\ |
1395 | SNDRV_PCM_FMTBIT_S32_LE) | 1400 | SNDRV_PCM_FMTBIT_S32_LE) |
1396 | 1401 | ||
1397 | struct snd_soc_dai wm8993_dai = { | 1402 | static struct snd_soc_dai_driver wm8993_dai = { |
1398 | .name = "WM8993", | 1403 | .name = "wm8993-hifi", |
1399 | .playback = { | 1404 | .playback = { |
1400 | .stream_name = "Playback", | 1405 | .stream_name = "Playback", |
1401 | .channels_min = 1, | 1406 | .channels_min = 1, |
@@ -1413,32 +1418,81 @@ struct snd_soc_dai wm8993_dai = { | |||
1413 | .ops = &wm8993_ops, | 1418 | .ops = &wm8993_ops, |
1414 | .symmetric_rates = 1, | 1419 | .symmetric_rates = 1, |
1415 | }; | 1420 | }; |
1416 | EXPORT_SYMBOL_GPL(wm8993_dai); | ||
1417 | |||
1418 | static struct snd_soc_codec *wm8993_codec; | ||
1419 | 1421 | ||
1420 | static int wm8993_probe(struct platform_device *pdev) | 1422 | static int wm8993_probe(struct snd_soc_codec *codec) |
1421 | { | 1423 | { |
1422 | struct snd_soc_device *socdev = platform_get_drvdata(pdev); | 1424 | struct wm8993_priv *wm8993 = snd_soc_codec_get_drvdata(codec); |
1423 | struct snd_soc_codec *codec; | 1425 | int ret, i, val; |
1424 | struct wm8993_priv *wm8993; | 1426 | |
1425 | int ret = 0; | 1427 | wm8993->hubs_data.hp_startup_mode = 1; |
1428 | wm8993->hubs_data.dcs_codes = -2; | ||
1429 | |||
1430 | ret = snd_soc_codec_set_cache_io(codec, 8, 16, SND_SOC_I2C); | ||
1431 | if (ret != 0) { | ||
1432 | dev_err(codec->dev, "Failed to set cache I/O: %d\n", ret); | ||
1433 | return ret; | ||
1434 | } | ||
1435 | |||
1436 | for (i = 0; i < ARRAY_SIZE(wm8993->supplies); i++) | ||
1437 | wm8993->supplies[i].supply = wm8993_supply_names[i]; | ||
1426 | 1438 | ||
1427 | if (!wm8993_codec) { | 1439 | ret = regulator_bulk_get(codec->dev, ARRAY_SIZE(wm8993->supplies), |
1428 | dev_err(&pdev->dev, "I2C device not yet probed\n"); | 1440 | wm8993->supplies); |
1429 | goto err; | 1441 | if (ret != 0) { |
1442 | dev_err(codec->dev, "Failed to request supplies: %d\n", ret); | ||
1443 | return ret; | ||
1430 | } | 1444 | } |
1431 | 1445 | ||
1432 | socdev->card->codec = wm8993_codec; | 1446 | ret = regulator_bulk_enable(ARRAY_SIZE(wm8993->supplies), |
1433 | codec = wm8993_codec; | 1447 | wm8993->supplies); |
1434 | wm8993 = snd_soc_codec_get_drvdata(codec); | 1448 | if (ret != 0) { |
1449 | dev_err(codec->dev, "Failed to enable supplies: %d\n", ret); | ||
1450 | goto err_get; | ||
1451 | } | ||
1435 | 1452 | ||
1436 | ret = snd_soc_new_pcms(socdev, SNDRV_DEFAULT_IDX1, SNDRV_DEFAULT_STR1); | 1453 | val = snd_soc_read(codec, WM8993_SOFTWARE_RESET); |
1437 | if (ret < 0) { | 1454 | if (val != wm8993_reg_defaults[WM8993_SOFTWARE_RESET]) { |
1438 | dev_err(codec->dev, "failed to create pcms\n"); | 1455 | dev_err(codec->dev, "Invalid ID register value %x\n", val); |
1439 | goto err; | 1456 | ret = -EINVAL; |
1457 | goto err_enable; | ||
1440 | } | 1458 | } |
1441 | 1459 | ||
1460 | ret = snd_soc_write(codec, WM8993_SOFTWARE_RESET, 0xffff); | ||
1461 | if (ret != 0) | ||
1462 | goto err_enable; | ||
1463 | |||
1464 | codec->cache_only = 1; | ||
1465 | |||
1466 | /* By default we're using the output mixers */ | ||
1467 | wm8993->class_w_users = 2; | ||
1468 | |||
1469 | /* Latch volume update bits and default ZC on */ | ||
1470 | snd_soc_update_bits(codec, WM8993_RIGHT_DAC_DIGITAL_VOLUME, | ||
1471 | WM8993_DAC_VU, WM8993_DAC_VU); | ||
1472 | snd_soc_update_bits(codec, WM8993_RIGHT_ADC_DIGITAL_VOLUME, | ||
1473 | WM8993_ADC_VU, WM8993_ADC_VU); | ||
1474 | |||
1475 | /* Manualy manage the HPOUT sequencing for independent stereo | ||
1476 | * control. */ | ||
1477 | snd_soc_update_bits(codec, WM8993_ANALOGUE_HP_0, | ||
1478 | WM8993_HPOUT1_AUTO_PU, 0); | ||
1479 | |||
1480 | /* Use automatic clock configuration */ | ||
1481 | snd_soc_update_bits(codec, WM8993_CLOCKING_4, WM8993_SR_MODE, 0); | ||
1482 | |||
1483 | wm_hubs_handle_analogue_pdata(codec, wm8993->pdata.lineout1_diff, | ||
1484 | wm8993->pdata.lineout2_diff, | ||
1485 | wm8993->pdata.lineout1fb, | ||
1486 | wm8993->pdata.lineout2fb, | ||
1487 | wm8993->pdata.jd_scthr, | ||
1488 | wm8993->pdata.jd_thr, | ||
1489 | wm8993->pdata.micbias1_lvl, | ||
1490 | wm8993->pdata.micbias2_lvl); | ||
1491 | |||
1492 | ret = wm8993_set_bias_level(codec, SND_SOC_BIAS_STANDBY); | ||
1493 | if (ret != 0) | ||
1494 | goto err_enable; | ||
1495 | |||
1442 | snd_soc_add_controls(codec, wm8993_snd_controls, | 1496 | snd_soc_add_controls(codec, wm8993_snd_controls, |
1443 | ARRAY_SIZE(wm8993_snd_controls)); | 1497 | ARRAY_SIZE(wm8993_snd_controls)); |
1444 | if (wm8993->pdata.num_retune_configs != 0) { | 1498 | if (wm8993->pdata.num_retune_configs != 0) { |
@@ -1457,36 +1511,36 @@ static int wm8993_probe(struct platform_device *pdev) | |||
1457 | wm_hubs_add_analogue_routes(codec, wm8993->pdata.lineout1_diff, | 1511 | wm_hubs_add_analogue_routes(codec, wm8993->pdata.lineout1_diff, |
1458 | wm8993->pdata.lineout2_diff); | 1512 | wm8993->pdata.lineout2_diff); |
1459 | 1513 | ||
1460 | return ret; | 1514 | return 0; |
1461 | 1515 | ||
1462 | err: | 1516 | err_enable: |
1517 | regulator_bulk_disable(ARRAY_SIZE(wm8993->supplies), wm8993->supplies); | ||
1518 | err_get: | ||
1519 | regulator_bulk_free(ARRAY_SIZE(wm8993->supplies), wm8993->supplies); | ||
1463 | return ret; | 1520 | return ret; |
1464 | } | 1521 | } |
1465 | 1522 | ||
1466 | static int wm8993_remove(struct platform_device *pdev) | 1523 | static int wm8993_remove(struct snd_soc_codec *codec) |
1467 | { | 1524 | { |
1468 | struct snd_soc_device *socdev = platform_get_drvdata(pdev); | 1525 | struct wm8993_priv *wm8993 = snd_soc_codec_get_drvdata(codec); |
1469 | |||
1470 | snd_soc_free_pcms(socdev); | ||
1471 | snd_soc_dapm_free(socdev); | ||
1472 | 1526 | ||
1527 | wm8993_set_bias_level(codec, SND_SOC_BIAS_OFF); | ||
1528 | regulator_bulk_free(ARRAY_SIZE(wm8993->supplies), wm8993->supplies); | ||
1473 | return 0; | 1529 | return 0; |
1474 | } | 1530 | } |
1475 | 1531 | ||
1476 | #ifdef CONFIG_PM | 1532 | #ifdef CONFIG_PM |
1477 | static int wm8993_suspend(struct platform_device *pdev, pm_message_t state) | 1533 | static int wm8993_suspend(struct snd_soc_codec *codec, pm_message_t state) |
1478 | { | 1534 | { |
1479 | struct snd_soc_device *socdev = platform_get_drvdata(pdev); | ||
1480 | struct snd_soc_codec *codec = socdev->card->codec; | ||
1481 | struct wm8993_priv *wm8993 = snd_soc_codec_get_drvdata(codec); | 1535 | struct wm8993_priv *wm8993 = snd_soc_codec_get_drvdata(codec); |
1482 | int fll_fout = wm8993->fll_fout; | 1536 | int fll_fout = wm8993->fll_fout; |
1483 | int fll_fref = wm8993->fll_fref; | 1537 | int fll_fref = wm8993->fll_fref; |
1484 | int ret; | 1538 | int ret; |
1485 | 1539 | ||
1486 | /* Stop the FLL in an orderly fashion */ | 1540 | /* Stop the FLL in an orderly fashion */ |
1487 | ret = wm8993_set_fll(codec->dai, 0, 0, 0, 0); | 1541 | ret = _wm8993_set_fll(codec, 0, 0, 0, 0); |
1488 | if (ret != 0) { | 1542 | if (ret != 0) { |
1489 | dev_err(&pdev->dev, "Failed to stop FLL\n"); | 1543 | dev_err(codec->dev, "Failed to stop FLL\n"); |
1490 | return ret; | 1544 | return ret; |
1491 | } | 1545 | } |
1492 | 1546 | ||
@@ -1498,10 +1552,8 @@ static int wm8993_suspend(struct platform_device *pdev, pm_message_t state) | |||
1498 | return 0; | 1552 | return 0; |
1499 | } | 1553 | } |
1500 | 1554 | ||
1501 | static int wm8993_resume(struct platform_device *pdev) | 1555 | static int wm8993_resume(struct snd_soc_codec *codec) |
1502 | { | 1556 | { |
1503 | struct snd_soc_device *socdev = platform_get_drvdata(pdev); | ||
1504 | struct snd_soc_codec *codec = socdev->card->codec; | ||
1505 | struct wm8993_priv *wm8993 = snd_soc_codec_get_drvdata(codec); | 1557 | struct wm8993_priv *wm8993 = snd_soc_codec_get_drvdata(codec); |
1506 | int ret; | 1558 | int ret; |
1507 | 1559 | ||
@@ -1515,7 +1567,7 @@ static int wm8993_resume(struct platform_device *pdev) | |||
1515 | wm8993->fll_fref = 0; | 1567 | wm8993->fll_fref = 0; |
1516 | wm8993->fll_fout = 0; | 1568 | wm8993->fll_fout = 0; |
1517 | 1569 | ||
1518 | ret = wm8993_set_fll(codec->dai, 0, wm8993->fll_src, | 1570 | ret = _wm8993_set_fll(codec, 0, wm8993->fll_src, |
1519 | fll_fref, fll_fout); | 1571 | fll_fref, fll_fout); |
1520 | if (ret != 0) | 1572 | if (ret != 0) |
1521 | dev_err(codec->dev, "Failed to restart FLL\n"); | 1573 | dev_err(codec->dev, "Failed to restart FLL\n"); |
@@ -1528,162 +1580,42 @@ static int wm8993_resume(struct platform_device *pdev) | |||
1528 | #define wm8993_resume NULL | 1580 | #define wm8993_resume NULL |
1529 | #endif | 1581 | #endif |
1530 | 1582 | ||
1531 | struct snd_soc_codec_device soc_codec_dev_wm8993 = { | 1583 | static struct snd_soc_codec_driver soc_codec_dev_wm8993 = { |
1532 | .probe = wm8993_probe, | 1584 | .probe = wm8993_probe, |
1533 | .remove = wm8993_remove, | 1585 | .remove = wm8993_remove, |
1534 | .suspend = wm8993_suspend, | 1586 | .suspend = wm8993_suspend, |
1535 | .resume = wm8993_resume, | 1587 | .resume = wm8993_resume, |
1588 | .set_bias_level = wm8993_set_bias_level, | ||
1589 | .reg_cache_size = sizeof(wm8993_reg_defaults), | ||
1590 | .reg_word_size = sizeof(u16), | ||
1591 | .reg_cache_default = wm8993_reg_defaults, | ||
1592 | .volatile_register = wm8993_volatile, | ||
1536 | }; | 1593 | }; |
1537 | EXPORT_SYMBOL_GPL(soc_codec_dev_wm8993); | ||
1538 | 1594 | ||
1539 | static int wm8993_i2c_probe(struct i2c_client *i2c, | 1595 | #if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE) |
1540 | const struct i2c_device_id *id) | 1596 | static __devinit int wm8993_i2c_probe(struct i2c_client *i2c, |
1597 | const struct i2c_device_id *id) | ||
1541 | { | 1598 | { |
1542 | struct wm8993_priv *wm8993; | 1599 | struct wm8993_priv *wm8993; |
1543 | struct snd_soc_codec *codec; | ||
1544 | unsigned int val; | ||
1545 | int ret; | 1600 | int ret; |
1546 | int i; | ||
1547 | |||
1548 | if (wm8993_codec) { | ||
1549 | dev_err(&i2c->dev, "A WM8993 is already registered\n"); | ||
1550 | return -EINVAL; | ||
1551 | } | ||
1552 | 1601 | ||
1553 | wm8993 = kzalloc(sizeof(struct wm8993_priv), GFP_KERNEL); | 1602 | wm8993 = kzalloc(sizeof(struct wm8993_priv), GFP_KERNEL); |
1554 | if (wm8993 == NULL) | 1603 | if (wm8993 == NULL) |
1555 | return -ENOMEM; | 1604 | return -ENOMEM; |
1556 | 1605 | ||
1557 | codec = &wm8993->codec; | ||
1558 | if (i2c->dev.platform_data) | ||
1559 | memcpy(&wm8993->pdata, i2c->dev.platform_data, | ||
1560 | sizeof(wm8993->pdata)); | ||
1561 | |||
1562 | mutex_init(&codec->mutex); | ||
1563 | INIT_LIST_HEAD(&codec->dapm_widgets); | ||
1564 | INIT_LIST_HEAD(&codec->dapm_paths); | ||
1565 | |||
1566 | codec->name = "WM8993"; | ||
1567 | codec->volatile_register = wm8993_volatile; | ||
1568 | codec->reg_cache = wm8993->reg_cache; | ||
1569 | codec->reg_cache_size = ARRAY_SIZE(wm8993->reg_cache); | ||
1570 | codec->bias_level = SND_SOC_BIAS_OFF; | ||
1571 | codec->set_bias_level = wm8993_set_bias_level; | ||
1572 | codec->dai = &wm8993_dai; | ||
1573 | codec->num_dai = 1; | ||
1574 | snd_soc_codec_set_drvdata(codec, wm8993); | ||
1575 | |||
1576 | wm8993->hubs_data.hp_startup_mode = 1; | ||
1577 | wm8993->hubs_data.dcs_codes = -2; | ||
1578 | |||
1579 | memcpy(wm8993->reg_cache, wm8993_reg_defaults, | ||
1580 | sizeof(wm8993->reg_cache)); | ||
1581 | |||
1582 | ret = snd_soc_codec_set_cache_io(codec, 8, 16, SND_SOC_I2C); | ||
1583 | if (ret != 0) { | ||
1584 | dev_err(codec->dev, "Failed to set cache I/O: %d\n", ret); | ||
1585 | goto err; | ||
1586 | } | ||
1587 | |||
1588 | i2c_set_clientdata(i2c, wm8993); | 1606 | i2c_set_clientdata(i2c, wm8993); |
1589 | codec->control_data = i2c; | ||
1590 | wm8993_codec = codec; | ||
1591 | |||
1592 | codec->dev = &i2c->dev; | ||
1593 | |||
1594 | for (i = 0; i < ARRAY_SIZE(wm8993->supplies); i++) | ||
1595 | wm8993->supplies[i].supply = wm8993_supply_names[i]; | ||
1596 | |||
1597 | ret = regulator_bulk_get(codec->dev, ARRAY_SIZE(wm8993->supplies), | ||
1598 | wm8993->supplies); | ||
1599 | if (ret != 0) { | ||
1600 | dev_err(codec->dev, "Failed to request supplies: %d\n", ret); | ||
1601 | goto err; | ||
1602 | } | ||
1603 | |||
1604 | ret = regulator_bulk_enable(ARRAY_SIZE(wm8993->supplies), | ||
1605 | wm8993->supplies); | ||
1606 | if (ret != 0) { | ||
1607 | dev_err(codec->dev, "Failed to enable supplies: %d\n", ret); | ||
1608 | goto err_get; | ||
1609 | } | ||
1610 | |||
1611 | val = snd_soc_read(codec, WM8993_SOFTWARE_RESET); | ||
1612 | if (val != wm8993_reg_defaults[WM8993_SOFTWARE_RESET]) { | ||
1613 | dev_err(codec->dev, "Invalid ID register value %x\n", val); | ||
1614 | ret = -EINVAL; | ||
1615 | goto err_enable; | ||
1616 | } | ||
1617 | |||
1618 | ret = snd_soc_write(codec, WM8993_SOFTWARE_RESET, 0xffff); | ||
1619 | if (ret != 0) | ||
1620 | goto err_enable; | ||
1621 | |||
1622 | codec->cache_only = 1; | ||
1623 | |||
1624 | /* By default we're using the output mixers */ | ||
1625 | wm8993->class_w_users = 2; | ||
1626 | |||
1627 | /* Latch volume update bits and default ZC on */ | ||
1628 | snd_soc_update_bits(codec, WM8993_RIGHT_DAC_DIGITAL_VOLUME, | ||
1629 | WM8993_DAC_VU, WM8993_DAC_VU); | ||
1630 | snd_soc_update_bits(codec, WM8993_RIGHT_ADC_DIGITAL_VOLUME, | ||
1631 | WM8993_ADC_VU, WM8993_ADC_VU); | ||
1632 | 1607 | ||
1633 | /* Manualy manage the HPOUT sequencing for independent stereo | 1608 | ret = snd_soc_register_codec(&i2c->dev, |
1634 | * control. */ | 1609 | &soc_codec_dev_wm8993, &wm8993_dai, 1); |
1635 | snd_soc_update_bits(codec, WM8993_ANALOGUE_HP_0, | 1610 | if (ret < 0) |
1636 | WM8993_HPOUT1_AUTO_PU, 0); | 1611 | kfree(wm8993); |
1637 | |||
1638 | /* Use automatic clock configuration */ | ||
1639 | snd_soc_update_bits(codec, WM8993_CLOCKING_4, WM8993_SR_MODE, 0); | ||
1640 | |||
1641 | wm_hubs_handle_analogue_pdata(codec, wm8993->pdata.lineout1_diff, | ||
1642 | wm8993->pdata.lineout2_diff, | ||
1643 | wm8993->pdata.lineout1fb, | ||
1644 | wm8993->pdata.lineout2fb, | ||
1645 | wm8993->pdata.jd_scthr, | ||
1646 | wm8993->pdata.jd_thr, | ||
1647 | wm8993->pdata.micbias1_lvl, | ||
1648 | wm8993->pdata.micbias2_lvl); | ||
1649 | |||
1650 | ret = wm8993_set_bias_level(codec, SND_SOC_BIAS_STANDBY); | ||
1651 | if (ret != 0) | ||
1652 | goto err_enable; | ||
1653 | |||
1654 | wm8993_dai.dev = codec->dev; | ||
1655 | |||
1656 | ret = snd_soc_register_dai(&wm8993_dai); | ||
1657 | if (ret != 0) | ||
1658 | goto err_bias; | ||
1659 | |||
1660 | ret = snd_soc_register_codec(codec); | ||
1661 | |||
1662 | return 0; | ||
1663 | |||
1664 | err_bias: | ||
1665 | wm8993_set_bias_level(codec, SND_SOC_BIAS_OFF); | ||
1666 | err_enable: | ||
1667 | regulator_bulk_disable(ARRAY_SIZE(wm8993->supplies), wm8993->supplies); | ||
1668 | err_get: | ||
1669 | regulator_bulk_free(ARRAY_SIZE(wm8993->supplies), wm8993->supplies); | ||
1670 | err: | ||
1671 | wm8993_codec = NULL; | ||
1672 | kfree(wm8993); | ||
1673 | return ret; | 1612 | return ret; |
1674 | } | 1613 | } |
1675 | 1614 | ||
1676 | static int wm8993_i2c_remove(struct i2c_client *client) | 1615 | static __devexit int wm8993_i2c_remove(struct i2c_client *client) |
1677 | { | 1616 | { |
1678 | struct wm8993_priv *wm8993 = i2c_get_clientdata(client); | 1617 | snd_soc_unregister_codec(&client->dev); |
1679 | 1618 | kfree(i2c_get_clientdata(client)); | |
1680 | snd_soc_unregister_codec(&wm8993->codec); | ||
1681 | snd_soc_unregister_dai(&wm8993_dai); | ||
1682 | |||
1683 | wm8993_set_bias_level(&wm8993->codec, SND_SOC_BIAS_OFF); | ||
1684 | regulator_bulk_free(ARRAY_SIZE(wm8993->supplies), wm8993->supplies); | ||
1685 | kfree(wm8993); | ||
1686 | |||
1687 | return 0; | 1619 | return 0; |
1688 | } | 1620 | } |
1689 | 1621 | ||
@@ -1695,30 +1627,34 @@ MODULE_DEVICE_TABLE(i2c, wm8993_i2c_id); | |||
1695 | 1627 | ||
1696 | static struct i2c_driver wm8993_i2c_driver = { | 1628 | static struct i2c_driver wm8993_i2c_driver = { |
1697 | .driver = { | 1629 | .driver = { |
1698 | .name = "WM8993", | 1630 | .name = "wm8993-codec", |
1699 | .owner = THIS_MODULE, | 1631 | .owner = THIS_MODULE, |
1700 | }, | 1632 | }, |
1701 | .probe = wm8993_i2c_probe, | 1633 | .probe = wm8993_i2c_probe, |
1702 | .remove = wm8993_i2c_remove, | 1634 | .remove = __devexit_p(wm8993_i2c_remove), |
1703 | .id_table = wm8993_i2c_id, | 1635 | .id_table = wm8993_i2c_id, |
1704 | }; | 1636 | }; |
1705 | 1637 | #endif | |
1706 | 1638 | ||
1707 | static int __init wm8993_modinit(void) | 1639 | static int __init wm8993_modinit(void) |
1708 | { | 1640 | { |
1709 | int ret; | 1641 | int ret = 0; |
1710 | 1642 | #if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE) | |
1711 | ret = i2c_add_driver(&wm8993_i2c_driver); | 1643 | ret = i2c_add_driver(&wm8993_i2c_driver); |
1712 | if (ret != 0) | 1644 | if (ret != 0) { |
1713 | pr_err("WM8993: Unable to register I2C driver: %d\n", ret); | 1645 | pr_err("WM8993: Unable to register I2C driver: %d\n", |
1714 | 1646 | ret); | |
1647 | } | ||
1648 | #endif | ||
1715 | return ret; | 1649 | return ret; |
1716 | } | 1650 | } |
1717 | module_init(wm8993_modinit); | 1651 | module_init(wm8993_modinit); |
1718 | 1652 | ||
1719 | static void __exit wm8993_exit(void) | 1653 | static void __exit wm8993_exit(void) |
1720 | { | 1654 | { |
1655 | #if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE) | ||
1721 | i2c_del_driver(&wm8993_i2c_driver); | 1656 | i2c_del_driver(&wm8993_i2c_driver); |
1657 | #endif | ||
1722 | } | 1658 | } |
1723 | module_exit(wm8993_exit); | 1659 | module_exit(wm8993_exit); |
1724 | 1660 | ||
diff --git a/sound/soc/codecs/wm8993.h b/sound/soc/codecs/wm8993.h index 30e71ca88dad..2184617b9611 100644 --- a/sound/soc/codecs/wm8993.h +++ b/sound/soc/codecs/wm8993.h | |||
@@ -1,9 +1,6 @@ | |||
1 | #ifndef WM8993_H | 1 | #ifndef WM8993_H |
2 | #define WM8993_H | 2 | #define WM8993_H |
3 | 3 | ||
4 | extern struct snd_soc_dai wm8993_dai; | ||
5 | extern struct snd_soc_codec_device soc_codec_dev_wm8993; | ||
6 | |||
7 | #define WM8993_SYSCLK_MCLK 1 | 4 | #define WM8993_SYSCLK_MCLK 1 |
8 | #define WM8993_SYSCLK_FLL 2 | 5 | #define WM8993_SYSCLK_FLL 2 |
9 | 6 | ||
diff --git a/sound/soc/codecs/wm8994.c b/sound/soc/codecs/wm8994.c index a87046a96f2a..7823f92413f3 100644 --- a/sound/soc/codecs/wm8994.c +++ b/sound/soc/codecs/wm8994.c | |||
@@ -36,9 +36,6 @@ | |||
36 | #include "wm8994.h" | 36 | #include "wm8994.h" |
37 | #include "wm_hubs.h" | 37 | #include "wm_hubs.h" |
38 | 38 | ||
39 | static struct snd_soc_codec *wm8994_codec; | ||
40 | struct snd_soc_codec_device soc_codec_dev_wm8994; | ||
41 | |||
42 | struct fll_config { | 39 | struct fll_config { |
43 | int src; | 40 | int src; |
44 | int in; | 41 | int in; |
@@ -71,7 +68,9 @@ struct wm8994_micdet { | |||
71 | /* codec private data */ | 68 | /* codec private data */ |
72 | struct wm8994_priv { | 69 | struct wm8994_priv { |
73 | struct wm_hubs_data hubs; | 70 | struct wm_hubs_data hubs; |
74 | struct snd_soc_codec codec; | 71 | enum snd_soc_control_type control_type; |
72 | void *control_data; | ||
73 | struct snd_soc_codec *codec; | ||
75 | u16 reg_cache[WM8994_REG_CACHE_SIZE + 1]; | 74 | u16 reg_cache[WM8994_REG_CACHE_SIZE + 1]; |
76 | int sysclk[2]; | 75 | int sysclk[2]; |
77 | int sysclk_rate[2]; | 76 | int sysclk_rate[2]; |
@@ -1901,8 +1900,6 @@ static int wm8994_put_drc_sw(struct snd_kcontrol *kcontrol, | |||
1901 | return snd_soc_put_volsw(kcontrol, ucontrol); | 1900 | return snd_soc_put_volsw(kcontrol, ucontrol); |
1902 | } | 1901 | } |
1903 | 1902 | ||
1904 | |||
1905 | |||
1906 | static void wm8994_set_drc(struct snd_soc_codec *codec, int drc) | 1903 | static void wm8994_set_drc(struct snd_soc_codec *codec, int drc) |
1907 | { | 1904 | { |
1908 | struct wm8994_priv *wm8994 = snd_soc_codec_get_drvdata(codec); | 1905 | struct wm8994_priv *wm8994 = snd_soc_codec_get_drvdata(codec); |
@@ -1941,7 +1938,7 @@ static int wm8994_put_drc_enum(struct snd_kcontrol *kcontrol, | |||
1941 | struct snd_ctl_elem_value *ucontrol) | 1938 | struct snd_ctl_elem_value *ucontrol) |
1942 | { | 1939 | { |
1943 | struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol); | 1940 | struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol); |
1944 | struct wm8994_priv *wm8994 = snd_soc_codec_get_drvdata(codec); | 1941 | struct wm8994_priv *wm8994 = snd_soc_codec_get_drvdata(codec); |
1945 | struct wm8994_pdata *pdata = wm8994->pdata; | 1942 | struct wm8994_pdata *pdata = wm8994->pdata; |
1946 | int drc = wm8994_get_drc(kcontrol->id.name); | 1943 | int drc = wm8994_get_drc(kcontrol->id.name); |
1947 | int value = ucontrol->value.integer.value[0]; | 1944 | int value = ucontrol->value.integer.value[0]; |
@@ -2044,7 +2041,7 @@ static int wm8994_put_retune_mobile_enum(struct snd_kcontrol *kcontrol, | |||
2044 | struct snd_ctl_elem_value *ucontrol) | 2041 | struct snd_ctl_elem_value *ucontrol) |
2045 | { | 2042 | { |
2046 | struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol); | 2043 | struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol); |
2047 | struct wm8994_priv *wm8994 = snd_soc_codec_get_drvdata(codec); | 2044 | struct wm8994_priv *wm8994 = snd_soc_codec_get_drvdata(codec); |
2048 | struct wm8994_pdata *pdata = wm8994->pdata; | 2045 | struct wm8994_pdata *pdata = wm8994->pdata; |
2049 | int block = wm8994_get_retune_mobile_block(kcontrol->id.name); | 2046 | int block = wm8994_get_retune_mobile_block(kcontrol->id.name); |
2050 | int value = ucontrol->value.integer.value[0]; | 2047 | int value = ucontrol->value.integer.value[0]; |
@@ -2066,7 +2063,7 @@ static int wm8994_get_retune_mobile_enum(struct snd_kcontrol *kcontrol, | |||
2066 | struct snd_ctl_elem_value *ucontrol) | 2063 | struct snd_ctl_elem_value *ucontrol) |
2067 | { | 2064 | { |
2068 | struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol); | 2065 | struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol); |
2069 | struct wm8994_priv *wm8994 = snd_soc_codec_get_drvdata(codec); | 2066 | struct wm8994_priv *wm8994 =snd_soc_codec_get_drvdata(codec); |
2070 | int block = wm8994_get_retune_mobile_block(kcontrol->id.name); | 2067 | int block = wm8994_get_retune_mobile_block(kcontrol->id.name); |
2071 | 2068 | ||
2072 | ucontrol->value.enumerated.item[0] = wm8994->retune_mobile_cfg[block]; | 2069 | ucontrol->value.enumerated.item[0] = wm8994->retune_mobile_cfg[block]; |
@@ -2880,10 +2877,9 @@ static int wm8994_get_fll_config(struct fll_div *fll, | |||
2880 | return 0; | 2877 | return 0; |
2881 | } | 2878 | } |
2882 | 2879 | ||
2883 | static int wm8994_set_fll(struct snd_soc_dai *dai, int id, int src, | 2880 | static int _wm8994_set_fll(struct snd_soc_codec *codec, int id, int src, |
2884 | unsigned int freq_in, unsigned int freq_out) | 2881 | unsigned int freq_in, unsigned int freq_out) |
2885 | { | 2882 | { |
2886 | struct snd_soc_codec *codec = dai->codec; | ||
2887 | struct wm8994_priv *wm8994 = snd_soc_codec_get_drvdata(codec); | 2883 | struct wm8994_priv *wm8994 = snd_soc_codec_get_drvdata(codec); |
2888 | int reg_offset, ret; | 2884 | int reg_offset, ret; |
2889 | struct fll_div fll; | 2885 | struct fll_div fll; |
@@ -2994,8 +2990,15 @@ static int wm8994_set_fll(struct snd_soc_dai *dai, int id, int src, | |||
2994 | return 0; | 2990 | return 0; |
2995 | } | 2991 | } |
2996 | 2992 | ||
2993 | |||
2997 | static int opclk_divs[] = { 10, 20, 30, 40, 55, 60, 80, 120, 160 }; | 2994 | static int opclk_divs[] = { 10, 20, 30, 40, 55, 60, 80, 120, 160 }; |
2998 | 2995 | ||
2996 | static int wm8994_set_fll(struct snd_soc_dai *dai, int id, int src, | ||
2997 | unsigned int freq_in, unsigned int freq_out) | ||
2998 | { | ||
2999 | return _wm8994_set_fll(dai->codec, id, src, freq_in, freq_out); | ||
3000 | } | ||
3001 | |||
2999 | static int wm8994_set_dai_sysclk(struct snd_soc_dai *dai, | 3002 | static int wm8994_set_dai_sysclk(struct snd_soc_dai *dai, |
3000 | int clk_id, unsigned int freq, int dir) | 3003 | int clk_id, unsigned int freq, int dir) |
3001 | { | 3004 | { |
@@ -3507,10 +3510,9 @@ static struct snd_soc_dai_ops wm8994_aif3_dai_ops = { | |||
3507 | .set_tristate = wm8994_set_tristate, | 3510 | .set_tristate = wm8994_set_tristate, |
3508 | }; | 3511 | }; |
3509 | 3512 | ||
3510 | struct snd_soc_dai wm8994_dai[] = { | 3513 | static struct snd_soc_dai_driver wm8994_dai[] = { |
3511 | { | 3514 | { |
3512 | .name = "WM8994 AIF1", | 3515 | .name = "wm8994-aif1", |
3513 | .id = 1, | ||
3514 | .playback = { | 3516 | .playback = { |
3515 | .stream_name = "AIF1 Playback", | 3517 | .stream_name = "AIF1 Playback", |
3516 | .channels_min = 2, | 3518 | .channels_min = 2, |
@@ -3528,8 +3530,7 @@ struct snd_soc_dai wm8994_dai[] = { | |||
3528 | .ops = &wm8994_aif1_dai_ops, | 3530 | .ops = &wm8994_aif1_dai_ops, |
3529 | }, | 3531 | }, |
3530 | { | 3532 | { |
3531 | .name = "WM8994 AIF2", | 3533 | .name = "wm8994-aif2", |
3532 | .id = 2, | ||
3533 | .playback = { | 3534 | .playback = { |
3534 | .stream_name = "AIF2 Playback", | 3535 | .stream_name = "AIF2 Playback", |
3535 | .channels_min = 2, | 3536 | .channels_min = 2, |
@@ -3547,8 +3548,7 @@ struct snd_soc_dai wm8994_dai[] = { | |||
3547 | .ops = &wm8994_aif2_dai_ops, | 3548 | .ops = &wm8994_aif2_dai_ops, |
3548 | }, | 3549 | }, |
3549 | { | 3550 | { |
3550 | .name = "WM8994 AIF3", | 3551 | .name = "wm8994-aif3", |
3551 | .id = 3, | ||
3552 | .playback = { | 3552 | .playback = { |
3553 | .stream_name = "AIF3 Playback", | 3553 | .stream_name = "AIF3 Playback", |
3554 | .channels_min = 2, | 3554 | .channels_min = 2, |
@@ -3566,20 +3566,17 @@ struct snd_soc_dai wm8994_dai[] = { | |||
3566 | .ops = &wm8994_aif3_dai_ops, | 3566 | .ops = &wm8994_aif3_dai_ops, |
3567 | } | 3567 | } |
3568 | }; | 3568 | }; |
3569 | EXPORT_SYMBOL_GPL(wm8994_dai); | ||
3570 | 3569 | ||
3571 | #ifdef CONFIG_PM | 3570 | #ifdef CONFIG_PM |
3572 | static int wm8994_suspend(struct platform_device *pdev, pm_message_t state) | 3571 | static int wm8994_suspend(struct snd_soc_codec *codec, pm_message_t state) |
3573 | { | 3572 | { |
3574 | struct snd_soc_device *socdev = platform_get_drvdata(pdev); | ||
3575 | struct snd_soc_codec *codec = socdev->card->codec; | ||
3576 | struct wm8994_priv *wm8994 = snd_soc_codec_get_drvdata(codec); | 3573 | struct wm8994_priv *wm8994 = snd_soc_codec_get_drvdata(codec); |
3577 | int i, ret; | 3574 | int i, ret; |
3578 | 3575 | ||
3579 | for (i = 0; i < ARRAY_SIZE(wm8994->fll); i++) { | 3576 | for (i = 0; i < ARRAY_SIZE(wm8994->fll); i++) { |
3580 | memcpy(&wm8994->fll_suspend[i], &wm8994->fll[i], | 3577 | memcpy(&wm8994->fll_suspend[i], &wm8994->fll[i], |
3581 | sizeof(struct fll_config)); | 3578 | sizeof(struct fll_config)); |
3582 | ret = wm8994_set_fll(&codec->dai[0], i + 1, 0, 0, 0); | 3579 | ret = _wm8994_set_fll(codec, i + 1, 0, 0, 0); |
3583 | if (ret < 0) | 3580 | if (ret < 0) |
3584 | dev_warn(codec->dev, "Failed to stop FLL%d: %d\n", | 3581 | dev_warn(codec->dev, "Failed to stop FLL%d: %d\n", |
3585 | i + 1, ret); | 3582 | i + 1, ret); |
@@ -3590,10 +3587,8 @@ static int wm8994_suspend(struct platform_device *pdev, pm_message_t state) | |||
3590 | return 0; | 3587 | return 0; |
3591 | } | 3588 | } |
3592 | 3589 | ||
3593 | static int wm8994_resume(struct platform_device *pdev) | 3590 | static int wm8994_resume(struct snd_soc_codec *codec) |
3594 | { | 3591 | { |
3595 | struct snd_soc_device *socdev = platform_get_drvdata(pdev); | ||
3596 | struct snd_soc_codec *codec = socdev->card->codec; | ||
3597 | struct wm8994_priv *wm8994 = snd_soc_codec_get_drvdata(codec); | 3592 | struct wm8994_priv *wm8994 = snd_soc_codec_get_drvdata(codec); |
3598 | u16 *reg_cache = codec->reg_cache; | 3593 | u16 *reg_cache = codec->reg_cache; |
3599 | int i, ret; | 3594 | int i, ret; |
@@ -3622,7 +3617,7 @@ static int wm8994_resume(struct platform_device *pdev) | |||
3622 | if (!wm8994->fll_suspend[i].out) | 3617 | if (!wm8994->fll_suspend[i].out) |
3623 | continue; | 3618 | continue; |
3624 | 3619 | ||
3625 | ret = wm8994_set_fll(&codec->dai[0], i + 1, | 3620 | ret = _wm8994_set_fll(codec, i + 1, |
3626 | wm8994->fll_suspend[i].src, | 3621 | wm8994->fll_suspend[i].src, |
3627 | wm8994->fll_suspend[i].in, | 3622 | wm8994->fll_suspend[i].in, |
3628 | wm8994->fll_suspend[i].out); | 3623 | wm8994->fll_suspend[i].out); |
@@ -3640,7 +3635,7 @@ static int wm8994_resume(struct platform_device *pdev) | |||
3640 | 3635 | ||
3641 | static void wm8994_handle_retune_mobile_pdata(struct wm8994_priv *wm8994) | 3636 | static void wm8994_handle_retune_mobile_pdata(struct wm8994_priv *wm8994) |
3642 | { | 3637 | { |
3643 | struct snd_soc_codec *codec = &wm8994->codec; | 3638 | struct snd_soc_codec *codec = wm8994->codec; |
3644 | struct wm8994_pdata *pdata = wm8994->pdata; | 3639 | struct wm8994_pdata *pdata = wm8994->pdata; |
3645 | struct snd_kcontrol_new controls[] = { | 3640 | struct snd_kcontrol_new controls[] = { |
3646 | SOC_ENUM_EXT("AIF1.1 EQ Mode", | 3641 | SOC_ENUM_EXT("AIF1.1 EQ Mode", |
@@ -3698,16 +3693,16 @@ static void wm8994_handle_retune_mobile_pdata(struct wm8994_priv *wm8994) | |||
3698 | wm8994->retune_mobile_enum.max = wm8994->num_retune_mobile_texts; | 3693 | wm8994->retune_mobile_enum.max = wm8994->num_retune_mobile_texts; |
3699 | wm8994->retune_mobile_enum.texts = wm8994->retune_mobile_texts; | 3694 | wm8994->retune_mobile_enum.texts = wm8994->retune_mobile_texts; |
3700 | 3695 | ||
3701 | ret = snd_soc_add_controls(&wm8994->codec, controls, | 3696 | ret = snd_soc_add_controls(wm8994->codec, controls, |
3702 | ARRAY_SIZE(controls)); | 3697 | ARRAY_SIZE(controls)); |
3703 | if (ret != 0) | 3698 | if (ret != 0) |
3704 | dev_err(wm8994->codec.dev, | 3699 | dev_err(wm8994->codec->dev, |
3705 | "Failed to add ReTune Mobile controls: %d\n", ret); | 3700 | "Failed to add ReTune Mobile controls: %d\n", ret); |
3706 | } | 3701 | } |
3707 | 3702 | ||
3708 | static void wm8994_handle_pdata(struct wm8994_priv *wm8994) | 3703 | static void wm8994_handle_pdata(struct wm8994_priv *wm8994) |
3709 | { | 3704 | { |
3710 | struct snd_soc_codec *codec = &wm8994->codec; | 3705 | struct snd_soc_codec *codec = wm8994->codec; |
3711 | struct wm8994_pdata *pdata = wm8994->pdata; | 3706 | struct wm8994_pdata *pdata = wm8994->pdata; |
3712 | int ret, i; | 3707 | int ret, i; |
3713 | 3708 | ||
@@ -3739,7 +3734,7 @@ static void wm8994_handle_pdata(struct wm8994_priv *wm8994) | |||
3739 | wm8994->drc_texts = kmalloc(sizeof(char *) | 3734 | wm8994->drc_texts = kmalloc(sizeof(char *) |
3740 | * pdata->num_drc_cfgs, GFP_KERNEL); | 3735 | * pdata->num_drc_cfgs, GFP_KERNEL); |
3741 | if (!wm8994->drc_texts) { | 3736 | if (!wm8994->drc_texts) { |
3742 | dev_err(wm8994->codec.dev, | 3737 | dev_err(wm8994->codec->dev, |
3743 | "Failed to allocate %d DRC config texts\n", | 3738 | "Failed to allocate %d DRC config texts\n", |
3744 | pdata->num_drc_cfgs); | 3739 | pdata->num_drc_cfgs); |
3745 | return; | 3740 | return; |
@@ -3751,10 +3746,10 @@ static void wm8994_handle_pdata(struct wm8994_priv *wm8994) | |||
3751 | wm8994->drc_enum.max = pdata->num_drc_cfgs; | 3746 | wm8994->drc_enum.max = pdata->num_drc_cfgs; |
3752 | wm8994->drc_enum.texts = wm8994->drc_texts; | 3747 | wm8994->drc_enum.texts = wm8994->drc_texts; |
3753 | 3748 | ||
3754 | ret = snd_soc_add_controls(&wm8994->codec, controls, | 3749 | ret = snd_soc_add_controls(wm8994->codec, controls, |
3755 | ARRAY_SIZE(controls)); | 3750 | ARRAY_SIZE(controls)); |
3756 | if (ret != 0) | 3751 | if (ret != 0) |
3757 | dev_err(wm8994->codec.dev, | 3752 | dev_err(wm8994->codec->dev, |
3758 | "Failed to add DRC mode controls: %d\n", ret); | 3753 | "Failed to add DRC mode controls: %d\n", ret); |
3759 | 3754 | ||
3760 | for (i = 0; i < WM8994_NUM_DRC; i++) | 3755 | for (i = 0; i < WM8994_NUM_DRC; i++) |
@@ -3767,62 +3762,10 @@ static void wm8994_handle_pdata(struct wm8994_priv *wm8994) | |||
3767 | if (pdata->num_retune_mobile_cfgs) | 3762 | if (pdata->num_retune_mobile_cfgs) |
3768 | wm8994_handle_retune_mobile_pdata(wm8994); | 3763 | wm8994_handle_retune_mobile_pdata(wm8994); |
3769 | else | 3764 | else |
3770 | snd_soc_add_controls(&wm8994->codec, wm8994_eq_controls, | 3765 | snd_soc_add_controls(wm8994->codec, wm8994_eq_controls, |
3771 | ARRAY_SIZE(wm8994_eq_controls)); | 3766 | ARRAY_SIZE(wm8994_eq_controls)); |
3772 | } | 3767 | } |
3773 | 3768 | ||
3774 | static int wm8994_probe(struct platform_device *pdev) | ||
3775 | { | ||
3776 | struct snd_soc_device *socdev = platform_get_drvdata(pdev); | ||
3777 | struct snd_soc_codec *codec; | ||
3778 | int ret = 0; | ||
3779 | |||
3780 | if (wm8994_codec == NULL) { | ||
3781 | dev_err(&pdev->dev, "Codec device not registered\n"); | ||
3782 | return -ENODEV; | ||
3783 | } | ||
3784 | |||
3785 | socdev->card->codec = wm8994_codec; | ||
3786 | codec = wm8994_codec; | ||
3787 | |||
3788 | /* register pcms */ | ||
3789 | ret = snd_soc_new_pcms(socdev, SNDRV_DEFAULT_IDX1, SNDRV_DEFAULT_STR1); | ||
3790 | if (ret < 0) { | ||
3791 | dev_err(codec->dev, "failed to create pcms: %d\n", ret); | ||
3792 | return ret; | ||
3793 | } | ||
3794 | |||
3795 | wm8994_handle_pdata(snd_soc_codec_get_drvdata(codec)); | ||
3796 | |||
3797 | wm_hubs_add_analogue_controls(codec); | ||
3798 | snd_soc_add_controls(codec, wm8994_snd_controls, | ||
3799 | ARRAY_SIZE(wm8994_snd_controls)); | ||
3800 | snd_soc_dapm_new_controls(codec, wm8994_dapm_widgets, | ||
3801 | ARRAY_SIZE(wm8994_dapm_widgets)); | ||
3802 | wm_hubs_add_analogue_routes(codec, 0, 0); | ||
3803 | snd_soc_dapm_add_routes(codec, intercon, ARRAY_SIZE(intercon)); | ||
3804 | |||
3805 | return 0; | ||
3806 | } | ||
3807 | |||
3808 | static int wm8994_remove(struct platform_device *pdev) | ||
3809 | { | ||
3810 | struct snd_soc_device *socdev = platform_get_drvdata(pdev); | ||
3811 | |||
3812 | snd_soc_free_pcms(socdev); | ||
3813 | snd_soc_dapm_free(socdev); | ||
3814 | |||
3815 | return 0; | ||
3816 | } | ||
3817 | |||
3818 | struct snd_soc_codec_device soc_codec_dev_wm8994 = { | ||
3819 | .probe = wm8994_probe, | ||
3820 | .remove = wm8994_remove, | ||
3821 | .suspend = wm8994_suspend, | ||
3822 | .resume = wm8994_resume, | ||
3823 | }; | ||
3824 | EXPORT_SYMBOL_GPL(soc_codec_dev_wm8994); | ||
3825 | |||
3826 | /** | 3769 | /** |
3827 | * wm8994_mic_detect - Enable microphone detection via the WM8994 IRQ | 3770 | * wm8994_mic_detect - Enable microphone detection via the WM8994 IRQ |
3828 | * | 3771 | * |
@@ -3881,7 +3824,7 @@ EXPORT_SYMBOL_GPL(wm8994_mic_detect); | |||
3881 | static irqreturn_t wm8994_mic_irq(int irq, void *data) | 3824 | static irqreturn_t wm8994_mic_irq(int irq, void *data) |
3882 | { | 3825 | { |
3883 | struct wm8994_priv *priv = data; | 3826 | struct wm8994_priv *priv = data; |
3884 | struct snd_soc_codec *codec = &priv->codec; | 3827 | struct snd_soc_codec *codec = priv->codec; |
3885 | int reg; | 3828 | int reg; |
3886 | int report; | 3829 | int report; |
3887 | 3830 | ||
@@ -3913,47 +3856,20 @@ static irqreturn_t wm8994_mic_irq(int irq, void *data) | |||
3913 | return IRQ_HANDLED; | 3856 | return IRQ_HANDLED; |
3914 | } | 3857 | } |
3915 | 3858 | ||
3916 | static int wm8994_codec_probe(struct platform_device *pdev) | 3859 | static int wm8994_codec_probe(struct snd_soc_codec *codec) |
3917 | { | 3860 | { |
3918 | int ret; | ||
3919 | struct wm8994_priv *wm8994; | 3861 | struct wm8994_priv *wm8994; |
3920 | struct snd_soc_codec *codec; | 3862 | int ret, i, rev; |
3921 | int i; | ||
3922 | u16 rev; | ||
3923 | 3863 | ||
3924 | if (wm8994_codec) { | 3864 | codec->control_data = dev_get_drvdata(codec->dev->parent); |
3925 | dev_err(&pdev->dev, "Another WM8994 is registered\n"); | ||
3926 | return -EINVAL; | ||
3927 | } | ||
3928 | 3865 | ||
3929 | wm8994 = kzalloc(sizeof(struct wm8994_priv), GFP_KERNEL); | 3866 | wm8994 = kzalloc(sizeof(struct wm8994_priv), GFP_KERNEL); |
3930 | if (!wm8994) { | 3867 | if (wm8994 == NULL) |
3931 | dev_err(&pdev->dev, "Failed to allocate private data\n"); | ||
3932 | return -ENOMEM; | 3868 | return -ENOMEM; |
3933 | } | ||
3934 | |||
3935 | codec = &wm8994->codec; | ||
3936 | |||
3937 | mutex_init(&codec->mutex); | ||
3938 | INIT_LIST_HEAD(&codec->dapm_widgets); | ||
3939 | INIT_LIST_HEAD(&codec->dapm_paths); | ||
3940 | |||
3941 | snd_soc_codec_set_drvdata(codec, wm8994); | 3869 | snd_soc_codec_set_drvdata(codec, wm8994); |
3942 | codec->control_data = dev_get_drvdata(pdev->dev.parent); | 3870 | |
3943 | codec->name = "WM8994"; | 3871 | wm8994->pdata = dev_get_platdata(codec->dev->parent); |
3944 | codec->owner = THIS_MODULE; | 3872 | wm8994->codec = codec; |
3945 | codec->read = wm8994_read; | ||
3946 | codec->write = wm8994_write; | ||
3947 | codec->readable_register = wm8994_readable; | ||
3948 | codec->bias_level = SND_SOC_BIAS_OFF; | ||
3949 | codec->set_bias_level = wm8994_set_bias_level; | ||
3950 | codec->dai = &wm8994_dai[0]; | ||
3951 | codec->num_dai = 3; | ||
3952 | codec->reg_cache_size = WM8994_MAX_REGISTER; | ||
3953 | codec->reg_cache = &wm8994->reg_cache; | ||
3954 | codec->dev = &pdev->dev; | ||
3955 | |||
3956 | wm8994->pdata = pdev->dev.parent->platform_data; | ||
3957 | 3873 | ||
3958 | /* Fill the cache with physical values we inherited; don't reset */ | 3874 | /* Fill the cache with physical values we inherited; don't reset */ |
3959 | ret = wm8994_bulk_read(codec->control_data, 0, | 3875 | ret = wm8994_bulk_read(codec->control_data, 0, |
@@ -3989,25 +3905,25 @@ static int wm8994_codec_probe(struct platform_device *pdev) | |||
3989 | ret = wm8994_request_irq(codec->control_data, WM8994_IRQ_MIC1_DET, | 3905 | ret = wm8994_request_irq(codec->control_data, WM8994_IRQ_MIC1_DET, |
3990 | wm8994_mic_irq, "Mic 1 detect", wm8994); | 3906 | wm8994_mic_irq, "Mic 1 detect", wm8994); |
3991 | if (ret != 0) | 3907 | if (ret != 0) |
3992 | dev_warn(&pdev->dev, | 3908 | dev_warn(codec->dev, |
3993 | "Failed to request Mic1 detect IRQ: %d\n", ret); | 3909 | "Failed to request Mic1 detect IRQ: %d\n", ret); |
3994 | 3910 | ||
3995 | ret = wm8994_request_irq(codec->control_data, WM8994_IRQ_MIC1_SHRT, | 3911 | ret = wm8994_request_irq(codec->control_data, WM8994_IRQ_MIC1_SHRT, |
3996 | wm8994_mic_irq, "Mic 1 short", wm8994); | 3912 | wm8994_mic_irq, "Mic 1 short", wm8994); |
3997 | if (ret != 0) | 3913 | if (ret != 0) |
3998 | dev_warn(&pdev->dev, | 3914 | dev_warn(codec->dev, |
3999 | "Failed to request Mic1 short IRQ: %d\n", ret); | 3915 | "Failed to request Mic1 short IRQ: %d\n", ret); |
4000 | 3916 | ||
4001 | ret = wm8994_request_irq(codec->control_data, WM8994_IRQ_MIC2_DET, | 3917 | ret = wm8994_request_irq(codec->control_data, WM8994_IRQ_MIC2_DET, |
4002 | wm8994_mic_irq, "Mic 2 detect", wm8994); | 3918 | wm8994_mic_irq, "Mic 2 detect", wm8994); |
4003 | if (ret != 0) | 3919 | if (ret != 0) |
4004 | dev_warn(&pdev->dev, | 3920 | dev_warn(codec->dev, |
4005 | "Failed to request Mic2 detect IRQ: %d\n", ret); | 3921 | "Failed to request Mic2 detect IRQ: %d\n", ret); |
4006 | 3922 | ||
4007 | ret = wm8994_request_irq(codec->control_data, WM8994_IRQ_MIC2_SHRT, | 3923 | ret = wm8994_request_irq(codec->control_data, WM8994_IRQ_MIC2_SHRT, |
4008 | wm8994_mic_irq, "Mic 2 short", wm8994); | 3924 | wm8994_mic_irq, "Mic 2 short", wm8994); |
4009 | if (ret != 0) | 3925 | if (ret != 0) |
4010 | dev_warn(&pdev->dev, | 3926 | dev_warn(codec->dev, |
4011 | "Failed to request Mic2 short IRQ: %d\n", ret); | 3927 | "Failed to request Mic2 short IRQ: %d\n", ret); |
4012 | 3928 | ||
4013 | /* Remember if AIFnLRCLK is configured as a GPIO. This should be | 3929 | /* Remember if AIFnLRCLK is configured as a GPIO. This should be |
@@ -4038,13 +3954,8 @@ static int wm8994_codec_probe(struct platform_device *pdev) | |||
4038 | wm8994->lrclk_shared[1] = 0; | 3954 | wm8994->lrclk_shared[1] = 0; |
4039 | } | 3955 | } |
4040 | 3956 | ||
4041 | for (i = 0; i < ARRAY_SIZE(wm8994_dai); i++) | ||
4042 | wm8994_dai[i].dev = codec->dev; | ||
4043 | |||
4044 | wm8994_set_bias_level(codec, SND_SOC_BIAS_STANDBY); | 3957 | wm8994_set_bias_level(codec, SND_SOC_BIAS_STANDBY); |
4045 | 3958 | ||
4046 | wm8994_codec = codec; | ||
4047 | |||
4048 | /* Latch volume updates (right only; we always do left then right). */ | 3959 | /* Latch volume updates (right only; we always do left then right). */ |
4049 | snd_soc_update_bits(codec, WM8994_AIF1_DAC1_RIGHT_VOLUME, | 3960 | snd_soc_update_bits(codec, WM8994_AIF1_DAC1_RIGHT_VOLUME, |
4050 | WM8994_AIF1DAC1_VU, WM8994_AIF1DAC1_VU); | 3961 | WM8994_AIF1DAC1_VU, WM8994_AIF1DAC1_VU); |
@@ -4081,24 +3992,18 @@ static int wm8994_codec_probe(struct platform_device *pdev) | |||
4081 | 3992 | ||
4082 | wm8994_update_class_w(codec); | 3993 | wm8994_update_class_w(codec); |
4083 | 3994 | ||
4084 | ret = snd_soc_register_codec(codec); | 3995 | wm8994_handle_pdata(wm8994); |
4085 | if (ret != 0) { | ||
4086 | dev_err(codec->dev, "Failed to register codec: %d\n", ret); | ||
4087 | goto err_irq; | ||
4088 | } | ||
4089 | |||
4090 | ret = snd_soc_register_dais(wm8994_dai, ARRAY_SIZE(wm8994_dai)); | ||
4091 | if (ret != 0) { | ||
4092 | dev_err(codec->dev, "Failed to register DAIs: %d\n", ret); | ||
4093 | goto err_codec; | ||
4094 | } | ||
4095 | 3996 | ||
4096 | platform_set_drvdata(pdev, wm8994); | 3997 | wm_hubs_add_analogue_controls(codec); |
3998 | snd_soc_add_controls(codec, wm8994_snd_controls, | ||
3999 | ARRAY_SIZE(wm8994_snd_controls)); | ||
4000 | snd_soc_dapm_new_controls(codec, wm8994_dapm_widgets, | ||
4001 | ARRAY_SIZE(wm8994_dapm_widgets)); | ||
4002 | wm_hubs_add_analogue_routes(codec, 0, 0); | ||
4003 | snd_soc_dapm_add_routes(codec, intercon, ARRAY_SIZE(intercon)); | ||
4097 | 4004 | ||
4098 | return 0; | 4005 | return 0; |
4099 | 4006 | ||
4100 | err_codec: | ||
4101 | snd_soc_unregister_codec(codec); | ||
4102 | err_irq: | 4007 | err_irq: |
4103 | wm8994_free_irq(codec->control_data, WM8994_IRQ_MIC2_SHRT, wm8994); | 4008 | wm8994_free_irq(codec->control_data, WM8994_IRQ_MIC2_SHRT, wm8994); |
4104 | wm8994_free_irq(codec->control_data, WM8994_IRQ_MIC2_DET, wm8994); | 4009 | wm8994_free_irq(codec->control_data, WM8994_IRQ_MIC2_DET, wm8994); |
@@ -4109,31 +4014,50 @@ err: | |||
4109 | return ret; | 4014 | return ret; |
4110 | } | 4015 | } |
4111 | 4016 | ||
4112 | static int __devexit wm8994_codec_remove(struct platform_device *pdev) | 4017 | static int wm8994_codec_remove(struct snd_soc_codec *codec) |
4113 | { | 4018 | { |
4114 | struct wm8994_priv *wm8994 = platform_get_drvdata(pdev); | 4019 | struct wm8994_priv *wm8994 = snd_soc_codec_get_drvdata(codec); |
4115 | struct snd_soc_codec *codec = &wm8994->codec; | ||
4116 | 4020 | ||
4117 | wm8994_set_bias_level(codec, SND_SOC_BIAS_OFF); | 4021 | wm8994_set_bias_level(codec, SND_SOC_BIAS_OFF); |
4118 | snd_soc_unregister_dais(wm8994_dai, ARRAY_SIZE(wm8994_dai)); | 4022 | |
4119 | snd_soc_unregister_codec(&wm8994->codec); | ||
4120 | wm8994_free_irq(codec->control_data, WM8994_IRQ_MIC2_SHRT, wm8994); | 4023 | wm8994_free_irq(codec->control_data, WM8994_IRQ_MIC2_SHRT, wm8994); |
4121 | wm8994_free_irq(codec->control_data, WM8994_IRQ_MIC2_DET, wm8994); | 4024 | wm8994_free_irq(codec->control_data, WM8994_IRQ_MIC2_DET, wm8994); |
4122 | wm8994_free_irq(codec->control_data, WM8994_IRQ_MIC1_SHRT, wm8994); | 4025 | wm8994_free_irq(codec->control_data, WM8994_IRQ_MIC1_SHRT, wm8994); |
4123 | wm8994_free_irq(codec->control_data, WM8994_IRQ_MIC1_DET, wm8994); | 4026 | wm8994_free_irq(codec->control_data, WM8994_IRQ_MIC1_DET, wm8994); |
4124 | kfree(wm8994); | 4027 | kfree(wm8994); |
4125 | wm8994_codec = NULL; | ||
4126 | 4028 | ||
4127 | return 0; | 4029 | return 0; |
4128 | } | 4030 | } |
4129 | 4031 | ||
4032 | static struct snd_soc_codec_driver soc_codec_dev_wm8994 = { | ||
4033 | .probe = wm8994_codec_probe, | ||
4034 | .remove = wm8994_codec_remove, | ||
4035 | .suspend = wm8994_suspend, | ||
4036 | .resume = wm8994_resume, | ||
4037 | .read = wm8994_read, | ||
4038 | .write = wm8994_write, | ||
4039 | .set_bias_level = wm8994_set_bias_level, | ||
4040 | }; | ||
4041 | |||
4042 | static int __devinit wm8994_probe(struct platform_device *pdev) | ||
4043 | { | ||
4044 | return snd_soc_register_codec(&pdev->dev, &soc_codec_dev_wm8994, | ||
4045 | wm8994_dai, ARRAY_SIZE(wm8994_dai)); | ||
4046 | } | ||
4047 | |||
4048 | static int __devexit wm8994_remove(struct platform_device *pdev) | ||
4049 | { | ||
4050 | snd_soc_unregister_codec(&pdev->dev); | ||
4051 | return 0; | ||
4052 | } | ||
4053 | |||
4130 | static struct platform_driver wm8994_codec_driver = { | 4054 | static struct platform_driver wm8994_codec_driver = { |
4131 | .driver = { | 4055 | .driver = { |
4132 | .name = "wm8994-codec", | 4056 | .name = "wm8994-codec", |
4133 | .owner = THIS_MODULE, | 4057 | .owner = THIS_MODULE, |
4134 | }, | 4058 | }, |
4135 | .probe = wm8994_codec_probe, | 4059 | .probe = wm8994_probe, |
4136 | .remove = __devexit_p(wm8994_codec_remove), | 4060 | .remove = __devexit_p(wm8994_remove), |
4137 | }; | 4061 | }; |
4138 | 4062 | ||
4139 | static __init int wm8994_init(void) | 4063 | static __init int wm8994_init(void) |
diff --git a/sound/soc/codecs/wm8994.h b/sound/soc/codecs/wm8994.h index 2e0ca67a8df7..d8dce260c430 100644 --- a/sound/soc/codecs/wm8994.h +++ b/sound/soc/codecs/wm8994.h | |||
@@ -11,9 +11,6 @@ | |||
11 | 11 | ||
12 | #include <sound/soc.h> | 12 | #include <sound/soc.h> |
13 | 13 | ||
14 | extern struct snd_soc_codec_device soc_codec_dev_wm8994; | ||
15 | extern struct snd_soc_dai wm8994_dai[]; | ||
16 | |||
17 | /* Sources for AIF1/2 SYSCLK - use with set_dai_sysclk() */ | 14 | /* Sources for AIF1/2 SYSCLK - use with set_dai_sysclk() */ |
18 | #define WM8994_SYSCLK_MCLK1 1 | 15 | #define WM8994_SYSCLK_MCLK1 1 |
19 | #define WM8994_SYSCLK_MCLK2 2 | 16 | #define WM8994_SYSCLK_MCLK2 2 |
diff --git a/sound/soc/codecs/wm9081.c b/sound/soc/codecs/wm9081.c index 76b37ff6c264..00249d5b6793 100644 --- a/sound/soc/codecs/wm9081.c +++ b/sound/soc/codecs/wm9081.c | |||
@@ -156,7 +156,8 @@ static struct { | |||
156 | }; | 156 | }; |
157 | 157 | ||
158 | struct wm9081_priv { | 158 | struct wm9081_priv { |
159 | struct snd_soc_codec codec; | 159 | enum snd_soc_control_type control_type; |
160 | void *control_data; | ||
160 | u16 reg_cache[WM9081_MAX_REGISTER + 1]; | 161 | u16 reg_cache[WM9081_MAX_REGISTER + 1]; |
161 | int sysclk_source; | 162 | int sysclk_source; |
162 | int mclk_rate; | 163 | int mclk_rate; |
@@ -1212,8 +1213,8 @@ static struct snd_soc_dai_ops wm9081_dai_ops = { | |||
1212 | /* We report two channels because the CODEC processes a stereo signal, even | 1213 | /* We report two channels because the CODEC processes a stereo signal, even |
1213 | * though it is only capable of handling a mono output. | 1214 | * though it is only capable of handling a mono output. |
1214 | */ | 1215 | */ |
1215 | struct snd_soc_dai wm9081_dai = { | 1216 | static struct snd_soc_dai_driver wm9081_dai = { |
1216 | .name = "WM9081", | 1217 | .name = "wm9081-hifi", |
1217 | .playback = { | 1218 | .playback = { |
1218 | .stream_name = "HiFi Playback", | 1219 | .stream_name = "HiFi Playback", |
1219 | .channels_min = 1, | 1220 | .channels_min = 1, |
@@ -1223,34 +1224,42 @@ struct snd_soc_dai wm9081_dai = { | |||
1223 | }, | 1224 | }, |
1224 | .ops = &wm9081_dai_ops, | 1225 | .ops = &wm9081_dai_ops, |
1225 | }; | 1226 | }; |
1226 | EXPORT_SYMBOL_GPL(wm9081_dai); | ||
1227 | 1227 | ||
1228 | 1228 | static int wm9081_probe(struct snd_soc_codec *codec) | |
1229 | static struct snd_soc_codec *wm9081_codec; | ||
1230 | |||
1231 | static int wm9081_probe(struct platform_device *pdev) | ||
1232 | { | 1229 | { |
1233 | struct snd_soc_device *socdev = platform_get_drvdata(pdev); | 1230 | struct wm9081_priv *wm9081 = snd_soc_codec_get_drvdata(codec); |
1234 | struct snd_soc_codec *codec; | 1231 | int ret; |
1235 | struct wm9081_priv *wm9081; | 1232 | u16 reg; |
1236 | int ret = 0; | ||
1237 | 1233 | ||
1238 | if (wm9081_codec == NULL) { | 1234 | codec->control_data = wm9081->control_data; |
1239 | dev_err(&pdev->dev, "Codec device not registered\n"); | 1235 | ret = snd_soc_codec_set_cache_io(codec, 8, 16, wm9081->control_type); |
1240 | return -ENODEV; | 1236 | if (ret != 0) { |
1237 | dev_err(codec->dev, "Failed to set cache I/O: %d\n", ret); | ||
1238 | return ret; | ||
1241 | } | 1239 | } |
1242 | 1240 | ||
1243 | socdev->card->codec = wm9081_codec; | 1241 | reg = snd_soc_read(codec, WM9081_SOFTWARE_RESET); |
1244 | codec = wm9081_codec; | 1242 | if (reg != 0x9081) { |
1245 | wm9081 = snd_soc_codec_get_drvdata(codec); | 1243 | dev_err(codec->dev, "Device is not a WM9081: ID=0x%x\n", reg); |
1244 | ret = -EINVAL; | ||
1245 | return ret; | ||
1246 | } | ||
1246 | 1247 | ||
1247 | /* register pcms */ | 1248 | ret = wm9081_reset(codec); |
1248 | ret = snd_soc_new_pcms(socdev, SNDRV_DEFAULT_IDX1, SNDRV_DEFAULT_STR1); | ||
1249 | if (ret < 0) { | 1249 | if (ret < 0) { |
1250 | dev_err(codec->dev, "failed to create pcms: %d\n", ret); | 1250 | dev_err(codec->dev, "Failed to issue reset\n"); |
1251 | goto pcm_err; | 1251 | return ret; |
1252 | } | 1252 | } |
1253 | 1253 | ||
1254 | wm9081_set_bias_level(codec, SND_SOC_BIAS_STANDBY); | ||
1255 | |||
1256 | /* Enable zero cross by default */ | ||
1257 | reg = snd_soc_read(codec, WM9081_ANALOGUE_LINEOUT); | ||
1258 | snd_soc_write(codec, WM9081_ANALOGUE_LINEOUT, reg | WM9081_LINEOUTZC); | ||
1259 | reg = snd_soc_read(codec, WM9081_ANALOGUE_SPEAKER_PGA); | ||
1260 | snd_soc_write(codec, WM9081_ANALOGUE_SPEAKER_PGA, | ||
1261 | reg | WM9081_SPKPGAZC); | ||
1262 | |||
1254 | snd_soc_add_controls(codec, wm9081_snd_controls, | 1263 | snd_soc_add_controls(codec, wm9081_snd_controls, |
1255 | ARRAY_SIZE(wm9081_snd_controls)); | 1264 | ARRAY_SIZE(wm9081_snd_controls)); |
1256 | if (!wm9081->retune) { | 1265 | if (!wm9081->retune) { |
@@ -1265,40 +1274,28 @@ static int wm9081_probe(struct platform_device *pdev) | |||
1265 | snd_soc_dapm_add_routes(codec, audio_paths, ARRAY_SIZE(audio_paths)); | 1274 | snd_soc_dapm_add_routes(codec, audio_paths, ARRAY_SIZE(audio_paths)); |
1266 | 1275 | ||
1267 | return ret; | 1276 | return ret; |
1268 | |||
1269 | pcm_err: | ||
1270 | return ret; | ||
1271 | } | 1277 | } |
1272 | 1278 | ||
1273 | static int wm9081_remove(struct platform_device *pdev) | 1279 | static int wm9081_remove(struct snd_soc_codec *codec) |
1274 | { | 1280 | { |
1275 | struct snd_soc_device *socdev = platform_get_drvdata(pdev); | 1281 | wm9081_set_bias_level(codec, SND_SOC_BIAS_OFF); |
1276 | |||
1277 | snd_soc_free_pcms(socdev); | ||
1278 | snd_soc_dapm_free(socdev); | ||
1279 | |||
1280 | return 0; | 1282 | return 0; |
1281 | } | 1283 | } |
1282 | 1284 | ||
1283 | #ifdef CONFIG_PM | 1285 | #ifdef CONFIG_PM |
1284 | static int wm9081_suspend(struct platform_device *pdev, pm_message_t state) | 1286 | static int wm9081_suspend(struct snd_soc_codec *codec, pm_message_t state) |
1285 | { | 1287 | { |
1286 | struct snd_soc_device *socdev = platform_get_drvdata(pdev); | ||
1287 | struct snd_soc_codec *codec = socdev->card->codec; | ||
1288 | |||
1289 | wm9081_set_bias_level(codec, SND_SOC_BIAS_OFF); | 1288 | wm9081_set_bias_level(codec, SND_SOC_BIAS_OFF); |
1290 | 1289 | ||
1291 | return 0; | 1290 | return 0; |
1292 | } | 1291 | } |
1293 | 1292 | ||
1294 | static int wm9081_resume(struct platform_device *pdev) | 1293 | static int wm9081_resume(struct snd_soc_codec *codec) |
1295 | { | 1294 | { |
1296 | struct snd_soc_device *socdev = platform_get_drvdata(pdev); | ||
1297 | struct snd_soc_codec *codec = socdev->card->codec; | ||
1298 | u16 *reg_cache = codec->reg_cache; | 1295 | u16 *reg_cache = codec->reg_cache; |
1299 | int i; | 1296 | int i; |
1300 | 1297 | ||
1301 | for (i = 0; i < codec->reg_cache_size; i++) { | 1298 | for (i = 0; i < codec->driver->reg_cache_size; i++) { |
1302 | if (i == WM9081_SOFTWARE_RESET) | 1299 | if (i == WM9081_SOFTWARE_RESET) |
1303 | continue; | 1300 | continue; |
1304 | 1301 | ||
@@ -1314,133 +1311,43 @@ static int wm9081_resume(struct platform_device *pdev) | |||
1314 | #define wm9081_resume NULL | 1311 | #define wm9081_resume NULL |
1315 | #endif | 1312 | #endif |
1316 | 1313 | ||
1317 | struct snd_soc_codec_device soc_codec_dev_wm9081 = { | 1314 | static struct snd_soc_codec_driver soc_codec_dev_wm9081 = { |
1318 | .probe = wm9081_probe, | 1315 | .probe = wm9081_probe, |
1319 | .remove = wm9081_remove, | 1316 | .remove = wm9081_remove, |
1320 | .suspend = wm9081_suspend, | 1317 | .suspend = wm9081_suspend, |
1321 | .resume = wm9081_resume, | 1318 | .resume = wm9081_resume, |
1319 | .set_bias_level = wm9081_set_bias_level, | ||
1320 | .reg_cache_size = sizeof(wm9081_reg_defaults), | ||
1321 | .reg_word_size = sizeof(u16), | ||
1322 | .reg_cache_default = wm9081_reg_defaults, | ||
1323 | .volatile_register = wm9081_volatile_register, | ||
1322 | }; | 1324 | }; |
1323 | EXPORT_SYMBOL_GPL(soc_codec_dev_wm9081); | ||
1324 | |||
1325 | static int wm9081_register(struct wm9081_priv *wm9081, | ||
1326 | enum snd_soc_control_type control) | ||
1327 | { | ||
1328 | struct snd_soc_codec *codec = &wm9081->codec; | ||
1329 | int ret; | ||
1330 | u16 reg; | ||
1331 | |||
1332 | if (wm9081_codec) { | ||
1333 | dev_err(codec->dev, "Another WM9081 is registered\n"); | ||
1334 | ret = -EINVAL; | ||
1335 | goto err; | ||
1336 | } | ||
1337 | |||
1338 | mutex_init(&codec->mutex); | ||
1339 | INIT_LIST_HEAD(&codec->dapm_widgets); | ||
1340 | INIT_LIST_HEAD(&codec->dapm_paths); | ||
1341 | |||
1342 | snd_soc_codec_set_drvdata(codec, wm9081); | ||
1343 | codec->name = "WM9081"; | ||
1344 | codec->owner = THIS_MODULE; | ||
1345 | codec->dai = &wm9081_dai; | ||
1346 | codec->num_dai = 1; | ||
1347 | codec->reg_cache_size = ARRAY_SIZE(wm9081->reg_cache); | ||
1348 | codec->reg_cache = &wm9081->reg_cache; | ||
1349 | codec->bias_level = SND_SOC_BIAS_OFF; | ||
1350 | codec->set_bias_level = wm9081_set_bias_level; | ||
1351 | codec->volatile_register = wm9081_volatile_register; | ||
1352 | |||
1353 | memcpy(codec->reg_cache, wm9081_reg_defaults, | ||
1354 | sizeof(wm9081_reg_defaults)); | ||
1355 | |||
1356 | ret = snd_soc_codec_set_cache_io(codec, 8, 16, control); | ||
1357 | if (ret != 0) { | ||
1358 | dev_err(codec->dev, "Failed to set cache I/O: %d\n", ret); | ||
1359 | goto err; | ||
1360 | } | ||
1361 | |||
1362 | reg = snd_soc_read(codec, WM9081_SOFTWARE_RESET); | ||
1363 | if (reg != 0x9081) { | ||
1364 | dev_err(codec->dev, "Device is not a WM9081: ID=0x%x\n", reg); | ||
1365 | ret = -EINVAL; | ||
1366 | goto err; | ||
1367 | } | ||
1368 | |||
1369 | ret = wm9081_reset(codec); | ||
1370 | if (ret < 0) { | ||
1371 | dev_err(codec->dev, "Failed to issue reset\n"); | ||
1372 | goto err; | ||
1373 | } | ||
1374 | |||
1375 | wm9081_set_bias_level(codec, SND_SOC_BIAS_STANDBY); | ||
1376 | |||
1377 | /* Enable zero cross by default */ | ||
1378 | reg = snd_soc_read(codec, WM9081_ANALOGUE_LINEOUT); | ||
1379 | snd_soc_write(codec, WM9081_ANALOGUE_LINEOUT, reg | WM9081_LINEOUTZC); | ||
1380 | reg = snd_soc_read(codec, WM9081_ANALOGUE_SPEAKER_PGA); | ||
1381 | snd_soc_write(codec, WM9081_ANALOGUE_SPEAKER_PGA, | ||
1382 | reg | WM9081_SPKPGAZC); | ||
1383 | |||
1384 | wm9081_dai.dev = codec->dev; | ||
1385 | |||
1386 | wm9081_codec = codec; | ||
1387 | |||
1388 | ret = snd_soc_register_codec(codec); | ||
1389 | if (ret != 0) { | ||
1390 | dev_err(codec->dev, "Failed to register codec: %d\n", ret); | ||
1391 | goto err; | ||
1392 | } | ||
1393 | |||
1394 | ret = snd_soc_register_dai(&wm9081_dai); | ||
1395 | if (ret != 0) { | ||
1396 | dev_err(codec->dev, "Failed to register DAI: %d\n", ret); | ||
1397 | goto err_codec; | ||
1398 | } | ||
1399 | |||
1400 | return 0; | ||
1401 | |||
1402 | err_codec: | ||
1403 | snd_soc_unregister_codec(codec); | ||
1404 | err: | ||
1405 | kfree(wm9081); | ||
1406 | return ret; | ||
1407 | } | ||
1408 | |||
1409 | static void wm9081_unregister(struct wm9081_priv *wm9081) | ||
1410 | { | ||
1411 | wm9081_set_bias_level(&wm9081->codec, SND_SOC_BIAS_OFF); | ||
1412 | snd_soc_unregister_dai(&wm9081_dai); | ||
1413 | snd_soc_unregister_codec(&wm9081->codec); | ||
1414 | kfree(wm9081); | ||
1415 | wm9081_codec = NULL; | ||
1416 | } | ||
1417 | 1325 | ||
1326 | #if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE) | ||
1418 | static __devinit int wm9081_i2c_probe(struct i2c_client *i2c, | 1327 | static __devinit int wm9081_i2c_probe(struct i2c_client *i2c, |
1419 | const struct i2c_device_id *id) | 1328 | const struct i2c_device_id *id) |
1420 | { | 1329 | { |
1421 | struct wm9081_priv *wm9081; | 1330 | struct wm9081_priv *wm9081; |
1422 | struct snd_soc_codec *codec; | 1331 | int ret; |
1423 | 1332 | ||
1424 | wm9081 = kzalloc(sizeof(struct wm9081_priv), GFP_KERNEL); | 1333 | wm9081 = kzalloc(sizeof(struct wm9081_priv), GFP_KERNEL); |
1425 | if (wm9081 == NULL) | 1334 | if (wm9081 == NULL) |
1426 | return -ENOMEM; | 1335 | return -ENOMEM; |
1427 | 1336 | ||
1428 | codec = &wm9081->codec; | ||
1429 | codec->hw_write = (hw_write_t)i2c_master_send; | ||
1430 | wm9081->retune = i2c->dev.platform_data; | ||
1431 | |||
1432 | i2c_set_clientdata(i2c, wm9081); | 1337 | i2c_set_clientdata(i2c, wm9081); |
1433 | codec->control_data = i2c; | 1338 | wm9081->control_data = i2c; |
1434 | |||
1435 | codec->dev = &i2c->dev; | ||
1436 | 1339 | ||
1437 | return wm9081_register(wm9081, SND_SOC_I2C); | 1340 | ret = snd_soc_register_codec(&i2c->dev, |
1341 | &soc_codec_dev_wm9081, &wm9081_dai, 1); | ||
1342 | if (ret < 0) | ||
1343 | kfree(wm9081); | ||
1344 | return ret; | ||
1438 | } | 1345 | } |
1439 | 1346 | ||
1440 | static __devexit int wm9081_i2c_remove(struct i2c_client *client) | 1347 | static __devexit int wm9081_i2c_remove(struct i2c_client *client) |
1441 | { | 1348 | { |
1442 | struct wm9081_priv *wm9081 = i2c_get_clientdata(client); | 1349 | snd_soc_unregister_codec(&client->dev); |
1443 | wm9081_unregister(wm9081); | 1350 | kfree(i2c_get_clientdata(client)); |
1444 | return 0; | 1351 | return 0; |
1445 | } | 1352 | } |
1446 | 1353 | ||
@@ -1452,31 +1359,34 @@ MODULE_DEVICE_TABLE(i2c, wm9081_i2c_id); | |||
1452 | 1359 | ||
1453 | static struct i2c_driver wm9081_i2c_driver = { | 1360 | static struct i2c_driver wm9081_i2c_driver = { |
1454 | .driver = { | 1361 | .driver = { |
1455 | .name = "wm9081", | 1362 | .name = "wm9081-codec", |
1456 | .owner = THIS_MODULE, | 1363 | .owner = THIS_MODULE, |
1457 | }, | 1364 | }, |
1458 | .probe = wm9081_i2c_probe, | 1365 | .probe = wm9081_i2c_probe, |
1459 | .remove = __devexit_p(wm9081_i2c_remove), | 1366 | .remove = __devexit_p(wm9081_i2c_remove), |
1460 | .id_table = wm9081_i2c_id, | 1367 | .id_table = wm9081_i2c_id, |
1461 | }; | 1368 | }; |
1369 | #endif | ||
1462 | 1370 | ||
1463 | static int __init wm9081_modinit(void) | 1371 | static int __init wm9081_modinit(void) |
1464 | { | 1372 | { |
1465 | int ret; | 1373 | int ret = 0; |
1466 | 1374 | #if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE) | |
1467 | ret = i2c_add_driver(&wm9081_i2c_driver); | 1375 | ret = i2c_add_driver(&wm9081_i2c_driver); |
1468 | if (ret != 0) { | 1376 | if (ret != 0) { |
1469 | printk(KERN_ERR "Failed to register WM9081 I2C driver: %d\n", | 1377 | printk(KERN_ERR "Failed to register WM9081 I2C driver: %d\n", |
1470 | ret); | 1378 | ret); |
1471 | } | 1379 | } |
1472 | 1380 | #endif | |
1473 | return ret; | 1381 | return ret; |
1474 | } | 1382 | } |
1475 | module_init(wm9081_modinit); | 1383 | module_init(wm9081_modinit); |
1476 | 1384 | ||
1477 | static void __exit wm9081_exit(void) | 1385 | static void __exit wm9081_exit(void) |
1478 | { | 1386 | { |
1387 | #if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE) | ||
1479 | i2c_del_driver(&wm9081_i2c_driver); | 1388 | i2c_del_driver(&wm9081_i2c_driver); |
1389 | #endif | ||
1480 | } | 1390 | } |
1481 | module_exit(wm9081_exit); | 1391 | module_exit(wm9081_exit); |
1482 | 1392 | ||
diff --git a/sound/soc/codecs/wm9081.h b/sound/soc/codecs/wm9081.h index 42d3bc757021..871cccb066dc 100644 --- a/sound/soc/codecs/wm9081.h +++ b/sound/soc/codecs/wm9081.h | |||
@@ -15,9 +15,6 @@ | |||
15 | 15 | ||
16 | #include <sound/soc.h> | 16 | #include <sound/soc.h> |
17 | 17 | ||
18 | extern struct snd_soc_dai wm9081_dai; | ||
19 | extern struct snd_soc_codec_device soc_codec_dev_wm9081; | ||
20 | |||
21 | /* | 18 | /* |
22 | * SYSCLK sources | 19 | * SYSCLK sources |
23 | */ | 20 | */ |
diff --git a/sound/soc/codecs/wm9090.c b/sound/soc/codecs/wm9090.c index 1592250daec0..7a1825418ee4 100644 --- a/sound/soc/codecs/wm9090.c +++ b/sound/soc/codecs/wm9090.c | |||
@@ -34,8 +34,6 @@ | |||
34 | 34 | ||
35 | #include "wm9090.h" | 35 | #include "wm9090.h" |
36 | 36 | ||
37 | static struct snd_soc_codec *wm9090_codec; | ||
38 | |||
39 | static const u16 wm9090_reg_defaults[] = { | 37 | static const u16 wm9090_reg_defaults[] = { |
40 | 0x9093, /* R0 - Software Reset */ | 38 | 0x9093, /* R0 - Software Reset */ |
41 | 0x0006, /* R1 - Power Management (1) */ | 39 | 0x0006, /* R1 - Power Management (1) */ |
@@ -142,15 +140,10 @@ static const u16 wm9090_reg_defaults[] = { | |||
142 | 140 | ||
143 | /* This struct is used to save the context */ | 141 | /* This struct is used to save the context */ |
144 | struct wm9090_priv { | 142 | struct wm9090_priv { |
145 | /* We're not really registering as a CODEC since ASoC core | ||
146 | * does not yet support multiple CODECs but having the CODEC | ||
147 | * structure means we can reuse some of the ASoC core | ||
148 | * features. | ||
149 | */ | ||
150 | struct snd_soc_codec codec; | ||
151 | struct mutex mutex; | 143 | struct mutex mutex; |
152 | u16 reg_cache[WM9090_MAX_REGISTER + 1]; | 144 | u16 reg_cache[WM9090_MAX_REGISTER + 1]; |
153 | struct wm9090_platform_data pdata; | 145 | struct wm9090_platform_data pdata; |
146 | void *control_data; | ||
154 | }; | 147 | }; |
155 | 148 | ||
156 | static int wm9090_volatile(unsigned int reg) | 149 | static int wm9090_volatile(unsigned int reg) |
@@ -523,7 +516,7 @@ static int wm9090_set_bias_level(struct snd_soc_codec *codec, | |||
523 | case SND_SOC_BIAS_STANDBY: | 516 | case SND_SOC_BIAS_STANDBY: |
524 | if (codec->bias_level == SND_SOC_BIAS_OFF) { | 517 | if (codec->bias_level == SND_SOC_BIAS_OFF) { |
525 | /* Restore the register cache */ | 518 | /* Restore the register cache */ |
526 | for (i = 1; i < codec->reg_cache_size; i++) { | 519 | for (i = 1; i < codec->driver->reg_cache_size; i++) { |
527 | if (reg_cache[i] == wm9090_reg_defaults[i]) | 520 | if (reg_cache[i] == wm9090_reg_defaults[i]) |
528 | continue; | 521 | continue; |
529 | if (wm9090_volatile(i)) | 522 | if (wm9090_volatile(i)) |
@@ -556,51 +549,67 @@ static int wm9090_set_bias_level(struct snd_soc_codec *codec, | |||
556 | return 0; | 549 | return 0; |
557 | } | 550 | } |
558 | 551 | ||
559 | static int wm9090_probe(struct platform_device *pdev) | 552 | static int wm9090_probe(struct snd_soc_codec *codec) |
560 | { | 553 | { |
561 | struct snd_soc_device *socdev = platform_get_drvdata(pdev); | 554 | struct wm9090_priv *wm9090 = snd_soc_codec_get_drvdata(codec); |
562 | struct snd_soc_codec *codec; | 555 | int ret; |
563 | int ret = 0; | ||
564 | 556 | ||
565 | if (wm9090_codec == NULL) { | 557 | codec->control_data = wm9090->control_data; |
566 | dev_err(&pdev->dev, "Codec device not registered\n"); | 558 | ret = snd_soc_codec_set_cache_io(codec, 8, 16, SND_SOC_I2C); |
567 | return -ENODEV; | 559 | if (ret != 0) { |
560 | dev_err(codec->dev, "Failed to set cache I/O: %d\n", ret); | ||
561 | return ret; | ||
568 | } | 562 | } |
569 | 563 | ||
570 | socdev->card->codec = wm9090_codec; | 564 | ret = snd_soc_read(codec, WM9090_SOFTWARE_RESET); |
571 | codec = wm9090_codec; | 565 | if (ret < 0) |
572 | 566 | return ret; | |
573 | /* register pcms */ | 567 | if (ret != wm9090_reg_defaults[WM9090_SOFTWARE_RESET]) { |
574 | ret = snd_soc_new_pcms(socdev, SNDRV_DEFAULT_IDX1, SNDRV_DEFAULT_STR1); | 568 | dev_err(codec->dev, "Device is not a WM9090, ID=%x\n", ret); |
575 | if (ret < 0) { | 569 | return -EINVAL; |
576 | dev_err(codec->dev, "failed to create pcms: %d\n", ret); | ||
577 | goto pcm_err; | ||
578 | } | 570 | } |
579 | 571 | ||
572 | ret = snd_soc_write(codec, WM9090_SOFTWARE_RESET, 0); | ||
573 | if (ret < 0) | ||
574 | return ret; | ||
575 | |||
576 | /* Configure some defaults; they will be written out when we | ||
577 | * bring the bias up. | ||
578 | */ | ||
579 | wm9090->reg_cache[WM9090_IN1_LINE_INPUT_A_VOLUME] |= WM9090_IN1_VU | ||
580 | | WM9090_IN1A_ZC; | ||
581 | wm9090->reg_cache[WM9090_IN1_LINE_INPUT_B_VOLUME] |= WM9090_IN1_VU | ||
582 | | WM9090_IN1B_ZC; | ||
583 | wm9090->reg_cache[WM9090_IN2_LINE_INPUT_A_VOLUME] |= WM9090_IN2_VU | ||
584 | | WM9090_IN2A_ZC; | ||
585 | wm9090->reg_cache[WM9090_IN2_LINE_INPUT_B_VOLUME] |= WM9090_IN2_VU | ||
586 | | WM9090_IN2B_ZC; | ||
587 | wm9090->reg_cache[WM9090_SPEAKER_VOLUME_LEFT] |= | ||
588 | WM9090_SPKOUT_VU | WM9090_SPKOUTL_ZC; | ||
589 | wm9090->reg_cache[WM9090_LEFT_OUTPUT_VOLUME] |= | ||
590 | WM9090_HPOUT1_VU | WM9090_HPOUT1L_ZC; | ||
591 | wm9090->reg_cache[WM9090_RIGHT_OUTPUT_VOLUME] |= | ||
592 | WM9090_HPOUT1_VU | WM9090_HPOUT1R_ZC; | ||
593 | |||
594 | wm9090->reg_cache[WM9090_CLOCKING_1] |= WM9090_TOCLK_ENA; | ||
595 | |||
596 | wm9090_set_bias_level(codec, SND_SOC_BIAS_STANDBY); | ||
597 | |||
580 | wm9090_add_controls(codec); | 598 | wm9090_add_controls(codec); |
581 | 599 | ||
582 | return 0; | 600 | return 0; |
583 | |||
584 | pcm_err: | ||
585 | return ret; | ||
586 | } | 601 | } |
587 | 602 | ||
588 | #ifdef CONFIG_PM | 603 | #ifdef CONFIG_PM |
589 | static int wm9090_suspend(struct platform_device *pdev, pm_message_t state) | 604 | static int wm9090_suspend(struct snd_soc_codec *codec, pm_message_t state) |
590 | { | 605 | { |
591 | struct snd_soc_device *socdev = platform_get_drvdata(pdev); | ||
592 | struct snd_soc_codec *codec = socdev->card->codec; | ||
593 | |||
594 | wm9090_set_bias_level(codec, SND_SOC_BIAS_OFF); | 606 | wm9090_set_bias_level(codec, SND_SOC_BIAS_OFF); |
595 | 607 | ||
596 | return 0; | 608 | return 0; |
597 | } | 609 | } |
598 | 610 | ||
599 | static int wm9090_resume(struct platform_device *pdev) | 611 | static int wm9090_resume(struct snd_soc_codec *codec) |
600 | { | 612 | { |
601 | struct snd_soc_device *socdev = platform_get_drvdata(pdev); | ||
602 | struct snd_soc_codec *codec = socdev->card->codec; | ||
603 | |||
604 | wm9090_set_bias_level(codec, SND_SOC_BIAS_STANDBY); | 613 | wm9090_set_bias_level(codec, SND_SOC_BIAS_STANDBY); |
605 | 614 | ||
606 | return 0; | 615 | return 0; |
@@ -610,29 +619,29 @@ static int wm9090_resume(struct platform_device *pdev) | |||
610 | #define wm9090_resume NULL | 619 | #define wm9090_resume NULL |
611 | #endif | 620 | #endif |
612 | 621 | ||
613 | static int wm9090_remove(struct platform_device *pdev) | 622 | static int wm9090_remove(struct snd_soc_codec *codec) |
614 | { | 623 | { |
615 | struct snd_soc_device *socdev = platform_get_drvdata(pdev); | 624 | wm9090_set_bias_level(codec, SND_SOC_BIAS_OFF); |
616 | |||
617 | snd_soc_free_pcms(socdev); | ||
618 | snd_soc_dapm_free(socdev); | ||
619 | 625 | ||
620 | return 0; | 626 | return 0; |
621 | } | 627 | } |
622 | 628 | ||
623 | struct snd_soc_codec_device soc_codec_dev_wm9090 = { | 629 | static struct snd_soc_codec_driver soc_codec_dev_wm9090 = { |
624 | .probe = wm9090_probe, | 630 | .probe = wm9090_probe, |
625 | .remove = wm9090_remove, | 631 | .remove = wm9090_remove, |
626 | .suspend = wm9090_suspend, | 632 | .suspend = wm9090_suspend, |
627 | .resume = wm9090_resume, | 633 | .resume = wm9090_resume, |
634 | .set_bias_level = wm9090_set_bias_level, | ||
635 | .reg_cache_size = (WM9090_MAX_REGISTER + 1), | ||
636 | .reg_word_size = sizeof(u16), | ||
637 | .reg_cache_default = wm9090_reg_defaults, | ||
638 | .volatile_register = wm9090_volatile, | ||
628 | }; | 639 | }; |
629 | EXPORT_SYMBOL_GPL(soc_codec_dev_wm9090); | ||
630 | 640 | ||
631 | static int wm9090_i2c_probe(struct i2c_client *i2c, | 641 | static int wm9090_i2c_probe(struct i2c_client *i2c, |
632 | const struct i2c_device_id *id) | 642 | const struct i2c_device_id *id) |
633 | { | 643 | { |
634 | struct wm9090_priv *wm9090; | 644 | struct wm9090_priv *wm9090; |
635 | struct snd_soc_codec *codec; | ||
636 | int ret; | 645 | int ret; |
637 | 646 | ||
638 | wm9090 = kzalloc(sizeof(*wm9090), GFP_KERNEL); | 647 | wm9090 = kzalloc(sizeof(*wm9090), GFP_KERNEL); |
@@ -640,102 +649,28 @@ static int wm9090_i2c_probe(struct i2c_client *i2c, | |||
640 | dev_err(&i2c->dev, "Can not allocate memory\n"); | 649 | dev_err(&i2c->dev, "Can not allocate memory\n"); |
641 | return -ENOMEM; | 650 | return -ENOMEM; |
642 | } | 651 | } |
643 | codec = &wm9090->codec; | ||
644 | 652 | ||
645 | if (i2c->dev.platform_data) | 653 | if (i2c->dev.platform_data) |
646 | memcpy(&wm9090->pdata, i2c->dev.platform_data, | 654 | memcpy(&wm9090->pdata, i2c->dev.platform_data, |
647 | sizeof(wm9090->pdata)); | 655 | sizeof(wm9090->pdata)); |
648 | 656 | ||
649 | wm9090_codec = codec; | ||
650 | |||
651 | i2c_set_clientdata(i2c, wm9090); | 657 | i2c_set_clientdata(i2c, wm9090); |
658 | wm9090->control_data = i2c; | ||
659 | mutex_init(&wm9090->mutex); | ||
652 | 660 | ||
653 | mutex_init(&codec->mutex); | 661 | ret = snd_soc_register_codec(&i2c->dev, |
654 | INIT_LIST_HEAD(&codec->dapm_widgets); | 662 | &soc_codec_dev_wm9090, NULL, 0); |
655 | INIT_LIST_HEAD(&codec->dapm_paths); | ||
656 | |||
657 | codec->control_data = i2c; | ||
658 | snd_soc_codec_set_drvdata(codec, wm9090); | ||
659 | codec->dev = &i2c->dev; | ||
660 | codec->name = "WM9090"; | ||
661 | codec->owner = THIS_MODULE; | ||
662 | codec->bias_level = SND_SOC_BIAS_OFF; | ||
663 | codec->set_bias_level = wm9090_set_bias_level, | ||
664 | codec->reg_cache_size = WM9090_MAX_REGISTER + 1; | ||
665 | codec->reg_cache = &wm9090->reg_cache; | ||
666 | codec->volatile_register = wm9090_volatile; | ||
667 | |||
668 | ret = snd_soc_codec_set_cache_io(codec, 8, 16, SND_SOC_I2C); | ||
669 | if (ret != 0) { | ||
670 | dev_err(codec->dev, "Failed to set cache I/O: %d\n", ret); | ||
671 | goto err; | ||
672 | } | ||
673 | |||
674 | memcpy(&wm9090->reg_cache, wm9090_reg_defaults, | ||
675 | sizeof(wm9090->reg_cache)); | ||
676 | |||
677 | ret = snd_soc_read(codec, WM9090_SOFTWARE_RESET); | ||
678 | if (ret < 0) | ||
679 | goto err; | ||
680 | if (ret != wm9090_reg_defaults[WM9090_SOFTWARE_RESET]) { | ||
681 | dev_err(&i2c->dev, "Device is not a WM9090, ID=%x\n", ret); | ||
682 | ret = -EINVAL; | ||
683 | goto err; | ||
684 | } | ||
685 | |||
686 | ret = snd_soc_write(codec, WM9090_SOFTWARE_RESET, 0); | ||
687 | if (ret < 0) | 663 | if (ret < 0) |
688 | goto err; | 664 | kfree(wm9090); |
689 | |||
690 | /* Configure some defaults; they will be written out when we | ||
691 | * bring the bias up. | ||
692 | */ | ||
693 | wm9090->reg_cache[WM9090_IN1_LINE_INPUT_A_VOLUME] |= WM9090_IN1_VU | ||
694 | | WM9090_IN1A_ZC; | ||
695 | wm9090->reg_cache[WM9090_IN1_LINE_INPUT_B_VOLUME] |= WM9090_IN1_VU | ||
696 | | WM9090_IN1B_ZC; | ||
697 | wm9090->reg_cache[WM9090_IN2_LINE_INPUT_A_VOLUME] |= WM9090_IN2_VU | ||
698 | | WM9090_IN2A_ZC; | ||
699 | wm9090->reg_cache[WM9090_IN2_LINE_INPUT_B_VOLUME] |= WM9090_IN2_VU | ||
700 | | WM9090_IN2B_ZC; | ||
701 | wm9090->reg_cache[WM9090_SPEAKER_VOLUME_LEFT] |= | ||
702 | WM9090_SPKOUT_VU | WM9090_SPKOUTL_ZC; | ||
703 | wm9090->reg_cache[WM9090_LEFT_OUTPUT_VOLUME] |= | ||
704 | WM9090_HPOUT1_VU | WM9090_HPOUT1L_ZC; | ||
705 | wm9090->reg_cache[WM9090_RIGHT_OUTPUT_VOLUME] |= | ||
706 | WM9090_HPOUT1_VU | WM9090_HPOUT1R_ZC; | ||
707 | |||
708 | wm9090->reg_cache[WM9090_CLOCKING_1] |= WM9090_TOCLK_ENA; | ||
709 | |||
710 | wm9090_set_bias_level(codec, SND_SOC_BIAS_STANDBY); | ||
711 | |||
712 | ret = snd_soc_register_codec(codec); | ||
713 | if (ret != 0) { | ||
714 | dev_err(&i2c->dev, "Failed to register CODEC: %d\n", ret); | ||
715 | goto err_bias; | ||
716 | } | ||
717 | |||
718 | return 0; | ||
719 | |||
720 | err_bias: | ||
721 | wm9090_set_bias_level(codec, SND_SOC_BIAS_OFF); | ||
722 | err: | ||
723 | kfree(wm9090); | ||
724 | i2c_set_clientdata(i2c, NULL); | ||
725 | wm9090_codec = NULL; | ||
726 | |||
727 | return ret; | 665 | return ret; |
728 | } | 666 | } |
729 | 667 | ||
730 | static int wm9090_i2c_remove(struct i2c_client *i2c) | 668 | static int wm9090_i2c_remove(struct i2c_client *i2c) |
731 | { | 669 | { |
732 | struct wm9090_priv *wm9090 = i2c_get_clientdata(i2c); | 670 | struct wm9090_priv *wm9090 = i2c_get_clientdata(i2c); |
733 | struct snd_soc_codec *codec = &wm9090->codec; | ||
734 | 671 | ||
735 | snd_soc_unregister_codec(codec); | 672 | snd_soc_unregister_codec(&i2c->dev); |
736 | wm9090_set_bias_level(codec, SND_SOC_BIAS_OFF); | ||
737 | kfree(wm9090); | 673 | kfree(wm9090); |
738 | wm9090_codec = NULL; | ||
739 | 674 | ||
740 | return 0; | 675 | return 0; |
741 | } | 676 | } |
@@ -748,7 +683,7 @@ MODULE_DEVICE_TABLE(i2c, wm9090_id); | |||
748 | 683 | ||
749 | static struct i2c_driver wm9090_i2c_driver = { | 684 | static struct i2c_driver wm9090_i2c_driver = { |
750 | .driver = { | 685 | .driver = { |
751 | .name = "wm9090", | 686 | .name = "wm9090-codec", |
752 | .owner = THIS_MODULE, | 687 | .owner = THIS_MODULE, |
753 | }, | 688 | }, |
754 | .probe = wm9090_i2c_probe, | 689 | .probe = wm9090_i2c_probe, |
diff --git a/sound/soc/codecs/wm9090.h b/sound/soc/codecs/wm9090.h index b08eab932a5b..29b9d9fc70b4 100644 --- a/sound/soc/codecs/wm9090.h +++ b/sound/soc/codecs/wm9090.h | |||
@@ -23,8 +23,6 @@ | |||
23 | #ifndef __WM9090_H | 23 | #ifndef __WM9090_H |
24 | #define __WM9090_H | 24 | #define __WM9090_H |
25 | 25 | ||
26 | extern struct snd_soc_codec_device soc_codec_dev_wm9090; | ||
27 | |||
28 | /* | 26 | /* |
29 | * Register values. | 27 | * Register values. |
30 | */ | 28 | */ |
diff --git a/sound/soc/codecs/wm9705.c b/sound/soc/codecs/wm9705.c index 8793341849d1..e4d8f5339c51 100644 --- a/sound/soc/codecs/wm9705.c +++ b/sound/soc/codecs/wm9705.c | |||
@@ -248,8 +248,7 @@ static int ac97_prepare(struct snd_pcm_substream *substream, | |||
248 | { | 248 | { |
249 | struct snd_pcm_runtime *runtime = substream->runtime; | 249 | struct snd_pcm_runtime *runtime = substream->runtime; |
250 | struct snd_soc_pcm_runtime *rtd = substream->private_data; | 250 | struct snd_soc_pcm_runtime *rtd = substream->private_data; |
251 | struct snd_soc_device *socdev = rtd->socdev; | 251 | struct snd_soc_codec *codec = rtd->codec; |
252 | struct snd_soc_codec *codec = socdev->card->codec; | ||
253 | int reg; | 252 | int reg; |
254 | u16 vra; | 253 | u16 vra; |
255 | 254 | ||
@@ -273,9 +272,9 @@ static struct snd_soc_dai_ops wm9705_dai_ops = { | |||
273 | .prepare = ac97_prepare, | 272 | .prepare = ac97_prepare, |
274 | }; | 273 | }; |
275 | 274 | ||
276 | struct snd_soc_dai wm9705_dai[] = { | 275 | static struct snd_soc_dai_driver wm9705_dai[] = { |
277 | { | 276 | { |
278 | .name = "AC97 HiFi", | 277 | .name = "wm9705-hifi", |
279 | .ac97_control = 1, | 278 | .ac97_control = 1, |
280 | .playback = { | 279 | .playback = { |
281 | .stream_name = "HiFi Playback", | 280 | .stream_name = "HiFi Playback", |
@@ -294,7 +293,7 @@ struct snd_soc_dai wm9705_dai[] = { | |||
294 | .ops = &wm9705_dai_ops, | 293 | .ops = &wm9705_dai_ops, |
295 | }, | 294 | }, |
296 | { | 295 | { |
297 | .name = "AC97 Aux", | 296 | .name = "wm9705-aux", |
298 | .playback = { | 297 | .playback = { |
299 | .stream_name = "Aux Playback", | 298 | .stream_name = "Aux Playback", |
300 | .channels_min = 1, | 299 | .channels_min = 1, |
@@ -304,7 +303,6 @@ struct snd_soc_dai wm9705_dai[] = { | |||
304 | }, | 303 | }, |
305 | } | 304 | } |
306 | }; | 305 | }; |
307 | EXPORT_SYMBOL_GPL(wm9705_dai); | ||
308 | 306 | ||
309 | static int wm9705_reset(struct snd_soc_codec *codec) | 307 | static int wm9705_reset(struct snd_soc_codec *codec) |
310 | { | 308 | { |
@@ -318,20 +316,15 @@ static int wm9705_reset(struct snd_soc_codec *codec) | |||
318 | } | 316 | } |
319 | 317 | ||
320 | #ifdef CONFIG_PM | 318 | #ifdef CONFIG_PM |
321 | static int wm9705_soc_suspend(struct platform_device *pdev, pm_message_t msg) | 319 | static int wm9705_soc_suspend(struct snd_soc_codec *codec, pm_message_t msg) |
322 | { | 320 | { |
323 | struct snd_soc_device *socdev = platform_get_drvdata(pdev); | ||
324 | struct snd_soc_codec *codec = socdev->card->codec; | ||
325 | |||
326 | soc_ac97_ops.write(codec->ac97, AC97_POWERDOWN, 0xffff); | 321 | soc_ac97_ops.write(codec->ac97, AC97_POWERDOWN, 0xffff); |
327 | 322 | ||
328 | return 0; | 323 | return 0; |
329 | } | 324 | } |
330 | 325 | ||
331 | static int wm9705_soc_resume(struct platform_device *pdev) | 326 | static int wm9705_soc_resume(struct snd_soc_codec *codec) |
332 | { | 327 | { |
333 | struct snd_soc_device *socdev = platform_get_drvdata(pdev); | ||
334 | struct snd_soc_codec *codec = socdev->card->codec; | ||
335 | int i, ret; | 328 | int i, ret; |
336 | u16 *cache = codec->reg_cache; | 329 | u16 *cache = codec->reg_cache; |
337 | 330 | ||
@@ -352,49 +345,18 @@ static int wm9705_soc_resume(struct platform_device *pdev) | |||
352 | #define wm9705_soc_resume NULL | 345 | #define wm9705_soc_resume NULL |
353 | #endif | 346 | #endif |
354 | 347 | ||
355 | static int wm9705_soc_probe(struct platform_device *pdev) | 348 | static int wm9705_soc_probe(struct snd_soc_codec *codec) |
356 | { | 349 | { |
357 | struct snd_soc_device *socdev = platform_get_drvdata(pdev); | ||
358 | struct snd_soc_codec *codec; | ||
359 | int ret = 0; | 350 | int ret = 0; |
360 | 351 | ||
361 | printk(KERN_INFO "WM9705 SoC Audio Codec\n"); | 352 | printk(KERN_INFO "WM9705 SoC Audio Codec\n"); |
362 | 353 | ||
363 | socdev->card->codec = kzalloc(sizeof(struct snd_soc_codec), | ||
364 | GFP_KERNEL); | ||
365 | if (socdev->card->codec == NULL) | ||
366 | return -ENOMEM; | ||
367 | codec = socdev->card->codec; | ||
368 | mutex_init(&codec->mutex); | ||
369 | |||
370 | codec->reg_cache = kmemdup(wm9705_reg, sizeof(wm9705_reg), GFP_KERNEL); | ||
371 | if (codec->reg_cache == NULL) { | ||
372 | ret = -ENOMEM; | ||
373 | goto cache_err; | ||
374 | } | ||
375 | codec->reg_cache_size = sizeof(wm9705_reg); | ||
376 | codec->reg_cache_step = 2; | ||
377 | |||
378 | codec->name = "WM9705"; | ||
379 | codec->owner = THIS_MODULE; | ||
380 | codec->dai = wm9705_dai; | ||
381 | codec->num_dai = ARRAY_SIZE(wm9705_dai); | ||
382 | codec->write = ac97_write; | ||
383 | codec->read = ac97_read; | ||
384 | INIT_LIST_HEAD(&codec->dapm_widgets); | ||
385 | INIT_LIST_HEAD(&codec->dapm_paths); | ||
386 | |||
387 | ret = snd_soc_new_ac97_codec(codec, &soc_ac97_ops, 0); | 354 | ret = snd_soc_new_ac97_codec(codec, &soc_ac97_ops, 0); |
388 | if (ret < 0) { | 355 | if (ret < 0) { |
389 | printk(KERN_ERR "wm9705: failed to register AC97 codec\n"); | 356 | printk(KERN_ERR "wm9705: failed to register AC97 codec\n"); |
390 | goto codec_err; | 357 | return ret; |
391 | } | 358 | } |
392 | 359 | ||
393 | /* register pcms */ | ||
394 | ret = snd_soc_new_pcms(socdev, SNDRV_DEFAULT_IDX1, SNDRV_DEFAULT_STR1); | ||
395 | if (ret < 0) | ||
396 | goto pcm_err; | ||
397 | |||
398 | ret = wm9705_reset(codec); | 360 | ret = wm9705_reset(codec); |
399 | if (ret) | 361 | if (ret) |
400 | goto reset_err; | 362 | goto reset_err; |
@@ -406,40 +368,62 @@ static int wm9705_soc_probe(struct platform_device *pdev) | |||
406 | return 0; | 368 | return 0; |
407 | 369 | ||
408 | reset_err: | 370 | reset_err: |
409 | snd_soc_free_pcms(socdev); | ||
410 | pcm_err: | ||
411 | snd_soc_free_ac97_codec(codec); | 371 | snd_soc_free_ac97_codec(codec); |
412 | codec_err: | ||
413 | kfree(codec->reg_cache); | ||
414 | cache_err: | ||
415 | kfree(socdev->card->codec); | ||
416 | socdev->card->codec = NULL; | ||
417 | return ret; | 372 | return ret; |
418 | } | 373 | } |
419 | 374 | ||
420 | static int wm9705_soc_remove(struct platform_device *pdev) | 375 | static int wm9705_soc_remove(struct snd_soc_codec *codec) |
421 | { | 376 | { |
422 | struct snd_soc_device *socdev = platform_get_drvdata(pdev); | ||
423 | struct snd_soc_codec *codec = socdev->card->codec; | ||
424 | |||
425 | if (codec == NULL) | ||
426 | return 0; | ||
427 | |||
428 | snd_soc_dapm_free(socdev); | ||
429 | snd_soc_free_pcms(socdev); | ||
430 | snd_soc_free_ac97_codec(codec); | 377 | snd_soc_free_ac97_codec(codec); |
431 | kfree(codec->reg_cache); | ||
432 | kfree(codec); | ||
433 | return 0; | 378 | return 0; |
434 | } | 379 | } |
435 | 380 | ||
436 | struct snd_soc_codec_device soc_codec_dev_wm9705 = { | 381 | static struct snd_soc_codec_driver soc_codec_dev_wm9705 = { |
437 | .probe = wm9705_soc_probe, | 382 | .probe = wm9705_soc_probe, |
438 | .remove = wm9705_soc_remove, | 383 | .remove = wm9705_soc_remove, |
439 | .suspend = wm9705_soc_suspend, | 384 | .suspend = wm9705_soc_suspend, |
440 | .resume = wm9705_soc_resume, | 385 | .resume = wm9705_soc_resume, |
386 | .read = ac97_read, | ||
387 | .write = ac97_write, | ||
388 | .reg_cache_size = sizeof(wm9705_reg), | ||
389 | .reg_word_size = sizeof(u16), | ||
390 | .reg_cache_step = 2, | ||
391 | .reg_cache_default = wm9705_reg, | ||
392 | }; | ||
393 | |||
394 | static __devinit int wm9705_probe(struct platform_device *pdev) | ||
395 | { | ||
396 | return snd_soc_register_codec(&pdev->dev, | ||
397 | &soc_codec_dev_wm9705, wm9705_dai, ARRAY_SIZE(wm9705_dai)); | ||
398 | } | ||
399 | |||
400 | static int __devexit wm9705_remove(struct platform_device *pdev) | ||
401 | { | ||
402 | snd_soc_unregister_codec(&pdev->dev); | ||
403 | return 0; | ||
404 | } | ||
405 | |||
406 | static struct platform_driver wm9705_codec_driver = { | ||
407 | .driver = { | ||
408 | .name = "wm9705-codec", | ||
409 | .owner = THIS_MODULE, | ||
410 | }, | ||
411 | |||
412 | .probe = wm9705_probe, | ||
413 | .remove = __devexit_p(wm9705_remove), | ||
441 | }; | 414 | }; |
442 | EXPORT_SYMBOL_GPL(soc_codec_dev_wm9705); | 415 | |
416 | static int __init wm9705_init(void) | ||
417 | { | ||
418 | return platform_driver_register(&wm9705_codec_driver); | ||
419 | } | ||
420 | module_init(wm9705_init); | ||
421 | |||
422 | static void __exit wm9705_exit(void) | ||
423 | { | ||
424 | platform_driver_unregister(&wm9705_codec_driver); | ||
425 | } | ||
426 | module_exit(wm9705_exit); | ||
443 | 427 | ||
444 | MODULE_DESCRIPTION("ASoC WM9705 driver"); | 428 | MODULE_DESCRIPTION("ASoC WM9705 driver"); |
445 | MODULE_AUTHOR("Ian Molton"); | 429 | MODULE_AUTHOR("Ian Molton"); |
diff --git a/sound/soc/codecs/wm9705.h b/sound/soc/codecs/wm9705.h index d380f110f9e2..23ea9ce47359 100644 --- a/sound/soc/codecs/wm9705.h +++ b/sound/soc/codecs/wm9705.h | |||
@@ -8,7 +8,4 @@ | |||
8 | #define WM9705_DAI_AC97_HIFI 0 | 8 | #define WM9705_DAI_AC97_HIFI 0 |
9 | #define WM9705_DAI_AC97_AUX 1 | 9 | #define WM9705_DAI_AC97_AUX 1 |
10 | 10 | ||
11 | extern struct snd_soc_dai wm9705_dai[2]; | ||
12 | extern struct snd_soc_codec_device soc_codec_dev_wm9705; | ||
13 | |||
14 | #endif | 11 | #endif |
diff --git a/sound/soc/codecs/wm9712.c b/sound/soc/codecs/wm9712.c index 28790a2ffe8d..f8f37ae30910 100644 --- a/sound/soc/codecs/wm9712.c +++ b/sound/soc/codecs/wm9712.c | |||
@@ -478,8 +478,7 @@ static int ac97_prepare(struct snd_pcm_substream *substream, | |||
478 | { | 478 | { |
479 | struct snd_pcm_runtime *runtime = substream->runtime; | 479 | struct snd_pcm_runtime *runtime = substream->runtime; |
480 | struct snd_soc_pcm_runtime *rtd = substream->private_data; | 480 | struct snd_soc_pcm_runtime *rtd = substream->private_data; |
481 | struct snd_soc_device *socdev = rtd->socdev; | 481 | struct snd_soc_codec *codec =rtd->codec; |
482 | struct snd_soc_codec *codec = socdev->card->codec; | ||
483 | int reg; | 482 | int reg; |
484 | u16 vra; | 483 | u16 vra; |
485 | 484 | ||
@@ -499,8 +498,7 @@ static int ac97_aux_prepare(struct snd_pcm_substream *substream, | |||
499 | { | 498 | { |
500 | struct snd_pcm_runtime *runtime = substream->runtime; | 499 | struct snd_pcm_runtime *runtime = substream->runtime; |
501 | struct snd_soc_pcm_runtime *rtd = substream->private_data; | 500 | struct snd_soc_pcm_runtime *rtd = substream->private_data; |
502 | struct snd_soc_device *socdev = rtd->socdev; | 501 | struct snd_soc_codec *codec = rtd->codec; |
503 | struct snd_soc_codec *codec = socdev->card->codec; | ||
504 | u16 vra, xsle; | 502 | u16 vra, xsle; |
505 | 503 | ||
506 | vra = ac97_read(codec, AC97_EXTENDED_STATUS); | 504 | vra = ac97_read(codec, AC97_EXTENDED_STATUS); |
@@ -526,9 +524,9 @@ static struct snd_soc_dai_ops wm9712_dai_ops_aux = { | |||
526 | .prepare = ac97_aux_prepare, | 524 | .prepare = ac97_aux_prepare, |
527 | }; | 525 | }; |
528 | 526 | ||
529 | struct snd_soc_dai wm9712_dai[] = { | 527 | struct snd_soc_dai_driver wm9712_dai[] = { |
530 | { | 528 | { |
531 | .name = "AC97 HiFi", | 529 | .name = "wm9712-hifi", |
532 | .ac97_control = 1, | 530 | .ac97_control = 1, |
533 | .playback = { | 531 | .playback = { |
534 | .stream_name = "HiFi Playback", | 532 | .stream_name = "HiFi Playback", |
@@ -545,7 +543,7 @@ struct snd_soc_dai wm9712_dai[] = { | |||
545 | .ops = &wm9712_dai_ops_hifi, | 543 | .ops = &wm9712_dai_ops_hifi, |
546 | }, | 544 | }, |
547 | { | 545 | { |
548 | .name = "AC97 Aux", | 546 | .name = "wm9712-aux", |
549 | .playback = { | 547 | .playback = { |
550 | .stream_name = "Aux Playback", | 548 | .stream_name = "Aux Playback", |
551 | .channels_min = 1, | 549 | .channels_min = 1, |
@@ -555,7 +553,6 @@ struct snd_soc_dai wm9712_dai[] = { | |||
555 | .ops = &wm9712_dai_ops_aux, | 553 | .ops = &wm9712_dai_ops_aux, |
556 | } | 554 | } |
557 | }; | 555 | }; |
558 | EXPORT_SYMBOL_GPL(wm9712_dai); | ||
559 | 556 | ||
560 | static int wm9712_set_bias_level(struct snd_soc_codec *codec, | 557 | static int wm9712_set_bias_level(struct snd_soc_codec *codec, |
561 | enum snd_soc_bias_level level) | 558 | enum snd_soc_bias_level level) |
@@ -597,20 +594,15 @@ err: | |||
597 | return -EIO; | 594 | return -EIO; |
598 | } | 595 | } |
599 | 596 | ||
600 | static int wm9712_soc_suspend(struct platform_device *pdev, | 597 | static int wm9712_soc_suspend(struct snd_soc_codec *codec, |
601 | pm_message_t state) | 598 | pm_message_t state) |
602 | { | 599 | { |
603 | struct snd_soc_device *socdev = platform_get_drvdata(pdev); | ||
604 | struct snd_soc_codec *codec = socdev->card->codec; | ||
605 | |||
606 | wm9712_set_bias_level(codec, SND_SOC_BIAS_OFF); | 600 | wm9712_set_bias_level(codec, SND_SOC_BIAS_OFF); |
607 | return 0; | 601 | return 0; |
608 | } | 602 | } |
609 | 603 | ||
610 | static int wm9712_soc_resume(struct platform_device *pdev) | 604 | static int wm9712_soc_resume(struct snd_soc_codec *codec) |
611 | { | 605 | { |
612 | struct snd_soc_device *socdev = platform_get_drvdata(pdev); | ||
613 | struct snd_soc_codec *codec = socdev->card->codec; | ||
614 | int i, ret; | 606 | int i, ret; |
615 | u16 *cache = codec->reg_cache; | 607 | u16 *cache = codec->reg_cache; |
616 | 608 | ||
@@ -635,51 +627,18 @@ static int wm9712_soc_resume(struct platform_device *pdev) | |||
635 | return ret; | 627 | return ret; |
636 | } | 628 | } |
637 | 629 | ||
638 | static int wm9712_soc_probe(struct platform_device *pdev) | 630 | static int wm9712_soc_probe(struct snd_soc_codec *codec) |
639 | { | 631 | { |
640 | struct snd_soc_device *socdev = platform_get_drvdata(pdev); | ||
641 | struct snd_soc_codec *codec; | ||
642 | int ret = 0; | 632 | int ret = 0; |
643 | 633 | ||
644 | printk(KERN_INFO "WM9711/WM9712 SoC Audio Codec %s\n", WM9712_VERSION); | 634 | printk(KERN_INFO "WM9711/WM9712 SoC Audio Codec %s\n", WM9712_VERSION); |
645 | 635 | ||
646 | socdev->card->codec = kzalloc(sizeof(struct snd_soc_codec), | ||
647 | GFP_KERNEL); | ||
648 | if (socdev->card->codec == NULL) | ||
649 | return -ENOMEM; | ||
650 | codec = socdev->card->codec; | ||
651 | mutex_init(&codec->mutex); | ||
652 | |||
653 | codec->reg_cache = kmemdup(wm9712_reg, sizeof(wm9712_reg), GFP_KERNEL); | ||
654 | |||
655 | if (codec->reg_cache == NULL) { | ||
656 | ret = -ENOMEM; | ||
657 | goto cache_err; | ||
658 | } | ||
659 | codec->reg_cache_size = sizeof(wm9712_reg); | ||
660 | codec->reg_cache_step = 2; | ||
661 | |||
662 | codec->name = "WM9712"; | ||
663 | codec->owner = THIS_MODULE; | ||
664 | codec->dai = wm9712_dai; | ||
665 | codec->num_dai = ARRAY_SIZE(wm9712_dai); | ||
666 | codec->write = ac97_write; | ||
667 | codec->read = ac97_read; | ||
668 | codec->set_bias_level = wm9712_set_bias_level; | ||
669 | INIT_LIST_HEAD(&codec->dapm_widgets); | ||
670 | INIT_LIST_HEAD(&codec->dapm_paths); | ||
671 | |||
672 | ret = snd_soc_new_ac97_codec(codec, &soc_ac97_ops, 0); | 636 | ret = snd_soc_new_ac97_codec(codec, &soc_ac97_ops, 0); |
673 | if (ret < 0) { | 637 | if (ret < 0) { |
674 | printk(KERN_ERR "wm9712: failed to register AC97 codec\n"); | 638 | printk(KERN_ERR "wm9712: failed to register AC97 codec\n"); |
675 | goto codec_err; | 639 | return ret; |
676 | } | 640 | } |
677 | 641 | ||
678 | /* register pcms */ | ||
679 | ret = snd_soc_new_pcms(socdev, SNDRV_DEFAULT_IDX1, SNDRV_DEFAULT_STR1); | ||
680 | if (ret < 0) | ||
681 | goto pcm_err; | ||
682 | |||
683 | ret = wm9712_reset(codec, 0); | 642 | ret = wm9712_reset(codec, 0); |
684 | if (ret < 0) { | 643 | if (ret < 0) { |
685 | printk(KERN_ERR "Failed to reset WM9712: AC97 link error\n"); | 644 | printk(KERN_ERR "Failed to reset WM9712: AC97 link error\n"); |
@@ -697,42 +656,63 @@ static int wm9712_soc_probe(struct platform_device *pdev) | |||
697 | return 0; | 656 | return 0; |
698 | 657 | ||
699 | reset_err: | 658 | reset_err: |
700 | snd_soc_free_pcms(socdev); | ||
701 | pcm_err: | ||
702 | snd_soc_free_ac97_codec(codec); | 659 | snd_soc_free_ac97_codec(codec); |
703 | |||
704 | codec_err: | ||
705 | kfree(codec->reg_cache); | ||
706 | |||
707 | cache_err: | ||
708 | kfree(socdev->card->codec); | ||
709 | socdev->card->codec = NULL; | ||
710 | return ret; | 660 | return ret; |
711 | } | 661 | } |
712 | 662 | ||
713 | static int wm9712_soc_remove(struct platform_device *pdev) | 663 | static int wm9712_soc_remove(struct snd_soc_codec *codec) |
714 | { | 664 | { |
715 | struct snd_soc_device *socdev = platform_get_drvdata(pdev); | ||
716 | struct snd_soc_codec *codec = socdev->card->codec; | ||
717 | |||
718 | if (codec == NULL) | ||
719 | return 0; | ||
720 | |||
721 | snd_soc_dapm_free(socdev); | ||
722 | snd_soc_free_pcms(socdev); | ||
723 | snd_soc_free_ac97_codec(codec); | 665 | snd_soc_free_ac97_codec(codec); |
724 | kfree(codec->reg_cache); | ||
725 | kfree(codec); | ||
726 | return 0; | 666 | return 0; |
727 | } | 667 | } |
728 | 668 | ||
729 | struct snd_soc_codec_device soc_codec_dev_wm9712 = { | 669 | static struct snd_soc_codec_driver soc_codec_dev_wm9712 = { |
730 | .probe = wm9712_soc_probe, | 670 | .probe = wm9712_soc_probe, |
731 | .remove = wm9712_soc_remove, | 671 | .remove = wm9712_soc_remove, |
732 | .suspend = wm9712_soc_suspend, | 672 | .suspend = wm9712_soc_suspend, |
733 | .resume = wm9712_soc_resume, | 673 | .resume = wm9712_soc_resume, |
674 | .read = ac97_read, | ||
675 | .write = ac97_write, | ||
676 | .set_bias_level = wm9712_set_bias_level, | ||
677 | .reg_cache_size = sizeof(wm9712_reg), | ||
678 | .reg_word_size = sizeof(u16), | ||
679 | .reg_cache_step = 2, | ||
680 | .reg_cache_default = wm9712_reg, | ||
734 | }; | 681 | }; |
735 | EXPORT_SYMBOL_GPL(soc_codec_dev_wm9712); | 682 | |
683 | static __devinit int wm9712_probe(struct platform_device *pdev) | ||
684 | { | ||
685 | return snd_soc_register_codec(&pdev->dev, | ||
686 | &soc_codec_dev_wm9712, wm9712_dai, ARRAY_SIZE(wm9712_dai)); | ||
687 | } | ||
688 | |||
689 | static int __devexit wm9712_remove(struct platform_device *pdev) | ||
690 | { | ||
691 | snd_soc_unregister_codec(&pdev->dev); | ||
692 | return 0; | ||
693 | } | ||
694 | |||
695 | static struct platform_driver wm9712_codec_driver = { | ||
696 | .driver = { | ||
697 | .name = "wm9712-codec", | ||
698 | .owner = THIS_MODULE, | ||
699 | }, | ||
700 | |||
701 | .probe = wm9712_probe, | ||
702 | .remove = __devexit_p(wm9712_remove), | ||
703 | }; | ||
704 | |||
705 | static int __init wm9712_init(void) | ||
706 | { | ||
707 | return platform_driver_register(&wm9712_codec_driver); | ||
708 | } | ||
709 | module_init(wm9712_init); | ||
710 | |||
711 | static void __exit wm9712_exit(void) | ||
712 | { | ||
713 | platform_driver_unregister(&wm9712_codec_driver); | ||
714 | } | ||
715 | module_exit(wm9712_exit); | ||
736 | 716 | ||
737 | MODULE_DESCRIPTION("ASoC WM9711/WM9712 driver"); | 717 | MODULE_DESCRIPTION("ASoC WM9711/WM9712 driver"); |
738 | MODULE_AUTHOR("Liam Girdwood"); | 718 | MODULE_AUTHOR("Liam Girdwood"); |
diff --git a/sound/soc/codecs/wm9712.h b/sound/soc/codecs/wm9712.h index d29e8a18ca6d..fb69c3aa4ed0 100644 --- a/sound/soc/codecs/wm9712.h +++ b/sound/soc/codecs/wm9712.h | |||
@@ -8,7 +8,4 @@ | |||
8 | #define WM9712_DAI_AC97_HIFI 0 | 8 | #define WM9712_DAI_AC97_HIFI 0 |
9 | #define WM9712_DAI_AC97_AUX 1 | 9 | #define WM9712_DAI_AC97_AUX 1 |
10 | 10 | ||
11 | extern struct snd_soc_dai wm9712_dai[2]; | ||
12 | extern struct snd_soc_codec_device soc_codec_dev_wm9712; | ||
13 | |||
14 | #endif | 11 | #endif |
diff --git a/sound/soc/codecs/wm9713.c b/sound/soc/codecs/wm9713.c index 34e0c91092fa..463917e762b5 100644 --- a/sound/soc/codecs/wm9713.c +++ b/sound/soc/codecs/wm9713.c | |||
@@ -1057,9 +1057,9 @@ static struct snd_soc_dai_ops wm9713_dai_ops_voice = { | |||
1057 | .set_tristate = wm9713_set_dai_tristate, | 1057 | .set_tristate = wm9713_set_dai_tristate, |
1058 | }; | 1058 | }; |
1059 | 1059 | ||
1060 | struct snd_soc_dai wm9713_dai[] = { | 1060 | static struct snd_soc_dai_driver wm9713_dai[] = { |
1061 | { | 1061 | { |
1062 | .name = "AC97 HiFi", | 1062 | .name = "wm9713-hifi", |
1063 | .ac97_control = 1, | 1063 | .ac97_control = 1, |
1064 | .playback = { | 1064 | .playback = { |
1065 | .stream_name = "HiFi Playback", | 1065 | .stream_name = "HiFi Playback", |
@@ -1076,7 +1076,7 @@ struct snd_soc_dai wm9713_dai[] = { | |||
1076 | .ops = &wm9713_dai_ops_hifi, | 1076 | .ops = &wm9713_dai_ops_hifi, |
1077 | }, | 1077 | }, |
1078 | { | 1078 | { |
1079 | .name = "AC97 Aux", | 1079 | .name = "wm9713-aux", |
1080 | .playback = { | 1080 | .playback = { |
1081 | .stream_name = "Aux Playback", | 1081 | .stream_name = "Aux Playback", |
1082 | .channels_min = 1, | 1082 | .channels_min = 1, |
@@ -1086,7 +1086,7 @@ struct snd_soc_dai wm9713_dai[] = { | |||
1086 | .ops = &wm9713_dai_ops_aux, | 1086 | .ops = &wm9713_dai_ops_aux, |
1087 | }, | 1087 | }, |
1088 | { | 1088 | { |
1089 | .name = "WM9713 Voice", | 1089 | .name = "wm9713-voice", |
1090 | .playback = { | 1090 | .playback = { |
1091 | .stream_name = "Voice Playback", | 1091 | .stream_name = "Voice Playback", |
1092 | .channels_min = 1, | 1092 | .channels_min = 1, |
@@ -1103,7 +1103,6 @@ struct snd_soc_dai wm9713_dai[] = { | |||
1103 | .symmetric_rates = 1, | 1103 | .symmetric_rates = 1, |
1104 | }, | 1104 | }, |
1105 | }; | 1105 | }; |
1106 | EXPORT_SYMBOL_GPL(wm9713_dai); | ||
1107 | 1106 | ||
1108 | int wm9713_reset(struct snd_soc_codec *codec, int try_warm) | 1107 | int wm9713_reset(struct snd_soc_codec *codec, int try_warm) |
1109 | { | 1108 | { |
@@ -1152,11 +1151,9 @@ static int wm9713_set_bias_level(struct snd_soc_codec *codec, | |||
1152 | return 0; | 1151 | return 0; |
1153 | } | 1152 | } |
1154 | 1153 | ||
1155 | static int wm9713_soc_suspend(struct platform_device *pdev, | 1154 | static int wm9713_soc_suspend(struct snd_soc_codec *codec, |
1156 | pm_message_t state) | 1155 | pm_message_t state) |
1157 | { | 1156 | { |
1158 | struct snd_soc_device *socdev = platform_get_drvdata(pdev); | ||
1159 | struct snd_soc_codec *codec = socdev->card->codec; | ||
1160 | u16 reg; | 1157 | u16 reg; |
1161 | 1158 | ||
1162 | /* Disable everything except touchpanel - that will be handled | 1159 | /* Disable everything except touchpanel - that will be handled |
@@ -1171,10 +1168,8 @@ static int wm9713_soc_suspend(struct platform_device *pdev, | |||
1171 | return 0; | 1168 | return 0; |
1172 | } | 1169 | } |
1173 | 1170 | ||
1174 | static int wm9713_soc_resume(struct platform_device *pdev) | 1171 | static int wm9713_soc_resume(struct snd_soc_codec *codec) |
1175 | { | 1172 | { |
1176 | struct snd_soc_device *socdev = platform_get_drvdata(pdev); | ||
1177 | struct snd_soc_codec *codec = socdev->card->codec; | ||
1178 | struct wm9713_priv *wm9713 = snd_soc_codec_get_drvdata(codec); | 1173 | struct wm9713_priv *wm9713 = snd_soc_codec_get_drvdata(codec); |
1179 | int i, ret; | 1174 | int i, ret; |
1180 | u16 *cache = codec->reg_cache; | 1175 | u16 *cache = codec->reg_cache; |
@@ -1204,53 +1199,20 @@ static int wm9713_soc_resume(struct platform_device *pdev) | |||
1204 | return ret; | 1199 | return ret; |
1205 | } | 1200 | } |
1206 | 1201 | ||
1207 | static int wm9713_soc_probe(struct platform_device *pdev) | 1202 | static int wm9713_soc_probe(struct snd_soc_codec *codec) |
1208 | { | 1203 | { |
1209 | struct snd_soc_device *socdev = platform_get_drvdata(pdev); | 1204 | struct wm9713_priv *wm9713; |
1210 | struct snd_soc_codec *codec; | ||
1211 | int ret = 0, reg; | 1205 | int ret = 0, reg; |
1212 | 1206 | ||
1213 | socdev->card->codec = kzalloc(sizeof(struct snd_soc_codec), | 1207 | wm9713 = kzalloc(sizeof(struct wm9713_priv), GFP_KERNEL); |
1214 | GFP_KERNEL); | 1208 | if (wm9713 == NULL) |
1215 | if (socdev->card->codec == NULL) | ||
1216 | return -ENOMEM; | 1209 | return -ENOMEM; |
1217 | codec = socdev->card->codec; | 1210 | snd_soc_codec_set_drvdata(codec, wm9713); |
1218 | mutex_init(&codec->mutex); | ||
1219 | |||
1220 | codec->reg_cache = kmemdup(wm9713_reg, sizeof(wm9713_reg), GFP_KERNEL); | ||
1221 | if (codec->reg_cache == NULL) { | ||
1222 | ret = -ENOMEM; | ||
1223 | goto cache_err; | ||
1224 | } | ||
1225 | codec->reg_cache_size = sizeof(wm9713_reg); | ||
1226 | codec->reg_cache_step = 2; | ||
1227 | |||
1228 | snd_soc_codec_set_drvdata(codec, kzalloc(sizeof(struct wm9713_priv), | ||
1229 | GFP_KERNEL)); | ||
1230 | if (snd_soc_codec_get_drvdata(codec) == NULL) { | ||
1231 | ret = -ENOMEM; | ||
1232 | goto priv_err; | ||
1233 | } | ||
1234 | |||
1235 | codec->name = "WM9713"; | ||
1236 | codec->owner = THIS_MODULE; | ||
1237 | codec->dai = wm9713_dai; | ||
1238 | codec->num_dai = ARRAY_SIZE(wm9713_dai); | ||
1239 | codec->write = ac97_write; | ||
1240 | codec->read = ac97_read; | ||
1241 | codec->set_bias_level = wm9713_set_bias_level; | ||
1242 | INIT_LIST_HEAD(&codec->dapm_widgets); | ||
1243 | INIT_LIST_HEAD(&codec->dapm_paths); | ||
1244 | 1211 | ||
1245 | ret = snd_soc_new_ac97_codec(codec, &soc_ac97_ops, 0); | 1212 | ret = snd_soc_new_ac97_codec(codec, &soc_ac97_ops, 0); |
1246 | if (ret < 0) | 1213 | if (ret < 0) |
1247 | goto codec_err; | 1214 | goto codec_err; |
1248 | 1215 | ||
1249 | /* register pcms */ | ||
1250 | ret = snd_soc_new_pcms(socdev, SNDRV_DEFAULT_IDX1, SNDRV_DEFAULT_STR1); | ||
1251 | if (ret < 0) | ||
1252 | goto pcm_err; | ||
1253 | |||
1254 | /* do a cold reset for the controller and then try | 1216 | /* do a cold reset for the controller and then try |
1255 | * a warm reset followed by an optional cold reset for codec */ | 1217 | * a warm reset followed by an optional cold reset for codec */ |
1256 | wm9713_reset(codec, 0); | 1218 | wm9713_reset(codec, 0); |
@@ -1273,46 +1235,67 @@ static int wm9713_soc_probe(struct platform_device *pdev) | |||
1273 | return 0; | 1235 | return 0; |
1274 | 1236 | ||
1275 | reset_err: | 1237 | reset_err: |
1276 | snd_soc_free_pcms(socdev); | ||
1277 | pcm_err: | ||
1278 | snd_soc_free_ac97_codec(codec); | 1238 | snd_soc_free_ac97_codec(codec); |
1279 | |||
1280 | codec_err: | 1239 | codec_err: |
1281 | kfree(snd_soc_codec_get_drvdata(codec)); | 1240 | kfree(wm9713); |
1282 | |||
1283 | priv_err: | ||
1284 | kfree(codec->reg_cache); | ||
1285 | |||
1286 | cache_err: | ||
1287 | kfree(socdev->card->codec); | ||
1288 | socdev->card->codec = NULL; | ||
1289 | return ret; | 1241 | return ret; |
1290 | } | 1242 | } |
1291 | 1243 | ||
1292 | static int wm9713_soc_remove(struct platform_device *pdev) | 1244 | static int wm9713_soc_remove(struct snd_soc_codec *codec) |
1293 | { | 1245 | { |
1294 | struct snd_soc_device *socdev = platform_get_drvdata(pdev); | 1246 | struct wm9713_priv *wm9713 = snd_soc_codec_get_drvdata(codec); |
1295 | struct snd_soc_codec *codec = socdev->card->codec; | ||
1296 | |||
1297 | if (codec == NULL) | ||
1298 | return 0; | ||
1299 | |||
1300 | snd_soc_dapm_free(socdev); | ||
1301 | snd_soc_free_pcms(socdev); | ||
1302 | snd_soc_free_ac97_codec(codec); | 1247 | snd_soc_free_ac97_codec(codec); |
1303 | kfree(snd_soc_codec_get_drvdata(codec)); | 1248 | kfree(wm9713); |
1304 | kfree(codec->reg_cache); | ||
1305 | kfree(codec); | ||
1306 | return 0; | 1249 | return 0; |
1307 | } | 1250 | } |
1308 | 1251 | ||
1309 | struct snd_soc_codec_device soc_codec_dev_wm9713 = { | 1252 | static struct snd_soc_codec_driver soc_codec_dev_wm9713 = { |
1310 | .probe = wm9713_soc_probe, | 1253 | .probe = wm9713_soc_probe, |
1311 | .remove = wm9713_soc_remove, | 1254 | .remove = wm9713_soc_remove, |
1312 | .suspend = wm9713_soc_suspend, | 1255 | .suspend = wm9713_soc_suspend, |
1313 | .resume = wm9713_soc_resume, | 1256 | .resume = wm9713_soc_resume, |
1257 | .read = ac97_read, | ||
1258 | .write = ac97_write, | ||
1259 | .set_bias_level = wm9713_set_bias_level, | ||
1260 | .reg_cache_size = sizeof(wm9713_reg), | ||
1261 | .reg_word_size = sizeof(u16), | ||
1262 | .reg_cache_step = 2, | ||
1263 | .reg_cache_default = wm9713_reg, | ||
1264 | }; | ||
1265 | |||
1266 | static __devinit int wm9713_probe(struct platform_device *pdev) | ||
1267 | { | ||
1268 | return snd_soc_register_codec(&pdev->dev, | ||
1269 | &soc_codec_dev_wm9713, wm9713_dai, ARRAY_SIZE(wm9713_dai)); | ||
1270 | } | ||
1271 | |||
1272 | static int __devexit wm9713_remove(struct platform_device *pdev) | ||
1273 | { | ||
1274 | snd_soc_unregister_codec(&pdev->dev); | ||
1275 | return 0; | ||
1276 | } | ||
1277 | |||
1278 | static struct platform_driver wm9713_codec_driver = { | ||
1279 | .driver = { | ||
1280 | .name = "wm9713-codec", | ||
1281 | .owner = THIS_MODULE, | ||
1282 | }, | ||
1283 | |||
1284 | .probe = wm9713_probe, | ||
1285 | .remove = __devexit_p(wm9713_remove), | ||
1314 | }; | 1286 | }; |
1315 | EXPORT_SYMBOL_GPL(soc_codec_dev_wm9713); | 1287 | |
1288 | static int __init wm9713_init(void) | ||
1289 | { | ||
1290 | return platform_driver_register(&wm9713_codec_driver); | ||
1291 | } | ||
1292 | module_init(wm9713_init); | ||
1293 | |||
1294 | static void __exit wm9713_exit(void) | ||
1295 | { | ||
1296 | platform_driver_unregister(&wm9713_codec_driver); | ||
1297 | } | ||
1298 | module_exit(wm9713_exit); | ||
1316 | 1299 | ||
1317 | MODULE_DESCRIPTION("ASoC WM9713/WM9714 driver"); | 1300 | MODULE_DESCRIPTION("ASoC WM9713/WM9714 driver"); |
1318 | MODULE_AUTHOR("Liam Girdwood"); | 1301 | MODULE_AUTHOR("Liam Girdwood"); |
diff --git a/sound/soc/codecs/wm9713.h b/sound/soc/codecs/wm9713.h index 63b8d81756e3..793da863a03d 100644 --- a/sound/soc/codecs/wm9713.h +++ b/sound/soc/codecs/wm9713.h | |||
@@ -45,9 +45,6 @@ | |||
45 | #define WM9713_DAI_AC97_AUX 1 | 45 | #define WM9713_DAI_AC97_AUX 1 |
46 | #define WM9713_DAI_PCM_VOICE 2 | 46 | #define WM9713_DAI_PCM_VOICE 2 |
47 | 47 | ||
48 | extern struct snd_soc_codec_device soc_codec_dev_wm9713; | ||
49 | extern struct snd_soc_dai wm9713_dai[3]; | ||
50 | |||
51 | int wm9713_reset(struct snd_soc_codec *codec, int try_warm); | 48 | int wm9713_reset(struct snd_soc_codec *codec, int try_warm); |
52 | 49 | ||
53 | #endif | 50 | #endif |
diff --git a/sound/soc/davinci/davinci-evm.c b/sound/soc/davinci/davinci-evm.c index 97f74d6a33e6..2b07b17a6b2d 100644 --- a/sound/soc/davinci/davinci-evm.c +++ b/sound/soc/davinci/davinci-evm.c | |||
@@ -28,12 +28,9 @@ | |||
28 | #include <mach/mux.h> | 28 | #include <mach/mux.h> |
29 | 29 | ||
30 | #include "../codecs/tlv320aic3x.h" | 30 | #include "../codecs/tlv320aic3x.h" |
31 | #include "../codecs/cq93vc.h" | ||
32 | #include "../codecs/spdif_transciever.h" | ||
33 | #include "davinci-pcm.h" | 31 | #include "davinci-pcm.h" |
34 | #include "davinci-i2s.h" | 32 | #include "davinci-i2s.h" |
35 | #include "davinci-mcasp.h" | 33 | #include "davinci-mcasp.h" |
36 | #include "davinci-vcif.h" | ||
37 | 34 | ||
38 | #define AUDIO_FORMAT (SND_SOC_DAIFMT_DSP_B | \ | 35 | #define AUDIO_FORMAT (SND_SOC_DAIFMT_DSP_B | \ |
39 | SND_SOC_DAIFMT_CBM_CFM | SND_SOC_DAIFMT_IB_NF) | 36 | SND_SOC_DAIFMT_CBM_CFM | SND_SOC_DAIFMT_IB_NF) |
@@ -41,8 +38,8 @@ static int evm_hw_params(struct snd_pcm_substream *substream, | |||
41 | struct snd_pcm_hw_params *params) | 38 | struct snd_pcm_hw_params *params) |
42 | { | 39 | { |
43 | struct snd_soc_pcm_runtime *rtd = substream->private_data; | 40 | struct snd_soc_pcm_runtime *rtd = substream->private_data; |
44 | struct snd_soc_dai *codec_dai = rtd->dai->codec_dai; | 41 | struct snd_soc_dai *codec_dai = rtd->codec_dai; |
45 | struct snd_soc_dai *cpu_dai = rtd->dai->cpu_dai; | 42 | struct snd_soc_dai *cpu_dai = rtd->cpu_dai; |
46 | int ret = 0; | 43 | int ret = 0; |
47 | unsigned sysclk; | 44 | unsigned sysclk; |
48 | 45 | ||
@@ -87,7 +84,7 @@ static int evm_spdif_hw_params(struct snd_pcm_substream *substream, | |||
87 | struct snd_pcm_hw_params *params) | 84 | struct snd_pcm_hw_params *params) |
88 | { | 85 | { |
89 | struct snd_soc_pcm_runtime *rtd = substream->private_data; | 86 | struct snd_soc_pcm_runtime *rtd = substream->private_data; |
90 | struct snd_soc_dai *cpu_dai = rtd->dai->cpu_dai; | 87 | struct snd_soc_dai *cpu_dai = rtd->cpu_dai; |
91 | 88 | ||
92 | /* set cpu DAI configuration */ | 89 | /* set cpu DAI configuration */ |
93 | return snd_soc_dai_set_fmt(cpu_dai, AUDIO_FORMAT); | 90 | return snd_soc_dai_set_fmt(cpu_dai, AUDIO_FORMAT); |
@@ -132,8 +129,10 @@ static const struct snd_soc_dapm_route audio_map[] = { | |||
132 | }; | 129 | }; |
133 | 130 | ||
134 | /* Logic for a aic3x as connected on a davinci-evm */ | 131 | /* Logic for a aic3x as connected on a davinci-evm */ |
135 | static int evm_aic3x_init(struct snd_soc_codec *codec) | 132 | static int evm_aic3x_init(struct snd_soc_pcm_runtime *rtd) |
136 | { | 133 | { |
134 | struct snd_soc_codec *codec = rtd->codec; | ||
135 | |||
137 | /* Add davinci-evm specific widgets */ | 136 | /* Add davinci-evm specific widgets */ |
138 | snd_soc_dapm_new_controls(codec, aic3x_dapm_widgets, | 137 | snd_soc_dapm_new_controls(codec, aic3x_dapm_widgets, |
139 | ARRAY_SIZE(aic3x_dapm_widgets)); | 138 | ARRAY_SIZE(aic3x_dapm_widgets)); |
@@ -161,8 +160,10 @@ static int evm_aic3x_init(struct snd_soc_codec *codec) | |||
161 | static struct snd_soc_dai_link evm_dai = { | 160 | static struct snd_soc_dai_link evm_dai = { |
162 | .name = "TLV320AIC3X", | 161 | .name = "TLV320AIC3X", |
163 | .stream_name = "AIC3X", | 162 | .stream_name = "AIC3X", |
164 | .cpu_dai = &davinci_i2s_dai, | 163 | .cpu_dai_name = "davinci-mcasp.0", |
165 | .codec_dai = &aic3x_dai, | 164 | .codec_dai_name = "tlv320aic3x-hifi", |
165 | .codec_name = "tlv320aic3x-codec.0-001a", | ||
166 | .platform_name = "davinci-pcm-audio", | ||
166 | .init = evm_aic3x_init, | 167 | .init = evm_aic3x_init, |
167 | .ops = &evm_ops, | 168 | .ops = &evm_ops, |
168 | }; | 169 | }; |
@@ -171,40 +172,49 @@ static struct snd_soc_dai_link dm365_evm_dai = { | |||
171 | #ifdef CONFIG_SND_DM365_AIC3X_CODEC | 172 | #ifdef CONFIG_SND_DM365_AIC3X_CODEC |
172 | .name = "TLV320AIC3X", | 173 | .name = "TLV320AIC3X", |
173 | .stream_name = "AIC3X", | 174 | .stream_name = "AIC3X", |
174 | .cpu_dai = &davinci_i2s_dai, | 175 | .cpu_dai_name = "davinci-i2s", |
175 | .codec_dai = &aic3x_dai, | 176 | .codec_dai_name = "tlv320aic3x-hifi", |
176 | .init = evm_aic3x_init, | 177 | .init = evm_aic3x_init, |
178 | .codec_name = "tlv320aic3x-codec.0-001a", | ||
177 | .ops = &evm_ops, | 179 | .ops = &evm_ops, |
178 | #elif defined(CONFIG_SND_DM365_VOICE_CODEC) | 180 | #elif defined(CONFIG_SND_DM365_VOICE_CODEC) |
179 | .name = "Voice Codec - CQ93VC", | 181 | .name = "Voice Codec - CQ93VC", |
180 | .stream_name = "CQ93", | 182 | .stream_name = "CQ93", |
181 | .cpu_dai = &davinci_vcif_dai, | 183 | .cpu_dai_name = "davinci-vcif", |
182 | .codec_dai = &cq93vc_dai, | 184 | .codec_dai_name = "cq93vc-hifi", |
185 | .codec_name = "cq93vc-codec", | ||
183 | #endif | 186 | #endif |
187 | .platform_name = "davinci-pcm-audio", | ||
184 | }; | 188 | }; |
185 | 189 | ||
186 | static struct snd_soc_dai_link dm6467_evm_dai[] = { | 190 | static struct snd_soc_dai_link dm6467_evm_dai[] = { |
187 | { | 191 | { |
188 | .name = "TLV320AIC3X", | 192 | .name = "TLV320AIC3X", |
189 | .stream_name = "AIC3X", | 193 | .stream_name = "AIC3X", |
190 | .cpu_dai = &davinci_mcasp_dai[DAVINCI_MCASP_I2S_DAI], | 194 | .cpu_dai_name= "davinci-mcasp.0", |
191 | .codec_dai = &aic3x_dai, | 195 | .codec_dai_name = "tlv320aic3x-hifi", |
196 | .platform_name ="davinci-pcm-audio", | ||
197 | .codec_name = "tlv320aic3x-codec.0-001a", | ||
192 | .init = evm_aic3x_init, | 198 | .init = evm_aic3x_init, |
193 | .ops = &evm_ops, | 199 | .ops = &evm_ops, |
194 | }, | 200 | }, |
195 | { | 201 | { |
196 | .name = "McASP", | 202 | .name = "McASP", |
197 | .stream_name = "spdif", | 203 | .stream_name = "spdif", |
198 | .cpu_dai = &davinci_mcasp_dai[DAVINCI_MCASP_DIT_DAI], | 204 | .cpu_dai_name= "davinci-mcasp.1", |
199 | .codec_dai = &dit_stub_dai, | 205 | .codec_dai_name = "dit-hifi", |
206 | .codec_name = "spdif_dit", | ||
207 | .platform_name = "davinci-pcm-audio", | ||
200 | .ops = &evm_spdif_ops, | 208 | .ops = &evm_spdif_ops, |
201 | }, | 209 | }, |
202 | }; | 210 | }; |
203 | static struct snd_soc_dai_link da8xx_evm_dai = { | 211 | static struct snd_soc_dai_link da8xx_evm_dai = { |
204 | .name = "TLV320AIC3X", | 212 | .name = "TLV320AIC3X", |
205 | .stream_name = "AIC3X", | 213 | .stream_name = "AIC3X", |
206 | .cpu_dai = &davinci_mcasp_dai[DAVINCI_MCASP_I2S_DAI], | 214 | .cpu_dai_name= "davinci-mcasp.0", |
207 | .codec_dai = &aic3x_dai, | 215 | .codec_dai_name = "tlv320aic3x-hifi", |
216 | .codec_name = "tlv320aic3x-codec.0-001a", | ||
217 | .platform_name = "davinci-pcm-audio", | ||
208 | .init = evm_aic3x_init, | 218 | .init = evm_aic3x_init, |
209 | .ops = &evm_ops, | 219 | .ops = &evm_ops, |
210 | }; | 220 | }; |
@@ -212,7 +222,6 @@ static struct snd_soc_dai_link da8xx_evm_dai = { | |||
212 | /* davinci dm6446, dm355 evm audio machine driver */ | 222 | /* davinci dm6446, dm355 evm audio machine driver */ |
213 | static struct snd_soc_card snd_soc_card_evm = { | 223 | static struct snd_soc_card snd_soc_card_evm = { |
214 | .name = "DaVinci EVM", | 224 | .name = "DaVinci EVM", |
215 | .platform = &davinci_soc_platform, | ||
216 | .dai_link = &evm_dai, | 225 | .dai_link = &evm_dai, |
217 | .num_links = 1, | 226 | .num_links = 1, |
218 | }; | 227 | }; |
@@ -220,16 +229,13 @@ static struct snd_soc_card snd_soc_card_evm = { | |||
220 | /* davinci dm365 evm audio machine driver */ | 229 | /* davinci dm365 evm audio machine driver */ |
221 | static struct snd_soc_card dm365_snd_soc_card_evm = { | 230 | static struct snd_soc_card dm365_snd_soc_card_evm = { |
222 | .name = "DaVinci DM365 EVM", | 231 | .name = "DaVinci DM365 EVM", |
223 | .platform = &davinci_soc_platform, | ||
224 | .dai_link = &dm365_evm_dai, | 232 | .dai_link = &dm365_evm_dai, |
225 | .num_links = 1, | 233 | .num_links = 1, |
226 | }; | 234 | }; |
227 | 235 | ||
228 | |||
229 | /* davinci dm6467 evm audio machine driver */ | 236 | /* davinci dm6467 evm audio machine driver */ |
230 | static struct snd_soc_card dm6467_snd_soc_card_evm = { | 237 | static struct snd_soc_card dm6467_snd_soc_card_evm = { |
231 | .name = "DaVinci DM6467 EVM", | 238 | .name = "DaVinci DM6467 EVM", |
232 | .platform = &davinci_soc_platform, | ||
233 | .dai_link = dm6467_evm_dai, | 239 | .dai_link = dm6467_evm_dai, |
234 | .num_links = ARRAY_SIZE(dm6467_evm_dai), | 240 | .num_links = ARRAY_SIZE(dm6467_evm_dai), |
235 | }; | 241 | }; |
@@ -237,82 +243,40 @@ static struct snd_soc_card dm6467_snd_soc_card_evm = { | |||
237 | static struct snd_soc_card da830_snd_soc_card = { | 243 | static struct snd_soc_card da830_snd_soc_card = { |
238 | .name = "DA830/OMAP-L137 EVM", | 244 | .name = "DA830/OMAP-L137 EVM", |
239 | .dai_link = &da8xx_evm_dai, | 245 | .dai_link = &da8xx_evm_dai, |
240 | .platform = &davinci_soc_platform, | ||
241 | .num_links = 1, | 246 | .num_links = 1, |
242 | }; | 247 | }; |
243 | 248 | ||
244 | static struct snd_soc_card da850_snd_soc_card = { | 249 | static struct snd_soc_card da850_snd_soc_card = { |
245 | .name = "DA850/OMAP-L138 EVM", | 250 | .name = "DA850/OMAP-L138 EVM", |
246 | .dai_link = &da8xx_evm_dai, | 251 | .dai_link = &da8xx_evm_dai, |
247 | .platform = &davinci_soc_platform, | ||
248 | .num_links = 1, | 252 | .num_links = 1, |
249 | }; | 253 | }; |
250 | 254 | ||
251 | static struct aic3x_setup_data aic3x_setup; | ||
252 | |||
253 | /* evm audio subsystem */ | ||
254 | static struct snd_soc_device evm_snd_devdata = { | ||
255 | .card = &snd_soc_card_evm, | ||
256 | .codec_dev = &soc_codec_dev_aic3x, | ||
257 | .codec_data = &aic3x_setup, | ||
258 | }; | ||
259 | |||
260 | /* evm audio subsystem */ | ||
261 | static struct snd_soc_device dm365_evm_snd_devdata = { | ||
262 | .card = &dm365_snd_soc_card_evm, | ||
263 | #ifdef CONFIG_SND_DM365_AIC3X_CODEC | ||
264 | .codec_dev = &soc_codec_dev_aic3x, | ||
265 | .codec_data = &aic3x_setup, | ||
266 | #elif defined(CONFIG_SND_DM365_VOICE_CODEC) | ||
267 | .codec_dev = &soc_codec_dev_cq93vc, | ||
268 | #endif | ||
269 | }; | ||
270 | |||
271 | /* evm audio subsystem */ | ||
272 | static struct snd_soc_device dm6467_evm_snd_devdata = { | ||
273 | .card = &dm6467_snd_soc_card_evm, | ||
274 | .codec_dev = &soc_codec_dev_aic3x, | ||
275 | .codec_data = &aic3x_setup, | ||
276 | }; | ||
277 | |||
278 | /* evm audio subsystem */ | ||
279 | static struct snd_soc_device da830_evm_snd_devdata = { | ||
280 | .card = &da830_snd_soc_card, | ||
281 | .codec_dev = &soc_codec_dev_aic3x, | ||
282 | .codec_data = &aic3x_setup, | ||
283 | }; | ||
284 | |||
285 | static struct snd_soc_device da850_evm_snd_devdata = { | ||
286 | .card = &da850_snd_soc_card, | ||
287 | .codec_dev = &soc_codec_dev_aic3x, | ||
288 | .codec_data = &aic3x_setup, | ||
289 | }; | ||
290 | |||
291 | static struct platform_device *evm_snd_device; | 255 | static struct platform_device *evm_snd_device; |
292 | 256 | ||
293 | static int __init evm_init(void) | 257 | static int __init evm_init(void) |
294 | { | 258 | { |
295 | struct snd_soc_device *evm_snd_dev_data; | 259 | struct snd_soc_card *evm_snd_dev_data; |
296 | int index; | 260 | int index; |
297 | int ret; | 261 | int ret; |
298 | 262 | ||
299 | if (machine_is_davinci_evm()) { | 263 | if (machine_is_davinci_evm()) { |
300 | evm_snd_dev_data = &evm_snd_devdata; | 264 | evm_snd_dev_data = &snd_soc_card_evm; |
301 | index = 0; | 265 | index = 0; |
302 | } else if (machine_is_davinci_dm355_evm()) { | 266 | } else if (machine_is_davinci_dm355_evm()) { |
303 | evm_snd_dev_data = &evm_snd_devdata; | 267 | evm_snd_dev_data = &snd_soc_card_evm; |
304 | index = 1; | 268 | index = 1; |
305 | } else if (machine_is_davinci_dm365_evm()) { | 269 | } else if (machine_is_davinci_dm365_evm()) { |
306 | evm_snd_dev_data = &dm365_evm_snd_devdata; | 270 | evm_snd_dev_data = &dm365_snd_soc_card_evm; |
307 | index = 0; | 271 | index = 0; |
308 | } else if (machine_is_davinci_dm6467_evm()) { | 272 | } else if (machine_is_davinci_dm6467_evm()) { |
309 | evm_snd_dev_data = &dm6467_evm_snd_devdata; | 273 | evm_snd_dev_data = &dm6467_snd_soc_card_evm; |
310 | index = 0; | 274 | index = 0; |
311 | } else if (machine_is_davinci_da830_evm()) { | 275 | } else if (machine_is_davinci_da830_evm()) { |
312 | evm_snd_dev_data = &da830_evm_snd_devdata; | 276 | evm_snd_dev_data = &da830_snd_soc_card; |
313 | index = 1; | 277 | index = 1; |
314 | } else if (machine_is_davinci_da850_evm()) { | 278 | } else if (machine_is_davinci_da850_evm()) { |
315 | evm_snd_dev_data = &da850_evm_snd_devdata; | 279 | evm_snd_dev_data = &da850_snd_soc_card; |
316 | index = 0; | 280 | index = 0; |
317 | } else | 281 | } else |
318 | return -EINVAL; | 282 | return -EINVAL; |
@@ -322,7 +286,6 @@ static int __init evm_init(void) | |||
322 | return -ENOMEM; | 286 | return -ENOMEM; |
323 | 287 | ||
324 | platform_set_drvdata(evm_snd_device, evm_snd_dev_data); | 288 | platform_set_drvdata(evm_snd_device, evm_snd_dev_data); |
325 | evm_snd_dev_data->dev = &evm_snd_device->dev; | ||
326 | ret = platform_device_add(evm_snd_device); | 289 | ret = platform_device_add(evm_snd_device); |
327 | if (ret) | 290 | if (ret) |
328 | platform_device_put(evm_snd_device); | 291 | platform_device_put(evm_snd_device); |
diff --git a/sound/soc/davinci/davinci-i2s.c b/sound/soc/davinci/davinci-i2s.c index 9e8932abf158..9f8b6c556866 100644 --- a/sound/soc/davinci/davinci-i2s.c +++ b/sound/soc/davinci/davinci-i2s.c | |||
@@ -183,8 +183,7 @@ static void davinci_mcbsp_start(struct davinci_mcbsp_dev *dev, | |||
183 | struct snd_pcm_substream *substream) | 183 | struct snd_pcm_substream *substream) |
184 | { | 184 | { |
185 | struct snd_soc_pcm_runtime *rtd = substream->private_data; | 185 | struct snd_soc_pcm_runtime *rtd = substream->private_data; |
186 | struct snd_soc_device *socdev = rtd->socdev; | 186 | struct snd_soc_platform *platform = rtd->platform; |
187 | struct snd_soc_platform *platform = socdev->card->platform; | ||
188 | int playback = (substream->stream == SNDRV_PCM_STREAM_PLAYBACK); | 187 | int playback = (substream->stream == SNDRV_PCM_STREAM_PLAYBACK); |
189 | u32 spcr; | 188 | u32 spcr; |
190 | u32 mask = playback ? DAVINCI_MCBSP_SPCR_XRST : DAVINCI_MCBSP_SPCR_RRST; | 189 | u32 mask = playback ? DAVINCI_MCBSP_SPCR_XRST : DAVINCI_MCBSP_SPCR_RRST; |
@@ -205,8 +204,8 @@ static void davinci_mcbsp_start(struct davinci_mcbsp_dev *dev, | |||
205 | if (playback) { | 204 | if (playback) { |
206 | /* Stop the DMA to avoid data loss */ | 205 | /* Stop the DMA to avoid data loss */ |
207 | /* while the transmitter is out of reset to handle XSYNCERR */ | 206 | /* while the transmitter is out of reset to handle XSYNCERR */ |
208 | if (platform->pcm_ops->trigger) { | 207 | if (platform->driver->ops->trigger) { |
209 | int ret = platform->pcm_ops->trigger(substream, | 208 | int ret = platform->driver->ops->trigger(substream, |
210 | SNDRV_PCM_TRIGGER_STOP); | 209 | SNDRV_PCM_TRIGGER_STOP); |
211 | if (ret < 0) | 210 | if (ret < 0) |
212 | printk(KERN_DEBUG "Playback DMA stop failed\n"); | 211 | printk(KERN_DEBUG "Playback DMA stop failed\n"); |
@@ -227,8 +226,8 @@ static void davinci_mcbsp_start(struct davinci_mcbsp_dev *dev, | |||
227 | toggle_clock(dev, playback); | 226 | toggle_clock(dev, playback); |
228 | 227 | ||
229 | /* Restart the DMA */ | 228 | /* Restart the DMA */ |
230 | if (platform->pcm_ops->trigger) { | 229 | if (platform->driver->ops->trigger) { |
231 | int ret = platform->pcm_ops->trigger(substream, | 230 | int ret = platform->driver->ops->trigger(substream, |
232 | SNDRV_PCM_TRIGGER_START); | 231 | SNDRV_PCM_TRIGGER_START); |
233 | if (ret < 0) | 232 | if (ret < 0) |
234 | printk(KERN_DEBUG "Playback DMA start failed\n"); | 233 | printk(KERN_DEBUG "Playback DMA start failed\n"); |
@@ -263,7 +262,7 @@ static void davinci_mcbsp_stop(struct davinci_mcbsp_dev *dev, int playback) | |||
263 | static int davinci_i2s_set_dai_fmt(struct snd_soc_dai *cpu_dai, | 262 | static int davinci_i2s_set_dai_fmt(struct snd_soc_dai *cpu_dai, |
264 | unsigned int fmt) | 263 | unsigned int fmt) |
265 | { | 264 | { |
266 | struct davinci_mcbsp_dev *dev = cpu_dai->private_data; | 265 | struct davinci_mcbsp_dev *dev = snd_soc_dai_get_drvdata(cpu_dai); |
267 | unsigned int pcr; | 266 | unsigned int pcr; |
268 | unsigned int srgr; | 267 | unsigned int srgr; |
269 | /* Attention srgr is updated by hw_params! */ | 268 | /* Attention srgr is updated by hw_params! */ |
@@ -404,7 +403,7 @@ static int davinci_i2s_set_dai_fmt(struct snd_soc_dai *cpu_dai, | |||
404 | static int davinci_i2s_dai_set_clkdiv(struct snd_soc_dai *cpu_dai, | 403 | static int davinci_i2s_dai_set_clkdiv(struct snd_soc_dai *cpu_dai, |
405 | int div_id, int div) | 404 | int div_id, int div) |
406 | { | 405 | { |
407 | struct davinci_mcbsp_dev *dev = cpu_dai->private_data; | 406 | struct davinci_mcbsp_dev *dev = snd_soc_dai_get_drvdata(cpu_dai); |
408 | 407 | ||
409 | if (div_id != DAVINCI_MCBSP_CLKGDV) | 408 | if (div_id != DAVINCI_MCBSP_CLKGDV) |
410 | return -ENODEV; | 409 | return -ENODEV; |
@@ -417,7 +416,7 @@ static int davinci_i2s_hw_params(struct snd_pcm_substream *substream, | |||
417 | struct snd_pcm_hw_params *params, | 416 | struct snd_pcm_hw_params *params, |
418 | struct snd_soc_dai *dai) | 417 | struct snd_soc_dai *dai) |
419 | { | 418 | { |
420 | struct davinci_mcbsp_dev *dev = dai->private_data; | 419 | struct davinci_mcbsp_dev *dev = snd_soc_dai_get_drvdata(dai); |
421 | struct davinci_pcm_dma_params *dma_params = | 420 | struct davinci_pcm_dma_params *dma_params = |
422 | &dev->dma_params[substream->stream]; | 421 | &dev->dma_params[substream->stream]; |
423 | struct snd_interval *i = NULL; | 422 | struct snd_interval *i = NULL; |
@@ -427,6 +426,9 @@ static int davinci_i2s_hw_params(struct snd_pcm_substream *substream, | |||
427 | snd_pcm_format_t fmt; | 426 | snd_pcm_format_t fmt; |
428 | unsigned element_cnt = 1; | 427 | unsigned element_cnt = 1; |
429 | 428 | ||
429 | dai->capture_dma_data = dev->dma_params; | ||
430 | dai->playback_dma_data = dev->dma_params; | ||
431 | |||
430 | /* general line settings */ | 432 | /* general line settings */ |
431 | spcr = davinci_mcbsp_read_reg(dev, DAVINCI_MCBSP_SPCR_REG); | 433 | spcr = davinci_mcbsp_read_reg(dev, DAVINCI_MCBSP_SPCR_REG); |
432 | if (substream->stream == SNDRV_PCM_STREAM_CAPTURE) { | 434 | if (substream->stream == SNDRV_PCM_STREAM_CAPTURE) { |
@@ -569,7 +571,7 @@ static int davinci_i2s_hw_params(struct snd_pcm_substream *substream, | |||
569 | static int davinci_i2s_prepare(struct snd_pcm_substream *substream, | 571 | static int davinci_i2s_prepare(struct snd_pcm_substream *substream, |
570 | struct snd_soc_dai *dai) | 572 | struct snd_soc_dai *dai) |
571 | { | 573 | { |
572 | struct davinci_mcbsp_dev *dev = dai->private_data; | 574 | struct davinci_mcbsp_dev *dev = snd_soc_dai_get_drvdata(dai); |
573 | int playback = (substream->stream == SNDRV_PCM_STREAM_PLAYBACK); | 575 | int playback = (substream->stream == SNDRV_PCM_STREAM_PLAYBACK); |
574 | davinci_mcbsp_stop(dev, playback); | 576 | davinci_mcbsp_stop(dev, playback); |
575 | if ((dev->pcr & DAVINCI_MCBSP_PCR_FSXM) == 0) { | 577 | if ((dev->pcr & DAVINCI_MCBSP_PCR_FSXM) == 0) { |
@@ -582,7 +584,7 @@ static int davinci_i2s_prepare(struct snd_pcm_substream *substream, | |||
582 | static int davinci_i2s_trigger(struct snd_pcm_substream *substream, int cmd, | 584 | static int davinci_i2s_trigger(struct snd_pcm_substream *substream, int cmd, |
583 | struct snd_soc_dai *dai) | 585 | struct snd_soc_dai *dai) |
584 | { | 586 | { |
585 | struct davinci_mcbsp_dev *dev = dai->private_data; | 587 | struct davinci_mcbsp_dev *dev = snd_soc_dai_get_drvdata(dai); |
586 | int ret = 0; | 588 | int ret = 0; |
587 | int playback = (substream->stream == SNDRV_PCM_STREAM_PLAYBACK); | 589 | int playback = (substream->stream == SNDRV_PCM_STREAM_PLAYBACK); |
588 | if ((dev->pcr & DAVINCI_MCBSP_PCR_FSXM) == 0) | 590 | if ((dev->pcr & DAVINCI_MCBSP_PCR_FSXM) == 0) |
@@ -608,7 +610,7 @@ static int davinci_i2s_trigger(struct snd_pcm_substream *substream, int cmd, | |||
608 | static void davinci_i2s_shutdown(struct snd_pcm_substream *substream, | 610 | static void davinci_i2s_shutdown(struct snd_pcm_substream *substream, |
609 | struct snd_soc_dai *dai) | 611 | struct snd_soc_dai *dai) |
610 | { | 612 | { |
611 | struct davinci_mcbsp_dev *dev = dai->private_data; | 613 | struct davinci_mcbsp_dev *dev = snd_soc_dai_get_drvdata(dai); |
612 | int playback = (substream->stream == SNDRV_PCM_STREAM_PLAYBACK); | 614 | int playback = (substream->stream == SNDRV_PCM_STREAM_PLAYBACK); |
613 | davinci_mcbsp_stop(dev, playback); | 615 | davinci_mcbsp_stop(dev, playback); |
614 | } | 616 | } |
@@ -625,9 +627,7 @@ static struct snd_soc_dai_ops davinci_i2s_dai_ops = { | |||
625 | 627 | ||
626 | }; | 628 | }; |
627 | 629 | ||
628 | struct snd_soc_dai davinci_i2s_dai = { | 630 | static struct snd_soc_dai_driver davinci_i2s_dai = { |
629 | .name = "davinci-i2s", | ||
630 | .id = 0, | ||
631 | .playback = { | 631 | .playback = { |
632 | .channels_min = 2, | 632 | .channels_min = 2, |
633 | .channels_max = 2, | 633 | .channels_max = 2, |
@@ -641,7 +641,6 @@ struct snd_soc_dai davinci_i2s_dai = { | |||
641 | .ops = &davinci_i2s_dai_ops, | 641 | .ops = &davinci_i2s_dai_ops, |
642 | 642 | ||
643 | }; | 643 | }; |
644 | EXPORT_SYMBOL_GPL(davinci_i2s_dai); | ||
645 | 644 | ||
646 | static int davinci_i2s_probe(struct platform_device *pdev) | 645 | static int davinci_i2s_probe(struct platform_device *pdev) |
647 | { | 646 | { |
@@ -720,10 +719,9 @@ static int davinci_i2s_probe(struct platform_device *pdev) | |||
720 | dev->dma_params[SNDRV_PCM_STREAM_CAPTURE].channel = res->start; | 719 | dev->dma_params[SNDRV_PCM_STREAM_CAPTURE].channel = res->start; |
721 | dev->dev = &pdev->dev; | 720 | dev->dev = &pdev->dev; |
722 | 721 | ||
723 | davinci_i2s_dai.private_data = dev; | 722 | dev_set_drvdata(&pdev->dev, dev); |
724 | davinci_i2s_dai.capture.dma_data = dev->dma_params; | 723 | |
725 | davinci_i2s_dai.playback.dma_data = dev->dma_params; | 724 | ret = snd_soc_register_dai(&pdev->dev, &davinci_i2s_dai); |
726 | ret = snd_soc_register_dai(&davinci_i2s_dai); | ||
727 | if (ret != 0) | 725 | if (ret != 0) |
728 | goto err_free_mem; | 726 | goto err_free_mem; |
729 | 727 | ||
@@ -739,10 +737,10 @@ err_release_region: | |||
739 | 737 | ||
740 | static int davinci_i2s_remove(struct platform_device *pdev) | 738 | static int davinci_i2s_remove(struct platform_device *pdev) |
741 | { | 739 | { |
742 | struct davinci_mcbsp_dev *dev = davinci_i2s_dai.private_data; | 740 | struct davinci_mcbsp_dev *dev = dev_get_drvdata(&pdev->dev); |
743 | struct resource *mem; | 741 | struct resource *mem; |
744 | 742 | ||
745 | snd_soc_unregister_dai(&davinci_i2s_dai); | 743 | snd_soc_unregister_dai(&pdev->dev); |
746 | clk_disable(dev->clk); | 744 | clk_disable(dev->clk); |
747 | clk_put(dev->clk); | 745 | clk_put(dev->clk); |
748 | dev->clk = NULL; | 746 | dev->clk = NULL; |
@@ -757,7 +755,7 @@ static struct platform_driver davinci_mcbsp_driver = { | |||
757 | .probe = davinci_i2s_probe, | 755 | .probe = davinci_i2s_probe, |
758 | .remove = davinci_i2s_remove, | 756 | .remove = davinci_i2s_remove, |
759 | .driver = { | 757 | .driver = { |
760 | .name = "davinci-asp", | 758 | .name = "davinci-i2s", |
761 | .owner = THIS_MODULE, | 759 | .owner = THIS_MODULE, |
762 | }, | 760 | }, |
763 | }; | 761 | }; |
diff --git a/sound/soc/davinci/davinci-i2s.h b/sound/soc/davinci/davinci-i2s.h index 0b1e77b8c279..48dac3e2521a 100644 --- a/sound/soc/davinci/davinci-i2s.h +++ b/sound/soc/davinci/davinci-i2s.h | |||
@@ -17,6 +17,4 @@ enum davinci_mcbsp_div { | |||
17 | DAVINCI_MCBSP_CLKGDV, /* Sample rate generator divider */ | 17 | DAVINCI_MCBSP_CLKGDV, /* Sample rate generator divider */ |
18 | }; | 18 | }; |
19 | 19 | ||
20 | extern struct snd_soc_dai davinci_i2s_dai; | ||
21 | |||
22 | #endif | 20 | #endif |
diff --git a/sound/soc/davinci/davinci-mcasp.c b/sound/soc/davinci/davinci-mcasp.c index b24720894af6..c8e97dcbfff4 100644 --- a/sound/soc/davinci/davinci-mcasp.c +++ b/sound/soc/davinci/davinci-mcasp.c | |||
@@ -422,7 +422,7 @@ static void davinci_mcasp_stop(struct davinci_audio_dev *dev, int stream) | |||
422 | static int davinci_mcasp_set_dai_fmt(struct snd_soc_dai *cpu_dai, | 422 | static int davinci_mcasp_set_dai_fmt(struct snd_soc_dai *cpu_dai, |
423 | unsigned int fmt) | 423 | unsigned int fmt) |
424 | { | 424 | { |
425 | struct davinci_audio_dev *dev = cpu_dai->private_data; | 425 | struct davinci_audio_dev *dev = snd_soc_dai_get_drvdata(cpu_dai); |
426 | void __iomem *base = dev->base; | 426 | void __iomem *base = dev->base; |
427 | 427 | ||
428 | switch (fmt & SND_SOC_DAIFMT_MASTER_MASK) { | 428 | switch (fmt & SND_SOC_DAIFMT_MASTER_MASK) { |
@@ -709,12 +709,15 @@ static int davinci_mcasp_hw_params(struct snd_pcm_substream *substream, | |||
709 | struct snd_pcm_hw_params *params, | 709 | struct snd_pcm_hw_params *params, |
710 | struct snd_soc_dai *cpu_dai) | 710 | struct snd_soc_dai *cpu_dai) |
711 | { | 711 | { |
712 | struct davinci_audio_dev *dev = cpu_dai->private_data; | 712 | struct davinci_audio_dev *dev = snd_soc_dai_get_drvdata(cpu_dai); |
713 | struct davinci_pcm_dma_params *dma_params = | 713 | struct davinci_pcm_dma_params *dma_params = |
714 | &dev->dma_params[substream->stream]; | 714 | &dev->dma_params[substream->stream]; |
715 | int word_length; | 715 | int word_length; |
716 | u8 fifo_level; | 716 | u8 fifo_level; |
717 | 717 | ||
718 | cpu_dai->capture_dma_data = dev->dma_params; | ||
719 | cpu_dai->playback_dma_data = dev->dma_params; | ||
720 | |||
718 | davinci_hw_common_param(dev, substream->stream); | 721 | davinci_hw_common_param(dev, substream->stream); |
719 | if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) | 722 | if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) |
720 | fifo_level = dev->txnumevt; | 723 | fifo_level = dev->txnumevt; |
@@ -761,8 +764,7 @@ static int davinci_mcasp_hw_params(struct snd_pcm_substream *substream, | |||
761 | static int davinci_mcasp_trigger(struct snd_pcm_substream *substream, | 764 | static int davinci_mcasp_trigger(struct snd_pcm_substream *substream, |
762 | int cmd, struct snd_soc_dai *cpu_dai) | 765 | int cmd, struct snd_soc_dai *cpu_dai) |
763 | { | 766 | { |
764 | struct snd_soc_pcm_runtime *rtd = substream->private_data; | 767 | struct davinci_audio_dev *dev = snd_soc_dai_get_drvdata(cpu_dai); |
765 | struct davinci_audio_dev *dev = rtd->dai->cpu_dai->private_data; | ||
766 | int ret = 0; | 768 | int ret = 0; |
767 | 769 | ||
768 | switch (cmd) { | 770 | switch (cmd) { |
@@ -804,10 +806,9 @@ static struct snd_soc_dai_ops davinci_mcasp_dai_ops = { | |||
804 | 806 | ||
805 | }; | 807 | }; |
806 | 808 | ||
807 | struct snd_soc_dai davinci_mcasp_dai[] = { | 809 | static struct snd_soc_dai_driver davinci_mcasp_dai[] = { |
808 | { | 810 | { |
809 | .name = "davinci-i2s", | 811 | .name = "davinci-mcasp.0", |
810 | .id = 0, | ||
811 | .playback = { | 812 | .playback = { |
812 | .channels_min = 2, | 813 | .channels_min = 2, |
813 | .channels_max = 2, | 814 | .channels_max = 2, |
@@ -828,8 +829,7 @@ struct snd_soc_dai davinci_mcasp_dai[] = { | |||
828 | 829 | ||
829 | }, | 830 | }, |
830 | { | 831 | { |
831 | .name = "davinci-dit", | 832 | "davinci-mcasp.1", |
832 | .id = 1, | ||
833 | .playback = { | 833 | .playback = { |
834 | .channels_min = 1, | 834 | .channels_min = 1, |
835 | .channels_max = 384, | 835 | .channels_max = 384, |
@@ -840,7 +840,6 @@ struct snd_soc_dai davinci_mcasp_dai[] = { | |||
840 | }, | 840 | }, |
841 | 841 | ||
842 | }; | 842 | }; |
843 | EXPORT_SYMBOL_GPL(davinci_mcasp_dai); | ||
844 | 843 | ||
845 | static int davinci_mcasp_probe(struct platform_device *pdev) | 844 | static int davinci_mcasp_probe(struct platform_device *pdev) |
846 | { | 845 | { |
@@ -917,11 +916,8 @@ static int davinci_mcasp_probe(struct platform_device *pdev) | |||
917 | } | 916 | } |
918 | 917 | ||
919 | dma_data->channel = res->start; | 918 | dma_data->channel = res->start; |
920 | davinci_mcasp_dai[pdata->op_mode].private_data = dev; | 919 | dev_set_drvdata(&pdev->dev, dev); |
921 | davinci_mcasp_dai[pdata->op_mode].capture.dma_data = dev->dma_params; | 920 | ret = snd_soc_register_dai(&pdev->dev, &davinci_mcasp_dai[pdata->op_mode]); |
922 | davinci_mcasp_dai[pdata->op_mode].playback.dma_data = dev->dma_params; | ||
923 | davinci_mcasp_dai[pdata->op_mode].dev = &pdev->dev; | ||
924 | ret = snd_soc_register_dai(&davinci_mcasp_dai[pdata->op_mode]); | ||
925 | 921 | ||
926 | if (ret != 0) | 922 | if (ret != 0) |
927 | goto err_release_region; | 923 | goto err_release_region; |
@@ -937,12 +933,10 @@ err_release_data: | |||
937 | 933 | ||
938 | static int davinci_mcasp_remove(struct platform_device *pdev) | 934 | static int davinci_mcasp_remove(struct platform_device *pdev) |
939 | { | 935 | { |
940 | struct snd_platform_data *pdata = pdev->dev.platform_data; | 936 | struct davinci_audio_dev *dev = dev_get_drvdata(&pdev->dev); |
941 | struct davinci_audio_dev *dev; | ||
942 | struct resource *mem; | 937 | struct resource *mem; |
943 | 938 | ||
944 | snd_soc_unregister_dai(&davinci_mcasp_dai[pdata->op_mode]); | 939 | snd_soc_unregister_dai(&pdev->dev); |
945 | dev = davinci_mcasp_dai[pdata->op_mode].private_data; | ||
946 | clk_disable(dev->clk); | 940 | clk_disable(dev->clk); |
947 | clk_put(dev->clk); | 941 | clk_put(dev->clk); |
948 | dev->clk = NULL; | 942 | dev->clk = NULL; |
diff --git a/sound/soc/davinci/davinci-mcasp.h b/sound/soc/davinci/davinci-mcasp.h index e755b5121ec7..4681acc63606 100644 --- a/sound/soc/davinci/davinci-mcasp.h +++ b/sound/soc/davinci/davinci-mcasp.h | |||
@@ -22,8 +22,6 @@ | |||
22 | #include <mach/asp.h> | 22 | #include <mach/asp.h> |
23 | #include "davinci-pcm.h" | 23 | #include "davinci-pcm.h" |
24 | 24 | ||
25 | extern struct snd_soc_dai davinci_mcasp_dai[]; | ||
26 | |||
27 | #define DAVINCI_MCASP_RATES SNDRV_PCM_RATE_8000_96000 | 25 | #define DAVINCI_MCASP_RATES SNDRV_PCM_RATE_8000_96000 |
28 | #define DAVINCI_MCASP_I2S_DAI 0 | 26 | #define DAVINCI_MCASP_I2S_DAI 0 |
29 | #define DAVINCI_MCASP_DIT_DAI 1 | 27 | #define DAVINCI_MCASP_DIT_DAI 1 |
diff --git a/sound/soc/davinci/davinci-pcm.c b/sound/soc/davinci/davinci-pcm.c index a7124116d2e0..9d35b8c1a624 100644 --- a/sound/soc/davinci/davinci-pcm.c +++ b/sound/soc/davinci/davinci-pcm.c | |||
@@ -653,7 +653,7 @@ static int davinci_pcm_open(struct snd_pcm_substream *substream) | |||
653 | struct davinci_pcm_dma_params *pa; | 653 | struct davinci_pcm_dma_params *pa; |
654 | struct davinci_pcm_dma_params *params; | 654 | struct davinci_pcm_dma_params *params; |
655 | 655 | ||
656 | pa = snd_soc_dai_get_dma_data(rtd->dai->cpu_dai, substream); | 656 | pa = snd_soc_dai_get_dma_data(rtd->cpu_dai, substream); |
657 | if (!pa) | 657 | if (!pa) |
658 | return -ENODEV; | 658 | return -ENODEV; |
659 | params = &pa[substream->stream]; | 659 | params = &pa[substream->stream]; |
@@ -821,7 +821,7 @@ static int davinci_pcm_new(struct snd_card *card, | |||
821 | if (!card->dev->coherent_dma_mask) | 821 | if (!card->dev->coherent_dma_mask) |
822 | card->dev->coherent_dma_mask = 0xffffffff; | 822 | card->dev->coherent_dma_mask = 0xffffffff; |
823 | 823 | ||
824 | if (dai->playback.channels_min) { | 824 | if (dai->driver->playback.channels_min) { |
825 | ret = davinci_pcm_preallocate_dma_buffer(pcm, | 825 | ret = davinci_pcm_preallocate_dma_buffer(pcm, |
826 | SNDRV_PCM_STREAM_PLAYBACK, | 826 | SNDRV_PCM_STREAM_PLAYBACK, |
827 | pcm_hardware_playback.buffer_bytes_max); | 827 | pcm_hardware_playback.buffer_bytes_max); |
@@ -829,7 +829,7 @@ static int davinci_pcm_new(struct snd_card *card, | |||
829 | return ret; | 829 | return ret; |
830 | } | 830 | } |
831 | 831 | ||
832 | if (dai->capture.channels_min) { | 832 | if (dai->driver->capture.channels_min) { |
833 | ret = davinci_pcm_preallocate_dma_buffer(pcm, | 833 | ret = davinci_pcm_preallocate_dma_buffer(pcm, |
834 | SNDRV_PCM_STREAM_CAPTURE, | 834 | SNDRV_PCM_STREAM_CAPTURE, |
835 | pcm_hardware_capture.buffer_bytes_max); | 835 | pcm_hardware_capture.buffer_bytes_max); |
@@ -840,25 +840,44 @@ static int davinci_pcm_new(struct snd_card *card, | |||
840 | return 0; | 840 | return 0; |
841 | } | 841 | } |
842 | 842 | ||
843 | struct snd_soc_platform davinci_soc_platform = { | 843 | static struct snd_soc_platform_driver davinci_soc_platform = { |
844 | .name = "davinci-audio", | 844 | .ops = &davinci_pcm_ops, |
845 | .pcm_ops = &davinci_pcm_ops, | ||
846 | .pcm_new = davinci_pcm_new, | 845 | .pcm_new = davinci_pcm_new, |
847 | .pcm_free = davinci_pcm_free, | 846 | .pcm_free = davinci_pcm_free, |
848 | }; | 847 | }; |
849 | EXPORT_SYMBOL_GPL(davinci_soc_platform); | ||
850 | 848 | ||
851 | static int __init davinci_soc_platform_init(void) | 849 | static int __devinit davinci_soc_platform_probe(struct platform_device *pdev) |
852 | { | 850 | { |
853 | return snd_soc_register_platform(&davinci_soc_platform); | 851 | return snd_soc_register_platform(&pdev->dev, &davinci_soc_platform); |
854 | } | 852 | } |
855 | module_init(davinci_soc_platform_init); | ||
856 | 853 | ||
857 | static void __exit davinci_soc_platform_exit(void) | 854 | static int __devexit davinci_soc_platform_remove(struct platform_device *pdev) |
858 | { | 855 | { |
859 | snd_soc_unregister_platform(&davinci_soc_platform); | 856 | snd_soc_unregister_platform(&pdev->dev); |
857 | return 0; | ||
858 | } | ||
859 | |||
860 | static struct platform_driver davinci_pcm_driver = { | ||
861 | .driver = { | ||
862 | .name = "davinci-pcm-audio", | ||
863 | .owner = THIS_MODULE, | ||
864 | }, | ||
865 | |||
866 | .probe = davinci_soc_platform_probe, | ||
867 | .remove = __devexit_p(davinci_soc_platform_remove), | ||
868 | }; | ||
869 | |||
870 | static int __init snd_davinci_pcm_init(void) | ||
871 | { | ||
872 | return platform_driver_register(&davinci_pcm_driver); | ||
873 | } | ||
874 | module_init(snd_davinci_pcm_init); | ||
875 | |||
876 | static void __exit snd_davinci_pcm_exit(void) | ||
877 | { | ||
878 | platform_driver_unregister(&davinci_pcm_driver); | ||
860 | } | 879 | } |
861 | module_exit(davinci_soc_platform_exit); | 880 | module_exit(snd_davinci_pcm_exit); |
862 | 881 | ||
863 | MODULE_AUTHOR("Vladimir Barinov"); | 882 | MODULE_AUTHOR("Vladimir Barinov"); |
864 | MODULE_DESCRIPTION("TI DAVINCI PCM DMA module"); | 883 | MODULE_DESCRIPTION("TI DAVINCI PCM DMA module"); |
diff --git a/sound/soc/davinci/davinci-pcm.h b/sound/soc/davinci/davinci-pcm.h index b799a02333d8..c0d6c9be4b4d 100644 --- a/sound/soc/davinci/davinci-pcm.h +++ b/sound/soc/davinci/davinci-pcm.h | |||
@@ -28,7 +28,4 @@ struct davinci_pcm_dma_params { | |||
28 | unsigned int fifo_level; | 28 | unsigned int fifo_level; |
29 | }; | 29 | }; |
30 | 30 | ||
31 | |||
32 | extern struct snd_soc_platform davinci_soc_platform; | ||
33 | |||
34 | #endif | 31 | #endif |
diff --git a/sound/soc/davinci/davinci-sffsdr.c b/sound/soc/davinci/davinci-sffsdr.c index 40eccfe9e358..997c54f3693c 100644 --- a/sound/soc/davinci/davinci-sffsdr.c +++ b/sound/soc/davinci/davinci-sffsdr.c | |||
@@ -29,7 +29,6 @@ | |||
29 | #include <asm/plat-sffsdr/sffsdr-fpga.h> | 29 | #include <asm/plat-sffsdr/sffsdr-fpga.h> |
30 | #endif | 30 | #endif |
31 | 31 | ||
32 | #include <mach/mcbsp.h> | ||
33 | #include <mach/edma.h> | 32 | #include <mach/edma.h> |
34 | 33 | ||
35 | #include "../codecs/pcm3008.h" | 34 | #include "../codecs/pcm3008.h" |
@@ -48,7 +47,7 @@ static int sffsdr_hw_params(struct snd_pcm_substream *substream, | |||
48 | struct snd_pcm_hw_params *params) | 47 | struct snd_pcm_hw_params *params) |
49 | { | 48 | { |
50 | struct snd_soc_pcm_runtime *rtd = substream->private_data; | 49 | struct snd_soc_pcm_runtime *rtd = substream->private_data; |
51 | struct snd_soc_dai *cpu_dai = rtd->dai->cpu_dai; | 50 | struct snd_soc_dai *cpu_dai = rtd->cpu_dai; |
52 | int fs; | 51 | int fs; |
53 | int ret = 0; | 52 | int ret = 0; |
54 | 53 | ||
@@ -85,15 +84,16 @@ static struct snd_soc_ops sffsdr_ops = { | |||
85 | static struct snd_soc_dai_link sffsdr_dai = { | 84 | static struct snd_soc_dai_link sffsdr_dai = { |
86 | .name = "PCM3008", /* Codec name */ | 85 | .name = "PCM3008", /* Codec name */ |
87 | .stream_name = "PCM3008 HiFi", | 86 | .stream_name = "PCM3008 HiFi", |
88 | .cpu_dai = &davinci_i2s_dai, | 87 | .cpu_dai_name = "davinci-asp.0", |
89 | .codec_dai = &pcm3008_dai, | 88 | .codec_dai_name = "pcm3008-hifi", |
89 | .codec_name = "pcm3008-codec", | ||
90 | .platform_name = "davinci-pcm-audio", | ||
90 | .ops = &sffsdr_ops, | 91 | .ops = &sffsdr_ops, |
91 | }; | 92 | }; |
92 | 93 | ||
93 | /* davinci-sffsdr audio machine driver */ | 94 | /* davinci-sffsdr audio machine driver */ |
94 | static struct snd_soc_card snd_soc_sffsdr = { | 95 | static struct snd_soc_card snd_soc_sffsdr = { |
95 | .name = "DaVinci SFFSDR", | 96 | .name = "DaVinci SFFSDR", |
96 | .platform = &davinci_soc_platform, | ||
97 | .dai_link = &sffsdr_dai, | 97 | .dai_link = &sffsdr_dai, |
98 | .num_links = 1, | 98 | .num_links = 1, |
99 | }; | 99 | }; |
@@ -106,11 +106,12 @@ static struct pcm3008_setup_data sffsdr_pcm3008_setup = { | |||
106 | .pdda_pin = GPIO(38), | 106 | .pdda_pin = GPIO(38), |
107 | }; | 107 | }; |
108 | 108 | ||
109 | /* sffsdr audio subsystem */ | 109 | struct platform_device pcm3008_codec = { |
110 | static struct snd_soc_device sffsdr_snd_devdata = { | 110 | .name = "pcm3008-codec", |
111 | .card = &snd_soc_sffsdr, | 111 | .id = 0, |
112 | .codec_dev = &soc_codec_dev_pcm3008, | 112 | .dev = { |
113 | .codec_data = &sffsdr_pcm3008_setup, | 113 | .platform_data = &sffsdr_pcm3008_setup, |
114 | }, | ||
114 | }; | 115 | }; |
115 | 116 | ||
116 | static struct resource sffsdr_snd_resources[] = { | 117 | static struct resource sffsdr_snd_resources[] = { |
@@ -135,14 +136,15 @@ static int __init sffsdr_init(void) | |||
135 | if (!machine_is_sffsdr()) | 136 | if (!machine_is_sffsdr()) |
136 | return -EINVAL; | 137 | return -EINVAL; |
137 | 138 | ||
139 | platform_device_register(&pcm3008_codec); | ||
140 | |||
138 | sffsdr_snd_device = platform_device_alloc("soc-audio", 0); | 141 | sffsdr_snd_device = platform_device_alloc("soc-audio", 0); |
139 | if (!sffsdr_snd_device) { | 142 | if (!sffsdr_snd_device) { |
140 | printk(KERN_ERR "platform device allocation failed\n"); | 143 | printk(KERN_ERR "platform device allocation failed\n"); |
141 | return -ENOMEM; | 144 | return -ENOMEM; |
142 | } | 145 | } |
143 | 146 | ||
144 | platform_set_drvdata(sffsdr_snd_device, &sffsdr_snd_devdata); | 147 | platform_set_drvdata(sffsdr_snd_device, &snd_soc_sffsdr); |
145 | sffsdr_snd_devdata.dev = &sffsdr_snd_device->dev; | ||
146 | platform_device_add_data(sffsdr_snd_device, &sffsdr_snd_data, | 148 | platform_device_add_data(sffsdr_snd_device, &sffsdr_snd_data, |
147 | sizeof(sffsdr_snd_data)); | 149 | sizeof(sffsdr_snd_data)); |
148 | 150 | ||
@@ -168,6 +170,7 @@ error: | |||
168 | static void __exit sffsdr_exit(void) | 170 | static void __exit sffsdr_exit(void) |
169 | { | 171 | { |
170 | platform_device_unregister(sffsdr_snd_device); | 172 | platform_device_unregister(sffsdr_snd_device); |
173 | platform_device_unregister(&pcm3008_codec); | ||
171 | } | 174 | } |
172 | 175 | ||
173 | module_init(sffsdr_init); | 176 | module_init(sffsdr_init); |
diff --git a/sound/soc/davinci/davinci-vcif.c b/sound/soc/davinci/davinci-vcif.c index 48678533da7a..ea232f6a2c21 100644 --- a/sound/soc/davinci/davinci-vcif.c +++ b/sound/soc/davinci/davinci-vcif.c | |||
@@ -36,7 +36,6 @@ | |||
36 | 36 | ||
37 | #include "davinci-pcm.h" | 37 | #include "davinci-pcm.h" |
38 | #include "davinci-i2s.h" | 38 | #include "davinci-i2s.h" |
39 | #include "davinci-vcif.h" | ||
40 | 39 | ||
41 | #define MOD_REG_BIT(val, mask, set) do { \ | 40 | #define MOD_REG_BIT(val, mask, set) do { \ |
42 | if (set) { \ | 41 | if (set) { \ |
@@ -55,7 +54,7 @@ static void davinci_vcif_start(struct snd_pcm_substream *substream) | |||
55 | { | 54 | { |
56 | struct snd_soc_pcm_runtime *rtd = substream->private_data; | 55 | struct snd_soc_pcm_runtime *rtd = substream->private_data; |
57 | struct davinci_vcif_dev *davinci_vcif_dev = | 56 | struct davinci_vcif_dev *davinci_vcif_dev = |
58 | rtd->dai->cpu_dai->private_data; | 57 | snd_soc_dai_get_drvdata(rtd->cpu_dai); |
59 | struct davinci_vc *davinci_vc = davinci_vcif_dev->davinci_vc; | 58 | struct davinci_vc *davinci_vc = davinci_vcif_dev->davinci_vc; |
60 | u32 w; | 59 | u32 w; |
61 | 60 | ||
@@ -74,7 +73,7 @@ static void davinci_vcif_stop(struct snd_pcm_substream *substream) | |||
74 | { | 73 | { |
75 | struct snd_soc_pcm_runtime *rtd = substream->private_data; | 74 | struct snd_soc_pcm_runtime *rtd = substream->private_data; |
76 | struct davinci_vcif_dev *davinci_vcif_dev = | 75 | struct davinci_vcif_dev *davinci_vcif_dev = |
77 | rtd->dai->cpu_dai->private_data; | 76 | snd_soc_dai_get_drvdata(rtd->cpu_dai); |
78 | struct davinci_vc *davinci_vc = davinci_vcif_dev->davinci_vc; | 77 | struct davinci_vc *davinci_vc = davinci_vcif_dev->davinci_vc; |
79 | u32 w; | 78 | u32 w; |
80 | 79 | ||
@@ -92,12 +91,15 @@ static int davinci_vcif_hw_params(struct snd_pcm_substream *substream, | |||
92 | struct snd_pcm_hw_params *params, | 91 | struct snd_pcm_hw_params *params, |
93 | struct snd_soc_dai *dai) | 92 | struct snd_soc_dai *dai) |
94 | { | 93 | { |
95 | struct davinci_vcif_dev *davinci_vcif_dev = dai->private_data; | 94 | struct davinci_vcif_dev *davinci_vcif_dev = snd_soc_dai_get_drvdata(dai); |
96 | struct davinci_vc *davinci_vc = davinci_vcif_dev->davinci_vc; | 95 | struct davinci_vc *davinci_vc = davinci_vcif_dev->davinci_vc; |
97 | struct davinci_pcm_dma_params *dma_params = | 96 | struct davinci_pcm_dma_params *dma_params = |
98 | &davinci_vcif_dev->dma_params[substream->stream]; | 97 | &davinci_vcif_dev->dma_params[substream->stream]; |
99 | u32 w; | 98 | u32 w; |
100 | 99 | ||
100 | dai->capture_dma_data = davinci_vcif_dev->dma_params; | ||
101 | dai->playback_dma_data = davinci_vcif_dev->dma_params; | ||
102 | |||
101 | /* Restart the codec before setup */ | 103 | /* Restart the codec before setup */ |
102 | davinci_vcif_stop(substream); | 104 | davinci_vcif_stop(substream); |
103 | davinci_vcif_start(substream); | 105 | davinci_vcif_start(substream); |
@@ -179,8 +181,7 @@ static struct snd_soc_dai_ops davinci_vcif_dai_ops = { | |||
179 | .hw_params = davinci_vcif_hw_params, | 181 | .hw_params = davinci_vcif_hw_params, |
180 | }; | 182 | }; |
181 | 183 | ||
182 | struct snd_soc_dai davinci_vcif_dai = { | 184 | static struct snd_soc_dai_driver davinci_vcif_dai = { |
183 | .name = "davinci-vcif", | ||
184 | .playback = { | 185 | .playback = { |
185 | .channels_min = 1, | 186 | .channels_min = 1, |
186 | .channels_max = 2, | 187 | .channels_max = 2, |
@@ -194,7 +195,6 @@ struct snd_soc_dai davinci_vcif_dai = { | |||
194 | .ops = &davinci_vcif_dai_ops, | 195 | .ops = &davinci_vcif_dai_ops, |
195 | 196 | ||
196 | }; | 197 | }; |
197 | EXPORT_SYMBOL_GPL(davinci_vcif_dai); | ||
198 | 198 | ||
199 | static int davinci_vcif_probe(struct platform_device *pdev) | 199 | static int davinci_vcif_probe(struct platform_device *pdev) |
200 | { | 200 | { |
@@ -222,12 +222,9 @@ static int davinci_vcif_probe(struct platform_device *pdev) | |||
222 | davinci_vcif_dev->dma_params[SNDRV_PCM_STREAM_CAPTURE].dma_addr = | 222 | davinci_vcif_dev->dma_params[SNDRV_PCM_STREAM_CAPTURE].dma_addr = |
223 | davinci_vc->davinci_vcif.dma_rx_addr; | 223 | davinci_vc->davinci_vcif.dma_rx_addr; |
224 | 224 | ||
225 | davinci_vcif_dai.dev = &pdev->dev; | 225 | dev_set_drvdata(&pdev->dev, davinci_vcif_dev); |
226 | davinci_vcif_dai.capture.dma_data = davinci_vcif_dev->dma_params; | ||
227 | davinci_vcif_dai.playback.dma_data = davinci_vcif_dev->dma_params; | ||
228 | davinci_vcif_dai.private_data = davinci_vcif_dev; | ||
229 | 226 | ||
230 | ret = snd_soc_register_dai(&davinci_vcif_dai); | 227 | ret = snd_soc_register_dai(&pdev->dev, &davinci_vcif_dai); |
231 | if (ret != 0) { | 228 | if (ret != 0) { |
232 | dev_err(&pdev->dev, "could not register dai\n"); | 229 | dev_err(&pdev->dev, "could not register dai\n"); |
233 | goto fail; | 230 | goto fail; |
@@ -243,7 +240,7 @@ fail: | |||
243 | 240 | ||
244 | static int davinci_vcif_remove(struct platform_device *pdev) | 241 | static int davinci_vcif_remove(struct platform_device *pdev) |
245 | { | 242 | { |
246 | snd_soc_unregister_dai(&davinci_vcif_dai); | 243 | snd_soc_unregister_dai(&pdev->dev); |
247 | 244 | ||
248 | return 0; | 245 | return 0; |
249 | } | 246 | } |
@@ -252,7 +249,7 @@ static struct platform_driver davinci_vcif_driver = { | |||
252 | .probe = davinci_vcif_probe, | 249 | .probe = davinci_vcif_probe, |
253 | .remove = davinci_vcif_remove, | 250 | .remove = davinci_vcif_remove, |
254 | .driver = { | 251 | .driver = { |
255 | .name = "davinci_vcif", | 252 | .name = "davinci-vcif", |
256 | .owner = THIS_MODULE, | 253 | .owner = THIS_MODULE, |
257 | }, | 254 | }, |
258 | }; | 255 | }; |
diff --git a/sound/soc/davinci/davinci-vcif.h b/sound/soc/davinci/davinci-vcif.h deleted file mode 100644 index 571c9948724f..000000000000 --- a/sound/soc/davinci/davinci-vcif.h +++ /dev/null | |||
@@ -1,28 +0,0 @@ | |||
1 | /* | ||
2 | * ALSA SoC Voice Codec Interface for TI DAVINCI processor | ||
3 | * | ||
4 | * Copyright (C) 2010 Texas Instruments. | ||
5 | * | ||
6 | * Author: Miguel Aguilar <miguel.aguilar@ridgerun.com> | ||
7 | * | ||
8 | * This program is free software; you can redistribute it and/or modify | ||
9 | * it under the terms of the GNU General Public License as published by | ||
10 | * the Free Software Foundation; either version 2 of the License, or | ||
11 | * (at your option) any later version. | ||
12 | * | ||
13 | * This program is distributed in the hope that it will be useful, | ||
14 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
15 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
16 | * GNU General Public License for more details. | ||
17 | * | ||
18 | * You should have received a copy of the GNU General Public License | ||
19 | * along with this program; if not, write to the Free Software | ||
20 | * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA | ||
21 | */ | ||
22 | |||
23 | #ifndef _DAVINCI_VCIF_H | ||
24 | #define _DAVINCI_VCIF_H | ||
25 | |||
26 | extern struct snd_soc_dai davinci_vcif_dai; | ||
27 | |||
28 | #endif | ||
diff --git a/sound/soc/ep93xx/ep93xx-i2s.c b/sound/soc/ep93xx/ep93xx-i2s.c index 00b946632184..4f4873359613 100644 --- a/sound/soc/ep93xx/ep93xx-i2s.c +++ b/sound/soc/ep93xx/ep93xx-i2s.c | |||
@@ -31,7 +31,6 @@ | |||
31 | #include <mach/dma.h> | 31 | #include <mach/dma.h> |
32 | 32 | ||
33 | #include "ep93xx-pcm.h" | 33 | #include "ep93xx-pcm.h" |
34 | #include "ep93xx-i2s.h" | ||
35 | 34 | ||
36 | #define EP93XX_I2S_TXCLKCFG 0x00 | 35 | #define EP93XX_I2S_TXCLKCFG 0x00 |
37 | #define EP93XX_I2S_RXCLKCFG 0x04 | 36 | #define EP93XX_I2S_RXCLKCFG 0x04 |
@@ -145,8 +144,8 @@ static int ep93xx_i2s_startup(struct snd_pcm_substream *substream, | |||
145 | struct snd_soc_dai *dai) | 144 | struct snd_soc_dai *dai) |
146 | { | 145 | { |
147 | struct snd_soc_pcm_runtime *rtd = substream->private_data; | 146 | struct snd_soc_pcm_runtime *rtd = substream->private_data; |
148 | struct snd_soc_dai *cpu_dai = rtd->dai->cpu_dai; | 147 | struct ep93xx_i2s_info *info = snd_soc_dai_get_drvdata(dai); |
149 | struct ep93xx_i2s_info *info = rtd->dai->cpu_dai->private_data; | 148 | struct snd_soc_dai *cpu_dai = rtd->cpu_dai; |
150 | 149 | ||
151 | snd_soc_dai_set_dma_data(cpu_dai, substream, | 150 | snd_soc_dai_set_dma_data(cpu_dai, substream, |
152 | &info->dma_params[substream->stream]); | 151 | &info->dma_params[substream->stream]); |
@@ -156,8 +155,7 @@ static int ep93xx_i2s_startup(struct snd_pcm_substream *substream, | |||
156 | static void ep93xx_i2s_shutdown(struct snd_pcm_substream *substream, | 155 | static void ep93xx_i2s_shutdown(struct snd_pcm_substream *substream, |
157 | struct snd_soc_dai *dai) | 156 | struct snd_soc_dai *dai) |
158 | { | 157 | { |
159 | struct snd_soc_pcm_runtime *rtd = substream->private_data; | 158 | struct ep93xx_i2s_info *info = snd_soc_dai_get_drvdata(dai); |
160 | struct ep93xx_i2s_info *info = rtd->dai->cpu_dai->private_data; | ||
161 | 159 | ||
162 | ep93xx_i2s_disable(info, substream->stream); | 160 | ep93xx_i2s_disable(info, substream->stream); |
163 | } | 161 | } |
@@ -165,7 +163,7 @@ static void ep93xx_i2s_shutdown(struct snd_pcm_substream *substream, | |||
165 | static int ep93xx_i2s_set_dai_fmt(struct snd_soc_dai *cpu_dai, | 163 | static int ep93xx_i2s_set_dai_fmt(struct snd_soc_dai *cpu_dai, |
166 | unsigned int fmt) | 164 | unsigned int fmt) |
167 | { | 165 | { |
168 | struct ep93xx_i2s_info *info = cpu_dai->private_data; | 166 | struct ep93xx_i2s_info *info = snd_soc_dai_get_drvdata(cpu_dai); |
169 | unsigned int clk_cfg, lin_ctrl; | 167 | unsigned int clk_cfg, lin_ctrl; |
170 | 168 | ||
171 | clk_cfg = ep93xx_i2s_read_reg(info, EP93XX_I2S_RXCLKCFG); | 169 | clk_cfg = ep93xx_i2s_read_reg(info, EP93XX_I2S_RXCLKCFG); |
@@ -242,9 +240,7 @@ static int ep93xx_i2s_hw_params(struct snd_pcm_substream *substream, | |||
242 | struct snd_pcm_hw_params *params, | 240 | struct snd_pcm_hw_params *params, |
243 | struct snd_soc_dai *dai) | 241 | struct snd_soc_dai *dai) |
244 | { | 242 | { |
245 | struct snd_soc_pcm_runtime *rtd = substream->private_data; | 243 | struct ep93xx_i2s_info *info = snd_soc_dai_get_drvdata(dai); |
246 | struct snd_soc_dai *cpu_dai = rtd->dai->cpu_dai; | ||
247 | struct ep93xx_i2s_info *info = cpu_dai->private_data; | ||
248 | unsigned word_len, div, sdiv, lrdiv; | 244 | unsigned word_len, div, sdiv, lrdiv; |
249 | int found = 0, err; | 245 | int found = 0, err; |
250 | 246 | ||
@@ -302,7 +298,7 @@ out: | |||
302 | static int ep93xx_i2s_set_sysclk(struct snd_soc_dai *cpu_dai, int clk_id, | 298 | static int ep93xx_i2s_set_sysclk(struct snd_soc_dai *cpu_dai, int clk_id, |
303 | unsigned int freq, int dir) | 299 | unsigned int freq, int dir) |
304 | { | 300 | { |
305 | struct ep93xx_i2s_info *info = cpu_dai->private_data; | 301 | struct ep93xx_i2s_info *info = snd_soc_dai_get_drvdata(cpu_dai); |
306 | 302 | ||
307 | if (dir == SND_SOC_CLOCK_IN || clk_id != 0) | 303 | if (dir == SND_SOC_CLOCK_IN || clk_id != 0) |
308 | return -EINVAL; | 304 | return -EINVAL; |
@@ -313,7 +309,7 @@ static int ep93xx_i2s_set_sysclk(struct snd_soc_dai *cpu_dai, int clk_id, | |||
313 | #ifdef CONFIG_PM | 309 | #ifdef CONFIG_PM |
314 | static int ep93xx_i2s_suspend(struct snd_soc_dai *dai) | 310 | static int ep93xx_i2s_suspend(struct snd_soc_dai *dai) |
315 | { | 311 | { |
316 | struct ep93xx_i2s_info *info = dai->private_data; | 312 | struct ep93xx_i2s_info *info = snd_soc_dai_get_drvdata(dai); |
317 | 313 | ||
318 | if (!dai->active) | 314 | if (!dai->active) |
319 | return; | 315 | return; |
@@ -324,7 +320,7 @@ static int ep93xx_i2s_suspend(struct snd_soc_dai *dai) | |||
324 | 320 | ||
325 | static int ep93xx_i2s_resume(struct snd_soc_dai *dai) | 321 | static int ep93xx_i2s_resume(struct snd_soc_dai *dai) |
326 | { | 322 | { |
327 | struct ep93xx_i2s_info *info = dai->private_data; | 323 | struct ep93xx_i2s_info *info = snd_soc_dai_get_drvdata(dai); |
328 | 324 | ||
329 | if (!dai->active) | 325 | if (!dai->active) |
330 | return; | 326 | return; |
@@ -349,9 +345,7 @@ static struct snd_soc_dai_ops ep93xx_i2s_dai_ops = { | |||
349 | SNDRV_PCM_FMTBIT_S24_LE | \ | 345 | SNDRV_PCM_FMTBIT_S24_LE | \ |
350 | SNDRV_PCM_FMTBIT_S32_LE) | 346 | SNDRV_PCM_FMTBIT_S32_LE) |
351 | 347 | ||
352 | struct snd_soc_dai ep93xx_i2s_dai = { | 348 | static struct snd_soc_dai_driver ep93xx_i2s_dai = { |
353 | .name = "ep93xx-i2s", | ||
354 | .id = 0, | ||
355 | .symmetric_rates= 1, | 349 | .symmetric_rates= 1, |
356 | .suspend = ep93xx_i2s_suspend, | 350 | .suspend = ep93xx_i2s_suspend, |
357 | .resume = ep93xx_i2s_resume, | 351 | .resume = ep93xx_i2s_resume, |
@@ -369,7 +363,6 @@ struct snd_soc_dai ep93xx_i2s_dai = { | |||
369 | }, | 363 | }, |
370 | .ops = &ep93xx_i2s_dai_ops, | 364 | .ops = &ep93xx_i2s_dai_ops, |
371 | }; | 365 | }; |
372 | EXPORT_SYMBOL_GPL(ep93xx_i2s_dai); | ||
373 | 366 | ||
374 | static int ep93xx_i2s_probe(struct platform_device *pdev) | 367 | static int ep93xx_i2s_probe(struct platform_device *pdev) |
375 | { | 368 | { |
@@ -383,8 +376,7 @@ static int ep93xx_i2s_probe(struct platform_device *pdev) | |||
383 | goto fail; | 376 | goto fail; |
384 | } | 377 | } |
385 | 378 | ||
386 | ep93xx_i2s_dai.dev = &pdev->dev; | 379 | dev_set_drvdata(&pdev->dev, info); |
387 | ep93xx_i2s_dai.private_data = info; | ||
388 | info->dma_params = ep93xx_i2s_dma_params; | 380 | info->dma_params = ep93xx_i2s_dma_params; |
389 | 381 | ||
390 | res = platform_get_resource(pdev, IORESOURCE_MEM, 0); | 382 | res = platform_get_resource(pdev, IORESOURCE_MEM, 0); |
@@ -424,7 +416,7 @@ static int ep93xx_i2s_probe(struct platform_device *pdev) | |||
424 | goto fail_put_sclk; | 416 | goto fail_put_sclk; |
425 | } | 417 | } |
426 | 418 | ||
427 | err = snd_soc_register_dai(&ep93xx_i2s_dai); | 419 | err = snd_soc_register_dai(&pdev->dev, &ep93xx_i2s_dai); |
428 | if (err) | 420 | if (err) |
429 | goto fail_put_lrclk; | 421 | goto fail_put_lrclk; |
430 | 422 | ||
@@ -447,9 +439,9 @@ fail: | |||
447 | 439 | ||
448 | static int __devexit ep93xx_i2s_remove(struct platform_device *pdev) | 440 | static int __devexit ep93xx_i2s_remove(struct platform_device *pdev) |
449 | { | 441 | { |
450 | struct ep93xx_i2s_info *info = ep93xx_i2s_dai.private_data; | 442 | struct ep93xx_i2s_info *info = dev_get_drvdata(&pdev->dev); |
451 | 443 | ||
452 | snd_soc_unregister_dai(&ep93xx_i2s_dai); | 444 | snd_soc_unregister_dai(&pdev->dev); |
453 | clk_put(info->lrclk); | 445 | clk_put(info->lrclk); |
454 | clk_put(info->sclk); | 446 | clk_put(info->sclk); |
455 | clk_put(info->mclk); | 447 | clk_put(info->mclk); |
diff --git a/sound/soc/ep93xx/ep93xx-i2s.h b/sound/soc/ep93xx/ep93xx-i2s.h deleted file mode 100644 index 3bd4ebfaa1de..000000000000 --- a/sound/soc/ep93xx/ep93xx-i2s.h +++ /dev/null | |||
@@ -1,18 +0,0 @@ | |||
1 | /* | ||
2 | * linux/sound/soc/ep93xx-i2s.h | ||
3 | * EP93xx I2S driver | ||
4 | * | ||
5 | * Copyright (C) 2010 Ryan Mallon <ryan@bluewatersys.com> | ||
6 | * | ||
7 | * This program is free software; you can redistribute it and/or modify | ||
8 | * it under the terms of the GNU General Public License version 2 as | ||
9 | * published by the Free Software Foundation. | ||
10 | * | ||
11 | */ | ||
12 | |||
13 | #ifndef _EP93XX_SND_SOC_I2S_H | ||
14 | #define _EP93XX_SND_SOC_I2S_H | ||
15 | |||
16 | extern struct snd_soc_dai ep93xx_i2s_dai; | ||
17 | |||
18 | #endif /* _EP93XX_SND_SOC_I2S_H */ | ||
diff --git a/sound/soc/ep93xx/ep93xx-pcm.c b/sound/soc/ep93xx/ep93xx-pcm.c index 4ba938400791..2f121ddbe4bb 100644 --- a/sound/soc/ep93xx/ep93xx-pcm.c +++ b/sound/soc/ep93xx/ep93xx-pcm.c | |||
@@ -95,7 +95,7 @@ static void ep93xx_pcm_buffer_finished(void *cookie, | |||
95 | static int ep93xx_pcm_open(struct snd_pcm_substream *substream) | 95 | static int ep93xx_pcm_open(struct snd_pcm_substream *substream) |
96 | { | 96 | { |
97 | struct snd_soc_pcm_runtime *soc_rtd = substream->private_data; | 97 | struct snd_soc_pcm_runtime *soc_rtd = substream->private_data; |
98 | struct snd_soc_dai *cpu_dai = soc_rtd->dai->cpu_dai; | 98 | struct snd_soc_dai *cpu_dai = soc_rtd->cpu_dai; |
99 | struct ep93xx_pcm_dma_params *dma_params; | 99 | struct ep93xx_pcm_dma_params *dma_params; |
100 | struct ep93xx_runtime_data *rtd; | 100 | struct ep93xx_runtime_data *rtd; |
101 | int ret; | 101 | int ret; |
@@ -276,14 +276,14 @@ static int ep93xx_pcm_new(struct snd_card *card, struct snd_soc_dai *dai, | |||
276 | if (!card->dev->coherent_dma_mask) | 276 | if (!card->dev->coherent_dma_mask) |
277 | card->dev->coherent_dma_mask = 0xffffffff; | 277 | card->dev->coherent_dma_mask = 0xffffffff; |
278 | 278 | ||
279 | if (dai->playback.channels_min) { | 279 | if (dai->driver->playback.channels_min) { |
280 | ret = ep93xx_pcm_preallocate_dma_buffer(pcm, | 280 | ret = ep93xx_pcm_preallocate_dma_buffer(pcm, |
281 | SNDRV_PCM_STREAM_PLAYBACK); | 281 | SNDRV_PCM_STREAM_PLAYBACK); |
282 | if (ret) | 282 | if (ret) |
283 | return ret; | 283 | return ret; |
284 | } | 284 | } |
285 | 285 | ||
286 | if (dai->capture.channels_min) { | 286 | if (dai->driver->capture.channels_min) { |
287 | ret = ep93xx_pcm_preallocate_dma_buffer(pcm, | 287 | ret = ep93xx_pcm_preallocate_dma_buffer(pcm, |
288 | SNDRV_PCM_STREAM_CAPTURE); | 288 | SNDRV_PCM_STREAM_CAPTURE); |
289 | if (ret) | 289 | if (ret) |
@@ -293,22 +293,41 @@ static int ep93xx_pcm_new(struct snd_card *card, struct snd_soc_dai *dai, | |||
293 | return 0; | 293 | return 0; |
294 | } | 294 | } |
295 | 295 | ||
296 | struct snd_soc_platform ep93xx_soc_platform = { | 296 | static struct snd_soc_platform_driver ep93xx_soc_platform = { |
297 | .name = "ep93xx-audio", | 297 | .ops = &ep93xx_pcm_ops, |
298 | .pcm_ops = &ep93xx_pcm_ops, | ||
299 | .pcm_new = &ep93xx_pcm_new, | 298 | .pcm_new = &ep93xx_pcm_new, |
300 | .pcm_free = &ep93xx_pcm_free_dma_buffers, | 299 | .pcm_free = &ep93xx_pcm_free_dma_buffers, |
301 | }; | 300 | }; |
302 | EXPORT_SYMBOL_GPL(ep93xx_soc_platform); | 301 | |
302 | static int __devinit ep93xx_soc_platform_probe(struct platform_device *pdev) | ||
303 | { | ||
304 | return snd_soc_register_platform(&pdev->dev, &ep93xx_soc_platform); | ||
305 | } | ||
306 | |||
307 | static int __devexit ep93xx_soc_platform_remove(struct platform_device *pdev) | ||
308 | { | ||
309 | snd_soc_unregister_platform(&pdev->dev); | ||
310 | return 0; | ||
311 | } | ||
312 | |||
313 | static struct platform_driver ep93xx_pcm_driver = { | ||
314 | .driver = { | ||
315 | .name = "ep93xx-pcm-audio", | ||
316 | .owner = THIS_MODULE, | ||
317 | }, | ||
318 | |||
319 | .probe = ep93xx_soc_platform_probe, | ||
320 | .remove = __devexit_p(ep93xx_soc_platform_remove), | ||
321 | }; | ||
303 | 322 | ||
304 | static int __init ep93xx_soc_platform_init(void) | 323 | static int __init ep93xx_soc_platform_init(void) |
305 | { | 324 | { |
306 | return snd_soc_register_platform(&ep93xx_soc_platform); | 325 | return platform_driver_register(&ep93xx_pcm_driver); |
307 | } | 326 | } |
308 | 327 | ||
309 | static void __exit ep93xx_soc_platform_exit(void) | 328 | static void __exit ep93xx_soc_platform_exit(void) |
310 | { | 329 | { |
311 | snd_soc_unregister_platform(&ep93xx_soc_platform); | 330 | platform_driver_unregister(&ep93xx_pcm_driver); |
312 | } | 331 | } |
313 | 332 | ||
314 | module_init(ep93xx_soc_platform_init); | 333 | module_init(ep93xx_soc_platform_init); |
diff --git a/sound/soc/ep93xx/ep93xx-pcm.h b/sound/soc/ep93xx/ep93xx-pcm.h index 4ffdd3f62fe9..111e1121ecb8 100644 --- a/sound/soc/ep93xx/ep93xx-pcm.h +++ b/sound/soc/ep93xx/ep93xx-pcm.h | |||
@@ -17,6 +17,4 @@ struct ep93xx_pcm_dma_params { | |||
17 | int dma_port; | 17 | int dma_port; |
18 | }; | 18 | }; |
19 | 19 | ||
20 | extern struct snd_soc_platform ep93xx_soc_platform; | ||
21 | |||
22 | #endif /* _EP93XX_SND_SOC_PCM_H */ | 20 | #endif /* _EP93XX_SND_SOC_PCM_H */ |
diff --git a/sound/soc/ep93xx/snappercl15.c b/sound/soc/ep93xx/snappercl15.c index 64955340ff75..28ab5ff772ac 100644 --- a/sound/soc/ep93xx/snappercl15.c +++ b/sound/soc/ep93xx/snappercl15.c | |||
@@ -22,7 +22,6 @@ | |||
22 | 22 | ||
23 | #include "../codecs/tlv320aic23.h" | 23 | #include "../codecs/tlv320aic23.h" |
24 | #include "ep93xx-pcm.h" | 24 | #include "ep93xx-pcm.h" |
25 | #include "ep93xx-i2s.h" | ||
26 | 25 | ||
27 | #define CODEC_CLOCK 5644800 | 26 | #define CODEC_CLOCK 5644800 |
28 | 27 | ||
@@ -30,8 +29,8 @@ static int snappercl15_hw_params(struct snd_pcm_substream *substream, | |||
30 | struct snd_pcm_hw_params *params) | 29 | struct snd_pcm_hw_params *params) |
31 | { | 30 | { |
32 | struct snd_soc_pcm_runtime *rtd = substream->private_data; | 31 | struct snd_soc_pcm_runtime *rtd = substream->private_data; |
33 | struct snd_soc_dai *codec_dai = rtd->dai->codec_dai; | 32 | struct snd_soc_dai *codec_dai = rtd->codec_dai; |
34 | struct snd_soc_dai *cpu_dai = rtd->dai->cpu_dai; | 33 | struct snd_soc_dai *cpu_dai = rtd->cpu_dai; |
35 | int err; | 34 | int err; |
36 | 35 | ||
37 | err = snd_soc_dai_set_fmt(codec_dai, SND_SOC_DAIFMT_I2S | | 36 | err = snd_soc_dai_set_fmt(codec_dai, SND_SOC_DAIFMT_I2S | |
@@ -77,8 +76,10 @@ static const struct snd_soc_dapm_route audio_map[] = { | |||
77 | {"MICIN", NULL, "Mic Jack"}, | 76 | {"MICIN", NULL, "Mic Jack"}, |
78 | }; | 77 | }; |
79 | 78 | ||
80 | static int snappercl15_tlv320aic23_init(struct snd_soc_codec *codec) | 79 | static int snappercl15_tlv320aic23_init(struct snd_soc_pcm_runtime *rtd) |
81 | { | 80 | { |
81 | struct snd_soc_codec *codec = rtd->codec; | ||
82 | |||
82 | snd_soc_dapm_new_controls(codec, tlv320aic23_dapm_widgets, | 83 | snd_soc_dapm_new_controls(codec, tlv320aic23_dapm_widgets, |
83 | ARRAY_SIZE(tlv320aic23_dapm_widgets)); | 84 | ARRAY_SIZE(tlv320aic23_dapm_widgets)); |
84 | 85 | ||
@@ -89,24 +90,20 @@ static int snappercl15_tlv320aic23_init(struct snd_soc_codec *codec) | |||
89 | static struct snd_soc_dai_link snappercl15_dai = { | 90 | static struct snd_soc_dai_link snappercl15_dai = { |
90 | .name = "tlv320aic23", | 91 | .name = "tlv320aic23", |
91 | .stream_name = "AIC23", | 92 | .stream_name = "AIC23", |
92 | .cpu_dai = &ep93xx_i2s_dai, | 93 | .cpu_dai_name = "ep93xx-i2s", |
93 | .codec_dai = &tlv320aic23_dai, | 94 | .codec_dai_name = "tlv320aic23-hifi", |
95 | .codec_name = "tlv320aic23-codec.0-001a", | ||
96 | .platform_name = "ep93xx-pcm-audio", | ||
94 | .init = snappercl15_tlv320aic23_init, | 97 | .init = snappercl15_tlv320aic23_init, |
95 | .ops = &snappercl15_ops, | 98 | .ops = &snappercl15_ops, |
96 | }; | 99 | }; |
97 | 100 | ||
98 | static struct snd_soc_card snd_soc_snappercl15 = { | 101 | static struct snd_soc_card snd_soc_snappercl15 = { |
99 | .name = "Snapper CL15", | 102 | .name = "Snapper CL15", |
100 | .platform = &ep93xx_soc_platform, | ||
101 | .dai_link = &snappercl15_dai, | 103 | .dai_link = &snappercl15_dai, |
102 | .num_links = 1, | 104 | .num_links = 1, |
103 | }; | 105 | }; |
104 | 106 | ||
105 | static struct snd_soc_device snappercl15_snd_devdata = { | ||
106 | .card = &snd_soc_snappercl15, | ||
107 | .codec_dev = &soc_codec_dev_tlv320aic23, | ||
108 | }; | ||
109 | |||
110 | static struct platform_device *snappercl15_snd_device; | 107 | static struct platform_device *snappercl15_snd_device; |
111 | 108 | ||
112 | static int __init snappercl15_init(void) | 109 | static int __init snappercl15_init(void) |
@@ -126,8 +123,7 @@ static int __init snappercl15_init(void) | |||
126 | if (!snappercl15_snd_device) | 123 | if (!snappercl15_snd_device) |
127 | return -ENOMEM; | 124 | return -ENOMEM; |
128 | 125 | ||
129 | platform_set_drvdata(snappercl15_snd_device, &snappercl15_snd_devdata); | 126 | platform_set_drvdata(snappercl15_snd_device, &snd_soc_snappercl15); |
130 | snappercl15_snd_devdata.dev = &snappercl15_snd_device->dev; | ||
131 | ret = platform_device_add(snappercl15_snd_device); | 127 | ret = platform_device_add(snappercl15_snd_device); |
132 | if (ret) | 128 | if (ret) |
133 | platform_device_put(snappercl15_snd_device); | 129 | platform_device_put(snappercl15_snd_device); |
diff --git a/sound/soc/fsl/Kconfig b/sound/soc/fsl/Kconfig index 8cb65ccad35f..981868700388 100644 --- a/sound/soc/fsl/Kconfig +++ b/sound/soc/fsl/Kconfig | |||
@@ -1,6 +1,3 @@ | |||
1 | config SND_SOC_OF_SIMPLE | ||
2 | tristate | ||
3 | |||
4 | config SND_MPC52xx_DMA | 1 | config SND_MPC52xx_DMA |
5 | tristate | 2 | tristate |
6 | 3 | ||
diff --git a/sound/soc/fsl/Makefile b/sound/soc/fsl/Makefile index a83a73967ec6..7e472a53fcd3 100644 --- a/sound/soc/fsl/Makefile +++ b/sound/soc/fsl/Makefile | |||
@@ -1,6 +1,3 @@ | |||
1 | # Simple machine driver that extracts configuration from the OF device tree | ||
2 | obj-$(CONFIG_SND_SOC_OF_SIMPLE) += soc-of-simple.o | ||
3 | |||
4 | # MPC8610 HPCD Machine Support | 1 | # MPC8610 HPCD Machine Support |
5 | snd-soc-mpc8610-hpcd-objs := mpc8610_hpcd.o | 2 | snd-soc-mpc8610-hpcd-objs := mpc8610_hpcd.o |
6 | obj-$(CONFIG_SND_SOC_MPC8610_HPCD) += snd-soc-mpc8610-hpcd.o | 3 | obj-$(CONFIG_SND_SOC_MPC8610_HPCD) += snd-soc-mpc8610-hpcd.o |
diff --git a/sound/soc/fsl/efika-audio-fabric.c b/sound/soc/fsl/efika-audio-fabric.c index 1a5b8e0d6a34..53251e6b5bd5 100644 --- a/sound/soc/fsl/efika-audio-fabric.c +++ b/sound/soc/fsl/efika-audio-fabric.c | |||
@@ -24,7 +24,6 @@ | |||
24 | #include <sound/pcm_params.h> | 24 | #include <sound/pcm_params.h> |
25 | #include <sound/initval.h> | 25 | #include <sound/initval.h> |
26 | #include <sound/soc.h> | 26 | #include <sound/soc.h> |
27 | #include <sound/soc-of-simple.h> | ||
28 | 27 | ||
29 | #include "mpc5200_dma.h" | 28 | #include "mpc5200_dma.h" |
30 | #include "mpc5200_psc_ac97.h" | 29 | #include "mpc5200_psc_ac97.h" |
@@ -32,21 +31,24 @@ | |||
32 | 31 | ||
33 | #define DRV_NAME "efika-audio-fabric" | 32 | #define DRV_NAME "efika-audio-fabric" |
34 | 33 | ||
35 | static struct snd_soc_device device; | ||
36 | static struct snd_soc_card card; | 34 | static struct snd_soc_card card; |
37 | 35 | ||
38 | static struct snd_soc_dai_link efika_fabric_dai[] = { | 36 | static struct snd_soc_dai_link efika_fabric_dai[] = { |
39 | { | 37 | { |
40 | .name = "AC97", | 38 | .name = "AC97", |
41 | .stream_name = "AC97 Analog", | 39 | .stream_name = "AC97 Analog", |
42 | .codec_dai = &stac9766_dai[STAC9766_DAI_AC97_ANALOG], | 40 | .codec_dai_name = "stac9766-hifi-analog", |
43 | .cpu_dai = &psc_ac97_dai[MPC5200_AC97_NORMAL], | 41 | .cpu_dai_name = "mpc5200-psc-ac97.0", |
42 | .platform_name = "mpc5200-pcm-audio", | ||
43 | .codec_name = "stac9766-codec", | ||
44 | }, | 44 | }, |
45 | { | 45 | { |
46 | .name = "AC97", | 46 | .name = "AC97", |
47 | .stream_name = "AC97 IEC958", | 47 | .stream_name = "AC97 IEC958", |
48 | .codec_dai = &stac9766_dai[STAC9766_DAI_AC97_DIGITAL], | 48 | .codec_dai_name = "stac9766-hifi-IEC958", |
49 | .cpu_dai = &psc_ac97_dai[MPC5200_AC97_SPDIF], | 49 | .cpu_dai_name = "mpc5200-psc-ac97.1", |
50 | .platform_name = "mpc5200-pcm-audio", | ||
51 | .codec_name = "stac9766-codec", | ||
50 | }, | 52 | }, |
51 | }; | 53 | }; |
52 | 54 | ||
@@ -58,13 +60,10 @@ static __init int efika_fabric_init(void) | |||
58 | if (!of_machine_is_compatible("bplan,efika")) | 60 | if (!of_machine_is_compatible("bplan,efika")) |
59 | return -ENODEV; | 61 | return -ENODEV; |
60 | 62 | ||
61 | card.platform = &mpc5200_audio_dma_platform; | ||
62 | card.name = "Efika"; | 63 | card.name = "Efika"; |
63 | card.dai_link = efika_fabric_dai; | 64 | card.dai_link = efika_fabric_dai; |
64 | card.num_links = ARRAY_SIZE(efika_fabric_dai); | 65 | card.num_links = ARRAY_SIZE(efika_fabric_dai); |
65 | 66 | ||
66 | device.card = &card; | ||
67 | device.codec_dev = &soc_codec_dev_stac9766; | ||
68 | 67 | ||
69 | pdev = platform_device_alloc("soc-audio", 1); | 68 | pdev = platform_device_alloc("soc-audio", 1); |
70 | if (!pdev) { | 69 | if (!pdev) { |
@@ -72,8 +71,7 @@ static __init int efika_fabric_init(void) | |||
72 | return -ENODEV; | 71 | return -ENODEV; |
73 | } | 72 | } |
74 | 73 | ||
75 | platform_set_drvdata(pdev, &device); | 74 | platform_set_drvdata(pdev, &card); |
76 | device.dev = &pdev->dev; | ||
77 | 75 | ||
78 | rc = platform_device_add(pdev); | 76 | rc = platform_device_add(pdev); |
79 | if (rc) { | 77 | if (rc) { |
diff --git a/sound/soc/fsl/fsl_dma.c b/sound/soc/fsl/fsl_dma.c index 410c7496a18d..57774cb91ae3 100644 --- a/sound/soc/fsl/fsl_dma.c +++ b/sound/soc/fsl/fsl_dma.c | |||
@@ -3,10 +3,11 @@ | |||
3 | * | 3 | * |
4 | * Author: Timur Tabi <timur@freescale.com> | 4 | * Author: Timur Tabi <timur@freescale.com> |
5 | * | 5 | * |
6 | * Copyright 2007-2008 Freescale Semiconductor, Inc. This file is licensed | 6 | * Copyright 2007-2010 Freescale Semiconductor, Inc. |
7 | * under the terms of the GNU General Public License version 2. This | 7 | * |
8 | * program is licensed "as is" without any warranty of any kind, whether | 8 | * This file is licensed under the terms of the GNU General Public License |
9 | * express or implied. | 9 | * version 2. This program is licensed "as is" without any warranty of any |
10 | * kind, whether express or implied. | ||
10 | * | 11 | * |
11 | * This driver implements ASoC support for the Elo DMA controller, which is | 12 | * This driver implements ASoC support for the Elo DMA controller, which is |
12 | * the DMA controller on Freescale 83xx, 85xx, and 86xx SOCs. In ALSA terms, | 13 | * the DMA controller on Freescale 83xx, 85xx, and 86xx SOCs. In ALSA terms, |
@@ -20,6 +21,8 @@ | |||
20 | #include <linux/interrupt.h> | 21 | #include <linux/interrupt.h> |
21 | #include <linux/delay.h> | 22 | #include <linux/delay.h> |
22 | #include <linux/gfp.h> | 23 | #include <linux/gfp.h> |
24 | #include <linux/of_platform.h> | ||
25 | #include <linux/list.h> | ||
23 | 26 | ||
24 | #include <sound/core.h> | 27 | #include <sound/core.h> |
25 | #include <sound/pcm.h> | 28 | #include <sound/pcm.h> |
@@ -29,6 +32,7 @@ | |||
29 | #include <asm/io.h> | 32 | #include <asm/io.h> |
30 | 33 | ||
31 | #include "fsl_dma.h" | 34 | #include "fsl_dma.h" |
35 | #include "fsl_ssi.h" /* For the offset of stx0 and srx0 */ | ||
32 | 36 | ||
33 | /* | 37 | /* |
34 | * The formats that the DMA controller supports, which is anything | 38 | * The formats that the DMA controller supports, which is anything |
@@ -52,26 +56,15 @@ | |||
52 | #define FSLDMA_PCM_RATES (SNDRV_PCM_RATE_5512 | SNDRV_PCM_RATE_8000_192000 | \ | 56 | #define FSLDMA_PCM_RATES (SNDRV_PCM_RATE_5512 | SNDRV_PCM_RATE_8000_192000 | \ |
53 | SNDRV_PCM_RATE_CONTINUOUS) | 57 | SNDRV_PCM_RATE_CONTINUOUS) |
54 | 58 | ||
55 | /* DMA global data. This structure is used by fsl_dma_open() to determine | 59 | struct dma_object { |
56 | * which DMA channels to assign to a substream. Unfortunately, ASoC V1 does | 60 | struct snd_soc_platform_driver dai; |
57 | * not allow the machine driver to provide this information to the PCM | ||
58 | * driver in advance, and there's no way to differentiate between the two | ||
59 | * DMA controllers. So for now, this driver only supports one SSI device | ||
60 | * using two DMA channels. We cannot support multiple DMA devices. | ||
61 | * | ||
62 | * ssi_stx_phys: bus address of SSI STX register | ||
63 | * ssi_srx_phys: bus address of SSI SRX register | ||
64 | * dma_channel: pointer to the DMA channel's registers | ||
65 | * irq: IRQ for this DMA channel | ||
66 | * assigned: set to 1 if that DMA channel is assigned to a substream | ||
67 | */ | ||
68 | static struct { | ||
69 | dma_addr_t ssi_stx_phys; | 61 | dma_addr_t ssi_stx_phys; |
70 | dma_addr_t ssi_srx_phys; | 62 | dma_addr_t ssi_srx_phys; |
71 | struct ccsr_dma_channel __iomem *dma_channel[2]; | 63 | struct ccsr_dma_channel __iomem *channel; |
72 | unsigned int irq[2]; | 64 | unsigned int irq; |
73 | unsigned int assigned[2]; | 65 | bool assigned; |
74 | } dma_global_data; | 66 | char path[1]; |
67 | }; | ||
75 | 68 | ||
76 | /* | 69 | /* |
77 | * The number of DMA links to use. Two is the bare minimum, but if you | 70 | * The number of DMA links to use. Two is the bare minimum, but if you |
@@ -88,8 +81,6 @@ static struct { | |||
88 | * structure. | 81 | * structure. |
89 | * | 82 | * |
90 | * @link[]: array of link descriptors | 83 | * @link[]: array of link descriptors |
91 | * @controller_id: which DMA controller (0, 1, ...) | ||
92 | * @channel_id: which DMA channel on the controller (0, 1, 2, ...) | ||
93 | * @dma_channel: pointer to the DMA channel's registers | 84 | * @dma_channel: pointer to the DMA channel's registers |
94 | * @irq: IRQ for this DMA channel | 85 | * @irq: IRQ for this DMA channel |
95 | * @substream: pointer to the substream object, needed by the ISR | 86 | * @substream: pointer to the substream object, needed by the ISR |
@@ -104,8 +95,6 @@ static struct { | |||
104 | */ | 95 | */ |
105 | struct fsl_dma_private { | 96 | struct fsl_dma_private { |
106 | struct fsl_dma_link_descriptor link[NUM_DMA_LINKS]; | 97 | struct fsl_dma_link_descriptor link[NUM_DMA_LINKS]; |
107 | unsigned int controller_id; | ||
108 | unsigned int channel_id; | ||
109 | struct ccsr_dma_channel __iomem *dma_channel; | 98 | struct ccsr_dma_channel __iomem *dma_channel; |
110 | unsigned int irq; | 99 | unsigned int irq; |
111 | struct snd_pcm_substream *substream; | 100 | struct snd_pcm_substream *substream; |
@@ -185,13 +174,23 @@ static void fsl_dma_update_pointers(struct fsl_dma_private *dma_private) | |||
185 | struct fsl_dma_link_descriptor *link = | 174 | struct fsl_dma_link_descriptor *link = |
186 | &dma_private->link[dma_private->current_link]; | 175 | &dma_private->link[dma_private->current_link]; |
187 | 176 | ||
188 | /* Update our link descriptors to point to the next period */ | 177 | /* Update our link descriptors to point to the next period. On a 36-bit |
189 | if (dma_private->substream->stream == SNDRV_PCM_STREAM_PLAYBACK) | 178 | * system, we also need to update the ESAD bits. We also set (keep) the |
190 | link->source_addr = | 179 | * snoop bits. See the comments in fsl_dma_hw_params() about snooping. |
191 | cpu_to_be32(dma_private->dma_buf_next); | 180 | */ |
192 | else | 181 | if (dma_private->substream->stream == SNDRV_PCM_STREAM_PLAYBACK) { |
193 | link->dest_addr = | 182 | link->source_addr = cpu_to_be32(dma_private->dma_buf_next); |
194 | cpu_to_be32(dma_private->dma_buf_next); | 183 | #ifdef CONFIG_PHYS_64BIT |
184 | link->source_attr = cpu_to_be32(CCSR_DMA_ATR_SNOOP | | ||
185 | upper_32_bits(dma_private->dma_buf_next)); | ||
186 | #endif | ||
187 | } else { | ||
188 | link->dest_addr = cpu_to_be32(dma_private->dma_buf_next); | ||
189 | #ifdef CONFIG_PHYS_64BIT | ||
190 | link->dest_attr = cpu_to_be32(CCSR_DMA_ATR_SNOOP | | ||
191 | upper_32_bits(dma_private->dma_buf_next)); | ||
192 | #endif | ||
193 | } | ||
195 | 194 | ||
196 | /* Update our variables for next time */ | 195 | /* Update our variables for next time */ |
197 | dma_private->dma_buf_next += dma_private->period_size; | 196 | dma_private->dma_buf_next += dma_private->period_size; |
@@ -212,6 +211,9 @@ static void fsl_dma_update_pointers(struct fsl_dma_private *dma_private) | |||
212 | static irqreturn_t fsl_dma_isr(int irq, void *dev_id) | 211 | static irqreturn_t fsl_dma_isr(int irq, void *dev_id) |
213 | { | 212 | { |
214 | struct fsl_dma_private *dma_private = dev_id; | 213 | struct fsl_dma_private *dma_private = dev_id; |
214 | struct snd_pcm_substream *substream = dma_private->substream; | ||
215 | struct snd_soc_pcm_runtime *rtd = substream->private_data; | ||
216 | struct device *dev = rtd->platform->dev; | ||
215 | struct ccsr_dma_channel __iomem *dma_channel = dma_private->dma_channel; | 217 | struct ccsr_dma_channel __iomem *dma_channel = dma_private->dma_channel; |
216 | irqreturn_t ret = IRQ_NONE; | 218 | irqreturn_t ret = IRQ_NONE; |
217 | u32 sr, sr2 = 0; | 219 | u32 sr, sr2 = 0; |
@@ -222,11 +224,8 @@ static irqreturn_t fsl_dma_isr(int irq, void *dev_id) | |||
222 | sr = in_be32(&dma_channel->sr); | 224 | sr = in_be32(&dma_channel->sr); |
223 | 225 | ||
224 | if (sr & CCSR_DMA_SR_TE) { | 226 | if (sr & CCSR_DMA_SR_TE) { |
225 | dev_err(dma_private->substream->pcm->card->dev, | 227 | dev_err(dev, "dma transmit error\n"); |
226 | "DMA transmit error (controller=%u channel=%u irq=%u\n", | 228 | fsl_dma_abort_stream(substream); |
227 | dma_private->controller_id, | ||
228 | dma_private->channel_id, irq); | ||
229 | fsl_dma_abort_stream(dma_private->substream); | ||
230 | sr2 |= CCSR_DMA_SR_TE; | 229 | sr2 |= CCSR_DMA_SR_TE; |
231 | ret = IRQ_HANDLED; | 230 | ret = IRQ_HANDLED; |
232 | } | 231 | } |
@@ -235,11 +234,8 @@ static irqreturn_t fsl_dma_isr(int irq, void *dev_id) | |||
235 | ret = IRQ_HANDLED; | 234 | ret = IRQ_HANDLED; |
236 | 235 | ||
237 | if (sr & CCSR_DMA_SR_PE) { | 236 | if (sr & CCSR_DMA_SR_PE) { |
238 | dev_err(dma_private->substream->pcm->card->dev, | 237 | dev_err(dev, "dma programming error\n"); |
239 | "DMA%u programming error (channel=%u irq=%u)\n", | 238 | fsl_dma_abort_stream(substream); |
240 | dma_private->controller_id, | ||
241 | dma_private->channel_id, irq); | ||
242 | fsl_dma_abort_stream(dma_private->substream); | ||
243 | sr2 |= CCSR_DMA_SR_PE; | 239 | sr2 |= CCSR_DMA_SR_PE; |
244 | ret = IRQ_HANDLED; | 240 | ret = IRQ_HANDLED; |
245 | } | 241 | } |
@@ -253,8 +249,6 @@ static irqreturn_t fsl_dma_isr(int irq, void *dev_id) | |||
253 | ret = IRQ_HANDLED; | 249 | ret = IRQ_HANDLED; |
254 | 250 | ||
255 | if (sr & CCSR_DMA_SR_EOSI) { | 251 | if (sr & CCSR_DMA_SR_EOSI) { |
256 | struct snd_pcm_substream *substream = dma_private->substream; | ||
257 | |||
258 | /* Tell ALSA we completed a period. */ | 252 | /* Tell ALSA we completed a period. */ |
259 | snd_pcm_period_elapsed(substream); | 253 | snd_pcm_period_elapsed(substream); |
260 | 254 | ||
@@ -288,11 +282,19 @@ static irqreturn_t fsl_dma_isr(int irq, void *dev_id) | |||
288 | * This function is called when the codec driver calls snd_soc_new_pcms(), | 282 | * This function is called when the codec driver calls snd_soc_new_pcms(), |
289 | * once for each .dai_link in the machine driver's snd_soc_card | 283 | * once for each .dai_link in the machine driver's snd_soc_card |
290 | * structure. | 284 | * structure. |
285 | * | ||
286 | * snd_dma_alloc_pages() is just a front-end to dma_alloc_coherent(), which | ||
287 | * (currently) always allocates the DMA buffer in lowmem, even if GFP_HIGHMEM | ||
288 | * is specified. Therefore, any DMA buffers we allocate will always be in low | ||
289 | * memory, but we support for 36-bit physical addresses anyway. | ||
290 | * | ||
291 | * Regardless of where the memory is actually allocated, since the device can | ||
292 | * technically DMA to any 36-bit address, we do need to set the DMA mask to 36. | ||
291 | */ | 293 | */ |
292 | static int fsl_dma_new(struct snd_card *card, struct snd_soc_dai *dai, | 294 | static int fsl_dma_new(struct snd_card *card, struct snd_soc_dai *dai, |
293 | struct snd_pcm *pcm) | 295 | struct snd_pcm *pcm) |
294 | { | 296 | { |
295 | static u64 fsl_dma_dmamask = DMA_BIT_MASK(32); | 297 | static u64 fsl_dma_dmamask = DMA_BIT_MASK(36); |
296 | int ret; | 298 | int ret; |
297 | 299 | ||
298 | if (!card->dev->dma_mask) | 300 | if (!card->dev->dma_mask) |
@@ -305,10 +307,8 @@ static int fsl_dma_new(struct snd_card *card, struct snd_soc_dai *dai, | |||
305 | fsl_dma_hardware.buffer_bytes_max, | 307 | fsl_dma_hardware.buffer_bytes_max, |
306 | &pcm->streams[0].substream->dma_buffer); | 308 | &pcm->streams[0].substream->dma_buffer); |
307 | if (ret) { | 309 | if (ret) { |
308 | dev_err(card->dev, | 310 | dev_err(card->dev, "can't allocate playback dma buffer\n"); |
309 | "Can't allocate playback DMA buffer (size=%u)\n", | 311 | return ret; |
310 | fsl_dma_hardware.buffer_bytes_max); | ||
311 | return -ENOMEM; | ||
312 | } | 312 | } |
313 | 313 | ||
314 | ret = snd_dma_alloc_pages(SNDRV_DMA_TYPE_DEV, card->dev, | 314 | ret = snd_dma_alloc_pages(SNDRV_DMA_TYPE_DEV, card->dev, |
@@ -316,10 +316,8 @@ static int fsl_dma_new(struct snd_card *card, struct snd_soc_dai *dai, | |||
316 | &pcm->streams[1].substream->dma_buffer); | 316 | &pcm->streams[1].substream->dma_buffer); |
317 | if (ret) { | 317 | if (ret) { |
318 | snd_dma_free_pages(&pcm->streams[0].substream->dma_buffer); | 318 | snd_dma_free_pages(&pcm->streams[0].substream->dma_buffer); |
319 | dev_err(card->dev, | 319 | dev_err(card->dev, "can't allocate capture dma buffer\n"); |
320 | "Can't allocate capture DMA buffer (size=%u)\n", | 320 | return ret; |
321 | fsl_dma_hardware.buffer_bytes_max); | ||
322 | return -ENOMEM; | ||
323 | } | 321 | } |
324 | 322 | ||
325 | return 0; | 323 | return 0; |
@@ -390,6 +388,10 @@ static int fsl_dma_new(struct snd_card *card, struct snd_soc_dai *dai, | |||
390 | static int fsl_dma_open(struct snd_pcm_substream *substream) | 388 | static int fsl_dma_open(struct snd_pcm_substream *substream) |
391 | { | 389 | { |
392 | struct snd_pcm_runtime *runtime = substream->runtime; | 390 | struct snd_pcm_runtime *runtime = substream->runtime; |
391 | struct snd_soc_pcm_runtime *rtd = substream->private_data; | ||
392 | struct device *dev = rtd->platform->dev; | ||
393 | struct dma_object *dma = | ||
394 | container_of(rtd->platform->driver, struct dma_object, dai); | ||
393 | struct fsl_dma_private *dma_private; | 395 | struct fsl_dma_private *dma_private; |
394 | struct ccsr_dma_channel __iomem *dma_channel; | 396 | struct ccsr_dma_channel __iomem *dma_channel; |
395 | dma_addr_t ld_buf_phys; | 397 | dma_addr_t ld_buf_phys; |
@@ -407,52 +409,44 @@ static int fsl_dma_open(struct snd_pcm_substream *substream) | |||
407 | ret = snd_pcm_hw_constraint_integer(runtime, | 409 | ret = snd_pcm_hw_constraint_integer(runtime, |
408 | SNDRV_PCM_HW_PARAM_PERIODS); | 410 | SNDRV_PCM_HW_PARAM_PERIODS); |
409 | if (ret < 0) { | 411 | if (ret < 0) { |
410 | dev_err(substream->pcm->card->dev, "invalid buffer size\n"); | 412 | dev_err(dev, "invalid buffer size\n"); |
411 | return ret; | 413 | return ret; |
412 | } | 414 | } |
413 | 415 | ||
414 | channel = substream->stream == SNDRV_PCM_STREAM_PLAYBACK ? 0 : 1; | 416 | channel = substream->stream == SNDRV_PCM_STREAM_PLAYBACK ? 0 : 1; |
415 | 417 | ||
416 | if (dma_global_data.assigned[channel]) { | 418 | if (dma->assigned) { |
417 | dev_err(substream->pcm->card->dev, | 419 | dev_err(dev, "dma channel already assigned\n"); |
418 | "DMA channel already assigned\n"); | ||
419 | return -EBUSY; | 420 | return -EBUSY; |
420 | } | 421 | } |
421 | 422 | ||
422 | dma_private = dma_alloc_coherent(substream->pcm->card->dev, | 423 | dma_private = dma_alloc_coherent(dev, sizeof(struct fsl_dma_private), |
423 | sizeof(struct fsl_dma_private), &ld_buf_phys, GFP_KERNEL); | 424 | &ld_buf_phys, GFP_KERNEL); |
424 | if (!dma_private) { | 425 | if (!dma_private) { |
425 | dev_err(substream->pcm->card->dev, | 426 | dev_err(dev, "can't allocate dma private data\n"); |
426 | "can't allocate DMA private data\n"); | ||
427 | return -ENOMEM; | 427 | return -ENOMEM; |
428 | } | 428 | } |
429 | if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) | 429 | if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) |
430 | dma_private->ssi_sxx_phys = dma_global_data.ssi_stx_phys; | 430 | dma_private->ssi_sxx_phys = dma->ssi_stx_phys; |
431 | else | 431 | else |
432 | dma_private->ssi_sxx_phys = dma_global_data.ssi_srx_phys; | 432 | dma_private->ssi_sxx_phys = dma->ssi_srx_phys; |
433 | 433 | ||
434 | dma_private->dma_channel = dma_global_data.dma_channel[channel]; | 434 | dma_private->dma_channel = dma->channel; |
435 | dma_private->irq = dma_global_data.irq[channel]; | 435 | dma_private->irq = dma->irq; |
436 | dma_private->substream = substream; | 436 | dma_private->substream = substream; |
437 | dma_private->ld_buf_phys = ld_buf_phys; | 437 | dma_private->ld_buf_phys = ld_buf_phys; |
438 | dma_private->dma_buf_phys = substream->dma_buffer.addr; | 438 | dma_private->dma_buf_phys = substream->dma_buffer.addr; |
439 | 439 | ||
440 | /* We only support one DMA controller for now */ | ||
441 | dma_private->controller_id = 0; | ||
442 | dma_private->channel_id = channel; | ||
443 | |||
444 | ret = request_irq(dma_private->irq, fsl_dma_isr, 0, "DMA", dma_private); | 440 | ret = request_irq(dma_private->irq, fsl_dma_isr, 0, "DMA", dma_private); |
445 | if (ret) { | 441 | if (ret) { |
446 | dev_err(substream->pcm->card->dev, | 442 | dev_err(dev, "can't register ISR for IRQ %u (ret=%i)\n", |
447 | "can't register ISR for IRQ %u (ret=%i)\n", | ||
448 | dma_private->irq, ret); | 443 | dma_private->irq, ret); |
449 | dma_free_coherent(substream->pcm->card->dev, | 444 | dma_free_coherent(dev, sizeof(struct fsl_dma_private), |
450 | sizeof(struct fsl_dma_private), | ||
451 | dma_private, dma_private->ld_buf_phys); | 445 | dma_private, dma_private->ld_buf_phys); |
452 | return ret; | 446 | return ret; |
453 | } | 447 | } |
454 | 448 | ||
455 | dma_global_data.assigned[channel] = 1; | 449 | dma->assigned = 1; |
456 | 450 | ||
457 | snd_pcm_set_runtime_buffer(substream, &substream->dma_buffer); | 451 | snd_pcm_set_runtime_buffer(substream, &substream->dma_buffer); |
458 | snd_soc_set_runtime_hwparams(substream, &fsl_dma_hardware); | 452 | snd_soc_set_runtime_hwparams(substream, &fsl_dma_hardware); |
@@ -546,6 +540,8 @@ static int fsl_dma_hw_params(struct snd_pcm_substream *substream, | |||
546 | { | 540 | { |
547 | struct snd_pcm_runtime *runtime = substream->runtime; | 541 | struct snd_pcm_runtime *runtime = substream->runtime; |
548 | struct fsl_dma_private *dma_private = runtime->private_data; | 542 | struct fsl_dma_private *dma_private = runtime->private_data; |
543 | struct snd_soc_pcm_runtime *rtd = substream->private_data; | ||
544 | struct device *dev = rtd->platform->dev; | ||
549 | 545 | ||
550 | /* Number of bits per sample */ | 546 | /* Number of bits per sample */ |
551 | unsigned int sample_size = | 547 | unsigned int sample_size = |
@@ -606,8 +602,7 @@ static int fsl_dma_hw_params(struct snd_pcm_substream *substream, | |||
606 | break; | 602 | break; |
607 | default: | 603 | default: |
608 | /* We should never get here */ | 604 | /* We should never get here */ |
609 | dev_err(substream->pcm->card->dev, | 605 | dev_err(dev, "unsupported sample size %u\n", sample_size); |
610 | "unsupported sample size %u\n", sample_size); | ||
611 | return -EINVAL; | 606 | return -EINVAL; |
612 | } | 607 | } |
613 | 608 | ||
@@ -631,12 +626,7 @@ static int fsl_dma_hw_params(struct snd_pcm_substream *substream, | |||
631 | 626 | ||
632 | link->count = cpu_to_be32(period_size); | 627 | link->count = cpu_to_be32(period_size); |
633 | 628 | ||
634 | /* Even though the DMA controller supports 36-bit addressing, | 629 | /* The snoop bit tells the DMA controller whether it should tell |
635 | * for simplicity we allow only 32-bit addresses for the audio | ||
636 | * buffer itself. This was enforced in fsl_dma_new() with the | ||
637 | * DMA mask. | ||
638 | * | ||
639 | * The snoop bit tells the DMA controller whether it should tell | ||
640 | * the ECM to snoop during a read or write to an address. For | 630 | * the ECM to snoop during a read or write to an address. For |
641 | * audio, we use DMA to transfer data between memory and an I/O | 631 | * audio, we use DMA to transfer data between memory and an I/O |
642 | * device (the SSI's STX0 or SRX0 register). Snooping is only | 632 | * device (the SSI's STX0 or SRX0 register). Snooping is only |
@@ -651,20 +641,24 @@ static int fsl_dma_hw_params(struct snd_pcm_substream *substream, | |||
651 | * flush out the data for the previous period. So if you | 641 | * flush out the data for the previous period. So if you |
652 | * increased period_bytes_min to a large enough size, you might | 642 | * increased period_bytes_min to a large enough size, you might |
653 | * get more performance by not snooping, and you'll still be | 643 | * get more performance by not snooping, and you'll still be |
654 | * okay. | 644 | * okay. You'll need to update fsl_dma_update_pointers() also. |
655 | */ | 645 | */ |
656 | if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) { | 646 | if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) { |
657 | link->source_addr = cpu_to_be32(temp_addr); | 647 | link->source_addr = cpu_to_be32(temp_addr); |
658 | link->source_attr = cpu_to_be32(CCSR_DMA_ATR_SNOOP); | 648 | link->source_attr = cpu_to_be32(CCSR_DMA_ATR_SNOOP | |
649 | upper_32_bits(temp_addr)); | ||
659 | 650 | ||
660 | link->dest_addr = cpu_to_be32(ssi_sxx_phys); | 651 | link->dest_addr = cpu_to_be32(ssi_sxx_phys); |
661 | link->dest_attr = cpu_to_be32(CCSR_DMA_ATR_NOSNOOP); | 652 | link->dest_attr = cpu_to_be32(CCSR_DMA_ATR_NOSNOOP | |
653 | upper_32_bits(ssi_sxx_phys)); | ||
662 | } else { | 654 | } else { |
663 | link->source_addr = cpu_to_be32(ssi_sxx_phys); | 655 | link->source_addr = cpu_to_be32(ssi_sxx_phys); |
664 | link->source_attr = cpu_to_be32(CCSR_DMA_ATR_NOSNOOP); | 656 | link->source_attr = cpu_to_be32(CCSR_DMA_ATR_NOSNOOP | |
657 | upper_32_bits(ssi_sxx_phys)); | ||
665 | 658 | ||
666 | link->dest_addr = cpu_to_be32(temp_addr); | 659 | link->dest_addr = cpu_to_be32(temp_addr); |
667 | link->dest_attr = cpu_to_be32(CCSR_DMA_ATR_SNOOP); | 660 | link->dest_attr = cpu_to_be32(CCSR_DMA_ATR_SNOOP | |
661 | upper_32_bits(temp_addr)); | ||
668 | } | 662 | } |
669 | 663 | ||
670 | temp_addr += period_size; | 664 | temp_addr += period_size; |
@@ -689,14 +683,29 @@ static snd_pcm_uframes_t fsl_dma_pointer(struct snd_pcm_substream *substream) | |||
689 | { | 683 | { |
690 | struct snd_pcm_runtime *runtime = substream->runtime; | 684 | struct snd_pcm_runtime *runtime = substream->runtime; |
691 | struct fsl_dma_private *dma_private = runtime->private_data; | 685 | struct fsl_dma_private *dma_private = runtime->private_data; |
686 | struct snd_soc_pcm_runtime *rtd = substream->private_data; | ||
687 | struct device *dev = rtd->platform->dev; | ||
692 | struct ccsr_dma_channel __iomem *dma_channel = dma_private->dma_channel; | 688 | struct ccsr_dma_channel __iomem *dma_channel = dma_private->dma_channel; |
693 | dma_addr_t position; | 689 | dma_addr_t position; |
694 | snd_pcm_uframes_t frames; | 690 | snd_pcm_uframes_t frames; |
695 | 691 | ||
696 | if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) | 692 | /* Obtain the current DMA pointer, but don't read the ESAD bits if we |
693 | * only have 32-bit DMA addresses. This function is typically called | ||
694 | * in interrupt context, so we need to optimize it. | ||
695 | */ | ||
696 | if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) { | ||
697 | position = in_be32(&dma_channel->sar); | 697 | position = in_be32(&dma_channel->sar); |
698 | else | 698 | #ifdef CONFIG_PHYS_64BIT |
699 | position |= (u64)(in_be32(&dma_channel->satr) & | ||
700 | CCSR_DMA_ATR_ESAD_MASK) << 32; | ||
701 | #endif | ||
702 | } else { | ||
699 | position = in_be32(&dma_channel->dar); | 703 | position = in_be32(&dma_channel->dar); |
704 | #ifdef CONFIG_PHYS_64BIT | ||
705 | position |= (u64)(in_be32(&dma_channel->datr) & | ||
706 | CCSR_DMA_ATR_ESAD_MASK) << 32; | ||
707 | #endif | ||
708 | } | ||
700 | 709 | ||
701 | /* | 710 | /* |
702 | * When capture is started, the SSI immediately starts to fill its FIFO. | 711 | * When capture is started, the SSI immediately starts to fill its FIFO. |
@@ -710,8 +719,7 @@ static snd_pcm_uframes_t fsl_dma_pointer(struct snd_pcm_substream *substream) | |||
710 | 719 | ||
711 | if ((position < dma_private->dma_buf_phys) || | 720 | if ((position < dma_private->dma_buf_phys) || |
712 | (position > dma_private->dma_buf_end)) { | 721 | (position > dma_private->dma_buf_end)) { |
713 | dev_err(substream->pcm->card->dev, | 722 | dev_err(dev, "dma pointer is out of range, halting stream\n"); |
714 | "dma pointer is out of range, halting stream\n"); | ||
715 | return SNDRV_PCM_POS_XRUN; | 723 | return SNDRV_PCM_POS_XRUN; |
716 | } | 724 | } |
717 | 725 | ||
@@ -772,26 +780,28 @@ static int fsl_dma_close(struct snd_pcm_substream *substream) | |||
772 | { | 780 | { |
773 | struct snd_pcm_runtime *runtime = substream->runtime; | 781 | struct snd_pcm_runtime *runtime = substream->runtime; |
774 | struct fsl_dma_private *dma_private = runtime->private_data; | 782 | struct fsl_dma_private *dma_private = runtime->private_data; |
775 | int dir = substream->stream == SNDRV_PCM_STREAM_PLAYBACK ? 0 : 1; | 783 | struct snd_soc_pcm_runtime *rtd = substream->private_data; |
784 | struct device *dev = rtd->platform->dev; | ||
785 | struct dma_object *dma = | ||
786 | container_of(rtd->platform->driver, struct dma_object, dai); | ||
776 | 787 | ||
777 | if (dma_private) { | 788 | if (dma_private) { |
778 | if (dma_private->irq) | 789 | if (dma_private->irq) |
779 | free_irq(dma_private->irq, dma_private); | 790 | free_irq(dma_private->irq, dma_private); |
780 | 791 | ||
781 | if (dma_private->ld_buf_phys) { | 792 | if (dma_private->ld_buf_phys) { |
782 | dma_unmap_single(substream->pcm->card->dev, | 793 | dma_unmap_single(dev, dma_private->ld_buf_phys, |
783 | dma_private->ld_buf_phys, | 794 | sizeof(dma_private->link), |
784 | sizeof(dma_private->link), DMA_TO_DEVICE); | 795 | DMA_TO_DEVICE); |
785 | } | 796 | } |
786 | 797 | ||
787 | /* Deallocate the fsl_dma_private structure */ | 798 | /* Deallocate the fsl_dma_private structure */ |
788 | dma_free_coherent(substream->pcm->card->dev, | 799 | dma_free_coherent(dev, sizeof(struct fsl_dma_private), |
789 | sizeof(struct fsl_dma_private), | 800 | dma_private, dma_private->ld_buf_phys); |
790 | dma_private, dma_private->ld_buf_phys); | ||
791 | substream->runtime->private_data = NULL; | 801 | substream->runtime->private_data = NULL; |
792 | } | 802 | } |
793 | 803 | ||
794 | dma_global_data.assigned[dir] = 0; | 804 | dma->assigned = 0; |
795 | 805 | ||
796 | return 0; | 806 | return 0; |
797 | } | 807 | } |
@@ -814,6 +824,37 @@ static void fsl_dma_free_dma_buffers(struct snd_pcm *pcm) | |||
814 | } | 824 | } |
815 | } | 825 | } |
816 | 826 | ||
827 | /** | ||
828 | * find_ssi_node -- returns the SSI node that points to his DMA channel node | ||
829 | * | ||
830 | * Although this DMA driver attempts to operate independently of the other | ||
831 | * devices, it still needs to determine some information about the SSI device | ||
832 | * that it's working with. Unfortunately, the device tree does not contain | ||
833 | * a pointer from the DMA channel node to the SSI node -- the pointer goes the | ||
834 | * other way. So we need to scan the device tree for SSI nodes until we find | ||
835 | * the one that points to the given DMA channel node. It's ugly, but at least | ||
836 | * it's contained in this one function. | ||
837 | */ | ||
838 | static struct device_node *find_ssi_node(struct device_node *dma_channel_np) | ||
839 | { | ||
840 | struct device_node *ssi_np, *np; | ||
841 | |||
842 | for_each_compatible_node(ssi_np, NULL, "fsl,mpc8610-ssi") { | ||
843 | /* Check each DMA phandle to see if it points to us. We | ||
844 | * assume that device_node pointers are a valid comparison. | ||
845 | */ | ||
846 | np = of_parse_phandle(ssi_np, "fsl,playback-dma", 0); | ||
847 | if (np == dma_channel_np) | ||
848 | return ssi_np; | ||
849 | |||
850 | np = of_parse_phandle(ssi_np, "fsl,capture-dma", 0); | ||
851 | if (np == dma_channel_np) | ||
852 | return ssi_np; | ||
853 | } | ||
854 | |||
855 | return NULL; | ||
856 | } | ||
857 | |||
817 | static struct snd_pcm_ops fsl_dma_ops = { | 858 | static struct snd_pcm_ops fsl_dma_ops = { |
818 | .open = fsl_dma_open, | 859 | .open = fsl_dma_open, |
819 | .close = fsl_dma_close, | 860 | .close = fsl_dma_close, |
@@ -823,59 +864,102 @@ static struct snd_pcm_ops fsl_dma_ops = { | |||
823 | .pointer = fsl_dma_pointer, | 864 | .pointer = fsl_dma_pointer, |
824 | }; | 865 | }; |
825 | 866 | ||
826 | struct snd_soc_platform fsl_soc_platform = { | 867 | static int __devinit fsl_soc_dma_probe(struct of_device *of_dev, |
827 | .name = "fsl-dma", | 868 | const struct of_device_id *match) |
828 | .pcm_ops = &fsl_dma_ops, | 869 | { |
829 | .pcm_new = fsl_dma_new, | 870 | struct dma_object *dma; |
830 | .pcm_free = fsl_dma_free_dma_buffers, | 871 | struct device_node *np = of_dev->dev.of_node; |
831 | }; | 872 | struct device_node *ssi_np; |
832 | EXPORT_SYMBOL_GPL(fsl_soc_platform); | 873 | struct resource res; |
874 | int ret; | ||
833 | 875 | ||
834 | /** | 876 | /* Find the SSI node that points to us. */ |
835 | * fsl_dma_configure: store the DMA parameters from the fabric driver. | 877 | ssi_np = find_ssi_node(np); |
836 | * | 878 | if (!ssi_np) { |
837 | * This function is called by the ASoC fabric driver to give us the DMA and | 879 | dev_err(&of_dev->dev, "cannot find parent SSI node\n"); |
838 | * SSI channel information. | 880 | return -ENODEV; |
839 | * | 881 | } |
840 | * Unfortunately, ASoC V1 does make it possible to determine the DMA/SSI | 882 | |
841 | * data when a substream is created, so for now we need to store this data | 883 | ret = of_address_to_resource(ssi_np, 0, &res); |
842 | * into a global variable. This means that we can only support one DMA | 884 | of_node_put(ssi_np); |
843 | * controller, and hence only one SSI. | 885 | if (ret) { |
844 | */ | 886 | dev_err(&of_dev->dev, "could not determine device resources\n"); |
845 | int fsl_dma_configure(struct fsl_dma_info *dma_info) | 887 | return ret; |
888 | } | ||
889 | |||
890 | dma = kzalloc(sizeof(*dma) + strlen(np->full_name), GFP_KERNEL); | ||
891 | if (!dma) { | ||
892 | dev_err(&of_dev->dev, "could not allocate dma object\n"); | ||
893 | return -ENOMEM; | ||
894 | } | ||
895 | |||
896 | strcpy(dma->path, np->full_name); | ||
897 | dma->dai.ops = &fsl_dma_ops; | ||
898 | dma->dai.pcm_new = fsl_dma_new; | ||
899 | dma->dai.pcm_free = fsl_dma_free_dma_buffers; | ||
900 | |||
901 | /* Store the SSI-specific information that we need */ | ||
902 | dma->ssi_stx_phys = res.start + offsetof(struct ccsr_ssi, stx0); | ||
903 | dma->ssi_srx_phys = res.start + offsetof(struct ccsr_ssi, srx0); | ||
904 | |||
905 | ret = snd_soc_register_platform(&of_dev->dev, &dma->dai); | ||
906 | if (ret) { | ||
907 | dev_err(&of_dev->dev, "could not register platform\n"); | ||
908 | kfree(dma); | ||
909 | return ret; | ||
910 | } | ||
911 | |||
912 | dma->channel = of_iomap(np, 0); | ||
913 | dma->irq = irq_of_parse_and_map(np, 0); | ||
914 | |||
915 | dev_set_drvdata(&of_dev->dev, dma); | ||
916 | |||
917 | return 0; | ||
918 | } | ||
919 | |||
920 | static int __devexit fsl_soc_dma_remove(struct of_device *of_dev) | ||
846 | { | 921 | { |
847 | static int initialized; | 922 | struct dma_object *dma = dev_get_drvdata(&of_dev->dev); |
848 | 923 | ||
849 | /* We only support one DMA controller for now */ | 924 | snd_soc_unregister_platform(&of_dev->dev); |
850 | if (initialized) | 925 | iounmap(dma->channel); |
851 | return 0; | 926 | irq_dispose_mapping(dma->irq); |
927 | kfree(dma); | ||
852 | 928 | ||
853 | dma_global_data.ssi_stx_phys = dma_info->ssi_stx_phys; | 929 | return 0; |
854 | dma_global_data.ssi_srx_phys = dma_info->ssi_srx_phys; | ||
855 | dma_global_data.dma_channel[0] = dma_info->dma_channel[0]; | ||
856 | dma_global_data.dma_channel[1] = dma_info->dma_channel[1]; | ||
857 | dma_global_data.irq[0] = dma_info->dma_irq[0]; | ||
858 | dma_global_data.irq[1] = dma_info->dma_irq[1]; | ||
859 | dma_global_data.assigned[0] = 0; | ||
860 | dma_global_data.assigned[1] = 0; | ||
861 | |||
862 | initialized = 1; | ||
863 | return 1; | ||
864 | } | 930 | } |
865 | EXPORT_SYMBOL_GPL(fsl_dma_configure); | ||
866 | 931 | ||
867 | static int __init fsl_soc_platform_init(void) | 932 | static const struct of_device_id fsl_soc_dma_ids[] = { |
933 | { .compatible = "fsl,ssi-dma-channel", }, | ||
934 | {} | ||
935 | }; | ||
936 | MODULE_DEVICE_TABLE(of, fsl_soc_dma_ids); | ||
937 | |||
938 | static struct of_platform_driver fsl_soc_dma_driver = { | ||
939 | .driver = { | ||
940 | .name = "fsl-pcm-audio", | ||
941 | .owner = THIS_MODULE, | ||
942 | .of_match_table = fsl_soc_dma_ids, | ||
943 | }, | ||
944 | .probe = fsl_soc_dma_probe, | ||
945 | .remove = __devexit_p(fsl_soc_dma_remove), | ||
946 | }; | ||
947 | |||
948 | static int __init fsl_soc_dma_init(void) | ||
868 | { | 949 | { |
869 | return snd_soc_register_platform(&fsl_soc_platform); | 950 | pr_info("Freescale Elo DMA ASoC PCM Driver\n"); |
951 | |||
952 | return of_register_platform_driver(&fsl_soc_dma_driver); | ||
870 | } | 953 | } |
871 | module_init(fsl_soc_platform_init); | ||
872 | 954 | ||
873 | static void __exit fsl_soc_platform_exit(void) | 955 | static void __exit fsl_soc_dma_exit(void) |
874 | { | 956 | { |
875 | snd_soc_unregister_platform(&fsl_soc_platform); | 957 | of_unregister_platform_driver(&fsl_soc_dma_driver); |
876 | } | 958 | } |
877 | module_exit(fsl_soc_platform_exit); | 959 | |
960 | module_init(fsl_soc_dma_init); | ||
961 | module_exit(fsl_soc_dma_exit); | ||
878 | 962 | ||
879 | MODULE_AUTHOR("Timur Tabi <timur@freescale.com>"); | 963 | MODULE_AUTHOR("Timur Tabi <timur@freescale.com>"); |
880 | MODULE_DESCRIPTION("Freescale Elo DMA ASoC PCM module"); | 964 | MODULE_DESCRIPTION("Freescale Elo DMA ASoC PCM Driver"); |
881 | MODULE_LICENSE("GPL"); | 965 | MODULE_LICENSE("GPL v2"); |
diff --git a/sound/soc/fsl/fsl_dma.h b/sound/soc/fsl/fsl_dma.h index 385d4a42603c..78fee97e8036 100644 --- a/sound/soc/fsl/fsl_dma.h +++ b/sound/soc/fsl/fsl_dma.h | |||
@@ -126,24 +126,4 @@ struct fsl_dma_link_descriptor { | |||
126 | u8 res[4]; /* Reserved */ | 126 | u8 res[4]; /* Reserved */ |
127 | } __attribute__ ((aligned(32), packed)); | 127 | } __attribute__ ((aligned(32), packed)); |
128 | 128 | ||
129 | /* DMA information needed to create a snd_soc_dai object | ||
130 | * | ||
131 | * ssi_stx_phys: bus address of SSI STX register to use | ||
132 | * ssi_srx_phys: bus address of SSI SRX register to use | ||
133 | * dma[0]: points to the DMA channel to use for playback | ||
134 | * dma[1]: points to the DMA channel to use for capture | ||
135 | * dma_irq[0]: IRQ of the DMA channel to use for playback | ||
136 | * dma_irq[1]: IRQ of the DMA channel to use for capture | ||
137 | */ | ||
138 | struct fsl_dma_info { | ||
139 | dma_addr_t ssi_stx_phys; | ||
140 | dma_addr_t ssi_srx_phys; | ||
141 | struct ccsr_dma_channel __iomem *dma_channel[2]; | ||
142 | unsigned int dma_irq[2]; | ||
143 | }; | ||
144 | |||
145 | extern struct snd_soc_platform fsl_soc_platform; | ||
146 | |||
147 | int fsl_dma_configure(struct fsl_dma_info *dma_info); | ||
148 | |||
149 | #endif | 129 | #endif |
diff --git a/sound/soc/fsl/fsl_ssi.c b/sound/soc/fsl/fsl_ssi.c index 762c1b8e8e4e..7939c337ed9d 100644 --- a/sound/soc/fsl/fsl_ssi.c +++ b/sound/soc/fsl/fsl_ssi.c | |||
@@ -3,10 +3,11 @@ | |||
3 | * | 3 | * |
4 | * Author: Timur Tabi <timur@freescale.com> | 4 | * Author: Timur Tabi <timur@freescale.com> |
5 | * | 5 | * |
6 | * Copyright 2007-2008 Freescale Semiconductor, Inc. This file is licensed | 6 | * Copyright 2007-2010 Freescale Semiconductor, Inc. |
7 | * under the terms of the GNU General Public License version 2. This | 7 | * |
8 | * program is licensed "as is" without any warranty of any kind, whether | 8 | * This file is licensed under the terms of the GNU General Public License |
9 | * express or implied. | 9 | * version 2. This program is licensed "as is" without any warranty of any |
10 | * kind, whether express or implied. | ||
10 | */ | 11 | */ |
11 | 12 | ||
12 | #include <linux/init.h> | 13 | #include <linux/init.h> |
@@ -15,6 +16,7 @@ | |||
15 | #include <linux/device.h> | 16 | #include <linux/device.h> |
16 | #include <linux/delay.h> | 17 | #include <linux/delay.h> |
17 | #include <linux/slab.h> | 18 | #include <linux/slab.h> |
19 | #include <linux/of_platform.h> | ||
18 | 20 | ||
19 | #include <sound/core.h> | 21 | #include <sound/core.h> |
20 | #include <sound/pcm.h> | 22 | #include <sound/pcm.h> |
@@ -22,8 +24,6 @@ | |||
22 | #include <sound/initval.h> | 24 | #include <sound/initval.h> |
23 | #include <sound/soc.h> | 25 | #include <sound/soc.h> |
24 | 26 | ||
25 | #include <asm/immap_86xx.h> | ||
26 | |||
27 | #include "fsl_ssi.h" | 27 | #include "fsl_ssi.h" |
28 | 28 | ||
29 | /** | 29 | /** |
@@ -71,33 +71,31 @@ | |||
71 | /** | 71 | /** |
72 | * fsl_ssi_private: per-SSI private data | 72 | * fsl_ssi_private: per-SSI private data |
73 | * | 73 | * |
74 | * @name: short name for this device ("SSI0", "SSI1", etc) | ||
75 | * @ssi: pointer to the SSI's registers | 74 | * @ssi: pointer to the SSI's registers |
76 | * @ssi_phys: physical address of the SSI registers | 75 | * @ssi_phys: physical address of the SSI registers |
77 | * @irq: IRQ of this SSI | 76 | * @irq: IRQ of this SSI |
78 | * @first_stream: pointer to the stream that was opened first | 77 | * @first_stream: pointer to the stream that was opened first |
79 | * @second_stream: pointer to second stream | 78 | * @second_stream: pointer to second stream |
80 | * @dev: struct device pointer | ||
81 | * @playback: the number of playback streams opened | 79 | * @playback: the number of playback streams opened |
82 | * @capture: the number of capture streams opened | 80 | * @capture: the number of capture streams opened |
83 | * @asynchronous: 0=synchronous mode, 1=asynchronous mode | 81 | * @asynchronous: 0=synchronous mode, 1=asynchronous mode |
84 | * @cpu_dai: the CPU DAI for this device | 82 | * @cpu_dai: the CPU DAI for this device |
85 | * @dev_attr: the sysfs device attribute structure | 83 | * @dev_attr: the sysfs device attribute structure |
86 | * @stats: SSI statistics | 84 | * @stats: SSI statistics |
85 | * @name: name for this device | ||
87 | */ | 86 | */ |
88 | struct fsl_ssi_private { | 87 | struct fsl_ssi_private { |
89 | char name[8]; | ||
90 | struct ccsr_ssi __iomem *ssi; | 88 | struct ccsr_ssi __iomem *ssi; |
91 | dma_addr_t ssi_phys; | 89 | dma_addr_t ssi_phys; |
92 | unsigned int irq; | 90 | unsigned int irq; |
93 | struct snd_pcm_substream *first_stream; | 91 | struct snd_pcm_substream *first_stream; |
94 | struct snd_pcm_substream *second_stream; | 92 | struct snd_pcm_substream *second_stream; |
95 | struct device *dev; | ||
96 | unsigned int playback; | 93 | unsigned int playback; |
97 | unsigned int capture; | 94 | unsigned int capture; |
98 | int asynchronous; | 95 | int asynchronous; |
99 | struct snd_soc_dai cpu_dai; | 96 | struct snd_soc_dai_driver cpu_dai_drv; |
100 | struct device_attribute dev_attr; | 97 | struct device_attribute dev_attr; |
98 | struct platform_device *pdev; | ||
101 | 99 | ||
102 | struct { | 100 | struct { |
103 | unsigned int rfrc; | 101 | unsigned int rfrc; |
@@ -122,6 +120,8 @@ struct fsl_ssi_private { | |||
122 | unsigned int tfe1; | 120 | unsigned int tfe1; |
123 | unsigned int tfe0; | 121 | unsigned int tfe0; |
124 | } stats; | 122 | } stats; |
123 | |||
124 | char name[1]; | ||
125 | }; | 125 | }; |
126 | 126 | ||
127 | /** | 127 | /** |
@@ -280,7 +280,7 @@ static int fsl_ssi_startup(struct snd_pcm_substream *substream, | |||
280 | struct snd_soc_dai *dai) | 280 | struct snd_soc_dai *dai) |
281 | { | 281 | { |
282 | struct snd_soc_pcm_runtime *rtd = substream->private_data; | 282 | struct snd_soc_pcm_runtime *rtd = substream->private_data; |
283 | struct fsl_ssi_private *ssi_private = rtd->dai->cpu_dai->private_data; | 283 | struct fsl_ssi_private *ssi_private = snd_soc_dai_get_drvdata(rtd->cpu_dai); |
284 | 284 | ||
285 | /* | 285 | /* |
286 | * If this is the first stream opened, then request the IRQ | 286 | * If this is the first stream opened, then request the IRQ |
@@ -290,6 +290,7 @@ static int fsl_ssi_startup(struct snd_pcm_substream *substream, | |||
290 | struct ccsr_ssi __iomem *ssi = ssi_private->ssi; | 290 | struct ccsr_ssi __iomem *ssi = ssi_private->ssi; |
291 | int ret; | 291 | int ret; |
292 | 292 | ||
293 | /* The 'name' should not have any slashes in it. */ | ||
293 | ret = request_irq(ssi_private->irq, fsl_ssi_isr, 0, | 294 | ret = request_irq(ssi_private->irq, fsl_ssi_isr, 0, |
294 | ssi_private->name, ssi_private); | 295 | ssi_private->name, ssi_private); |
295 | if (ret < 0) { | 296 | if (ret < 0) { |
@@ -422,7 +423,7 @@ static int fsl_ssi_startup(struct snd_pcm_substream *substream, | |||
422 | static int fsl_ssi_hw_params(struct snd_pcm_substream *substream, | 423 | static int fsl_ssi_hw_params(struct snd_pcm_substream *substream, |
423 | struct snd_pcm_hw_params *hw_params, struct snd_soc_dai *cpu_dai) | 424 | struct snd_pcm_hw_params *hw_params, struct snd_soc_dai *cpu_dai) |
424 | { | 425 | { |
425 | struct fsl_ssi_private *ssi_private = cpu_dai->private_data; | 426 | struct fsl_ssi_private *ssi_private = snd_soc_dai_get_drvdata(cpu_dai); |
426 | 427 | ||
427 | if (substream == ssi_private->first_stream) { | 428 | if (substream == ssi_private->first_stream) { |
428 | struct ccsr_ssi __iomem *ssi = ssi_private->ssi; | 429 | struct ccsr_ssi __iomem *ssi = ssi_private->ssi; |
@@ -458,7 +459,7 @@ static int fsl_ssi_trigger(struct snd_pcm_substream *substream, int cmd, | |||
458 | struct snd_soc_dai *dai) | 459 | struct snd_soc_dai *dai) |
459 | { | 460 | { |
460 | struct snd_soc_pcm_runtime *rtd = substream->private_data; | 461 | struct snd_soc_pcm_runtime *rtd = substream->private_data; |
461 | struct fsl_ssi_private *ssi_private = rtd->dai->cpu_dai->private_data; | 462 | struct fsl_ssi_private *ssi_private = snd_soc_dai_get_drvdata(rtd->cpu_dai); |
462 | struct ccsr_ssi __iomem *ssi = ssi_private->ssi; | 463 | struct ccsr_ssi __iomem *ssi = ssi_private->ssi; |
463 | 464 | ||
464 | switch (cmd) { | 465 | switch (cmd) { |
@@ -497,7 +498,7 @@ static void fsl_ssi_shutdown(struct snd_pcm_substream *substream, | |||
497 | struct snd_soc_dai *dai) | 498 | struct snd_soc_dai *dai) |
498 | { | 499 | { |
499 | struct snd_soc_pcm_runtime *rtd = substream->private_data; | 500 | struct snd_soc_pcm_runtime *rtd = substream->private_data; |
500 | struct fsl_ssi_private *ssi_private = rtd->dai->cpu_dai->private_data; | 501 | struct fsl_ssi_private *ssi_private = snd_soc_dai_get_drvdata(rtd->cpu_dai); |
501 | 502 | ||
502 | if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) | 503 | if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) |
503 | ssi_private->playback--; | 504 | ssi_private->playback--; |
@@ -523,56 +524,15 @@ static void fsl_ssi_shutdown(struct snd_pcm_substream *substream, | |||
523 | } | 524 | } |
524 | } | 525 | } |
525 | 526 | ||
526 | /** | ||
527 | * fsl_ssi_set_sysclk: set the clock frequency and direction | ||
528 | * | ||
529 | * This function is called by the machine driver to tell us what the clock | ||
530 | * frequency and direction are. | ||
531 | * | ||
532 | * Currently, we only support operating as a clock slave (SND_SOC_CLOCK_IN), | ||
533 | * and we don't care about the frequency. Return an error if the direction | ||
534 | * is not SND_SOC_CLOCK_IN. | ||
535 | * | ||
536 | * @clk_id: reserved, should be zero | ||
537 | * @freq: the frequency of the given clock ID, currently ignored | ||
538 | * @dir: SND_SOC_CLOCK_IN (clock slave) or SND_SOC_CLOCK_OUT (clock master) | ||
539 | */ | ||
540 | static int fsl_ssi_set_sysclk(struct snd_soc_dai *cpu_dai, | ||
541 | int clk_id, unsigned int freq, int dir) | ||
542 | { | ||
543 | |||
544 | return (dir == SND_SOC_CLOCK_IN) ? 0 : -EINVAL; | ||
545 | } | ||
546 | |||
547 | /** | ||
548 | * fsl_ssi_set_fmt: set the serial format. | ||
549 | * | ||
550 | * This function is called by the machine driver to tell us what serial | ||
551 | * format to use. | ||
552 | * | ||
553 | * Currently, we only support I2S mode. Return an error if the format is | ||
554 | * not SND_SOC_DAIFMT_I2S. | ||
555 | * | ||
556 | * @format: one of SND_SOC_DAIFMT_xxx | ||
557 | */ | ||
558 | static int fsl_ssi_set_fmt(struct snd_soc_dai *cpu_dai, unsigned int format) | ||
559 | { | ||
560 | return (format == SND_SOC_DAIFMT_I2S) ? 0 : -EINVAL; | ||
561 | } | ||
562 | |||
563 | /** | ||
564 | * fsl_ssi_dai_template: template CPU DAI for the SSI | ||
565 | */ | ||
566 | static struct snd_soc_dai_ops fsl_ssi_dai_ops = { | 527 | static struct snd_soc_dai_ops fsl_ssi_dai_ops = { |
567 | .startup = fsl_ssi_startup, | 528 | .startup = fsl_ssi_startup, |
568 | .hw_params = fsl_ssi_hw_params, | 529 | .hw_params = fsl_ssi_hw_params, |
569 | .shutdown = fsl_ssi_shutdown, | 530 | .shutdown = fsl_ssi_shutdown, |
570 | .trigger = fsl_ssi_trigger, | 531 | .trigger = fsl_ssi_trigger, |
571 | .set_sysclk = fsl_ssi_set_sysclk, | ||
572 | .set_fmt = fsl_ssi_set_fmt, | ||
573 | }; | 532 | }; |
574 | 533 | ||
575 | static struct snd_soc_dai fsl_ssi_dai_template = { | 534 | /* Template for the CPU dai driver structure */ |
535 | static struct snd_soc_dai_driver fsl_ssi_dai_template = { | ||
576 | .playback = { | 536 | .playback = { |
577 | /* The SSI does not support monaural audio. */ | 537 | /* The SSI does not support monaural audio. */ |
578 | .channels_min = 2, | 538 | .channels_min = 2, |
@@ -640,95 +600,186 @@ static ssize_t fsl_sysfs_ssi_show(struct device *dev, | |||
640 | } | 600 | } |
641 | 601 | ||
642 | /** | 602 | /** |
643 | * fsl_ssi_create_dai: create a snd_soc_dai structure | 603 | * Make every character in a string lower-case |
644 | * | ||
645 | * This function is called by the machine driver to create a snd_soc_dai | ||
646 | * structure. The function creates an ssi_private object, which contains | ||
647 | * the snd_soc_dai. It also creates the sysfs statistics device. | ||
648 | */ | 604 | */ |
649 | struct snd_soc_dai *fsl_ssi_create_dai(struct fsl_ssi_info *ssi_info) | 605 | static void make_lowercase(char *s) |
606 | { | ||
607 | char *p = s; | ||
608 | char c; | ||
609 | |||
610 | while ((c = *p)) { | ||
611 | if ((c >= 'A') && (c <= 'Z')) | ||
612 | *p = c + ('a' - 'A'); | ||
613 | p++; | ||
614 | } | ||
615 | } | ||
616 | |||
617 | static int __devinit fsl_ssi_probe(struct of_device *of_dev, | ||
618 | const struct of_device_id *match) | ||
650 | { | 619 | { |
651 | struct snd_soc_dai *fsl_ssi_dai; | ||
652 | struct fsl_ssi_private *ssi_private; | 620 | struct fsl_ssi_private *ssi_private; |
653 | int ret = 0; | 621 | int ret = 0; |
654 | struct device_attribute *dev_attr; | 622 | struct device_attribute *dev_attr = NULL; |
623 | struct device_node *np = of_dev->dev.of_node; | ||
624 | const char *p, *sprop; | ||
625 | struct resource res; | ||
626 | char name[64]; | ||
627 | |||
628 | /* SSIs that are not connected on the board should have a | ||
629 | * status = "disabled" | ||
630 | * property in their device tree nodes. | ||
631 | */ | ||
632 | if (!of_device_is_available(np)) | ||
633 | return -ENODEV; | ||
634 | |||
635 | /* Check for a codec-handle property. */ | ||
636 | if (!of_get_property(np, "codec-handle", NULL)) { | ||
637 | dev_err(&of_dev->dev, "missing codec-handle property\n"); | ||
638 | return -ENODEV; | ||
639 | } | ||
640 | |||
641 | /* We only support the SSI in "I2S Slave" mode */ | ||
642 | sprop = of_get_property(np, "fsl,mode", NULL); | ||
643 | if (!sprop || strcmp(sprop, "i2s-slave")) { | ||
644 | dev_notice(&of_dev->dev, "mode %s is unsupported\n", sprop); | ||
645 | return -ENODEV; | ||
646 | } | ||
655 | 647 | ||
656 | ssi_private = kzalloc(sizeof(struct fsl_ssi_private), GFP_KERNEL); | 648 | /* The DAI name is the last part of the full name of the node. */ |
649 | p = strrchr(np->full_name, '/') + 1; | ||
650 | ssi_private = kzalloc(sizeof(struct fsl_ssi_private) + strlen(p), | ||
651 | GFP_KERNEL); | ||
657 | if (!ssi_private) { | 652 | if (!ssi_private) { |
658 | dev_err(ssi_info->dev, "could not allocate DAI object\n"); | 653 | dev_err(&of_dev->dev, "could not allocate DAI object\n"); |
659 | return NULL; | 654 | return -ENOMEM; |
660 | } | 655 | } |
661 | memcpy(&ssi_private->cpu_dai, &fsl_ssi_dai_template, | ||
662 | sizeof(struct snd_soc_dai)); | ||
663 | 656 | ||
664 | fsl_ssi_dai = &ssi_private->cpu_dai; | 657 | strcpy(ssi_private->name, p); |
665 | dev_attr = &ssi_private->dev_attr; | ||
666 | 658 | ||
667 | sprintf(ssi_private->name, "ssi%u", (u8) ssi_info->id); | 659 | /* Initialize this copy of the CPU DAI driver structure */ |
668 | ssi_private->ssi = ssi_info->ssi; | 660 | memcpy(&ssi_private->cpu_dai_drv, &fsl_ssi_dai_template, |
669 | ssi_private->ssi_phys = ssi_info->ssi_phys; | 661 | sizeof(fsl_ssi_dai_template)); |
670 | ssi_private->irq = ssi_info->irq; | 662 | ssi_private->cpu_dai_drv.name = ssi_private->name; |
671 | ssi_private->dev = ssi_info->dev; | 663 | |
672 | ssi_private->asynchronous = ssi_info->asynchronous; | 664 | /* Get the addresses and IRQ */ |
665 | ret = of_address_to_resource(np, 0, &res); | ||
666 | if (ret) { | ||
667 | dev_err(&of_dev->dev, "could not determine device resources\n"); | ||
668 | kfree(ssi_private); | ||
669 | return ret; | ||
670 | } | ||
671 | ssi_private->ssi = ioremap(res.start, 1 + res.end - res.start); | ||
672 | ssi_private->ssi_phys = res.start; | ||
673 | ssi_private->irq = irq_of_parse_and_map(np, 0); | ||
673 | 674 | ||
674 | dev_set_drvdata(ssi_private->dev, fsl_ssi_dai); | 675 | /* Are the RX and the TX clocks locked? */ |
676 | if (of_find_property(np, "fsl,ssi-asynchronous", NULL)) | ||
677 | ssi_private->asynchronous = 1; | ||
678 | else | ||
679 | ssi_private->cpu_dai_drv.symmetric_rates = 1; | ||
675 | 680 | ||
676 | /* Initialize the the device_attribute structure */ | 681 | /* Initialize the the device_attribute structure */ |
677 | dev_attr->attr.name = "ssi-stats"; | 682 | dev_attr = &ssi_private->dev_attr; |
683 | dev_attr->attr.name = "statistics"; | ||
678 | dev_attr->attr.mode = S_IRUGO; | 684 | dev_attr->attr.mode = S_IRUGO; |
679 | dev_attr->show = fsl_sysfs_ssi_show; | 685 | dev_attr->show = fsl_sysfs_ssi_show; |
680 | 686 | ||
681 | ret = device_create_file(ssi_private->dev, dev_attr); | 687 | ret = device_create_file(&of_dev->dev, dev_attr); |
682 | if (ret) { | 688 | if (ret) { |
683 | dev_err(ssi_info->dev, "could not create sysfs %s file\n", | 689 | dev_err(&of_dev->dev, "could not create sysfs %s file\n", |
684 | ssi_private->dev_attr.attr.name); | 690 | ssi_private->dev_attr.attr.name); |
685 | kfree(fsl_ssi_dai); | 691 | goto error; |
686 | return NULL; | ||
687 | } | 692 | } |
688 | 693 | ||
689 | fsl_ssi_dai->private_data = ssi_private; | 694 | /* Register with ASoC */ |
690 | fsl_ssi_dai->name = ssi_private->name; | 695 | dev_set_drvdata(&of_dev->dev, ssi_private); |
691 | fsl_ssi_dai->id = ssi_info->id; | 696 | |
692 | fsl_ssi_dai->dev = ssi_info->dev; | 697 | ret = snd_soc_register_dai(&of_dev->dev, &ssi_private->cpu_dai_drv); |
693 | fsl_ssi_dai->symmetric_rates = 1; | 698 | if (ret) { |
699 | dev_err(&of_dev->dev, "failed to register DAI: %d\n", ret); | ||
700 | goto error; | ||
701 | } | ||
694 | 702 | ||
695 | ret = snd_soc_register_dai(fsl_ssi_dai); | 703 | /* Trigger the machine driver's probe function. The platform driver |
696 | if (ret != 0) { | 704 | * name of the machine driver is taken from the /model property of the |
697 | dev_err(ssi_info->dev, "failed to register DAI: %d\n", ret); | 705 | * device tree. We also pass the address of the CPU DAI driver |
698 | kfree(fsl_ssi_dai); | 706 | * structure. |
699 | return NULL; | 707 | */ |
708 | sprop = of_get_property(of_find_node_by_path("/"), "model", NULL); | ||
709 | /* Sometimes the model name has a "fsl," prefix, so we strip that. */ | ||
710 | p = strrchr(sprop, ','); | ||
711 | if (p) | ||
712 | sprop = p + 1; | ||
713 | snprintf(name, sizeof(name), "snd-soc-%s", sprop); | ||
714 | make_lowercase(name); | ||
715 | |||
716 | ssi_private->pdev = | ||
717 | platform_device_register_data(&of_dev->dev, name, 0, NULL, 0); | ||
718 | if (IS_ERR(ssi_private->pdev)) { | ||
719 | ret = PTR_ERR(ssi_private->pdev); | ||
720 | dev_err(&of_dev->dev, "failed to register platform: %d\n", ret); | ||
721 | goto error; | ||
700 | } | 722 | } |
701 | 723 | ||
702 | return fsl_ssi_dai; | 724 | return 0; |
725 | |||
726 | error: | ||
727 | snd_soc_unregister_dai(&of_dev->dev); | ||
728 | dev_set_drvdata(&of_dev->dev, NULL); | ||
729 | if (dev_attr) | ||
730 | device_remove_file(&of_dev->dev, dev_attr); | ||
731 | irq_dispose_mapping(ssi_private->irq); | ||
732 | iounmap(ssi_private->ssi); | ||
733 | kfree(ssi_private); | ||
734 | |||
735 | return ret; | ||
703 | } | 736 | } |
704 | EXPORT_SYMBOL_GPL(fsl_ssi_create_dai); | ||
705 | 737 | ||
706 | /** | 738 | static int fsl_ssi_remove(struct of_device *of_dev) |
707 | * fsl_ssi_destroy_dai: destroy the snd_soc_dai object | ||
708 | * | ||
709 | * This function undoes the operations of fsl_ssi_create_dai() | ||
710 | */ | ||
711 | void fsl_ssi_destroy_dai(struct snd_soc_dai *fsl_ssi_dai) | ||
712 | { | 739 | { |
713 | struct fsl_ssi_private *ssi_private = | 740 | struct fsl_ssi_private *ssi_private = dev_get_drvdata(&of_dev->dev); |
714 | container_of(fsl_ssi_dai, struct fsl_ssi_private, cpu_dai); | ||
715 | |||
716 | device_remove_file(ssi_private->dev, &ssi_private->dev_attr); | ||
717 | 741 | ||
718 | snd_soc_unregister_dai(&ssi_private->cpu_dai); | 742 | platform_device_unregister(ssi_private->pdev); |
743 | snd_soc_unregister_dai(&of_dev->dev); | ||
744 | device_remove_file(&of_dev->dev, &ssi_private->dev_attr); | ||
719 | 745 | ||
720 | kfree(ssi_private); | 746 | kfree(ssi_private); |
747 | dev_set_drvdata(&of_dev->dev, NULL); | ||
748 | |||
749 | return 0; | ||
721 | } | 750 | } |
722 | EXPORT_SYMBOL_GPL(fsl_ssi_destroy_dai); | 751 | |
752 | static const struct of_device_id fsl_ssi_ids[] = { | ||
753 | { .compatible = "fsl,mpc8610-ssi", }, | ||
754 | {} | ||
755 | }; | ||
756 | MODULE_DEVICE_TABLE(of, fsl_ssi_ids); | ||
757 | |||
758 | static struct of_platform_driver fsl_ssi_driver = { | ||
759 | .driver = { | ||
760 | .name = "fsl-ssi-dai", | ||
761 | .owner = THIS_MODULE, | ||
762 | .of_match_table = fsl_ssi_ids, | ||
763 | }, | ||
764 | .probe = fsl_ssi_probe, | ||
765 | .remove = fsl_ssi_remove, | ||
766 | }; | ||
723 | 767 | ||
724 | static int __init fsl_ssi_init(void) | 768 | static int __init fsl_ssi_init(void) |
725 | { | 769 | { |
726 | printk(KERN_INFO "Freescale Synchronous Serial Interface (SSI) ASoC Driver\n"); | 770 | printk(KERN_INFO "Freescale Synchronous Serial Interface (SSI) ASoC Driver\n"); |
727 | 771 | ||
728 | return 0; | 772 | return of_register_platform_driver(&fsl_ssi_driver); |
729 | } | 773 | } |
774 | |||
775 | static void __exit fsl_ssi_exit(void) | ||
776 | { | ||
777 | of_unregister_platform_driver(&fsl_ssi_driver); | ||
778 | } | ||
779 | |||
730 | module_init(fsl_ssi_init); | 780 | module_init(fsl_ssi_init); |
781 | module_exit(fsl_ssi_exit); | ||
731 | 782 | ||
732 | MODULE_AUTHOR("Timur Tabi <timur@freescale.com>"); | 783 | MODULE_AUTHOR("Timur Tabi <timur@freescale.com>"); |
733 | MODULE_DESCRIPTION("Freescale Synchronous Serial Interface (SSI) ASoC Driver"); | 784 | MODULE_DESCRIPTION("Freescale Synchronous Serial Interface (SSI) ASoC Driver"); |
734 | MODULE_LICENSE("GPL"); | 785 | MODULE_LICENSE("GPL v2"); |
diff --git a/sound/soc/fsl/fsl_ssi.h b/sound/soc/fsl/fsl_ssi.h index eade01feaab6..217300029b5b 100644 --- a/sound/soc/fsl/fsl_ssi.h +++ b/sound/soc/fsl/fsl_ssi.h | |||
@@ -196,31 +196,5 @@ struct ccsr_ssi { | |||
196 | #define CCSR_SSI_SOR_WAIT(x) (((x) & 3) << CCSR_SSI_SOR_WAIT_SHIFT) | 196 | #define CCSR_SSI_SOR_WAIT(x) (((x) & 3) << CCSR_SSI_SOR_WAIT_SHIFT) |
197 | #define CCSR_SSI_SOR_SYNRST 0x00000001 | 197 | #define CCSR_SSI_SOR_SYNRST 0x00000001 |
198 | 198 | ||
199 | /* Instantiation data for an SSI interface | ||
200 | * | ||
201 | * This structure contains all the information that the the SSI driver needs | ||
202 | * to instantiate an SSI interface with ALSA. The machine driver should | ||
203 | * create this structure, fill it in, call fsl_ssi_create_dai(), and then | ||
204 | * delete the structure. | ||
205 | * | ||
206 | * id: which SSI this is (0, 1, etc. ) | ||
207 | * ssi: pointer to the SSI's registers | ||
208 | * ssi_phys: physical address of the SSI registers | ||
209 | * irq: IRQ of this SSI | ||
210 | * dev: struct device, used to create the sysfs statistics file | ||
211 | * asynchronous: 0=synchronous mode, 1=asynchronous mode | ||
212 | */ | ||
213 | struct fsl_ssi_info { | ||
214 | unsigned int id; | ||
215 | struct ccsr_ssi __iomem *ssi; | ||
216 | dma_addr_t ssi_phys; | ||
217 | unsigned int irq; | ||
218 | struct device *dev; | ||
219 | int asynchronous; | ||
220 | }; | ||
221 | |||
222 | struct snd_soc_dai *fsl_ssi_create_dai(struct fsl_ssi_info *ssi_info); | ||
223 | void fsl_ssi_destroy_dai(struct snd_soc_dai *fsl_ssi_dai); | ||
224 | |||
225 | #endif | 199 | #endif |
226 | 200 | ||
diff --git a/sound/soc/fsl/mpc5200_dma.c b/sound/soc/fsl/mpc5200_dma.c index 1d4e7164e80a..dce6b551cd78 100644 --- a/sound/soc/fsl/mpc5200_dma.c +++ b/sound/soc/fsl/mpc5200_dma.c | |||
@@ -9,6 +9,8 @@ | |||
9 | #include <linux/module.h> | 9 | #include <linux/module.h> |
10 | #include <linux/of_device.h> | 10 | #include <linux/of_device.h> |
11 | #include <linux/slab.h> | 11 | #include <linux/slab.h> |
12 | #include <linux/of_device.h> | ||
13 | #include <linux/of_platform.h> | ||
12 | 14 | ||
13 | #include <sound/soc.h> | 15 | #include <sound/soc.h> |
14 | 16 | ||
@@ -107,7 +109,7 @@ static int psc_dma_hw_free(struct snd_pcm_substream *substream) | |||
107 | static int psc_dma_trigger(struct snd_pcm_substream *substream, int cmd) | 109 | static int psc_dma_trigger(struct snd_pcm_substream *substream, int cmd) |
108 | { | 110 | { |
109 | struct snd_soc_pcm_runtime *rtd = substream->private_data; | 111 | struct snd_soc_pcm_runtime *rtd = substream->private_data; |
110 | struct psc_dma *psc_dma = rtd->dai->cpu_dai->private_data; | 112 | struct psc_dma *psc_dma = snd_soc_dai_get_drvdata(rtd->cpu_dai); |
111 | struct snd_pcm_runtime *runtime = substream->runtime; | 113 | struct snd_pcm_runtime *runtime = substream->runtime; |
112 | struct psc_dma_stream *s = to_psc_dma_stream(substream, psc_dma); | 114 | struct psc_dma_stream *s = to_psc_dma_stream(substream, psc_dma); |
113 | struct mpc52xx_psc __iomem *regs = psc_dma->psc_regs; | 115 | struct mpc52xx_psc __iomem *regs = psc_dma->psc_regs; |
@@ -212,7 +214,7 @@ static int psc_dma_open(struct snd_pcm_substream *substream) | |||
212 | { | 214 | { |
213 | struct snd_pcm_runtime *runtime = substream->runtime; | 215 | struct snd_pcm_runtime *runtime = substream->runtime; |
214 | struct snd_soc_pcm_runtime *rtd = substream->private_data; | 216 | struct snd_soc_pcm_runtime *rtd = substream->private_data; |
215 | struct psc_dma *psc_dma = rtd->dai->cpu_dai->private_data; | 217 | struct psc_dma *psc_dma = snd_soc_dai_get_drvdata(rtd->cpu_dai); |
216 | struct psc_dma_stream *s; | 218 | struct psc_dma_stream *s; |
217 | int rc; | 219 | int rc; |
218 | 220 | ||
@@ -239,7 +241,7 @@ static int psc_dma_open(struct snd_pcm_substream *substream) | |||
239 | static int psc_dma_close(struct snd_pcm_substream *substream) | 241 | static int psc_dma_close(struct snd_pcm_substream *substream) |
240 | { | 242 | { |
241 | struct snd_soc_pcm_runtime *rtd = substream->private_data; | 243 | struct snd_soc_pcm_runtime *rtd = substream->private_data; |
242 | struct psc_dma *psc_dma = rtd->dai->cpu_dai->private_data; | 244 | struct psc_dma *psc_dma = snd_soc_dai_get_drvdata(rtd->cpu_dai); |
243 | struct psc_dma_stream *s; | 245 | struct psc_dma_stream *s; |
244 | 246 | ||
245 | dev_dbg(psc_dma->dev, "psc_dma_close(substream=%p)\n", substream); | 247 | dev_dbg(psc_dma->dev, "psc_dma_close(substream=%p)\n", substream); |
@@ -264,7 +266,7 @@ static snd_pcm_uframes_t | |||
264 | psc_dma_pointer(struct snd_pcm_substream *substream) | 266 | psc_dma_pointer(struct snd_pcm_substream *substream) |
265 | { | 267 | { |
266 | struct snd_soc_pcm_runtime *rtd = substream->private_data; | 268 | struct snd_soc_pcm_runtime *rtd = substream->private_data; |
267 | struct psc_dma *psc_dma = rtd->dai->cpu_dai->private_data; | 269 | struct psc_dma *psc_dma = snd_soc_dai_get_drvdata(rtd->cpu_dai); |
268 | struct psc_dma_stream *s; | 270 | struct psc_dma_stream *s; |
269 | dma_addr_t count; | 271 | dma_addr_t count; |
270 | 272 | ||
@@ -302,11 +304,11 @@ static int psc_dma_new(struct snd_card *card, struct snd_soc_dai *dai, | |||
302 | struct snd_pcm *pcm) | 304 | struct snd_pcm *pcm) |
303 | { | 305 | { |
304 | struct snd_soc_pcm_runtime *rtd = pcm->private_data; | 306 | struct snd_soc_pcm_runtime *rtd = pcm->private_data; |
305 | struct psc_dma *psc_dma = rtd->dai->cpu_dai->private_data; | 307 | struct psc_dma *psc_dma = snd_soc_dai_get_drvdata(rtd->cpu_dai); |
306 | size_t size = psc_dma_hardware.buffer_bytes_max; | 308 | size_t size = psc_dma_hardware.buffer_bytes_max; |
307 | int rc = 0; | 309 | int rc = 0; |
308 | 310 | ||
309 | dev_dbg(rtd->socdev->dev, "psc_dma_new(card=%p, dai=%p, pcm=%p)\n", | 311 | dev_dbg(rtd->platform->dev, "psc_dma_new(card=%p, dai=%p, pcm=%p)\n", |
310 | card, dai, pcm); | 312 | card, dai, pcm); |
311 | 313 | ||
312 | if (!card->dev->dma_mask) | 314 | if (!card->dev->dma_mask) |
@@ -328,8 +330,8 @@ static int psc_dma_new(struct snd_card *card, struct snd_soc_dai *dai, | |||
328 | goto capture_alloc_err; | 330 | goto capture_alloc_err; |
329 | } | 331 | } |
330 | 332 | ||
331 | if (rtd->socdev->card->codec->ac97) | 333 | if (rtd->codec->ac97) |
332 | rtd->socdev->card->codec->ac97->private_data = psc_dma; | 334 | rtd->codec->ac97->private_data = psc_dma; |
333 | 335 | ||
334 | return 0; | 336 | return 0; |
335 | 337 | ||
@@ -349,7 +351,7 @@ static void psc_dma_free(struct snd_pcm *pcm) | |||
349 | struct snd_pcm_substream *substream; | 351 | struct snd_pcm_substream *substream; |
350 | int stream; | 352 | int stream; |
351 | 353 | ||
352 | dev_dbg(rtd->socdev->dev, "psc_dma_free(pcm=%p)\n", pcm); | 354 | dev_dbg(rtd->platform->dev, "psc_dma_free(pcm=%p)\n", pcm); |
353 | 355 | ||
354 | for (stream = 0; stream < 2; stream++) { | 356 | for (stream = 0; stream < 2; stream++) { |
355 | substream = pcm->streams[stream].substream; | 357 | substream = pcm->streams[stream].substream; |
@@ -361,15 +363,14 @@ static void psc_dma_free(struct snd_pcm *pcm) | |||
361 | } | 363 | } |
362 | } | 364 | } |
363 | 365 | ||
364 | struct snd_soc_platform mpc5200_audio_dma_platform = { | 366 | static struct snd_soc_platform_driver mpc5200_audio_dma_platform = { |
365 | .name = "mpc5200-psc-audio", | 367 | .ops = &psc_dma_ops, |
366 | .pcm_ops = &psc_dma_ops, | ||
367 | .pcm_new = &psc_dma_new, | 368 | .pcm_new = &psc_dma_new, |
368 | .pcm_free = &psc_dma_free, | 369 | .pcm_free = &psc_dma_free, |
369 | }; | 370 | }; |
370 | EXPORT_SYMBOL_GPL(mpc5200_audio_dma_platform); | ||
371 | 371 | ||
372 | int mpc5200_audio_dma_create(struct of_device *op) | 372 | static int mpc5200_hpcd_probe(struct of_device *op, |
373 | const struct of_device_id *match) | ||
373 | { | 374 | { |
374 | phys_addr_t fifo; | 375 | phys_addr_t fifo; |
375 | struct psc_dma *psc_dma; | 376 | struct psc_dma *psc_dma; |
@@ -475,7 +476,7 @@ int mpc5200_audio_dma_create(struct of_device *op) | |||
475 | dev_set_drvdata(&op->dev, psc_dma); | 476 | dev_set_drvdata(&op->dev, psc_dma); |
476 | 477 | ||
477 | /* Tell the ASoC OF helpers about it */ | 478 | /* Tell the ASoC OF helpers about it */ |
478 | return snd_soc_register_platform(&mpc5200_audio_dma_platform); | 479 | return snd_soc_register_platform(&op->dev, &mpc5200_audio_dma_platform); |
479 | out_irq: | 480 | out_irq: |
480 | free_irq(psc_dma->irq, psc_dma); | 481 | free_irq(psc_dma->irq, psc_dma); |
481 | free_irq(psc_dma->capture.irq, &psc_dma->capture); | 482 | free_irq(psc_dma->capture.irq, &psc_dma->capture); |
@@ -486,15 +487,14 @@ out_unmap: | |||
486 | iounmap(regs); | 487 | iounmap(regs); |
487 | return ret; | 488 | return ret; |
488 | } | 489 | } |
489 | EXPORT_SYMBOL_GPL(mpc5200_audio_dma_create); | ||
490 | 490 | ||
491 | int mpc5200_audio_dma_destroy(struct of_device *op) | 491 | static int mpc5200_hpcd_remove(struct of_device *op) |
492 | { | 492 | { |
493 | struct psc_dma *psc_dma = dev_get_drvdata(&op->dev); | 493 | struct psc_dma *psc_dma = dev_get_drvdata(&op->dev); |
494 | 494 | ||
495 | dev_dbg(&op->dev, "mpc5200_audio_dma_destroy()\n"); | 495 | dev_dbg(&op->dev, "mpc5200_audio_dma_destroy()\n"); |
496 | 496 | ||
497 | snd_soc_unregister_platform(&mpc5200_audio_dma_platform); | 497 | snd_soc_unregister_platform(&op->dev); |
498 | 498 | ||
499 | bcom_gen_bd_rx_release(psc_dma->capture.bcom_task); | 499 | bcom_gen_bd_rx_release(psc_dma->capture.bcom_task); |
500 | bcom_gen_bd_tx_release(psc_dma->playback.bcom_task); | 500 | bcom_gen_bd_tx_release(psc_dma->playback.bcom_task); |
@@ -510,7 +510,35 @@ int mpc5200_audio_dma_destroy(struct of_device *op) | |||
510 | 510 | ||
511 | return 0; | 511 | return 0; |
512 | } | 512 | } |
513 | EXPORT_SYMBOL_GPL(mpc5200_audio_dma_destroy); | 513 | |
514 | static struct of_device_id mpc5200_hpcd_match[] = { | ||
515 | { | ||
516 | .compatible = "fsl,mpc5200-pcm", | ||
517 | }, | ||
518 | {} | ||
519 | }; | ||
520 | MODULE_DEVICE_TABLE(of, mpc5200_hpcd_match); | ||
521 | |||
522 | static struct of_platform_driver mpc5200_hpcd_of_driver = { | ||
523 | .owner = THIS_MODULE, | ||
524 | .name = "mpc5200-pcm-audio", | ||
525 | .match_table = mpc5200_hpcd_match, | ||
526 | .probe = mpc5200_hpcd_probe, | ||
527 | .remove = mpc5200_hpcd_remove, | ||
528 | }; | ||
529 | |||
530 | static int __init mpc5200_hpcd_init(void) | ||
531 | { | ||
532 | return of_register_platform_driver(&mpc5200_hpcd_of_driver); | ||
533 | } | ||
534 | |||
535 | static void __exit mpc5200_hpcd_exit(void) | ||
536 | { | ||
537 | of_unregister_platform_driver(&mpc5200_hpcd_of_driver); | ||
538 | } | ||
539 | |||
540 | module_init(mpc5200_hpcd_init); | ||
541 | module_exit(mpc5200_hpcd_exit); | ||
514 | 542 | ||
515 | MODULE_AUTHOR("Grant Likely <grant.likely@secretlab.ca>"); | 543 | MODULE_AUTHOR("Grant Likely <grant.likely@secretlab.ca>"); |
516 | MODULE_DESCRIPTION("Freescale MPC5200 PSC in DMA mode ASoC Driver"); | 544 | MODULE_DESCRIPTION("Freescale MPC5200 PSC in DMA mode ASoC Driver"); |
diff --git a/sound/soc/fsl/mpc5200_dma.h b/sound/soc/fsl/mpc5200_dma.h index 22208b373fb9..7472531bc2a4 100644 --- a/sound/soc/fsl/mpc5200_dma.h +++ b/sound/soc/fsl/mpc5200_dma.h | |||
@@ -81,9 +81,4 @@ to_psc_dma_stream(struct snd_pcm_substream *substream, struct psc_dma *psc_dma) | |||
81 | return &psc_dma->playback; | 81 | return &psc_dma->playback; |
82 | } | 82 | } |
83 | 83 | ||
84 | int mpc5200_audio_dma_create(struct of_device *op); | ||
85 | int mpc5200_audio_dma_destroy(struct of_device *op); | ||
86 | |||
87 | extern struct snd_soc_platform mpc5200_audio_dma_platform; | ||
88 | |||
89 | #endif /* __SOUND_SOC_FSL_MPC5200_DMA_H__ */ | 84 | #endif /* __SOUND_SOC_FSL_MPC5200_DMA_H__ */ |
diff --git a/sound/soc/fsl/mpc5200_psc_ac97.c b/sound/soc/fsl/mpc5200_psc_ac97.c index e2ee220bfb7e..11706c128c08 100644 --- a/sound/soc/fsl/mpc5200_psc_ac97.c +++ b/sound/soc/fsl/mpc5200_psc_ac97.c | |||
@@ -129,7 +129,7 @@ static int psc_ac97_hw_analog_params(struct snd_pcm_substream *substream, | |||
129 | struct snd_pcm_hw_params *params, | 129 | struct snd_pcm_hw_params *params, |
130 | struct snd_soc_dai *cpu_dai) | 130 | struct snd_soc_dai *cpu_dai) |
131 | { | 131 | { |
132 | struct psc_dma *psc_dma = cpu_dai->private_data; | 132 | struct psc_dma *psc_dma = snd_soc_dai_get_drvdata(cpu_dai); |
133 | struct psc_dma_stream *s = to_psc_dma_stream(substream, psc_dma); | 133 | struct psc_dma_stream *s = to_psc_dma_stream(substream, psc_dma); |
134 | 134 | ||
135 | dev_dbg(psc_dma->dev, "%s(substream=%p) p_size=%i p_bytes=%i" | 135 | dev_dbg(psc_dma->dev, "%s(substream=%p) p_size=%i p_bytes=%i" |
@@ -152,7 +152,7 @@ static int psc_ac97_hw_digital_params(struct snd_pcm_substream *substream, | |||
152 | struct snd_pcm_hw_params *params, | 152 | struct snd_pcm_hw_params *params, |
153 | struct snd_soc_dai *cpu_dai) | 153 | struct snd_soc_dai *cpu_dai) |
154 | { | 154 | { |
155 | struct psc_dma *psc_dma = cpu_dai->private_data; | 155 | struct psc_dma *psc_dma = snd_soc_dai_get_drvdata(cpu_dai); |
156 | 156 | ||
157 | dev_dbg(psc_dma->dev, "%s(substream=%p)\n", __func__, substream); | 157 | dev_dbg(psc_dma->dev, "%s(substream=%p)\n", __func__, substream); |
158 | 158 | ||
@@ -167,8 +167,7 @@ static int psc_ac97_hw_digital_params(struct snd_pcm_substream *substream, | |||
167 | static int psc_ac97_trigger(struct snd_pcm_substream *substream, int cmd, | 167 | static int psc_ac97_trigger(struct snd_pcm_substream *substream, int cmd, |
168 | struct snd_soc_dai *dai) | 168 | struct snd_soc_dai *dai) |
169 | { | 169 | { |
170 | struct snd_soc_pcm_runtime *rtd = substream->private_data; | 170 | struct psc_dma *psc_dma = snd_soc_dai_get_drvdata(dai); |
171 | struct psc_dma *psc_dma = rtd->dai->cpu_dai->private_data; | ||
172 | struct psc_dma_stream *s = to_psc_dma_stream(substream, psc_dma); | 171 | struct psc_dma_stream *s = to_psc_dma_stream(substream, psc_dma); |
173 | 172 | ||
174 | switch (cmd) { | 173 | switch (cmd) { |
@@ -193,10 +192,9 @@ static int psc_ac97_trigger(struct snd_pcm_substream *substream, int cmd, | |||
193 | return 0; | 192 | return 0; |
194 | } | 193 | } |
195 | 194 | ||
196 | static int psc_ac97_probe(struct platform_device *pdev, | 195 | static int psc_ac97_probe(struct snd_soc_dai *cpu_dai) |
197 | struct snd_soc_dai *cpu_dai) | ||
198 | { | 196 | { |
199 | struct psc_dma *psc_dma = cpu_dai->private_data; | 197 | struct psc_dma *psc_dma = snd_soc_dai_get_drvdata(cpu_dai); |
200 | struct mpc52xx_psc __iomem *regs = psc_dma->psc_regs; | 198 | struct mpc52xx_psc __iomem *regs = psc_dma->psc_regs; |
201 | 199 | ||
202 | /* Go */ | 200 | /* Go */ |
@@ -223,9 +221,8 @@ static struct snd_soc_dai_ops psc_ac97_digital_ops = { | |||
223 | .hw_params = psc_ac97_hw_digital_params, | 221 | .hw_params = psc_ac97_hw_digital_params, |
224 | }; | 222 | }; |
225 | 223 | ||
226 | struct snd_soc_dai psc_ac97_dai[] = { | 224 | static struct snd_soc_dai_driver psc_ac97_dai[] = { |
227 | { | 225 | { |
228 | .name = "AC97", | ||
229 | .ac97_control = 1, | 226 | .ac97_control = 1, |
230 | .probe = psc_ac97_probe, | 227 | .probe = psc_ac97_probe, |
231 | .playback = { | 228 | .playback = { |
@@ -243,7 +240,6 @@ struct snd_soc_dai psc_ac97_dai[] = { | |||
243 | .ops = &psc_ac97_analog_ops, | 240 | .ops = &psc_ac97_analog_ops, |
244 | }, | 241 | }, |
245 | { | 242 | { |
246 | .name = "SPDIF", | ||
247 | .ac97_control = 1, | 243 | .ac97_control = 1, |
248 | .playback = { | 244 | .playback = { |
249 | .channels_min = 1, | 245 | .channels_min = 1, |
@@ -254,7 +250,6 @@ struct snd_soc_dai psc_ac97_dai[] = { | |||
254 | }, | 250 | }, |
255 | .ops = &psc_ac97_digital_ops, | 251 | .ops = &psc_ac97_digital_ops, |
256 | } }; | 252 | } }; |
257 | EXPORT_SYMBOL_GPL(psc_ac97_dai); | ||
258 | 253 | ||
259 | 254 | ||
260 | 255 | ||
@@ -266,18 +261,11 @@ EXPORT_SYMBOL_GPL(psc_ac97_dai); | |||
266 | static int __devinit psc_ac97_of_probe(struct of_device *op, | 261 | static int __devinit psc_ac97_of_probe(struct of_device *op, |
267 | const struct of_device_id *match) | 262 | const struct of_device_id *match) |
268 | { | 263 | { |
269 | int rc, i; | 264 | int rc; |
270 | struct snd_ac97 ac97; | 265 | struct snd_ac97 ac97; |
271 | struct mpc52xx_psc __iomem *regs; | 266 | struct mpc52xx_psc __iomem *regs; |
272 | 267 | ||
273 | rc = mpc5200_audio_dma_create(op); | 268 | rc = snd_soc_register_dais(&op->dev, psc_ac97_dai, ARRAY_SIZE(psc_ac97_dai)); |
274 | if (rc != 0) | ||
275 | return rc; | ||
276 | |||
277 | for (i = 0; i < ARRAY_SIZE(psc_ac97_dai); i++) | ||
278 | psc_ac97_dai[i].dev = &op->dev; | ||
279 | |||
280 | rc = snd_soc_register_dais(psc_ac97_dai, ARRAY_SIZE(psc_ac97_dai)); | ||
281 | if (rc != 0) { | 269 | if (rc != 0) { |
282 | dev_err(&op->dev, "Failed to register DAI\n"); | 270 | dev_err(&op->dev, "Failed to register DAI\n"); |
283 | return rc; | 271 | return rc; |
@@ -287,9 +275,6 @@ static int __devinit psc_ac97_of_probe(struct of_device *op, | |||
287 | regs = psc_dma->psc_regs; | 275 | regs = psc_dma->psc_regs; |
288 | ac97.private_data = psc_dma; | 276 | ac97.private_data = psc_dma; |
289 | 277 | ||
290 | for (i = 0; i < ARRAY_SIZE(psc_ac97_dai); i++) | ||
291 | psc_ac97_dai[i].private_data = psc_dma; | ||
292 | |||
293 | psc_dma->imr = 0; | 278 | psc_dma->imr = 0; |
294 | out_be16(&psc_dma->psc_regs->isr_imr.imr, psc_dma->imr); | 279 | out_be16(&psc_dma->psc_regs->isr_imr.imr, psc_dma->imr); |
295 | 280 | ||
@@ -305,7 +290,8 @@ static int __devinit psc_ac97_of_probe(struct of_device *op, | |||
305 | 290 | ||
306 | static int __devexit psc_ac97_of_remove(struct of_device *op) | 291 | static int __devexit psc_ac97_of_remove(struct of_device *op) |
307 | { | 292 | { |
308 | return mpc5200_audio_dma_destroy(op); | 293 | snd_soc_unregister_dais(&op->dev, ARRAY_SIZE(psc_ac97_dai)); |
294 | return 0; | ||
309 | } | 295 | } |
310 | 296 | ||
311 | /* Match table for of_platform binding */ | 297 | /* Match table for of_platform binding */ |
diff --git a/sound/soc/fsl/mpc5200_psc_ac97.h b/sound/soc/fsl/mpc5200_psc_ac97.h index 4bc18c35c369..e881e784b270 100644 --- a/sound/soc/fsl/mpc5200_psc_ac97.h +++ b/sound/soc/fsl/mpc5200_psc_ac97.h | |||
@@ -7,8 +7,6 @@ | |||
7 | #ifndef __SOUND_SOC_FSL_MPC52xx_PSC_AC97_H__ | 7 | #ifndef __SOUND_SOC_FSL_MPC52xx_PSC_AC97_H__ |
8 | #define __SOUND_SOC_FSL_MPC52xx_PSC_AC97_H__ | 8 | #define __SOUND_SOC_FSL_MPC52xx_PSC_AC97_H__ |
9 | 9 | ||
10 | extern struct snd_soc_dai psc_ac97_dai[]; | ||
11 | |||
12 | #define MPC5200_AC97_NORMAL 0 | 10 | #define MPC5200_AC97_NORMAL 0 |
13 | #define MPC5200_AC97_SPDIF 1 | 11 | #define MPC5200_AC97_SPDIF 1 |
14 | 12 | ||
diff --git a/sound/soc/fsl/mpc5200_psc_i2s.c b/sound/soc/fsl/mpc5200_psc_i2s.c index 676841cbae98..5b9f2c73f031 100644 --- a/sound/soc/fsl/mpc5200_psc_i2s.c +++ b/sound/soc/fsl/mpc5200_psc_i2s.c | |||
@@ -40,7 +40,7 @@ static int psc_i2s_hw_params(struct snd_pcm_substream *substream, | |||
40 | struct snd_soc_dai *dai) | 40 | struct snd_soc_dai *dai) |
41 | { | 41 | { |
42 | struct snd_soc_pcm_runtime *rtd = substream->private_data; | 42 | struct snd_soc_pcm_runtime *rtd = substream->private_data; |
43 | struct psc_dma *psc_dma = rtd->dai->cpu_dai->private_data; | 43 | struct psc_dma *psc_dma = snd_soc_dai_get_drvdata(rtd->cpu_dai); |
44 | u32 mode; | 44 | u32 mode; |
45 | 45 | ||
46 | dev_dbg(psc_dma->dev, "%s(substream=%p) p_size=%i p_bytes=%i" | 46 | dev_dbg(psc_dma->dev, "%s(substream=%p) p_size=%i p_bytes=%i" |
@@ -88,7 +88,7 @@ static int psc_i2s_hw_params(struct snd_pcm_substream *substream, | |||
88 | static int psc_i2s_set_sysclk(struct snd_soc_dai *cpu_dai, | 88 | static int psc_i2s_set_sysclk(struct snd_soc_dai *cpu_dai, |
89 | int clk_id, unsigned int freq, int dir) | 89 | int clk_id, unsigned int freq, int dir) |
90 | { | 90 | { |
91 | struct psc_dma *psc_dma = cpu_dai->private_data; | 91 | struct psc_dma *psc_dma = snd_soc_dai_get_drvdata(cpu_dai); |
92 | dev_dbg(psc_dma->dev, "psc_i2s_set_sysclk(cpu_dai=%p, dir=%i)\n", | 92 | dev_dbg(psc_dma->dev, "psc_i2s_set_sysclk(cpu_dai=%p, dir=%i)\n", |
93 | cpu_dai, dir); | 93 | cpu_dai, dir); |
94 | return (dir == SND_SOC_CLOCK_IN) ? 0 : -EINVAL; | 94 | return (dir == SND_SOC_CLOCK_IN) ? 0 : -EINVAL; |
@@ -107,7 +107,7 @@ static int psc_i2s_set_sysclk(struct snd_soc_dai *cpu_dai, | |||
107 | */ | 107 | */ |
108 | static int psc_i2s_set_fmt(struct snd_soc_dai *cpu_dai, unsigned int format) | 108 | static int psc_i2s_set_fmt(struct snd_soc_dai *cpu_dai, unsigned int format) |
109 | { | 109 | { |
110 | struct psc_dma *psc_dma = cpu_dai->private_data; | 110 | struct psc_dma *psc_dma = snd_soc_dai_get_drvdata(cpu_dai); |
111 | dev_dbg(psc_dma->dev, "psc_i2s_set_fmt(cpu_dai=%p, format=%i)\n", | 111 | dev_dbg(psc_dma->dev, "psc_i2s_set_fmt(cpu_dai=%p, format=%i)\n", |
112 | cpu_dai, format); | 112 | cpu_dai, format); |
113 | return (format == SND_SOC_DAIFMT_I2S) ? 0 : -EINVAL; | 113 | return (format == SND_SOC_DAIFMT_I2S) ? 0 : -EINVAL; |
@@ -129,8 +129,7 @@ static struct snd_soc_dai_ops psc_i2s_dai_ops = { | |||
129 | .set_fmt = psc_i2s_set_fmt, | 129 | .set_fmt = psc_i2s_set_fmt, |
130 | }; | 130 | }; |
131 | 131 | ||
132 | struct snd_soc_dai psc_i2s_dai[] = {{ | 132 | static struct snd_soc_dai_driver psc_i2s_dai[] = {{ |
133 | .name = "I2S", | ||
134 | .playback = { | 133 | .playback = { |
135 | .channels_min = 2, | 134 | .channels_min = 2, |
136 | .channels_max = 2, | 135 | .channels_max = 2, |
@@ -145,7 +144,6 @@ struct snd_soc_dai psc_i2s_dai[] = {{ | |||
145 | }, | 144 | }, |
146 | .ops = &psc_i2s_dai_ops, | 145 | .ops = &psc_i2s_dai_ops, |
147 | } }; | 146 | } }; |
148 | EXPORT_SYMBOL_GPL(psc_i2s_dai); | ||
149 | 147 | ||
150 | /* --------------------------------------------------------------------- | 148 | /* --------------------------------------------------------------------- |
151 | * OF platform bus binding code: | 149 | * OF platform bus binding code: |
@@ -159,11 +157,7 @@ static int __devinit psc_i2s_of_probe(struct of_device *op, | |||
159 | struct psc_dma *psc_dma; | 157 | struct psc_dma *psc_dma; |
160 | struct mpc52xx_psc __iomem *regs; | 158 | struct mpc52xx_psc __iomem *regs; |
161 | 159 | ||
162 | rc = mpc5200_audio_dma_create(op); | 160 | rc = snd_soc_register_dais(&op->dev, psc_i2s_dai, ARRAY_SIZE(psc_i2s_dai)); |
163 | if (rc != 0) | ||
164 | return rc; | ||
165 | |||
166 | rc = snd_soc_register_dais(psc_i2s_dai, ARRAY_SIZE(psc_i2s_dai)); | ||
167 | if (rc != 0) { | 161 | if (rc != 0) { |
168 | pr_err("Failed to register DAI\n"); | 162 | pr_err("Failed to register DAI\n"); |
169 | return 0; | 163 | return 0; |
@@ -207,7 +201,8 @@ static int __devinit psc_i2s_of_probe(struct of_device *op, | |||
207 | 201 | ||
208 | static int __devexit psc_i2s_of_remove(struct of_device *op) | 202 | static int __devexit psc_i2s_of_remove(struct of_device *op) |
209 | { | 203 | { |
210 | return mpc5200_audio_dma_destroy(op); | 204 | snd_soc_unregister_dais(&op->dev, ARRAY_SIZE(psc_i2s_dai)); |
205 | return 0; | ||
211 | } | 206 | } |
212 | 207 | ||
213 | /* Match table for of_platform binding */ | 208 | /* Match table for of_platform binding */ |
diff --git a/sound/soc/fsl/mpc8610_hpcd.c b/sound/soc/fsl/mpc8610_hpcd.c index 6a2764ee8203..38339c158ed9 100644 --- a/sound/soc/fsl/mpc8610_hpcd.c +++ b/sound/soc/fsl/mpc8610_hpcd.c | |||
@@ -1,85 +1,96 @@ | |||
1 | /** | 1 | /** |
2 | * Freescale MPC8610HPCD ALSA SoC Fabric driver | 2 | * Freescale MPC8610HPCD ALSA SoC Machine driver |
3 | * | 3 | * |
4 | * Author: Timur Tabi <timur@freescale.com> | 4 | * Author: Timur Tabi <timur@freescale.com> |
5 | * | 5 | * |
6 | * Copyright 2007-2008 Freescale Semiconductor, Inc. This file is licensed | 6 | * Copyright 2007-2010 Freescale Semiconductor, Inc. |
7 | * under the terms of the GNU General Public License version 2. This | 7 | * |
8 | * program is licensed "as is" without any warranty of any kind, whether | 8 | * This file is licensed under the terms of the GNU General Public License |
9 | * express or implied. | 9 | * version 2. This program is licensed "as is" without any warranty of any |
10 | * kind, whether express or implied. | ||
10 | */ | 11 | */ |
11 | 12 | ||
12 | #include <linux/slab.h> | ||
13 | #include <linux/module.h> | 13 | #include <linux/module.h> |
14 | #include <linux/interrupt.h> | 14 | #include <linux/interrupt.h> |
15 | #include <linux/of_device.h> | 15 | #include <linux/of_device.h> |
16 | #include <linux/of_platform.h> | ||
17 | #include <sound/soc.h> | 16 | #include <sound/soc.h> |
18 | #include <asm/immap_86xx.h> | 17 | #include <asm/fsl_guts.h> |
19 | 18 | ||
20 | #include "../codecs/cs4270.h" | ||
21 | #include "fsl_dma.h" | 19 | #include "fsl_dma.h" |
22 | #include "fsl_ssi.h" | 20 | #include "fsl_ssi.h" |
23 | 21 | ||
22 | /* There's only one global utilities register */ | ||
23 | static phys_addr_t guts_phys; | ||
24 | |||
25 | #define DAI_NAME_SIZE 32 | ||
26 | |||
24 | /** | 27 | /** |
25 | * mpc8610_hpcd_data: fabric-specific ASoC device data | 28 | * mpc8610_hpcd_data: machine-specific ASoC device data |
26 | * | 29 | * |
27 | * This structure contains data for a single sound platform device on an | 30 | * This structure contains data for a single sound platform device on an |
28 | * MPC8610 HPCD. Some of the data is taken from the device tree. | 31 | * MPC8610 HPCD. Some of the data is taken from the device tree. |
29 | */ | 32 | */ |
30 | struct mpc8610_hpcd_data { | 33 | struct mpc8610_hpcd_data { |
31 | struct snd_soc_device sound_devdata; | 34 | struct snd_soc_dai_link dai[2]; |
32 | struct snd_soc_dai_link dai; | 35 | struct snd_soc_card card; |
33 | struct snd_soc_card machine; | ||
34 | unsigned int dai_format; | 36 | unsigned int dai_format; |
35 | unsigned int codec_clk_direction; | 37 | unsigned int codec_clk_direction; |
36 | unsigned int cpu_clk_direction; | 38 | unsigned int cpu_clk_direction; |
37 | unsigned int clk_frequency; | 39 | unsigned int clk_frequency; |
38 | struct ccsr_guts __iomem *guts; | 40 | unsigned int ssi_id; /* 0 = SSI1, 1 = SSI2, etc */ |
39 | struct ccsr_ssi __iomem *ssi; | 41 | unsigned int dma_id[2]; /* 0 = DMA1, 1 = DMA2, etc */ |
40 | unsigned int ssi_id; /* 0 = SSI1, 1 = SSI2, etc */ | ||
41 | unsigned int ssi_irq; | ||
42 | unsigned int dma_id; /* 0 = DMA1, 1 = DMA2, etc */ | ||
43 | unsigned int dma_irq[2]; | ||
44 | struct ccsr_dma_channel __iomem *dma[2]; | ||
45 | unsigned int dma_channel_id[2]; /* 0 = ch 0, 1 = ch 1, etc*/ | 42 | unsigned int dma_channel_id[2]; /* 0 = ch 0, 1 = ch 1, etc*/ |
43 | char codec_dai_name[DAI_NAME_SIZE]; | ||
44 | char codec_name[DAI_NAME_SIZE]; | ||
45 | char platform_name[2][DAI_NAME_SIZE]; /* One for each DMA channel */ | ||
46 | }; | 46 | }; |
47 | 47 | ||
48 | /** | 48 | /** |
49 | * mpc8610_hpcd_machine_probe: initalize the board | 49 | * mpc8610_hpcd_machine_probe: initialize the board |
50 | * | 50 | * |
51 | * This function is called when platform_device_add() is called. It is used | 51 | * This function is used to initialize the board-specific hardware. |
52 | * to initialize the board-specific hardware. | ||
53 | * | 52 | * |
54 | * Here we program the DMACR and PMUXCR registers. | 53 | * Here we program the DMACR and PMUXCR registers. |
55 | */ | 54 | */ |
56 | static int mpc8610_hpcd_machine_probe(struct platform_device *sound_device) | 55 | static int mpc8610_hpcd_machine_probe(struct platform_device *sound_device) |
57 | { | 56 | { |
57 | struct snd_soc_card *card = platform_get_drvdata(sound_device); | ||
58 | struct mpc8610_hpcd_data *machine_data = | 58 | struct mpc8610_hpcd_data *machine_data = |
59 | sound_device->dev.platform_data; | 59 | container_of(card, struct mpc8610_hpcd_data, card); |
60 | struct ccsr_guts_86xx __iomem *guts; | ||
60 | 61 | ||
61 | /* Program the signal routing between the SSI and the DMA */ | 62 | guts = ioremap(guts_phys, sizeof(struct ccsr_guts_86xx)); |
62 | guts_set_dmacr(machine_data->guts, machine_data->dma_id, | 63 | if (!guts) { |
63 | machine_data->dma_channel_id[0], CCSR_GUTS_DMACR_DEV_SSI); | 64 | dev_err(card->dev, "could not map global utilities\n"); |
64 | guts_set_dmacr(machine_data->guts, machine_data->dma_id, | 65 | return -ENOMEM; |
65 | machine_data->dma_channel_id[1], CCSR_GUTS_DMACR_DEV_SSI); | 66 | } |
66 | 67 | ||
67 | guts_set_pmuxcr_dma(machine_data->guts, machine_data->dma_id, | 68 | /* Program the signal routing between the SSI and the DMA */ |
68 | machine_data->dma_channel_id[0], 0); | 69 | guts_set_dmacr(guts, machine_data->dma_id[0], |
69 | guts_set_pmuxcr_dma(machine_data->guts, machine_data->dma_id, | 70 | machine_data->dma_channel_id[0], |
70 | machine_data->dma_channel_id[1], 0); | 71 | CCSR_GUTS_DMACR_DEV_SSI); |
72 | guts_set_dmacr(guts, machine_data->dma_id[1], | ||
73 | machine_data->dma_channel_id[1], | ||
74 | CCSR_GUTS_DMACR_DEV_SSI); | ||
75 | |||
76 | guts_set_pmuxcr_dma(guts, machine_data->dma_id[0], | ||
77 | machine_data->dma_channel_id[0], 0); | ||
78 | guts_set_pmuxcr_dma(guts, machine_data->dma_id[1], | ||
79 | machine_data->dma_channel_id[1], 0); | ||
71 | 80 | ||
72 | switch (machine_data->ssi_id) { | 81 | switch (machine_data->ssi_id) { |
73 | case 0: | 82 | case 0: |
74 | clrsetbits_be32(&machine_data->guts->pmuxcr, | 83 | clrsetbits_be32(&guts->pmuxcr, |
75 | CCSR_GUTS_PMUXCR_SSI1_MASK, CCSR_GUTS_PMUXCR_SSI1_SSI); | 84 | CCSR_GUTS_PMUXCR_SSI1_MASK, CCSR_GUTS_PMUXCR_SSI1_SSI); |
76 | break; | 85 | break; |
77 | case 1: | 86 | case 1: |
78 | clrsetbits_be32(&machine_data->guts->pmuxcr, | 87 | clrsetbits_be32(&guts->pmuxcr, |
79 | CCSR_GUTS_PMUXCR_SSI2_MASK, CCSR_GUTS_PMUXCR_SSI2_SSI); | 88 | CCSR_GUTS_PMUXCR_SSI2_MASK, CCSR_GUTS_PMUXCR_SSI2_SSI); |
80 | break; | 89 | break; |
81 | } | 90 | } |
82 | 91 | ||
92 | iounmap(guts); | ||
93 | |||
83 | return 0; | 94 | return 0; |
84 | } | 95 | } |
85 | 96 | ||
@@ -93,38 +104,15 @@ static int mpc8610_hpcd_machine_probe(struct platform_device *sound_device) | |||
93 | static int mpc8610_hpcd_startup(struct snd_pcm_substream *substream) | 104 | static int mpc8610_hpcd_startup(struct snd_pcm_substream *substream) |
94 | { | 105 | { |
95 | struct snd_soc_pcm_runtime *rtd = substream->private_data; | 106 | struct snd_soc_pcm_runtime *rtd = substream->private_data; |
96 | struct snd_soc_dai *codec_dai = rtd->dai->codec_dai; | ||
97 | struct snd_soc_dai *cpu_dai = rtd->dai->cpu_dai; | ||
98 | struct mpc8610_hpcd_data *machine_data = | 107 | struct mpc8610_hpcd_data *machine_data = |
99 | rtd->socdev->dev->platform_data; | 108 | container_of(rtd->card, struct mpc8610_hpcd_data, card); |
109 | struct device *dev = rtd->card->dev; | ||
100 | int ret = 0; | 110 | int ret = 0; |
101 | 111 | ||
102 | /* Tell the CPU driver what the serial protocol is. */ | ||
103 | ret = snd_soc_dai_set_fmt(cpu_dai, machine_data->dai_format); | ||
104 | if (ret < 0) { | ||
105 | dev_err(substream->pcm->card->dev, | ||
106 | "could not set CPU driver audio format\n"); | ||
107 | return ret; | ||
108 | } | ||
109 | |||
110 | /* Tell the codec driver what the serial protocol is. */ | 112 | /* Tell the codec driver what the serial protocol is. */ |
111 | ret = snd_soc_dai_set_fmt(codec_dai, machine_data->dai_format); | 113 | ret = snd_soc_dai_set_fmt(rtd->codec_dai, machine_data->dai_format); |
112 | if (ret < 0) { | 114 | if (ret < 0) { |
113 | dev_err(substream->pcm->card->dev, | 115 | dev_err(dev, "could not set codec driver audio format\n"); |
114 | "could not set codec driver audio format\n"); | ||
115 | return ret; | ||
116 | } | ||
117 | |||
118 | /* | ||
119 | * Tell the CPU driver what the clock frequency is, and whether it's a | ||
120 | * slave or master. | ||
121 | */ | ||
122 | ret = snd_soc_dai_set_sysclk(cpu_dai, 0, | ||
123 | machine_data->clk_frequency, | ||
124 | machine_data->cpu_clk_direction); | ||
125 | if (ret < 0) { | ||
126 | dev_err(substream->pcm->card->dev, | ||
127 | "could not set CPU driver clock parameters\n"); | ||
128 | return ret; | 116 | return ret; |
129 | } | 117 | } |
130 | 118 | ||
@@ -132,12 +120,11 @@ static int mpc8610_hpcd_startup(struct snd_pcm_substream *substream) | |||
132 | * Tell the codec driver what the MCLK frequency is, and whether it's | 120 | * Tell the codec driver what the MCLK frequency is, and whether it's |
133 | * a slave or master. | 121 | * a slave or master. |
134 | */ | 122 | */ |
135 | ret = snd_soc_dai_set_sysclk(codec_dai, 0, | 123 | ret = snd_soc_dai_set_sysclk(rtd->codec_dai, 0, |
136 | machine_data->clk_frequency, | 124 | machine_data->clk_frequency, |
137 | machine_data->codec_clk_direction); | 125 | machine_data->codec_clk_direction); |
138 | if (ret < 0) { | 126 | if (ret < 0) { |
139 | dev_err(substream->pcm->card->dev, | 127 | dev_err(dev, "could not set codec driver clock params\n"); |
140 | "could not set codec driver clock params\n"); | ||
141 | return ret; | 128 | return ret; |
142 | } | 129 | } |
143 | 130 | ||
@@ -150,116 +137,254 @@ static int mpc8610_hpcd_startup(struct snd_pcm_substream *substream) | |||
150 | * This function is called to remove the sound device for one SSI. We | 137 | * This function is called to remove the sound device for one SSI. We |
151 | * de-program the DMACR and PMUXCR register. | 138 | * de-program the DMACR and PMUXCR register. |
152 | */ | 139 | */ |
153 | int mpc8610_hpcd_machine_remove(struct platform_device *sound_device) | 140 | static int mpc8610_hpcd_machine_remove(struct platform_device *sound_device) |
154 | { | 141 | { |
142 | struct snd_soc_card *card = platform_get_drvdata(sound_device); | ||
155 | struct mpc8610_hpcd_data *machine_data = | 143 | struct mpc8610_hpcd_data *machine_data = |
156 | sound_device->dev.platform_data; | 144 | container_of(card, struct mpc8610_hpcd_data, card); |
145 | struct ccsr_guts_86xx __iomem *guts; | ||
146 | |||
147 | guts = ioremap(guts_phys, sizeof(struct ccsr_guts_86xx)); | ||
148 | if (!guts) { | ||
149 | dev_err(card->dev, "could not map global utilities\n"); | ||
150 | return -ENOMEM; | ||
151 | } | ||
157 | 152 | ||
158 | /* Restore the signal routing */ | 153 | /* Restore the signal routing */ |
159 | 154 | ||
160 | guts_set_dmacr(machine_data->guts, machine_data->dma_id, | 155 | guts_set_dmacr(guts, machine_data->dma_id[0], |
161 | machine_data->dma_channel_id[0], 0); | 156 | machine_data->dma_channel_id[0], 0); |
162 | guts_set_dmacr(machine_data->guts, machine_data->dma_id, | 157 | guts_set_dmacr(guts, machine_data->dma_id[1], |
163 | machine_data->dma_channel_id[1], 0); | 158 | machine_data->dma_channel_id[1], 0); |
164 | 159 | ||
165 | switch (machine_data->ssi_id) { | 160 | switch (machine_data->ssi_id) { |
166 | case 0: | 161 | case 0: |
167 | clrsetbits_be32(&machine_data->guts->pmuxcr, | 162 | clrsetbits_be32(&guts->pmuxcr, |
168 | CCSR_GUTS_PMUXCR_SSI1_MASK, CCSR_GUTS_PMUXCR_SSI1_LA); | 163 | CCSR_GUTS_PMUXCR_SSI1_MASK, CCSR_GUTS_PMUXCR_SSI1_LA); |
169 | break; | 164 | break; |
170 | case 1: | 165 | case 1: |
171 | clrsetbits_be32(&machine_data->guts->pmuxcr, | 166 | clrsetbits_be32(&guts->pmuxcr, |
172 | CCSR_GUTS_PMUXCR_SSI2_MASK, CCSR_GUTS_PMUXCR_SSI2_LA); | 167 | CCSR_GUTS_PMUXCR_SSI2_MASK, CCSR_GUTS_PMUXCR_SSI2_LA); |
173 | break; | 168 | break; |
174 | } | 169 | } |
175 | 170 | ||
171 | iounmap(guts); | ||
172 | |||
176 | return 0; | 173 | return 0; |
177 | } | 174 | } |
178 | 175 | ||
179 | /** | 176 | /** |
180 | * mpc8610_hpcd_ops: ASoC fabric driver operations | 177 | * mpc8610_hpcd_ops: ASoC machine driver operations |
181 | */ | 178 | */ |
182 | static struct snd_soc_ops mpc8610_hpcd_ops = { | 179 | static struct snd_soc_ops mpc8610_hpcd_ops = { |
183 | .startup = mpc8610_hpcd_startup, | 180 | .startup = mpc8610_hpcd_startup, |
184 | }; | 181 | }; |
185 | 182 | ||
186 | /** | 183 | /** |
187 | * mpc8610_hpcd_probe: OF probe function for the fabric driver | 184 | * get_node_by_phandle_name - get a node by its phandle name |
188 | * | 185 | * |
189 | * This function gets called when an SSI node is found in the device tree. | 186 | * This function takes a node, the name of a property in that node, and a |
187 | * compatible string. Assuming the property is a phandle to another node, | ||
188 | * it returns that node, (optionally) if that node is compatible. | ||
190 | * | 189 | * |
191 | * Although this is a fabric driver, the SSI node is the "master" node with | 190 | * If the property is not a phandle, or the node it points to is not compatible |
192 | * respect to audio hardware connections. Therefore, we create a new ASoC | 191 | * with the specific string, then NULL is returned. |
193 | * device for each new SSI node that has a codec attached. | 192 | */ |
193 | static struct device_node *get_node_by_phandle_name(struct device_node *np, | ||
194 | const char *name, | ||
195 | const char *compatible) | ||
196 | { | ||
197 | const phandle *ph; | ||
198 | int len; | ||
199 | |||
200 | ph = of_get_property(np, name, &len); | ||
201 | if (!ph || (len != sizeof(phandle))) | ||
202 | return NULL; | ||
203 | |||
204 | np = of_find_node_by_phandle(*ph); | ||
205 | if (!np) | ||
206 | return NULL; | ||
207 | |||
208 | if (compatible && !of_device_is_compatible(np, compatible)) { | ||
209 | of_node_put(np); | ||
210 | return NULL; | ||
211 | } | ||
212 | |||
213 | return np; | ||
214 | } | ||
215 | |||
216 | /** | ||
217 | * get_parent_cell_index -- return the cell-index of the parent of a node | ||
194 | * | 218 | * |
195 | * FIXME: Currently, we only support one DMA controller, so if there are | 219 | * Return the value of the cell-index property of the parent of the given |
196 | * multiple SSI nodes with codecs, only the first will be supported. | 220 | * node. This is used for DMA channel nodes that need to know the DMA ID |
221 | * of the controller they are on. | ||
222 | */ | ||
223 | static int get_parent_cell_index(struct device_node *np) | ||
224 | { | ||
225 | struct device_node *parent = of_get_parent(np); | ||
226 | const u32 *iprop; | ||
227 | |||
228 | if (!parent) | ||
229 | return -1; | ||
230 | |||
231 | iprop = of_get_property(parent, "cell-index", NULL); | ||
232 | of_node_put(parent); | ||
233 | |||
234 | if (!iprop) | ||
235 | return -1; | ||
236 | |||
237 | return *iprop; | ||
238 | } | ||
239 | |||
240 | /** | ||
241 | * codec_node_dev_name - determine the dev_name for a codec node | ||
242 | * | ||
243 | * This function determines the dev_name for an I2C node. This is the name | ||
244 | * that would be returned by dev_name() if this device_node were part of a | ||
245 | * 'struct device' It's ugly and hackish, but it works. | ||
197 | * | 246 | * |
198 | * FIXME: Even if we did support multiple DMA controllers, we have no | 247 | * The dev_name for such devices include the bus number and I2C address. For |
199 | * mechanism for assigning DMA controllers and channels to the individual | 248 | * example, "cs4270-codec.0-004f". |
200 | * SSI devices. We also probably aren't compatible with the generic Elo DMA | ||
201 | * device driver. | ||
202 | */ | 249 | */ |
203 | static int mpc8610_hpcd_probe(struct of_device *ofdev, | 250 | static int codec_node_dev_name(struct device_node *np, char *buf, size_t len) |
204 | const struct of_device_id *match) | ||
205 | { | 251 | { |
206 | struct device_node *np = ofdev->dev.of_node; | ||
207 | struct device_node *codec_np = NULL; | ||
208 | struct device_node *guts_np = NULL; | ||
209 | struct device_node *dma_np = NULL; | ||
210 | struct device_node *dma_channel_np = NULL; | ||
211 | const phandle *codec_ph; | ||
212 | const char *sprop; | ||
213 | const u32 *iprop; | 252 | const u32 *iprop; |
253 | int bus, addr; | ||
254 | char temp[DAI_NAME_SIZE]; | ||
255 | |||
256 | of_modalias_node(np, temp, DAI_NAME_SIZE); | ||
257 | |||
258 | iprop = of_get_property(np, "reg", NULL); | ||
259 | if (!iprop) | ||
260 | return -EINVAL; | ||
261 | |||
262 | addr = *iprop; | ||
263 | |||
264 | bus = get_parent_cell_index(np); | ||
265 | if (bus < 0) | ||
266 | return bus; | ||
267 | |||
268 | snprintf(buf, len, "%s-codec.%u-%04x", temp, bus, addr); | ||
269 | |||
270 | return 0; | ||
271 | } | ||
272 | |||
273 | static int get_dma_channel(struct device_node *ssi_np, | ||
274 | const char *compatible, | ||
275 | struct snd_soc_dai_link *dai, | ||
276 | unsigned int *dma_channel_id, | ||
277 | unsigned int *dma_id) | ||
278 | { | ||
214 | struct resource res; | 279 | struct resource res; |
280 | struct device_node *dma_channel_np; | ||
281 | const u32 *iprop; | ||
282 | int ret; | ||
283 | |||
284 | dma_channel_np = get_node_by_phandle_name(ssi_np, compatible, | ||
285 | "fsl,ssi-dma-channel"); | ||
286 | if (!dma_channel_np) | ||
287 | return -EINVAL; | ||
288 | |||
289 | /* Determine the dev_name for the device_node. This code mimics the | ||
290 | * behavior of of_device_make_bus_id(). We need this because ASoC uses | ||
291 | * the dev_name() of the device to match the platform (DMA) device with | ||
292 | * the CPU (SSI) device. It's all ugly and hackish, but it works (for | ||
293 | * now). | ||
294 | * | ||
295 | * dai->platform name should already point to an allocated buffer. | ||
296 | */ | ||
297 | ret = of_address_to_resource(dma_channel_np, 0, &res); | ||
298 | if (ret) | ||
299 | return ret; | ||
300 | snprintf((char *)dai->platform_name, DAI_NAME_SIZE, "%llx.%s", | ||
301 | (unsigned long long) res.start, dma_channel_np->name); | ||
302 | |||
303 | iprop = of_get_property(dma_channel_np, "cell-index", NULL); | ||
304 | if (!iprop) { | ||
305 | of_node_put(dma_channel_np); | ||
306 | return -EINVAL; | ||
307 | } | ||
308 | |||
309 | *dma_channel_id = *iprop; | ||
310 | *dma_id = get_parent_cell_index(dma_channel_np); | ||
311 | of_node_put(dma_channel_np); | ||
312 | |||
313 | return 0; | ||
314 | } | ||
315 | |||
316 | /** | ||
317 | * mpc8610_hpcd_probe: platform probe function for the machine driver | ||
318 | * | ||
319 | * Although this is a machine driver, the SSI node is the "master" node with | ||
320 | * respect to audio hardware connections. Therefore, we create a new ASoC | ||
321 | * device for each new SSI node that has a codec attached. | ||
322 | */ | ||
323 | static int mpc8610_hpcd_probe(struct platform_device *pdev) | ||
324 | { | ||
325 | struct device *dev = pdev->dev.parent; | ||
326 | /* of_dev is the OF device for the SSI node that probed us */ | ||
327 | struct of_device *of_dev = container_of(dev, struct of_device, dev); | ||
328 | struct device_node *np = of_dev->dev.of_node; | ||
329 | struct device_node *codec_np = NULL; | ||
215 | struct platform_device *sound_device = NULL; | 330 | struct platform_device *sound_device = NULL; |
216 | struct mpc8610_hpcd_data *machine_data; | 331 | struct mpc8610_hpcd_data *machine_data; |
217 | struct fsl_ssi_info ssi_info; | ||
218 | struct fsl_dma_info dma_info; | ||
219 | int ret = -ENODEV; | 332 | int ret = -ENODEV; |
220 | unsigned int playback_dma_channel; | 333 | const char *sprop; |
221 | unsigned int capture_dma_channel; | 334 | const u32 *iprop; |
335 | |||
336 | /* We are only interested in SSIs with a codec phandle in them, | ||
337 | * so let's make sure this SSI has one. The MPC8610 HPCD only | ||
338 | * knows about the CS4270 codec, so reject anything else. | ||
339 | */ | ||
340 | codec_np = get_node_by_phandle_name(np, "codec-handle", | ||
341 | "cirrus,cs4270"); | ||
342 | if (!codec_np) { | ||
343 | dev_err(dev, "invalid codec node\n"); | ||
344 | return -EINVAL; | ||
345 | } | ||
222 | 346 | ||
223 | machine_data = kzalloc(sizeof(struct mpc8610_hpcd_data), GFP_KERNEL); | 347 | machine_data = kzalloc(sizeof(struct mpc8610_hpcd_data), GFP_KERNEL); |
224 | if (!machine_data) | 348 | if (!machine_data) |
225 | return -ENOMEM; | 349 | return -ENOMEM; |
226 | 350 | ||
227 | memset(&ssi_info, 0, sizeof(ssi_info)); | 351 | machine_data->dai[0].cpu_dai_name = dev_name(&of_dev->dev); |
228 | memset(&dma_info, 0, sizeof(dma_info)); | 352 | machine_data->dai[0].ops = &mpc8610_hpcd_ops; |
229 | |||
230 | ssi_info.dev = &ofdev->dev; | ||
231 | 353 | ||
232 | /* | 354 | /* Determine the codec name, it will be used as the codec DAI name */ |
233 | * We are only interested in SSIs with a codec phandle in them, so let's | 355 | ret = codec_node_dev_name(codec_np, machine_data->codec_name, |
234 | * make sure this SSI has one. | 356 | DAI_NAME_SIZE); |
235 | */ | 357 | if (ret) { |
236 | codec_ph = of_get_property(np, "codec-handle", NULL); | 358 | dev_err(&pdev->dev, "invalid codec node %s\n", |
237 | if (!codec_ph) | 359 | codec_np->full_name); |
360 | ret = -EINVAL; | ||
238 | goto error; | 361 | goto error; |
362 | } | ||
363 | machine_data->dai[0].codec_name = machine_data->codec_name; | ||
239 | 364 | ||
240 | codec_np = of_find_node_by_phandle(*codec_ph); | 365 | /* The DAI name from the codec (snd_soc_dai_driver.name) */ |
241 | if (!codec_np) | 366 | machine_data->dai[0].codec_dai_name = "cs4270-hifi"; |
242 | goto error; | ||
243 | 367 | ||
244 | /* The MPC8610 HPCD only knows about the CS4270 codec, so reject | 368 | /* We register two DAIs per SSI, one for playback and the other for |
245 | anything else. */ | 369 | * capture. Currently, we only support codecs that have one DAI for |
246 | if (!of_device_is_compatible(codec_np, "cirrus,cs4270")) | 370 | * both playback and capture. |
247 | goto error; | 371 | */ |
372 | memcpy(&machine_data->dai[1], &machine_data->dai[0], | ||
373 | sizeof(struct snd_soc_dai_link)); | ||
248 | 374 | ||
249 | /* Get the device ID */ | 375 | /* Get the device ID */ |
250 | iprop = of_get_property(np, "cell-index", NULL); | 376 | iprop = of_get_property(np, "cell-index", NULL); |
251 | if (!iprop) { | 377 | if (!iprop) { |
252 | dev_err(&ofdev->dev, "cell-index property not found\n"); | 378 | dev_err(&pdev->dev, "cell-index property not found\n"); |
253 | ret = -EINVAL; | 379 | ret = -EINVAL; |
254 | goto error; | 380 | goto error; |
255 | } | 381 | } |
256 | machine_data->ssi_id = *iprop; | 382 | machine_data->ssi_id = *iprop; |
257 | ssi_info.id = *iprop; | ||
258 | 383 | ||
259 | /* Get the serial format and clock direction. */ | 384 | /* Get the serial format and clock direction. */ |
260 | sprop = of_get_property(np, "fsl,mode", NULL); | 385 | sprop = of_get_property(np, "fsl,mode", NULL); |
261 | if (!sprop) { | 386 | if (!sprop) { |
262 | dev_err(&ofdev->dev, "fsl,mode property not found\n"); | 387 | dev_err(&pdev->dev, "fsl,mode property not found\n"); |
263 | ret = -EINVAL; | 388 | ret = -EINVAL; |
264 | goto error; | 389 | goto error; |
265 | } | 390 | } |
@@ -269,15 +394,14 @@ static int mpc8610_hpcd_probe(struct of_device *ofdev, | |||
269 | machine_data->codec_clk_direction = SND_SOC_CLOCK_OUT; | 394 | machine_data->codec_clk_direction = SND_SOC_CLOCK_OUT; |
270 | machine_data->cpu_clk_direction = SND_SOC_CLOCK_IN; | 395 | machine_data->cpu_clk_direction = SND_SOC_CLOCK_IN; |
271 | 396 | ||
272 | /* | 397 | /* In i2s-slave mode, the codec has its own clock source, so we |
273 | * In i2s-slave mode, the codec has its own clock source, so we | ||
274 | * need to get the frequency from the device tree and pass it to | 398 | * need to get the frequency from the device tree and pass it to |
275 | * the codec driver. | 399 | * the codec driver. |
276 | */ | 400 | */ |
277 | iprop = of_get_property(codec_np, "clock-frequency", NULL); | 401 | iprop = of_get_property(codec_np, "clock-frequency", NULL); |
278 | if (!iprop || !*iprop) { | 402 | if (!iprop || !*iprop) { |
279 | dev_err(&ofdev->dev, "codec bus-frequency property " | 403 | dev_err(&pdev->dev, "codec bus-frequency " |
280 | "is missing or invalid\n"); | 404 | "property is missing or invalid\n"); |
281 | ret = -EINVAL; | 405 | ret = -EINVAL; |
282 | goto error; | 406 | goto error; |
283 | } | 407 | } |
@@ -311,317 +435,153 @@ static int mpc8610_hpcd_probe(struct of_device *ofdev, | |||
311 | machine_data->codec_clk_direction = SND_SOC_CLOCK_IN; | 435 | machine_data->codec_clk_direction = SND_SOC_CLOCK_IN; |
312 | machine_data->cpu_clk_direction = SND_SOC_CLOCK_OUT; | 436 | machine_data->cpu_clk_direction = SND_SOC_CLOCK_OUT; |
313 | } else { | 437 | } else { |
314 | dev_err(&ofdev->dev, | 438 | dev_err(&pdev->dev, |
315 | "unrecognized fsl,mode property \"%s\"\n", sprop); | 439 | "unrecognized fsl,mode property '%s'\n", sprop); |
316 | ret = -EINVAL; | 440 | ret = -EINVAL; |
317 | goto error; | 441 | goto error; |
318 | } | 442 | } |
319 | 443 | ||
320 | if (!machine_data->clk_frequency) { | 444 | if (!machine_data->clk_frequency) { |
321 | dev_err(&ofdev->dev, "unknown clock frequency\n"); | 445 | dev_err(&pdev->dev, "unknown clock frequency\n"); |
322 | ret = -EINVAL; | 446 | ret = -EINVAL; |
323 | goto error; | 447 | goto error; |
324 | } | 448 | } |
325 | 449 | ||
326 | /* Read the SSI information from the device tree */ | 450 | /* Find the playback DMA channel to use. */ |
327 | ret = of_address_to_resource(np, 0, &res); | 451 | machine_data->dai[0].platform_name = machine_data->platform_name[0]; |
452 | ret = get_dma_channel(np, "fsl,playback-dma", &machine_data->dai[0], | ||
453 | &machine_data->dma_channel_id[0], | ||
454 | &machine_data->dma_id[0]); | ||
328 | if (ret) { | 455 | if (ret) { |
329 | dev_err(&ofdev->dev, "could not obtain SSI address\n"); | 456 | dev_err(&pdev->dev, "missing/invalid playback DMA phandle\n"); |
330 | goto error; | ||
331 | } | ||
332 | if (!res.start) { | ||
333 | dev_err(&ofdev->dev, "invalid SSI address\n"); | ||
334 | goto error; | ||
335 | } | ||
336 | ssi_info.ssi_phys = res.start; | ||
337 | |||
338 | machine_data->ssi = ioremap(ssi_info.ssi_phys, sizeof(struct ccsr_ssi)); | ||
339 | if (!machine_data->ssi) { | ||
340 | dev_err(&ofdev->dev, "could not map SSI address %x\n", | ||
341 | ssi_info.ssi_phys); | ||
342 | ret = -EINVAL; | ||
343 | goto error; | 457 | goto error; |
344 | } | 458 | } |
345 | ssi_info.ssi = machine_data->ssi; | ||
346 | 459 | ||
347 | 460 | /* Find the capture DMA channel to use. */ | |
348 | /* Get the IRQ of the SSI */ | 461 | machine_data->dai[1].platform_name = machine_data->platform_name[1]; |
349 | machine_data->ssi_irq = irq_of_parse_and_map(np, 0); | 462 | ret = get_dma_channel(np, "fsl,capture-dma", &machine_data->dai[1], |
350 | if (!machine_data->ssi_irq) { | 463 | &machine_data->dma_channel_id[1], |
351 | dev_err(&ofdev->dev, "could not get SSI IRQ\n"); | 464 | &machine_data->dma_id[1]); |
352 | ret = -EINVAL; | 465 | if (ret) { |
353 | goto error; | 466 | dev_err(&pdev->dev, "missing/invalid capture DMA phandle\n"); |
354 | } | ||
355 | ssi_info.irq = machine_data->ssi_irq; | ||
356 | |||
357 | /* Do we want to use asynchronous mode? */ | ||
358 | ssi_info.asynchronous = | ||
359 | of_find_property(np, "fsl,ssi-asynchronous", NULL) ? 1 : 0; | ||
360 | if (ssi_info.asynchronous) | ||
361 | dev_info(&ofdev->dev, "using asynchronous mode\n"); | ||
362 | |||
363 | /* Map the global utilities registers. */ | ||
364 | guts_np = of_find_compatible_node(NULL, NULL, "fsl,mpc8610-guts"); | ||
365 | if (!guts_np) { | ||
366 | dev_err(&ofdev->dev, "could not obtain address of GUTS\n"); | ||
367 | ret = -EINVAL; | ||
368 | goto error; | ||
369 | } | ||
370 | machine_data->guts = of_iomap(guts_np, 0); | ||
371 | of_node_put(guts_np); | ||
372 | if (!machine_data->guts) { | ||
373 | dev_err(&ofdev->dev, "could not map GUTS\n"); | ||
374 | ret = -EINVAL; | ||
375 | goto error; | ||
376 | } | ||
377 | |||
378 | /* Find the DMA channels to use. Both SSIs need to use the same DMA | ||
379 | * controller, so let's use DMA#1. | ||
380 | */ | ||
381 | for_each_compatible_node(dma_np, NULL, "fsl,mpc8610-dma") { | ||
382 | iprop = of_get_property(dma_np, "cell-index", NULL); | ||
383 | if (iprop && (*iprop == 0)) { | ||
384 | of_node_put(dma_np); | ||
385 | break; | ||
386 | } | ||
387 | } | ||
388 | if (!dma_np) { | ||
389 | dev_err(&ofdev->dev, "could not find DMA node\n"); | ||
390 | ret = -EINVAL; | ||
391 | goto error; | ||
392 | } | ||
393 | machine_data->dma_id = *iprop; | ||
394 | |||
395 | /* SSI1 needs to use DMA Channels 0 and 1, and SSI2 needs to use DMA | ||
396 | * channels 2 and 3. This is just how the MPC8610 is wired | ||
397 | * internally. | ||
398 | */ | ||
399 | playback_dma_channel = (machine_data->ssi_id == 0) ? 0 : 2; | ||
400 | capture_dma_channel = (machine_data->ssi_id == 0) ? 1 : 3; | ||
401 | |||
402 | /* | ||
403 | * Find the DMA channels to use. | ||
404 | */ | ||
405 | while ((dma_channel_np = of_get_next_child(dma_np, dma_channel_np))) { | ||
406 | iprop = of_get_property(dma_channel_np, "cell-index", NULL); | ||
407 | if (iprop && (*iprop == playback_dma_channel)) { | ||
408 | /* dma_channel[0] and dma_irq[0] are for playback */ | ||
409 | dma_info.dma_channel[0] = of_iomap(dma_channel_np, 0); | ||
410 | dma_info.dma_irq[0] = | ||
411 | irq_of_parse_and_map(dma_channel_np, 0); | ||
412 | machine_data->dma_channel_id[0] = *iprop; | ||
413 | continue; | ||
414 | } | ||
415 | if (iprop && (*iprop == capture_dma_channel)) { | ||
416 | /* dma_channel[1] and dma_irq[1] are for capture */ | ||
417 | dma_info.dma_channel[1] = of_iomap(dma_channel_np, 0); | ||
418 | dma_info.dma_irq[1] = | ||
419 | irq_of_parse_and_map(dma_channel_np, 0); | ||
420 | machine_data->dma_channel_id[1] = *iprop; | ||
421 | continue; | ||
422 | } | ||
423 | } | ||
424 | if (!dma_info.dma_channel[0] || !dma_info.dma_channel[1] || | ||
425 | !dma_info.dma_irq[0] || !dma_info.dma_irq[1]) { | ||
426 | dev_err(&ofdev->dev, "could not find DMA channels\n"); | ||
427 | ret = -EINVAL; | ||
428 | goto error; | 467 | goto error; |
429 | } | 468 | } |
430 | 469 | ||
431 | dma_info.ssi_stx_phys = ssi_info.ssi_phys + | 470 | /* Initialize our DAI data structure. */ |
432 | offsetof(struct ccsr_ssi, stx0); | 471 | machine_data->dai[0].stream_name = "playback"; |
433 | dma_info.ssi_srx_phys = ssi_info.ssi_phys + | 472 | machine_data->dai[1].stream_name = "capture"; |
434 | offsetof(struct ccsr_ssi, srx0); | 473 | machine_data->dai[0].name = machine_data->dai[0].stream_name; |
435 | 474 | machine_data->dai[1].name = machine_data->dai[1].stream_name; | |
436 | /* We have the DMA information, so tell the DMA driver what it is */ | ||
437 | if (!fsl_dma_configure(&dma_info)) { | ||
438 | dev_err(&ofdev->dev, "could not instantiate DMA device\n"); | ||
439 | ret = -EBUSY; | ||
440 | goto error; | ||
441 | } | ||
442 | 475 | ||
443 | /* | 476 | machine_data->card.probe = mpc8610_hpcd_machine_probe; |
444 | * Initialize our DAI data structure. We should probably get this | 477 | machine_data->card.remove = mpc8610_hpcd_machine_remove; |
445 | * information from the device tree. | 478 | machine_data->card.name = pdev->name; /* The platform driver name */ |
446 | */ | 479 | machine_data->card.num_links = 2; |
447 | machine_data->dai.name = "CS4270"; | 480 | machine_data->card.dai_link = machine_data->dai; |
448 | machine_data->dai.stream_name = "CS4270"; | ||
449 | |||
450 | machine_data->dai.cpu_dai = fsl_ssi_create_dai(&ssi_info); | ||
451 | machine_data->dai.codec_dai = &cs4270_dai; /* The codec_dai we want */ | ||
452 | machine_data->dai.ops = &mpc8610_hpcd_ops; | ||
453 | |||
454 | machine_data->machine.probe = mpc8610_hpcd_machine_probe; | ||
455 | machine_data->machine.remove = mpc8610_hpcd_machine_remove; | ||
456 | machine_data->machine.name = "MPC8610 HPCD"; | ||
457 | machine_data->machine.num_links = 1; | ||
458 | machine_data->machine.dai_link = &machine_data->dai; | ||
459 | 481 | ||
460 | /* Allocate a new audio platform device structure */ | 482 | /* Allocate a new audio platform device structure */ |
461 | sound_device = platform_device_alloc("soc-audio", -1); | 483 | sound_device = platform_device_alloc("soc-audio", -1); |
462 | if (!sound_device) { | 484 | if (!sound_device) { |
463 | dev_err(&ofdev->dev, "platform device allocation failed\n"); | 485 | dev_err(&pdev->dev, "platform device alloc failed\n"); |
464 | ret = -ENOMEM; | 486 | ret = -ENOMEM; |
465 | goto error; | 487 | goto error; |
466 | } | 488 | } |
467 | 489 | ||
468 | machine_data->sound_devdata.card = &machine_data->machine; | 490 | /* Associate the card data with the sound device */ |
469 | machine_data->sound_devdata.codec_dev = &soc_codec_device_cs4270; | 491 | platform_set_drvdata(sound_device, &machine_data->card); |
470 | machine_data->machine.platform = &fsl_soc_platform; | ||
471 | |||
472 | sound_device->dev.platform_data = machine_data; | ||
473 | |||
474 | |||
475 | /* Set the platform device and ASoC device to point to each other */ | ||
476 | platform_set_drvdata(sound_device, &machine_data->sound_devdata); | ||
477 | 492 | ||
478 | machine_data->sound_devdata.dev = &sound_device->dev; | 493 | /* Register with ASoC */ |
479 | |||
480 | |||
481 | /* Tell ASoC to probe us. This will call mpc8610_hpcd_machine.probe(), | ||
482 | if it exists. */ | ||
483 | ret = platform_device_add(sound_device); | 494 | ret = platform_device_add(sound_device); |
484 | |||
485 | if (ret) { | 495 | if (ret) { |
486 | dev_err(&ofdev->dev, "platform device add failed\n"); | 496 | dev_err(&pdev->dev, "platform device add failed\n"); |
487 | goto error; | 497 | goto error; |
488 | } | 498 | } |
489 | 499 | ||
490 | dev_set_drvdata(&ofdev->dev, sound_device); | 500 | of_node_put(codec_np); |
491 | 501 | ||
492 | return 0; | 502 | return 0; |
493 | 503 | ||
494 | error: | 504 | error: |
495 | of_node_put(codec_np); | 505 | of_node_put(codec_np); |
496 | of_node_put(guts_np); | ||
497 | of_node_put(dma_np); | ||
498 | of_node_put(dma_channel_np); | ||
499 | 506 | ||
500 | if (sound_device) | 507 | if (sound_device) |
501 | platform_device_unregister(sound_device); | 508 | platform_device_unregister(sound_device); |
502 | 509 | ||
503 | if (machine_data->dai.cpu_dai) | ||
504 | fsl_ssi_destroy_dai(machine_data->dai.cpu_dai); | ||
505 | |||
506 | if (ssi_info.ssi) | ||
507 | iounmap(ssi_info.ssi); | ||
508 | |||
509 | if (ssi_info.irq) | ||
510 | irq_dispose_mapping(ssi_info.irq); | ||
511 | |||
512 | if (dma_info.dma_channel[0]) | ||
513 | iounmap(dma_info.dma_channel[0]); | ||
514 | |||
515 | if (dma_info.dma_channel[1]) | ||
516 | iounmap(dma_info.dma_channel[1]); | ||
517 | |||
518 | if (dma_info.dma_irq[0]) | ||
519 | irq_dispose_mapping(dma_info.dma_irq[0]); | ||
520 | |||
521 | if (dma_info.dma_irq[1]) | ||
522 | irq_dispose_mapping(dma_info.dma_irq[1]); | ||
523 | |||
524 | if (machine_data->guts) | ||
525 | iounmap(machine_data->guts); | ||
526 | |||
527 | kfree(machine_data); | 510 | kfree(machine_data); |
528 | 511 | ||
529 | return ret; | 512 | return ret; |
530 | } | 513 | } |
531 | 514 | ||
532 | /** | 515 | /** |
533 | * mpc8610_hpcd_remove: remove the OF device | 516 | * mpc8610_hpcd_remove: remove the platform device |
534 | * | 517 | * |
535 | * This function is called when the OF device is removed. | 518 | * This function is called when the platform device is removed. |
536 | */ | 519 | */ |
537 | static int mpc8610_hpcd_remove(struct of_device *ofdev) | 520 | static int __devexit mpc8610_hpcd_remove(struct platform_device *pdev) |
538 | { | 521 | { |
539 | struct platform_device *sound_device = dev_get_drvdata(&ofdev->dev); | 522 | struct platform_device *sound_device = dev_get_drvdata(&pdev->dev); |
523 | struct snd_soc_card *card = platform_get_drvdata(sound_device); | ||
540 | struct mpc8610_hpcd_data *machine_data = | 524 | struct mpc8610_hpcd_data *machine_data = |
541 | sound_device->dev.platform_data; | 525 | container_of(card, struct mpc8610_hpcd_data, card); |
542 | 526 | ||
543 | platform_device_unregister(sound_device); | 527 | platform_device_unregister(sound_device); |
544 | 528 | ||
545 | if (machine_data->dai.cpu_dai) | ||
546 | fsl_ssi_destroy_dai(machine_data->dai.cpu_dai); | ||
547 | |||
548 | if (machine_data->ssi) | ||
549 | iounmap(machine_data->ssi); | ||
550 | |||
551 | if (machine_data->dma[0]) | ||
552 | iounmap(machine_data->dma[0]); | ||
553 | |||
554 | if (machine_data->dma[1]) | ||
555 | iounmap(machine_data->dma[1]); | ||
556 | |||
557 | if (machine_data->dma_irq[0]) | ||
558 | irq_dispose_mapping(machine_data->dma_irq[0]); | ||
559 | |||
560 | if (machine_data->dma_irq[1]) | ||
561 | irq_dispose_mapping(machine_data->dma_irq[1]); | ||
562 | |||
563 | if (machine_data->guts) | ||
564 | iounmap(machine_data->guts); | ||
565 | |||
566 | kfree(machine_data); | 529 | kfree(machine_data); |
567 | sound_device->dev.platform_data = NULL; | 530 | sound_device->dev.platform_data = NULL; |
568 | 531 | ||
569 | dev_set_drvdata(&ofdev->dev, NULL); | 532 | dev_set_drvdata(&pdev->dev, NULL); |
570 | 533 | ||
571 | return 0; | 534 | return 0; |
572 | } | 535 | } |
573 | 536 | ||
574 | static struct of_device_id mpc8610_hpcd_match[] = { | 537 | static struct platform_driver mpc8610_hpcd_driver = { |
575 | { | 538 | .probe = mpc8610_hpcd_probe, |
576 | .compatible = "fsl,mpc8610-ssi", | 539 | .remove = __devexit_p(mpc8610_hpcd_remove), |
577 | }, | ||
578 | {} | ||
579 | }; | ||
580 | MODULE_DEVICE_TABLE(of, mpc8610_hpcd_match); | ||
581 | |||
582 | static struct of_platform_driver mpc8610_hpcd_of_driver = { | ||
583 | .driver = { | 540 | .driver = { |
584 | .name = "mpc8610_hpcd", | 541 | /* The name must match the 'model' property in the device tree, |
542 | * in lowercase letters. | ||
543 | */ | ||
544 | .name = "snd-soc-mpc8610hpcd", | ||
585 | .owner = THIS_MODULE, | 545 | .owner = THIS_MODULE, |
586 | .of_match_table = mpc8610_hpcd_match, | ||
587 | }, | 546 | }, |
588 | .probe = mpc8610_hpcd_probe, | ||
589 | .remove = mpc8610_hpcd_remove, | ||
590 | }; | 547 | }; |
591 | 548 | ||
592 | /** | 549 | /** |
593 | * mpc8610_hpcd_init: fabric driver initialization. | 550 | * mpc8610_hpcd_init: machine driver initialization. |
594 | * | 551 | * |
595 | * This function is called when this module is loaded. | 552 | * This function is called when this module is loaded. |
596 | */ | 553 | */ |
597 | static int __init mpc8610_hpcd_init(void) | 554 | static int __init mpc8610_hpcd_init(void) |
598 | { | 555 | { |
599 | int ret; | 556 | struct device_node *guts_np; |
600 | 557 | struct resource res; | |
601 | printk(KERN_INFO "Freescale MPC8610 HPCD ALSA SoC fabric driver\n"); | ||
602 | 558 | ||
603 | ret = of_register_platform_driver(&mpc8610_hpcd_of_driver); | 559 | pr_info("Freescale MPC8610 HPCD ALSA SoC machine driver\n"); |
604 | 560 | ||
605 | if (ret) | 561 | /* Get the physical address of the global utilities registers */ |
606 | printk(KERN_ERR | 562 | guts_np = of_find_compatible_node(NULL, NULL, "fsl,mpc8610-guts"); |
607 | "mpc8610-hpcd: failed to register platform driver\n"); | 563 | if (of_address_to_resource(guts_np, 0, &res)) { |
564 | pr_err("mpc8610-hpcd: missing/invalid global utilities node\n"); | ||
565 | return -EINVAL; | ||
566 | } | ||
567 | guts_phys = res.start; | ||
608 | 568 | ||
609 | return ret; | 569 | return platform_driver_register(&mpc8610_hpcd_driver); |
610 | } | 570 | } |
611 | 571 | ||
612 | /** | 572 | /** |
613 | * mpc8610_hpcd_exit: fabric driver exit | 573 | * mpc8610_hpcd_exit: machine driver exit |
614 | * | 574 | * |
615 | * This function is called when this driver is unloaded. | 575 | * This function is called when this driver is unloaded. |
616 | */ | 576 | */ |
617 | static void __exit mpc8610_hpcd_exit(void) | 577 | static void __exit mpc8610_hpcd_exit(void) |
618 | { | 578 | { |
619 | of_unregister_platform_driver(&mpc8610_hpcd_of_driver); | 579 | platform_driver_unregister(&mpc8610_hpcd_driver); |
620 | } | 580 | } |
621 | 581 | ||
622 | module_init(mpc8610_hpcd_init); | 582 | module_init(mpc8610_hpcd_init); |
623 | module_exit(mpc8610_hpcd_exit); | 583 | module_exit(mpc8610_hpcd_exit); |
624 | 584 | ||
625 | MODULE_AUTHOR("Timur Tabi <timur@freescale.com>"); | 585 | MODULE_AUTHOR("Timur Tabi <timur@freescale.com>"); |
626 | MODULE_DESCRIPTION("Freescale MPC8610 HPCD ALSA SoC fabric driver"); | 586 | MODULE_DESCRIPTION("Freescale MPC8610 HPCD ALSA SoC machine driver"); |
627 | MODULE_LICENSE("GPL"); | 587 | MODULE_LICENSE("GPL v2"); |
diff --git a/sound/soc/fsl/pcm030-audio-fabric.c b/sound/soc/fsl/pcm030-audio-fabric.c index 6644cba7cbf2..fe15bb26e484 100644 --- a/sound/soc/fsl/pcm030-audio-fabric.c +++ b/sound/soc/fsl/pcm030-audio-fabric.c | |||
@@ -32,21 +32,24 @@ | |||
32 | 32 | ||
33 | #define DRV_NAME "pcm030-audio-fabric" | 33 | #define DRV_NAME "pcm030-audio-fabric" |
34 | 34 | ||
35 | static struct snd_soc_device device; | ||
36 | static struct snd_soc_card card; | 35 | static struct snd_soc_card card; |
37 | 36 | ||
38 | static struct snd_soc_dai_link pcm030_fabric_dai[] = { | 37 | static struct snd_soc_dai_link pcm030_fabric_dai[] = { |
39 | { | 38 | { |
40 | .name = "AC97", | 39 | .name = "AC97", |
41 | .stream_name = "AC97 Analog", | 40 | .stream_name = "AC97 Analog", |
42 | .codec_dai = &wm9712_dai[WM9712_DAI_AC97_HIFI], | 41 | .codec_dai_name = "wm9712-hifi", |
43 | .cpu_dai = &psc_ac97_dai[MPC5200_AC97_NORMAL], | 42 | .cpu_dai_name = "mpc5200-psc-ac97.0", |
43 | .platform_name = "mpc5200-pcm-audio", | ||
44 | .codec_name = "wm9712-codec", | ||
44 | }, | 45 | }, |
45 | { | 46 | { |
46 | .name = "AC97", | 47 | .name = "AC97", |
47 | .stream_name = "AC97 IEC958", | 48 | .stream_name = "AC97 IEC958", |
48 | .codec_dai = &wm9712_dai[WM9712_DAI_AC97_AUX], | 49 | .codec_dai_name = "wm9712-aux", |
49 | .cpu_dai = &psc_ac97_dai[MPC5200_AC97_SPDIF], | 50 | .cpu_dai_name = "mpc5200-psc-ac97.1", |
51 | .platform_name = "mpc5200-pcm-audio", | ||
52 | ..codec_name = "wm9712-codec", | ||
50 | }, | 53 | }, |
51 | }; | 54 | }; |
52 | 55 | ||
@@ -58,22 +61,18 @@ static __init int pcm030_fabric_init(void) | |||
58 | if (!of_machine_is_compatible("phytec,pcm030")) | 61 | if (!of_machine_is_compatible("phytec,pcm030")) |
59 | return -ENODEV; | 62 | return -ENODEV; |
60 | 63 | ||
61 | card.platform = &mpc5200_audio_dma_platform; | 64 | |
62 | card.name = "pcm030"; | 65 | card.name = "pcm030"; |
63 | card.dai_link = pcm030_fabric_dai; | 66 | card.dai_link = pcm030_fabric_dai; |
64 | card.num_links = ARRAY_SIZE(pcm030_fabric_dai); | 67 | card.num_links = ARRAY_SIZE(pcm030_fabric_dai); |
65 | 68 | ||
66 | device.card = &card; | ||
67 | device.codec_dev = &soc_codec_dev_wm9712; | ||
68 | |||
69 | pdev = platform_device_alloc("soc-audio", 1); | 69 | pdev = platform_device_alloc("soc-audio", 1); |
70 | if (!pdev) { | 70 | if (!pdev) { |
71 | pr_err("pcm030_fabric_init: platform_device_alloc() failed\n"); | 71 | pr_err("pcm030_fabric_init: platform_device_alloc() failed\n"); |
72 | return -ENODEV; | 72 | return -ENODEV; |
73 | } | 73 | } |
74 | 74 | ||
75 | platform_set_drvdata(pdev, &device); | 75 | platform_set_drvdata(pdev, &card); |
76 | device.dev = &pdev->dev; | ||
77 | 76 | ||
78 | rc = platform_device_add(pdev); | 77 | rc = platform_device_add(pdev); |
79 | if (rc) { | 78 | if (rc) { |
diff --git a/sound/soc/fsl/soc-of-simple.c b/sound/soc/fsl/soc-of-simple.c deleted file mode 100644 index 3bc13fd89096..000000000000 --- a/sound/soc/fsl/soc-of-simple.c +++ /dev/null | |||
@@ -1,172 +0,0 @@ | |||
1 | /* | ||
2 | * OF helpers for ALSA SoC Layer | ||
3 | * | ||
4 | * Copyright (C) 2008, Secret Lab Technologies Ltd. | ||
5 | */ | ||
6 | |||
7 | #include <linux/module.h> | ||
8 | #include <linux/moduleparam.h> | ||
9 | #include <linux/init.h> | ||
10 | #include <linux/delay.h> | ||
11 | #include <linux/pm.h> | ||
12 | #include <linux/bitops.h> | ||
13 | #include <linux/platform_device.h> | ||
14 | #include <linux/of.h> | ||
15 | #include <linux/slab.h> | ||
16 | #include <sound/core.h> | ||
17 | #include <sound/pcm.h> | ||
18 | #include <sound/pcm_params.h> | ||
19 | #include <sound/soc.h> | ||
20 | #include <sound/soc-of-simple.h> | ||
21 | #include <sound/initval.h> | ||
22 | |||
23 | MODULE_AUTHOR("Grant Likely <grant.likely@secretlab.ca>"); | ||
24 | MODULE_LICENSE("GPL"); | ||
25 | MODULE_DESCRIPTION("ALSA SoC OpenFirmware bindings"); | ||
26 | |||
27 | static DEFINE_MUTEX(of_snd_soc_mutex); | ||
28 | static LIST_HEAD(of_snd_soc_device_list); | ||
29 | static int of_snd_soc_next_index; | ||
30 | |||
31 | struct of_snd_soc_device { | ||
32 | int id; | ||
33 | struct list_head list; | ||
34 | struct snd_soc_device device; | ||
35 | struct snd_soc_card card; | ||
36 | struct snd_soc_dai_link dai_link; | ||
37 | struct platform_device *pdev; | ||
38 | struct device_node *platform_node; | ||
39 | struct device_node *codec_node; | ||
40 | }; | ||
41 | |||
42 | static struct snd_soc_ops of_snd_soc_ops = { | ||
43 | }; | ||
44 | |||
45 | static struct of_snd_soc_device * | ||
46 | of_snd_soc_get_device(struct device_node *codec_node) | ||
47 | { | ||
48 | struct of_snd_soc_device *of_soc; | ||
49 | |||
50 | list_for_each_entry(of_soc, &of_snd_soc_device_list, list) { | ||
51 | if (of_soc->codec_node == codec_node) | ||
52 | return of_soc; | ||
53 | } | ||
54 | |||
55 | of_soc = kzalloc(sizeof(struct of_snd_soc_device), GFP_KERNEL); | ||
56 | if (!of_soc) | ||
57 | return NULL; | ||
58 | |||
59 | /* Initialize the structure and add it to the global list */ | ||
60 | of_soc->codec_node = codec_node; | ||
61 | of_soc->id = of_snd_soc_next_index++; | ||
62 | of_soc->card.dai_link = &of_soc->dai_link; | ||
63 | of_soc->card.num_links = 1; | ||
64 | of_soc->device.card = &of_soc->card; | ||
65 | of_soc->dai_link.ops = &of_snd_soc_ops; | ||
66 | list_add(&of_soc->list, &of_snd_soc_device_list); | ||
67 | |||
68 | return of_soc; | ||
69 | } | ||
70 | |||
71 | static void of_snd_soc_register_device(struct of_snd_soc_device *of_soc) | ||
72 | { | ||
73 | struct platform_device *pdev; | ||
74 | int rc; | ||
75 | |||
76 | /* Only register the device if both the codec and platform have | ||
77 | * been registered */ | ||
78 | if ((!of_soc->device.codec_data) || (!of_soc->platform_node)) | ||
79 | return; | ||
80 | |||
81 | pr_info("platform<-->codec match achieved; registering machine\n"); | ||
82 | |||
83 | pdev = platform_device_alloc("soc-audio", of_soc->id); | ||
84 | if (!pdev) { | ||
85 | pr_err("of_soc: platform_device_alloc() failed\n"); | ||
86 | return; | ||
87 | } | ||
88 | |||
89 | pdev->dev.platform_data = of_soc; | ||
90 | platform_set_drvdata(pdev, &of_soc->device); | ||
91 | of_soc->device.dev = &pdev->dev; | ||
92 | |||
93 | /* The ASoC device is complete; register it */ | ||
94 | rc = platform_device_add(pdev); | ||
95 | if (rc) { | ||
96 | pr_err("of_soc: platform_device_add() failed\n"); | ||
97 | return; | ||
98 | } | ||
99 | |||
100 | } | ||
101 | |||
102 | int of_snd_soc_register_codec(struct snd_soc_codec_device *codec_dev, | ||
103 | void *codec_data, struct snd_soc_dai *dai, | ||
104 | struct device_node *node) | ||
105 | { | ||
106 | struct of_snd_soc_device *of_soc; | ||
107 | int rc = 0; | ||
108 | |||
109 | pr_info("registering ASoC codec driver: %s\n", node->full_name); | ||
110 | |||
111 | mutex_lock(&of_snd_soc_mutex); | ||
112 | of_soc = of_snd_soc_get_device(node); | ||
113 | if (!of_soc) { | ||
114 | rc = -ENOMEM; | ||
115 | goto out; | ||
116 | } | ||
117 | |||
118 | /* Store the codec data */ | ||
119 | of_soc->device.codec_data = codec_data; | ||
120 | of_soc->device.codec_dev = codec_dev; | ||
121 | of_soc->dai_link.name = (char *)node->name; | ||
122 | of_soc->dai_link.stream_name = (char *)node->name; | ||
123 | of_soc->dai_link.codec_dai = dai; | ||
124 | |||
125 | /* Now try to register the SoC device */ | ||
126 | of_snd_soc_register_device(of_soc); | ||
127 | |||
128 | out: | ||
129 | mutex_unlock(&of_snd_soc_mutex); | ||
130 | return rc; | ||
131 | } | ||
132 | EXPORT_SYMBOL_GPL(of_snd_soc_register_codec); | ||
133 | |||
134 | int of_snd_soc_register_platform(struct snd_soc_platform *platform, | ||
135 | struct device_node *node, | ||
136 | struct snd_soc_dai *cpu_dai) | ||
137 | { | ||
138 | struct of_snd_soc_device *of_soc; | ||
139 | struct device_node *codec_node; | ||
140 | const phandle *handle; | ||
141 | int len, rc = 0; | ||
142 | |||
143 | pr_info("registering ASoC platform driver: %s\n", node->full_name); | ||
144 | |||
145 | handle = of_get_property(node, "codec-handle", &len); | ||
146 | if (!handle || len < sizeof(handle)) | ||
147 | return -ENODEV; | ||
148 | codec_node = of_find_node_by_phandle(*handle); | ||
149 | if (!codec_node) | ||
150 | return -ENODEV; | ||
151 | pr_info("looking for codec: %s\n", codec_node->full_name); | ||
152 | |||
153 | mutex_lock(&of_snd_soc_mutex); | ||
154 | of_soc = of_snd_soc_get_device(codec_node); | ||
155 | if (!of_soc) { | ||
156 | rc = -ENOMEM; | ||
157 | goto out; | ||
158 | } | ||
159 | |||
160 | of_soc->platform_node = node; | ||
161 | of_soc->dai_link.cpu_dai = cpu_dai; | ||
162 | of_soc->card.platform = platform; | ||
163 | of_soc->card.name = of_soc->dai_link.cpu_dai->name; | ||
164 | |||
165 | /* Now try to register the SoC device */ | ||
166 | of_snd_soc_register_device(of_soc); | ||
167 | |||
168 | out: | ||
169 | mutex_unlock(&of_snd_soc_mutex); | ||
170 | return rc; | ||
171 | } | ||
172 | EXPORT_SYMBOL_GPL(of_snd_soc_register_platform); | ||
diff --git a/sound/soc/imx/Kconfig b/sound/soc/imx/Kconfig index 52dac5e3874c..66ba26393c10 100644 --- a/sound/soc/imx/Kconfig +++ b/sound/soc/imx/Kconfig | |||
@@ -8,12 +8,24 @@ menuconfig SND_IMX_SOC | |||
8 | Say Y or M if you want to add support for codecs attached to | 8 | Say Y or M if you want to add support for codecs attached to |
9 | the i.MX SSI interface. | 9 | the i.MX SSI interface. |
10 | 10 | ||
11 | |||
11 | if SND_IMX_SOC | 12 | if SND_IMX_SOC |
12 | 13 | ||
14 | config SND_MXC_SOC_SSI | ||
15 | tristate | ||
16 | |||
17 | config SND_MXC_SOC_FIQ | ||
18 | tristate | ||
19 | |||
20 | config SND_MXC_SOC_MX2 | ||
21 | tristate | ||
22 | |||
13 | config SND_MXC_SOC_WM1133_EV1 | 23 | config SND_MXC_SOC_WM1133_EV1 |
14 | tristate "Audio on the the i.MX31ADS with WM1133-EV1 fitted" | 24 | tristate "Audio on the the i.MX31ADS with WM1133-EV1 fitted" |
15 | depends on MACH_MX31ADS_WM1133_EV1 && EXPERIMENTAL | 25 | depends on MACH_MX31ADS_WM1133_EV1 && EXPERIMENTAL |
16 | select SND_SOC_WM8350 | 26 | select SND_SOC_WM8350 |
27 | select SND_MXC_SOC_SSI | ||
28 | select SND_MXC_SOC_FIQ | ||
17 | help | 29 | help |
18 | Enable support for audio on the i.MX31ADS with the WM1133-EV1 | 30 | Enable support for audio on the i.MX31ADS with the WM1133-EV1 |
19 | PMIC board with WM8835x fitted. | 31 | PMIC board with WM8835x fitted. |
@@ -22,6 +34,8 @@ config SND_SOC_PHYCORE_AC97 | |||
22 | tristate "SoC Audio support for Phytec phyCORE (and phyCARD) boards" | 34 | tristate "SoC Audio support for Phytec phyCORE (and phyCARD) boards" |
23 | depends on MACH_PCM043 || MACH_PCA100 | 35 | depends on MACH_PCM043 || MACH_PCA100 |
24 | select SND_SOC_WM9712 | 36 | select SND_SOC_WM9712 |
37 | select SND_MXC_SOC_SSI | ||
38 | select SND_MXC_SOC_FIQ | ||
25 | help | 39 | help |
26 | Say Y if you want to add support for SoC audio on Phytec phyCORE | 40 | Say Y if you want to add support for SoC audio on Phytec phyCORE |
27 | and phyCARD boards in AC97 mode | 41 | and phyCARD boards in AC97 mode |
@@ -30,6 +44,8 @@ config SND_SOC_EUKREA_TLV320 | |||
30 | tristate "Eukrea TLV320" | 44 | tristate "Eukrea TLV320" |
31 | depends on MACH_EUKREA_MBIMX27_BASEBOARD || MACH_EUKREA_MBIMXSD_BASEBOARD | 45 | depends on MACH_EUKREA_MBIMX27_BASEBOARD || MACH_EUKREA_MBIMXSD_BASEBOARD |
32 | select SND_SOC_TLV320AIC23 | 46 | select SND_SOC_TLV320AIC23 |
47 | select SND_MXC_SOC_SSI | ||
48 | select SND_MXC_SOC_FIQ | ||
33 | help | 49 | help |
34 | Enable I2S based access to the TLV320AIC23B codec attached | 50 | Enable I2S based access to the TLV320AIC23B codec attached |
35 | to the SSI interface | 51 | to the SSI interface |
diff --git a/sound/soc/imx/Makefile b/sound/soc/imx/Makefile index 7bc57baf2b0e..b67fc02a4ecc 100644 --- a/sound/soc/imx/Makefile +++ b/sound/soc/imx/Makefile | |||
@@ -1,11 +1,11 @@ | |||
1 | # i.MX Platform Support | 1 | # i.MX Platform Support |
2 | snd-soc-imx-objs := imx-ssi.o imx-pcm-fiq.o | 2 | snd-soc-imx-objs := imx-ssi.o |
3 | 3 | snd-soc-imx-fiq-objs := imx-pcm-fiq.o | |
4 | ifdef CONFIG_MACH_MX27 | 4 | snd-soc-imx-mx2-objs := imx-pcm-dma-mx2.o |
5 | snd-soc-imx-objs += imx-pcm-dma-mx2.o | ||
6 | endif | ||
7 | 5 | ||
8 | obj-$(CONFIG_SND_IMX_SOC) += snd-soc-imx.o | 6 | obj-$(CONFIG_SND_IMX_SOC) += snd-soc-imx.o |
7 | obj-$(CONFIG_SND_MXC_SOC_FIQ) += snd-soc-imx-fiq.o | ||
8 | obj-$(CONFIG_SND_MXC_SOC_MX2) += snd-soc-imx-mx2.o | ||
9 | 9 | ||
10 | # i.MX Machine Support | 10 | # i.MX Machine Support |
11 | snd-soc-eukrea-tlv320-objs := eukrea-tlv320.o | 11 | snd-soc-eukrea-tlv320-objs := eukrea-tlv320.o |
diff --git a/sound/soc/imx/eukrea-tlv320.c b/sound/soc/imx/eukrea-tlv320.c index f15dfbdc47ee..807f736ee294 100644 --- a/sound/soc/imx/eukrea-tlv320.c +++ b/sound/soc/imx/eukrea-tlv320.c | |||
@@ -79,22 +79,19 @@ static struct snd_soc_ops eukrea_tlv320_snd_ops = { | |||
79 | static struct snd_soc_dai_link eukrea_tlv320_dai = { | 79 | static struct snd_soc_dai_link eukrea_tlv320_dai = { |
80 | .name = "tlv320aic23", | 80 | .name = "tlv320aic23", |
81 | .stream_name = "TLV320AIC23", | 81 | .stream_name = "TLV320AIC23", |
82 | .codec_dai = &tlv320aic23_dai, | 82 | .codec_dai = "tlv320aic23-hifi", |
83 | .platform_name = "imx-pcm-audio.0", | ||
84 | .codec_name = "tlv320aic23-codec.0-001a", | ||
85 | .cpu_dai = "imx-ssi-dai.0", | ||
83 | .ops = &eukrea_tlv320_snd_ops, | 86 | .ops = &eukrea_tlv320_snd_ops, |
84 | }; | 87 | }; |
85 | 88 | ||
86 | static struct snd_soc_card eukrea_tlv320 = { | 89 | static struct snd_soc_card eukrea_tlv320 = { |
87 | .name = "cpuimx-audio", | 90 | .name = "cpuimx-audio", |
88 | .platform = &imx_soc_platform, | ||
89 | .dai_link = &eukrea_tlv320_dai, | 91 | .dai_link = &eukrea_tlv320_dai, |
90 | .num_links = 1, | 92 | .num_links = 1, |
91 | }; | 93 | }; |
92 | 94 | ||
93 | static struct snd_soc_device eukrea_tlv320_snd_devdata = { | ||
94 | .card = &eukrea_tlv320, | ||
95 | .codec_dev = &soc_codec_dev_tlv320aic23, | ||
96 | }; | ||
97 | |||
98 | static struct platform_device *eukrea_tlv320_snd_device; | 95 | static struct platform_device *eukrea_tlv320_snd_device; |
99 | 96 | ||
100 | static int __init eukrea_tlv320_init(void) | 97 | static int __init eukrea_tlv320_init(void) |
@@ -110,10 +107,7 @@ static int __init eukrea_tlv320_init(void) | |||
110 | if (!eukrea_tlv320_snd_device) | 107 | if (!eukrea_tlv320_snd_device) |
111 | return -ENOMEM; | 108 | return -ENOMEM; |
112 | 109 | ||
113 | eukrea_tlv320_dai.cpu_dai = &imx_ssi_pcm_dai[0]; | 110 | platform_set_drvdata(eukrea_tlv320_snd_device, &eukrea_tlv320); |
114 | |||
115 | platform_set_drvdata(eukrea_tlv320_snd_device, &eukrea_tlv320_snd_devdata); | ||
116 | eukrea_tlv320_snd_devdata.dev = &eukrea_tlv320_snd_device->dev; | ||
117 | ret = platform_device_add(eukrea_tlv320_snd_device); | 111 | ret = platform_device_add(eukrea_tlv320_snd_device); |
118 | 112 | ||
119 | if (ret) { | 113 | if (ret) { |
diff --git a/sound/soc/imx/imx-pcm-dma-mx2.c b/sound/soc/imx/imx-pcm-dma-mx2.c index 0a595da4811d..fd493ee1428e 100644 --- a/sound/soc/imx/imx-pcm-dma-mx2.c +++ b/sound/soc/imx/imx-pcm-dma-mx2.c | |||
@@ -103,7 +103,7 @@ static int imx_ssi_dma_alloc(struct snd_pcm_substream *substream) | |||
103 | struct imx_pcm_runtime_data *iprtd = runtime->private_data; | 103 | struct imx_pcm_runtime_data *iprtd = runtime->private_data; |
104 | int ret; | 104 | int ret; |
105 | 105 | ||
106 | dma_params = snd_soc_dai_get_dma_data(rtd->dai->cpu_dai, substream); | 106 | dma_params = snd_soc_dai_get_dma_data(rtd->cpu_dai, substream); |
107 | 107 | ||
108 | iprtd->dma = imx_dma_request_by_prio(DRV_NAME, DMA_PRIO_HIGH); | 108 | iprtd->dma = imx_dma_request_by_prio(DRV_NAME, DMA_PRIO_HIGH); |
109 | if (iprtd->dma < 0) { | 109 | if (iprtd->dma < 0) { |
@@ -213,7 +213,7 @@ static int snd_imx_pcm_prepare(struct snd_pcm_substream *substream) | |||
213 | struct imx_pcm_runtime_data *iprtd = runtime->private_data; | 213 | struct imx_pcm_runtime_data *iprtd = runtime->private_data; |
214 | int err; | 214 | int err; |
215 | 215 | ||
216 | dma_params = snd_soc_dai_get_dma_data(rtd->dai->cpu_dai, substream); | 216 | dma_params = snd_soc_dai_get_dma_data(rtd->cpu_dai, substream); |
217 | 217 | ||
218 | iprtd->substream = substream; | 218 | iprtd->substream = substream; |
219 | iprtd->buf = (unsigned int *)substream->dma_buffer.area; | 219 | iprtd->buf = (unsigned int *)substream->dma_buffer.area; |
@@ -318,19 +318,42 @@ static struct snd_pcm_ops imx_pcm_ops = { | |||
318 | .mmap = snd_imx_pcm_mmap, | 318 | .mmap = snd_imx_pcm_mmap, |
319 | }; | 319 | }; |
320 | 320 | ||
321 | static struct snd_soc_platform imx_soc_platform_dma = { | 321 | static struct snd_soc_platform_driver imx_soc_platform_mx2 = { |
322 | .name = "imx-audio", | 322 | .ops = &imx_pcm_ops, |
323 | .pcm_ops = &imx_pcm_ops, | ||
324 | .pcm_new = imx_pcm_new, | 323 | .pcm_new = imx_pcm_new, |
325 | .pcm_free = imx_pcm_free, | 324 | .pcm_free = imx_pcm_free, |
326 | }; | 325 | }; |
327 | 326 | ||
328 | struct snd_soc_platform *imx_ssi_dma_mx2_init(struct platform_device *pdev, | 327 | static int __devinit imx_soc_platform_probe(struct platform_device *pdev) |
329 | struct imx_ssi *ssi) | ||
330 | { | 328 | { |
331 | ssi->dma_params_tx.burstsize = DMA_TXFIFO_BURST; | 329 | return snd_soc_register_platform(&pdev->dev, &imx_soc_platform_mx2); |
332 | ssi->dma_params_rx.burstsize = DMA_RXFIFO_BURST; | 330 | } |
331 | |||
332 | static int __devexit imx_soc_platform_remove(struct platform_device *pdev) | ||
333 | { | ||
334 | snd_soc_unregister_platform(&pdev->dev); | ||
335 | return 0; | ||
336 | } | ||
337 | |||
338 | static struct platform_driver imx_pcm_driver = { | ||
339 | .driver = { | ||
340 | .name = "imx-pcm-audio", | ||
341 | .owner = THIS_MODULE, | ||
342 | }, | ||
333 | 343 | ||
334 | return &imx_soc_platform_dma; | 344 | .probe = imx_soc_platform_probe, |
345 | .remove = __devexit_p(imx_soc_platform_remove), | ||
346 | }; | ||
347 | |||
348 | static int __init snd_imx_pcm_init(void) | ||
349 | { | ||
350 | return platform_driver_register(&imx_pcm_driver); | ||
351 | } | ||
352 | module_init(snd_imx_pcm_init); | ||
353 | |||
354 | static void __exit snd_imx_pcm_exit(void) | ||
355 | { | ||
356 | platform_driver_unregister(&imx_pcm_driver); | ||
335 | } | 357 | } |
358 | module_exit(snd_imx_pcm_exit); | ||
336 | 359 | ||
diff --git a/sound/soc/imx/imx-pcm-fiq.c b/sound/soc/imx/imx-pcm-fiq.c index b2bf27282cd2..413b78da248f 100644 --- a/sound/soc/imx/imx-pcm-fiq.c +++ b/sound/soc/imx/imx-pcm-fiq.c | |||
@@ -236,6 +236,8 @@ static struct snd_pcm_ops imx_pcm_ops = { | |||
236 | .mmap = snd_imx_pcm_mmap, | 236 | .mmap = snd_imx_pcm_mmap, |
237 | }; | 237 | }; |
238 | 238 | ||
239 | static int ssi_irq = 0; | ||
240 | |||
239 | static int imx_pcm_fiq_new(struct snd_card *card, struct snd_soc_dai *dai, | 241 | static int imx_pcm_fiq_new(struct snd_card *card, struct snd_soc_dai *dai, |
240 | struct snd_pcm *pcm) | 242 | struct snd_pcm *pcm) |
241 | { | 243 | { |
@@ -245,7 +247,7 @@ static int imx_pcm_fiq_new(struct snd_card *card, struct snd_soc_dai *dai, | |||
245 | if (ret) | 247 | if (ret) |
246 | return ret; | 248 | return ret; |
247 | 249 | ||
248 | if (dai->playback.channels_min) { | 250 | if (dai->driver->playback.channels_min) { |
249 | struct snd_pcm_substream *substream = | 251 | struct snd_pcm_substream *substream = |
250 | pcm->streams[SNDRV_PCM_STREAM_PLAYBACK].substream; | 252 | pcm->streams[SNDRV_PCM_STREAM_PLAYBACK].substream; |
251 | struct snd_dma_buffer *buf = &substream->dma_buffer; | 253 | struct snd_dma_buffer *buf = &substream->dma_buffer; |
@@ -253,7 +255,7 @@ static int imx_pcm_fiq_new(struct snd_card *card, struct snd_soc_dai *dai, | |||
253 | imx_ssi_fiq_tx_buffer = (unsigned long)buf->area; | 255 | imx_ssi_fiq_tx_buffer = (unsigned long)buf->area; |
254 | } | 256 | } |
255 | 257 | ||
256 | if (dai->capture.channels_min) { | 258 | if (dai->driver->capture.channels_min) { |
257 | struct snd_pcm_substream *substream = | 259 | struct snd_pcm_substream *substream = |
258 | pcm->streams[SNDRV_PCM_STREAM_CAPTURE].substream; | 260 | pcm->streams[SNDRV_PCM_STREAM_CAPTURE].substream; |
259 | struct snd_dma_buffer *buf = &substream->dma_buffer; | 261 | struct snd_dma_buffer *buf = &substream->dma_buffer; |
@@ -267,24 +269,32 @@ static int imx_pcm_fiq_new(struct snd_card *card, struct snd_soc_dai *dai, | |||
267 | return 0; | 269 | return 0; |
268 | } | 270 | } |
269 | 271 | ||
270 | static struct snd_soc_platform imx_soc_platform_fiq = { | 272 | static void imx_pcm_fiq_free(struct snd_pcm *pcm) |
271 | .pcm_ops = &imx_pcm_ops, | 273 | { |
274 | mxc_set_irq_fiq(ssi_irq, 0); | ||
275 | release_fiq(&fh); | ||
276 | imx_pcm_free(pcm); | ||
277 | } | ||
278 | |||
279 | static struct snd_soc_platform_driver imx_soc_platform_fiq = { | ||
280 | .ops = &imx_pcm_ops, | ||
272 | .pcm_new = imx_pcm_fiq_new, | 281 | .pcm_new = imx_pcm_fiq_new, |
273 | .pcm_free = imx_pcm_free, | 282 | .pcm_free = imx_pcm_fiq_free, |
274 | }; | 283 | }; |
275 | 284 | ||
276 | struct snd_soc_platform *imx_ssi_fiq_init(struct platform_device *pdev, | 285 | static int __devinit imx_soc_platform_probe(struct platform_device *pdev) |
277 | struct imx_ssi *ssi) | ||
278 | { | 286 | { |
279 | int ret = 0; | 287 | struct imx_ssi *ssi = platform_get_drvdata(pdev); |
288 | int ret; | ||
280 | 289 | ||
281 | ret = claim_fiq(&fh); | 290 | ret = claim_fiq(&fh); |
282 | if (ret) { | 291 | if (ret) { |
283 | dev_err(&pdev->dev, "failed to claim fiq: %d", ret); | 292 | dev_err(&pdev->dev, "failed to claim fiq: %d", ret); |
284 | return ERR_PTR(ret); | 293 | return ret; |
285 | } | 294 | } |
286 | 295 | ||
287 | mxc_set_irq_fiq(ssi->irq, 1); | 296 | mxc_set_irq_fiq(ssi->irq, 1); |
297 | ssi_irq = ssi->irq; | ||
288 | 298 | ||
289 | imx_pcm_fiq = ssi->irq; | 299 | imx_pcm_fiq = ssi->irq; |
290 | 300 | ||
@@ -293,13 +303,43 @@ struct snd_soc_platform *imx_ssi_fiq_init(struct platform_device *pdev, | |||
293 | ssi->dma_params_tx.burstsize = 4; | 303 | ssi->dma_params_tx.burstsize = 4; |
294 | ssi->dma_params_rx.burstsize = 6; | 304 | ssi->dma_params_rx.burstsize = 6; |
295 | 305 | ||
296 | return &imx_soc_platform_fiq; | 306 | ret = snd_soc_register_platform(&pdev->dev, &imx_soc_platform_fiq); |
307 | if (ret) | ||
308 | goto failed_register; | ||
309 | |||
310 | return 0; | ||
311 | |||
312 | failed_register: | ||
313 | mxc_set_irq_fiq(ssi_irq, 0); | ||
314 | release_fiq(&fh); | ||
315 | |||
316 | return ret; | ||
297 | } | 317 | } |
298 | 318 | ||
299 | void imx_ssi_fiq_exit(struct platform_device *pdev, | 319 | static int __devexit imx_soc_platform_remove(struct platform_device *pdev) |
300 | struct imx_ssi *ssi) | ||
301 | { | 320 | { |
302 | mxc_set_irq_fiq(ssi->irq, 0); | 321 | snd_soc_unregister_platform(&pdev->dev); |
303 | release_fiq(&fh); | 322 | return 0; |
304 | } | 323 | } |
305 | 324 | ||
325 | static struct platform_driver imx_pcm_driver = { | ||
326 | .driver = { | ||
327 | .name = "imx-fiq-pcm-audio", | ||
328 | .owner = THIS_MODULE, | ||
329 | }, | ||
330 | |||
331 | .probe = imx_soc_platform_probe, | ||
332 | .remove = __devexit_p(imx_soc_platform_remove), | ||
333 | }; | ||
334 | |||
335 | static int __init snd_imx_pcm_init(void) | ||
336 | { | ||
337 | return platform_driver_register(&imx_pcm_driver); | ||
338 | } | ||
339 | module_init(snd_imx_pcm_init); | ||
340 | |||
341 | static void __exit snd_imx_pcm_exit(void) | ||
342 | { | ||
343 | platform_driver_unregister(&imx_pcm_driver); | ||
344 | } | ||
345 | module_exit(snd_imx_pcm_exit); | ||
diff --git a/sound/soc/imx/imx-ssi.c b/sound/soc/imx/imx-ssi.c index 50f51624c535..02a3e7c799d8 100644 --- a/sound/soc/imx/imx-ssi.c +++ b/sound/soc/imx/imx-ssi.c | |||
@@ -61,7 +61,7 @@ | |||
61 | static int imx_ssi_set_dai_tdm_slot(struct snd_soc_dai *cpu_dai, | 61 | static int imx_ssi_set_dai_tdm_slot(struct snd_soc_dai *cpu_dai, |
62 | unsigned int tx_mask, unsigned int rx_mask, int slots, int slot_width) | 62 | unsigned int tx_mask, unsigned int rx_mask, int slots, int slot_width) |
63 | { | 63 | { |
64 | struct imx_ssi *ssi = cpu_dai->private_data; | 64 | struct imx_ssi *ssi = snd_soc_dai_get_drvdata(cpu_dai); |
65 | u32 sccr; | 65 | u32 sccr; |
66 | 66 | ||
67 | sccr = readl(ssi->base + SSI_STCCR); | 67 | sccr = readl(ssi->base + SSI_STCCR); |
@@ -86,7 +86,7 @@ static int imx_ssi_set_dai_tdm_slot(struct snd_soc_dai *cpu_dai, | |||
86 | */ | 86 | */ |
87 | static int imx_ssi_set_dai_fmt(struct snd_soc_dai *cpu_dai, unsigned int fmt) | 87 | static int imx_ssi_set_dai_fmt(struct snd_soc_dai *cpu_dai, unsigned int fmt) |
88 | { | 88 | { |
89 | struct imx_ssi *ssi = cpu_dai->private_data; | 89 | struct imx_ssi *ssi = snd_soc_dai_get_drvdata(cpu_dai); |
90 | u32 strcr = 0, scr; | 90 | u32 strcr = 0, scr; |
91 | 91 | ||
92 | scr = readl(ssi->base + SSI_SCR) & ~(SSI_SCR_SYN | SSI_SCR_NET); | 92 | scr = readl(ssi->base + SSI_SCR) & ~(SSI_SCR_SYN | SSI_SCR_NET); |
@@ -164,7 +164,7 @@ static int imx_ssi_set_dai_fmt(struct snd_soc_dai *cpu_dai, unsigned int fmt) | |||
164 | static int imx_ssi_set_dai_sysclk(struct snd_soc_dai *cpu_dai, | 164 | static int imx_ssi_set_dai_sysclk(struct snd_soc_dai *cpu_dai, |
165 | int clk_id, unsigned int freq, int dir) | 165 | int clk_id, unsigned int freq, int dir) |
166 | { | 166 | { |
167 | struct imx_ssi *ssi = cpu_dai->private_data; | 167 | struct imx_ssi *ssi = snd_soc_dai_get_drvdata(cpu_dai); |
168 | u32 scr; | 168 | u32 scr; |
169 | 169 | ||
170 | scr = readl(ssi->base + SSI_SCR); | 170 | scr = readl(ssi->base + SSI_SCR); |
@@ -192,7 +192,7 @@ static int imx_ssi_set_dai_sysclk(struct snd_soc_dai *cpu_dai, | |||
192 | static int imx_ssi_set_dai_clkdiv(struct snd_soc_dai *cpu_dai, | 192 | static int imx_ssi_set_dai_clkdiv(struct snd_soc_dai *cpu_dai, |
193 | int div_id, int div) | 193 | int div_id, int div) |
194 | { | 194 | { |
195 | struct imx_ssi *ssi = cpu_dai->private_data; | 195 | struct imx_ssi *ssi = snd_soc_dai_get_drvdata(cpu_dai); |
196 | u32 stccr, srccr; | 196 | u32 stccr, srccr; |
197 | 197 | ||
198 | stccr = readl(ssi->base + SSI_STCCR); | 198 | stccr = readl(ssi->base + SSI_STCCR); |
@@ -241,7 +241,7 @@ static int imx_ssi_hw_params(struct snd_pcm_substream *substream, | |||
241 | struct snd_pcm_hw_params *params, | 241 | struct snd_pcm_hw_params *params, |
242 | struct snd_soc_dai *cpu_dai) | 242 | struct snd_soc_dai *cpu_dai) |
243 | { | 243 | { |
244 | struct imx_ssi *ssi = cpu_dai->private_data; | 244 | struct imx_ssi *ssi = snd_soc_dai_get_drvdata(cpu_dai); |
245 | struct imx_pcm_dma_params *dma_data; | 245 | struct imx_pcm_dma_params *dma_data; |
246 | u32 reg, sccr; | 246 | u32 reg, sccr; |
247 | 247 | ||
@@ -279,9 +279,7 @@ static int imx_ssi_hw_params(struct snd_pcm_substream *substream, | |||
279 | static int imx_ssi_trigger(struct snd_pcm_substream *substream, int cmd, | 279 | static int imx_ssi_trigger(struct snd_pcm_substream *substream, int cmd, |
280 | struct snd_soc_dai *dai) | 280 | struct snd_soc_dai *dai) |
281 | { | 281 | { |
282 | struct snd_soc_pcm_runtime *rtd = substream->private_data; | 282 | struct imx_ssi *ssi = snd_soc_dai_get_drvdata(dai); |
283 | struct snd_soc_dai *cpu_dai = rtd->dai->cpu_dai; | ||
284 | struct imx_ssi *ssi = cpu_dai->private_data; | ||
285 | unsigned int sier_bits, sier; | 283 | unsigned int sier_bits, sier; |
286 | unsigned int scr; | 284 | unsigned int scr; |
287 | 285 | ||
@@ -350,22 +348,6 @@ static struct snd_soc_dai_ops imx_ssi_pcm_dai_ops = { | |||
350 | .trigger = imx_ssi_trigger, | 348 | .trigger = imx_ssi_trigger, |
351 | }; | 349 | }; |
352 | 350 | ||
353 | static struct snd_soc_dai imx_ssi_dai = { | ||
354 | .playback = { | ||
355 | .channels_min = 2, | ||
356 | .channels_max = 2, | ||
357 | .rates = SNDRV_PCM_RATE_8000_96000, | ||
358 | .formats = SNDRV_PCM_FMTBIT_S16_LE, | ||
359 | }, | ||
360 | .capture = { | ||
361 | .channels_min = 2, | ||
362 | .channels_max = 2, | ||
363 | .rates = SNDRV_PCM_RATE_8000_96000, | ||
364 | .formats = SNDRV_PCM_FMTBIT_S16_LE, | ||
365 | }, | ||
366 | .ops = &imx_ssi_pcm_dai_ops, | ||
367 | }; | ||
368 | |||
369 | int snd_imx_pcm_mmap(struct snd_pcm_substream *substream, | 351 | int snd_imx_pcm_mmap(struct snd_pcm_substream *substream, |
370 | struct vm_area_struct *vma) | 352 | struct vm_area_struct *vma) |
371 | { | 353 | { |
@@ -381,6 +363,7 @@ int snd_imx_pcm_mmap(struct snd_pcm_substream *substream, | |||
381 | runtime->dma_bytes); | 363 | runtime->dma_bytes); |
382 | return ret; | 364 | return ret; |
383 | } | 365 | } |
366 | EXPORT_SYMBOL_GPL(snd_imx_pcm_mmap); | ||
384 | 367 | ||
385 | static int imx_pcm_preallocate_dma_buffer(struct snd_pcm *pcm, int stream) | 368 | static int imx_pcm_preallocate_dma_buffer(struct snd_pcm *pcm, int stream) |
386 | { | 369 | { |
@@ -412,14 +395,14 @@ int imx_pcm_new(struct snd_card *card, struct snd_soc_dai *dai, | |||
412 | card->dev->dma_mask = &imx_pcm_dmamask; | 395 | card->dev->dma_mask = &imx_pcm_dmamask; |
413 | if (!card->dev->coherent_dma_mask) | 396 | if (!card->dev->coherent_dma_mask) |
414 | card->dev->coherent_dma_mask = DMA_BIT_MASK(32); | 397 | card->dev->coherent_dma_mask = DMA_BIT_MASK(32); |
415 | if (dai->playback.channels_min) { | 398 | if (dai->driver->playback.channels_min) { |
416 | ret = imx_pcm_preallocate_dma_buffer(pcm, | 399 | ret = imx_pcm_preallocate_dma_buffer(pcm, |
417 | SNDRV_PCM_STREAM_PLAYBACK); | 400 | SNDRV_PCM_STREAM_PLAYBACK); |
418 | if (ret) | 401 | if (ret) |
419 | goto out; | 402 | goto out; |
420 | } | 403 | } |
421 | 404 | ||
422 | if (dai->capture.channels_min) { | 405 | if (dai->driver->capture.channels_min) { |
423 | ret = imx_pcm_preallocate_dma_buffer(pcm, | 406 | ret = imx_pcm_preallocate_dma_buffer(pcm, |
424 | SNDRV_PCM_STREAM_CAPTURE); | 407 | SNDRV_PCM_STREAM_CAPTURE); |
425 | if (ret) | 408 | if (ret) |
@@ -429,6 +412,7 @@ int imx_pcm_new(struct snd_card *card, struct snd_soc_dai *dai, | |||
429 | out: | 412 | out: |
430 | return ret; | 413 | return ret; |
431 | } | 414 | } |
415 | EXPORT_SYMBOL_GPL(imx_pcm_new); | ||
432 | 416 | ||
433 | void imx_pcm_free(struct snd_pcm *pcm) | 417 | void imx_pcm_free(struct snd_pcm *pcm) |
434 | { | 418 | { |
@@ -450,14 +434,40 @@ void imx_pcm_free(struct snd_pcm *pcm) | |||
450 | buf->area = NULL; | 434 | buf->area = NULL; |
451 | } | 435 | } |
452 | } | 436 | } |
437 | EXPORT_SYMBOL_GPL(imx_pcm_free); | ||
453 | 438 | ||
454 | struct snd_soc_platform imx_soc_platform = { | 439 | static struct snd_soc_dai_driver imx_ssi_dai = { |
455 | .name = "imx-audio", | 440 | .playback = { |
441 | .channels_min = 2, | ||
442 | .channels_max = 2, | ||
443 | .rates = SNDRV_PCM_RATE_8000_96000, | ||
444 | .formats = SNDRV_PCM_FMTBIT_S16_LE, | ||
445 | }, | ||
446 | .capture = { | ||
447 | .channels_min = 2, | ||
448 | .channels_max = 2, | ||
449 | .rates = SNDRV_PCM_RATE_8000_96000, | ||
450 | .formats = SNDRV_PCM_FMTBIT_S16_LE, | ||
451 | }, | ||
452 | .ops = &imx_ssi_pcm_dai_ops, | ||
456 | }; | 453 | }; |
457 | EXPORT_SYMBOL_GPL(imx_soc_platform); | ||
458 | 454 | ||
459 | static struct snd_soc_dai imx_ac97_dai = { | 455 | static int imx_ssi_dai_probe(struct snd_soc_dai *dai) |
460 | .name = "AC97", | 456 | { |
457 | struct imx_ssi *ssi = dev_get_drvdata(dai->dev); | ||
458 | uint32_t val; | ||
459 | |||
460 | snd_soc_dai_set_drvdata(dai, ssi); | ||
461 | |||
462 | val = SSI_SFCSR_TFWM0(ssi->dma_params_tx.burstsize) | | ||
463 | SSI_SFCSR_RFWM0(ssi->dma_params_rx.burstsize); | ||
464 | writel(val, ssi->base + SSI_SFCSR); | ||
465 | |||
466 | return 0; | ||
467 | } | ||
468 | |||
469 | static struct snd_soc_dai_driver imx_ac97_dai = { | ||
470 | .probe = imx_ssi_dai_probe, | ||
461 | .ac97_control = 1, | 471 | .ac97_control = 1, |
462 | .playback = { | 472 | .playback = { |
463 | .stream_name = "AC97 Playback", | 473 | .stream_name = "AC97 Playback", |
@@ -577,25 +587,18 @@ struct snd_ac97_bus_ops soc_ac97_ops = { | |||
577 | }; | 587 | }; |
578 | EXPORT_SYMBOL_GPL(soc_ac97_ops); | 588 | EXPORT_SYMBOL_GPL(soc_ac97_ops); |
579 | 589 | ||
580 | struct snd_soc_dai imx_ssi_pcm_dai[2]; | ||
581 | EXPORT_SYMBOL_GPL(imx_ssi_pcm_dai); | ||
582 | |||
583 | static int imx_ssi_probe(struct platform_device *pdev) | 590 | static int imx_ssi_probe(struct platform_device *pdev) |
584 | { | 591 | { |
585 | struct resource *res; | 592 | struct resource *res; |
586 | struct imx_ssi *ssi; | 593 | struct imx_ssi *ssi; |
587 | struct imx_ssi_platform_data *pdata = pdev->dev.platform_data; | 594 | struct imx_ssi_platform_data *pdata = pdev->dev.platform_data; |
588 | struct snd_soc_platform *platform; | ||
589 | int ret = 0; | 595 | int ret = 0; |
590 | unsigned int val; | 596 | struct snd_soc_dai_driver *dai; |
591 | struct snd_soc_dai *dai = &imx_ssi_pcm_dai[pdev->id]; | ||
592 | |||
593 | if (dai->id >= ARRAY_SIZE(imx_ssi_pcm_dai)) | ||
594 | return -EINVAL; | ||
595 | 597 | ||
596 | ssi = kzalloc(sizeof(*ssi), GFP_KERNEL); | 598 | ssi = kzalloc(sizeof(*ssi), GFP_KERNEL); |
597 | if (!ssi) | 599 | if (!ssi) |
598 | return -ENOMEM; | 600 | return -ENOMEM; |
601 | dev_set_drvdata(&pdev->dev, ssi); | ||
599 | 602 | ||
600 | if (pdata) { | 603 | if (pdata) { |
601 | ssi->ac97_reset = pdata->ac97_reset; | 604 | ssi->ac97_reset = pdata->ac97_reset; |
@@ -640,9 +643,9 @@ static int imx_ssi_probe(struct platform_device *pdev) | |||
640 | } | 643 | } |
641 | ac97_ssi = ssi; | 644 | ac97_ssi = ssi; |
642 | setup_channel_to_ac97(ssi); | 645 | setup_channel_to_ac97(ssi); |
643 | memcpy(dai, &imx_ac97_dai, sizeof(imx_ac97_dai)); | 646 | dai = &imx_ac97_dai; |
644 | } else | 647 | } else |
645 | memcpy(dai, &imx_ssi_dai, sizeof(imx_ssi_dai)); | 648 | dai = &imx_ssi_dai; |
646 | 649 | ||
647 | writel(0x0, ssi->base + SSI_SIER); | 650 | writel(0x0, ssi->base + SSI_SIER); |
648 | 651 | ||
@@ -657,37 +660,36 @@ static int imx_ssi_probe(struct platform_device *pdev) | |||
657 | if (res) | 660 | if (res) |
658 | ssi->dma_params_rx.dma = res->start; | 661 | ssi->dma_params_rx.dma = res->start; |
659 | 662 | ||
660 | dai->id = pdev->id; | ||
661 | dai->dev = &pdev->dev; | ||
662 | dai->name = kasprintf(GFP_KERNEL, "imx-ssi.%d", pdev->id); | ||
663 | dai->private_data = ssi; | ||
664 | |||
665 | if ((cpu_is_mx27() || cpu_is_mx21()) && | 663 | if ((cpu_is_mx27() || cpu_is_mx21()) && |
666 | !(ssi->flags & IMX_SSI_USE_AC97) && | 664 | !(ssi->flags & IMX_SSI_USE_AC97) && |
667 | (ssi->flags & IMX_SSI_DMA)) { | 665 | (ssi->flags & IMX_SSI_DMA)) { |
668 | ssi->flags |= IMX_SSI_DMA; | 666 | ssi->flags |= IMX_SSI_DMA; |
669 | platform = imx_ssi_dma_mx2_init(pdev, ssi); | 667 | } |
670 | } else | ||
671 | platform = imx_ssi_fiq_init(pdev, ssi); | ||
672 | |||
673 | imx_soc_platform.pcm_ops = platform->pcm_ops; | ||
674 | imx_soc_platform.pcm_new = platform->pcm_new; | ||
675 | imx_soc_platform.pcm_free = platform->pcm_free; | ||
676 | 668 | ||
677 | val = SSI_SFCSR_TFWM0(ssi->dma_params_tx.burstsize) | | 669 | platform_set_drvdata(pdev, ssi); |
678 | SSI_SFCSR_RFWM0(ssi->dma_params_rx.burstsize); | ||
679 | writel(val, ssi->base + SSI_SFCSR); | ||
680 | 670 | ||
681 | ret = snd_soc_register_dai(dai); | 671 | ret = snd_soc_register_dai(&pdev->dev, dai); |
682 | if (ret) { | 672 | if (ret) { |
683 | dev_err(&pdev->dev, "register DAI failed\n"); | 673 | dev_err(&pdev->dev, "register DAI failed\n"); |
684 | goto failed_register; | 674 | goto failed_register; |
685 | } | 675 | } |
686 | 676 | ||
687 | platform_set_drvdata(pdev, ssi); | 677 | ssi->soc_platform_pdev = platform_device_alloc("imx-fiq-pcm-audio", pdev->id); |
678 | if (!ssi->soc_platform_pdev) | ||
679 | goto failed_pdev_alloc; | ||
680 | platform_set_drvdata(ssi->soc_platform_pdev, ssi); | ||
681 | ret = platform_device_add(ssi->soc_platform_pdev); | ||
682 | if (ret) { | ||
683 | dev_err(&pdev->dev, "failed to add platform device\n"); | ||
684 | goto failed_pdev_add; | ||
685 | } | ||
688 | 686 | ||
689 | return 0; | 687 | return 0; |
690 | 688 | ||
689 | failed_pdev_add: | ||
690 | platform_device_put(ssi->soc_platform_pdev); | ||
691 | failed_pdev_alloc: | ||
692 | snd_soc_unregister_dai(&pdev->dev); | ||
691 | failed_register: | 693 | failed_register: |
692 | failed_ac97: | 694 | failed_ac97: |
693 | iounmap(ssi->base); | 695 | iounmap(ssi->base); |
@@ -706,16 +708,15 @@ static int __devexit imx_ssi_remove(struct platform_device *pdev) | |||
706 | { | 708 | { |
707 | struct resource *res = platform_get_resource(pdev, IORESOURCE_MEM, 0); | 709 | struct resource *res = platform_get_resource(pdev, IORESOURCE_MEM, 0); |
708 | struct imx_ssi *ssi = platform_get_drvdata(pdev); | 710 | struct imx_ssi *ssi = platform_get_drvdata(pdev); |
709 | struct snd_soc_dai *dai = &imx_ssi_pcm_dai[pdev->id]; | ||
710 | 711 | ||
711 | snd_soc_unregister_dai(dai); | 712 | platform_device_del(ssi->soc_platform_pdev); |
713 | platform_device_put(ssi->soc_platform_pdev); | ||
714 | |||
715 | snd_soc_unregister_dai(&pdev->dev); | ||
712 | 716 | ||
713 | if (ssi->flags & IMX_SSI_USE_AC97) | 717 | if (ssi->flags & IMX_SSI_USE_AC97) |
714 | ac97_ssi = NULL; | 718 | ac97_ssi = NULL; |
715 | 719 | ||
716 | if (!(ssi->flags & IMX_SSI_DMA)) | ||
717 | imx_ssi_fiq_exit(pdev, ssi); | ||
718 | |||
719 | iounmap(ssi->base); | 720 | iounmap(ssi->base); |
720 | release_mem_region(res->start, resource_size(res)); | 721 | release_mem_region(res->start, resource_size(res)); |
721 | clk_disable(ssi->clk); | 722 | clk_disable(ssi->clk); |
@@ -730,34 +731,19 @@ static struct platform_driver imx_ssi_driver = { | |||
730 | .remove = __devexit_p(imx_ssi_remove), | 731 | .remove = __devexit_p(imx_ssi_remove), |
731 | 732 | ||
732 | .driver = { | 733 | .driver = { |
733 | .name = DRV_NAME, | 734 | .name = "imx-ssi-dai", |
734 | .owner = THIS_MODULE, | 735 | .owner = THIS_MODULE, |
735 | }, | 736 | }, |
736 | }; | 737 | }; |
737 | 738 | ||
738 | static int __init imx_ssi_init(void) | 739 | static int __init imx_ssi_init(void) |
739 | { | 740 | { |
740 | int ret; | 741 | return platform_driver_register(&imx_ssi_driver); |
741 | |||
742 | ret = snd_soc_register_platform(&imx_soc_platform); | ||
743 | if (ret) { | ||
744 | pr_err("failed to register soc platform: %d\n", ret); | ||
745 | return ret; | ||
746 | } | ||
747 | |||
748 | ret = platform_driver_register(&imx_ssi_driver); | ||
749 | if (ret) { | ||
750 | snd_soc_unregister_platform(&imx_soc_platform); | ||
751 | return ret; | ||
752 | } | ||
753 | |||
754 | return 0; | ||
755 | } | 742 | } |
756 | 743 | ||
757 | static void __exit imx_ssi_exit(void) | 744 | static void __exit imx_ssi_exit(void) |
758 | { | 745 | { |
759 | platform_driver_unregister(&imx_ssi_driver); | 746 | platform_driver_unregister(&imx_ssi_driver); |
760 | snd_soc_unregister_platform(&imx_soc_platform); | ||
761 | } | 747 | } |
762 | 748 | ||
763 | module_init(imx_ssi_init); | 749 | module_init(imx_ssi_init); |
diff --git a/sound/soc/imx/imx-ssi.h b/sound/soc/imx/imx-ssi.h index 55f26ebcd8c2..53b780d9b2b0 100644 --- a/sound/soc/imx/imx-ssi.h +++ b/sound/soc/imx/imx-ssi.h | |||
@@ -183,9 +183,6 @@ | |||
183 | #define IMX_SSI_RX_DIV_PSR 4 | 183 | #define IMX_SSI_RX_DIV_PSR 4 |
184 | #define IMX_SSI_RX_DIV_PM 5 | 184 | #define IMX_SSI_RX_DIV_PM 5 |
185 | 185 | ||
186 | extern struct snd_soc_dai imx_ssi_pcm_dai[2]; | ||
187 | extern struct snd_soc_platform imx_soc_platform; | ||
188 | |||
189 | #define DRV_NAME "imx-ssi" | 186 | #define DRV_NAME "imx-ssi" |
190 | 187 | ||
191 | struct imx_pcm_dma_params { | 188 | struct imx_pcm_dma_params { |
@@ -197,7 +194,7 @@ struct imx_pcm_dma_params { | |||
197 | struct imx_ssi { | 194 | struct imx_ssi { |
198 | struct platform_device *ac97_dev; | 195 | struct platform_device *ac97_dev; |
199 | 196 | ||
200 | struct snd_soc_device imx_ac97; | 197 | struct snd_soc_dai *imx_ac97; |
201 | struct clk *clk; | 198 | struct clk *clk; |
202 | void __iomem *base; | 199 | void __iomem *base; |
203 | int irq; | 200 | int irq; |
@@ -213,6 +210,8 @@ struct imx_ssi { | |||
213 | struct imx_pcm_dma_params dma_params_tx; | 210 | struct imx_pcm_dma_params dma_params_tx; |
214 | 211 | ||
215 | int enabled; | 212 | int enabled; |
213 | |||
214 | struct platform_device *soc_platform_pdev; | ||
216 | }; | 215 | }; |
217 | 216 | ||
218 | struct snd_soc_platform *imx_ssi_fiq_init(struct platform_device *pdev, | 217 | struct snd_soc_platform *imx_ssi_fiq_init(struct platform_device *pdev, |
diff --git a/sound/soc/imx/phycore-ac97.c b/sound/soc/imx/phycore-ac97.c index a8307d55c70e..65f0f99ca6dd 100644 --- a/sound/soc/imx/phycore-ac97.c +++ b/sound/soc/imx/phycore-ac97.c | |||
@@ -32,23 +32,20 @@ static struct snd_soc_dai_link imx_phycore_dai_ac97[] = { | |||
32 | { | 32 | { |
33 | .name = "HiFi", | 33 | .name = "HiFi", |
34 | .stream_name = "HiFi", | 34 | .stream_name = "HiFi", |
35 | .codec_dai = &wm9712_dai[WM9712_DAI_AC97_HIFI], | 35 | .codec_dai_name = "wm9712-hifi", |
36 | .codec_name = "wm9712-codec", | ||
37 | .cpu_dai_name = "imx-ssi-dai.0", | ||
38 | .platform_name = "imx-fiq-pcm-audio.0", | ||
36 | .ops = &imx_phycore_hifi_ops, | 39 | .ops = &imx_phycore_hifi_ops, |
37 | }, | 40 | }, |
38 | }; | 41 | }; |
39 | 42 | ||
40 | static struct snd_soc_card imx_phycore = { | 43 | static struct snd_soc_card imx_phycore = { |
41 | .name = "PhyCORE-audio", | 44 | .name = "PhyCORE-audio", |
42 | .platform = &imx_soc_platform, | ||
43 | .dai_link = imx_phycore_dai_ac97, | 45 | .dai_link = imx_phycore_dai_ac97, |
44 | .num_links = ARRAY_SIZE(imx_phycore_dai_ac97), | 46 | .num_links = ARRAY_SIZE(imx_phycore_dai_ac97), |
45 | }; | 47 | }; |
46 | 48 | ||
47 | static struct snd_soc_device imx_phycore_snd_devdata = { | ||
48 | .card = &imx_phycore, | ||
49 | .codec_dev = &soc_codec_dev_wm9712, | ||
50 | }; | ||
51 | |||
52 | static struct platform_device *imx_phycore_snd_device; | 49 | static struct platform_device *imx_phycore_snd_device; |
53 | 50 | ||
54 | static int __init imx_phycore_init(void) | 51 | static int __init imx_phycore_init(void) |
@@ -63,10 +60,12 @@ static int __init imx_phycore_init(void) | |||
63 | if (!imx_phycore_snd_device) | 60 | if (!imx_phycore_snd_device) |
64 | return -ENOMEM; | 61 | return -ENOMEM; |
65 | 62 | ||
66 | imx_phycore_dai_ac97[0].cpu_dai = &imx_ssi_pcm_dai[0]; | 63 | platform_set_drvdata(imx_phycore_snd_device, &imx_phycore); |
64 | ret = platform_device_add(imx_phycore_snd_device); | ||
67 | 65 | ||
68 | platform_set_drvdata(imx_phycore_snd_device, &imx_phycore_snd_devdata); | 66 | imx_phycore_snd_device = platform_device_alloc("wm9712-codec", -1); |
69 | imx_phycore_snd_devdata.dev = &imx_phycore_snd_device->dev; | 67 | if (!imx_phycore_snd_device) |
68 | return -ENOMEM; | ||
70 | ret = platform_device_add(imx_phycore_snd_device); | 69 | ret = platform_device_add(imx_phycore_snd_device); |
71 | 70 | ||
72 | if (ret) { | 71 | if (ret) { |
diff --git a/sound/soc/imx/wm1133-ev1.c b/sound/soc/imx/wm1133-ev1.c index a6e7d9497639..74068636c1d8 100644 --- a/sound/soc/imx/wm1133-ev1.c +++ b/sound/soc/imx/wm1133-ev1.c | |||
@@ -82,8 +82,8 @@ static int wm1133_ev1_hw_params(struct snd_pcm_substream *substream, | |||
82 | struct snd_pcm_hw_params *params) | 82 | struct snd_pcm_hw_params *params) |
83 | { | 83 | { |
84 | struct snd_soc_pcm_runtime *rtd = substream->private_data; | 84 | struct snd_soc_pcm_runtime *rtd = substream->private_data; |
85 | struct snd_soc_dai *codec_dai = rtd->dai->codec_dai; | 85 | struct snd_soc_dai *codec_dai = rtd->codec_dai; |
86 | struct snd_soc_dai *cpu_dai = rtd->dai->cpu_dai; | 86 | struct snd_soc_dai *cpu_dai = rtd->cpu_dai; |
87 | int i, found = 0; | 87 | int i, found = 0; |
88 | snd_pcm_format_t format = params_format(params); | 88 | snd_pcm_format_t format = params_format(params); |
89 | unsigned int rate = params_rate(params); | 89 | unsigned int rate = params_rate(params); |
@@ -210,9 +210,9 @@ static struct snd_soc_jack_pin mic_jack_pins[] = { | |||
210 | { .pin = "Mic2 Jack", .mask = SND_JACK_MICROPHONE }, | 210 | { .pin = "Mic2 Jack", .mask = SND_JACK_MICROPHONE }, |
211 | }; | 211 | }; |
212 | 212 | ||
213 | static int wm1133_ev1_init(struct snd_soc_codec *codec) | 213 | static int wm1133_ev1_init(struct snd_soc_pcm_runtime *rtd) |
214 | { | 214 | { |
215 | struct snd_soc_card *card = codec->socdev->card; | 215 | struct snd_soc_codec *codec = rtd->codec; |
216 | 216 | ||
217 | snd_soc_dapm_new_controls(codec, wm1133_ev1_widgets, | 217 | snd_soc_dapm_new_controls(codec, wm1133_ev1_widgets, |
218 | ARRAY_SIZE(wm1133_ev1_widgets)); | 218 | ARRAY_SIZE(wm1133_ev1_widgets)); |
@@ -221,13 +221,13 @@ static int wm1133_ev1_init(struct snd_soc_codec *codec) | |||
221 | ARRAY_SIZE(wm1133_ev1_map)); | 221 | ARRAY_SIZE(wm1133_ev1_map)); |
222 | 222 | ||
223 | /* Headphone jack detection */ | 223 | /* Headphone jack detection */ |
224 | snd_soc_jack_new(card, "Headphone", SND_JACK_HEADPHONE, &hp_jack); | 224 | snd_soc_jack_new(codec, "Headphone", SND_JACK_HEADPHONE, &hp_jack); |
225 | snd_soc_jack_add_pins(&hp_jack, ARRAY_SIZE(hp_jack_pins), | 225 | snd_soc_jack_add_pins(&hp_jack, ARRAY_SIZE(hp_jack_pins), |
226 | hp_jack_pins); | 226 | hp_jack_pins); |
227 | wm8350_hp_jack_detect(codec, WM8350_JDR, &hp_jack, SND_JACK_HEADPHONE); | 227 | wm8350_hp_jack_detect(codec, WM8350_JDR, &hp_jack, SND_JACK_HEADPHONE); |
228 | 228 | ||
229 | /* Microphone jack detection */ | 229 | /* Microphone jack detection */ |
230 | snd_soc_jack_new(card, "Microphone", | 230 | snd_soc_jack_new(codec, "Microphone", |
231 | SND_JACK_MICROPHONE | SND_JACK_BTN_0, &mic_jack); | 231 | SND_JACK_MICROPHONE | SND_JACK_BTN_0, &mic_jack); |
232 | snd_soc_jack_add_pins(&mic_jack, ARRAY_SIZE(mic_jack_pins), | 232 | snd_soc_jack_add_pins(&mic_jack, ARRAY_SIZE(mic_jack_pins), |
233 | mic_jack_pins); | 233 | mic_jack_pins); |
@@ -243,8 +243,10 @@ static int wm1133_ev1_init(struct snd_soc_codec *codec) | |||
243 | static struct snd_soc_dai_link wm1133_ev1_dai = { | 243 | static struct snd_soc_dai_link wm1133_ev1_dai = { |
244 | .name = "WM1133-EV1", | 244 | .name = "WM1133-EV1", |
245 | .stream_name = "Audio", | 245 | .stream_name = "Audio", |
246 | .cpu_dai = &imx_ssi_pcm_dai[0], | 246 | .cpu_dai_name = "imx-ssi-dai.0", |
247 | .codec_dai = &wm8350_dai, | 247 | .codec_dai_name = "wm8350-hifi", |
248 | .platform_name = "imx-fiq-pcm-audio.0", | ||
249 | .codec_name = "wm8350-codec.0-0x1a", | ||
248 | .init = wm1133_ev1_init, | 250 | .init = wm1133_ev1_init, |
249 | .ops = &wm1133_ev1_ops, | 251 | .ops = &wm1133_ev1_ops, |
250 | .symmetric_rates = 1, | 252 | .symmetric_rates = 1, |
@@ -252,16 +254,10 @@ static struct snd_soc_dai_link wm1133_ev1_dai = { | |||
252 | 254 | ||
253 | static struct snd_soc_card wm1133_ev1 = { | 255 | static struct snd_soc_card wm1133_ev1 = { |
254 | .name = "WM1133-EV1", | 256 | .name = "WM1133-EV1", |
255 | .platform = &imx_soc_platform, | ||
256 | .dai_link = &wm1133_ev1_dai, | 257 | .dai_link = &wm1133_ev1_dai, |
257 | .num_links = 1, | 258 | .num_links = 1, |
258 | }; | 259 | }; |
259 | 260 | ||
260 | static struct snd_soc_device wm1133_ev1_snd_devdata = { | ||
261 | .card = &wm1133_ev1, | ||
262 | .codec_dev = &soc_codec_dev_wm8350, | ||
263 | }; | ||
264 | |||
265 | static struct platform_device *wm1133_ev1_snd_device; | 261 | static struct platform_device *wm1133_ev1_snd_device; |
266 | 262 | ||
267 | static int __init wm1133_ev1_audio_init(void) | 263 | static int __init wm1133_ev1_audio_init(void) |
@@ -286,8 +282,7 @@ static int __init wm1133_ev1_audio_init(void) | |||
286 | if (!wm1133_ev1_snd_device) | 282 | if (!wm1133_ev1_snd_device) |
287 | return -ENOMEM; | 283 | return -ENOMEM; |
288 | 284 | ||
289 | platform_set_drvdata(wm1133_ev1_snd_device, &wm1133_ev1_snd_devdata); | 285 | platform_set_drvdata(wm1133_ev1_snd_device, &wm1133_ev1); |
290 | wm1133_ev1_snd_devdata.dev = &wm1133_ev1_snd_device->dev; | ||
291 | ret = platform_device_add(wm1133_ev1_snd_device); | 286 | ret = platform_device_add(wm1133_ev1_snd_device); |
292 | 287 | ||
293 | if (ret) | 288 | if (ret) |
diff --git a/sound/soc/jz4740/jz4740-i2s.c b/sound/soc/jz4740/jz4740-i2s.c index eb518f0c5e01..f3cffd183401 100644 --- a/sound/soc/jz4740/jz4740-i2s.c +++ b/sound/soc/jz4740/jz4740-i2s.c | |||
@@ -106,15 +106,10 @@ static inline void jz4740_i2s_write(const struct jz4740_i2s *i2s, | |||
106 | writel(value, i2s->base + reg); | 106 | writel(value, i2s->base + reg); |
107 | } | 107 | } |
108 | 108 | ||
109 | static inline struct jz4740_i2s *jz4740_dai_to_i2s(struct snd_soc_dai *dai) | ||
110 | { | ||
111 | return dai->private_data; | ||
112 | } | ||
113 | |||
114 | static int jz4740_i2s_startup(struct snd_pcm_substream *substream, | 109 | static int jz4740_i2s_startup(struct snd_pcm_substream *substream, |
115 | struct snd_soc_dai *dai) | 110 | struct snd_soc_dai *dai) |
116 | { | 111 | { |
117 | struct jz4740_i2s *i2s = jz4740_dai_to_i2s(dai); | 112 | struct jz4740_i2s *i2s = snd_soc_dai_get_drvdata(dai); |
118 | uint32_t conf, ctrl; | 113 | uint32_t conf, ctrl; |
119 | 114 | ||
120 | if (dai->active) | 115 | if (dai->active) |
@@ -136,7 +131,7 @@ static int jz4740_i2s_startup(struct snd_pcm_substream *substream, | |||
136 | static void jz4740_i2s_shutdown(struct snd_pcm_substream *substream, | 131 | static void jz4740_i2s_shutdown(struct snd_pcm_substream *substream, |
137 | struct snd_soc_dai *dai) | 132 | struct snd_soc_dai *dai) |
138 | { | 133 | { |
139 | struct jz4740_i2s *i2s = jz4740_dai_to_i2s(dai); | 134 | struct jz4740_i2s *i2s = snd_soc_dai_get_drvdata(dai); |
140 | uint32_t conf; | 135 | uint32_t conf; |
141 | 136 | ||
142 | if (!dai->active) | 137 | if (!dai->active) |
@@ -152,7 +147,7 @@ static void jz4740_i2s_shutdown(struct snd_pcm_substream *substream, | |||
152 | static int jz4740_i2s_trigger(struct snd_pcm_substream *substream, int cmd, | 147 | static int jz4740_i2s_trigger(struct snd_pcm_substream *substream, int cmd, |
153 | struct snd_soc_dai *dai) | 148 | struct snd_soc_dai *dai) |
154 | { | 149 | { |
155 | struct jz4740_i2s *i2s = jz4740_dai_to_i2s(dai); | 150 | struct jz4740_i2s *i2s = snd_soc_dai_get_drvdata(dai); |
156 | 151 | ||
157 | uint32_t ctrl; | 152 | uint32_t ctrl; |
158 | uint32_t mask; | 153 | uint32_t mask; |
@@ -186,7 +181,7 @@ static int jz4740_i2s_trigger(struct snd_pcm_substream *substream, int cmd, | |||
186 | 181 | ||
187 | static int jz4740_i2s_set_fmt(struct snd_soc_dai *dai, unsigned int fmt) | 182 | static int jz4740_i2s_set_fmt(struct snd_soc_dai *dai, unsigned int fmt) |
188 | { | 183 | { |
189 | struct jz4740_i2s *i2s = jz4740_dai_to_i2s(dai); | 184 | struct jz4740_i2s *i2s = snd_soc_dai_get_drvdata(dai); |
190 | 185 | ||
191 | uint32_t format = 0; | 186 | uint32_t format = 0; |
192 | uint32_t conf; | 187 | uint32_t conf; |
@@ -238,7 +233,7 @@ static int jz4740_i2s_set_fmt(struct snd_soc_dai *dai, unsigned int fmt) | |||
238 | static int jz4740_i2s_hw_params(struct snd_pcm_substream *substream, | 233 | static int jz4740_i2s_hw_params(struct snd_pcm_substream *substream, |
239 | struct snd_pcm_hw_params *params, struct snd_soc_dai *dai) | 234 | struct snd_pcm_hw_params *params, struct snd_soc_dai *dai) |
240 | { | 235 | { |
241 | struct jz4740_i2s *i2s = jz4740_dai_to_i2s(dai); | 236 | struct jz4740_i2s *i2s = snd_soc_dai_get_drvdata(dai); |
242 | enum jz4740_dma_width dma_width; | 237 | enum jz4740_dma_width dma_width; |
243 | struct jz4740_pcm_config *pcm_config; | 238 | struct jz4740_pcm_config *pcm_config; |
244 | unsigned int sample_size; | 239 | unsigned int sample_size; |
@@ -288,7 +283,7 @@ static int jz4740_i2s_hw_params(struct snd_pcm_substream *substream, | |||
288 | static int jz4740_i2s_set_sysclk(struct snd_soc_dai *dai, int clk_id, | 283 | static int jz4740_i2s_set_sysclk(struct snd_soc_dai *dai, int clk_id, |
289 | unsigned int freq, int dir) | 284 | unsigned int freq, int dir) |
290 | { | 285 | { |
291 | struct jz4740_i2s *i2s = jz4740_dai_to_i2s(dai); | 286 | struct jz4740_i2s *i2s = snd_soc_dai_get_drvdata(dai); |
292 | struct clk *parent; | 287 | struct clk *parent; |
293 | int ret = 0; | 288 | int ret = 0; |
294 | 289 | ||
@@ -312,7 +307,7 @@ static int jz4740_i2s_set_sysclk(struct snd_soc_dai *dai, int clk_id, | |||
312 | 307 | ||
313 | static int jz4740_i2s_suspend(struct snd_soc_dai *dai) | 308 | static int jz4740_i2s_suspend(struct snd_soc_dai *dai) |
314 | { | 309 | { |
315 | struct jz4740_i2s *i2s = jz4740_dai_to_i2s(dai); | 310 | struct jz4740_i2s *i2s = snd_soc_dai_get_drvdata(dai); |
316 | uint32_t conf; | 311 | uint32_t conf; |
317 | 312 | ||
318 | if (dai->active) { | 313 | if (dai->active) { |
@@ -330,7 +325,7 @@ static int jz4740_i2s_suspend(struct snd_soc_dai *dai) | |||
330 | 325 | ||
331 | static int jz4740_i2s_resume(struct snd_soc_dai *dai) | 326 | static int jz4740_i2s_resume(struct snd_soc_dai *dai) |
332 | { | 327 | { |
333 | struct jz4740_i2s *i2s = jz4740_dai_to_i2s(dai); | 328 | struct jz4740_i2s *i2s = snd_soc_dai_get_drvdata(dai); |
334 | uint32_t conf; | 329 | uint32_t conf; |
335 | 330 | ||
336 | clk_enable(i2s->clk_aic); | 331 | clk_enable(i2s->clk_aic); |
@@ -346,11 +341,38 @@ static int jz4740_i2s_resume(struct snd_soc_dai *dai) | |||
346 | return 0; | 341 | return 0; |
347 | } | 342 | } |
348 | 343 | ||
349 | static int jz4740_i2s_probe(struct platform_device *pdev, struct snd_soc_dai *dai) | 344 | static void jz4740_i2c_init_pcm_config(struct jz4740_i2s *i2s) |
350 | { | 345 | { |
351 | struct jz4740_i2s *i2s = jz4740_dai_to_i2s(dai); | 346 | struct jz4740_dma_config *dma_config; |
347 | |||
348 | /* Playback */ | ||
349 | dma_config = &i2s->pcm_config_playback.dma_config; | ||
350 | dma_config->src_width = JZ4740_DMA_WIDTH_32BIT, | ||
351 | dma_config->transfer_size = JZ4740_DMA_TRANSFER_SIZE_16BYTE; | ||
352 | dma_config->request_type = JZ4740_DMA_TYPE_AIC_TRANSMIT; | ||
353 | dma_config->flags = JZ4740_DMA_SRC_AUTOINC; | ||
354 | dma_config->mode = JZ4740_DMA_MODE_SINGLE; | ||
355 | i2s->pcm_config_playback.fifo_addr = i2s->phys_base + JZ_REG_AIC_FIFO; | ||
356 | |||
357 | /* Capture */ | ||
358 | dma_config = &i2s->pcm_config_capture.dma_config; | ||
359 | dma_config->dst_width = JZ4740_DMA_WIDTH_32BIT, | ||
360 | dma_config->transfer_size = JZ4740_DMA_TRANSFER_SIZE_16BYTE; | ||
361 | dma_config->request_type = JZ4740_DMA_TYPE_AIC_RECEIVE; | ||
362 | dma_config->flags = JZ4740_DMA_DST_AUTOINC; | ||
363 | dma_config->mode = JZ4740_DMA_MODE_SINGLE; | ||
364 | i2s->pcm_config_capture.fifo_addr = i2s->phys_base + JZ_REG_AIC_FIFO; | ||
365 | } | ||
366 | |||
367 | static int jz4740_i2s_dai_probe(struct snd_soc_dai *dai) | ||
368 | { | ||
369 | struct jz4740_i2s *i2s = snd_soc_dai_get_drvdata(dai); | ||
352 | uint32_t conf; | 370 | uint32_t conf; |
353 | 371 | ||
372 | clk_enable(i2s->clk_aic); | ||
373 | |||
374 | jz4740_i2c_init_pcm_config(i2s); | ||
375 | |||
354 | conf = (7 << JZ_AIC_CONF_FIFO_RX_THRESHOLD_OFFSET) | | 376 | conf = (7 << JZ_AIC_CONF_FIFO_RX_THRESHOLD_OFFSET) | |
355 | (8 << JZ_AIC_CONF_FIFO_TX_THRESHOLD_OFFSET) | | 377 | (8 << JZ_AIC_CONF_FIFO_TX_THRESHOLD_OFFSET) | |
356 | JZ_AIC_CONF_OVERFLOW_PLAY_LAST | | 378 | JZ_AIC_CONF_OVERFLOW_PLAY_LAST | |
@@ -363,6 +385,14 @@ static int jz4740_i2s_probe(struct platform_device *pdev, struct snd_soc_dai *da | |||
363 | return 0; | 385 | return 0; |
364 | } | 386 | } |
365 | 387 | ||
388 | static int jz4740_i2s_dai_remove(struct snd_soc_dai *dai) | ||
389 | { | ||
390 | struct jz4740_i2s *i2s = snd_soc_dai_get_drvdata(dai); | ||
391 | |||
392 | clk_disable(i2s->clk_aic); | ||
393 | return 0; | ||
394 | } | ||
395 | |||
366 | static struct snd_soc_dai_ops jz4740_i2s_dai_ops = { | 396 | static struct snd_soc_dai_ops jz4740_i2s_dai_ops = { |
367 | .startup = jz4740_i2s_startup, | 397 | .startup = jz4740_i2s_startup, |
368 | .shutdown = jz4740_i2s_shutdown, | 398 | .shutdown = jz4740_i2s_shutdown, |
@@ -375,9 +405,9 @@ static struct snd_soc_dai_ops jz4740_i2s_dai_ops = { | |||
375 | #define JZ4740_I2S_FMTS (SNDRV_PCM_FMTBIT_S8 | \ | 405 | #define JZ4740_I2S_FMTS (SNDRV_PCM_FMTBIT_S8 | \ |
376 | SNDRV_PCM_FMTBIT_S16_LE) | 406 | SNDRV_PCM_FMTBIT_S16_LE) |
377 | 407 | ||
378 | struct snd_soc_dai jz4740_i2s_dai = { | 408 | static struct snd_soc_dai_driver jz4740_i2s_dai = { |
379 | .name = "jz4740-i2s", | 409 | .probe = jz4740_i2s_dai_probe, |
380 | .probe = jz4740_i2s_probe, | 410 | .remove = jz4740_i2s_dai_remove, |
381 | .playback = { | 411 | .playback = { |
382 | .channels_min = 1, | 412 | .channels_min = 1, |
383 | .channels_max = 2, | 413 | .channels_max = 2, |
@@ -395,30 +425,6 @@ struct snd_soc_dai jz4740_i2s_dai = { | |||
395 | .suspend = jz4740_i2s_suspend, | 425 | .suspend = jz4740_i2s_suspend, |
396 | .resume = jz4740_i2s_resume, | 426 | .resume = jz4740_i2s_resume, |
397 | }; | 427 | }; |
398 | EXPORT_SYMBOL_GPL(jz4740_i2s_dai); | ||
399 | |||
400 | static void __devinit jz4740_i2c_init_pcm_config(struct jz4740_i2s *i2s) | ||
401 | { | ||
402 | struct jz4740_dma_config *dma_config; | ||
403 | |||
404 | /* Playback */ | ||
405 | dma_config = &i2s->pcm_config_playback.dma_config; | ||
406 | dma_config->src_width = JZ4740_DMA_WIDTH_32BIT, | ||
407 | dma_config->transfer_size = JZ4740_DMA_TRANSFER_SIZE_16BYTE; | ||
408 | dma_config->request_type = JZ4740_DMA_TYPE_AIC_TRANSMIT; | ||
409 | dma_config->flags = JZ4740_DMA_SRC_AUTOINC; | ||
410 | dma_config->mode = JZ4740_DMA_MODE_SINGLE; | ||
411 | i2s->pcm_config_playback.fifo_addr = i2s->phys_base + JZ_REG_AIC_FIFO; | ||
412 | |||
413 | /* Capture */ | ||
414 | dma_config = &i2s->pcm_config_capture.dma_config; | ||
415 | dma_config->dst_width = JZ4740_DMA_WIDTH_32BIT, | ||
416 | dma_config->transfer_size = JZ4740_DMA_TRANSFER_SIZE_16BYTE; | ||
417 | dma_config->request_type = JZ4740_DMA_TYPE_AIC_RECEIVE; | ||
418 | dma_config->flags = JZ4740_DMA_DST_AUTOINC; | ||
419 | dma_config->mode = JZ4740_DMA_MODE_SINGLE; | ||
420 | i2s->pcm_config_capture.fifo_addr = i2s->phys_base + JZ_REG_AIC_FIFO; | ||
421 | } | ||
422 | 428 | ||
423 | static int __devinit jz4740_i2s_dev_probe(struct platform_device *pdev) | 429 | static int __devinit jz4740_i2s_dev_probe(struct platform_device *pdev) |
424 | { | 430 | { |
@@ -463,24 +469,17 @@ static int __devinit jz4740_i2s_dev_probe(struct platform_device *pdev) | |||
463 | goto err_clk_put_aic; | 469 | goto err_clk_put_aic; |
464 | } | 470 | } |
465 | 471 | ||
466 | clk_enable(i2s->clk_aic); | 472 | platform_set_drvdata(pdev, i2s); |
467 | 473 | ret = snd_soc_register_dai(&pdev->dev, &jz4740_i2s_dai); | |
468 | jz4740_i2c_init_pcm_config(i2s); | ||
469 | |||
470 | jz4740_i2s_dai.private_data = i2s; | ||
471 | ret = snd_soc_register_dai(&jz4740_i2s_dai); | ||
472 | 474 | ||
473 | if (ret) { | 475 | if (ret) { |
474 | dev_err(&pdev->dev, "Failed to register DAI\n"); | 476 | dev_err(&pdev->dev, "Failed to register DAI\n"); |
475 | goto err_clk_put_i2s; | 477 | goto err_clk_put_i2s; |
476 | } | 478 | } |
477 | 479 | ||
478 | platform_set_drvdata(pdev, i2s); | ||
479 | |||
480 | return 0; | 480 | return 0; |
481 | 481 | ||
482 | err_clk_put_i2s: | 482 | err_clk_put_i2s: |
483 | clk_disable(i2s->clk_aic); | ||
484 | clk_put(i2s->clk_i2s); | 483 | clk_put(i2s->clk_i2s); |
485 | err_clk_put_aic: | 484 | err_clk_put_aic: |
486 | clk_put(i2s->clk_aic); | 485 | clk_put(i2s->clk_aic); |
@@ -498,9 +497,8 @@ static int __devexit jz4740_i2s_dev_remove(struct platform_device *pdev) | |||
498 | { | 497 | { |
499 | struct jz4740_i2s *i2s = platform_get_drvdata(pdev); | 498 | struct jz4740_i2s *i2s = platform_get_drvdata(pdev); |
500 | 499 | ||
501 | snd_soc_unregister_dai(&jz4740_i2s_dai); | 500 | snd_soc_unregister_dai(&pdev->dev); |
502 | 501 | ||
503 | clk_disable(i2s->clk_aic); | ||
504 | clk_put(i2s->clk_i2s); | 502 | clk_put(i2s->clk_i2s); |
505 | clk_put(i2s->clk_aic); | 503 | clk_put(i2s->clk_aic); |
506 | 504 | ||
diff --git a/sound/soc/jz4740/jz4740-i2s.h b/sound/soc/jz4740/jz4740-i2s.h index da22ed88a589..5e49339d8b93 100644 --- a/sound/soc/jz4740/jz4740-i2s.h +++ b/sound/soc/jz4740/jz4740-i2s.h | |||
@@ -13,6 +13,4 @@ | |||
13 | 13 | ||
14 | #define JZ4740_I2S_BIT_CLK 0 | 14 | #define JZ4740_I2S_BIT_CLK 0 |
15 | 15 | ||
16 | extern struct snd_soc_dai jz4740_i2s_dai; | ||
17 | |||
18 | #endif | 16 | #endif |
diff --git a/sound/soc/jz4740/jz4740-pcm.c b/sound/soc/jz4740/jz4740-pcm.c index ee68d850c8dd..fb1483f7c966 100644 --- a/sound/soc/jz4740/jz4740-pcm.c +++ b/sound/soc/jz4740/jz4740-pcm.c | |||
@@ -109,7 +109,7 @@ static int jz4740_pcm_hw_params(struct snd_pcm_substream *substream, | |||
109 | struct snd_soc_pcm_runtime *rtd = substream->private_data; | 109 | struct snd_soc_pcm_runtime *rtd = substream->private_data; |
110 | struct jz4740_pcm_config *config; | 110 | struct jz4740_pcm_config *config; |
111 | 111 | ||
112 | config = snd_soc_dai_get_dma_data(rtd->dai->cpu_dai, substream); | 112 | config = snd_soc_dai_get_dma_data(rtd->cpu_dai, substream); |
113 | 113 | ||
114 | if (!config) | 114 | if (!config) |
115 | return 0; | 115 | return 0; |
@@ -310,14 +310,14 @@ int jz4740_pcm_new(struct snd_card *card, struct snd_soc_dai *dai, | |||
310 | if (!card->dev->coherent_dma_mask) | 310 | if (!card->dev->coherent_dma_mask) |
311 | card->dev->coherent_dma_mask = DMA_BIT_MASK(32); | 311 | card->dev->coherent_dma_mask = DMA_BIT_MASK(32); |
312 | 312 | ||
313 | if (dai->playback.channels_min) { | 313 | if (dai->driver->playback.channels_min) { |
314 | ret = jz4740_pcm_preallocate_dma_buffer(pcm, | 314 | ret = jz4740_pcm_preallocate_dma_buffer(pcm, |
315 | SNDRV_PCM_STREAM_PLAYBACK); | 315 | SNDRV_PCM_STREAM_PLAYBACK); |
316 | if (ret) | 316 | if (ret) |
317 | goto err; | 317 | goto err; |
318 | } | 318 | } |
319 | 319 | ||
320 | if (dai->capture.channels_min) { | 320 | if (dai->driver->capture.channels_min) { |
321 | ret = jz4740_pcm_preallocate_dma_buffer(pcm, | 321 | ret = jz4740_pcm_preallocate_dma_buffer(pcm, |
322 | SNDRV_PCM_STREAM_CAPTURE); | 322 | SNDRV_PCM_STREAM_CAPTURE); |
323 | if (ret) | 323 | if (ret) |
@@ -328,22 +328,20 @@ err: | |||
328 | return ret; | 328 | return ret; |
329 | } | 329 | } |
330 | 330 | ||
331 | struct snd_soc_platform jz4740_soc_platform = { | 331 | static struct snd_soc_platform_driver jz4740_soc_platform = { |
332 | .name = "jz4740-pcm", | 332 | .ops = &jz4740_pcm_ops, |
333 | .pcm_ops = &jz4740_pcm_ops, | ||
334 | .pcm_new = jz4740_pcm_new, | 333 | .pcm_new = jz4740_pcm_new, |
335 | .pcm_free = jz4740_pcm_free, | 334 | .pcm_free = jz4740_pcm_free, |
336 | }; | 335 | }; |
337 | EXPORT_SYMBOL_GPL(jz4740_soc_platform); | ||
338 | 336 | ||
339 | static int __devinit jz4740_pcm_probe(struct platform_device *pdev) | 337 | static int __devinit jz4740_pcm_probe(struct platform_device *pdev) |
340 | { | 338 | { |
341 | return snd_soc_register_platform(&jz4740_soc_platform); | 339 | return snd_soc_register_platform(&pdev->dev, &jz4740_soc_platform); |
342 | } | 340 | } |
343 | 341 | ||
344 | static int __devexit jz4740_pcm_remove(struct platform_device *pdev) | 342 | static int __devexit jz4740_pcm_remove(struct platform_device *pdev) |
345 | { | 343 | { |
346 | snd_soc_unregister_platform(&jz4740_soc_platform); | 344 | snd_soc_unregister_platform(&pdev->dev); |
347 | return 0; | 345 | return 0; |
348 | } | 346 | } |
349 | 347 | ||
@@ -351,7 +349,7 @@ static struct platform_driver jz4740_pcm_driver = { | |||
351 | .probe = jz4740_pcm_probe, | 349 | .probe = jz4740_pcm_probe, |
352 | .remove = __devexit_p(jz4740_pcm_remove), | 350 | .remove = __devexit_p(jz4740_pcm_remove), |
353 | .driver = { | 351 | .driver = { |
354 | .name = "jz4740-pcm", | 352 | .name = "jz4740-pcm-audio", |
355 | .owner = THIS_MODULE, | 353 | .owner = THIS_MODULE, |
356 | }, | 354 | }, |
357 | }; | 355 | }; |
diff --git a/sound/soc/jz4740/jz4740-pcm.h b/sound/soc/jz4740/jz4740-pcm.h index e3f221e2779c..1220cbb4382c 100644 --- a/sound/soc/jz4740/jz4740-pcm.h +++ b/sound/soc/jz4740/jz4740-pcm.h | |||
@@ -11,8 +11,6 @@ | |||
11 | #include <linux/dma-mapping.h> | 11 | #include <linux/dma-mapping.h> |
12 | #include <asm/mach-jz4740/dma.h> | 12 | #include <asm/mach-jz4740/dma.h> |
13 | 13 | ||
14 | /* platform data */ | ||
15 | extern struct snd_soc_platform jz4740_soc_platform; | ||
16 | 14 | ||
17 | struct jz4740_pcm_config { | 15 | struct jz4740_pcm_config { |
18 | struct jz4740_dma_config dma_config; | 16 | struct jz4740_dma_config dma_config; |
diff --git a/sound/soc/jz4740/qi_lb60.c b/sound/soc/jz4740/qi_lb60.c index f15f4918f15f..78dabebe8fd0 100644 --- a/sound/soc/jz4740/qi_lb60.c +++ b/sound/soc/jz4740/qi_lb60.c | |||
@@ -60,10 +60,11 @@ static const struct snd_soc_dapm_route qi_lb60_routes[] = { | |||
60 | SND_SOC_DAIFMT_NB_NF | \ | 60 | SND_SOC_DAIFMT_NB_NF | \ |
61 | SND_SOC_DAIFMT_CBM_CFM) | 61 | SND_SOC_DAIFMT_CBM_CFM) |
62 | 62 | ||
63 | static int qi_lb60_codec_init(struct snd_soc_codec *codec) | 63 | static int qi_lb60_codec_init(struct snd_soc_pcm_runtime *rtd) |
64 | { | 64 | { |
65 | struct snd_soc_codec *codec = rtd->codec; | ||
66 | struct snd_soc_dai *cpu_dai = rtd->cpu_dai; | ||
65 | int ret; | 67 | int ret; |
66 | struct snd_soc_dai *cpu_dai = codec->socdev->card->dai_link->cpu_dai; | ||
67 | 68 | ||
68 | snd_soc_dapm_nc_pin(codec, "LIN"); | 69 | snd_soc_dapm_nc_pin(codec, "LIN"); |
69 | snd_soc_dapm_nc_pin(codec, "RIN"); | 70 | snd_soc_dapm_nc_pin(codec, "RIN"); |
@@ -84,8 +85,10 @@ static int qi_lb60_codec_init(struct snd_soc_codec *codec) | |||
84 | static struct snd_soc_dai_link qi_lb60_dai = { | 85 | static struct snd_soc_dai_link qi_lb60_dai = { |
85 | .name = "jz4740", | 86 | .name = "jz4740", |
86 | .stream_name = "jz4740", | 87 | .stream_name = "jz4740", |
87 | .cpu_dai = &jz4740_i2s_dai, | 88 | .cpu_dai_name = "jz4740-i2s", |
88 | .codec_dai = &jz4740_codec_dai, | 89 | .platform_name = "jz4740-pmc-audio", |
90 | .codec_dai_name = "jz4740-hifi", | ||
91 | .codec_name = "jz4740-codec", | ||
89 | .init = qi_lb60_codec_init, | 92 | .init = qi_lb60_codec_init, |
90 | }; | 93 | }; |
91 | 94 | ||
@@ -93,12 +96,6 @@ static struct snd_soc_card qi_lb60 = { | |||
93 | .name = "QI LB60", | 96 | .name = "QI LB60", |
94 | .dai_link = &qi_lb60_dai, | 97 | .dai_link = &qi_lb60_dai, |
95 | .num_links = 1, | 98 | .num_links = 1, |
96 | .platform = &jz4740_soc_platform, | ||
97 | }; | ||
98 | |||
99 | static struct snd_soc_device qi_lb60_snd_devdata = { | ||
100 | .card = &qi_lb60, | ||
101 | .codec_dev = &soc_codec_dev_jz4740_codec, | ||
102 | }; | 99 | }; |
103 | 100 | ||
104 | static struct platform_device *qi_lb60_snd_device; | 101 | static struct platform_device *qi_lb60_snd_device; |
@@ -129,8 +126,7 @@ static int __init qi_lb60_init(void) | |||
129 | gpio_direction_output(QI_LB60_SND_GPIO, 0); | 126 | gpio_direction_output(QI_LB60_SND_GPIO, 0); |
130 | gpio_direction_output(QI_LB60_AMP_GPIO, 0); | 127 | gpio_direction_output(QI_LB60_AMP_GPIO, 0); |
131 | 128 | ||
132 | platform_set_drvdata(qi_lb60_snd_device, &qi_lb60_snd_devdata); | 129 | platform_set_drvdata(qi_lb60_snd_device, &qi_lb60); |
133 | qi_lb60_snd_devdata.dev = &qi_lb60_snd_device->dev; | ||
134 | 130 | ||
135 | ret = platform_device_add(qi_lb60_snd_device); | 131 | ret = platform_device_add(qi_lb60_snd_device); |
136 | if (ret) { | 132 | if (ret) { |
diff --git a/sound/soc/kirkwood/kirkwood-dma.c b/sound/soc/kirkwood/kirkwood-dma.c index a30205be3e2b..693049d42d24 100644 --- a/sound/soc/kirkwood/kirkwood-dma.c +++ b/sound/soc/kirkwood/kirkwood-dma.c | |||
@@ -18,7 +18,6 @@ | |||
18 | #include <linux/dma-mapping.h> | 18 | #include <linux/dma-mapping.h> |
19 | #include <linux/mbus.h> | 19 | #include <linux/mbus.h> |
20 | #include <sound/soc.h> | 20 | #include <sound/soc.h> |
21 | #include "kirkwood-dma.h" | ||
22 | #include "kirkwood.h" | 21 | #include "kirkwood.h" |
23 | 22 | ||
24 | #define KIRKWOOD_RATES \ | 23 | #define KIRKWOOD_RATES \ |
@@ -123,9 +122,10 @@ static int kirkwood_dma_open(struct snd_pcm_substream *substream) | |||
123 | int err; | 122 | int err; |
124 | struct snd_pcm_runtime *runtime = substream->runtime; | 123 | struct snd_pcm_runtime *runtime = substream->runtime; |
125 | struct snd_soc_pcm_runtime *soc_runtime = substream->private_data; | 124 | struct snd_soc_pcm_runtime *soc_runtime = substream->private_data; |
126 | struct snd_soc_dai *cpu_dai = soc_runtime->dai->cpu_dai; | 125 | struct snd_soc_platform *platform = soc_runtime->platform; |
126 | struct snd_soc_dai *cpu_dai = soc_runtime->cpu_dai; | ||
127 | struct kirkwood_dma_data *priv; | 127 | struct kirkwood_dma_data *priv; |
128 | struct kirkwood_dma_priv *prdata = cpu_dai->private_data; | 128 | struct kirkwood_dma_priv *prdata = snd_soc_platform_get_drvdata(platform); |
129 | unsigned long addr; | 129 | unsigned long addr; |
130 | 130 | ||
131 | priv = snd_soc_dai_get_dma_data(cpu_dai, substream); | 131 | priv = snd_soc_dai_get_dma_data(cpu_dai, substream); |
@@ -151,7 +151,7 @@ static int kirkwood_dma_open(struct snd_pcm_substream *substream) | |||
151 | if (err < 0) | 151 | if (err < 0) |
152 | return err; | 152 | return err; |
153 | 153 | ||
154 | if (soc_runtime->dai->cpu_dai->private_data == NULL) { | 154 | if (prdata == NULL) { |
155 | prdata = kzalloc(sizeof(struct kirkwood_dma_priv), GFP_KERNEL); | 155 | prdata = kzalloc(sizeof(struct kirkwood_dma_priv), GFP_KERNEL); |
156 | if (prdata == NULL) | 156 | if (prdata == NULL) |
157 | return -ENOMEM; | 157 | return -ENOMEM; |
@@ -165,7 +165,7 @@ static int kirkwood_dma_open(struct snd_pcm_substream *substream) | |||
165 | return -EBUSY; | 165 | return -EBUSY; |
166 | } | 166 | } |
167 | 167 | ||
168 | soc_runtime->dai->cpu_dai->private_data = prdata; | 168 | snd_soc_platform_set_drvdata(platform, prdata); |
169 | 169 | ||
170 | /* | 170 | /* |
171 | * Enable Error interrupts. We're only ack'ing them but | 171 | * Enable Error interrupts. We're only ack'ing them but |
@@ -191,8 +191,9 @@ static int kirkwood_dma_open(struct snd_pcm_substream *substream) | |||
191 | static int kirkwood_dma_close(struct snd_pcm_substream *substream) | 191 | static int kirkwood_dma_close(struct snd_pcm_substream *substream) |
192 | { | 192 | { |
193 | struct snd_soc_pcm_runtime *soc_runtime = substream->private_data; | 193 | struct snd_soc_pcm_runtime *soc_runtime = substream->private_data; |
194 | struct snd_soc_dai *cpu_dai = soc_runtime->dai->cpu_dai; | 194 | struct snd_soc_dai *cpu_dai = soc_runtime->cpu_dai; |
195 | struct kirkwood_dma_priv *prdata = cpu_dai->private_data; | 195 | struct snd_soc_platform *platform = soc_runtime->platform; |
196 | struct kirkwood_dma_priv *prdata = snd_soc_platform_get_drvdata(platform); | ||
196 | struct kirkwood_dma_data *priv; | 197 | struct kirkwood_dma_data *priv; |
197 | 198 | ||
198 | priv = snd_soc_dai_get_dma_data(cpu_dai, substream); | 199 | priv = snd_soc_dai_get_dma_data(cpu_dai, substream); |
@@ -209,7 +210,7 @@ static int kirkwood_dma_close(struct snd_pcm_substream *substream) | |||
209 | writel(0, priv->io + KIRKWOOD_ERR_MASK); | 210 | writel(0, priv->io + KIRKWOOD_ERR_MASK); |
210 | free_irq(priv->irq, prdata); | 211 | free_irq(priv->irq, prdata); |
211 | kfree(prdata); | 212 | kfree(prdata); |
212 | soc_runtime->dai->cpu_dai->private_data = NULL; | 213 | snd_soc_platform_set_drvdata(platform, NULL); |
213 | } | 214 | } |
214 | 215 | ||
215 | return 0; | 216 | return 0; |
@@ -236,7 +237,7 @@ static int kirkwood_dma_prepare(struct snd_pcm_substream *substream) | |||
236 | { | 237 | { |
237 | struct snd_pcm_runtime *runtime = substream->runtime; | 238 | struct snd_pcm_runtime *runtime = substream->runtime; |
238 | struct snd_soc_pcm_runtime *soc_runtime = substream->private_data; | 239 | struct snd_soc_pcm_runtime *soc_runtime = substream->private_data; |
239 | struct snd_soc_dai *cpu_dai = soc_runtime->dai->cpu_dai; | 240 | struct snd_soc_dai *cpu_dai = soc_runtime->cpu_dai; |
240 | struct kirkwood_dma_data *priv; | 241 | struct kirkwood_dma_data *priv; |
241 | unsigned long size, count; | 242 | unsigned long size, count; |
242 | 243 | ||
@@ -265,7 +266,7 @@ static snd_pcm_uframes_t kirkwood_dma_pointer(struct snd_pcm_substream | |||
265 | *substream) | 266 | *substream) |
266 | { | 267 | { |
267 | struct snd_soc_pcm_runtime *soc_runtime = substream->private_data; | 268 | struct snd_soc_pcm_runtime *soc_runtime = substream->private_data; |
268 | struct snd_soc_dai *cpu_dai = soc_runtime->dai->cpu_dai; | 269 | struct snd_soc_dai *cpu_dai = soc_runtime->cpu_dai; |
269 | struct kirkwood_dma_data *priv; | 270 | struct kirkwood_dma_data *priv; |
270 | snd_pcm_uframes_t count; | 271 | snd_pcm_uframes_t count; |
271 | 272 | ||
@@ -320,14 +321,14 @@ static int kirkwood_dma_new(struct snd_card *card, | |||
320 | if (!card->dev->coherent_dma_mask) | 321 | if (!card->dev->coherent_dma_mask) |
321 | card->dev->coherent_dma_mask = 0xffffffff; | 322 | card->dev->coherent_dma_mask = 0xffffffff; |
322 | 323 | ||
323 | if (dai->playback.channels_min) { | 324 | if (dai->driver->playback.channels_min) { |
324 | ret = kirkwood_dma_preallocate_dma_buffer(pcm, | 325 | ret = kirkwood_dma_preallocate_dma_buffer(pcm, |
325 | SNDRV_PCM_STREAM_PLAYBACK); | 326 | SNDRV_PCM_STREAM_PLAYBACK); |
326 | if (ret) | 327 | if (ret) |
327 | return ret; | 328 | return ret; |
328 | } | 329 | } |
329 | 330 | ||
330 | if (dai->capture.channels_min) { | 331 | if (dai->driver->capture.channels_min) { |
331 | ret = kirkwood_dma_preallocate_dma_buffer(pcm, | 332 | ret = kirkwood_dma_preallocate_dma_buffer(pcm, |
332 | SNDRV_PCM_STREAM_CAPTURE); | 333 | SNDRV_PCM_STREAM_CAPTURE); |
333 | if (ret) | 334 | if (ret) |
@@ -357,25 +358,44 @@ static void kirkwood_dma_free_dma_buffers(struct snd_pcm *pcm) | |||
357 | } | 358 | } |
358 | } | 359 | } |
359 | 360 | ||
360 | struct snd_soc_platform kirkwood_soc_platform = { | 361 | static struct snd_soc_platform_driver kirkwood_soc_platform = { |
361 | .name = "kirkwood-dma", | 362 | .ops = &kirkwood_dma_ops, |
362 | .pcm_ops = &kirkwood_dma_ops, | ||
363 | .pcm_new = kirkwood_dma_new, | 363 | .pcm_new = kirkwood_dma_new, |
364 | .pcm_free = kirkwood_dma_free_dma_buffers, | 364 | .pcm_free = kirkwood_dma_free_dma_buffers, |
365 | }; | 365 | }; |
366 | EXPORT_SYMBOL_GPL(kirkwood_soc_platform); | ||
367 | 366 | ||
368 | static int __init kirkwood_soc_platform_init(void) | 367 | static int __devinit kirkwood_soc_platform_probe(struct platform_device *pdev) |
369 | { | 368 | { |
370 | return snd_soc_register_platform(&kirkwood_soc_platform); | 369 | return snd_soc_register_platform(&pdev->dev, &kirkwood_soc_platform); |
371 | } | 370 | } |
372 | module_init(kirkwood_soc_platform_init); | ||
373 | 371 | ||
374 | static void __exit kirkwood_soc_platform_exit(void) | 372 | static int __devexit kirkwood_soc_platform_remove(struct platform_device *pdev) |
375 | { | 373 | { |
376 | snd_soc_unregister_platform(&kirkwood_soc_platform); | 374 | snd_soc_unregister_platform(&pdev->dev); |
375 | return 0; | ||
376 | } | ||
377 | |||
378 | static struct platform_driver kirkwood_pcm_driver = { | ||
379 | .driver = { | ||
380 | .name = "kirkwood-pcm-audio", | ||
381 | .owner = THIS_MODULE, | ||
382 | }, | ||
383 | |||
384 | .probe = kirkwood_soc_platform_probe, | ||
385 | .remove = __devexit_p(kirkwood_soc_platform_remove), | ||
386 | }; | ||
387 | |||
388 | static int __init kirkwood_pcm_init(void) | ||
389 | { | ||
390 | return platform_driver_register(&kirkwood_pcm_driver); | ||
391 | } | ||
392 | module_init(kirkwood_pcm_init); | ||
393 | |||
394 | static void __exit kirkwood_pcm_exit(void) | ||
395 | { | ||
396 | platform_driver_unregister(&kirkwood_pcm_driver); | ||
377 | } | 397 | } |
378 | module_exit(kirkwood_soc_platform_exit); | 398 | module_exit(kirkwood_pcm_exit); |
379 | 399 | ||
380 | MODULE_AUTHOR("Arnaud Patard <apatard@mandriva.com>"); | 400 | MODULE_AUTHOR("Arnaud Patard <apatard@mandriva.com>"); |
381 | MODULE_DESCRIPTION("Marvell Kirkwood Audio DMA module"); | 401 | MODULE_DESCRIPTION("Marvell Kirkwood Audio DMA module"); |
diff --git a/sound/soc/kirkwood/kirkwood-dma.h b/sound/soc/kirkwood/kirkwood-dma.h deleted file mode 100644 index ba4454cd34f1..000000000000 --- a/sound/soc/kirkwood/kirkwood-dma.h +++ /dev/null | |||
@@ -1,17 +0,0 @@ | |||
1 | /* | ||
2 | * kirkwood-dma.h | ||
3 | * | ||
4 | * (c) 2010 Arnaud Patard <apatard@mandriva.com> | ||
5 | * | ||
6 | * This program is free software; you can redistribute it and/or modify it | ||
7 | * under the terms of the GNU General Public License as published by the | ||
8 | * Free Software Foundation; either version 2 of the License, or (at your | ||
9 | * option) any later version. | ||
10 | */ | ||
11 | |||
12 | #ifndef _KIRKWOOD_DMA_H | ||
13 | #define _KIRKWOOD_DMA_H | ||
14 | |||
15 | extern struct snd_soc_platform kirkwood_soc_platform; | ||
16 | |||
17 | #endif | ||
diff --git a/sound/soc/kirkwood/kirkwood-i2s.c b/sound/soc/kirkwood/kirkwood-i2s.c index 981ffc2a13c8..9b62cba4f590 100644 --- a/sound/soc/kirkwood/kirkwood-i2s.c +++ b/sound/soc/kirkwood/kirkwood-i2s.c | |||
@@ -20,7 +20,6 @@ | |||
20 | #include <sound/pcm_params.h> | 20 | #include <sound/pcm_params.h> |
21 | #include <sound/soc.h> | 21 | #include <sound/soc.h> |
22 | #include <plat/audio.h> | 22 | #include <plat/audio.h> |
23 | #include "kirkwood-i2s.h" | ||
24 | #include "kirkwood.h" | 23 | #include "kirkwood.h" |
25 | 24 | ||
26 | #define DRV_NAME "kirkwood-i2s" | 25 | #define DRV_NAME "kirkwood-i2s" |
@@ -33,13 +32,10 @@ | |||
33 | SNDRV_PCM_FMTBIT_S24_LE | \ | 32 | SNDRV_PCM_FMTBIT_S24_LE | \ |
34 | SNDRV_PCM_FMTBIT_S32_LE) | 33 | SNDRV_PCM_FMTBIT_S32_LE) |
35 | 34 | ||
36 | |||
37 | struct snd_soc_dai kirkwood_i2s_dai; | ||
38 | static struct kirkwood_dma_data *priv; | ||
39 | |||
40 | static int kirkwood_i2s_set_fmt(struct snd_soc_dai *cpu_dai, | 35 | static int kirkwood_i2s_set_fmt(struct snd_soc_dai *cpu_dai, |
41 | unsigned int fmt) | 36 | unsigned int fmt) |
42 | { | 37 | { |
38 | struct kirkwood_dma_data *priv = snd_soc_dai_get_drvdata(cpu_dai); | ||
43 | unsigned long mask; | 39 | unsigned long mask; |
44 | unsigned long value; | 40 | unsigned long value; |
45 | 41 | ||
@@ -101,10 +97,20 @@ static inline void kirkwood_set_dco(void __iomem *io, unsigned long rate) | |||
101 | } while (value == 0); | 97 | } while (value == 0); |
102 | } | 98 | } |
103 | 99 | ||
100 | static int kirkwood_i2s_startup(struct snd_pcm_substream *substream, | ||
101 | struct snd_soc_dai *dai) | ||
102 | { | ||
103 | struct kirkwood_dma_data *priv = snd_soc_dai_get_drvdata(dai); | ||
104 | |||
105 | snd_soc_dai_set_dma_data(dai, substream, priv); | ||
106 | return 0; | ||
107 | } | ||
108 | |||
104 | static int kirkwood_i2s_hw_params(struct snd_pcm_substream *substream, | 109 | static int kirkwood_i2s_hw_params(struct snd_pcm_substream *substream, |
105 | struct snd_pcm_hw_params *params, | 110 | struct snd_pcm_hw_params *params, |
106 | struct snd_soc_dai *dai) | 111 | struct snd_soc_dai *dai) |
107 | { | 112 | { |
113 | struct kirkwood_dma_data *priv = snd_soc_dai_get_drvdata(dai); | ||
108 | unsigned int i2s_reg, reg; | 114 | unsigned int i2s_reg, reg; |
109 | unsigned long i2s_value, value; | 115 | unsigned long i2s_value, value; |
110 | 116 | ||
@@ -171,6 +177,7 @@ static int kirkwood_i2s_hw_params(struct snd_pcm_substream *substream, | |||
171 | static int kirkwood_i2s_play_trigger(struct snd_pcm_substream *substream, | 177 | static int kirkwood_i2s_play_trigger(struct snd_pcm_substream *substream, |
172 | int cmd, struct snd_soc_dai *dai) | 178 | int cmd, struct snd_soc_dai *dai) |
173 | { | 179 | { |
180 | struct kirkwood_dma_data *priv = snd_soc_dai_get_drvdata(dai); | ||
174 | unsigned long value; | 181 | unsigned long value; |
175 | 182 | ||
176 | /* | 183 | /* |
@@ -244,6 +251,7 @@ static int kirkwood_i2s_play_trigger(struct snd_pcm_substream *substream, | |||
244 | static int kirkwood_i2s_rec_trigger(struct snd_pcm_substream *substream, | 251 | static int kirkwood_i2s_rec_trigger(struct snd_pcm_substream *substream, |
245 | int cmd, struct snd_soc_dai *dai) | 252 | int cmd, struct snd_soc_dai *dai) |
246 | { | 253 | { |
254 | struct kirkwood_dma_data *priv = snd_soc_dai_get_drvdata(dai); | ||
247 | unsigned long value; | 255 | unsigned long value; |
248 | 256 | ||
249 | value = readl(priv->io + KIRKWOOD_RECCTL); | 257 | value = readl(priv->io + KIRKWOOD_RECCTL); |
@@ -323,9 +331,9 @@ static int kirkwood_i2s_trigger(struct snd_pcm_substream *substream, int cmd, | |||
323 | return 0; | 331 | return 0; |
324 | } | 332 | } |
325 | 333 | ||
326 | static int kirkwood_i2s_probe(struct platform_device *pdev, | 334 | static int kirkwood_i2s_probe(struct snd_soc_dai *dai) |
327 | struct snd_soc_dai *dai) | ||
328 | { | 335 | { |
336 | struct kirkwood_dma_data *priv = snd_soc_dai_get_drvdata(dai); | ||
329 | unsigned long value; | 337 | unsigned long value; |
330 | unsigned int reg_data; | 338 | unsigned int reg_data; |
331 | 339 | ||
@@ -359,21 +367,20 @@ static int kirkwood_i2s_probe(struct platform_device *pdev, | |||
359 | 367 | ||
360 | } | 368 | } |
361 | 369 | ||
362 | static void kirkwood_i2s_remove(struct platform_device *pdev, | 370 | static int kirkwood_i2s_remove(struct snd_soc_dai *dai) |
363 | struct snd_soc_dai *dai) | ||
364 | { | 371 | { |
372 | return 0; | ||
365 | } | 373 | } |
366 | 374 | ||
367 | static struct snd_soc_dai_ops kirkwood_i2s_dai_ops = { | 375 | static struct snd_soc_dai_ops kirkwood_i2s_dai_ops = { |
376 | .startup = kirkwood_i2s_startup, | ||
368 | .trigger = kirkwood_i2s_trigger, | 377 | .trigger = kirkwood_i2s_trigger, |
369 | .hw_params = kirkwood_i2s_hw_params, | 378 | .hw_params = kirkwood_i2s_hw_params, |
370 | .set_fmt = kirkwood_i2s_set_fmt, | 379 | .set_fmt = kirkwood_i2s_set_fmt, |
371 | }; | 380 | }; |
372 | 381 | ||
373 | 382 | ||
374 | struct snd_soc_dai kirkwood_i2s_dai = { | 383 | static struct snd_soc_dai_driver kirkwood_i2s_dai = { |
375 | .name = DRV_NAME, | ||
376 | .id = 0, | ||
377 | .probe = kirkwood_i2s_probe, | 384 | .probe = kirkwood_i2s_probe, |
378 | .remove = kirkwood_i2s_remove, | 385 | .remove = kirkwood_i2s_remove, |
379 | .playback = { | 386 | .playback = { |
@@ -388,13 +395,13 @@ struct snd_soc_dai kirkwood_i2s_dai = { | |||
388 | .formats = KIRKWOOD_I2S_FORMATS,}, | 395 | .formats = KIRKWOOD_I2S_FORMATS,}, |
389 | .ops = &kirkwood_i2s_dai_ops, | 396 | .ops = &kirkwood_i2s_dai_ops, |
390 | }; | 397 | }; |
391 | EXPORT_SYMBOL_GPL(kirkwood_i2s_dai); | ||
392 | 398 | ||
393 | static __devinit int kirkwood_i2s_dev_probe(struct platform_device *pdev) | 399 | static __devinit int kirkwood_i2s_dev_probe(struct platform_device *pdev) |
394 | { | 400 | { |
395 | struct resource *mem; | 401 | struct resource *mem; |
396 | struct kirkwood_asoc_platform_data *data = | 402 | struct kirkwood_asoc_platform_data *data = |
397 | pdev->dev.platform_data; | 403 | pdev->dev.platform_data; |
404 | struct kirkwood_dma_data *priv; | ||
398 | int err; | 405 | int err; |
399 | 406 | ||
400 | priv = kzalloc(sizeof(struct kirkwood_dma_data), GFP_KERNEL); | 407 | priv = kzalloc(sizeof(struct kirkwood_dma_data), GFP_KERNEL); |
@@ -403,6 +410,7 @@ static __devinit int kirkwood_i2s_dev_probe(struct platform_device *pdev) | |||
403 | err = -ENOMEM; | 410 | err = -ENOMEM; |
404 | goto error; | 411 | goto error; |
405 | } | 412 | } |
413 | dev_set_drvdata(&pdev->dev, priv); | ||
406 | 414 | ||
407 | mem = platform_get_resource(pdev, IORESOURCE_MEM, 0); | 415 | mem = platform_get_resource(pdev, IORESOURCE_MEM, 0); |
408 | if (!mem) { | 416 | if (!mem) { |
@@ -441,10 +449,7 @@ static __devinit int kirkwood_i2s_dev_probe(struct platform_device *pdev) | |||
441 | priv->dram = data->dram; | 449 | priv->dram = data->dram; |
442 | priv->burst = data->burst; | 450 | priv->burst = data->burst; |
443 | 451 | ||
444 | kirkwood_i2s_dai.capture.dma_data = priv; | 452 | return snd_soc_register_dai(&pdev->dev, &kirkwood_i2s_dai); |
445 | kirkwood_i2s_dai.playback.dma_data = priv; | ||
446 | |||
447 | return snd_soc_register_dai(&kirkwood_i2s_dai); | ||
448 | 453 | ||
449 | err_ioremap: | 454 | err_ioremap: |
450 | iounmap(priv->io); | 455 | iounmap(priv->io); |
@@ -458,12 +463,13 @@ error: | |||
458 | 463 | ||
459 | static __devexit int kirkwood_i2s_dev_remove(struct platform_device *pdev) | 464 | static __devexit int kirkwood_i2s_dev_remove(struct platform_device *pdev) |
460 | { | 465 | { |
461 | if (priv) { | 466 | struct kirkwood_dma_data *priv = dev_get_drvdata(&pdev->dev); |
462 | iounmap(priv->io); | 467 | |
463 | release_mem_region(priv->mem->start, SZ_16K); | 468 | snd_soc_unregister_dai(&pdev->dev); |
464 | kfree(priv); | 469 | iounmap(priv->io); |
465 | } | 470 | release_mem_region(priv->mem->start, SZ_16K); |
466 | snd_soc_unregister_dai(&kirkwood_i2s_dai); | 471 | kfree(priv); |
472 | |||
467 | return 0; | 473 | return 0; |
468 | } | 474 | } |
469 | 475 | ||
diff --git a/sound/soc/kirkwood/kirkwood-i2s.h b/sound/soc/kirkwood/kirkwood-i2s.h deleted file mode 100644 index c5595c616d7a..000000000000 --- a/sound/soc/kirkwood/kirkwood-i2s.h +++ /dev/null | |||
@@ -1,17 +0,0 @@ | |||
1 | /* | ||
2 | * kirkwood-i2s.h | ||
3 | * | ||
4 | * (c) 2010 Arnaud Patard <apatard@mandriva.com> | ||
5 | * | ||
6 | * This program is free software; you can redistribute it and/or modify it | ||
7 | * under the terms of the GNU General Public License as published by the | ||
8 | * Free Software Foundation; either version 2 of the License, or (at your | ||
9 | * option) any later version. | ||
10 | */ | ||
11 | |||
12 | #ifndef _KIRKWOOD_I2S_H | ||
13 | #define _KIRKWOOD_I2S_H | ||
14 | |||
15 | extern struct snd_soc_dai kirkwood_i2s_dai; | ||
16 | |||
17 | #endif | ||
diff --git a/sound/soc/kirkwood/kirkwood-openrd.c b/sound/soc/kirkwood/kirkwood-openrd.c index 0353d06bc41a..cc1a1e277edf 100644 --- a/sound/soc/kirkwood/kirkwood-openrd.c +++ b/sound/soc/kirkwood/kirkwood-openrd.c | |||
@@ -18,16 +18,14 @@ | |||
18 | #include <mach/kirkwood.h> | 18 | #include <mach/kirkwood.h> |
19 | #include <plat/audio.h> | 19 | #include <plat/audio.h> |
20 | #include <asm/mach-types.h> | 20 | #include <asm/mach-types.h> |
21 | #include "kirkwood-i2s.h" | ||
22 | #include "kirkwood-dma.h" | ||
23 | #include "../codecs/cs42l51.h" | 21 | #include "../codecs/cs42l51.h" |
24 | 22 | ||
25 | static int openrd_client_hw_params(struct snd_pcm_substream *substream, | 23 | static int openrd_client_hw_params(struct snd_pcm_substream *substream, |
26 | struct snd_pcm_hw_params *params) | 24 | struct snd_pcm_hw_params *params) |
27 | { | 25 | { |
28 | struct snd_soc_pcm_runtime *rtd = substream->private_data; | 26 | struct snd_soc_pcm_runtime *rtd = substream->private_data; |
29 | struct snd_soc_dai *codec_dai = rtd->dai->codec_dai; | 27 | struct snd_soc_dai *codec_dai = rtd->codec_dai; |
30 | struct snd_soc_dai *cpu_dai = rtd->dai->cpu_dai; | 28 | struct snd_soc_dai *cpu_dai = rtd->cpu_dai; |
31 | int ret; | 29 | int ret; |
32 | unsigned int freq, fmt; | 30 | unsigned int freq, fmt; |
33 | 31 | ||
@@ -66,8 +64,10 @@ static struct snd_soc_dai_link openrd_client_dai[] = { | |||
66 | { | 64 | { |
67 | .name = "CS42L51", | 65 | .name = "CS42L51", |
68 | .stream_name = "CS42L51 HiFi", | 66 | .stream_name = "CS42L51 HiFi", |
69 | .cpu_dai = &kirkwood_i2s_dai, | 67 | .cpu_dai_name = "kirkwood-i2s", |
70 | .codec_dai = &cs42l51_dai, | 68 | .platform_name = "kirkwood-pcm-audio", |
69 | .codec_dai_name = "cs42l51_hifi", | ||
70 | .codec_name = "cs42l51-codec.0-004a", | ||
71 | .ops = &openrd_client_ops, | 71 | .ops = &openrd_client_ops, |
72 | }, | 72 | }, |
73 | }; | 73 | }; |
@@ -75,16 +75,10 @@ static struct snd_soc_dai_link openrd_client_dai[] = { | |||
75 | 75 | ||
76 | static struct snd_soc_card openrd_client = { | 76 | static struct snd_soc_card openrd_client = { |
77 | .name = "OpenRD Client", | 77 | .name = "OpenRD Client", |
78 | .platform = &kirkwood_soc_platform, | ||
79 | .dai_link = openrd_client_dai, | 78 | .dai_link = openrd_client_dai, |
80 | .num_links = ARRAY_SIZE(openrd_client_dai), | 79 | .num_links = ARRAY_SIZE(openrd_client_dai), |
81 | }; | 80 | }; |
82 | 81 | ||
83 | static struct snd_soc_device openrd_client_snd_devdata = { | ||
84 | .card = &openrd_client, | ||
85 | .codec_dev = &soc_codec_device_cs42l51, | ||
86 | }; | ||
87 | |||
88 | static struct platform_device *openrd_client_snd_device; | 82 | static struct platform_device *openrd_client_snd_device; |
89 | 83 | ||
90 | static int __init openrd_client_init(void) | 84 | static int __init openrd_client_init(void) |
@@ -99,8 +93,7 @@ static int __init openrd_client_init(void) | |||
99 | return -ENOMEM; | 93 | return -ENOMEM; |
100 | 94 | ||
101 | platform_set_drvdata(openrd_client_snd_device, | 95 | platform_set_drvdata(openrd_client_snd_device, |
102 | &openrd_client_snd_devdata); | 96 | &openrd_client); |
103 | openrd_client_snd_devdata.dev = &openrd_client_snd_device->dev; | ||
104 | 97 | ||
105 | ret = platform_device_add(openrd_client_snd_device); | 98 | ret = platform_device_add(openrd_client_snd_device); |
106 | if (ret) { | 99 | if (ret) { |
diff --git a/sound/soc/nuc900/nuc900-ac97.c b/sound/soc/nuc900/nuc900-ac97.c index caa7c901bc2e..02b64a17dec2 100644 --- a/sound/soc/nuc900/nuc900-ac97.c +++ b/sound/soc/nuc900/nuc900-ac97.c | |||
@@ -297,8 +297,7 @@ static struct snd_soc_dai_ops nuc900_ac97_dai_ops = { | |||
297 | .trigger = nuc900_ac97_trigger, | 297 | .trigger = nuc900_ac97_trigger, |
298 | }; | 298 | }; |
299 | 299 | ||
300 | struct snd_soc_dai nuc900_ac97_dai = { | 300 | static struct snd_soc_dai_driver nuc900_ac97_dai = { |
301 | .name = "nuc900-ac97", | ||
302 | .probe = nuc900_ac97_probe, | 301 | .probe = nuc900_ac97_probe, |
303 | .remove = nuc900_ac97_remove, | 302 | .remove = nuc900_ac97_remove, |
304 | .ac97_control = 1, | 303 | .ac97_control = 1, |
@@ -316,7 +315,6 @@ struct snd_soc_dai nuc900_ac97_dai = { | |||
316 | }, | 315 | }, |
317 | .ops = &nuc900_ac97_dai_ops, | 316 | .ops = &nuc900_ac97_dai_ops, |
318 | } | 317 | } |
319 | EXPORT_SYMBOL_GPL(nuc900_ac97_dai); | ||
320 | 318 | ||
321 | static int __devinit nuc900_ac97_drvprobe(struct platform_device *pdev) | 319 | static int __devinit nuc900_ac97_drvprobe(struct platform_device *pdev) |
322 | { | 320 | { |
@@ -365,9 +363,7 @@ static int __devinit nuc900_ac97_drvprobe(struct platform_device *pdev) | |||
365 | 363 | ||
366 | nuc900_ac97_data = nuc900_audio; | 364 | nuc900_ac97_data = nuc900_audio; |
367 | 365 | ||
368 | nuc900_audio->dev = nuc900_ac97_dai.dev = &pdev->dev; | 366 | ret = snd_soc_register_dai(&pdev->dev, &nuc900_ac97_dai); |
369 | |||
370 | ret = snd_soc_register_dai(&nuc900_ac97_dai); | ||
371 | if (ret) | 367 | if (ret) |
372 | goto out3; | 368 | goto out3; |
373 | 369 | ||
@@ -390,7 +386,7 @@ out0: | |||
390 | static int __devexit nuc900_ac97_drvremove(struct platform_device *pdev) | 386 | static int __devexit nuc900_ac97_drvremove(struct platform_device *pdev) |
391 | { | 387 | { |
392 | 388 | ||
393 | snd_soc_unregister_dai(&nuc900_ac97_dai); | 389 | snd_soc_unregister_dai(&pdev->dev); |
394 | 390 | ||
395 | clk_put(nuc900_ac97_data->clk); | 391 | clk_put(nuc900_ac97_data->clk); |
396 | iounmap(nuc900_ac97_data->mmio); | 392 | iounmap(nuc900_ac97_data->mmio); |
@@ -404,7 +400,7 @@ static int __devexit nuc900_ac97_drvremove(struct platform_device *pdev) | |||
404 | 400 | ||
405 | static struct platform_driver nuc900_ac97_driver = { | 401 | static struct platform_driver nuc900_ac97_driver = { |
406 | .driver = { | 402 | .driver = { |
407 | .name = "nuc900-audio", | 403 | .name = "nuc900-ac97", |
408 | .owner = THIS_MODULE, | 404 | .owner = THIS_MODULE, |
409 | }, | 405 | }, |
410 | .probe = nuc900_ac97_drvprobe, | 406 | .probe = nuc900_ac97_drvprobe, |
diff --git a/sound/soc/nuc900/nuc900-audio.c b/sound/soc/nuc900/nuc900-audio.c index 72e6f518f7b2..161f5b667d7b 100644 --- a/sound/soc/nuc900/nuc900-audio.c +++ b/sound/soc/nuc900/nuc900-audio.c | |||
@@ -20,26 +20,21 @@ | |||
20 | #include <sound/soc.h> | 20 | #include <sound/soc.h> |
21 | #include <sound/soc-dapm.h> | 21 | #include <sound/soc-dapm.h> |
22 | 22 | ||
23 | #include "../codecs/ac97.h" | ||
24 | #include "nuc900-audio.h" | 23 | #include "nuc900-audio.h" |
25 | 24 | ||
26 | static struct snd_soc_dai_link nuc900evb_ac97_dai = { | 25 | static struct snd_soc_dai_link nuc900evb_ac97_dai = { |
27 | .name = "AC97", | 26 | .name = "AC97", |
28 | .stream_name = "AC97 HiFi", | 27 | .stream_name = "AC97 HiFi", |
29 | .cpu_dai = &nuc900_ac97_dai, | 28 | .cpu_dai_name = "nuc900-ac97", |
30 | .codec_dai = &ac97_dai, | 29 | .codec_dai_name = "ac97-hifi", |
30 | .codec_name = "ac97-codec", | ||
31 | .platform_name = "nuc900-pcm-audio", | ||
31 | }; | 32 | }; |
32 | 33 | ||
33 | static struct snd_soc_card nuc900evb_audio_machine = { | 34 | static struct snd_soc_card nuc900evb_audio_machine = { |
34 | .name = "NUC900EVB_AC97", | 35 | .name = "NUC900EVB_AC97", |
35 | .dai_link = &nuc900evb_ac97_dai, | 36 | .dai_link = &nuc900evb_ac97_dai, |
36 | .num_links = 1, | 37 | .num_links = 1, |
37 | .platform = &nuc900_soc_platform, | ||
38 | }; | ||
39 | |||
40 | static struct snd_soc_device nuc900evb_ac97_devdata = { | ||
41 | .card = &nuc900evb_audio_machine, | ||
42 | .codec_dev = &soc_codec_dev_ac97, | ||
43 | }; | 38 | }; |
44 | 39 | ||
45 | static struct platform_device *nuc900evb_asoc_dev; | 40 | static struct platform_device *nuc900evb_asoc_dev; |
@@ -54,9 +49,8 @@ static int __init nuc900evb_audio_init(void) | |||
54 | goto out; | 49 | goto out; |
55 | 50 | ||
56 | /* nuc900 board audio device */ | 51 | /* nuc900 board audio device */ |
57 | platform_set_drvdata(nuc900evb_asoc_dev, &nuc900evb_ac97_devdata); | 52 | platform_set_drvdata(nuc900evb_asoc_dev, &nuc900evb_audio_machine); |
58 | 53 | ||
59 | nuc900evb_ac97_devdata.dev = &nuc900evb_asoc_dev->dev; | ||
60 | ret = platform_device_add(nuc900evb_asoc_dev); | 54 | ret = platform_device_add(nuc900evb_asoc_dev); |
61 | 55 | ||
62 | if (ret) { | 56 | if (ret) { |
diff --git a/sound/soc/nuc900/nuc900-audio.h b/sound/soc/nuc900/nuc900-audio.h index 3038f519729f..aeed8ead2b2b 100644 --- a/sound/soc/nuc900/nuc900-audio.h +++ b/sound/soc/nuc900/nuc900-audio.h | |||
@@ -110,8 +110,4 @@ struct nuc900_audio { | |||
110 | 110 | ||
111 | }; | 111 | }; |
112 | 112 | ||
113 | extern struct nuc900_audio *nuc900_ac97_data; | ||
114 | extern struct snd_soc_dai nuc900_ac97_dai; | ||
115 | extern struct snd_soc_platform nuc900_soc_platform; | ||
116 | |||
117 | #endif /*end _NUC900_AUDIO_H */ | 113 | #endif /*end _NUC900_AUDIO_H */ |
diff --git a/sound/soc/nuc900/nuc900-pcm.c b/sound/soc/nuc900/nuc900-pcm.c index e81e803b3a63..195d1ac94771 100644 --- a/sound/soc/nuc900/nuc900-pcm.c +++ b/sound/soc/nuc900/nuc900-pcm.c | |||
@@ -328,26 +328,44 @@ static int nuc900_dma_new(struct snd_card *card, | |||
328 | return 0; | 328 | return 0; |
329 | } | 329 | } |
330 | 330 | ||
331 | struct snd_soc_platform nuc900_soc_platform = { | 331 | static struct snd_soc_platform_driver nuc900_soc_platform = { |
332 | .name = "nuc900-dma", | 332 | .ops = &nuc900_dma_ops, |
333 | .pcm_ops = &nuc900_dma_ops, | ||
334 | .pcm_new = nuc900_dma_new, | 333 | .pcm_new = nuc900_dma_new, |
335 | .pcm_free = nuc900_dma_free_dma_buffers, | 334 | .pcm_free = nuc900_dma_free_dma_buffers, |
336 | } | 335 | } |
337 | EXPORT_SYMBOL_GPL(nuc900_soc_platform); | ||
338 | 336 | ||
339 | static int __init nuc900_soc_platform_init(void) | 337 | static int __devinit nuc900_soc_platform_probe(struct platform_device *pdev) |
340 | { | 338 | { |
341 | return snd_soc_register_platform(&nuc900_soc_platform); | 339 | return snd_soc_register_platform(&pdev->dev, &nuc900_soc_platform); |
342 | } | 340 | } |
343 | 341 | ||
344 | static void __exit nuc900_soc_platform_exit(void) | 342 | static int __devexit nuc900_soc_platform_remove(struct platform_device *pdev) |
345 | { | 343 | { |
346 | snd_soc_unregister_platform(&nuc900_soc_platform); | 344 | snd_soc_unregister_platform(&pdev->dev); |
345 | return 0; | ||
347 | } | 346 | } |
348 | 347 | ||
349 | module_init(nuc900_soc_platform_init); | 348 | static struct platform_driver nuc900_pcm_driver = { |
350 | module_exit(nuc900_soc_platform_exit); | 349 | .driver = { |
350 | .name = "nuc900-pcm-audio", | ||
351 | .owner = THIS_MODULE, | ||
352 | }, | ||
353 | |||
354 | .probe = nuc900_soc_platform_probe, | ||
355 | .remove = __devexit_p(nuc900_soc_platform_remove), | ||
356 | }; | ||
357 | |||
358 | static int __init nuc900_pcm_init(void) | ||
359 | { | ||
360 | return platform_driver_register(&nuc900_pcm_driver); | ||
361 | } | ||
362 | module_init(nuc900_pcm_init); | ||
363 | |||
364 | static void __exit nuc900_pcm_exit(void) | ||
365 | { | ||
366 | platform_driver_unregister(&nuc900_pcm_driver); | ||
367 | } | ||
368 | module_exit(nuc900_pcm_exit); | ||
351 | 369 | ||
352 | MODULE_AUTHOR("Wan ZongShun, <mcuos.com@gmail.com>"); | 370 | MODULE_AUTHOR("Wan ZongShun, <mcuos.com@gmail.com>"); |
353 | MODULE_DESCRIPTION("nuc900 Audio DMA module"); | 371 | MODULE_DESCRIPTION("nuc900 Audio DMA module"); |
diff --git a/sound/soc/omap/am3517evm.c b/sound/soc/omap/am3517evm.c index 135901b2ea11..68bd902ccd4e 100644 --- a/sound/soc/omap/am3517evm.c +++ b/sound/soc/omap/am3517evm.c | |||
@@ -40,8 +40,8 @@ static int am3517evm_hw_params(struct snd_pcm_substream *substream, | |||
40 | struct snd_pcm_hw_params *params) | 40 | struct snd_pcm_hw_params *params) |
41 | { | 41 | { |
42 | struct snd_soc_pcm_runtime *rtd = substream->private_data; | 42 | struct snd_soc_pcm_runtime *rtd = substream->private_data; |
43 | struct snd_soc_dai *codec_dai = rtd->dai->codec_dai; | 43 | struct snd_soc_dai *codec_dai = rtd->codec_dai; |
44 | struct snd_soc_dai *cpu_dai = rtd->dai->cpu_dai; | 44 | struct snd_soc_dai *cpu_dai = rtd->cpu_dai; |
45 | int ret; | 45 | int ret; |
46 | 46 | ||
47 | /* Set codec DAI configuration */ | 47 | /* Set codec DAI configuration */ |
@@ -111,8 +111,10 @@ static const struct snd_soc_dapm_route audio_map[] = { | |||
111 | {"MICIN", NULL, "Mic In"}, | 111 | {"MICIN", NULL, "Mic In"}, |
112 | }; | 112 | }; |
113 | 113 | ||
114 | static int am3517evm_aic23_init(struct snd_soc_codec *codec) | 114 | static int am3517evm_aic23_init(struct snd_soc_pcm_runtime *rtd) |
115 | { | 115 | { |
116 | struct snd_soc_codec *codec = rtd->codec; | ||
117 | |||
116 | /* Add am3517-evm specific widgets */ | 118 | /* Add am3517-evm specific widgets */ |
117 | snd_soc_dapm_new_controls(codec, tlv320aic23_dapm_widgets, | 119 | snd_soc_dapm_new_controls(codec, tlv320aic23_dapm_widgets, |
118 | ARRAY_SIZE(tlv320aic23_dapm_widgets)); | 120 | ARRAY_SIZE(tlv320aic23_dapm_widgets)); |
@@ -134,8 +136,10 @@ static int am3517evm_aic23_init(struct snd_soc_codec *codec) | |||
134 | static struct snd_soc_dai_link am3517evm_dai = { | 136 | static struct snd_soc_dai_link am3517evm_dai = { |
135 | .name = "TLV320AIC23", | 137 | .name = "TLV320AIC23", |
136 | .stream_name = "AIC23", | 138 | .stream_name = "AIC23", |
137 | .cpu_dai = &omap_mcbsp_dai[0], | 139 | .cpu_dai_name ="omap-mcbsp-dai.0", |
138 | .codec_dai = &tlv320aic23_dai, | 140 | .codec_dai_name = "tlv320aic23-hifi", |
141 | .platform_name = "omap-pcm-audio", | ||
142 | .codec_name = "tlv320aic23-codec", | ||
139 | .init = am3517evm_aic23_init, | 143 | .init = am3517evm_aic23_init, |
140 | .ops = &am3517evm_ops, | 144 | .ops = &am3517evm_ops, |
141 | }; | 145 | }; |
@@ -143,17 +147,10 @@ static struct snd_soc_dai_link am3517evm_dai = { | |||
143 | /* Audio machine driver */ | 147 | /* Audio machine driver */ |
144 | static struct snd_soc_card snd_soc_am3517evm = { | 148 | static struct snd_soc_card snd_soc_am3517evm = { |
145 | .name = "am3517evm", | 149 | .name = "am3517evm", |
146 | .platform = &omap_soc_platform, | ||
147 | .dai_link = &am3517evm_dai, | 150 | .dai_link = &am3517evm_dai, |
148 | .num_links = 1, | 151 | .num_links = 1, |
149 | }; | 152 | }; |
150 | 153 | ||
151 | /* Audio subsystem */ | ||
152 | static struct snd_soc_device am3517evm_snd_devdata = { | ||
153 | .card = &snd_soc_am3517evm, | ||
154 | .codec_dev = &soc_codec_dev_tlv320aic23, | ||
155 | }; | ||
156 | |||
157 | static struct platform_device *am3517evm_snd_device; | 154 | static struct platform_device *am3517evm_snd_device; |
158 | 155 | ||
159 | static int __init am3517evm_soc_init(void) | 156 | static int __init am3517evm_soc_init(void) |
@@ -172,9 +169,7 @@ static int __init am3517evm_soc_init(void) | |||
172 | return -ENOMEM; | 169 | return -ENOMEM; |
173 | } | 170 | } |
174 | 171 | ||
175 | platform_set_drvdata(am3517evm_snd_device, &am3517evm_snd_devdata); | 172 | platform_set_drvdata(am3517evm_snd_device, &snd_soc_am3517evm); |
176 | am3517evm_snd_devdata.dev = &am3517evm_snd_device->dev; | ||
177 | *(unsigned int *)am3517evm_dai.cpu_dai->private_data = 0; /* McBSP1 */ | ||
178 | 173 | ||
179 | ret = platform_device_add(am3517evm_snd_device); | 174 | ret = platform_device_add(am3517evm_snd_device); |
180 | if (ret) | 175 | if (ret) |
diff --git a/sound/soc/omap/ams-delta.c b/sound/soc/omap/ams-delta.c index b0f618e44840..9d88efa06e3c 100644 --- a/sound/soc/omap/ams-delta.c +++ b/sound/soc/omap/ams-delta.c | |||
@@ -99,7 +99,7 @@ static int ams_delta_set_audio_mode(struct snd_kcontrol *kcontrol, | |||
99 | int pin, changed = 0; | 99 | int pin, changed = 0; |
100 | 100 | ||
101 | /* Refuse any mode changes if we are not able to control the codec. */ | 101 | /* Refuse any mode changes if we are not able to control the codec. */ |
102 | if (!codec->control_data) | 102 | if (!codec->hw_write) |
103 | return -EUNATCH; | 103 | return -EUNATCH; |
104 | 104 | ||
105 | if (ucontrol->value.enumerated.item[0] >= control->max) | 105 | if (ucontrol->value.enumerated.item[0] >= control->max) |
@@ -268,10 +268,32 @@ static void cx81801_timeout(unsigned long data) | |||
268 | ams_delta_latch2_write(AMS_DELTA_LATCH2_MODEM_CODEC, 0); | 268 | ams_delta_latch2_write(AMS_DELTA_LATCH2_MODEM_CODEC, 0); |
269 | } | 269 | } |
270 | 270 | ||
271 | /* | ||
272 | * Used for passing a codec structure pointer | ||
273 | * from the board initialization code to the tty line discipline. | ||
274 | */ | ||
275 | static struct snd_soc_codec *cx20442_codec; | ||
276 | |||
271 | /* Line discipline .open() */ | 277 | /* Line discipline .open() */ |
272 | static int cx81801_open(struct tty_struct *tty) | 278 | static int cx81801_open(struct tty_struct *tty) |
273 | { | 279 | { |
274 | return v253_ops.open(tty); | 280 | int ret; |
281 | |||
282 | if (!cx20442_codec) | ||
283 | return -ENODEV; | ||
284 | |||
285 | /* | ||
286 | * Pass the codec structure pointer for use by other ldisc callbacks, | ||
287 | * both the card and the codec specific parts. | ||
288 | */ | ||
289 | tty->disc_data = cx20442_codec; | ||
290 | |||
291 | ret = v253_ops.open(tty); | ||
292 | |||
293 | if (ret < 0) | ||
294 | tty->disc_data = NULL; | ||
295 | |||
296 | return ret; | ||
275 | } | 297 | } |
276 | 298 | ||
277 | /* Line discipline .close() */ | 299 | /* Line discipline .close() */ |
@@ -281,11 +303,14 @@ static void cx81801_close(struct tty_struct *tty) | |||
281 | 303 | ||
282 | del_timer_sync(&cx81801_timer); | 304 | del_timer_sync(&cx81801_timer); |
283 | 305 | ||
284 | v253_ops.close(tty); | ||
285 | |||
286 | /* Prevent the hook switch from further changing the DAPM pins */ | 306 | /* Prevent the hook switch from further changing the DAPM pins */ |
287 | INIT_LIST_HEAD(&ams_delta_hook_switch.pins); | 307 | INIT_LIST_HEAD(&ams_delta_hook_switch.pins); |
288 | 308 | ||
309 | if (!codec) | ||
310 | return; | ||
311 | |||
312 | v253_ops.close(tty); | ||
313 | |||
289 | /* Revert back to default audio input/output constellation */ | 314 | /* Revert back to default audio input/output constellation */ |
290 | snd_soc_dapm_disable_pin(codec, "Mouthpiece"); | 315 | snd_soc_dapm_disable_pin(codec, "Mouthpiece"); |
291 | snd_soc_dapm_enable_pin(codec, "Earpiece"); | 316 | snd_soc_dapm_enable_pin(codec, "Earpiece"); |
@@ -310,7 +335,10 @@ static void cx81801_receive(struct tty_struct *tty, | |||
310 | const unsigned char *c; | 335 | const unsigned char *c; |
311 | int apply, ret; | 336 | int apply, ret; |
312 | 337 | ||
313 | if (!codec->control_data) { | 338 | if (!codec) |
339 | return; | ||
340 | |||
341 | if (!codec->hw_write) { | ||
314 | /* First modem response, complete setup procedure */ | 342 | /* First modem response, complete setup procedure */ |
315 | 343 | ||
316 | /* Initialize timer used for config pulse generation */ | 344 | /* Initialize timer used for config pulse generation */ |
@@ -323,7 +351,7 @@ static void cx81801_receive(struct tty_struct *tty, | |||
323 | ARRAY_SIZE(ams_delta_hook_switch_pins), | 351 | ARRAY_SIZE(ams_delta_hook_switch_pins), |
324 | ams_delta_hook_switch_pins); | 352 | ams_delta_hook_switch_pins); |
325 | if (ret) | 353 | if (ret) |
326 | dev_warn(codec->socdev->card->dev, | 354 | dev_warn(codec->dev, |
327 | "Failed to link hook switch to DAPM pins, " | 355 | "Failed to link hook switch to DAPM pins, " |
328 | "will continue with hook switch unlinked.\n"); | 356 | "will continue with hook switch unlinked.\n"); |
329 | 357 | ||
@@ -383,7 +411,7 @@ static int ams_delta_hw_params(struct snd_pcm_substream *substream, | |||
383 | struct snd_soc_pcm_runtime *rtd = substream->private_data; | 411 | struct snd_soc_pcm_runtime *rtd = substream->private_data; |
384 | 412 | ||
385 | /* Set cpu DAI configuration */ | 413 | /* Set cpu DAI configuration */ |
386 | return snd_soc_dai_set_fmt(rtd->dai->cpu_dai, | 414 | return snd_soc_dai_set_fmt(rtd->cpu_dai, |
387 | SND_SOC_DAIFMT_DSP_A | | 415 | SND_SOC_DAIFMT_DSP_A | |
388 | SND_SOC_DAIFMT_NB_NF | | 416 | SND_SOC_DAIFMT_NB_NF | |
389 | SND_SOC_DAIFMT_CBM_CFM); | 417 | SND_SOC_DAIFMT_CBM_CFM); |
@@ -398,7 +426,7 @@ static struct snd_soc_ops ams_delta_ops = { | |||
398 | static int ams_delta_set_bias_level(struct snd_soc_card *card, | 426 | static int ams_delta_set_bias_level(struct snd_soc_card *card, |
399 | enum snd_soc_bias_level level) | 427 | enum snd_soc_bias_level level) |
400 | { | 428 | { |
401 | struct snd_soc_codec *codec = card->codec; | 429 | struct snd_soc_codec *codec = card->rtd->codec; |
402 | 430 | ||
403 | switch (level) { | 431 | switch (level) { |
404 | case SND_SOC_BIAS_ON: | 432 | case SND_SOC_BIAS_ON: |
@@ -461,18 +489,22 @@ static void ams_delta_shutdown(struct snd_pcm_substream *substream) | |||
461 | * Card initialization | 489 | * Card initialization |
462 | */ | 490 | */ |
463 | 491 | ||
464 | static int ams_delta_cx20442_init(struct snd_soc_codec *codec) | 492 | static int ams_delta_cx20442_init(struct snd_soc_pcm_runtime *rtd) |
465 | { | 493 | { |
466 | struct snd_soc_dai *codec_dai = codec->dai; | 494 | struct snd_soc_codec *codec = rtd->codec; |
467 | struct snd_soc_card *card = codec->socdev->card; | 495 | struct snd_soc_dai *codec_dai = rtd->codec_dai; |
496 | struct snd_soc_card *card = rtd->card; | ||
468 | int ret; | 497 | int ret; |
469 | /* Codec is ready, now add/activate board specific controls */ | 498 | /* Codec is ready, now add/activate board specific controls */ |
470 | 499 | ||
500 | /* Store a pointer to the codec structure for tty ldisc use */ | ||
501 | cx20442_codec = codec; | ||
502 | |||
471 | /* Set up digital mute if not provided by the codec */ | 503 | /* Set up digital mute if not provided by the codec */ |
472 | if (!codec_dai->ops) { | 504 | if (!codec_dai->driver->ops) { |
473 | codec_dai->ops = &ams_delta_dai_ops; | 505 | codec_dai->driver->ops = &ams_delta_dai_ops; |
474 | } else if (!codec_dai->ops->digital_mute) { | 506 | } else if (!codec_dai->driver->ops->digital_mute) { |
475 | codec_dai->ops->digital_mute = ams_delta_digital_mute; | 507 | codec_dai->driver->ops->digital_mute = ams_delta_digital_mute; |
476 | } else { | 508 | } else { |
477 | ams_delta_ops.startup = ams_delta_startup; | 509 | ams_delta_ops.startup = ams_delta_startup; |
478 | ams_delta_ops.shutdown = ams_delta_shutdown; | 510 | ams_delta_ops.shutdown = ams_delta_shutdown; |
@@ -483,7 +515,7 @@ static int ams_delta_cx20442_init(struct snd_soc_codec *codec) | |||
483 | 515 | ||
484 | /* Add hook switch - can be used to control the codec from userspace | 516 | /* Add hook switch - can be used to control the codec from userspace |
485 | * even if line discipline fails */ | 517 | * even if line discipline fails */ |
486 | ret = snd_soc_jack_new(card, "hook_switch", | 518 | ret = snd_soc_jack_new(rtd->codec, "hook_switch", |
487 | SND_JACK_HEADSET, &ams_delta_hook_switch); | 519 | SND_JACK_HEADSET, &ams_delta_hook_switch); |
488 | if (ret) | 520 | if (ret) |
489 | dev_warn(card->dev, | 521 | dev_warn(card->dev, |
@@ -551,27 +583,22 @@ static int ams_delta_cx20442_init(struct snd_soc_codec *codec) | |||
551 | static struct snd_soc_dai_link ams_delta_dai_link = { | 583 | static struct snd_soc_dai_link ams_delta_dai_link = { |
552 | .name = "CX20442", | 584 | .name = "CX20442", |
553 | .stream_name = "CX20442", | 585 | .stream_name = "CX20442", |
554 | .cpu_dai = &omap_mcbsp_dai[0], | 586 | .cpu_dai_name ="omap-mcbsp-dai.0", |
555 | .codec_dai = &cx20442_dai, | 587 | .codec_dai_name = "cx20442-hifi", |
556 | .init = ams_delta_cx20442_init, | 588 | .init = ams_delta_cx20442_init, |
589 | .platform_name = "omap-pcm-audio", | ||
590 | .codec_name = "cx20442-codec", | ||
557 | .ops = &ams_delta_ops, | 591 | .ops = &ams_delta_ops, |
558 | }; | 592 | }; |
559 | 593 | ||
560 | /* Audio card driver */ | 594 | /* Audio card driver */ |
561 | static struct snd_soc_card ams_delta_audio_card = { | 595 | static struct snd_soc_card ams_delta_audio_card = { |
562 | .name = "AMS_DELTA", | 596 | .name = "AMS_DELTA", |
563 | .platform = &omap_soc_platform, | ||
564 | .dai_link = &ams_delta_dai_link, | 597 | .dai_link = &ams_delta_dai_link, |
565 | .num_links = 1, | 598 | .num_links = 1, |
566 | .set_bias_level = ams_delta_set_bias_level, | 599 | .set_bias_level = ams_delta_set_bias_level, |
567 | }; | 600 | }; |
568 | 601 | ||
569 | /* Audio subsystem */ | ||
570 | static struct snd_soc_device ams_delta_snd_soc_device = { | ||
571 | .card = &ams_delta_audio_card, | ||
572 | .codec_dev = &cx20442_codec_dev, | ||
573 | }; | ||
574 | |||
575 | /* Module init/exit */ | 602 | /* Module init/exit */ |
576 | static struct platform_device *ams_delta_audio_platform_device; | 603 | static struct platform_device *ams_delta_audio_platform_device; |
577 | static struct platform_device *cx20442_platform_device; | 604 | static struct platform_device *cx20442_platform_device; |
@@ -589,9 +616,7 @@ static int __init ams_delta_module_init(void) | |||
589 | return -ENOMEM; | 616 | return -ENOMEM; |
590 | 617 | ||
591 | platform_set_drvdata(ams_delta_audio_platform_device, | 618 | platform_set_drvdata(ams_delta_audio_platform_device, |
592 | &ams_delta_snd_soc_device); | 619 | &ams_delta_audio_card); |
593 | ams_delta_snd_soc_device.dev = &ams_delta_audio_platform_device->dev; | ||
594 | *(unsigned int *)ams_delta_dai_link.cpu_dai->private_data = OMAP_MCBSP1; | ||
595 | 620 | ||
596 | ret = platform_device_add(ams_delta_audio_platform_device); | 621 | ret = platform_device_add(ams_delta_audio_platform_device); |
597 | if (ret) | 622 | if (ret) |
@@ -601,8 +626,8 @@ static int __init ams_delta_module_init(void) | |||
601 | * Codec platform device could be registered from elsewhere (board?), | 626 | * Codec platform device could be registered from elsewhere (board?), |
602 | * but I do it here as it makes sense only if used with the card. | 627 | * but I do it here as it makes sense only if used with the card. |
603 | */ | 628 | */ |
604 | cx20442_platform_device = platform_device_register_simple("cx20442", | 629 | cx20442_platform_device = |
605 | -1, NULL, 0); | 630 | platform_device_register_simple("cx20442-codec", -1, NULL, 0); |
606 | return 0; | 631 | return 0; |
607 | err: | 632 | err: |
608 | platform_device_put(ams_delta_audio_platform_device); | 633 | platform_device_put(ams_delta_audio_platform_device); |
@@ -612,19 +637,6 @@ module_init(ams_delta_module_init); | |||
612 | 637 | ||
613 | static void __exit ams_delta_module_exit(void) | 638 | static void __exit ams_delta_module_exit(void) |
614 | { | 639 | { |
615 | struct snd_soc_codec *codec; | ||
616 | struct tty_struct *tty; | ||
617 | |||
618 | if (ams_delta_audio_card.codec) { | ||
619 | codec = ams_delta_audio_card.codec; | ||
620 | |||
621 | if (codec->control_data) { | ||
622 | tty = codec->control_data; | ||
623 | |||
624 | tty_hangup(tty); | ||
625 | } | ||
626 | } | ||
627 | |||
628 | if (tty_unregister_ldisc(N_V253) != 0) | 640 | if (tty_unregister_ldisc(N_V253) != 0) |
629 | dev_warn(&ams_delta_audio_platform_device->dev, | 641 | dev_warn(&ams_delta_audio_platform_device->dev, |
630 | "failed to unregister V253 line discipline\n"); | 642 | "failed to unregister V253 line discipline\n"); |
diff --git a/sound/soc/omap/igep0020.c b/sound/soc/omap/igep0020.c index 3583c429f9be..d296cfcc672e 100644 --- a/sound/soc/omap/igep0020.c +++ b/sound/soc/omap/igep0020.c | |||
@@ -33,14 +33,13 @@ | |||
33 | 33 | ||
34 | #include "omap-mcbsp.h" | 34 | #include "omap-mcbsp.h" |
35 | #include "omap-pcm.h" | 35 | #include "omap-pcm.h" |
36 | #include "../codecs/twl4030.h" | ||
37 | 36 | ||
38 | static int igep2_hw_params(struct snd_pcm_substream *substream, | 37 | static int igep2_hw_params(struct snd_pcm_substream *substream, |
39 | struct snd_pcm_hw_params *params) | 38 | struct snd_pcm_hw_params *params) |
40 | { | 39 | { |
41 | struct snd_soc_pcm_runtime *rtd = substream->private_data; | 40 | struct snd_soc_pcm_runtime *rtd = substream->private_data; |
42 | struct snd_soc_dai *codec_dai = rtd->dai->codec_dai; | 41 | struct snd_soc_dai *codec_dai = rtd->codec_dai; |
43 | struct snd_soc_dai *cpu_dai = rtd->dai->cpu_dai; | 42 | struct snd_soc_dai *cpu_dai = rtd->cpu_dai; |
44 | int ret; | 43 | int ret; |
45 | 44 | ||
46 | /* Set codec DAI configuration */ | 45 | /* Set codec DAI configuration */ |
@@ -82,25 +81,20 @@ static struct snd_soc_ops igep2_ops = { | |||
82 | static struct snd_soc_dai_link igep2_dai = { | 81 | static struct snd_soc_dai_link igep2_dai = { |
83 | .name = "TWL4030", | 82 | .name = "TWL4030", |
84 | .stream_name = "TWL4030", | 83 | .stream_name = "TWL4030", |
85 | .cpu_dai = &omap_mcbsp_dai[0], | 84 | .cpu_dai_name = "omap-mcbsp-dai.1", |
86 | .codec_dai = &twl4030_dai[TWL4030_DAI_HIFI], | 85 | .codec_dai_name = "twl4030-hifi", |
86 | .platform_name = "omap-pcm-audio", | ||
87 | .codec_name = "twl4030-codec", | ||
87 | .ops = &igep2_ops, | 88 | .ops = &igep2_ops, |
88 | }; | 89 | }; |
89 | 90 | ||
90 | /* Audio machine driver */ | 91 | /* Audio machine driver */ |
91 | static struct snd_soc_card snd_soc_card_igep2 = { | 92 | static struct snd_soc_card snd_soc_card_igep2 = { |
92 | .name = "igep2", | 93 | .name = "igep2", |
93 | .platform = &omap_soc_platform, | ||
94 | .dai_link = &igep2_dai, | 94 | .dai_link = &igep2_dai, |
95 | .num_links = 1, | 95 | .num_links = 1, |
96 | }; | 96 | }; |
97 | 97 | ||
98 | /* Audio subsystem */ | ||
99 | static struct snd_soc_device igep2_snd_devdata = { | ||
100 | .card = &snd_soc_card_igep2, | ||
101 | .codec_dev = &soc_codec_dev_twl4030, | ||
102 | }; | ||
103 | |||
104 | static struct platform_device *igep2_snd_device; | 98 | static struct platform_device *igep2_snd_device; |
105 | 99 | ||
106 | static int __init igep2_soc_init(void) | 100 | static int __init igep2_soc_init(void) |
@@ -119,9 +113,7 @@ static int __init igep2_soc_init(void) | |||
119 | return -ENOMEM; | 113 | return -ENOMEM; |
120 | } | 114 | } |
121 | 115 | ||
122 | platform_set_drvdata(igep2_snd_device, &igep2_snd_devdata); | 116 | platform_set_drvdata(igep2_snd_device, &snd_soc_card_igep2); |
123 | igep2_snd_devdata.dev = &igep2_snd_device->dev; | ||
124 | *(unsigned int *)igep2_dai.cpu_dai->private_data = 1; /* McBSP2 */ | ||
125 | 117 | ||
126 | ret = platform_device_add(igep2_snd_device); | 118 | ret = platform_device_add(igep2_snd_device); |
127 | if (ret) | 119 | if (ret) |
diff --git a/sound/soc/omap/mcpdm.c b/sound/soc/omap/mcpdm.c index 90b8bf71c893..928f03707451 100644 --- a/sound/soc/omap/mcpdm.c +++ b/sound/soc/omap/mcpdm.c | |||
@@ -402,7 +402,7 @@ int omap_mcpdm_set_offset(int offset1, int offset2) | |||
402 | return 0; | 402 | return 0; |
403 | } | 403 | } |
404 | 404 | ||
405 | static int __devinit omap_mcpdm_probe(struct platform_device *pdev) | 405 | int __devinit omap_mcpdm_probe(struct platform_device *pdev) |
406 | { | 406 | { |
407 | struct resource *res; | 407 | struct resource *res; |
408 | int ret = 0; | 408 | int ret = 0; |
@@ -449,7 +449,7 @@ exit: | |||
449 | return ret; | 449 | return ret; |
450 | } | 450 | } |
451 | 451 | ||
452 | static int __devexit omap_mcpdm_remove(struct platform_device *pdev) | 452 | int __devexit omap_mcpdm_remove(struct platform_device *pdev) |
453 | { | 453 | { |
454 | struct omap_mcpdm *mcpdm_ptr = platform_get_drvdata(pdev); | 454 | struct omap_mcpdm *mcpdm_ptr = platform_get_drvdata(pdev); |
455 | 455 | ||
@@ -468,18 +468,3 @@ static int __devexit omap_mcpdm_remove(struct platform_device *pdev) | |||
468 | return 0; | 468 | return 0; |
469 | } | 469 | } |
470 | 470 | ||
471 | static struct platform_driver omap_mcpdm_driver = { | ||
472 | .probe = omap_mcpdm_probe, | ||
473 | .remove = __devexit_p(omap_mcpdm_remove), | ||
474 | .driver = { | ||
475 | .name = "omap-mcpdm", | ||
476 | }, | ||
477 | }; | ||
478 | |||
479 | static struct platform_device *omap_mcpdm_device; | ||
480 | |||
481 | static int __init omap_mcpdm_init(void) | ||
482 | { | ||
483 | return platform_driver_register(&omap_mcpdm_driver); | ||
484 | } | ||
485 | arch_initcall(omap_mcpdm_init); | ||
diff --git a/sound/soc/omap/mcpdm.h b/sound/soc/omap/mcpdm.h index 7bb326ef0886..df3e16fb51f3 100644 --- a/sound/soc/omap/mcpdm.h +++ b/sound/soc/omap/mcpdm.h | |||
@@ -149,3 +149,5 @@ extern int omap_mcpdm_playback_close(struct omap_mcpdm_link *downlink); | |||
149 | extern int omap_mcpdm_request(void); | 149 | extern int omap_mcpdm_request(void); |
150 | extern void omap_mcpdm_free(void); | 150 | extern void omap_mcpdm_free(void); |
151 | extern int omap_mcpdm_set_offset(int offset1, int offset2); | 151 | extern int omap_mcpdm_set_offset(int offset1, int offset2); |
152 | int __devinit omap_mcpdm_probe(struct platform_device *pdev); | ||
153 | int __devexit omap_mcpdm_remove(struct platform_device *pdev); | ||
diff --git a/sound/soc/omap/n810.c b/sound/soc/omap/n810.c index 08e09d72790f..a3b6d897ad84 100644 --- a/sound/soc/omap/n810.c +++ b/sound/soc/omap/n810.c | |||
@@ -97,7 +97,7 @@ static int n810_startup(struct snd_pcm_substream *substream) | |||
97 | { | 97 | { |
98 | struct snd_pcm_runtime *runtime = substream->runtime; | 98 | struct snd_pcm_runtime *runtime = substream->runtime; |
99 | struct snd_soc_pcm_runtime *rtd = substream->private_data; | 99 | struct snd_soc_pcm_runtime *rtd = substream->private_data; |
100 | struct snd_soc_codec *codec = rtd->socdev->card->codec; | 100 | struct snd_soc_codec *codec = rtd->codec; |
101 | 101 | ||
102 | snd_pcm_hw_constraint_minmax(runtime, | 102 | snd_pcm_hw_constraint_minmax(runtime, |
103 | SNDRV_PCM_HW_PARAM_CHANNELS, 2, 2); | 103 | SNDRV_PCM_HW_PARAM_CHANNELS, 2, 2); |
@@ -115,8 +115,8 @@ static int n810_hw_params(struct snd_pcm_substream *substream, | |||
115 | struct snd_pcm_hw_params *params) | 115 | struct snd_pcm_hw_params *params) |
116 | { | 116 | { |
117 | struct snd_soc_pcm_runtime *rtd = substream->private_data; | 117 | struct snd_soc_pcm_runtime *rtd = substream->private_data; |
118 | struct snd_soc_dai *codec_dai = rtd->dai->codec_dai; | 118 | struct snd_soc_dai *codec_dai = rtd->codec_dai; |
119 | struct snd_soc_dai *cpu_dai = rtd->dai->cpu_dai; | 119 | struct snd_soc_dai *cpu_dai = rtd->cpu_dai; |
120 | int err; | 120 | int err; |
121 | 121 | ||
122 | /* Set codec DAI configuration */ | 122 | /* Set codec DAI configuration */ |
@@ -271,8 +271,9 @@ static const struct snd_kcontrol_new aic33_n810_controls[] = { | |||
271 | n810_get_input, n810_set_input), | 271 | n810_get_input, n810_set_input), |
272 | }; | 272 | }; |
273 | 273 | ||
274 | static int n810_aic33_init(struct snd_soc_codec *codec) | 274 | static int n810_aic33_init(struct snd_soc_pcm_runtime *rtd) |
275 | { | 275 | { |
276 | struct snd_soc_codec *codec = rtd->codec; | ||
276 | int err; | 277 | int err; |
277 | 278 | ||
278 | /* Not connected */ | 279 | /* Not connected */ |
@@ -307,8 +308,10 @@ static int n810_aic33_init(struct snd_soc_codec *codec) | |||
307 | static struct snd_soc_dai_link n810_dai = { | 308 | static struct snd_soc_dai_link n810_dai = { |
308 | .name = "TLV320AIC33", | 309 | .name = "TLV320AIC33", |
309 | .stream_name = "AIC33", | 310 | .stream_name = "AIC33", |
310 | .cpu_dai = &omap_mcbsp_dai[0], | 311 | .cpu_dai_name = "omap-mcbsp-dai.1", |
311 | .codec_dai = &aic3x_dai, | 312 | .platform_name = "omap-pcm-audio", |
313 | .codec_name = "tlv320aic3x-codec.2-0018", | ||
314 | .codec_dai_name = "tlv320aic3x-hifi", | ||
312 | .init = n810_aic33_init, | 315 | .init = n810_aic33_init, |
313 | .ops = &n810_ops, | 316 | .ops = &n810_ops, |
314 | }; | 317 | }; |
@@ -316,33 +319,12 @@ static struct snd_soc_dai_link n810_dai = { | |||
316 | /* Audio machine driver */ | 319 | /* Audio machine driver */ |
317 | static struct snd_soc_card snd_soc_n810 = { | 320 | static struct snd_soc_card snd_soc_n810 = { |
318 | .name = "N810", | 321 | .name = "N810", |
319 | .platform = &omap_soc_platform, | ||
320 | .dai_link = &n810_dai, | 322 | .dai_link = &n810_dai, |
321 | .num_links = 1, | 323 | .num_links = 1, |
322 | }; | 324 | }; |
323 | 325 | ||
324 | /* Audio private data */ | ||
325 | static struct aic3x_setup_data n810_aic33_setup = { | ||
326 | .gpio_func[0] = AIC3X_GPIO1_FUNC_DISABLED, | ||
327 | .gpio_func[1] = AIC3X_GPIO2_FUNC_DIGITAL_MIC_INPUT, | ||
328 | }; | ||
329 | |||
330 | /* Audio subsystem */ | ||
331 | static struct snd_soc_device n810_snd_devdata = { | ||
332 | .card = &snd_soc_n810, | ||
333 | .codec_dev = &soc_codec_dev_aic3x, | ||
334 | .codec_data = &n810_aic33_setup, | ||
335 | }; | ||
336 | |||
337 | static struct platform_device *n810_snd_device; | 326 | static struct platform_device *n810_snd_device; |
338 | 327 | ||
339 | /* temporary i2c device creation until this can be moved into the machine | ||
340 | * support file. | ||
341 | */ | ||
342 | static struct i2c_board_info i2c_device[] = { | ||
343 | { I2C_BOARD_INFO("tlv320aic3x", 0x1b), } | ||
344 | }; | ||
345 | |||
346 | static int __init n810_soc_init(void) | 328 | static int __init n810_soc_init(void) |
347 | { | 329 | { |
348 | int err; | 330 | int err; |
@@ -351,15 +333,11 @@ static int __init n810_soc_init(void) | |||
351 | if (!(machine_is_nokia_n810() || machine_is_nokia_n810_wimax())) | 333 | if (!(machine_is_nokia_n810() || machine_is_nokia_n810_wimax())) |
352 | return -ENODEV; | 334 | return -ENODEV; |
353 | 335 | ||
354 | i2c_register_board_info(1, i2c_device, ARRAY_SIZE(i2c_device)); | ||
355 | |||
356 | n810_snd_device = platform_device_alloc("soc-audio", -1); | 336 | n810_snd_device = platform_device_alloc("soc-audio", -1); |
357 | if (!n810_snd_device) | 337 | if (!n810_snd_device) |
358 | return -ENOMEM; | 338 | return -ENOMEM; |
359 | 339 | ||
360 | platform_set_drvdata(n810_snd_device, &n810_snd_devdata); | 340 | platform_set_drvdata(n810_snd_device, &snd_soc_n810); |
361 | n810_snd_devdata.dev = &n810_snd_device->dev; | ||
362 | *(unsigned int *)n810_dai.cpu_dai->private_data = 1; /* McBSP2 */ | ||
363 | err = platform_device_add(n810_snd_device); | 341 | err = platform_device_add(n810_snd_device); |
364 | if (err) | 342 | if (err) |
365 | goto err1; | 343 | goto err1; |
diff --git a/sound/soc/omap/omap-mcbsp.c b/sound/soc/omap/omap-mcbsp.c index 86f213905e2c..7ba5690118f8 100644 --- a/sound/soc/omap/omap-mcbsp.c +++ b/sound/soc/omap/omap-mcbsp.c | |||
@@ -62,8 +62,6 @@ struct omap_mcbsp_data { | |||
62 | int wlen; | 62 | int wlen; |
63 | }; | 63 | }; |
64 | 64 | ||
65 | #define to_mcbsp(priv) container_of((priv), struct omap_mcbsp_data, bus_id) | ||
66 | |||
67 | static struct omap_mcbsp_data mcbsp_data[NUM_LINKS]; | 65 | static struct omap_mcbsp_data mcbsp_data[NUM_LINKS]; |
68 | 66 | ||
69 | /* | 67 | /* |
@@ -153,13 +151,13 @@ static const unsigned long omap34xx_mcbsp_port[][2] = {}; | |||
153 | static void omap_mcbsp_set_threshold(struct snd_pcm_substream *substream) | 151 | static void omap_mcbsp_set_threshold(struct snd_pcm_substream *substream) |
154 | { | 152 | { |
155 | struct snd_soc_pcm_runtime *rtd = substream->private_data; | 153 | struct snd_soc_pcm_runtime *rtd = substream->private_data; |
156 | struct snd_soc_dai *cpu_dai = rtd->dai->cpu_dai; | 154 | struct snd_soc_dai *cpu_dai = rtd->cpu_dai; |
157 | struct omap_mcbsp_data *mcbsp_data = to_mcbsp(cpu_dai->private_data); | 155 | struct omap_mcbsp_data *mcbsp_data = snd_soc_dai_get_drvdata(cpu_dai); |
158 | struct omap_pcm_dma_data *dma_data; | 156 | struct omap_pcm_dma_data *dma_data; |
159 | int dma_op_mode = omap_mcbsp_get_dma_op_mode(mcbsp_data->bus_id); | 157 | int dma_op_mode = omap_mcbsp_get_dma_op_mode(mcbsp_data->bus_id); |
160 | int words; | 158 | int words; |
161 | 159 | ||
162 | dma_data = snd_soc_dai_get_dma_data(rtd->dai->cpu_dai, substream); | 160 | dma_data = snd_soc_dai_get_dma_data(rtd->cpu_dai, substream); |
163 | 161 | ||
164 | /* TODO: Currently, MODE_ELEMENT == MODE_FRAME */ | 162 | /* TODO: Currently, MODE_ELEMENT == MODE_FRAME */ |
165 | if (dma_op_mode == MCBSP_DMA_MODE_THRESHOLD) | 163 | if (dma_op_mode == MCBSP_DMA_MODE_THRESHOLD) |
@@ -203,11 +201,9 @@ static int omap_mcbsp_hwrule_min_buffersize(struct snd_pcm_hw_params *params, | |||
203 | } | 201 | } |
204 | 202 | ||
205 | static int omap_mcbsp_dai_startup(struct snd_pcm_substream *substream, | 203 | static int omap_mcbsp_dai_startup(struct snd_pcm_substream *substream, |
206 | struct snd_soc_dai *dai) | 204 | struct snd_soc_dai *cpu_dai) |
207 | { | 205 | { |
208 | struct snd_soc_pcm_runtime *rtd = substream->private_data; | 206 | struct omap_mcbsp_data *mcbsp_data = snd_soc_dai_get_drvdata(cpu_dai); |
209 | struct snd_soc_dai *cpu_dai = rtd->dai->cpu_dai; | ||
210 | struct omap_mcbsp_data *mcbsp_data = to_mcbsp(cpu_dai->private_data); | ||
211 | int bus_id = mcbsp_data->bus_id; | 207 | int bus_id = mcbsp_data->bus_id; |
212 | int err = 0; | 208 | int err = 0; |
213 | 209 | ||
@@ -249,11 +245,9 @@ static int omap_mcbsp_dai_startup(struct snd_pcm_substream *substream, | |||
249 | } | 245 | } |
250 | 246 | ||
251 | static void omap_mcbsp_dai_shutdown(struct snd_pcm_substream *substream, | 247 | static void omap_mcbsp_dai_shutdown(struct snd_pcm_substream *substream, |
252 | struct snd_soc_dai *dai) | 248 | struct snd_soc_dai *cpu_dai) |
253 | { | 249 | { |
254 | struct snd_soc_pcm_runtime *rtd = substream->private_data; | 250 | struct omap_mcbsp_data *mcbsp_data = snd_soc_dai_get_drvdata(cpu_dai); |
255 | struct snd_soc_dai *cpu_dai = rtd->dai->cpu_dai; | ||
256 | struct omap_mcbsp_data *mcbsp_data = to_mcbsp(cpu_dai->private_data); | ||
257 | 251 | ||
258 | if (!cpu_dai->active) { | 252 | if (!cpu_dai->active) { |
259 | omap_mcbsp_free(mcbsp_data->bus_id); | 253 | omap_mcbsp_free(mcbsp_data->bus_id); |
@@ -262,11 +256,9 @@ static void omap_mcbsp_dai_shutdown(struct snd_pcm_substream *substream, | |||
262 | } | 256 | } |
263 | 257 | ||
264 | static int omap_mcbsp_dai_trigger(struct snd_pcm_substream *substream, int cmd, | 258 | static int omap_mcbsp_dai_trigger(struct snd_pcm_substream *substream, int cmd, |
265 | struct snd_soc_dai *dai) | 259 | struct snd_soc_dai *cpu_dai) |
266 | { | 260 | { |
267 | struct snd_soc_pcm_runtime *rtd = substream->private_data; | 261 | struct omap_mcbsp_data *mcbsp_data = snd_soc_dai_get_drvdata(cpu_dai); |
268 | struct snd_soc_dai *cpu_dai = rtd->dai->cpu_dai; | ||
269 | struct omap_mcbsp_data *mcbsp_data = to_mcbsp(cpu_dai->private_data); | ||
270 | int err = 0, play = (substream->stream == SNDRV_PCM_STREAM_PLAYBACK); | 262 | int err = 0, play = (substream->stream == SNDRV_PCM_STREAM_PLAYBACK); |
271 | 263 | ||
272 | switch (cmd) { | 264 | switch (cmd) { |
@@ -295,8 +287,8 @@ static snd_pcm_sframes_t omap_mcbsp_dai_delay( | |||
295 | struct snd_soc_dai *dai) | 287 | struct snd_soc_dai *dai) |
296 | { | 288 | { |
297 | struct snd_soc_pcm_runtime *rtd = substream->private_data; | 289 | struct snd_soc_pcm_runtime *rtd = substream->private_data; |
298 | struct snd_soc_dai *cpu_dai = rtd->dai->cpu_dai; | 290 | struct snd_soc_dai *cpu_dai = rtd->cpu_dai; |
299 | struct omap_mcbsp_data *mcbsp_data = to_mcbsp(cpu_dai->private_data); | 291 | struct omap_mcbsp_data *mcbsp_data = snd_soc_dai_get_drvdata(cpu_dai); |
300 | u16 fifo_use; | 292 | u16 fifo_use; |
301 | snd_pcm_sframes_t delay; | 293 | snd_pcm_sframes_t delay; |
302 | 294 | ||
@@ -317,11 +309,9 @@ static snd_pcm_sframes_t omap_mcbsp_dai_delay( | |||
317 | 309 | ||
318 | static int omap_mcbsp_dai_hw_params(struct snd_pcm_substream *substream, | 310 | static int omap_mcbsp_dai_hw_params(struct snd_pcm_substream *substream, |
319 | struct snd_pcm_hw_params *params, | 311 | struct snd_pcm_hw_params *params, |
320 | struct snd_soc_dai *dai) | 312 | struct snd_soc_dai *cpu_dai) |
321 | { | 313 | { |
322 | struct snd_soc_pcm_runtime *rtd = substream->private_data; | 314 | struct omap_mcbsp_data *mcbsp_data = snd_soc_dai_get_drvdata(cpu_dai); |
323 | struct snd_soc_dai *cpu_dai = rtd->dai->cpu_dai; | ||
324 | struct omap_mcbsp_data *mcbsp_data = to_mcbsp(cpu_dai->private_data); | ||
325 | struct omap_mcbsp_reg_cfg *regs = &mcbsp_data->regs; | 315 | struct omap_mcbsp_reg_cfg *regs = &mcbsp_data->regs; |
326 | struct omap_pcm_dma_data *dma_data; | 316 | struct omap_pcm_dma_data *dma_data; |
327 | int dma, bus_id = mcbsp_data->bus_id; | 317 | int dma, bus_id = mcbsp_data->bus_id; |
@@ -496,7 +486,7 @@ static int omap_mcbsp_dai_hw_params(struct snd_pcm_substream *substream, | |||
496 | static int omap_mcbsp_dai_set_dai_fmt(struct snd_soc_dai *cpu_dai, | 486 | static int omap_mcbsp_dai_set_dai_fmt(struct snd_soc_dai *cpu_dai, |
497 | unsigned int fmt) | 487 | unsigned int fmt) |
498 | { | 488 | { |
499 | struct omap_mcbsp_data *mcbsp_data = to_mcbsp(cpu_dai->private_data); | 489 | struct omap_mcbsp_data *mcbsp_data = snd_soc_dai_get_drvdata(cpu_dai); |
500 | struct omap_mcbsp_reg_cfg *regs = &mcbsp_data->regs; | 490 | struct omap_mcbsp_reg_cfg *regs = &mcbsp_data->regs; |
501 | unsigned int temp_fmt = fmt; | 491 | unsigned int temp_fmt = fmt; |
502 | 492 | ||
@@ -596,7 +586,7 @@ static int omap_mcbsp_dai_set_dai_fmt(struct snd_soc_dai *cpu_dai, | |||
596 | static int omap_mcbsp_dai_set_clkdiv(struct snd_soc_dai *cpu_dai, | 586 | static int omap_mcbsp_dai_set_clkdiv(struct snd_soc_dai *cpu_dai, |
597 | int div_id, int div) | 587 | int div_id, int div) |
598 | { | 588 | { |
599 | struct omap_mcbsp_data *mcbsp_data = to_mcbsp(cpu_dai->private_data); | 589 | struct omap_mcbsp_data *mcbsp_data = snd_soc_dai_get_drvdata(cpu_dai); |
600 | struct omap_mcbsp_reg_cfg *regs = &mcbsp_data->regs; | 590 | struct omap_mcbsp_reg_cfg *regs = &mcbsp_data->regs; |
601 | 591 | ||
602 | if (div_id != OMAP_MCBSP_CLKGDV) | 592 | if (div_id != OMAP_MCBSP_CLKGDV) |
@@ -699,7 +689,7 @@ static int omap_mcbsp_dai_set_dai_sysclk(struct snd_soc_dai *cpu_dai, | |||
699 | int clk_id, unsigned int freq, | 689 | int clk_id, unsigned int freq, |
700 | int dir) | 690 | int dir) |
701 | { | 691 | { |
702 | struct omap_mcbsp_data *mcbsp_data = to_mcbsp(cpu_dai->private_data); | 692 | struct omap_mcbsp_data *mcbsp_data = snd_soc_dai_get_drvdata(cpu_dai); |
703 | struct omap_mcbsp_reg_cfg *regs = &mcbsp_data->regs; | 693 | struct omap_mcbsp_reg_cfg *regs = &mcbsp_data->regs; |
704 | int err = 0; | 694 | int err = 0; |
705 | 695 | ||
@@ -733,7 +723,7 @@ static int omap_mcbsp_dai_set_dai_sysclk(struct snd_soc_dai *cpu_dai, | |||
733 | return err; | 723 | return err; |
734 | } | 724 | } |
735 | 725 | ||
736 | static struct snd_soc_dai_ops omap_mcbsp_dai_ops = { | 726 | static struct snd_soc_dai_ops mcbsp_dai_ops = { |
737 | .startup = omap_mcbsp_dai_startup, | 727 | .startup = omap_mcbsp_dai_startup, |
738 | .shutdown = omap_mcbsp_dai_shutdown, | 728 | .shutdown = omap_mcbsp_dai_shutdown, |
739 | .trigger = omap_mcbsp_dai_trigger, | 729 | .trigger = omap_mcbsp_dai_trigger, |
@@ -744,42 +734,31 @@ static struct snd_soc_dai_ops omap_mcbsp_dai_ops = { | |||
744 | .set_sysclk = omap_mcbsp_dai_set_dai_sysclk, | 734 | .set_sysclk = omap_mcbsp_dai_set_dai_sysclk, |
745 | }; | 735 | }; |
746 | 736 | ||
747 | #define OMAP_MCBSP_DAI_BUILDER(link_id) \ | 737 | static int mcbsp_dai_probe(struct snd_soc_dai *dai) |
748 | { \ | 738 | { |
749 | .name = "omap-mcbsp-dai-"#link_id, \ | 739 | mcbsp_data[dai->id].bus_id = dai->id; |
750 | .id = (link_id), \ | 740 | snd_soc_dai_set_drvdata(dai, &mcbsp_data[dai->id].bus_id); |
751 | .playback = { \ | 741 | return 0; |
752 | .channels_min = 1, \ | ||
753 | .channels_max = 16, \ | ||
754 | .rates = OMAP_MCBSP_RATES, \ | ||
755 | .formats = SNDRV_PCM_FMTBIT_S16_LE | \ | ||
756 | SNDRV_PCM_FMTBIT_S32_LE, \ | ||
757 | }, \ | ||
758 | .capture = { \ | ||
759 | .channels_min = 1, \ | ||
760 | .channels_max = 16, \ | ||
761 | .rates = OMAP_MCBSP_RATES, \ | ||
762 | .formats = SNDRV_PCM_FMTBIT_S16_LE | \ | ||
763 | SNDRV_PCM_FMTBIT_S32_LE, \ | ||
764 | }, \ | ||
765 | .ops = &omap_mcbsp_dai_ops, \ | ||
766 | .private_data = &mcbsp_data[(link_id)].bus_id, \ | ||
767 | } | 742 | } |
768 | 743 | ||
769 | struct snd_soc_dai omap_mcbsp_dai[] = { | 744 | static struct snd_soc_dai_driver omap_mcbsp_dai = |
770 | OMAP_MCBSP_DAI_BUILDER(0), | 745 | { |
771 | OMAP_MCBSP_DAI_BUILDER(1), | 746 | .probe = mcbsp_dai_probe, |
772 | #if NUM_LINKS >= 3 | 747 | .playback = { |
773 | OMAP_MCBSP_DAI_BUILDER(2), | 748 | .channels_min = 1, |
774 | #endif | 749 | .channels_max = 16, |
775 | #if NUM_LINKS == 5 | 750 | .rates = OMAP_MCBSP_RATES, |
776 | OMAP_MCBSP_DAI_BUILDER(3), | 751 | .formats = SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S32_LE, |
777 | OMAP_MCBSP_DAI_BUILDER(4), | 752 | }, |
778 | #endif | 753 | .capture = { |
754 | .channels_min = 1, | ||
755 | .channels_max = 16, | ||
756 | .rates = OMAP_MCBSP_RATES, | ||
757 | .formats = SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S32_LE, | ||
758 | }, | ||
759 | .ops = &mcbsp_dai_ops, | ||
779 | }; | 760 | }; |
780 | 761 | ||
781 | EXPORT_SYMBOL_GPL(omap_mcbsp_dai); | ||
782 | |||
783 | int omap_mcbsp_st_info_volsw(struct snd_kcontrol *kcontrol, | 762 | int omap_mcbsp_st_info_volsw(struct snd_kcontrol *kcontrol, |
784 | struct snd_ctl_elem_info *uinfo) | 763 | struct snd_ctl_elem_info *uinfo) |
785 | { | 764 | { |
@@ -910,16 +889,36 @@ int omap_mcbsp_st_add_controls(struct snd_soc_codec *codec, int mcbsp_id) | |||
910 | } | 889 | } |
911 | EXPORT_SYMBOL_GPL(omap_mcbsp_st_add_controls); | 890 | EXPORT_SYMBOL_GPL(omap_mcbsp_st_add_controls); |
912 | 891 | ||
892 | static __devinit int asoc_mcbsp_probe(struct platform_device *pdev) | ||
893 | { | ||
894 | return snd_soc_register_dai(&pdev->dev, &omap_mcbsp_dai); | ||
895 | } | ||
896 | |||
897 | static int __devexit asoc_mcbsp_remove(struct platform_device *pdev) | ||
898 | { | ||
899 | snd_soc_unregister_dai(&pdev->dev); | ||
900 | return 0; | ||
901 | } | ||
902 | |||
903 | static struct platform_driver asoc_mcbsp_driver = { | ||
904 | .driver = { | ||
905 | .name = "omap-mcbsp-dai", | ||
906 | .owner = THIS_MODULE, | ||
907 | }, | ||
908 | |||
909 | .probe = asoc_mcbsp_probe, | ||
910 | .remove = __devexit_p(asoc_mcbsp_remove), | ||
911 | }; | ||
912 | |||
913 | static int __init snd_omap_mcbsp_init(void) | 913 | static int __init snd_omap_mcbsp_init(void) |
914 | { | 914 | { |
915 | return snd_soc_register_dais(omap_mcbsp_dai, | 915 | return platform_driver_register(&asoc_mcbsp_driver); |
916 | ARRAY_SIZE(omap_mcbsp_dai)); | ||
917 | } | 916 | } |
918 | module_init(snd_omap_mcbsp_init); | 917 | module_init(snd_omap_mcbsp_init); |
919 | 918 | ||
920 | static void __exit snd_omap_mcbsp_exit(void) | 919 | static void __exit snd_omap_mcbsp_exit(void) |
921 | { | 920 | { |
922 | snd_soc_unregister_dais(omap_mcbsp_dai, ARRAY_SIZE(omap_mcbsp_dai)); | 921 | platform_driver_unregister(&asoc_mcbsp_driver); |
923 | } | 922 | } |
924 | module_exit(snd_omap_mcbsp_exit); | 923 | module_exit(snd_omap_mcbsp_exit); |
925 | 924 | ||
diff --git a/sound/soc/omap/omap-mcbsp.h b/sound/soc/omap/omap-mcbsp.h index 6c363e5f4387..ffdcc5abb7b9 100644 --- a/sound/soc/omap/omap-mcbsp.h +++ b/sound/soc/omap/omap-mcbsp.h | |||
@@ -55,8 +55,6 @@ enum omap_mcbsp_div { | |||
55 | #define NUM_LINKS 5 | 55 | #define NUM_LINKS 5 |
56 | #endif | 56 | #endif |
57 | 57 | ||
58 | extern struct snd_soc_dai omap_mcbsp_dai[NUM_LINKS]; | ||
59 | |||
60 | int omap_mcbsp_st_add_controls(struct snd_soc_codec *codec, int mcbsp_id); | 58 | int omap_mcbsp_st_add_controls(struct snd_soc_codec *codec, int mcbsp_id); |
61 | 59 | ||
62 | #endif | 60 | #endif |
diff --git a/sound/soc/omap/omap-mcpdm.c b/sound/soc/omap/omap-mcpdm.c index b7f4f7e015f3..f161c2f5ed36 100644 --- a/sound/soc/omap/omap-mcpdm.c +++ b/sound/soc/omap/omap-mcpdm.c | |||
@@ -36,7 +36,6 @@ | |||
36 | #include <plat/dma.h> | 36 | #include <plat/dma.h> |
37 | #include <plat/mcbsp.h> | 37 | #include <plat/mcbsp.h> |
38 | #include "mcpdm.h" | 38 | #include "mcpdm.h" |
39 | #include "omap-mcpdm.h" | ||
40 | #include "omap-pcm.h" | 39 | #include "omap-pcm.h" |
41 | 40 | ||
42 | struct omap_mcpdm_data { | 41 | struct omap_mcpdm_data { |
@@ -89,11 +88,9 @@ static struct omap_pcm_dma_data omap_mcpdm_dai_dma_params[] = { | |||
89 | static int omap_mcpdm_dai_startup(struct snd_pcm_substream *substream, | 88 | static int omap_mcpdm_dai_startup(struct snd_pcm_substream *substream, |
90 | struct snd_soc_dai *dai) | 89 | struct snd_soc_dai *dai) |
91 | { | 90 | { |
92 | struct snd_soc_pcm_runtime *rtd = substream->private_data; | ||
93 | struct snd_soc_dai *cpu_dai = rtd->dai->cpu_dai; | ||
94 | int err = 0; | 91 | int err = 0; |
95 | 92 | ||
96 | if (!cpu_dai->active) | 93 | if (!dai->active) |
97 | err = omap_mcpdm_request(); | 94 | err = omap_mcpdm_request(); |
98 | 95 | ||
99 | return err; | 96 | return err; |
@@ -102,19 +99,14 @@ static int omap_mcpdm_dai_startup(struct snd_pcm_substream *substream, | |||
102 | static void omap_mcpdm_dai_shutdown(struct snd_pcm_substream *substream, | 99 | static void omap_mcpdm_dai_shutdown(struct snd_pcm_substream *substream, |
103 | struct snd_soc_dai *dai) | 100 | struct snd_soc_dai *dai) |
104 | { | 101 | { |
105 | struct snd_soc_pcm_runtime *rtd = substream->private_data; | 102 | if (!dai->active) |
106 | struct snd_soc_dai *cpu_dai = rtd->dai->cpu_dai; | ||
107 | |||
108 | if (!cpu_dai->active) | ||
109 | omap_mcpdm_free(); | 103 | omap_mcpdm_free(); |
110 | } | 104 | } |
111 | 105 | ||
112 | static int omap_mcpdm_dai_trigger(struct snd_pcm_substream *substream, int cmd, | 106 | static int omap_mcpdm_dai_trigger(struct snd_pcm_substream *substream, int cmd, |
113 | struct snd_soc_dai *dai) | 107 | struct snd_soc_dai *dai) |
114 | { | 108 | { |
115 | struct snd_soc_pcm_runtime *rtd = substream->private_data; | 109 | struct omap_mcpdm_data *mcpdm_priv = snd_soc_dai_get_drvdata(dai); |
116 | struct snd_soc_dai *cpu_dai = rtd->dai->cpu_dai; | ||
117 | struct omap_mcpdm_data *mcpdm_priv = cpu_dai->private_data; | ||
118 | int stream = substream->stream; | 110 | int stream = substream->stream; |
119 | int err = 0; | 111 | int err = 0; |
120 | 112 | ||
@@ -143,14 +135,12 @@ static int omap_mcpdm_dai_hw_params(struct snd_pcm_substream *substream, | |||
143 | struct snd_pcm_hw_params *params, | 135 | struct snd_pcm_hw_params *params, |
144 | struct snd_soc_dai *dai) | 136 | struct snd_soc_dai *dai) |
145 | { | 137 | { |
146 | struct snd_soc_pcm_runtime *rtd = substream->private_data; | 138 | struct omap_mcpdm_data *mcpdm_priv = snd_soc_dai_get_drvdata(dai); |
147 | struct snd_soc_dai *cpu_dai = rtd->dai->cpu_dai; | ||
148 | struct omap_mcpdm_data *mcpdm_priv = cpu_dai->private_data; | ||
149 | struct omap_mcpdm_link *mcpdm_links = mcpdm_priv->links; | 139 | struct omap_mcpdm_link *mcpdm_links = mcpdm_priv->links; |
150 | int stream = substream->stream; | 140 | int stream = substream->stream; |
151 | int channels, err, link_mask = 0; | 141 | int channels, err, link_mask = 0; |
152 | 142 | ||
153 | snd_soc_dai_set_dma_data(cpu_dai, substream, | 143 | snd_soc_dai_set_dma_data(dai, substream, |
154 | &omap_mcpdm_dai_dma_params[stream]); | 144 | &omap_mcpdm_dai_dma_params[stream]); |
155 | 145 | ||
156 | channels = params_channels(params); | 146 | channels = params_channels(params); |
@@ -189,9 +179,7 @@ static int omap_mcpdm_dai_hw_params(struct snd_pcm_substream *substream, | |||
189 | static int omap_mcpdm_dai_hw_free(struct snd_pcm_substream *substream, | 179 | static int omap_mcpdm_dai_hw_free(struct snd_pcm_substream *substream, |
190 | struct snd_soc_dai *dai) | 180 | struct snd_soc_dai *dai) |
191 | { | 181 | { |
192 | struct snd_soc_pcm_runtime *rtd = substream->private_data; | 182 | struct omap_mcpdm_data *mcpdm_priv = snd_soc_dai_get_drvdata(dai); |
193 | struct snd_soc_dai *cpu_dai = rtd->dai->cpu_dai; | ||
194 | struct omap_mcpdm_data *mcpdm_priv = cpu_dai->private_data; | ||
195 | struct omap_mcpdm_link *mcpdm_links = mcpdm_priv->links; | 183 | struct omap_mcpdm_link *mcpdm_links = mcpdm_priv->links; |
196 | int stream = substream->stream; | 184 | int stream = substream->stream; |
197 | int err; | 185 | int err; |
@@ -215,9 +203,14 @@ static struct snd_soc_dai_ops omap_mcpdm_dai_ops = { | |||
215 | #define OMAP_MCPDM_RATES (SNDRV_PCM_RATE_88200 | SNDRV_PCM_RATE_96000) | 203 | #define OMAP_MCPDM_RATES (SNDRV_PCM_RATE_88200 | SNDRV_PCM_RATE_96000) |
216 | #define OMAP_MCPDM_FORMATS (SNDRV_PCM_FMTBIT_S32_LE) | 204 | #define OMAP_MCPDM_FORMATS (SNDRV_PCM_FMTBIT_S32_LE) |
217 | 205 | ||
218 | struct snd_soc_dai omap_mcpdm_dai = { | 206 | static int omap_mcpdm_dai_probe(struct snd_soc_dai *dai) |
219 | .name = "omap-mcpdm", | 207 | { |
220 | .id = -1, | 208 | snd_soc_dai_set_drvdata(dai, &mcpdm_data); |
209 | return 0; | ||
210 | } | ||
211 | |||
212 | static struct snd_soc_dai_driver omap_mcpdm_dai = { | ||
213 | .probe = omap_mcpdm_dai_probe, | ||
221 | .playback = { | 214 | .playback = { |
222 | .channels_min = 1, | 215 | .channels_min = 1, |
223 | .channels_max = 4, | 216 | .channels_max = 4, |
@@ -231,19 +224,47 @@ struct snd_soc_dai omap_mcpdm_dai = { | |||
231 | .formats = OMAP_MCPDM_FORMATS, | 224 | .formats = OMAP_MCPDM_FORMATS, |
232 | }, | 225 | }, |
233 | .ops = &omap_mcpdm_dai_ops, | 226 | .ops = &omap_mcpdm_dai_ops, |
234 | .private_data = &mcpdm_data, | ||
235 | }; | 227 | }; |
236 | EXPORT_SYMBOL_GPL(omap_mcpdm_dai); | 228 | |
229 | static __devinit int asoc_mcpdm_probe(struct platform_device *pdev) | ||
230 | { | ||
231 | int ret; | ||
232 | |||
233 | ret = omap_mcpdm_probe(pdev); | ||
234 | if (ret < 0) | ||
235 | return ret; | ||
236 | ret = snd_soc_register_dai(&pdev->dev, &omap_mcpdm_dai); | ||
237 | if (ret < 0) | ||
238 | omap_mcpdm_remove(pdev); | ||
239 | return ret; | ||
240 | } | ||
241 | |||
242 | static int __devexit asoc_mcpdm_remove(struct platform_device *pdev) | ||
243 | { | ||
244 | snd_soc_unregister_dai(&pdev->dev); | ||
245 | omap_mcpdm_remove(pdev); | ||
246 | return 0; | ||
247 | } | ||
248 | |||
249 | static struct platform_driver asoc_mcpdm_driver = { | ||
250 | .driver = { | ||
251 | .name = "omap-mcpdm-dai", | ||
252 | .owner = THIS_MODULE, | ||
253 | }, | ||
254 | |||
255 | .probe = asoc_mcpdm_probe, | ||
256 | .remove = __devexit_p(asoc_mcpdm_remove), | ||
257 | }; | ||
237 | 258 | ||
238 | static int __init snd_omap_mcpdm_init(void) | 259 | static int __init snd_omap_mcpdm_init(void) |
239 | { | 260 | { |
240 | return snd_soc_register_dai(&omap_mcpdm_dai); | 261 | return platform_driver_register(&asoc_mcpdm_driver); |
241 | } | 262 | } |
242 | module_init(snd_omap_mcpdm_init); | 263 | module_init(snd_omap_mcpdm_init); |
243 | 264 | ||
244 | static void __exit snd_omap_mcpdm_exit(void) | 265 | static void __exit snd_omap_mcpdm_exit(void) |
245 | { | 266 | { |
246 | snd_soc_unregister_dai(&omap_mcpdm_dai); | 267 | platform_driver_unregister(&asoc_mcpdm_driver); |
247 | } | 268 | } |
248 | module_exit(snd_omap_mcpdm_exit); | 269 | module_exit(snd_omap_mcpdm_exit); |
249 | 270 | ||
diff --git a/sound/soc/omap/omap-mcpdm.h b/sound/soc/omap/omap-mcpdm.h deleted file mode 100644 index 73b80d559345..000000000000 --- a/sound/soc/omap/omap-mcpdm.h +++ /dev/null | |||
@@ -1,29 +0,0 @@ | |||
1 | /* | ||
2 | * omap-mcpdm.h | ||
3 | * | ||
4 | * Copyright (C) 2009 Texas Instruments | ||
5 | * | ||
6 | * Contact: Misael Lopez Cruz <x0052729@ti.com> | ||
7 | * | ||
8 | * This program is free software; you can redistribute it and/or | ||
9 | * modify it under the terms of the GNU General Public License | ||
10 | * version 2 as published by the Free Software Foundation. | ||
11 | * | ||
12 | * This program is distributed in the hope that it will be useful, but | ||
13 | * WITHOUT ANY WARRANTY; without even the implied warranty of | ||
14 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | ||
15 | * General Public License for more details. | ||
16 | * | ||
17 | * You should have received a copy of the GNU General Public License | ||
18 | * along with this program; if not, write to the Free Software | ||
19 | * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA | ||
20 | * 02110-1301 USA | ||
21 | * | ||
22 | */ | ||
23 | |||
24 | #ifndef __OMAP_MCPDM_H__ | ||
25 | #define __OMAP_MCPDM_H__ | ||
26 | |||
27 | extern struct snd_soc_dai omap_mcpdm_dai; | ||
28 | |||
29 | #endif /* End of __OMAP_MCPDM_H__ */ | ||
diff --git a/sound/soc/omap/omap-pcm.c b/sound/soc/omap/omap-pcm.c index 1e521904ea64..8caeb8d305c3 100644 --- a/sound/soc/omap/omap-pcm.c +++ b/sound/soc/omap/omap-pcm.c | |||
@@ -101,9 +101,10 @@ static int omap_pcm_hw_params(struct snd_pcm_substream *substream, | |||
101 | struct snd_soc_pcm_runtime *rtd = substream->private_data; | 101 | struct snd_soc_pcm_runtime *rtd = substream->private_data; |
102 | struct omap_runtime_data *prtd = runtime->private_data; | 102 | struct omap_runtime_data *prtd = runtime->private_data; |
103 | struct omap_pcm_dma_data *dma_data; | 103 | struct omap_pcm_dma_data *dma_data; |
104 | |||
104 | int err = 0; | 105 | int err = 0; |
105 | 106 | ||
106 | dma_data = snd_soc_dai_get_dma_data(rtd->dai->cpu_dai, substream); | 107 | dma_data = snd_soc_dai_get_dma_data(rtd->cpu_dai, substream); |
107 | 108 | ||
108 | /* return if this is a bufferless transfer e.g. | 109 | /* return if this is a bufferless transfer e.g. |
109 | * codec <--> BT codec or GSM modem -- lg FIXME */ | 110 | * codec <--> BT codec or GSM modem -- lg FIXME */ |
@@ -374,14 +375,14 @@ static int omap_pcm_new(struct snd_card *card, struct snd_soc_dai *dai, | |||
374 | if (!card->dev->coherent_dma_mask) | 375 | if (!card->dev->coherent_dma_mask) |
375 | card->dev->coherent_dma_mask = DMA_BIT_MASK(64); | 376 | card->dev->coherent_dma_mask = DMA_BIT_MASK(64); |
376 | 377 | ||
377 | if (dai->playback.channels_min) { | 378 | if (dai->driver->playback.channels_min) { |
378 | ret = omap_pcm_preallocate_dma_buffer(pcm, | 379 | ret = omap_pcm_preallocate_dma_buffer(pcm, |
379 | SNDRV_PCM_STREAM_PLAYBACK); | 380 | SNDRV_PCM_STREAM_PLAYBACK); |
380 | if (ret) | 381 | if (ret) |
381 | goto out; | 382 | goto out; |
382 | } | 383 | } |
383 | 384 | ||
384 | if (dai->capture.channels_min) { | 385 | if (dai->driver->capture.channels_min) { |
385 | ret = omap_pcm_preallocate_dma_buffer(pcm, | 386 | ret = omap_pcm_preallocate_dma_buffer(pcm, |
386 | SNDRV_PCM_STREAM_CAPTURE); | 387 | SNDRV_PCM_STREAM_CAPTURE); |
387 | if (ret) | 388 | if (ret) |
@@ -392,25 +393,45 @@ out: | |||
392 | return ret; | 393 | return ret; |
393 | } | 394 | } |
394 | 395 | ||
395 | struct snd_soc_platform omap_soc_platform = { | 396 | static struct snd_soc_platform_driver omap_soc_platform = { |
396 | .name = "omap-pcm-audio", | 397 | .ops = &omap_pcm_ops, |
397 | .pcm_ops = &omap_pcm_ops, | ||
398 | .pcm_new = omap_pcm_new, | 398 | .pcm_new = omap_pcm_new, |
399 | .pcm_free = omap_pcm_free_dma_buffers, | 399 | .pcm_free = omap_pcm_free_dma_buffers, |
400 | }; | 400 | }; |
401 | EXPORT_SYMBOL_GPL(omap_soc_platform); | ||
402 | 401 | ||
403 | static int __init omap_soc_platform_init(void) | 402 | static __devinit int omap_pcm_probe(struct platform_device *pdev) |
403 | { | ||
404 | return snd_soc_register_platform(&pdev->dev, | ||
405 | &omap_soc_platform); | ||
406 | } | ||
407 | |||
408 | static int __devexit omap_pcm_remove(struct platform_device *pdev) | ||
409 | { | ||
410 | snd_soc_unregister_platform(&pdev->dev); | ||
411 | return 0; | ||
412 | } | ||
413 | |||
414 | static struct platform_driver omap_pcm_driver = { | ||
415 | .driver = { | ||
416 | .name = "omap-pcm-audio", | ||
417 | .owner = THIS_MODULE, | ||
418 | }, | ||
419 | |||
420 | .probe = omap_pcm_probe, | ||
421 | .remove = __devexit_p(omap_pcm_remove), | ||
422 | }; | ||
423 | |||
424 | static int __init snd_omap_pcm_init(void) | ||
404 | { | 425 | { |
405 | return snd_soc_register_platform(&omap_soc_platform); | 426 | return platform_driver_register(&omap_pcm_driver); |
406 | } | 427 | } |
407 | module_init(omap_soc_platform_init); | 428 | module_init(snd_omap_pcm_init); |
408 | 429 | ||
409 | static void __exit omap_soc_platform_exit(void) | 430 | static void __exit snd_omap_pcm_exit(void) |
410 | { | 431 | { |
411 | snd_soc_unregister_platform(&omap_soc_platform); | 432 | platform_driver_unregister(&omap_pcm_driver); |
412 | } | 433 | } |
413 | module_exit(omap_soc_platform_exit); | 434 | module_exit(snd_omap_pcm_exit); |
414 | 435 | ||
415 | MODULE_AUTHOR("Jarkko Nikula <jhnikula@gmail.com>"); | 436 | MODULE_AUTHOR("Jarkko Nikula <jhnikula@gmail.com>"); |
416 | MODULE_DESCRIPTION("OMAP PCM DMA module"); | 437 | MODULE_DESCRIPTION("OMAP PCM DMA module"); |
diff --git a/sound/soc/omap/omap-pcm.h b/sound/soc/omap/omap-pcm.h index b19975d26907..fea0515331fb 100644 --- a/sound/soc/omap/omap-pcm.h +++ b/sound/soc/omap/omap-pcm.h | |||
@@ -35,6 +35,4 @@ struct omap_pcm_dma_data { | |||
35 | int packet_size; /* packet size only in PACKET mode */ | 35 | int packet_size; /* packet size only in PACKET mode */ |
36 | }; | 36 | }; |
37 | 37 | ||
38 | extern struct snd_soc_platform omap_soc_platform; | ||
39 | |||
40 | #endif | 38 | #endif |
diff --git a/sound/soc/omap/omap2evm.c b/sound/soc/omap/omap2evm.c index c7adea38274c..38cd1894623e 100644 --- a/sound/soc/omap/omap2evm.c +++ b/sound/soc/omap/omap2evm.c | |||
@@ -35,15 +35,13 @@ | |||
35 | 35 | ||
36 | #include "omap-mcbsp.h" | 36 | #include "omap-mcbsp.h" |
37 | #include "omap-pcm.h" | 37 | #include "omap-pcm.h" |
38 | #include "../codecs/twl4030.h" | ||
39 | 38 | ||
40 | static int omap2evm_hw_params(struct snd_pcm_substream *substream, | 39 | static int omap2evm_hw_params(struct snd_pcm_substream *substream, |
41 | struct snd_pcm_hw_params *params, | 40 | struct snd_pcm_hw_params *params) |
42 | struct snd_soc_dai *dai) | ||
43 | { | 41 | { |
44 | struct snd_soc_pcm_runtime *rtd = substream->private_data; | 42 | struct snd_soc_pcm_runtime *rtd = substream->private_data; |
45 | struct snd_soc_dai *codec_dai = rtd->dai->codec_dai; | 43 | struct snd_soc_dai *codec_dai = rtd->codec_dai; |
46 | struct snd_soc_dai *cpu_dai = rtd->dai->cpu_dai; | 44 | struct snd_soc_dai *cpu_dai = rtd->cpu_dai; |
47 | int ret; | 45 | int ret; |
48 | 46 | ||
49 | /* Set codec DAI configuration */ | 47 | /* Set codec DAI configuration */ |
@@ -85,25 +83,20 @@ static struct snd_soc_ops omap2evm_ops = { | |||
85 | static struct snd_soc_dai_link omap2evm_dai = { | 83 | static struct snd_soc_dai_link omap2evm_dai = { |
86 | .name = "TWL4030", | 84 | .name = "TWL4030", |
87 | .stream_name = "TWL4030", | 85 | .stream_name = "TWL4030", |
88 | .cpu_dai = &omap_mcbsp_dai[0], | 86 | .cpu_dai_name = "omap-mcbsp-dai.1", |
89 | .codec_dai = &twl4030_dai[TWL4030_DAI_HIFI], | 87 | .codec_dai_name = "twl4030-hifi", |
88 | .platform_name = "omap-pcm-audio", | ||
89 | .codec_name = "twl4030-codec", | ||
90 | .ops = &omap2evm_ops, | 90 | .ops = &omap2evm_ops, |
91 | }; | 91 | }; |
92 | 92 | ||
93 | /* Audio machine driver */ | 93 | /* Audio machine driver */ |
94 | static struct snd_soc_card snd_soc_omap2evm = { | 94 | static struct snd_soc_card snd_soc_omap2evm = { |
95 | .name = "omap2evm", | 95 | .name = "omap2evm", |
96 | .platform = &omap_soc_platform, | ||
97 | .dai_link = &omap2evm_dai, | 96 | .dai_link = &omap2evm_dai, |
98 | .num_links = 1, | 97 | .num_links = 1, |
99 | }; | 98 | }; |
100 | 99 | ||
101 | /* Audio subsystem */ | ||
102 | static struct snd_soc_device omap2evm_snd_devdata = { | ||
103 | .card = &snd_soc_omap2evm, | ||
104 | .codec_dev = &soc_codec_dev_twl4030, | ||
105 | }; | ||
106 | |||
107 | static struct platform_device *omap2evm_snd_device; | 100 | static struct platform_device *omap2evm_snd_device; |
108 | 101 | ||
109 | static int __init omap2evm_soc_init(void) | 102 | static int __init omap2evm_soc_init(void) |
@@ -122,9 +115,7 @@ static int __init omap2evm_soc_init(void) | |||
122 | return -ENOMEM; | 115 | return -ENOMEM; |
123 | } | 116 | } |
124 | 117 | ||
125 | platform_set_drvdata(omap2evm_snd_device, &omap2evm_snd_devdata); | 118 | platform_set_drvdata(omap2evm_snd_device, &snd_soc_omap2evm); |
126 | omap2evm_snd_devdata.dev = &omap2evm_snd_device->dev; | ||
127 | *(unsigned int *)omap2evm_dai.cpu_dai->private_data = 1; /* McBSP2 */ | ||
128 | 119 | ||
129 | ret = platform_device_add(omap2evm_snd_device); | 120 | ret = platform_device_add(omap2evm_snd_device); |
130 | if (ret) | 121 | if (ret) |
diff --git a/sound/soc/omap/omap3beagle.c b/sound/soc/omap/omap3beagle.c index 240e0975dd6a..7c11e1afe9e6 100644 --- a/sound/soc/omap/omap3beagle.c +++ b/sound/soc/omap/omap3beagle.c | |||
@@ -33,14 +33,13 @@ | |||
33 | 33 | ||
34 | #include "omap-mcbsp.h" | 34 | #include "omap-mcbsp.h" |
35 | #include "omap-pcm.h" | 35 | #include "omap-pcm.h" |
36 | #include "../codecs/twl4030.h" | ||
37 | 36 | ||
38 | static int omap3beagle_hw_params(struct snd_pcm_substream *substream, | 37 | static int omap3beagle_hw_params(struct snd_pcm_substream *substream, |
39 | struct snd_pcm_hw_params *params) | 38 | struct snd_pcm_hw_params *params) |
40 | { | 39 | { |
41 | struct snd_soc_pcm_runtime *rtd = substream->private_data; | 40 | struct snd_soc_pcm_runtime *rtd = substream->private_data; |
42 | struct snd_soc_dai *codec_dai = rtd->dai->codec_dai; | 41 | struct snd_soc_dai *codec_dai = rtd->codec_dai; |
43 | struct snd_soc_dai *cpu_dai = rtd->dai->cpu_dai; | 42 | struct snd_soc_dai *cpu_dai = rtd->cpu_dai; |
44 | unsigned int fmt; | 43 | unsigned int fmt; |
45 | int ret; | 44 | int ret; |
46 | 45 | ||
@@ -92,25 +91,21 @@ static struct snd_soc_ops omap3beagle_ops = { | |||
92 | static struct snd_soc_dai_link omap3beagle_dai = { | 91 | static struct snd_soc_dai_link omap3beagle_dai = { |
93 | .name = "TWL4030", | 92 | .name = "TWL4030", |
94 | .stream_name = "TWL4030", | 93 | .stream_name = "TWL4030", |
95 | .cpu_dai = &omap_mcbsp_dai[0], | 94 | .cpu_dai_name = "omap-mcbsp-dai.1", |
96 | .codec_dai = &twl4030_dai[TWL4030_DAI_HIFI], | 95 | .platform_name = "omap-pcm-audio", |
96 | .codec_dai_name = "twl4030-hifi", | ||
97 | .codec_name = "twl4030-codec", | ||
97 | .ops = &omap3beagle_ops, | 98 | .ops = &omap3beagle_ops, |
98 | }; | 99 | }; |
99 | 100 | ||
100 | /* Audio machine driver */ | 101 | /* Audio machine driver */ |
101 | static struct snd_soc_card snd_soc_omap3beagle = { | 102 | static struct snd_soc_card snd_soc_omap3beagle = { |
102 | .name = "omap3beagle", | 103 | .name = "omap3beagle", |
103 | .platform = &omap_soc_platform, | 104 | .owner = THIS_MODULE, |
104 | .dai_link = &omap3beagle_dai, | 105 | .dai_link = &omap3beagle_dai, |
105 | .num_links = 1, | 106 | .num_links = 1, |
106 | }; | 107 | }; |
107 | 108 | ||
108 | /* Audio subsystem */ | ||
109 | static struct snd_soc_device omap3beagle_snd_devdata = { | ||
110 | .card = &snd_soc_omap3beagle, | ||
111 | .codec_dev = &soc_codec_dev_twl4030, | ||
112 | }; | ||
113 | |||
114 | static struct platform_device *omap3beagle_snd_device; | 109 | static struct platform_device *omap3beagle_snd_device; |
115 | 110 | ||
116 | static int __init omap3beagle_soc_init(void) | 111 | static int __init omap3beagle_soc_init(void) |
@@ -129,9 +124,7 @@ static int __init omap3beagle_soc_init(void) | |||
129 | return -ENOMEM; | 124 | return -ENOMEM; |
130 | } | 125 | } |
131 | 126 | ||
132 | platform_set_drvdata(omap3beagle_snd_device, &omap3beagle_snd_devdata); | 127 | platform_set_drvdata(omap3beagle_snd_device, &snd_soc_omap3beagle); |
133 | omap3beagle_snd_devdata.dev = &omap3beagle_snd_device->dev; | ||
134 | *(unsigned int *)omap3beagle_dai.cpu_dai->private_data = 1; /* McBSP2 */ | ||
135 | 128 | ||
136 | ret = platform_device_add(omap3beagle_snd_device); | 129 | ret = platform_device_add(omap3beagle_snd_device); |
137 | if (ret) | 130 | if (ret) |
diff --git a/sound/soc/omap/omap3evm.c b/sound/soc/omap/omap3evm.c index dfcb344092e4..1ac5babef00d 100644 --- a/sound/soc/omap/omap3evm.c +++ b/sound/soc/omap/omap3evm.c | |||
@@ -31,14 +31,13 @@ | |||
31 | 31 | ||
32 | #include "omap-mcbsp.h" | 32 | #include "omap-mcbsp.h" |
33 | #include "omap-pcm.h" | 33 | #include "omap-pcm.h" |
34 | #include "../codecs/twl4030.h" | ||
35 | 34 | ||
36 | static int omap3evm_hw_params(struct snd_pcm_substream *substream, | 35 | static int omap3evm_hw_params(struct snd_pcm_substream *substream, |
37 | struct snd_pcm_hw_params *params) | 36 | struct snd_pcm_hw_params *params) |
38 | { | 37 | { |
39 | struct snd_soc_pcm_runtime *rtd = substream->private_data; | 38 | struct snd_soc_pcm_runtime *rtd = substream->private_data; |
40 | struct snd_soc_dai *codec_dai = rtd->dai->codec_dai; | 39 | struct snd_soc_dai *codec_dai = rtd->codec_dai; |
41 | struct snd_soc_dai *cpu_dai = rtd->dai->cpu_dai; | 40 | struct snd_soc_dai *cpu_dai = rtd->cpu_dai; |
42 | int ret; | 41 | int ret; |
43 | 42 | ||
44 | /* Set codec DAI configuration */ | 43 | /* Set codec DAI configuration */ |
@@ -80,32 +79,20 @@ static struct snd_soc_ops omap3evm_ops = { | |||
80 | static struct snd_soc_dai_link omap3evm_dai = { | 79 | static struct snd_soc_dai_link omap3evm_dai = { |
81 | .name = "TWL4030", | 80 | .name = "TWL4030", |
82 | .stream_name = "TWL4030", | 81 | .stream_name = "TWL4030", |
83 | .cpu_dai = &omap_mcbsp_dai[0], | 82 | .cpu_dai_name = "omap-mcbsp-dai.1", |
84 | .codec_dai = &twl4030_dai[TWL4030_DAI_HIFI], | 83 | .codec_dai_name = "twl4030-hifi", |
84 | .platform_name = "omap-pcm-audio", | ||
85 | .codec_name = "twl4030-codec", | ||
85 | .ops = &omap3evm_ops, | 86 | .ops = &omap3evm_ops, |
86 | }; | 87 | }; |
87 | 88 | ||
88 | /* Audio machine driver */ | 89 | /* Audio machine driver */ |
89 | static struct snd_soc_card snd_soc_omap3evm = { | 90 | static struct snd_soc_card snd_soc_omap3evm = { |
90 | .name = "omap3evm", | 91 | .name = "omap3evm", |
91 | .platform = &omap_soc_platform, | ||
92 | .dai_link = &omap3evm_dai, | 92 | .dai_link = &omap3evm_dai, |
93 | .num_links = 1, | 93 | .num_links = 1, |
94 | }; | 94 | }; |
95 | 95 | ||
96 | /* twl4030 setup */ | ||
97 | static struct twl4030_setup_data twl4030_setup = { | ||
98 | .ramp_delay_value = 4, | ||
99 | .sysclk = 26000, | ||
100 | }; | ||
101 | |||
102 | /* Audio subsystem */ | ||
103 | static struct snd_soc_device omap3evm_snd_devdata = { | ||
104 | .card = &snd_soc_omap3evm, | ||
105 | .codec_dev = &soc_codec_dev_twl4030, | ||
106 | .codec_data = &twl4030_setup, | ||
107 | }; | ||
108 | |||
109 | static struct platform_device *omap3evm_snd_device; | 96 | static struct platform_device *omap3evm_snd_device; |
110 | 97 | ||
111 | static int __init omap3evm_soc_init(void) | 98 | static int __init omap3evm_soc_init(void) |
@@ -124,10 +111,7 @@ static int __init omap3evm_soc_init(void) | |||
124 | return -ENOMEM; | 111 | return -ENOMEM; |
125 | } | 112 | } |
126 | 113 | ||
127 | platform_set_drvdata(omap3evm_snd_device, &omap3evm_snd_devdata); | 114 | platform_set_drvdata(omap3evm_snd_device, &snd_soc_omap3evm); |
128 | omap3evm_snd_devdata.dev = &omap3evm_snd_device->dev; | ||
129 | *(unsigned int *)omap3evm_dai.cpu_dai->private_data = 1; | ||
130 | |||
131 | ret = platform_device_add(omap3evm_snd_device); | 115 | ret = platform_device_add(omap3evm_snd_device); |
132 | if (ret) | 116 | if (ret) |
133 | goto err1; | 117 | goto err1; |
diff --git a/sound/soc/omap/omap3pandora.c b/sound/soc/omap/omap3pandora.c index 9eecac135bbb..dbd9d96b5f92 100644 --- a/sound/soc/omap/omap3pandora.c +++ b/sound/soc/omap/omap3pandora.c | |||
@@ -31,10 +31,10 @@ | |||
31 | #include <sound/soc-dapm.h> | 31 | #include <sound/soc-dapm.h> |
32 | 32 | ||
33 | #include <asm/mach-types.h> | 33 | #include <asm/mach-types.h> |
34 | #include <plat/mcbsp.h> | ||
34 | 35 | ||
35 | #include "omap-mcbsp.h" | 36 | #include "omap-mcbsp.h" |
36 | #include "omap-pcm.h" | 37 | #include "omap-pcm.h" |
37 | #include "../codecs/twl4030.h" | ||
38 | 38 | ||
39 | #define OMAP3_PANDORA_DAC_POWER_GPIO 118 | 39 | #define OMAP3_PANDORA_DAC_POWER_GPIO 118 |
40 | #define OMAP3_PANDORA_AMP_POWER_GPIO 14 | 40 | #define OMAP3_PANDORA_AMP_POWER_GPIO 14 |
@@ -47,8 +47,8 @@ static int omap3pandora_hw_params(struct snd_pcm_substream *substream, | |||
47 | struct snd_pcm_hw_params *params) | 47 | struct snd_pcm_hw_params *params) |
48 | { | 48 | { |
49 | struct snd_soc_pcm_runtime *rtd = substream->private_data; | 49 | struct snd_soc_pcm_runtime *rtd = substream->private_data; |
50 | struct snd_soc_dai *codec_dai = rtd->dai->codec_dai; | 50 | struct snd_soc_dai *codec_dai = rtd->codec_dai; |
51 | struct snd_soc_dai *cpu_dai = rtd->dai->cpu_dai; | 51 | struct snd_soc_dai *cpu_dai = rtd->cpu_dai; |
52 | int fmt = SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_NB_NF | | 52 | int fmt = SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_NB_NF | |
53 | SND_SOC_DAIFMT_CBS_CFS; | 53 | SND_SOC_DAIFMT_CBS_CFS; |
54 | int ret; | 54 | int ret; |
@@ -167,8 +167,9 @@ static const struct snd_soc_dapm_route omap3pandora_in_map[] = { | |||
167 | {"Mic Bias 2", NULL, "Mic (external)"}, | 167 | {"Mic Bias 2", NULL, "Mic (external)"}, |
168 | }; | 168 | }; |
169 | 169 | ||
170 | static int omap3pandora_out_init(struct snd_soc_codec *codec) | 170 | static int omap3pandora_out_init(struct snd_soc_pcm_runtime *rtd) |
171 | { | 171 | { |
172 | struct snd_soc_codec *codec = rtd->codec; | ||
172 | int ret; | 173 | int ret; |
173 | 174 | ||
174 | /* All TWL4030 output pins are floating */ | 175 | /* All TWL4030 output pins are floating */ |
@@ -194,8 +195,9 @@ static int omap3pandora_out_init(struct snd_soc_codec *codec) | |||
194 | return snd_soc_dapm_sync(codec); | 195 | return snd_soc_dapm_sync(codec); |
195 | } | 196 | } |
196 | 197 | ||
197 | static int omap3pandora_in_init(struct snd_soc_codec *codec) | 198 | static int omap3pandora_in_init(struct snd_soc_pcm_runtime *rtd) |
198 | { | 199 | { |
200 | struct snd_soc_codec *codec = rtd->codec; | ||
199 | int ret; | 201 | int ret; |
200 | 202 | ||
201 | /* Not comnnected */ | 203 | /* Not comnnected */ |
@@ -224,15 +226,19 @@ static struct snd_soc_dai_link omap3pandora_dai[] = { | |||
224 | { | 226 | { |
225 | .name = "PCM1773", | 227 | .name = "PCM1773", |
226 | .stream_name = "HiFi Out", | 228 | .stream_name = "HiFi Out", |
227 | .cpu_dai = &omap_mcbsp_dai[0], | 229 | .cpu_dai_name = "omap-mcbsp-dai.1", |
228 | .codec_dai = &twl4030_dai[TWL4030_DAI_HIFI], | 230 | .codec_dai_name = "twl4030-hifi", |
231 | .platform_name = "omap-pcm-audio", | ||
232 | .codec_name = "twl4030-codec", | ||
229 | .ops = &omap3pandora_ops, | 233 | .ops = &omap3pandora_ops, |
230 | .init = omap3pandora_out_init, | 234 | .init = omap3pandora_out_init, |
231 | }, { | 235 | }, { |
232 | .name = "TWL4030", | 236 | .name = "TWL4030", |
233 | .stream_name = "Line/Mic In", | 237 | .stream_name = "Line/Mic In", |
234 | .cpu_dai = &omap_mcbsp_dai[1], | 238 | .cpu_dai_name = "omap-mcbsp-dai.3", |
235 | .codec_dai = &twl4030_dai[TWL4030_DAI_HIFI], | 239 | .codec_dai_name = "twl4030-hifi", |
240 | .platform_name = "omap-pcm-audio", | ||
241 | .codec_name = "twl4030-codec", | ||
236 | .ops = &omap3pandora_ops, | 242 | .ops = &omap3pandora_ops, |
237 | .init = omap3pandora_in_init, | 243 | .init = omap3pandora_in_init, |
238 | } | 244 | } |
@@ -241,17 +247,10 @@ static struct snd_soc_dai_link omap3pandora_dai[] = { | |||
241 | /* SoC card */ | 247 | /* SoC card */ |
242 | static struct snd_soc_card snd_soc_card_omap3pandora = { | 248 | static struct snd_soc_card snd_soc_card_omap3pandora = { |
243 | .name = "omap3pandora", | 249 | .name = "omap3pandora", |
244 | .platform = &omap_soc_platform, | ||
245 | .dai_link = omap3pandora_dai, | 250 | .dai_link = omap3pandora_dai, |
246 | .num_links = ARRAY_SIZE(omap3pandora_dai), | 251 | .num_links = ARRAY_SIZE(omap3pandora_dai), |
247 | }; | 252 | }; |
248 | 253 | ||
249 | /* Audio subsystem */ | ||
250 | static struct snd_soc_device omap3pandora_snd_data = { | ||
251 | .card = &snd_soc_card_omap3pandora, | ||
252 | .codec_dev = &soc_codec_dev_twl4030, | ||
253 | }; | ||
254 | |||
255 | static struct platform_device *omap3pandora_snd_device; | 254 | static struct platform_device *omap3pandora_snd_device; |
256 | 255 | ||
257 | static int __init omap3pandora_soc_init(void) | 256 | static int __init omap3pandora_soc_init(void) |
@@ -294,10 +293,7 @@ static int __init omap3pandora_soc_init(void) | |||
294 | goto fail1; | 293 | goto fail1; |
295 | } | 294 | } |
296 | 295 | ||
297 | platform_set_drvdata(omap3pandora_snd_device, &omap3pandora_snd_data); | 296 | platform_set_drvdata(omap3pandora_snd_device, &snd_soc_card_omap3pandora); |
298 | omap3pandora_snd_data.dev = &omap3pandora_snd_device->dev; | ||
299 | *(unsigned int *)omap_mcbsp_dai[0].private_data = 1; /* McBSP2 */ | ||
300 | *(unsigned int *)omap_mcbsp_dai[1].private_data = 3; /* McBSP4 */ | ||
301 | 297 | ||
302 | ret = platform_device_add(omap3pandora_snd_device); | 298 | ret = platform_device_add(omap3pandora_snd_device); |
303 | if (ret) { | 299 | if (ret) { |
diff --git a/sound/soc/omap/osk5912.c b/sound/soc/omap/osk5912.c index 498ca2e03519..f0e662556428 100644 --- a/sound/soc/omap/osk5912.c +++ b/sound/soc/omap/osk5912.c | |||
@@ -55,8 +55,8 @@ static int osk_hw_params(struct snd_pcm_substream *substream, | |||
55 | struct snd_pcm_hw_params *params) | 55 | struct snd_pcm_hw_params *params) |
56 | { | 56 | { |
57 | struct snd_soc_pcm_runtime *rtd = substream->private_data; | 57 | struct snd_soc_pcm_runtime *rtd = substream->private_data; |
58 | struct snd_soc_dai *codec_dai = rtd->dai->codec_dai; | 58 | struct snd_soc_dai *codec_dai = rtd->codec_dai; |
59 | struct snd_soc_dai *cpu_dai = rtd->dai->cpu_dai; | 59 | struct snd_soc_dai *cpu_dai = rtd->cpu_dai; |
60 | int err; | 60 | int err; |
61 | 61 | ||
62 | /* Set codec DAI configuration */ | 62 | /* Set codec DAI configuration */ |
@@ -113,8 +113,9 @@ static const struct snd_soc_dapm_route audio_map[] = { | |||
113 | {"MICIN", NULL, "Mic Jack"}, | 113 | {"MICIN", NULL, "Mic Jack"}, |
114 | }; | 114 | }; |
115 | 115 | ||
116 | static int osk_tlv320aic23_init(struct snd_soc_codec *codec) | 116 | static int osk_tlv320aic23_init(struct snd_soc_pcm_runtime *rtd) |
117 | { | 117 | { |
118 | struct snd_soc_codec *codec = rtd->codec; | ||
118 | 119 | ||
119 | /* Add osk5912 specific widgets */ | 120 | /* Add osk5912 specific widgets */ |
120 | snd_soc_dapm_new_controls(codec, tlv320aic23_dapm_widgets, | 121 | snd_soc_dapm_new_controls(codec, tlv320aic23_dapm_widgets, |
@@ -136,8 +137,10 @@ static int osk_tlv320aic23_init(struct snd_soc_codec *codec) | |||
136 | static struct snd_soc_dai_link osk_dai = { | 137 | static struct snd_soc_dai_link osk_dai = { |
137 | .name = "TLV320AIC23", | 138 | .name = "TLV320AIC23", |
138 | .stream_name = "AIC23", | 139 | .stream_name = "AIC23", |
139 | .cpu_dai = &omap_mcbsp_dai[0], | 140 | .cpu_dai_name = "omap-mcbsp-dai.0", |
140 | .codec_dai = &tlv320aic23_dai, | 141 | .codec_dai_name = "tlv320aic23-hifi", |
142 | .platform_name = "omap-pcm-audio", | ||
143 | .codec_name = "tlv320aic23-codec", | ||
141 | .init = osk_tlv320aic23_init, | 144 | .init = osk_tlv320aic23_init, |
142 | .ops = &osk_ops, | 145 | .ops = &osk_ops, |
143 | }; | 146 | }; |
@@ -145,17 +148,10 @@ static struct snd_soc_dai_link osk_dai = { | |||
145 | /* Audio machine driver */ | 148 | /* Audio machine driver */ |
146 | static struct snd_soc_card snd_soc_card_osk = { | 149 | static struct snd_soc_card snd_soc_card_osk = { |
147 | .name = "OSK5912", | 150 | .name = "OSK5912", |
148 | .platform = &omap_soc_platform, | ||
149 | .dai_link = &osk_dai, | 151 | .dai_link = &osk_dai, |
150 | .num_links = 1, | 152 | .num_links = 1, |
151 | }; | 153 | }; |
152 | 154 | ||
153 | /* Audio subsystem */ | ||
154 | static struct snd_soc_device osk_snd_devdata = { | ||
155 | .card = &snd_soc_card_osk, | ||
156 | .codec_dev = &soc_codec_dev_tlv320aic23, | ||
157 | }; | ||
158 | |||
159 | static struct platform_device *osk_snd_device; | 155 | static struct platform_device *osk_snd_device; |
160 | 156 | ||
161 | static int __init osk_soc_init(void) | 157 | static int __init osk_soc_init(void) |
@@ -171,9 +167,7 @@ static int __init osk_soc_init(void) | |||
171 | if (!osk_snd_device) | 167 | if (!osk_snd_device) |
172 | return -ENOMEM; | 168 | return -ENOMEM; |
173 | 169 | ||
174 | platform_set_drvdata(osk_snd_device, &osk_snd_devdata); | 170 | platform_set_drvdata(osk_snd_device, &snd_soc_card_osk); |
175 | osk_snd_devdata.dev = &osk_snd_device->dev; | ||
176 | *(unsigned int *)osk_dai.cpu_dai->private_data = 0; /* McBSP1 */ | ||
177 | err = platform_device_add(osk_snd_device); | 171 | err = platform_device_add(osk_snd_device); |
178 | if (err) | 172 | if (err) |
179 | goto err1; | 173 | goto err1; |
diff --git a/sound/soc/omap/overo.c b/sound/soc/omap/overo.c index c25f5276ad6f..e95a607937de 100644 --- a/sound/soc/omap/overo.c +++ b/sound/soc/omap/overo.c | |||
@@ -33,14 +33,13 @@ | |||
33 | 33 | ||
34 | #include "omap-mcbsp.h" | 34 | #include "omap-mcbsp.h" |
35 | #include "omap-pcm.h" | 35 | #include "omap-pcm.h" |
36 | #include "../codecs/twl4030.h" | ||
37 | 36 | ||
38 | static int overo_hw_params(struct snd_pcm_substream *substream, | 37 | static int overo_hw_params(struct snd_pcm_substream *substream, |
39 | struct snd_pcm_hw_params *params) | 38 | struct snd_pcm_hw_params *params) |
40 | { | 39 | { |
41 | struct snd_soc_pcm_runtime *rtd = substream->private_data; | 40 | struct snd_soc_pcm_runtime *rtd = substream->private_data; |
42 | struct snd_soc_dai *codec_dai = rtd->dai->codec_dai; | 41 | struct snd_soc_dai *codec_dai = rtd->codec_dai; |
43 | struct snd_soc_dai *cpu_dai = rtd->dai->cpu_dai; | 42 | struct snd_soc_dai *cpu_dai = rtd->cpu_dai; |
44 | int ret; | 43 | int ret; |
45 | 44 | ||
46 | /* Set codec DAI configuration */ | 45 | /* Set codec DAI configuration */ |
@@ -82,25 +81,20 @@ static struct snd_soc_ops overo_ops = { | |||
82 | static struct snd_soc_dai_link overo_dai = { | 81 | static struct snd_soc_dai_link overo_dai = { |
83 | .name = "TWL4030", | 82 | .name = "TWL4030", |
84 | .stream_name = "TWL4030", | 83 | .stream_name = "TWL4030", |
85 | .cpu_dai = &omap_mcbsp_dai[0], | 84 | .cpu_dai_name = "omap-mcbsp-dai.1", |
86 | .codec_dai = &twl4030_dai[TWL4030_DAI_HIFI], | 85 | .codec_dai_name = "twl4030-hifi", |
86 | .platform_name = "omap-pcm-audio", | ||
87 | .codec_name = "twl4030-codec", | ||
87 | .ops = &overo_ops, | 88 | .ops = &overo_ops, |
88 | }; | 89 | }; |
89 | 90 | ||
90 | /* Audio machine driver */ | 91 | /* Audio machine driver */ |
91 | static struct snd_soc_card snd_soc_card_overo = { | 92 | static struct snd_soc_card snd_soc_card_overo = { |
92 | .name = "overo", | 93 | .name = "overo", |
93 | .platform = &omap_soc_platform, | ||
94 | .dai_link = &overo_dai, | 94 | .dai_link = &overo_dai, |
95 | .num_links = 1, | 95 | .num_links = 1, |
96 | }; | 96 | }; |
97 | 97 | ||
98 | /* Audio subsystem */ | ||
99 | static struct snd_soc_device overo_snd_devdata = { | ||
100 | .card = &snd_soc_card_overo, | ||
101 | .codec_dev = &soc_codec_dev_twl4030, | ||
102 | }; | ||
103 | |||
104 | static struct platform_device *overo_snd_device; | 98 | static struct platform_device *overo_snd_device; |
105 | 99 | ||
106 | static int __init overo_soc_init(void) | 100 | static int __init overo_soc_init(void) |
@@ -119,9 +113,7 @@ static int __init overo_soc_init(void) | |||
119 | return -ENOMEM; | 113 | return -ENOMEM; |
120 | } | 114 | } |
121 | 115 | ||
122 | platform_set_drvdata(overo_snd_device, &overo_snd_devdata); | 116 | platform_set_drvdata(overo_snd_device, &snd_soc_card_overo); |
123 | overo_snd_devdata.dev = &overo_snd_device->dev; | ||
124 | *(unsigned int *)overo_dai.cpu_dai->private_data = 1; /* McBSP2 */ | ||
125 | 117 | ||
126 | ret = platform_device_add(overo_snd_device); | 118 | ret = platform_device_add(overo_snd_device); |
127 | if (ret) | 119 | if (ret) |
diff --git a/sound/soc/omap/rx51.c b/sound/soc/omap/rx51.c index 88052d29617f..d1d8098923ce 100644 --- a/sound/soc/omap/rx51.c +++ b/sound/soc/omap/rx51.c | |||
@@ -31,6 +31,7 @@ | |||
31 | #include <sound/pcm.h> | 31 | #include <sound/pcm.h> |
32 | #include <sound/soc.h> | 32 | #include <sound/soc.h> |
33 | #include <sound/soc-dapm.h> | 33 | #include <sound/soc-dapm.h> |
34 | #include <plat/mcbsp.h> | ||
34 | 35 | ||
35 | #include <asm/mach-types.h> | 36 | #include <asm/mach-types.h> |
36 | 37 | ||
@@ -76,7 +77,7 @@ static int rx51_startup(struct snd_pcm_substream *substream) | |||
76 | { | 77 | { |
77 | struct snd_pcm_runtime *runtime = substream->runtime; | 78 | struct snd_pcm_runtime *runtime = substream->runtime; |
78 | struct snd_soc_pcm_runtime *rtd = substream->private_data; | 79 | struct snd_soc_pcm_runtime *rtd = substream->private_data; |
79 | struct snd_soc_codec *codec = rtd->socdev->card->codec; | 80 | struct snd_soc_codec *codec = rtd->codec; |
80 | 81 | ||
81 | snd_pcm_hw_constraint_minmax(runtime, | 82 | snd_pcm_hw_constraint_minmax(runtime, |
82 | SNDRV_PCM_HW_PARAM_CHANNELS, 2, 2); | 83 | SNDRV_PCM_HW_PARAM_CHANNELS, 2, 2); |
@@ -89,8 +90,8 @@ static int rx51_hw_params(struct snd_pcm_substream *substream, | |||
89 | struct snd_pcm_hw_params *params) | 90 | struct snd_pcm_hw_params *params) |
90 | { | 91 | { |
91 | struct snd_soc_pcm_runtime *rtd = substream->private_data; | 92 | struct snd_soc_pcm_runtime *rtd = substream->private_data; |
92 | struct snd_soc_dai *codec_dai = rtd->dai->codec_dai; | 93 | struct snd_soc_dai *codec_dai = rtd->codec_dai; |
93 | struct snd_soc_dai *cpu_dai = rtd->dai->cpu_dai; | 94 | struct snd_soc_dai *cpu_dai = rtd->cpu_dai; |
94 | int err; | 95 | int err; |
95 | 96 | ||
96 | /* Set codec DAI configuration */ | 97 | /* Set codec DAI configuration */ |
@@ -240,9 +241,9 @@ static const struct snd_kcontrol_new aic34_rx51_controls[] = { | |||
240 | rx51_get_jack, rx51_set_jack), | 241 | rx51_get_jack, rx51_set_jack), |
241 | }; | 242 | }; |
242 | 243 | ||
243 | static int rx51_aic34_init(struct snd_soc_codec *codec) | 244 | static int rx51_aic34_init(struct snd_soc_pcm_runtime *rtd) |
244 | { | 245 | { |
245 | struct snd_soc_card *card = codec->socdev->card; | 246 | struct snd_soc_codec *codec = rtd->codec; |
246 | int err; | 247 | int err; |
247 | 248 | ||
248 | /* Set up NC codec pins */ | 249 | /* Set up NC codec pins */ |
@@ -266,7 +267,7 @@ static int rx51_aic34_init(struct snd_soc_codec *codec) | |||
266 | snd_soc_dapm_sync(codec); | 267 | snd_soc_dapm_sync(codec); |
267 | 268 | ||
268 | /* AV jack detection */ | 269 | /* AV jack detection */ |
269 | err = snd_soc_jack_new(card, "AV Jack", | 270 | err = snd_soc_jack_new(codec, "AV Jack", |
270 | SND_JACK_VIDEOOUT, &rx51_av_jack); | 271 | SND_JACK_VIDEOOUT, &rx51_av_jack); |
271 | if (err) | 272 | if (err) |
272 | return err; | 273 | return err; |
@@ -282,32 +283,20 @@ static struct snd_soc_dai_link rx51_dai[] = { | |||
282 | { | 283 | { |
283 | .name = "TLV320AIC34", | 284 | .name = "TLV320AIC34", |
284 | .stream_name = "AIC34", | 285 | .stream_name = "AIC34", |
285 | .cpu_dai = &omap_mcbsp_dai[0], | 286 | .cpu_dai_name = "omap-mcbsp-dai.1", |
286 | .codec_dai = &aic3x_dai, | 287 | .codec_dai_name = "tlv320aic3x-hifi", |
288 | .platform_name = "omap-pcm-audio", | ||
289 | .codec_name = "tlv320aic3x-codec.2-0018", | ||
287 | .init = rx51_aic34_init, | 290 | .init = rx51_aic34_init, |
288 | .ops = &rx51_ops, | 291 | .ops = &rx51_ops, |
289 | }, | 292 | }, |
290 | }; | 293 | }; |
291 | 294 | ||
292 | /* Audio private data */ | ||
293 | static struct aic3x_setup_data rx51_aic34_setup = { | ||
294 | .gpio_func[0] = AIC3X_GPIO1_FUNC_DISABLED, | ||
295 | .gpio_func[1] = AIC3X_GPIO2_FUNC_DIGITAL_MIC_INPUT, | ||
296 | }; | ||
297 | |||
298 | /* Audio card */ | 295 | /* Audio card */ |
299 | static struct snd_soc_card rx51_sound_card = { | 296 | static struct snd_soc_card rx51_sound_card = { |
300 | .name = "RX-51", | 297 | .name = "RX-51", |
301 | .dai_link = rx51_dai, | 298 | .dai_link = rx51_dai, |
302 | .num_links = ARRAY_SIZE(rx51_dai), | 299 | .num_links = ARRAY_SIZE(rx51_dai), |
303 | .platform = &omap_soc_platform, | ||
304 | }; | ||
305 | |||
306 | /* Audio subsystem */ | ||
307 | static struct snd_soc_device rx51_snd_devdata = { | ||
308 | .card = &rx51_sound_card, | ||
309 | .codec_dev = &soc_codec_dev_aic3x, | ||
310 | .codec_data = &rx51_aic34_setup, | ||
311 | }; | 300 | }; |
312 | 301 | ||
313 | static struct platform_device *rx51_snd_device; | 302 | static struct platform_device *rx51_snd_device; |
@@ -330,9 +319,7 @@ static int __init rx51_soc_init(void) | |||
330 | goto err1; | 319 | goto err1; |
331 | } | 320 | } |
332 | 321 | ||
333 | platform_set_drvdata(rx51_snd_device, &rx51_snd_devdata); | 322 | platform_set_drvdata(rx51_snd_device, &rx51_sound_card); |
334 | rx51_snd_devdata.dev = &rx51_snd_device->dev; | ||
335 | *(unsigned int *)rx51_dai[0].cpu_dai->private_data = 1; /* McBSP2 */ | ||
336 | 323 | ||
337 | err = platform_device_add(rx51_snd_device); | 324 | err = platform_device_add(rx51_snd_device); |
338 | if (err) | 325 | if (err) |
diff --git a/sound/soc/omap/sdp3430.c b/sound/soc/omap/sdp3430.c index 3c85c0f92823..76ce77b91844 100644 --- a/sound/soc/omap/sdp3430.c +++ b/sound/soc/omap/sdp3430.c | |||
@@ -36,9 +36,11 @@ | |||
36 | #include <mach/gpio.h> | 36 | #include <mach/gpio.h> |
37 | #include <plat/mcbsp.h> | 37 | #include <plat/mcbsp.h> |
38 | 38 | ||
39 | /* Register descriptions for twl4030 codec part */ | ||
40 | #include <linux/mfd/twl4030-codec.h> | ||
41 | |||
39 | #include "omap-mcbsp.h" | 42 | #include "omap-mcbsp.h" |
40 | #include "omap-pcm.h" | 43 | #include "omap-pcm.h" |
41 | #include "../codecs/twl4030.h" | ||
42 | 44 | ||
43 | /* TWL4030 PMBR1 Register */ | 45 | /* TWL4030 PMBR1 Register */ |
44 | #define TWL4030_INTBR_PMBR1 0x0D | 46 | #define TWL4030_INTBR_PMBR1 0x0D |
@@ -51,8 +53,8 @@ static int sdp3430_hw_params(struct snd_pcm_substream *substream, | |||
51 | struct snd_pcm_hw_params *params) | 53 | struct snd_pcm_hw_params *params) |
52 | { | 54 | { |
53 | struct snd_soc_pcm_runtime *rtd = substream->private_data; | 55 | struct snd_soc_pcm_runtime *rtd = substream->private_data; |
54 | struct snd_soc_dai *codec_dai = rtd->dai->codec_dai; | 56 | struct snd_soc_dai *codec_dai = rtd->codec_dai; |
55 | struct snd_soc_dai *cpu_dai = rtd->dai->cpu_dai; | 57 | struct snd_soc_dai *cpu_dai = rtd->cpu_dai; |
56 | int ret; | 58 | int ret; |
57 | 59 | ||
58 | /* Set codec DAI configuration */ | 60 | /* Set codec DAI configuration */ |
@@ -94,8 +96,8 @@ static int sdp3430_hw_voice_params(struct snd_pcm_substream *substream, | |||
94 | struct snd_pcm_hw_params *params) | 96 | struct snd_pcm_hw_params *params) |
95 | { | 97 | { |
96 | struct snd_soc_pcm_runtime *rtd = substream->private_data; | 98 | struct snd_soc_pcm_runtime *rtd = substream->private_data; |
97 | struct snd_soc_dai *codec_dai = rtd->dai->codec_dai; | 99 | struct snd_soc_dai *codec_dai = rtd->codec_dai; |
98 | struct snd_soc_dai *cpu_dai = rtd->dai->cpu_dai; | 100 | struct snd_soc_dai *cpu_dai = rtd->cpu_dai; |
99 | int ret; | 101 | int ret; |
100 | 102 | ||
101 | /* Set codec DAI configuration */ | 103 | /* Set codec DAI configuration */ |
@@ -186,8 +188,9 @@ static const struct snd_soc_dapm_route audio_map[] = { | |||
186 | {"Headset Stereophone", NULL, "HSOR"}, | 188 | {"Headset Stereophone", NULL, "HSOR"}, |
187 | }; | 189 | }; |
188 | 190 | ||
189 | static int sdp3430_twl4030_init(struct snd_soc_codec *codec) | 191 | static int sdp3430_twl4030_init(struct snd_soc_pcm_runtime *rtd) |
190 | { | 192 | { |
193 | struct snd_soc_codec *codec = rtd->codec; | ||
191 | int ret; | 194 | int ret; |
192 | 195 | ||
193 | /* Add SDP3430 specific widgets */ | 196 | /* Add SDP3430 specific widgets */ |
@@ -225,7 +228,7 @@ static int sdp3430_twl4030_init(struct snd_soc_codec *codec) | |||
225 | return ret; | 228 | return ret; |
226 | 229 | ||
227 | /* Headset jack detection */ | 230 | /* Headset jack detection */ |
228 | ret = snd_soc_jack_new(&snd_soc_sdp3430, "Headset Jack", | 231 | ret = snd_soc_jack_new(codec, "Headset Jack", |
229 | SND_JACK_HEADSET, &hs_jack); | 232 | SND_JACK_HEADSET, &hs_jack); |
230 | if (ret) | 233 | if (ret) |
231 | return ret; | 234 | return ret; |
@@ -241,14 +244,15 @@ static int sdp3430_twl4030_init(struct snd_soc_codec *codec) | |||
241 | return ret; | 244 | return ret; |
242 | } | 245 | } |
243 | 246 | ||
244 | static int sdp3430_twl4030_voice_init(struct snd_soc_codec *codec) | 247 | static int sdp3430_twl4030_voice_init(struct snd_soc_pcm_runtime *rtd) |
245 | { | 248 | { |
249 | struct snd_soc_codec *codec = rtd->codec; | ||
246 | unsigned short reg; | 250 | unsigned short reg; |
247 | 251 | ||
248 | /* Enable voice interface */ | 252 | /* Enable voice interface */ |
249 | reg = codec->read(codec, TWL4030_REG_VOICE_IF); | 253 | reg = codec->driver->read(codec, TWL4030_REG_VOICE_IF); |
250 | reg |= TWL4030_VIF_DIN_EN | TWL4030_VIF_DOUT_EN | TWL4030_VIF_EN; | 254 | reg |= TWL4030_VIF_DIN_EN | TWL4030_VIF_DOUT_EN | TWL4030_VIF_EN; |
251 | codec->write(codec, TWL4030_REG_VOICE_IF, reg); | 255 | codec->driver->write(codec, TWL4030_REG_VOICE_IF, reg); |
252 | 256 | ||
253 | return 0; | 257 | return 0; |
254 | } | 258 | } |
@@ -259,16 +263,20 @@ static struct snd_soc_dai_link sdp3430_dai[] = { | |||
259 | { | 263 | { |
260 | .name = "TWL4030 I2S", | 264 | .name = "TWL4030 I2S", |
261 | .stream_name = "TWL4030 Audio", | 265 | .stream_name = "TWL4030 Audio", |
262 | .cpu_dai = &omap_mcbsp_dai[0], | 266 | .cpu_dai_name = "omap-mcbsp-dai.1", |
263 | .codec_dai = &twl4030_dai[TWL4030_DAI_HIFI], | 267 | .codec_dai_name = "twl4030-hifi", |
268 | .platform_name = "omap-pcm-audio", | ||
269 | .codec_name = "twl4030-codec", | ||
264 | .init = sdp3430_twl4030_init, | 270 | .init = sdp3430_twl4030_init, |
265 | .ops = &sdp3430_ops, | 271 | .ops = &sdp3430_ops, |
266 | }, | 272 | }, |
267 | { | 273 | { |
268 | .name = "TWL4030 PCM", | 274 | .name = "TWL4030 PCM", |
269 | .stream_name = "TWL4030 Voice", | 275 | .stream_name = "TWL4030 Voice", |
270 | .cpu_dai = &omap_mcbsp_dai[1], | 276 | .cpu_dai_name = "omap-mcbsp-dai.2", |
271 | .codec_dai = &twl4030_dai[TWL4030_DAI_VOICE], | 277 | .codec_dai_name = "twl4030-voice", |
278 | .platform_name = "omap-pcm-audio", | ||
279 | .codec_name = "twl4030-codec", | ||
272 | .init = sdp3430_twl4030_voice_init, | 280 | .init = sdp3430_twl4030_voice_init, |
273 | .ops = &sdp3430_voice_ops, | 281 | .ops = &sdp3430_voice_ops, |
274 | }, | 282 | }, |
@@ -277,25 +285,10 @@ static struct snd_soc_dai_link sdp3430_dai[] = { | |||
277 | /* Audio machine driver */ | 285 | /* Audio machine driver */ |
278 | static struct snd_soc_card snd_soc_sdp3430 = { | 286 | static struct snd_soc_card snd_soc_sdp3430 = { |
279 | .name = "SDP3430", | 287 | .name = "SDP3430", |
280 | .platform = &omap_soc_platform, | ||
281 | .dai_link = sdp3430_dai, | 288 | .dai_link = sdp3430_dai, |
282 | .num_links = ARRAY_SIZE(sdp3430_dai), | 289 | .num_links = ARRAY_SIZE(sdp3430_dai), |
283 | }; | 290 | }; |
284 | 291 | ||
285 | /* twl4030 setup */ | ||
286 | static struct twl4030_setup_data twl4030_setup = { | ||
287 | .ramp_delay_value = 3, | ||
288 | .sysclk = 26000, | ||
289 | .hs_extmute = 1, | ||
290 | }; | ||
291 | |||
292 | /* Audio subsystem */ | ||
293 | static struct snd_soc_device sdp3430_snd_devdata = { | ||
294 | .card = &snd_soc_sdp3430, | ||
295 | .codec_dev = &soc_codec_dev_twl4030, | ||
296 | .codec_data = &twl4030_setup, | ||
297 | }; | ||
298 | |||
299 | static struct platform_device *sdp3430_snd_device; | 292 | static struct platform_device *sdp3430_snd_device; |
300 | 293 | ||
301 | static int __init sdp3430_soc_init(void) | 294 | static int __init sdp3430_soc_init(void) |
@@ -315,10 +308,7 @@ static int __init sdp3430_soc_init(void) | |||
315 | return -ENOMEM; | 308 | return -ENOMEM; |
316 | } | 309 | } |
317 | 310 | ||
318 | platform_set_drvdata(sdp3430_snd_device, &sdp3430_snd_devdata); | 311 | platform_set_drvdata(sdp3430_snd_device, &snd_soc_sdp3430); |
319 | sdp3430_snd_devdata.dev = &sdp3430_snd_device->dev; | ||
320 | *(unsigned int *)sdp3430_dai[0].cpu_dai->private_data = 1; /* McBSP2 */ | ||
321 | *(unsigned int *)sdp3430_dai[1].cpu_dai->private_data = 2; /* McBSP3 */ | ||
322 | 312 | ||
323 | /* Set TWL4030 GPIO6 as EXTMUTE signal */ | 313 | /* Set TWL4030 GPIO6 as EXTMUTE signal */ |
324 | twl_i2c_read_u8(TWL4030_MODULE_INTBR, &pin_mux, | 314 | twl_i2c_read_u8(TWL4030_MODULE_INTBR, &pin_mux, |
diff --git a/sound/soc/omap/sdp4430.c b/sound/soc/omap/sdp4430.c index 4ebbde6b565f..62f6a622d791 100644 --- a/sound/soc/omap/sdp4430.c +++ b/sound/soc/omap/sdp4430.c | |||
@@ -31,7 +31,6 @@ | |||
31 | #include <plat/mux.h> | 31 | #include <plat/mux.h> |
32 | 32 | ||
33 | #include "mcpdm.h" | 33 | #include "mcpdm.h" |
34 | #include "omap-mcpdm.h" | ||
35 | #include "omap-pcm.h" | 34 | #include "omap-pcm.h" |
36 | #include "../codecs/twl6040.h" | 35 | #include "../codecs/twl6040.h" |
37 | 36 | ||
@@ -41,7 +40,7 @@ static int sdp4430_hw_params(struct snd_pcm_substream *substream, | |||
41 | struct snd_pcm_hw_params *params) | 40 | struct snd_pcm_hw_params *params) |
42 | { | 41 | { |
43 | struct snd_soc_pcm_runtime *rtd = substream->private_data; | 42 | struct snd_soc_pcm_runtime *rtd = substream->private_data; |
44 | struct snd_soc_dai *codec_dai = rtd->dai->codec_dai; | 43 | struct snd_soc_dai *codec_dai = rtd->codec_dai; |
45 | int clk_id, freq; | 44 | int clk_id, freq; |
46 | int ret; | 45 | int ret; |
47 | 46 | ||
@@ -60,6 +59,7 @@ static int sdp4430_hw_params(struct snd_pcm_substream *substream, | |||
60 | printk(KERN_ERR "can't set codec system clock\n"); | 59 | printk(KERN_ERR "can't set codec system clock\n"); |
61 | return ret; | 60 | return ret; |
62 | } | 61 | } |
62 | return ret; | ||
63 | } | 63 | } |
64 | 64 | ||
65 | static struct snd_soc_ops sdp4430_ops = { | 65 | static struct snd_soc_ops sdp4430_ops = { |
@@ -126,8 +126,9 @@ static const struct snd_soc_dapm_route audio_map[] = { | |||
126 | {"Earphone Spk", NULL, "EP"}, | 126 | {"Earphone Spk", NULL, "EP"}, |
127 | }; | 127 | }; |
128 | 128 | ||
129 | static int sdp4430_twl6040_init(struct snd_soc_codec *codec) | 129 | static int sdp4430_twl6040_init(struct snd_soc_pcm_runtime *rtd) |
130 | { | 130 | { |
131 | struct snd_soc_codec *codec = rtd->codec; | ||
131 | int ret; | 132 | int ret; |
132 | 133 | ||
133 | /* Add SDP4430 specific controls */ | 134 | /* Add SDP4430 specific controls */ |
@@ -164,8 +165,10 @@ static int sdp4430_twl6040_init(struct snd_soc_codec *codec) | |||
164 | static struct snd_soc_dai_link sdp4430_dai = { | 165 | static struct snd_soc_dai_link sdp4430_dai = { |
165 | .name = "TWL6040", | 166 | .name = "TWL6040", |
166 | .stream_name = "TWL6040", | 167 | .stream_name = "TWL6040", |
167 | .cpu_dai = &omap_mcpdm_dai, | 168 | .cpu_dai_name ="omap-mcpdm-dai", |
168 | .codec_dai = &twl6040_dai, | 169 | .codec_dai_name = "twl6040-hifi", |
170 | .platform_name = "omap-pcm-audio", | ||
171 | .codec_name = "twl6040-codec", | ||
169 | .init = sdp4430_twl6040_init, | 172 | .init = sdp4430_twl6040_init, |
170 | .ops = &sdp4430_ops, | 173 | .ops = &sdp4430_ops, |
171 | }; | 174 | }; |
@@ -173,17 +176,10 @@ static struct snd_soc_dai_link sdp4430_dai = { | |||
173 | /* Audio machine driver */ | 176 | /* Audio machine driver */ |
174 | static struct snd_soc_card snd_soc_sdp4430 = { | 177 | static struct snd_soc_card snd_soc_sdp4430 = { |
175 | .name = "SDP4430", | 178 | .name = "SDP4430", |
176 | .platform = &omap_soc_platform, | ||
177 | .dai_link = &sdp4430_dai, | 179 | .dai_link = &sdp4430_dai, |
178 | .num_links = 1, | 180 | .num_links = 1, |
179 | }; | 181 | }; |
180 | 182 | ||
181 | /* Audio subsystem */ | ||
182 | static struct snd_soc_device sdp4430_snd_devdata = { | ||
183 | .card = &snd_soc_sdp4430, | ||
184 | .codec_dev = &soc_codec_dev_twl6040, | ||
185 | }; | ||
186 | |||
187 | static struct platform_device *sdp4430_snd_device; | 183 | static struct platform_device *sdp4430_snd_device; |
188 | 184 | ||
189 | static int __init sdp4430_soc_init(void) | 185 | static int __init sdp4430_soc_init(void) |
@@ -202,8 +198,7 @@ static int __init sdp4430_soc_init(void) | |||
202 | return -ENOMEM; | 198 | return -ENOMEM; |
203 | } | 199 | } |
204 | 200 | ||
205 | platform_set_drvdata(sdp4430_snd_device, &sdp4430_snd_devdata); | 201 | platform_set_drvdata(sdp4430_snd_device, &snd_soc_sdp4430); |
206 | sdp4430_snd_devdata.dev = &sdp4430_snd_device->dev; | ||
207 | 202 | ||
208 | ret = platform_device_add(sdp4430_snd_device); | 203 | ret = platform_device_add(sdp4430_snd_device); |
209 | if (ret) | 204 | if (ret) |
diff --git a/sound/soc/omap/zoom2.c b/sound/soc/omap/zoom2.c index 50a94ee76ecc..338dc9552bd6 100644 --- a/sound/soc/omap/zoom2.c +++ b/sound/soc/omap/zoom2.c | |||
@@ -29,21 +29,23 @@ | |||
29 | #include <asm/mach-types.h> | 29 | #include <asm/mach-types.h> |
30 | #include <mach/hardware.h> | 30 | #include <mach/hardware.h> |
31 | #include <mach/gpio.h> | 31 | #include <mach/gpio.h> |
32 | #include <mach/board-zoom.h> | ||
32 | #include <plat/mcbsp.h> | 33 | #include <plat/mcbsp.h> |
33 | 34 | ||
35 | /* Register descriptions for twl4030 codec part */ | ||
36 | #include <linux/mfd/twl4030-codec.h> | ||
37 | |||
34 | #include "omap-mcbsp.h" | 38 | #include "omap-mcbsp.h" |
35 | #include "omap-pcm.h" | 39 | #include "omap-pcm.h" |
36 | #include "../codecs/twl4030.h" | ||
37 | 40 | ||
38 | #define ZOOM2_HEADSET_MUX_GPIO (OMAP_MAX_GPIO_LINES + 15) | 41 | #define ZOOM2_HEADSET_MUX_GPIO (OMAP_MAX_GPIO_LINES + 15) |
39 | #define ZOOM2_HEADSET_EXTMUTE_GPIO 153 | ||
40 | 42 | ||
41 | static int zoom2_hw_params(struct snd_pcm_substream *substream, | 43 | static int zoom2_hw_params(struct snd_pcm_substream *substream, |
42 | struct snd_pcm_hw_params *params) | 44 | struct snd_pcm_hw_params *params) |
43 | { | 45 | { |
44 | struct snd_soc_pcm_runtime *rtd = substream->private_data; | 46 | struct snd_soc_pcm_runtime *rtd = substream->private_data; |
45 | struct snd_soc_dai *codec_dai = rtd->dai->codec_dai; | 47 | struct snd_soc_dai *codec_dai = rtd->codec_dai; |
46 | struct snd_soc_dai *cpu_dai = rtd->dai->cpu_dai; | 48 | struct snd_soc_dai *cpu_dai = rtd->cpu_dai; |
47 | int ret; | 49 | int ret; |
48 | 50 | ||
49 | /* Set codec DAI configuration */ | 51 | /* Set codec DAI configuration */ |
@@ -85,8 +87,8 @@ static int zoom2_hw_voice_params(struct snd_pcm_substream *substream, | |||
85 | struct snd_pcm_hw_params *params) | 87 | struct snd_pcm_hw_params *params) |
86 | { | 88 | { |
87 | struct snd_soc_pcm_runtime *rtd = substream->private_data; | 89 | struct snd_soc_pcm_runtime *rtd = substream->private_data; |
88 | struct snd_soc_dai *codec_dai = rtd->dai->codec_dai; | 90 | struct snd_soc_dai *codec_dai = rtd->codec_dai; |
89 | struct snd_soc_dai *cpu_dai = rtd->dai->cpu_dai; | 91 | struct snd_soc_dai *cpu_dai = rtd->cpu_dai; |
90 | int ret; | 92 | int ret; |
91 | 93 | ||
92 | /* Set codec DAI configuration */ | 94 | /* Set codec DAI configuration */ |
@@ -157,8 +159,9 @@ static const struct snd_soc_dapm_route audio_map[] = { | |||
157 | {"Aux In", NULL, "AUXR"}, | 159 | {"Aux In", NULL, "AUXR"}, |
158 | }; | 160 | }; |
159 | 161 | ||
160 | static int zoom2_twl4030_init(struct snd_soc_codec *codec) | 162 | static int zoom2_twl4030_init(struct snd_soc_pcm_runtime *rtd) |
161 | { | 163 | { |
164 | struct snd_soc_codec *codec = rtd->codec; | ||
162 | int ret; | 165 | int ret; |
163 | 166 | ||
164 | /* Add Zoom2 specific widgets */ | 167 | /* Add Zoom2 specific widgets */ |
@@ -192,14 +195,15 @@ static int zoom2_twl4030_init(struct snd_soc_codec *codec) | |||
192 | return ret; | 195 | return ret; |
193 | } | 196 | } |
194 | 197 | ||
195 | static int zoom2_twl4030_voice_init(struct snd_soc_codec *codec) | 198 | static int zoom2_twl4030_voice_init(struct snd_soc_pcm_runtime *rtd) |
196 | { | 199 | { |
200 | struct snd_soc_codec *codec = rtd->codec; | ||
197 | unsigned short reg; | 201 | unsigned short reg; |
198 | 202 | ||
199 | /* Enable voice interface */ | 203 | /* Enable voice interface */ |
200 | reg = codec->read(codec, TWL4030_REG_VOICE_IF); | 204 | reg = codec->driver->read(codec, TWL4030_REG_VOICE_IF); |
201 | reg |= TWL4030_VIF_DIN_EN | TWL4030_VIF_DOUT_EN | TWL4030_VIF_EN; | 205 | reg |= TWL4030_VIF_DIN_EN | TWL4030_VIF_DOUT_EN | TWL4030_VIF_EN; |
202 | codec->write(codec, TWL4030_REG_VOICE_IF, reg); | 206 | codec->driver->write(codec, TWL4030_REG_VOICE_IF, reg); |
203 | 207 | ||
204 | return 0; | 208 | return 0; |
205 | } | 209 | } |
@@ -209,16 +213,20 @@ static struct snd_soc_dai_link zoom2_dai[] = { | |||
209 | { | 213 | { |
210 | .name = "TWL4030 I2S", | 214 | .name = "TWL4030 I2S", |
211 | .stream_name = "TWL4030 Audio", | 215 | .stream_name = "TWL4030 Audio", |
212 | .cpu_dai = &omap_mcbsp_dai[0], | 216 | .cpu_dai_name = "omap-mcbsp-dai.1", |
213 | .codec_dai = &twl4030_dai[TWL4030_DAI_HIFI], | 217 | .codec_dai_name = "twl4030-hifi", |
218 | .platform_name = "omap-pcm-audio", | ||
219 | .codec_name = "twl4030-codec", | ||
214 | .init = zoom2_twl4030_init, | 220 | .init = zoom2_twl4030_init, |
215 | .ops = &zoom2_ops, | 221 | .ops = &zoom2_ops, |
216 | }, | 222 | }, |
217 | { | 223 | { |
218 | .name = "TWL4030 PCM", | 224 | .name = "TWL4030 PCM", |
219 | .stream_name = "TWL4030 Voice", | 225 | .stream_name = "TWL4030 Voice", |
220 | .cpu_dai = &omap_mcbsp_dai[1], | 226 | .cpu_dai_name = "omap-mcbsp-dai.2", |
221 | .codec_dai = &twl4030_dai[TWL4030_DAI_VOICE], | 227 | .codec_dai_name = "twl4030-voice", |
228 | .platform_name = "omap-pcm-audio", | ||
229 | .codec_name = "twl4030-codec", | ||
222 | .init = zoom2_twl4030_voice_init, | 230 | .init = zoom2_twl4030_voice_init, |
223 | .ops = &zoom2_voice_ops, | 231 | .ops = &zoom2_voice_ops, |
224 | }, | 232 | }, |
@@ -227,32 +235,10 @@ static struct snd_soc_dai_link zoom2_dai[] = { | |||
227 | /* Audio machine driver */ | 235 | /* Audio machine driver */ |
228 | static struct snd_soc_card snd_soc_zoom2 = { | 236 | static struct snd_soc_card snd_soc_zoom2 = { |
229 | .name = "Zoom2", | 237 | .name = "Zoom2", |
230 | .platform = &omap_soc_platform, | ||
231 | .dai_link = zoom2_dai, | 238 | .dai_link = zoom2_dai, |
232 | .num_links = ARRAY_SIZE(zoom2_dai), | 239 | .num_links = ARRAY_SIZE(zoom2_dai), |
233 | }; | 240 | }; |
234 | 241 | ||
235 | /* EXTMUTE callback function */ | ||
236 | void zoom2_set_hs_extmute(int mute) | ||
237 | { | ||
238 | gpio_set_value(ZOOM2_HEADSET_EXTMUTE_GPIO, mute); | ||
239 | } | ||
240 | |||
241 | /* twl4030 setup */ | ||
242 | static struct twl4030_setup_data twl4030_setup = { | ||
243 | .ramp_delay_value = 3, /* 161 ms */ | ||
244 | .sysclk = 26000, | ||
245 | .hs_extmute = 1, | ||
246 | .set_hs_extmute = zoom2_set_hs_extmute, | ||
247 | }; | ||
248 | |||
249 | /* Audio subsystem */ | ||
250 | static struct snd_soc_device zoom2_snd_devdata = { | ||
251 | .card = &snd_soc_zoom2, | ||
252 | .codec_dev = &soc_codec_dev_twl4030, | ||
253 | .codec_data = &twl4030_setup, | ||
254 | }; | ||
255 | |||
256 | static struct platform_device *zoom2_snd_device; | 242 | static struct platform_device *zoom2_snd_device; |
257 | 243 | ||
258 | static int __init zoom2_soc_init(void) | 244 | static int __init zoom2_soc_init(void) |
@@ -271,11 +257,7 @@ static int __init zoom2_soc_init(void) | |||
271 | return -ENOMEM; | 257 | return -ENOMEM; |
272 | } | 258 | } |
273 | 259 | ||
274 | platform_set_drvdata(zoom2_snd_device, &zoom2_snd_devdata); | 260 | platform_set_drvdata(zoom2_snd_device, &snd_soc_zoom2); |
275 | zoom2_snd_devdata.dev = &zoom2_snd_device->dev; | ||
276 | *(unsigned int *)zoom2_dai[0].cpu_dai->private_data = 1; /* McBSP2 */ | ||
277 | *(unsigned int *)zoom2_dai[1].cpu_dai->private_data = 2; /* McBSP3 */ | ||
278 | |||
279 | ret = platform_device_add(zoom2_snd_device); | 261 | ret = platform_device_add(zoom2_snd_device); |
280 | if (ret) | 262 | if (ret) |
281 | goto err1; | 263 | goto err1; |
diff --git a/sound/soc/pxa/corgi.c b/sound/soc/pxa/corgi.c index fefe1a57f31a..11c6a495f970 100644 --- a/sound/soc/pxa/corgi.c +++ b/sound/soc/pxa/corgi.c | |||
@@ -99,7 +99,7 @@ static void corgi_ext_control(struct snd_soc_codec *codec) | |||
99 | static int corgi_startup(struct snd_pcm_substream *substream) | 99 | static int corgi_startup(struct snd_pcm_substream *substream) |
100 | { | 100 | { |
101 | struct snd_soc_pcm_runtime *rtd = substream->private_data; | 101 | struct snd_soc_pcm_runtime *rtd = substream->private_data; |
102 | struct snd_soc_codec *codec = rtd->socdev->card->codec; | 102 | struct snd_soc_codec *codec = rtd->codec; |
103 | 103 | ||
104 | /* check the jack status at stream startup */ | 104 | /* check the jack status at stream startup */ |
105 | corgi_ext_control(codec); | 105 | corgi_ext_control(codec); |
@@ -118,8 +118,8 @@ static int corgi_hw_params(struct snd_pcm_substream *substream, | |||
118 | struct snd_pcm_hw_params *params) | 118 | struct snd_pcm_hw_params *params) |
119 | { | 119 | { |
120 | struct snd_soc_pcm_runtime *rtd = substream->private_data; | 120 | struct snd_soc_pcm_runtime *rtd = substream->private_data; |
121 | struct snd_soc_dai *codec_dai = rtd->dai->codec_dai; | 121 | struct snd_soc_dai *codec_dai = rtd->codec_dai; |
122 | struct snd_soc_dai *cpu_dai = rtd->dai->cpu_dai; | 122 | struct snd_soc_dai *cpu_dai = rtd->cpu_dai; |
123 | unsigned int clk = 0; | 123 | unsigned int clk = 0; |
124 | int ret = 0; | 124 | int ret = 0; |
125 | 125 | ||
@@ -272,8 +272,9 @@ static const struct snd_kcontrol_new wm8731_corgi_controls[] = { | |||
272 | /* | 272 | /* |
273 | * Logic for a wm8731 as connected on a Sharp SL-C7x0 Device | 273 | * Logic for a wm8731 as connected on a Sharp SL-C7x0 Device |
274 | */ | 274 | */ |
275 | static int corgi_wm8731_init(struct snd_soc_codec *codec) | 275 | static int corgi_wm8731_init(struct snd_soc_pcm_runtime *rtd) |
276 | { | 276 | { |
277 | struct snd_soc_codec *codec = rtd->codec; | ||
277 | int err; | 278 | int err; |
278 | 279 | ||
279 | snd_soc_dapm_nc_pin(codec, "LLINEIN"); | 280 | snd_soc_dapm_nc_pin(codec, "LLINEIN"); |
@@ -300,8 +301,10 @@ static int corgi_wm8731_init(struct snd_soc_codec *codec) | |||
300 | static struct snd_soc_dai_link corgi_dai = { | 301 | static struct snd_soc_dai_link corgi_dai = { |
301 | .name = "WM8731", | 302 | .name = "WM8731", |
302 | .stream_name = "WM8731", | 303 | .stream_name = "WM8731", |
303 | .cpu_dai = &pxa_i2s_dai, | 304 | .cpu_dai_name = "pxa-is2-dai", |
304 | .codec_dai = &wm8731_dai, | 305 | .codec_dai_name = "wm8731-hifi", |
306 | .platform_name = "pxa-pcm-audio", | ||
307 | .codec_name = "wm8731-codec-0.001a", | ||
305 | .init = corgi_wm8731_init, | 308 | .init = corgi_wm8731_init, |
306 | .ops = &corgi_ops, | 309 | .ops = &corgi_ops, |
307 | }; | 310 | }; |
@@ -309,17 +312,10 @@ static struct snd_soc_dai_link corgi_dai = { | |||
309 | /* corgi audio machine driver */ | 312 | /* corgi audio machine driver */ |
310 | static struct snd_soc_card snd_soc_corgi = { | 313 | static struct snd_soc_card snd_soc_corgi = { |
311 | .name = "Corgi", | 314 | .name = "Corgi", |
312 | .platform = &pxa2xx_soc_platform, | ||
313 | .dai_link = &corgi_dai, | 315 | .dai_link = &corgi_dai, |
314 | .num_links = 1, | 316 | .num_links = 1, |
315 | }; | 317 | }; |
316 | 318 | ||
317 | /* corgi audio subsystem */ | ||
318 | static struct snd_soc_device corgi_snd_devdata = { | ||
319 | .card = &snd_soc_corgi, | ||
320 | .codec_dev = &soc_codec_dev_wm8731, | ||
321 | }; | ||
322 | |||
323 | static struct platform_device *corgi_snd_device; | 319 | static struct platform_device *corgi_snd_device; |
324 | 320 | ||
325 | static int __init corgi_init(void) | 321 | static int __init corgi_init(void) |
@@ -334,8 +330,7 @@ static int __init corgi_init(void) | |||
334 | if (!corgi_snd_device) | 330 | if (!corgi_snd_device) |
335 | return -ENOMEM; | 331 | return -ENOMEM; |
336 | 332 | ||
337 | platform_set_drvdata(corgi_snd_device, &corgi_snd_devdata); | 333 | platform_set_drvdata(corgi_snd_device, &snd_soc_corgi); |
338 | corgi_snd_devdata.dev = &corgi_snd_device->dev; | ||
339 | ret = platform_device_add(corgi_snd_device); | 334 | ret = platform_device_add(corgi_snd_device); |
340 | 335 | ||
341 | if (ret) | 336 | if (ret) |
diff --git a/sound/soc/pxa/e740_wm9705.c b/sound/soc/pxa/e740_wm9705.c index 7cd2f89d7b10..f614607b2055 100644 --- a/sound/soc/pxa/e740_wm9705.c +++ b/sound/soc/pxa/e740_wm9705.c | |||
@@ -24,7 +24,6 @@ | |||
24 | #include <asm/mach-types.h> | 24 | #include <asm/mach-types.h> |
25 | 25 | ||
26 | #include "../codecs/wm9705.h" | 26 | #include "../codecs/wm9705.h" |
27 | #include "pxa2xx-pcm.h" | ||
28 | #include "pxa2xx-ac97.h" | 27 | #include "pxa2xx-ac97.h" |
29 | 28 | ||
30 | 29 | ||
@@ -90,8 +89,10 @@ static const struct snd_soc_dapm_route audio_map[] = { | |||
90 | {"Mic Amp", NULL, "Mic (Internal)"}, | 89 | {"Mic Amp", NULL, "Mic (Internal)"}, |
91 | }; | 90 | }; |
92 | 91 | ||
93 | static int e740_ac97_init(struct snd_soc_codec *codec) | 92 | static int e740_ac97_init(struct snd_soc_pcm_runtime *rtd) |
94 | { | 93 | { |
94 | struct snd_soc_codec *codec = rtd->codec; | ||
95 | |||
95 | snd_soc_dapm_nc_pin(codec, "HPOUTL"); | 96 | snd_soc_dapm_nc_pin(codec, "HPOUTL"); |
96 | snd_soc_dapm_nc_pin(codec, "HPOUTR"); | 97 | snd_soc_dapm_nc_pin(codec, "HPOUTR"); |
97 | snd_soc_dapm_nc_pin(codec, "PHONE"); | 98 | snd_soc_dapm_nc_pin(codec, "PHONE"); |
@@ -116,30 +117,28 @@ static struct snd_soc_dai_link e740_dai[] = { | |||
116 | { | 117 | { |
117 | .name = "AC97", | 118 | .name = "AC97", |
118 | .stream_name = "AC97 HiFi", | 119 | .stream_name = "AC97 HiFi", |
119 | .cpu_dai = &pxa_ac97_dai[PXA2XX_DAI_AC97_HIFI], | 120 | .cpu_dai_name = "pxa-ac97.0", |
120 | .codec_dai = &wm9705_dai[WM9705_DAI_AC97_HIFI], | 121 | .codec_dai_name = "wm9705-hifi", |
122 | .platform_name = "pxa-pcm-audio", | ||
123 | .codec_name = "wm9705-codec", | ||
121 | .init = e740_ac97_init, | 124 | .init = e740_ac97_init, |
122 | }, | 125 | }, |
123 | { | 126 | { |
124 | .name = "AC97 Aux", | 127 | .name = "AC97 Aux", |
125 | .stream_name = "AC97 Aux", | 128 | .stream_name = "AC97 Aux", |
126 | .cpu_dai = &pxa_ac97_dai[PXA2XX_DAI_AC97_AUX], | 129 | .cpu_dai_name = "pxa-ac97.1", |
127 | .codec_dai = &wm9705_dai[WM9705_DAI_AC97_AUX], | 130 | .codec_dai_name = "wm9705-aux", |
131 | .platform_name = "pxa-pcm-audio", | ||
132 | .codec_name = "wm9705-codec", | ||
128 | }, | 133 | }, |
129 | }; | 134 | }; |
130 | 135 | ||
131 | static struct snd_soc_card e740 = { | 136 | static struct snd_soc_card e740 = { |
132 | .name = "Toshiba e740", | 137 | .name = "Toshiba e740", |
133 | .platform = &pxa2xx_soc_platform, | ||
134 | .dai_link = e740_dai, | 138 | .dai_link = e740_dai, |
135 | .num_links = ARRAY_SIZE(e740_dai), | 139 | .num_links = ARRAY_SIZE(e740_dai), |
136 | }; | 140 | }; |
137 | 141 | ||
138 | static struct snd_soc_device e740_snd_devdata = { | ||
139 | .card = &e740, | ||
140 | .codec_dev = &soc_codec_dev_wm9705, | ||
141 | }; | ||
142 | |||
143 | static struct platform_device *e740_snd_device; | 142 | static struct platform_device *e740_snd_device; |
144 | 143 | ||
145 | static int __init e740_init(void) | 144 | static int __init e740_init(void) |
@@ -178,8 +177,7 @@ static int __init e740_init(void) | |||
178 | goto free_apwr_gpio; | 177 | goto free_apwr_gpio; |
179 | } | 178 | } |
180 | 179 | ||
181 | platform_set_drvdata(e740_snd_device, &e740_snd_devdata); | 180 | platform_set_drvdata(e740_snd_device, &e740); |
182 | e740_snd_devdata.dev = &e740_snd_device->dev; | ||
183 | ret = platform_device_add(e740_snd_device); | 181 | ret = platform_device_add(e740_snd_device); |
184 | 182 | ||
185 | if (!ret) | 183 | if (!ret) |
diff --git a/sound/soc/pxa/e750_wm9705.c b/sound/soc/pxa/e750_wm9705.c index 8dceccc5e059..4c143803a75e 100644 --- a/sound/soc/pxa/e750_wm9705.c +++ b/sound/soc/pxa/e750_wm9705.c | |||
@@ -24,7 +24,6 @@ | |||
24 | #include <asm/mach-types.h> | 24 | #include <asm/mach-types.h> |
25 | 25 | ||
26 | #include "../codecs/wm9705.h" | 26 | #include "../codecs/wm9705.h" |
27 | #include "pxa2xx-pcm.h" | ||
28 | #include "pxa2xx-ac97.h" | 27 | #include "pxa2xx-ac97.h" |
29 | 28 | ||
30 | static int e750_spk_amp_event(struct snd_soc_dapm_widget *w, | 29 | static int e750_spk_amp_event(struct snd_soc_dapm_widget *w, |
@@ -72,8 +71,10 @@ static const struct snd_soc_dapm_route audio_map[] = { | |||
72 | {"MIC1", NULL, "Mic (Internal)"}, | 71 | {"MIC1", NULL, "Mic (Internal)"}, |
73 | }; | 72 | }; |
74 | 73 | ||
75 | static int e750_ac97_init(struct snd_soc_codec *codec) | 74 | static int e750_ac97_init(struct snd_soc_pcm_runtime *rtd) |
76 | { | 75 | { |
76 | struct snd_soc_codec *codec = rtd->codec; | ||
77 | |||
77 | snd_soc_dapm_nc_pin(codec, "LOUT"); | 78 | snd_soc_dapm_nc_pin(codec, "LOUT"); |
78 | snd_soc_dapm_nc_pin(codec, "ROUT"); | 79 | snd_soc_dapm_nc_pin(codec, "ROUT"); |
79 | snd_soc_dapm_nc_pin(codec, "PHONE"); | 80 | snd_soc_dapm_nc_pin(codec, "PHONE"); |
@@ -98,31 +99,29 @@ static struct snd_soc_dai_link e750_dai[] = { | |||
98 | { | 99 | { |
99 | .name = "AC97", | 100 | .name = "AC97", |
100 | .stream_name = "AC97 HiFi", | 101 | .stream_name = "AC97 HiFi", |
101 | .cpu_dai = &pxa_ac97_dai[PXA2XX_DAI_AC97_HIFI], | 102 | .cpu_dai_name = "pxa-ac97.0", |
102 | .codec_dai = &wm9705_dai[WM9705_DAI_AC97_HIFI], | 103 | .codec_dai_name = "wm9705-hifi", |
104 | .platform_name = "pxa-pcm-audio", | ||
105 | .codec_name = "wm9705-codec", | ||
103 | .init = e750_ac97_init, | 106 | .init = e750_ac97_init, |
104 | /* use ops to check startup state */ | 107 | /* use ops to check startup state */ |
105 | }, | 108 | }, |
106 | { | 109 | { |
107 | .name = "AC97 Aux", | 110 | .name = "AC97 Aux", |
108 | .stream_name = "AC97 Aux", | 111 | .stream_name = "AC97 Aux", |
109 | .cpu_dai = &pxa_ac97_dai[PXA2XX_DAI_AC97_AUX], | 112 | .cpu_dai_name = "pxa-ac97.1", |
110 | .codec_dai = &wm9705_dai[WM9705_DAI_AC97_AUX], | 113 | .codec_dai_name ="wm9705-aux", |
114 | .platform_name = "pxa-pcm-audio", | ||
115 | .codec_name = "wm9705-codec", | ||
111 | }, | 116 | }, |
112 | }; | 117 | }; |
113 | 118 | ||
114 | static struct snd_soc_card e750 = { | 119 | static struct snd_soc_card e750 = { |
115 | .name = "Toshiba e750", | 120 | .name = "Toshiba e750", |
116 | .platform = &pxa2xx_soc_platform, | ||
117 | .dai_link = e750_dai, | 121 | .dai_link = e750_dai, |
118 | .num_links = ARRAY_SIZE(e750_dai), | 122 | .num_links = ARRAY_SIZE(e750_dai), |
119 | }; | 123 | }; |
120 | 124 | ||
121 | static struct snd_soc_device e750_snd_devdata = { | ||
122 | .card = &e750, | ||
123 | .codec_dev = &soc_codec_dev_wm9705, | ||
124 | }; | ||
125 | |||
126 | static struct platform_device *e750_snd_device; | 125 | static struct platform_device *e750_snd_device; |
127 | 126 | ||
128 | static int __init e750_init(void) | 127 | static int __init e750_init(void) |
@@ -154,8 +153,7 @@ static int __init e750_init(void) | |||
154 | goto free_spk_amp_gpio; | 153 | goto free_spk_amp_gpio; |
155 | } | 154 | } |
156 | 155 | ||
157 | platform_set_drvdata(e750_snd_device, &e750_snd_devdata); | 156 | platform_set_drvdata(e750_snd_device, &e750); |
158 | e750_snd_devdata.dev = &e750_snd_device->dev; | ||
159 | ret = platform_device_add(e750_snd_device); | 157 | ret = platform_device_add(e750_snd_device); |
160 | 158 | ||
161 | if (!ret) | 159 | if (!ret) |
diff --git a/sound/soc/pxa/e800_wm9712.c b/sound/soc/pxa/e800_wm9712.c index bc019cdce429..d42e5fe832c5 100644 --- a/sound/soc/pxa/e800_wm9712.c +++ b/sound/soc/pxa/e800_wm9712.c | |||
@@ -23,7 +23,6 @@ | |||
23 | #include <mach/eseries-gpio.h> | 23 | #include <mach/eseries-gpio.h> |
24 | 24 | ||
25 | #include "../codecs/wm9712.h" | 25 | #include "../codecs/wm9712.h" |
26 | #include "pxa2xx-pcm.h" | ||
27 | #include "pxa2xx-ac97.h" | 26 | #include "pxa2xx-ac97.h" |
28 | 27 | ||
29 | static int e800_spk_amp_event(struct snd_soc_dapm_widget *w, | 28 | static int e800_spk_amp_event(struct snd_soc_dapm_widget *w, |
@@ -73,8 +72,10 @@ static const struct snd_soc_dapm_route audio_map[] = { | |||
73 | {"MIC2", NULL, "Mic (Internal2)"}, | 72 | {"MIC2", NULL, "Mic (Internal2)"}, |
74 | }; | 73 | }; |
75 | 74 | ||
76 | static int e800_ac97_init(struct snd_soc_codec *codec) | 75 | static int e800_ac97_init(struct snd_soc_pcm_runtime *rtd) |
77 | { | 76 | { |
77 | struct snd_soc_codec *codec = rtd->codec; | ||
78 | |||
78 | snd_soc_dapm_new_controls(codec, e800_dapm_widgets, | 79 | snd_soc_dapm_new_controls(codec, e800_dapm_widgets, |
79 | ARRAY_SIZE(e800_dapm_widgets)); | 80 | ARRAY_SIZE(e800_dapm_widgets)); |
80 | 81 | ||
@@ -88,30 +89,28 @@ static struct snd_soc_dai_link e800_dai[] = { | |||
88 | { | 89 | { |
89 | .name = "AC97", | 90 | .name = "AC97", |
90 | .stream_name = "AC97 HiFi", | 91 | .stream_name = "AC97 HiFi", |
91 | .cpu_dai = &pxa_ac97_dai[PXA2XX_DAI_AC97_HIFI], | 92 | .cpu_dai_name = "pxa-ac97.0", |
92 | .codec_dai = &wm9712_dai[WM9712_DAI_AC97_HIFI], | 93 | .codec_dai_name = "wm9712-hifi", |
94 | .platform_name = "pxa-pcm-audio", | ||
95 | .codec_name = "wm9712-codec", | ||
93 | .init = e800_ac97_init, | 96 | .init = e800_ac97_init, |
94 | }, | 97 | }, |
95 | { | 98 | { |
96 | .name = "AC97 Aux", | 99 | .name = "AC97 Aux", |
97 | .stream_name = "AC97 Aux", | 100 | .stream_name = "AC97 Aux", |
98 | .cpu_dai = &pxa_ac97_dai[PXA2XX_DAI_AC97_AUX], | 101 | .cpu_dai_name = "pxa-ac97.1", |
99 | .codec_dai = &wm9712_dai[WM9712_DAI_AC97_AUX], | 102 | .codec_dai_name ="wm9712-aux", |
103 | .platform_name = "pxa-pcm-audio", | ||
104 | .codec_name = "wm9712-codec", | ||
100 | }, | 105 | }, |
101 | }; | 106 | }; |
102 | 107 | ||
103 | static struct snd_soc_card e800 = { | 108 | static struct snd_soc_card e800 = { |
104 | .name = "Toshiba e800", | 109 | .name = "Toshiba e800", |
105 | .platform = &pxa2xx_soc_platform, | ||
106 | .dai_link = e800_dai, | 110 | .dai_link = e800_dai, |
107 | .num_links = ARRAY_SIZE(e800_dai), | 111 | .num_links = ARRAY_SIZE(e800_dai), |
108 | }; | 112 | }; |
109 | 113 | ||
110 | static struct snd_soc_device e800_snd_devdata = { | ||
111 | .card = &e800, | ||
112 | .codec_dev = &soc_codec_dev_wm9712, | ||
113 | }; | ||
114 | |||
115 | static struct platform_device *e800_snd_device; | 114 | static struct platform_device *e800_snd_device; |
116 | 115 | ||
117 | static int __init e800_init(void) | 116 | static int __init e800_init(void) |
@@ -141,8 +140,7 @@ static int __init e800_init(void) | |||
141 | if (!e800_snd_device) | 140 | if (!e800_snd_device) |
142 | return -ENOMEM; | 141 | return -ENOMEM; |
143 | 142 | ||
144 | platform_set_drvdata(e800_snd_device, &e800_snd_devdata); | 143 | platform_set_drvdata(e800_snd_device, &e800); |
145 | e800_snd_devdata.dev = &e800_snd_device->dev; | ||
146 | ret = platform_device_add(e800_snd_device); | 144 | ret = platform_device_add(e800_snd_device); |
147 | 145 | ||
148 | if (!ret) | 146 | if (!ret) |
diff --git a/sound/soc/pxa/em-x270.c b/sound/soc/pxa/em-x270.c index f4756e4025fd..7046128b2a4c 100644 --- a/sound/soc/pxa/em-x270.c +++ b/sound/soc/pxa/em-x270.c | |||
@@ -39,29 +39,27 @@ static struct snd_soc_dai_link em_x270_dai[] = { | |||
39 | { | 39 | { |
40 | .name = "AC97", | 40 | .name = "AC97", |
41 | .stream_name = "AC97 HiFi", | 41 | .stream_name = "AC97 HiFi", |
42 | .cpu_dai = &pxa_ac97_dai[PXA2XX_DAI_AC97_HIFI], | 42 | .cpu_dai_name = "pxa-ac97.0", |
43 | .codec_dai = &wm9712_dai[WM9712_DAI_AC97_HIFI], | 43 | .codec_dai_name = "wm9712-hifi", |
44 | .platform_name = "pxa-pcm-audio", | ||
45 | .codec_name = "wm9712-codec", | ||
44 | }, | 46 | }, |
45 | { | 47 | { |
46 | .name = "AC97 Aux", | 48 | .name = "AC97 Aux", |
47 | .stream_name = "AC97 Aux", | 49 | .stream_name = "AC97 Aux", |
48 | .cpu_dai = &pxa_ac97_dai[PXA2XX_DAI_AC97_AUX], | 50 | .cpu_dai_name = "pxa-ac97.1", |
49 | .codec_dai = &wm9712_dai[WM9712_DAI_AC97_AUX], | 51 | .codec_dai_name ="wm9712-aux", |
52 | .platform_name = "pxa-pcm-audio", | ||
53 | .codec_name = "wm9712-codec", | ||
50 | }, | 54 | }, |
51 | }; | 55 | }; |
52 | 56 | ||
53 | static struct snd_soc_card em_x270 = { | 57 | static struct snd_soc_card em_x270 = { |
54 | .name = "EM-X270", | 58 | .name = "EM-X270", |
55 | .platform = &pxa2xx_soc_platform, | ||
56 | .dai_link = em_x270_dai, | 59 | .dai_link = em_x270_dai, |
57 | .num_links = ARRAY_SIZE(em_x270_dai), | 60 | .num_links = ARRAY_SIZE(em_x270_dai), |
58 | }; | 61 | }; |
59 | 62 | ||
60 | static struct snd_soc_device em_x270_snd_devdata = { | ||
61 | .card = &em_x270, | ||
62 | .codec_dev = &soc_codec_dev_wm9712, | ||
63 | }; | ||
64 | |||
65 | static struct platform_device *em_x270_snd_device; | 63 | static struct platform_device *em_x270_snd_device; |
66 | 64 | ||
67 | static int __init em_x270_init(void) | 65 | static int __init em_x270_init(void) |
@@ -76,8 +74,7 @@ static int __init em_x270_init(void) | |||
76 | if (!em_x270_snd_device) | 74 | if (!em_x270_snd_device) |
77 | return -ENOMEM; | 75 | return -ENOMEM; |
78 | 76 | ||
79 | platform_set_drvdata(em_x270_snd_device, &em_x270_snd_devdata); | 77 | platform_set_drvdata(em_x270_snd_device, &em_x270); |
80 | em_x270_snd_devdata.dev = &em_x270_snd_device->dev; | ||
81 | ret = platform_device_add(em_x270_snd_device); | 78 | ret = platform_device_add(em_x270_snd_device); |
82 | 79 | ||
83 | if (ret) | 80 | if (ret) |
diff --git a/sound/soc/pxa/imote2.c b/sound/soc/pxa/imote2.c index 405587a01160..03765fc5ac74 100644 --- a/sound/soc/pxa/imote2.c +++ b/sound/soc/pxa/imote2.c | |||
@@ -6,14 +6,13 @@ | |||
6 | 6 | ||
7 | #include "../codecs/wm8940.h" | 7 | #include "../codecs/wm8940.h" |
8 | #include "pxa2xx-i2s.h" | 8 | #include "pxa2xx-i2s.h" |
9 | #include "pxa2xx-pcm.h" | ||
10 | 9 | ||
11 | static int imote2_asoc_hw_params(struct snd_pcm_substream *substream, | 10 | static int imote2_asoc_hw_params(struct snd_pcm_substream *substream, |
12 | struct snd_pcm_hw_params *params) | 11 | struct snd_pcm_hw_params *params) |
13 | { | 12 | { |
14 | struct snd_soc_pcm_runtime *rtd = substream->private_data; | 13 | struct snd_soc_pcm_runtime *rtd = substream->private_data; |
15 | struct snd_soc_dai *codec_dai = rtd->dai->codec_dai; | 14 | struct snd_soc_dai *codec_dai = rtd->codec_dai; |
16 | struct snd_soc_dai *cpu_dai = rtd->dai->cpu_dai; | 15 | struct snd_soc_dai *cpu_dai = rtd->cpu_dai; |
17 | unsigned int clk = 0; | 16 | unsigned int clk = 0; |
18 | int ret; | 17 | int ret; |
19 | 18 | ||
@@ -64,23 +63,19 @@ static struct snd_soc_ops imote2_asoc_ops = { | |||
64 | static struct snd_soc_dai_link imote2_dai = { | 63 | static struct snd_soc_dai_link imote2_dai = { |
65 | .name = "WM8940", | 64 | .name = "WM8940", |
66 | .stream_name = "WM8940", | 65 | .stream_name = "WM8940", |
67 | .cpu_dai = &pxa_i2s_dai, | 66 | .cpu_dai_name = "pxa-i2s", |
68 | .codec_dai = &wm8940_dai, | 67 | .codec_dai_name = "wm8940-hifi", |
68 | .platform_name = "pxa-pcm-audio", | ||
69 | .codec_name = "wm8940-codec.0-0034", | ||
69 | .ops = &imote2_asoc_ops, | 70 | .ops = &imote2_asoc_ops, |
70 | }; | 71 | }; |
71 | 72 | ||
72 | static struct snd_soc_card snd_soc_imote2 = { | 73 | static struct snd_soc_card snd_soc_imote2 = { |
73 | .name = "Imote2", | 74 | .name = "Imote2", |
74 | .platform = &pxa2xx_soc_platform, | ||
75 | .dai_link = &imote2_dai, | 75 | .dai_link = &imote2_dai, |
76 | .num_links = 1, | 76 | .num_links = 1, |
77 | }; | 77 | }; |
78 | 78 | ||
79 | static struct snd_soc_device imote2_snd_devdata = { | ||
80 | .card = &snd_soc_imote2, | ||
81 | .codec_dev = &soc_codec_dev_wm8940, | ||
82 | }; | ||
83 | |||
84 | static struct platform_device *imote2_snd_device; | 79 | static struct platform_device *imote2_snd_device; |
85 | 80 | ||
86 | static int __init imote2_asoc_init(void) | 81 | static int __init imote2_asoc_init(void) |
@@ -93,8 +88,7 @@ static int __init imote2_asoc_init(void) | |||
93 | if (!imote2_snd_device) | 88 | if (!imote2_snd_device) |
94 | return -ENOMEM; | 89 | return -ENOMEM; |
95 | 90 | ||
96 | platform_set_drvdata(imote2_snd_device, &imote2_snd_devdata); | 91 | platform_set_drvdata(imote2_snd_device, &snd_soc_imote2); |
97 | imote2_snd_devdata.dev = &imote2_snd_device->dev; | ||
98 | ret = platform_device_add(imote2_snd_device); | 92 | ret = platform_device_add(imote2_snd_device); |
99 | if (ret) | 93 | if (ret) |
100 | platform_device_put(imote2_snd_device); | 94 | platform_device_put(imote2_snd_device); |
diff --git a/sound/soc/pxa/magician.c b/sound/soc/pxa/magician.c index 4c8d99a8d386..608bc3dd835f 100644 --- a/sound/soc/pxa/magician.c +++ b/sound/soc/pxa/magician.c | |||
@@ -32,7 +32,6 @@ | |||
32 | #include <mach/magician.h> | 32 | #include <mach/magician.h> |
33 | #include <asm/mach-types.h> | 33 | #include <asm/mach-types.h> |
34 | #include "../codecs/uda1380.h" | 34 | #include "../codecs/uda1380.h" |
35 | #include "pxa2xx-pcm.h" | ||
36 | #include "pxa2xx-i2s.h" | 35 | #include "pxa2xx-i2s.h" |
37 | #include "pxa-ssp.h" | 36 | #include "pxa-ssp.h" |
38 | 37 | ||
@@ -71,7 +70,7 @@ static void magician_ext_control(struct snd_soc_codec *codec) | |||
71 | static int magician_startup(struct snd_pcm_substream *substream) | 70 | static int magician_startup(struct snd_pcm_substream *substream) |
72 | { | 71 | { |
73 | struct snd_soc_pcm_runtime *rtd = substream->private_data; | 72 | struct snd_soc_pcm_runtime *rtd = substream->private_data; |
74 | struct snd_soc_codec *codec = rtd->socdev->card->codec; | 73 | struct snd_soc_codec *codec = rtd->codec; |
75 | 74 | ||
76 | /* check the jack status at stream startup */ | 75 | /* check the jack status at stream startup */ |
77 | magician_ext_control(codec); | 76 | magician_ext_control(codec); |
@@ -86,8 +85,8 @@ static int magician_playback_hw_params(struct snd_pcm_substream *substream, | |||
86 | struct snd_pcm_hw_params *params) | 85 | struct snd_pcm_hw_params *params) |
87 | { | 86 | { |
88 | struct snd_soc_pcm_runtime *rtd = substream->private_data; | 87 | struct snd_soc_pcm_runtime *rtd = substream->private_data; |
89 | struct snd_soc_dai *codec_dai = rtd->dai->codec_dai; | 88 | struct snd_soc_dai *codec_dai = rtd->codec_dai; |
90 | struct snd_soc_dai *cpu_dai = rtd->dai->cpu_dai; | 89 | struct snd_soc_dai *cpu_dai = rtd->cpu_dai; |
91 | unsigned int acps, acds, width, rate; | 90 | unsigned int acps, acds, width, rate; |
92 | unsigned int div4 = PXA_SSP_CLK_SCDB_4; | 91 | unsigned int div4 = PXA_SSP_CLK_SCDB_4; |
93 | int ret = 0; | 92 | int ret = 0; |
@@ -227,8 +226,8 @@ static int magician_capture_hw_params(struct snd_pcm_substream *substream, | |||
227 | struct snd_pcm_hw_params *params) | 226 | struct snd_pcm_hw_params *params) |
228 | { | 227 | { |
229 | struct snd_soc_pcm_runtime *rtd = substream->private_data; | 228 | struct snd_soc_pcm_runtime *rtd = substream->private_data; |
230 | struct snd_soc_dai *codec_dai = rtd->dai->codec_dai; | 229 | struct snd_soc_dai *codec_dai = rtd->codec_dai; |
231 | struct snd_soc_dai *cpu_dai = rtd->dai->cpu_dai; | 230 | struct snd_soc_dai *cpu_dai = rtd->cpu_dai; |
232 | int ret = 0; | 231 | int ret = 0; |
233 | 232 | ||
234 | /* set codec DAI configuration */ | 233 | /* set codec DAI configuration */ |
@@ -393,8 +392,9 @@ static const struct snd_kcontrol_new uda1380_magician_controls[] = { | |||
393 | /* | 392 | /* |
394 | * Logic for a uda1380 as connected on a HTC Magician | 393 | * Logic for a uda1380 as connected on a HTC Magician |
395 | */ | 394 | */ |
396 | static int magician_uda1380_init(struct snd_soc_codec *codec) | 395 | static int magician_uda1380_init(struct snd_soc_pcm_runtime *rtd) |
397 | { | 396 | { |
397 | struct snd_soc_codec *codec = rtd->codec; | ||
398 | int err; | 398 | int err; |
399 | 399 | ||
400 | /* NC codec pins */ | 400 | /* NC codec pins */ |
@@ -427,16 +427,20 @@ static struct snd_soc_dai_link magician_dai[] = { | |||
427 | { | 427 | { |
428 | .name = "uda1380", | 428 | .name = "uda1380", |
429 | .stream_name = "UDA1380 Playback", | 429 | .stream_name = "UDA1380 Playback", |
430 | .cpu_dai = &pxa_ssp_dai[PXA_DAI_SSP1], | 430 | .cpu_dai_name = "pxa-ssp-dai.0", |
431 | .codec_dai = &uda1380_dai[UDA1380_DAI_PLAYBACK], | 431 | .codec_dai_name = "uda1380-hifi-playback", |
432 | .platform_name = "pxa-pcm-audio", | ||
433 | .codec_name = "uda1380-codec.0-0018", | ||
432 | .init = magician_uda1380_init, | 434 | .init = magician_uda1380_init, |
433 | .ops = &magician_playback_ops, | 435 | .ops = &magician_playback_ops, |
434 | }, | 436 | }, |
435 | { | 437 | { |
436 | .name = "uda1380", | 438 | .name = "uda1380", |
437 | .stream_name = "UDA1380 Capture", | 439 | .stream_name = "UDA1380 Capture", |
438 | .cpu_dai = &pxa_i2s_dai, | 440 | .cpu_dai_name = "pxa-i2s", |
439 | .codec_dai = &uda1380_dai[UDA1380_DAI_CAPTURE], | 441 | .codec_dai_name = "uda1380-hifi-capture", |
442 | .platform_name = "pxa-pcm-audio", | ||
443 | .codec_name = "uda1380-codec.0-0018", | ||
440 | .ops = &magician_capture_ops, | 444 | .ops = &magician_capture_ops, |
441 | } | 445 | } |
442 | }; | 446 | }; |
@@ -446,13 +450,7 @@ static struct snd_soc_card snd_soc_card_magician = { | |||
446 | .name = "Magician", | 450 | .name = "Magician", |
447 | .dai_link = magician_dai, | 451 | .dai_link = magician_dai, |
448 | .num_links = ARRAY_SIZE(magician_dai), | 452 | .num_links = ARRAY_SIZE(magician_dai), |
449 | .platform = &pxa2xx_soc_platform, | ||
450 | }; | ||
451 | 453 | ||
452 | /* magician audio subsystem */ | ||
453 | static struct snd_soc_device magician_snd_devdata = { | ||
454 | .card = &snd_soc_card_magician, | ||
455 | .codec_dev = &soc_codec_dev_uda1380, | ||
456 | }; | 454 | }; |
457 | 455 | ||
458 | static struct platform_device *magician_snd_device; | 456 | static struct platform_device *magician_snd_device; |
@@ -514,8 +512,7 @@ static int __init magician_init(void) | |||
514 | goto err_pdev; | 512 | goto err_pdev; |
515 | } | 513 | } |
516 | 514 | ||
517 | platform_set_drvdata(magician_snd_device, &magician_snd_devdata); | 515 | platform_set_drvdata(magician_snd_device, &snd_soc_card_magician); |
518 | magician_snd_devdata.dev = &magician_snd_device->dev; | ||
519 | ret = platform_device_add(magician_snd_device); | 516 | ret = platform_device_add(magician_snd_device); |
520 | if (ret) { | 517 | if (ret) { |
521 | platform_device_put(magician_snd_device); | 518 | platform_device_put(magician_snd_device); |
diff --git a/sound/soc/pxa/mioa701_wm9713.c b/sound/soc/pxa/mioa701_wm9713.c index 19eda8bbfdaf..f284cc54bc80 100644 --- a/sound/soc/pxa/mioa701_wm9713.c +++ b/sound/soc/pxa/mioa701_wm9713.c | |||
@@ -54,7 +54,6 @@ | |||
54 | #include <sound/initval.h> | 54 | #include <sound/initval.h> |
55 | #include <sound/ac97_codec.h> | 55 | #include <sound/ac97_codec.h> |
56 | 56 | ||
57 | #include "pxa2xx-pcm.h" | ||
58 | #include "pxa2xx-ac97.h" | 57 | #include "pxa2xx-ac97.h" |
59 | #include "../codecs/wm9713.h" | 58 | #include "../codecs/wm9713.h" |
60 | 59 | ||
@@ -128,8 +127,9 @@ static const struct snd_soc_dapm_route audio_map[] = { | |||
128 | {"Rear Speaker", NULL, "SPKR"}, | 127 | {"Rear Speaker", NULL, "SPKR"}, |
129 | }; | 128 | }; |
130 | 129 | ||
131 | static int mioa701_wm9713_init(struct snd_soc_codec *codec) | 130 | static int mioa701_wm9713_init(struct snd_soc_pcm_runtime *rtd) |
132 | { | 131 | { |
132 | struct snd_soc_codec *codec = rtd->codec; | ||
133 | unsigned short reg; | 133 | unsigned short reg; |
134 | 134 | ||
135 | /* Add mioa701 specific widgets */ | 135 | /* Add mioa701 specific widgets */ |
@@ -139,12 +139,12 @@ static int mioa701_wm9713_init(struct snd_soc_codec *codec) | |||
139 | snd_soc_dapm_add_routes(codec, ARRAY_AND_SIZE(audio_map)); | 139 | snd_soc_dapm_add_routes(codec, ARRAY_AND_SIZE(audio_map)); |
140 | 140 | ||
141 | /* Prepare GPIO8 for rear speaker amplifier */ | 141 | /* Prepare GPIO8 for rear speaker amplifier */ |
142 | reg = codec->read(codec, AC97_GPIO_CFG); | 142 | reg = codec->driver->read(codec, AC97_GPIO_CFG); |
143 | codec->write(codec, AC97_GPIO_CFG, reg | 0x0100); | 143 | codec->driver->write(codec, AC97_GPIO_CFG, reg | 0x0100); |
144 | 144 | ||
145 | /* Prepare MIC input */ | 145 | /* Prepare MIC input */ |
146 | reg = codec->read(codec, AC97_3D_CONTROL); | 146 | reg = codec->driver->read(codec, AC97_3D_CONTROL); |
147 | codec->write(codec, AC97_3D_CONTROL, reg | 0xc000); | 147 | codec->driver->write(codec, AC97_3D_CONTROL, reg | 0xc000); |
148 | 148 | ||
149 | snd_soc_dapm_enable_pin(codec, "Front Speaker"); | 149 | snd_soc_dapm_enable_pin(codec, "Front Speaker"); |
150 | snd_soc_dapm_enable_pin(codec, "Rear Speaker"); | 150 | snd_soc_dapm_enable_pin(codec, "Rear Speaker"); |
@@ -162,32 +162,30 @@ static struct snd_soc_dai_link mioa701_dai[] = { | |||
162 | { | 162 | { |
163 | .name = "AC97", | 163 | .name = "AC97", |
164 | .stream_name = "AC97 HiFi", | 164 | .stream_name = "AC97 HiFi", |
165 | .cpu_dai = &pxa_ac97_dai[PXA2XX_DAI_AC97_HIFI], | 165 | .cpu_dai_name = "pxa-ac97.0", |
166 | .codec_dai = &wm9713_dai[WM9713_DAI_AC97_HIFI], | 166 | .codec_dai_name = "wm9713-hifi", |
167 | .codec_name = "wm9713-codec", | ||
167 | .init = mioa701_wm9713_init, | 168 | .init = mioa701_wm9713_init, |
169 | .platform_name = "pxa-pcm-audio", | ||
168 | .ops = &mioa701_ops, | 170 | .ops = &mioa701_ops, |
169 | }, | 171 | }, |
170 | { | 172 | { |
171 | .name = "AC97 Aux", | 173 | .name = "AC97 Aux", |
172 | .stream_name = "AC97 Aux", | 174 | .stream_name = "AC97 Aux", |
173 | .cpu_dai = &pxa_ac97_dai[PXA2XX_DAI_AC97_AUX], | 175 | .cpu_dai_name = "pxa-ac97.1", |
174 | .codec_dai = &wm9713_dai[WM9713_DAI_AC97_AUX], | 176 | .codec_dai_name ="wm9713-aux", |
177 | .codec_name = "wm9713-codec", | ||
178 | .platform_name = "pxa-pcm-audio", | ||
175 | .ops = &mioa701_ops, | 179 | .ops = &mioa701_ops, |
176 | }, | 180 | }, |
177 | }; | 181 | }; |
178 | 182 | ||
179 | static struct snd_soc_card mioa701 = { | 183 | static struct snd_soc_card mioa701 = { |
180 | .name = "MioA701", | 184 | .name = "MioA701", |
181 | .platform = &pxa2xx_soc_platform, | ||
182 | .dai_link = mioa701_dai, | 185 | .dai_link = mioa701_dai, |
183 | .num_links = ARRAY_SIZE(mioa701_dai), | 186 | .num_links = ARRAY_SIZE(mioa701_dai), |
184 | }; | 187 | }; |
185 | 188 | ||
186 | static struct snd_soc_device mioa701_snd_devdata = { | ||
187 | .card = &mioa701, | ||
188 | .codec_dev = &soc_codec_dev_wm9713, | ||
189 | }; | ||
190 | |||
191 | static struct platform_device *mioa701_snd_device; | 189 | static struct platform_device *mioa701_snd_device; |
192 | 190 | ||
193 | static int mioa701_wm9713_probe(struct platform_device *pdev) | 191 | static int mioa701_wm9713_probe(struct platform_device *pdev) |
@@ -205,8 +203,7 @@ static int mioa701_wm9713_probe(struct platform_device *pdev) | |||
205 | if (!mioa701_snd_device) | 203 | if (!mioa701_snd_device) |
206 | return -ENOMEM; | 204 | return -ENOMEM; |
207 | 205 | ||
208 | platform_set_drvdata(mioa701_snd_device, &mioa701_snd_devdata); | 206 | platform_set_drvdata(mioa701_snd_device, &mioa701); |
209 | mioa701_snd_devdata.dev = &mioa701_snd_device->dev; | ||
210 | 207 | ||
211 | ret = platform_device_add(mioa701_snd_device); | 208 | ret = platform_device_add(mioa701_snd_device); |
212 | if (!ret) | 209 | if (!ret) |
diff --git a/sound/soc/pxa/palm27x.c b/sound/soc/pxa/palm27x.c index 1f96e3227be5..13f6d485d571 100644 --- a/sound/soc/pxa/palm27x.c +++ b/sound/soc/pxa/palm27x.c | |||
@@ -29,7 +29,6 @@ | |||
29 | #include <mach/palmasoc.h> | 29 | #include <mach/palmasoc.h> |
30 | 30 | ||
31 | #include "../codecs/wm9712.h" | 31 | #include "../codecs/wm9712.h" |
32 | #include "pxa2xx-pcm.h" | ||
33 | #include "pxa2xx-ac97.h" | 32 | #include "pxa2xx-ac97.h" |
34 | 33 | ||
35 | static struct snd_soc_jack hs_jack; | 34 | static struct snd_soc_jack hs_jack; |
@@ -75,8 +74,9 @@ static const struct snd_soc_dapm_route audio_map[] = { | |||
75 | 74 | ||
76 | static struct snd_soc_card palm27x_asoc; | 75 | static struct snd_soc_card palm27x_asoc; |
77 | 76 | ||
78 | static int palm27x_ac97_init(struct snd_soc_codec *codec) | 77 | static int palm27x_ac97_init(struct snd_soc_pcm_runtime *rtd) |
79 | { | 78 | { |
79 | struct snd_soc_codec *codec = rtd->codec; | ||
80 | int err; | 80 | int err; |
81 | 81 | ||
82 | /* add palm27x specific widgets */ | 82 | /* add palm27x specific widgets */ |
@@ -112,7 +112,7 @@ static int palm27x_ac97_init(struct snd_soc_codec *codec) | |||
112 | return err; | 112 | return err; |
113 | 113 | ||
114 | /* Jack detection API stuff */ | 114 | /* Jack detection API stuff */ |
115 | err = snd_soc_jack_new(&palm27x_asoc, "Headphone Jack", | 115 | err = snd_soc_jack_new(codec, "Headphone Jack", |
116 | SND_JACK_HEADPHONE, &hs_jack); | 116 | SND_JACK_HEADPHONE, &hs_jack); |
117 | if (err) | 117 | if (err) |
118 | return err; | 118 | return err; |
@@ -132,30 +132,28 @@ static struct snd_soc_dai_link palm27x_dai[] = { | |||
132 | { | 132 | { |
133 | .name = "AC97 HiFi", | 133 | .name = "AC97 HiFi", |
134 | .stream_name = "AC97 HiFi", | 134 | .stream_name = "AC97 HiFi", |
135 | .cpu_dai = &pxa_ac97_dai[PXA2XX_DAI_AC97_HIFI], | 135 | .cpu_dai_name = "pxa-ac97.0", |
136 | .codec_dai = &wm9712_dai[WM9712_DAI_AC97_HIFI], | 136 | .codec_dai_name = "wm9712-hifi", |
137 | .codec_name = "wm9712-codec", | ||
138 | .platform_name = "pxa-pcm-audio", | ||
137 | .init = palm27x_ac97_init, | 139 | .init = palm27x_ac97_init, |
138 | }, | 140 | }, |
139 | { | 141 | { |
140 | .name = "AC97 Aux", | 142 | .name = "AC97 Aux", |
141 | .stream_name = "AC97 Aux", | 143 | .stream_name = "AC97 Aux", |
142 | .cpu_dai = &pxa_ac97_dai[PXA2XX_DAI_AC97_AUX], | 144 | .cpu_dai_name = "pxa-ac97.1", |
143 | .codec_dai = &wm9712_dai[WM9712_DAI_AC97_AUX], | 145 | .codec_dai_name = "wm9712-aux", |
146 | .codec_name = "wm9712-codec", | ||
147 | .platform_name = "pxa-pcm-audio", | ||
144 | }, | 148 | }, |
145 | }; | 149 | }; |
146 | 150 | ||
147 | static struct snd_soc_card palm27x_asoc = { | 151 | static struct snd_soc_card palm27x_asoc = { |
148 | .name = "Palm/PXA27x", | 152 | .name = "Palm/PXA27x", |
149 | .platform = &pxa2xx_soc_platform, | ||
150 | .dai_link = palm27x_dai, | 153 | .dai_link = palm27x_dai, |
151 | .num_links = ARRAY_SIZE(palm27x_dai), | 154 | .num_links = ARRAY_SIZE(palm27x_dai), |
152 | }; | 155 | }; |
153 | 156 | ||
154 | static struct snd_soc_device palm27x_snd_devdata = { | ||
155 | .card = &palm27x_asoc, | ||
156 | .codec_dev = &soc_codec_dev_wm9712, | ||
157 | }; | ||
158 | |||
159 | static struct platform_device *palm27x_snd_device; | 157 | static struct platform_device *palm27x_snd_device; |
160 | 158 | ||
161 | static int palm27x_asoc_probe(struct platform_device *pdev) | 159 | static int palm27x_asoc_probe(struct platform_device *pdev) |
@@ -178,8 +176,7 @@ static int palm27x_asoc_probe(struct platform_device *pdev) | |||
178 | if (!palm27x_snd_device) | 176 | if (!palm27x_snd_device) |
179 | return -ENOMEM; | 177 | return -ENOMEM; |
180 | 178 | ||
181 | platform_set_drvdata(palm27x_snd_device, &palm27x_snd_devdata); | 179 | platform_set_drvdata(palm27x_snd_device, &palm27x_asoc); |
182 | palm27x_snd_devdata.dev = &palm27x_snd_device->dev; | ||
183 | ret = platform_device_add(palm27x_snd_device); | 180 | ret = platform_device_add(palm27x_snd_device); |
184 | 181 | ||
185 | if (ret != 0) | 182 | if (ret != 0) |
diff --git a/sound/soc/pxa/poodle.c b/sound/soc/pxa/poodle.c index c5f36e0eab58..3ba5a962ecb8 100644 --- a/sound/soc/pxa/poodle.c +++ b/sound/soc/pxa/poodle.c | |||
@@ -31,7 +31,6 @@ | |||
31 | #include <mach/audio.h> | 31 | #include <mach/audio.h> |
32 | 32 | ||
33 | #include "../codecs/wm8731.h" | 33 | #include "../codecs/wm8731.h" |
34 | #include "pxa2xx-pcm.h" | ||
35 | #include "pxa2xx-i2s.h" | 34 | #include "pxa2xx-i2s.h" |
36 | 35 | ||
37 | #define POODLE_HP 1 | 36 | #define POODLE_HP 1 |
@@ -76,7 +75,7 @@ static void poodle_ext_control(struct snd_soc_codec *codec) | |||
76 | static int poodle_startup(struct snd_pcm_substream *substream) | 75 | static int poodle_startup(struct snd_pcm_substream *substream) |
77 | { | 76 | { |
78 | struct snd_soc_pcm_runtime *rtd = substream->private_data; | 77 | struct snd_soc_pcm_runtime *rtd = substream->private_data; |
79 | struct snd_soc_codec *codec = rtd->socdev->card->codec; | 78 | struct snd_soc_codec *codec = rtd->codec; |
80 | 79 | ||
81 | /* check the jack status at stream startup */ | 80 | /* check the jack status at stream startup */ |
82 | poodle_ext_control(codec); | 81 | poodle_ext_control(codec); |
@@ -97,8 +96,8 @@ static int poodle_hw_params(struct snd_pcm_substream *substream, | |||
97 | struct snd_pcm_hw_params *params) | 96 | struct snd_pcm_hw_params *params) |
98 | { | 97 | { |
99 | struct snd_soc_pcm_runtime *rtd = substream->private_data; | 98 | struct snd_soc_pcm_runtime *rtd = substream->private_data; |
100 | struct snd_soc_dai *codec_dai = rtd->dai->codec_dai; | 99 | struct snd_soc_dai *codec_dai = rtd->codec_dai; |
101 | struct snd_soc_dai *cpu_dai = rtd->dai->cpu_dai; | 100 | struct snd_soc_dai *cpu_dai = rtd->cpu_dai; |
102 | unsigned int clk = 0; | 101 | unsigned int clk = 0; |
103 | int ret = 0; | 102 | int ret = 0; |
104 | 103 | ||
@@ -237,8 +236,9 @@ static const struct snd_kcontrol_new wm8731_poodle_controls[] = { | |||
237 | /* | 236 | /* |
238 | * Logic for a wm8731 as connected on a Sharp SL-C7x0 Device | 237 | * Logic for a wm8731 as connected on a Sharp SL-C7x0 Device |
239 | */ | 238 | */ |
240 | static int poodle_wm8731_init(struct snd_soc_codec *codec) | 239 | static int poodle_wm8731_init(struct snd_soc_pcm_runtime *rtd) |
241 | { | 240 | { |
241 | struct snd_soc_codec *codec = rtd->codec; | ||
242 | int err; | 242 | int err; |
243 | 243 | ||
244 | snd_soc_dapm_nc_pin(codec, "LLINEIN"); | 244 | snd_soc_dapm_nc_pin(codec, "LLINEIN"); |
@@ -266,8 +266,10 @@ static int poodle_wm8731_init(struct snd_soc_codec *codec) | |||
266 | static struct snd_soc_dai_link poodle_dai = { | 266 | static struct snd_soc_dai_link poodle_dai = { |
267 | .name = "WM8731", | 267 | .name = "WM8731", |
268 | .stream_name = "WM8731", | 268 | .stream_name = "WM8731", |
269 | .cpu_dai = &pxa_i2s_dai, | 269 | .cpu_dai_name = "pxa-i2s", |
270 | .codec_dai = &wm8731_dai, | 270 | .codec_dai_name = "wm8731-hifi" |
271 | .platform_name = "pxa-pcm-audio", | ||
272 | .codec_name = "wm8731-codec.0-001a", | ||
271 | .init = poodle_wm8731_init, | 273 | .init = poodle_wm8731_init, |
272 | .ops = &poodle_ops, | 274 | .ops = &poodle_ops, |
273 | }; | 275 | }; |
@@ -275,15 +277,9 @@ static struct snd_soc_dai_link poodle_dai = { | |||
275 | /* poodle audio machine driver */ | 277 | /* poodle audio machine driver */ |
276 | static struct snd_soc_card snd_soc_poodle = { | 278 | static struct snd_soc_card snd_soc_poodle = { |
277 | .name = "Poodle", | 279 | .name = "Poodle", |
278 | .platform = &pxa2xx_soc_platform, | ||
279 | .dai_link = &poodle_dai, | 280 | .dai_link = &poodle_dai, |
280 | .num_links = 1, | 281 | .num_links = 1, |
281 | }; | 282 | .owner = THIS_MODULE, |
282 | |||
283 | /* poodle audio subsystem */ | ||
284 | static struct snd_soc_device poodle_snd_devdata = { | ||
285 | .card = &snd_soc_poodle, | ||
286 | .codec_dev = &soc_codec_dev_wm8731, | ||
287 | }; | 283 | }; |
288 | 284 | ||
289 | static struct platform_device *poodle_snd_device; | 285 | static struct platform_device *poodle_snd_device; |
@@ -307,8 +303,7 @@ static int __init poodle_init(void) | |||
307 | if (!poodle_snd_device) | 303 | if (!poodle_snd_device) |
308 | return -ENOMEM; | 304 | return -ENOMEM; |
309 | 305 | ||
310 | platform_set_drvdata(poodle_snd_device, &poodle_snd_devdata); | 306 | platform_set_drvdata(poodle_snd_device, &snd_soc_poodle); |
311 | poodle_snd_devdata.dev = &poodle_snd_device->dev; | ||
312 | ret = platform_device_add(poodle_snd_device); | 307 | ret = platform_device_add(poodle_snd_device); |
313 | 308 | ||
314 | if (ret) | 309 | if (ret) |
diff --git a/sound/soc/pxa/pxa-ssp.c b/sound/soc/pxa/pxa-ssp.c index a1fd23e0e3d0..99d80e85621c 100644 --- a/sound/soc/pxa/pxa-ssp.c +++ b/sound/soc/pxa/pxa-ssp.c | |||
@@ -108,11 +108,9 @@ pxa_ssp_get_dma_params(struct ssp_device *ssp, int width4, int out) | |||
108 | } | 108 | } |
109 | 109 | ||
110 | static int pxa_ssp_startup(struct snd_pcm_substream *substream, | 110 | static int pxa_ssp_startup(struct snd_pcm_substream *substream, |
111 | struct snd_soc_dai *dai) | 111 | struct snd_soc_dai *cpu_dai) |
112 | { | 112 | { |
113 | struct snd_soc_pcm_runtime *rtd = substream->private_data; | 113 | struct ssp_priv *priv = snd_soc_dai_get_drvdata(cpu_dai); |
114 | struct snd_soc_dai *cpu_dai = rtd->dai->cpu_dai; | ||
115 | struct ssp_priv *priv = cpu_dai->private_data; | ||
116 | struct ssp_device *ssp = priv->ssp; | 114 | struct ssp_device *ssp = priv->ssp; |
117 | int ret = 0; | 115 | int ret = 0; |
118 | 116 | ||
@@ -128,11 +126,9 @@ static int pxa_ssp_startup(struct snd_pcm_substream *substream, | |||
128 | } | 126 | } |
129 | 127 | ||
130 | static void pxa_ssp_shutdown(struct snd_pcm_substream *substream, | 128 | static void pxa_ssp_shutdown(struct snd_pcm_substream *substream, |
131 | struct snd_soc_dai *dai) | 129 | struct snd_soc_dai *cpu_dai) |
132 | { | 130 | { |
133 | struct snd_soc_pcm_runtime *rtd = substream->private_data; | 131 | struct ssp_priv *priv = snd_soc_dai_get_drvdata(cpu_dai); |
134 | struct snd_soc_dai *cpu_dai = rtd->dai->cpu_dai; | ||
135 | struct ssp_priv *priv = cpu_dai->private_data; | ||
136 | struct ssp_device *ssp = priv->ssp; | 132 | struct ssp_device *ssp = priv->ssp; |
137 | 133 | ||
138 | if (!cpu_dai->active) { | 134 | if (!cpu_dai->active) { |
@@ -148,7 +144,7 @@ static void pxa_ssp_shutdown(struct snd_pcm_substream *substream, | |||
148 | 144 | ||
149 | static int pxa_ssp_suspend(struct snd_soc_dai *cpu_dai) | 145 | static int pxa_ssp_suspend(struct snd_soc_dai *cpu_dai) |
150 | { | 146 | { |
151 | struct ssp_priv *priv = cpu_dai->private_data; | 147 | struct ssp_priv *priv = snd_soc_dai_get_drvdata(cpu_dai); |
152 | struct ssp_device *ssp = priv->ssp; | 148 | struct ssp_device *ssp = priv->ssp; |
153 | 149 | ||
154 | if (!cpu_dai->active) | 150 | if (!cpu_dai->active) |
@@ -166,7 +162,7 @@ static int pxa_ssp_suspend(struct snd_soc_dai *cpu_dai) | |||
166 | 162 | ||
167 | static int pxa_ssp_resume(struct snd_soc_dai *cpu_dai) | 163 | static int pxa_ssp_resume(struct snd_soc_dai *cpu_dai) |
168 | { | 164 | { |
169 | struct ssp_priv *priv = cpu_dai->private_data; | 165 | struct ssp_priv *priv = snd_soc_dai_get_drvdata(cpu_dai); |
170 | struct ssp_device *ssp = priv->ssp; | 166 | struct ssp_device *ssp = priv->ssp; |
171 | uint32_t sssr = SSSR_ROR | SSSR_TUR | SSSR_BCE; | 167 | uint32_t sssr = SSSR_ROR | SSSR_TUR | SSSR_BCE; |
172 | 168 | ||
@@ -230,7 +226,7 @@ static u32 pxa_ssp_get_scr(struct ssp_device *ssp) | |||
230 | static int pxa_ssp_set_dai_sysclk(struct snd_soc_dai *cpu_dai, | 226 | static int pxa_ssp_set_dai_sysclk(struct snd_soc_dai *cpu_dai, |
231 | int clk_id, unsigned int freq, int dir) | 227 | int clk_id, unsigned int freq, int dir) |
232 | { | 228 | { |
233 | struct ssp_priv *priv = cpu_dai->private_data; | 229 | struct ssp_priv *priv = snd_soc_dai_get_drvdata(cpu_dai); |
234 | struct ssp_device *ssp = priv->ssp; | 230 | struct ssp_device *ssp = priv->ssp; |
235 | int val; | 231 | int val; |
236 | 232 | ||
@@ -287,7 +283,7 @@ static int pxa_ssp_set_dai_sysclk(struct snd_soc_dai *cpu_dai, | |||
287 | static int pxa_ssp_set_dai_clkdiv(struct snd_soc_dai *cpu_dai, | 283 | static int pxa_ssp_set_dai_clkdiv(struct snd_soc_dai *cpu_dai, |
288 | int div_id, int div) | 284 | int div_id, int div) |
289 | { | 285 | { |
290 | struct ssp_priv *priv = cpu_dai->private_data; | 286 | struct ssp_priv *priv = snd_soc_dai_get_drvdata(cpu_dai); |
291 | struct ssp_device *ssp = priv->ssp; | 287 | struct ssp_device *ssp = priv->ssp; |
292 | int val; | 288 | int val; |
293 | 289 | ||
@@ -338,7 +334,7 @@ static int pxa_ssp_set_dai_clkdiv(struct snd_soc_dai *cpu_dai, | |||
338 | static int pxa_ssp_set_dai_pll(struct snd_soc_dai *cpu_dai, int pll_id, | 334 | static int pxa_ssp_set_dai_pll(struct snd_soc_dai *cpu_dai, int pll_id, |
339 | int source, unsigned int freq_in, unsigned int freq_out) | 335 | int source, unsigned int freq_in, unsigned int freq_out) |
340 | { | 336 | { |
341 | struct ssp_priv *priv = cpu_dai->private_data; | 337 | struct ssp_priv *priv = snd_soc_dai_get_drvdata(cpu_dai); |
342 | struct ssp_device *ssp = priv->ssp; | 338 | struct ssp_device *ssp = priv->ssp; |
343 | u32 ssacd = pxa_ssp_read_reg(ssp, SSACD) & ~0x70; | 339 | u32 ssacd = pxa_ssp_read_reg(ssp, SSACD) & ~0x70; |
344 | 340 | ||
@@ -407,7 +403,7 @@ static int pxa_ssp_set_dai_pll(struct snd_soc_dai *cpu_dai, int pll_id, | |||
407 | static int pxa_ssp_set_dai_tdm_slot(struct snd_soc_dai *cpu_dai, | 403 | static int pxa_ssp_set_dai_tdm_slot(struct snd_soc_dai *cpu_dai, |
408 | unsigned int tx_mask, unsigned int rx_mask, int slots, int slot_width) | 404 | unsigned int tx_mask, unsigned int rx_mask, int slots, int slot_width) |
409 | { | 405 | { |
410 | struct ssp_priv *priv = cpu_dai->private_data; | 406 | struct ssp_priv *priv = snd_soc_dai_get_drvdata(cpu_dai); |
411 | struct ssp_device *ssp = priv->ssp; | 407 | struct ssp_device *ssp = priv->ssp; |
412 | u32 sscr0; | 408 | u32 sscr0; |
413 | 409 | ||
@@ -442,7 +438,7 @@ static int pxa_ssp_set_dai_tdm_slot(struct snd_soc_dai *cpu_dai, | |||
442 | static int pxa_ssp_set_dai_tristate(struct snd_soc_dai *cpu_dai, | 438 | static int pxa_ssp_set_dai_tristate(struct snd_soc_dai *cpu_dai, |
443 | int tristate) | 439 | int tristate) |
444 | { | 440 | { |
445 | struct ssp_priv *priv = cpu_dai->private_data; | 441 | struct ssp_priv *priv = snd_soc_dai_get_drvdata(cpu_dai); |
446 | struct ssp_device *ssp = priv->ssp; | 442 | struct ssp_device *ssp = priv->ssp; |
447 | u32 sscr1; | 443 | u32 sscr1; |
448 | 444 | ||
@@ -464,7 +460,7 @@ static int pxa_ssp_set_dai_tristate(struct snd_soc_dai *cpu_dai, | |||
464 | static int pxa_ssp_set_dai_fmt(struct snd_soc_dai *cpu_dai, | 460 | static int pxa_ssp_set_dai_fmt(struct snd_soc_dai *cpu_dai, |
465 | unsigned int fmt) | 461 | unsigned int fmt) |
466 | { | 462 | { |
467 | struct ssp_priv *priv = cpu_dai->private_data; | 463 | struct ssp_priv *priv = snd_soc_dai_get_drvdata(cpu_dai); |
468 | struct ssp_device *ssp = priv->ssp; | 464 | struct ssp_device *ssp = priv->ssp; |
469 | u32 sscr0; | 465 | u32 sscr0; |
470 | u32 sscr1; | 466 | u32 sscr1; |
@@ -555,11 +551,9 @@ static int pxa_ssp_set_dai_fmt(struct snd_soc_dai *cpu_dai, | |||
555 | */ | 551 | */ |
556 | static int pxa_ssp_hw_params(struct snd_pcm_substream *substream, | 552 | static int pxa_ssp_hw_params(struct snd_pcm_substream *substream, |
557 | struct snd_pcm_hw_params *params, | 553 | struct snd_pcm_hw_params *params, |
558 | struct snd_soc_dai *dai) | 554 | struct snd_soc_dai *cpu_dai) |
559 | { | 555 | { |
560 | struct snd_soc_pcm_runtime *rtd = substream->private_data; | 556 | struct ssp_priv *priv = snd_soc_dai_get_drvdata(cpu_dai); |
561 | struct snd_soc_dai *cpu_dai = rtd->dai->cpu_dai; | ||
562 | struct ssp_priv *priv = cpu_dai->private_data; | ||
563 | struct ssp_device *ssp = priv->ssp; | 557 | struct ssp_device *ssp = priv->ssp; |
564 | int chn = params_channels(params); | 558 | int chn = params_channels(params); |
565 | u32 sscr0; | 559 | u32 sscr0; |
@@ -568,7 +562,7 @@ static int pxa_ssp_hw_params(struct snd_pcm_substream *substream, | |||
568 | int ttsa = pxa_ssp_read_reg(ssp, SSTSA) & 0xf; | 562 | int ttsa = pxa_ssp_read_reg(ssp, SSTSA) & 0xf; |
569 | struct pxa2xx_pcm_dma_params *dma_data; | 563 | struct pxa2xx_pcm_dma_params *dma_data; |
570 | 564 | ||
571 | dma_data = snd_soc_dai_get_dma_data(dai, substream); | 565 | dma_data = snd_soc_dai_get_dma_data(cpu_dai, substream); |
572 | 566 | ||
573 | /* generate correct DMA params */ | 567 | /* generate correct DMA params */ |
574 | kfree(dma_data); | 568 | kfree(dma_data); |
@@ -581,7 +575,7 @@ static int pxa_ssp_hw_params(struct snd_pcm_substream *substream, | |||
581 | ((chn == 2) && (ttsa != 1)) || (width == 32), | 575 | ((chn == 2) && (ttsa != 1)) || (width == 32), |
582 | substream->stream == SNDRV_PCM_STREAM_PLAYBACK); | 576 | substream->stream == SNDRV_PCM_STREAM_PLAYBACK); |
583 | 577 | ||
584 | snd_soc_dai_set_dma_data(dai, substream, dma_data); | 578 | snd_soc_dai_set_dma_data(cpu_dai, substream, dma_data); |
585 | 579 | ||
586 | /* we can only change the settings if the port is not in use */ | 580 | /* we can only change the settings if the port is not in use */ |
587 | if (pxa_ssp_read_reg(ssp, SSCR0) & SSCR0_SSE) | 581 | if (pxa_ssp_read_reg(ssp, SSCR0) & SSCR0_SSE) |
@@ -668,12 +662,10 @@ static int pxa_ssp_hw_params(struct snd_pcm_substream *substream, | |||
668 | } | 662 | } |
669 | 663 | ||
670 | static int pxa_ssp_trigger(struct snd_pcm_substream *substream, int cmd, | 664 | static int pxa_ssp_trigger(struct snd_pcm_substream *substream, int cmd, |
671 | struct snd_soc_dai *dai) | 665 | struct snd_soc_dai *cpu_dai) |
672 | { | 666 | { |
673 | struct snd_soc_pcm_runtime *rtd = substream->private_data; | ||
674 | struct snd_soc_dai *cpu_dai = rtd->dai->cpu_dai; | ||
675 | int ret = 0; | 667 | int ret = 0; |
676 | struct ssp_priv *priv = cpu_dai->private_data; | 668 | struct ssp_priv *priv = snd_soc_dai_get_drvdata(cpu_dai); |
677 | struct ssp_device *ssp = priv->ssp; | 669 | struct ssp_device *ssp = priv->ssp; |
678 | int val; | 670 | int val; |
679 | 671 | ||
@@ -729,8 +721,7 @@ static int pxa_ssp_trigger(struct snd_pcm_substream *substream, int cmd, | |||
729 | return ret; | 721 | return ret; |
730 | } | 722 | } |
731 | 723 | ||
732 | static int pxa_ssp_probe(struct platform_device *pdev, | 724 | static int pxa_ssp_probe(struct snd_soc_dai *dai) |
733 | struct snd_soc_dai *dai) | ||
734 | { | 725 | { |
735 | struct ssp_priv *priv; | 726 | struct ssp_priv *priv; |
736 | int ret; | 727 | int ret; |
@@ -746,7 +737,7 @@ static int pxa_ssp_probe(struct platform_device *pdev, | |||
746 | } | 737 | } |
747 | 738 | ||
748 | priv->dai_fmt = (unsigned int) -1; | 739 | priv->dai_fmt = (unsigned int) -1; |
749 | dai->private_data = priv; | 740 | snd_soc_dai_set_drvdata(dai, priv); |
750 | 741 | ||
751 | return 0; | 742 | return 0; |
752 | 743 | ||
@@ -755,11 +746,12 @@ err_priv: | |||
755 | return ret; | 746 | return ret; |
756 | } | 747 | } |
757 | 748 | ||
758 | static void pxa_ssp_remove(struct platform_device *pdev, | 749 | static int pxa_ssp_remove(struct snd_soc_dai *dai) |
759 | struct snd_soc_dai *dai) | ||
760 | { | 750 | { |
761 | struct ssp_priv *priv = dai->private_data; | 751 | struct ssp_priv *priv = snd_soc_dai_get_drvdata(dai); |
752 | |||
762 | pxa_ssp_free(priv->ssp); | 753 | pxa_ssp_free(priv->ssp); |
754 | return 0; | ||
763 | } | 755 | } |
764 | 756 | ||
765 | #define PXA_SSP_RATES (SNDRV_PCM_RATE_8000 | SNDRV_PCM_RATE_11025 |\ | 757 | #define PXA_SSP_RATES (SNDRV_PCM_RATE_8000 | SNDRV_PCM_RATE_11025 |\ |
@@ -784,10 +776,7 @@ static struct snd_soc_dai_ops pxa_ssp_dai_ops = { | |||
784 | .set_tristate = pxa_ssp_set_dai_tristate, | 776 | .set_tristate = pxa_ssp_set_dai_tristate, |
785 | }; | 777 | }; |
786 | 778 | ||
787 | struct snd_soc_dai pxa_ssp_dai[] = { | 779 | static struct snd_soc_dai_driver pxa_ssp_dai = { |
788 | { | ||
789 | .name = "pxa2xx-ssp1", | ||
790 | .id = 0, | ||
791 | .probe = pxa_ssp_probe, | 780 | .probe = pxa_ssp_probe, |
792 | .remove = pxa_ssp_remove, | 781 | .remove = pxa_ssp_remove, |
793 | .suspend = pxa_ssp_suspend, | 782 | .suspend = pxa_ssp_suspend, |
@@ -805,81 +794,38 @@ struct snd_soc_dai pxa_ssp_dai[] = { | |||
805 | .formats = PXA_SSP_FORMATS, | 794 | .formats = PXA_SSP_FORMATS, |
806 | }, | 795 | }, |
807 | .ops = &pxa_ssp_dai_ops, | 796 | .ops = &pxa_ssp_dai_ops, |
797 | }; | ||
798 | |||
799 | static __devinit int asoc_ssp_probe(struct platform_device *pdev) | ||
800 | { | ||
801 | return snd_soc_register_dai(&pdev->dev, &pxa_ssp_dai); | ||
802 | } | ||
803 | |||
804 | static int __devexit asoc_ssp_remove(struct platform_device *pdev) | ||
805 | { | ||
806 | snd_soc_unregister_dai(&pdev->dev); | ||
807 | return 0; | ||
808 | } | ||
809 | |||
810 | static struct platform_driver asoc_ssp_driver = { | ||
811 | .driver = { | ||
812 | .name = "pxa-ssp-dai", | ||
813 | .owner = THIS_MODULE, | ||
808 | }, | 814 | }, |
809 | { .name = "pxa2xx-ssp2", | 815 | |
810 | .id = 1, | 816 | .probe = asoc_ssp_probe, |
811 | .probe = pxa_ssp_probe, | 817 | .remove = __devexit_p(asoc_ssp_remove), |
812 | .remove = pxa_ssp_remove, | ||
813 | .suspend = pxa_ssp_suspend, | ||
814 | .resume = pxa_ssp_resume, | ||
815 | .playback = { | ||
816 | .channels_min = 1, | ||
817 | .channels_max = 8, | ||
818 | .rates = PXA_SSP_RATES, | ||
819 | .formats = PXA_SSP_FORMATS, | ||
820 | }, | ||
821 | .capture = { | ||
822 | .channels_min = 1, | ||
823 | .channels_max = 8, | ||
824 | .rates = PXA_SSP_RATES, | ||
825 | .formats = PXA_SSP_FORMATS, | ||
826 | }, | ||
827 | .ops = &pxa_ssp_dai_ops, | ||
828 | }, | ||
829 | { | ||
830 | .name = "pxa2xx-ssp3", | ||
831 | .id = 2, | ||
832 | .probe = pxa_ssp_probe, | ||
833 | .remove = pxa_ssp_remove, | ||
834 | .suspend = pxa_ssp_suspend, | ||
835 | .resume = pxa_ssp_resume, | ||
836 | .playback = { | ||
837 | .channels_min = 1, | ||
838 | .channels_max = 8, | ||
839 | .rates = PXA_SSP_RATES, | ||
840 | .formats = PXA_SSP_FORMATS, | ||
841 | }, | ||
842 | .capture = { | ||
843 | .channels_min = 1, | ||
844 | .channels_max = 8, | ||
845 | .rates = PXA_SSP_RATES, | ||
846 | .formats = PXA_SSP_FORMATS, | ||
847 | }, | ||
848 | .ops = &pxa_ssp_dai_ops, | ||
849 | }, | ||
850 | { | ||
851 | .name = "pxa2xx-ssp4", | ||
852 | .id = 3, | ||
853 | .probe = pxa_ssp_probe, | ||
854 | .remove = pxa_ssp_remove, | ||
855 | .suspend = pxa_ssp_suspend, | ||
856 | .resume = pxa_ssp_resume, | ||
857 | .playback = { | ||
858 | .channels_min = 1, | ||
859 | .channels_max = 8, | ||
860 | .rates = PXA_SSP_RATES, | ||
861 | .formats = PXA_SSP_FORMATS, | ||
862 | }, | ||
863 | .capture = { | ||
864 | .channels_min = 1, | ||
865 | .channels_max = 8, | ||
866 | .rates = PXA_SSP_RATES, | ||
867 | .formats = PXA_SSP_FORMATS, | ||
868 | }, | ||
869 | .ops = &pxa_ssp_dai_ops, | ||
870 | }, | ||
871 | }; | 818 | }; |
872 | EXPORT_SYMBOL_GPL(pxa_ssp_dai); | ||
873 | 819 | ||
874 | static int __init pxa_ssp_init(void) | 820 | static int __init pxa_ssp_init(void) |
875 | { | 821 | { |
876 | return snd_soc_register_dais(pxa_ssp_dai, ARRAY_SIZE(pxa_ssp_dai)); | 822 | return platform_driver_register(&asoc_ssp_driver); |
877 | } | 823 | } |
878 | module_init(pxa_ssp_init); | 824 | module_init(pxa_ssp_init); |
879 | 825 | ||
880 | static void __exit pxa_ssp_exit(void) | 826 | static void __exit pxa_ssp_exit(void) |
881 | { | 827 | { |
882 | snd_soc_unregister_dais(pxa_ssp_dai, ARRAY_SIZE(pxa_ssp_dai)); | 828 | platform_driver_unregister(&asoc_ssp_driver); |
883 | } | 829 | } |
884 | module_exit(pxa_ssp_exit); | 830 | module_exit(pxa_ssp_exit); |
885 | 831 | ||
diff --git a/sound/soc/pxa/pxa-ssp.h b/sound/soc/pxa/pxa-ssp.h index 91deadd55675..bc79da221c0d 100644 --- a/sound/soc/pxa/pxa-ssp.h +++ b/sound/soc/pxa/pxa-ssp.h | |||
@@ -42,6 +42,4 @@ | |||
42 | 42 | ||
43 | #define PXA_SSP_PLL_OUT 0 | 43 | #define PXA_SSP_PLL_OUT 0 |
44 | 44 | ||
45 | extern struct snd_soc_dai pxa_ssp_dai[4]; | ||
46 | |||
47 | #endif | 45 | #endif |
diff --git a/sound/soc/pxa/pxa2xx-ac97.c b/sound/soc/pxa/pxa2xx-ac97.c index d314115e3dd7..9c2bafa112ad 100644 --- a/sound/soc/pxa/pxa2xx-ac97.c +++ b/sound/soc/pxa/pxa2xx-ac97.c | |||
@@ -104,24 +104,21 @@ static int pxa2xx_ac97_resume(struct snd_soc_dai *dai) | |||
104 | #define pxa2xx_ac97_resume NULL | 104 | #define pxa2xx_ac97_resume NULL |
105 | #endif | 105 | #endif |
106 | 106 | ||
107 | static int pxa2xx_ac97_probe(struct platform_device *pdev, | 107 | static int pxa2xx_ac97_probe(struct snd_soc_dai *dai) |
108 | struct snd_soc_dai *dai) | ||
109 | { | 108 | { |
110 | return pxa2xx_ac97_hw_probe(to_platform_device(dai->dev)); | 109 | return pxa2xx_ac97_hw_probe(to_platform_device(dai->dev)); |
111 | } | 110 | } |
112 | 111 | ||
113 | static void pxa2xx_ac97_remove(struct platform_device *pdev, | 112 | static int pxa2xx_ac97_remove(struct snd_soc_dai *dai) |
114 | struct snd_soc_dai *dai) | ||
115 | { | 113 | { |
116 | pxa2xx_ac97_hw_remove(to_platform_device(dai->dev)); | 114 | pxa2xx_ac97_hw_remove(to_platform_device(dai->dev)); |
115 | return 0; | ||
117 | } | 116 | } |
118 | 117 | ||
119 | static int pxa2xx_ac97_hw_params(struct snd_pcm_substream *substream, | 118 | static int pxa2xx_ac97_hw_params(struct snd_pcm_substream *substream, |
120 | struct snd_pcm_hw_params *params, | 119 | struct snd_pcm_hw_params *params, |
121 | struct snd_soc_dai *dai) | 120 | struct snd_soc_dai *cpu_dai) |
122 | { | 121 | { |
123 | struct snd_soc_pcm_runtime *rtd = substream->private_data; | ||
124 | struct snd_soc_dai *cpu_dai = rtd->dai->cpu_dai; | ||
125 | struct pxa2xx_pcm_dma_params *dma_data; | 122 | struct pxa2xx_pcm_dma_params *dma_data; |
126 | 123 | ||
127 | if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) | 124 | if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) |
@@ -136,10 +133,8 @@ static int pxa2xx_ac97_hw_params(struct snd_pcm_substream *substream, | |||
136 | 133 | ||
137 | static int pxa2xx_ac97_hw_aux_params(struct snd_pcm_substream *substream, | 134 | static int pxa2xx_ac97_hw_aux_params(struct snd_pcm_substream *substream, |
138 | struct snd_pcm_hw_params *params, | 135 | struct snd_pcm_hw_params *params, |
139 | struct snd_soc_dai *dai) | 136 | struct snd_soc_dai *cpu_dai) |
140 | { | 137 | { |
141 | struct snd_soc_pcm_runtime *rtd = substream->private_data; | ||
142 | struct snd_soc_dai *cpu_dai = rtd->dai->cpu_dai; | ||
143 | struct pxa2xx_pcm_dma_params *dma_data; | 138 | struct pxa2xx_pcm_dma_params *dma_data; |
144 | 139 | ||
145 | if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) | 140 | if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) |
@@ -154,11 +149,8 @@ static int pxa2xx_ac97_hw_aux_params(struct snd_pcm_substream *substream, | |||
154 | 149 | ||
155 | static int pxa2xx_ac97_hw_mic_params(struct snd_pcm_substream *substream, | 150 | static int pxa2xx_ac97_hw_mic_params(struct snd_pcm_substream *substream, |
156 | struct snd_pcm_hw_params *params, | 151 | struct snd_pcm_hw_params *params, |
157 | struct snd_soc_dai *dai) | 152 | struct snd_soc_dai *cpu_dai) |
158 | { | 153 | { |
159 | struct snd_soc_pcm_runtime *rtd = substream->private_data; | ||
160 | struct snd_soc_dai *cpu_dai = rtd->dai->cpu_dai; | ||
161 | |||
162 | if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) | 154 | if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) |
163 | return -ENODEV; | 155 | return -ENODEV; |
164 | else | 156 | else |
@@ -188,10 +180,9 @@ static struct snd_soc_dai_ops pxa_ac97_mic_dai_ops = { | |||
188 | * There is only 1 physical AC97 interface for pxa2xx, but it | 180 | * There is only 1 physical AC97 interface for pxa2xx, but it |
189 | * has extra fifo's that can be used for aux DACs and ADCs. | 181 | * has extra fifo's that can be used for aux DACs and ADCs. |
190 | */ | 182 | */ |
191 | struct snd_soc_dai pxa_ac97_dai[] = { | 183 | static struct snd_soc_dai_driver pxa_ac97_dai[] = { |
192 | { | 184 | { |
193 | .name = "pxa2xx-ac97", | 185 | .name = "pxa2xx-ac97", |
194 | .id = 0, | ||
195 | .ac97_control = 1, | 186 | .ac97_control = 1, |
196 | .probe = pxa2xx_ac97_probe, | 187 | .probe = pxa2xx_ac97_probe, |
197 | .remove = pxa2xx_ac97_remove, | 188 | .remove = pxa2xx_ac97_remove, |
@@ -213,7 +204,6 @@ struct snd_soc_dai pxa_ac97_dai[] = { | |||
213 | }, | 204 | }, |
214 | { | 205 | { |
215 | .name = "pxa2xx-ac97-aux", | 206 | .name = "pxa2xx-ac97-aux", |
216 | .id = 1, | ||
217 | .ac97_control = 1, | 207 | .ac97_control = 1, |
218 | .playback = { | 208 | .playback = { |
219 | .stream_name = "AC97 Aux Playback", | 209 | .stream_name = "AC97 Aux Playback", |
@@ -231,7 +221,6 @@ struct snd_soc_dai pxa_ac97_dai[] = { | |||
231 | }, | 221 | }, |
232 | { | 222 | { |
233 | .name = "pxa2xx-ac97-mic", | 223 | .name = "pxa2xx-ac97-mic", |
234 | .id = 2, | ||
235 | .ac97_control = 1, | 224 | .ac97_control = 1, |
236 | .capture = { | 225 | .capture = { |
237 | .stream_name = "AC97 Mic Capture", | 226 | .stream_name = "AC97 Mic Capture", |
@@ -243,36 +232,26 @@ struct snd_soc_dai pxa_ac97_dai[] = { | |||
243 | }, | 232 | }, |
244 | }; | 233 | }; |
245 | 234 | ||
246 | EXPORT_SYMBOL_GPL(pxa_ac97_dai); | ||
247 | EXPORT_SYMBOL_GPL(soc_ac97_ops); | 235 | EXPORT_SYMBOL_GPL(soc_ac97_ops); |
248 | 236 | ||
249 | static int __devinit pxa2xx_ac97_dev_probe(struct platform_device *pdev) | 237 | static __devinit int pxa2xx_ac97_dev_probe(struct platform_device *pdev) |
250 | { | 238 | { |
251 | int i; | 239 | if (pdev->id != -1) { |
252 | pxa2xx_audio_ops_t *pdata = pdev->dev.platform_data; | ||
253 | |||
254 | if (pdev->id >= 0) { | ||
255 | dev_err(&pdev->dev, "PXA2xx has only one AC97 port.\n"); | 240 | dev_err(&pdev->dev, "PXA2xx has only one AC97 port.\n"); |
256 | return -ENXIO; | 241 | return -ENXIO; |
257 | } | 242 | } |
258 | 243 | ||
259 | for (i = 0; i < ARRAY_SIZE(pxa_ac97_dai); i++) { | ||
260 | pxa_ac97_dai[i].dev = &pdev->dev; | ||
261 | if (pdata && pdata->codec_pdata[0]) | ||
262 | pxa_ac97_dai[i].ac97_pdata = pdata->codec_pdata[0]; | ||
263 | } | ||
264 | |||
265 | /* Punt most of the init to the SoC probe; we may need the machine | 244 | /* Punt most of the init to the SoC probe; we may need the machine |
266 | * driver to do interesting things with the clocking to get us up | 245 | * driver to do interesting things with the clocking to get us up |
267 | * and running. | 246 | * and running. |
268 | */ | 247 | */ |
269 | return snd_soc_register_dais(pxa_ac97_dai, ARRAY_SIZE(pxa_ac97_dai)); | 248 | return snd_soc_register_dais(&pdev->dev, pxa_ac97_dai, |
249 | ARRAY_SIZE(pxa_ac97_dai)); | ||
270 | } | 250 | } |
271 | 251 | ||
272 | static int __devexit pxa2xx_ac97_dev_remove(struct platform_device *pdev) | 252 | static int __devexit pxa2xx_ac97_dev_remove(struct platform_device *pdev) |
273 | { | 253 | { |
274 | snd_soc_unregister_dais(pxa_ac97_dai, ARRAY_SIZE(pxa_ac97_dai)); | 254 | snd_soc_unregister_dais(&pdev->dev, ARRAY_SIZE(pxa_ac97_dai)); |
275 | |||
276 | return 0; | 255 | return 0; |
277 | } | 256 | } |
278 | 257 | ||
diff --git a/sound/soc/pxa/pxa2xx-ac97.h b/sound/soc/pxa/pxa2xx-ac97.h index e390de8edcd4..eda891e6f31b 100644 --- a/sound/soc/pxa/pxa2xx-ac97.h +++ b/sound/soc/pxa/pxa2xx-ac97.h | |||
@@ -14,8 +14,6 @@ | |||
14 | #define PXA2XX_DAI_AC97_AUX 1 | 14 | #define PXA2XX_DAI_AC97_AUX 1 |
15 | #define PXA2XX_DAI_AC97_MIC 2 | 15 | #define PXA2XX_DAI_AC97_MIC 2 |
16 | 16 | ||
17 | extern struct snd_soc_dai pxa_ac97_dai[3]; | ||
18 | |||
19 | /* platform data */ | 17 | /* platform data */ |
20 | extern struct snd_ac97_bus_ops pxa2xx_ac97_ops; | 18 | extern struct snd_ac97_bus_ops pxa2xx_ac97_ops; |
21 | 19 | ||
diff --git a/sound/soc/pxa/pxa2xx-i2s.c b/sound/soc/pxa/pxa2xx-i2s.c index c1a5275721e4..3b473b200a8f 100644 --- a/sound/soc/pxa/pxa2xx-i2s.c +++ b/sound/soc/pxa/pxa2xx-i2s.c | |||
@@ -80,6 +80,7 @@ struct pxa_i2s_port { | |||
80 | }; | 80 | }; |
81 | static struct pxa_i2s_port pxa_i2s; | 81 | static struct pxa_i2s_port pxa_i2s; |
82 | static struct clk *clk_i2s; | 82 | static struct clk *clk_i2s; |
83 | static int clk_ena = 0; | ||
83 | 84 | ||
84 | static struct pxa2xx_pcm_dma_params pxa2xx_i2s_pcm_stereo_out = { | 85 | static struct pxa2xx_pcm_dma_params pxa2xx_i2s_pcm_stereo_out = { |
85 | .name = "I2S PCM Stereo out", | 86 | .name = "I2S PCM Stereo out", |
@@ -101,7 +102,7 @@ static int pxa2xx_i2s_startup(struct snd_pcm_substream *substream, | |||
101 | struct snd_soc_dai *dai) | 102 | struct snd_soc_dai *dai) |
102 | { | 103 | { |
103 | struct snd_soc_pcm_runtime *rtd = substream->private_data; | 104 | struct snd_soc_pcm_runtime *rtd = substream->private_data; |
104 | struct snd_soc_dai *cpu_dai = rtd->dai->cpu_dai; | 105 | struct snd_soc_dai *cpu_dai = rtd->cpu_dai; |
105 | 106 | ||
106 | if (IS_ERR(clk_i2s)) | 107 | if (IS_ERR(clk_i2s)) |
107 | return PTR_ERR(clk_i2s); | 108 | return PTR_ERR(clk_i2s); |
@@ -162,13 +163,11 @@ static int pxa2xx_i2s_hw_params(struct snd_pcm_substream *substream, | |||
162 | struct snd_pcm_hw_params *params, | 163 | struct snd_pcm_hw_params *params, |
163 | struct snd_soc_dai *dai) | 164 | struct snd_soc_dai *dai) |
164 | { | 165 | { |
165 | struct snd_soc_pcm_runtime *rtd = substream->private_data; | ||
166 | struct snd_soc_dai *cpu_dai = rtd->dai->cpu_dai; | ||
167 | struct pxa2xx_pcm_dma_params *dma_data; | 166 | struct pxa2xx_pcm_dma_params *dma_data; |
168 | 167 | ||
169 | BUG_ON(IS_ERR(clk_i2s)); | 168 | BUG_ON(IS_ERR(clk_i2s)); |
170 | clk_enable(clk_i2s); | 169 | clk_enable(clk_i2s); |
171 | dai->private_data = dai; | 170 | clk_ena = 1; |
172 | pxa_i2s_wait(); | 171 | pxa_i2s_wait(); |
173 | 172 | ||
174 | if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) | 173 | if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) |
@@ -176,7 +175,7 @@ static int pxa2xx_i2s_hw_params(struct snd_pcm_substream *substream, | |||
176 | else | 175 | else |
177 | dma_data = &pxa2xx_i2s_pcm_stereo_in; | 176 | dma_data = &pxa2xx_i2s_pcm_stereo_in; |
178 | 177 | ||
179 | snd_soc_dai_set_dma_data(cpu_dai, substream, dma_data); | 178 | snd_soc_dai_set_dma_data(dai, substream, dma_data); |
180 | 179 | ||
181 | /* is port used by another stream */ | 180 | /* is port used by another stream */ |
182 | if (!(SACR0 & SACR0_ENB)) { | 181 | if (!(SACR0 & SACR0_ENB)) { |
@@ -259,9 +258,9 @@ static void pxa2xx_i2s_shutdown(struct snd_pcm_substream *substream, | |||
259 | if ((SACR1 & (SACR1_DREC | SACR1_DRPL)) == (SACR1_DREC | SACR1_DRPL)) { | 258 | if ((SACR1 & (SACR1_DREC | SACR1_DRPL)) == (SACR1_DREC | SACR1_DRPL)) { |
260 | SACR0 &= ~SACR0_ENB; | 259 | SACR0 &= ~SACR0_ENB; |
261 | pxa_i2s_wait(); | 260 | pxa_i2s_wait(); |
262 | if (dai->private_data != NULL) { | 261 | if (clk_ena) { |
263 | clk_disable(clk_i2s); | 262 | clk_disable(clk_i2s); |
264 | dai->private_data = NULL; | 263 | clk_ena = 0; |
265 | } | 264 | } |
266 | } | 265 | } |
267 | } | 266 | } |
@@ -300,6 +299,35 @@ static int pxa2xx_i2s_resume(struct snd_soc_dai *dai) | |||
300 | #define pxa2xx_i2s_resume NULL | 299 | #define pxa2xx_i2s_resume NULL |
301 | #endif | 300 | #endif |
302 | 301 | ||
302 | static int pxa2xx_i2s_probe(struct snd_soc_dai *dai) | ||
303 | { | ||
304 | clk_i2s = clk_get(dai->dev, "I2SCLK"); | ||
305 | if (IS_ERR(clk_i2s)) | ||
306 | return PTR_ERR(clk_i2s); | ||
307 | |||
308 | /* | ||
309 | * PXA Developer's Manual: | ||
310 | * If SACR0[ENB] is toggled in the middle of a normal operation, | ||
311 | * the SACR0[RST] bit must also be set and cleared to reset all | ||
312 | * I2S controller registers. | ||
313 | */ | ||
314 | SACR0 = SACR0_RST; | ||
315 | SACR0 = 0; | ||
316 | /* Make sure RPL and REC are disabled */ | ||
317 | SACR1 = SACR1_DRPL | SACR1_DREC; | ||
318 | /* Along with FIFO servicing */ | ||
319 | SAIMR &= ~(SAIMR_RFS | SAIMR_TFS); | ||
320 | |||
321 | return 0; | ||
322 | } | ||
323 | |||
324 | static int pxa2xx_i2s_remove(struct snd_soc_dai *dai) | ||
325 | { | ||
326 | clk_put(clk_i2s); | ||
327 | clk_i2s = ERR_PTR(-ENOENT); | ||
328 | return 0; | ||
329 | } | ||
330 | |||
303 | #define PXA2XX_I2S_RATES (SNDRV_PCM_RATE_8000 | SNDRV_PCM_RATE_11025 |\ | 331 | #define PXA2XX_I2S_RATES (SNDRV_PCM_RATE_8000 | SNDRV_PCM_RATE_11025 |\ |
304 | SNDRV_PCM_RATE_16000 | SNDRV_PCM_RATE_22050 | SNDRV_PCM_RATE_44100 | \ | 332 | SNDRV_PCM_RATE_16000 | SNDRV_PCM_RATE_22050 | SNDRV_PCM_RATE_44100 | \ |
305 | SNDRV_PCM_RATE_48000 | SNDRV_PCM_RATE_96000) | 333 | SNDRV_PCM_RATE_48000 | SNDRV_PCM_RATE_96000) |
@@ -313,9 +341,9 @@ static struct snd_soc_dai_ops pxa_i2s_dai_ops = { | |||
313 | .set_sysclk = pxa2xx_i2s_set_dai_sysclk, | 341 | .set_sysclk = pxa2xx_i2s_set_dai_sysclk, |
314 | }; | 342 | }; |
315 | 343 | ||
316 | struct snd_soc_dai pxa_i2s_dai = { | 344 | static struct snd_soc_dai_driver pxa_i2s_dai = { |
317 | .name = "pxa2xx-i2s", | 345 | .probe = pxa2xx_i2s_probe, |
318 | .id = 0, | 346 | .remove = pxa2xx_i2s_remove, |
319 | .suspend = pxa2xx_i2s_suspend, | 347 | .suspend = pxa2xx_i2s_suspend, |
320 | .resume = pxa2xx_i2s_resume, | 348 | .resume = pxa2xx_i2s_resume, |
321 | .playback = { | 349 | .playback = { |
@@ -332,49 +360,20 @@ struct snd_soc_dai pxa_i2s_dai = { | |||
332 | .symmetric_rates = 1, | 360 | .symmetric_rates = 1, |
333 | }; | 361 | }; |
334 | 362 | ||
335 | EXPORT_SYMBOL_GPL(pxa_i2s_dai); | 363 | static int pxa2xx_i2s_drv_probe(struct platform_device *pdev) |
336 | |||
337 | static int pxa2xx_i2s_probe(struct platform_device *dev) | ||
338 | { | 364 | { |
339 | int ret; | 365 | return snd_soc_register_dai(&pdev->dev, &pxa_i2s_dai); |
340 | |||
341 | clk_i2s = clk_get(&dev->dev, "I2SCLK"); | ||
342 | if (IS_ERR(clk_i2s)) | ||
343 | return PTR_ERR(clk_i2s); | ||
344 | |||
345 | pxa_i2s_dai.dev = &dev->dev; | ||
346 | pxa_i2s_dai.private_data = NULL; | ||
347 | ret = snd_soc_register_dai(&pxa_i2s_dai); | ||
348 | if (ret != 0) | ||
349 | clk_put(clk_i2s); | ||
350 | |||
351 | /* | ||
352 | * PXA Developer's Manual: | ||
353 | * If SACR0[ENB] is toggled in the middle of a normal operation, | ||
354 | * the SACR0[RST] bit must also be set and cleared to reset all | ||
355 | * I2S controller registers. | ||
356 | */ | ||
357 | SACR0 = SACR0_RST; | ||
358 | SACR0 = 0; | ||
359 | /* Make sure RPL and REC are disabled */ | ||
360 | SACR1 = SACR1_DRPL | SACR1_DREC; | ||
361 | /* Along with FIFO servicing */ | ||
362 | SAIMR &= ~(SAIMR_RFS | SAIMR_TFS); | ||
363 | |||
364 | return ret; | ||
365 | } | 366 | } |
366 | 367 | ||
367 | static int __devexit pxa2xx_i2s_remove(struct platform_device *dev) | 368 | static int __devexit pxa2xx_i2s_drv_remove(struct platform_device *pdev) |
368 | { | 369 | { |
369 | snd_soc_unregister_dai(&pxa_i2s_dai); | 370 | snd_soc_unregister_dai(&pdev->dev); |
370 | clk_put(clk_i2s); | ||
371 | clk_i2s = ERR_PTR(-ENOENT); | ||
372 | return 0; | 371 | return 0; |
373 | } | 372 | } |
374 | 373 | ||
375 | static struct platform_driver pxa2xx_i2s_driver = { | 374 | static struct platform_driver pxa2xx_i2s_driver = { |
376 | .probe = pxa2xx_i2s_probe, | 375 | .probe = pxa2xx_i2s_drv_probe, |
377 | .remove = __devexit_p(pxa2xx_i2s_remove), | 376 | .remove = __devexit_p(pxa2xx_i2s_drv_remove), |
378 | 377 | ||
379 | .driver = { | 378 | .driver = { |
380 | .name = "pxa2xx-i2s", | 379 | .name = "pxa2xx-i2s", |
diff --git a/sound/soc/pxa/pxa2xx-i2s.h b/sound/soc/pxa/pxa2xx-i2s.h index e2def441153e..070f3c6059fe 100644 --- a/sound/soc/pxa/pxa2xx-i2s.h +++ b/sound/soc/pxa/pxa2xx-i2s.h | |||
@@ -15,6 +15,4 @@ | |||
15 | /* I2S clock */ | 15 | /* I2S clock */ |
16 | #define PXA2XX_I2S_SYSCLK 0 | 16 | #define PXA2XX_I2S_SYSCLK 0 |
17 | 17 | ||
18 | extern struct snd_soc_dai pxa_i2s_dai; | ||
19 | |||
20 | #endif | 18 | #endif |
diff --git a/sound/soc/pxa/pxa2xx-pcm.c b/sound/soc/pxa/pxa2xx-pcm.c index adc7e6f15f93..5127044acfec 100644 --- a/sound/soc/pxa/pxa2xx-pcm.c +++ b/sound/soc/pxa/pxa2xx-pcm.c | |||
@@ -28,7 +28,7 @@ static int pxa2xx_pcm_hw_params(struct snd_pcm_substream *substream, | |||
28 | struct pxa2xx_pcm_dma_params *dma; | 28 | struct pxa2xx_pcm_dma_params *dma; |
29 | int ret; | 29 | int ret; |
30 | 30 | ||
31 | dma = snd_soc_dai_get_dma_data(rtd->dai->cpu_dai, substream); | 31 | dma = snd_soc_dai_get_dma_data(rtd->cpu_dai, substream); |
32 | 32 | ||
33 | /* return if this is a bufferless transfer e.g. | 33 | /* return if this is a bufferless transfer e.g. |
34 | * codec <--> BT codec or GSM modem -- lg FIXME */ | 34 | * codec <--> BT codec or GSM modem -- lg FIXME */ |
@@ -95,14 +95,14 @@ static int pxa2xx_soc_pcm_new(struct snd_card *card, struct snd_soc_dai *dai, | |||
95 | if (!card->dev->coherent_dma_mask) | 95 | if (!card->dev->coherent_dma_mask) |
96 | card->dev->coherent_dma_mask = DMA_BIT_MASK(32); | 96 | card->dev->coherent_dma_mask = DMA_BIT_MASK(32); |
97 | 97 | ||
98 | if (dai->playback.channels_min) { | 98 | if (dai->driver->playback.channels_min) { |
99 | ret = pxa2xx_pcm_preallocate_dma_buffer(pcm, | 99 | ret = pxa2xx_pcm_preallocate_dma_buffer(pcm, |
100 | SNDRV_PCM_STREAM_PLAYBACK); | 100 | SNDRV_PCM_STREAM_PLAYBACK); |
101 | if (ret) | 101 | if (ret) |
102 | goto out; | 102 | goto out; |
103 | } | 103 | } |
104 | 104 | ||
105 | if (dai->capture.channels_min) { | 105 | if (dai->driver->capture.channels_min) { |
106 | ret = pxa2xx_pcm_preallocate_dma_buffer(pcm, | 106 | ret = pxa2xx_pcm_preallocate_dma_buffer(pcm, |
107 | SNDRV_PCM_STREAM_CAPTURE); | 107 | SNDRV_PCM_STREAM_CAPTURE); |
108 | if (ret) | 108 | if (ret) |
@@ -112,25 +112,44 @@ static int pxa2xx_soc_pcm_new(struct snd_card *card, struct snd_soc_dai *dai, | |||
112 | return ret; | 112 | return ret; |
113 | } | 113 | } |
114 | 114 | ||
115 | struct snd_soc_platform pxa2xx_soc_platform = { | 115 | static struct snd_soc_platform_driver pxa2xx_soc_platform = { |
116 | .name = "pxa2xx-audio", | 116 | .ops = &pxa2xx_pcm_ops, |
117 | .pcm_ops = &pxa2xx_pcm_ops, | ||
118 | .pcm_new = pxa2xx_soc_pcm_new, | 117 | .pcm_new = pxa2xx_soc_pcm_new, |
119 | .pcm_free = pxa2xx_pcm_free_dma_buffers, | 118 | .pcm_free = pxa2xx_pcm_free_dma_buffers, |
120 | }; | 119 | }; |
121 | EXPORT_SYMBOL_GPL(pxa2xx_soc_platform); | ||
122 | 120 | ||
123 | static int __init pxa2xx_soc_platform_init(void) | 121 | static int __devinit pxa2xx_soc_platform_probe(struct platform_device *pdev) |
124 | { | 122 | { |
125 | return snd_soc_register_platform(&pxa2xx_soc_platform); | 123 | return snd_soc_register_platform(&pdev->dev, &pxa2xx_soc_platform); |
126 | } | 124 | } |
127 | module_init(pxa2xx_soc_platform_init); | ||
128 | 125 | ||
129 | static void __exit pxa2xx_soc_platform_exit(void) | 126 | static int __devexit pxa2xx_soc_platform_remove(struct platform_device *pdev) |
130 | { | 127 | { |
131 | snd_soc_unregister_platform(&pxa2xx_soc_platform); | 128 | snd_soc_unregister_platform(&pdev->dev); |
129 | return 0; | ||
130 | } | ||
131 | |||
132 | static struct platform_driver pxa_pcm_driver = { | ||
133 | .driver = { | ||
134 | .name = "pxa-pcm-audio", | ||
135 | .owner = THIS_MODULE, | ||
136 | }, | ||
137 | |||
138 | .probe = pxa2xx_soc_platform_probe, | ||
139 | .remove = __devexit_p(pxa2xx_soc_platform_remove), | ||
140 | }; | ||
141 | |||
142 | static int __init snd_pxa_pcm_init(void) | ||
143 | { | ||
144 | return platform_driver_register(&pxa_pcm_driver); | ||
145 | } | ||
146 | module_init(snd_pxa_pcm_init); | ||
147 | |||
148 | static void __exit snd_pxa_pcm_exit(void) | ||
149 | { | ||
150 | platform_driver_unregister(&pxa_pcm_driver); | ||
132 | } | 151 | } |
133 | module_exit(pxa2xx_soc_platform_exit); | 152 | module_exit(snd_pxa_pcm_exit); |
134 | 153 | ||
135 | MODULE_AUTHOR("Nicolas Pitre"); | 154 | MODULE_AUTHOR("Nicolas Pitre"); |
136 | MODULE_DESCRIPTION("Intel PXA2xx PCM DMA module"); | 155 | MODULE_DESCRIPTION("Intel PXA2xx PCM DMA module"); |
diff --git a/sound/soc/pxa/pxa2xx-pcm.h b/sound/soc/pxa/pxa2xx-pcm.h deleted file mode 100644 index 60c3b20aeeb4..000000000000 --- a/sound/soc/pxa/pxa2xx-pcm.h +++ /dev/null | |||
@@ -1,19 +0,0 @@ | |||
1 | /* | ||
2 | * linux/sound/arm/pxa2xx-pcm.h -- ALSA PCM interface for the Intel PXA2xx chip | ||
3 | * | ||
4 | * Author: Nicolas Pitre | ||
5 | * Created: Nov 30, 2004 | ||
6 | * Copyright: MontaVista Software, Inc. | ||
7 | * | ||
8 | * This program is free software; you can redistribute it and/or modify | ||
9 | * it under the terms of the GNU General Public License version 2 as | ||
10 | * published by the Free Software Foundation. | ||
11 | */ | ||
12 | |||
13 | #ifndef _PXA2XX_PCM_H | ||
14 | #define _PXA2XX_PCM_H | ||
15 | |||
16 | /* platform data */ | ||
17 | extern struct snd_soc_platform pxa2xx_soc_platform; | ||
18 | |||
19 | #endif | ||
diff --git a/sound/soc/pxa/raumfeld.c b/sound/soc/pxa/raumfeld.c index 7e3f41696c41..2cda82bc5d2e 100644 --- a/sound/soc/pxa/raumfeld.c +++ b/sound/soc/pxa/raumfeld.c | |||
@@ -26,9 +26,6 @@ | |||
26 | 26 | ||
27 | #include <asm/mach-types.h> | 27 | #include <asm/mach-types.h> |
28 | 28 | ||
29 | #include "../codecs/cs4270.h" | ||
30 | #include "../codecs/ak4104.h" | ||
31 | #include "pxa2xx-pcm.h" | ||
32 | #include "pxa-ssp.h" | 29 | #include "pxa-ssp.h" |
33 | 30 | ||
34 | #define GPIO_SPDIF_RESET (38) | 31 | #define GPIO_SPDIF_RESET (38) |
@@ -71,7 +68,7 @@ static void raumfeld_enable_audio(bool en) | |||
71 | static int raumfeld_cs4270_startup(struct snd_pcm_substream *substream) | 68 | static int raumfeld_cs4270_startup(struct snd_pcm_substream *substream) |
72 | { | 69 | { |
73 | struct snd_soc_pcm_runtime *rtd = substream->private_data; | 70 | struct snd_soc_pcm_runtime *rtd = substream->private_data; |
74 | struct snd_soc_dai *codec_dai = rtd->dai->codec_dai; | 71 | struct snd_soc_dai *codec_dai = rtd->codec_dai; |
75 | 72 | ||
76 | /* set freq to 0 to enable all possible codec sample rates */ | 73 | /* set freq to 0 to enable all possible codec sample rates */ |
77 | return snd_soc_dai_set_sysclk(codec_dai, 0, 0, 0); | 74 | return snd_soc_dai_set_sysclk(codec_dai, 0, 0, 0); |
@@ -80,7 +77,7 @@ static int raumfeld_cs4270_startup(struct snd_pcm_substream *substream) | |||
80 | static void raumfeld_cs4270_shutdown(struct snd_pcm_substream *substream) | 77 | static void raumfeld_cs4270_shutdown(struct snd_pcm_substream *substream) |
81 | { | 78 | { |
82 | struct snd_soc_pcm_runtime *rtd = substream->private_data; | 79 | struct snd_soc_pcm_runtime *rtd = substream->private_data; |
83 | struct snd_soc_dai *codec_dai = rtd->dai->codec_dai; | 80 | struct snd_soc_dai *codec_dai = rtd->codec_dai; |
84 | 81 | ||
85 | /* set freq to 0 to enable all possible codec sample rates */ | 82 | /* set freq to 0 to enable all possible codec sample rates */ |
86 | snd_soc_dai_set_sysclk(codec_dai, 0, 0, 0); | 83 | snd_soc_dai_set_sysclk(codec_dai, 0, 0, 0); |
@@ -90,8 +87,8 @@ static int raumfeld_cs4270_hw_params(struct snd_pcm_substream *substream, | |||
90 | struct snd_pcm_hw_params *params) | 87 | struct snd_pcm_hw_params *params) |
91 | { | 88 | { |
92 | struct snd_soc_pcm_runtime *rtd = substream->private_data; | 89 | struct snd_soc_pcm_runtime *rtd = substream->private_data; |
93 | struct snd_soc_dai *codec_dai = rtd->dai->codec_dai; | 90 | struct snd_soc_dai *codec_dai = rtd->codec_dai; |
94 | struct snd_soc_dai *cpu_dai = rtd->dai->cpu_dai; | 91 | struct snd_soc_dai *cpu_dai = rtd->cpu_dai; |
95 | unsigned int fmt, clk = 0; | 92 | unsigned int fmt, clk = 0; |
96 | int ret = 0; | 93 | int ret = 0; |
97 | 94 | ||
@@ -167,32 +164,14 @@ static int raumfeld_line_resume(struct platform_device *pdev) | |||
167 | return 0; | 164 | return 0; |
168 | } | 165 | } |
169 | 166 | ||
170 | static struct snd_soc_dai_link raumfeld_line_dai = { | ||
171 | .name = "CS4270", | ||
172 | .stream_name = "CS4270", | ||
173 | .cpu_dai = &pxa_ssp_dai[PXA_DAI_SSP1], | ||
174 | .codec_dai = &cs4270_dai, | ||
175 | .ops = &raumfeld_cs4270_ops, | ||
176 | }; | ||
177 | |||
178 | static struct snd_soc_card snd_soc_line_raumfeld = { | ||
179 | .name = "Raumfeld analog", | ||
180 | .platform = &pxa2xx_soc_platform, | ||
181 | .dai_link = &raumfeld_line_dai, | ||
182 | .suspend_post = raumfeld_line_suspend, | ||
183 | .resume_pre = raumfeld_line_resume, | ||
184 | .num_links = 1, | ||
185 | }; | ||
186 | |||
187 | |||
188 | /* AK4104 */ | 167 | /* AK4104 */ |
189 | 168 | ||
190 | static int raumfeld_ak4104_hw_params(struct snd_pcm_substream *substream, | 169 | static int raumfeld_ak4104_hw_params(struct snd_pcm_substream *substream, |
191 | struct snd_pcm_hw_params *params) | 170 | struct snd_pcm_hw_params *params) |
192 | { | 171 | { |
193 | struct snd_soc_pcm_runtime *rtd = substream->private_data; | 172 | struct snd_soc_pcm_runtime *rtd = substream->private_data; |
194 | struct snd_soc_dai *codec_dai = rtd->dai->codec_dai; | 173 | struct snd_soc_dai *codec_dai = rtd->codec_dai; |
195 | struct snd_soc_dai *cpu_dai = rtd->dai->cpu_dai; | 174 | struct snd_soc_dai *cpu_dai = rtd->cpu_dai; |
196 | int fmt, ret = 0, clk = 0; | 175 | int fmt, ret = 0, clk = 0; |
197 | 176 | ||
198 | switch (params_rate(params)) { | 177 | switch (params_rate(params)) { |
@@ -247,34 +226,35 @@ static struct snd_soc_ops raumfeld_ak4104_ops = { | |||
247 | .hw_params = raumfeld_ak4104_hw_params, | 226 | .hw_params = raumfeld_ak4104_hw_params, |
248 | }; | 227 | }; |
249 | 228 | ||
250 | static struct snd_soc_dai_link raumfeld_spdif_dai = { | 229 | static struct snd_soc_dai_link raumfeld_dai[] = { |
230 | { | ||
251 | .name = "ak4104", | 231 | .name = "ak4104", |
252 | .stream_name = "Playback", | 232 | .stream_name = "Playback", |
253 | .cpu_dai = &pxa_ssp_dai[PXA_DAI_SSP2], | 233 | .cpu_dai_name = "pxa-ssp-dai.1", |
254 | .codec_dai = &ak4104_dai, | 234 | .codec_dai_name = "ak4104-hifi", |
235 | .platform_name = "pxa-pcm-audio", | ||
255 | .ops = &raumfeld_ak4104_ops, | 236 | .ops = &raumfeld_ak4104_ops, |
256 | }; | 237 | .codec_name = "ak4104-codec.0", |
257 | 238 | }, | |
258 | static struct snd_soc_card snd_soc_spdif_raumfeld = { | 239 | { |
259 | .name = "Raumfeld S/PDIF", | 240 | .name = "CS4270", |
260 | .platform = &pxa2xx_soc_platform, | 241 | .stream_name = "CS4270", |
261 | .dai_link = &raumfeld_spdif_dai, | 242 | .cpu_dai_name = "pxa-ssp-dai.0", |
262 | .num_links = 1 | 243 | .platform_name = "pxa-pcm-audio", |
263 | }; | 244 | .codec_dai_name = "cs4270-hifi", |
264 | 245 | .codec_name = "cs4270-codec.0-0048", | |
265 | /* raumfeld_audio audio subsystem */ | 246 | .ops = &raumfeld_cs4270_ops, |
266 | static struct snd_soc_device raumfeld_line_devdata = { | 247 | },}; |
267 | .card = &snd_soc_line_raumfeld, | ||
268 | .codec_dev = &soc_codec_device_cs4270, | ||
269 | }; | ||
270 | 248 | ||
271 | static struct snd_soc_device raumfeld_spdif_devdata = { | 249 | static struct snd_soc_card snd_soc_raumfeld = { |
272 | .card = &snd_soc_spdif_raumfeld, | 250 | .name = "Raumfeld", |
273 | .codec_dev = &soc_codec_device_ak4104, | 251 | .dai_link = raumfeld_dai, |
252 | .suspend_post = raumfeld_line_suspend, | ||
253 | .resume_pre = raumfeld_line_resume, | ||
254 | .num_links = ARRAY_SIZE(raumfeld_dai), | ||
274 | }; | 255 | }; |
275 | 256 | ||
276 | static struct platform_device *raumfeld_audio_line_device; | 257 | static struct platform_device *raumfeld_audio_device; |
277 | static struct platform_device *raumfeld_audio_spdif_device; | ||
278 | 258 | ||
279 | static int __init raumfeld_audio_init(void) | 259 | static int __init raumfeld_audio_init(void) |
280 | { | 260 | { |
@@ -292,38 +272,19 @@ static int __init raumfeld_audio_init(void) | |||
292 | 272 | ||
293 | set_max9485_clk(MAX9485_MCLK_FREQ_122880); | 273 | set_max9485_clk(MAX9485_MCLK_FREQ_122880); |
294 | 274 | ||
295 | /* LINE */ | 275 | /* Register LINE and SPDIF */ |
296 | raumfeld_audio_line_device = platform_device_alloc("soc-audio", 0); | 276 | raumfeld_audio_device = platform_device_alloc("soc-audio", 0); |
297 | if (!raumfeld_audio_line_device) | 277 | if (!raumfeld_audio_device) |
298 | return -ENOMEM; | 278 | return -ENOMEM; |
299 | 279 | ||
300 | platform_set_drvdata(raumfeld_audio_line_device, | 280 | platform_set_drvdata(raumfeld_audio_device, |
301 | &raumfeld_line_devdata); | 281 | &snd_soc_raumfeld); |
302 | raumfeld_line_devdata.dev = &raumfeld_audio_line_device->dev; | 282 | ret = platform_device_add(raumfeld_audio_device); |
303 | ret = platform_device_add(raumfeld_audio_line_device); | ||
304 | if (ret) | ||
305 | platform_device_put(raumfeld_audio_line_device); | ||
306 | 283 | ||
307 | /* no S/PDIF on Speakers */ | 284 | /* no S/PDIF on Speakers */ |
308 | if (machine_is_raumfeld_speaker()) | 285 | if (machine_is_raumfeld_speaker()) |
309 | return ret; | 286 | return ret; |
310 | 287 | ||
311 | /* S/PDIF */ | ||
312 | raumfeld_audio_spdif_device = platform_device_alloc("soc-audio", 1); | ||
313 | if (!raumfeld_audio_spdif_device) { | ||
314 | platform_device_put(raumfeld_audio_line_device); | ||
315 | return -ENOMEM; | ||
316 | } | ||
317 | |||
318 | platform_set_drvdata(raumfeld_audio_spdif_device, | ||
319 | &raumfeld_spdif_devdata); | ||
320 | raumfeld_spdif_devdata.dev = &raumfeld_audio_spdif_device->dev; | ||
321 | ret = platform_device_add(raumfeld_audio_spdif_device); | ||
322 | if (ret) { | ||
323 | platform_device_put(raumfeld_audio_line_device); | ||
324 | platform_device_put(raumfeld_audio_spdif_device); | ||
325 | } | ||
326 | |||
327 | raumfeld_enable_audio(true); | 288 | raumfeld_enable_audio(true); |
328 | 289 | ||
329 | return ret; | 290 | return ret; |
@@ -333,10 +294,7 @@ static void __exit raumfeld_audio_exit(void) | |||
333 | { | 294 | { |
334 | raumfeld_enable_audio(false); | 295 | raumfeld_enable_audio(false); |
335 | 296 | ||
336 | platform_device_unregister(raumfeld_audio_line_device); | 297 | platform_device_unregister(raumfeld_audio_device); |
337 | |||
338 | if (machine_is_raumfeld_connector()) | ||
339 | platform_device_unregister(raumfeld_audio_spdif_device); | ||
340 | 298 | ||
341 | i2c_unregister_device(max9486_client); | 299 | i2c_unregister_device(max9486_client); |
342 | 300 | ||
diff --git a/sound/soc/pxa/spitz.c b/sound/soc/pxa/spitz.c index 1941a357e8c4..f470f360f4dd 100644 --- a/sound/soc/pxa/spitz.c +++ b/sound/soc/pxa/spitz.c | |||
@@ -28,7 +28,6 @@ | |||
28 | #include <asm/mach-types.h> | 28 | #include <asm/mach-types.h> |
29 | #include <mach/spitz.h> | 29 | #include <mach/spitz.h> |
30 | #include "../codecs/wm8750.h" | 30 | #include "../codecs/wm8750.h" |
31 | #include "pxa2xx-pcm.h" | ||
32 | #include "pxa2xx-i2s.h" | 31 | #include "pxa2xx-i2s.h" |
33 | 32 | ||
34 | #define SPITZ_HP 0 | 33 | #define SPITZ_HP 0 |
@@ -107,7 +106,7 @@ static void spitz_ext_control(struct snd_soc_codec *codec) | |||
107 | static int spitz_startup(struct snd_pcm_substream *substream) | 106 | static int spitz_startup(struct snd_pcm_substream *substream) |
108 | { | 107 | { |
109 | struct snd_soc_pcm_runtime *rtd = substream->private_data; | 108 | struct snd_soc_pcm_runtime *rtd = substream->private_data; |
110 | struct snd_soc_codec *codec = rtd->socdev->card->codec; | 109 | struct snd_soc_codec *codec = rtd->codec; |
111 | 110 | ||
112 | /* check the jack status at stream startup */ | 111 | /* check the jack status at stream startup */ |
113 | spitz_ext_control(codec); | 112 | spitz_ext_control(codec); |
@@ -118,8 +117,8 @@ static int spitz_hw_params(struct snd_pcm_substream *substream, | |||
118 | struct snd_pcm_hw_params *params) | 117 | struct snd_pcm_hw_params *params) |
119 | { | 118 | { |
120 | struct snd_soc_pcm_runtime *rtd = substream->private_data; | 119 | struct snd_soc_pcm_runtime *rtd = substream->private_data; |
121 | struct snd_soc_dai *codec_dai = rtd->dai->codec_dai; | 120 | struct snd_soc_dai *codec_dai = rtd->codec_dai; |
122 | struct snd_soc_dai *cpu_dai = rtd->dai->cpu_dai; | 121 | struct snd_soc_dai *cpu_dai = rtd->cpu_dai; |
123 | unsigned int clk = 0; | 122 | unsigned int clk = 0; |
124 | int ret = 0; | 123 | int ret = 0; |
125 | 124 | ||
@@ -274,8 +273,9 @@ static const struct snd_kcontrol_new wm8750_spitz_controls[] = { | |||
274 | /* | 273 | /* |
275 | * Logic for a wm8750 as connected on a Sharp SL-Cxx00 Device | 274 | * Logic for a wm8750 as connected on a Sharp SL-Cxx00 Device |
276 | */ | 275 | */ |
277 | static int spitz_wm8750_init(struct snd_soc_codec *codec) | 276 | static int spitz_wm8750_init(struct snd_soc_pcm_runtime *rtd) |
278 | { | 277 | { |
278 | struct snd_soc_codec *codec = rtd->codec; | ||
279 | int err; | 279 | int err; |
280 | 280 | ||
281 | /* NC codec pins */ | 281 | /* NC codec pins */ |
@@ -308,8 +308,10 @@ static int spitz_wm8750_init(struct snd_soc_codec *codec) | |||
308 | static struct snd_soc_dai_link spitz_dai = { | 308 | static struct snd_soc_dai_link spitz_dai = { |
309 | .name = "wm8750", | 309 | .name = "wm8750", |
310 | .stream_name = "WM8750", | 310 | .stream_name = "WM8750", |
311 | .cpu_dai = &pxa_i2s_dai, | 311 | .cpu_dai_name = "pxa-is2", |
312 | .codec_dai = &wm8750_dai, | 312 | .codec_dai_name = "wm8750-hifi", |
313 | .platform_name = "pxa-pcm-audio", | ||
314 | .codec_name = "wm8750-codec.0-001a", | ||
313 | .init = spitz_wm8750_init, | 315 | .init = spitz_wm8750_init, |
314 | .ops = &spitz_ops, | 316 | .ops = &spitz_ops, |
315 | }; | 317 | }; |
@@ -317,49 +319,10 @@ static struct snd_soc_dai_link spitz_dai = { | |||
317 | /* spitz audio machine driver */ | 319 | /* spitz audio machine driver */ |
318 | static struct snd_soc_card snd_soc_spitz = { | 320 | static struct snd_soc_card snd_soc_spitz = { |
319 | .name = "Spitz", | 321 | .name = "Spitz", |
320 | .platform = &pxa2xx_soc_platform, | ||
321 | .dai_link = &spitz_dai, | 322 | .dai_link = &spitz_dai, |
322 | .num_links = 1, | 323 | .num_links = 1, |
323 | }; | 324 | }; |
324 | 325 | ||
325 | /* spitz audio subsystem */ | ||
326 | static struct snd_soc_device spitz_snd_devdata = { | ||
327 | .card = &snd_soc_spitz, | ||
328 | .codec_dev = &soc_codec_dev_wm8750, | ||
329 | }; | ||
330 | |||
331 | /* | ||
332 | * FIXME: This is a temporary bodge to avoid cross-tree merge issues. | ||
333 | * New drivers should register the wm8750 I2C device in the machine | ||
334 | * setup code (under arch/arm for ARM systems). | ||
335 | */ | ||
336 | static int wm8750_i2c_register(void) | ||
337 | { | ||
338 | struct i2c_board_info info; | ||
339 | struct i2c_adapter *adapter; | ||
340 | struct i2c_client *client; | ||
341 | |||
342 | memset(&info, 0, sizeof(struct i2c_board_info)); | ||
343 | info.addr = 0x1b; | ||
344 | strlcpy(info.type, "wm8750", I2C_NAME_SIZE); | ||
345 | |||
346 | adapter = i2c_get_adapter(0); | ||
347 | if (!adapter) { | ||
348 | printk(KERN_ERR "can't get i2c adapter 0\n"); | ||
349 | return -ENODEV; | ||
350 | } | ||
351 | |||
352 | client = i2c_new_device(adapter, &info); | ||
353 | i2c_put_adapter(adapter); | ||
354 | if (!client) { | ||
355 | printk(KERN_ERR "can't add i2c device at 0x%x\n", | ||
356 | (unsigned int)info.addr); | ||
357 | return -ENODEV; | ||
358 | } | ||
359 | |||
360 | return 0; | ||
361 | } | ||
362 | |||
363 | static struct platform_device *spitz_snd_device; | 326 | static struct platform_device *spitz_snd_device; |
364 | 327 | ||
365 | static int __init spitz_init(void) | 328 | static int __init spitz_init(void) |
@@ -369,16 +332,11 @@ static int __init spitz_init(void) | |||
369 | if (!(machine_is_spitz() || machine_is_borzoi() || machine_is_akita())) | 332 | if (!(machine_is_spitz() || machine_is_borzoi() || machine_is_akita())) |
370 | return -ENODEV; | 333 | return -ENODEV; |
371 | 334 | ||
372 | ret = wm8750_i2c_setup(); | ||
373 | if (ret != 0) | ||
374 | return ret; | ||
375 | |||
376 | spitz_snd_device = platform_device_alloc("soc-audio", -1); | 335 | spitz_snd_device = platform_device_alloc("soc-audio", -1); |
377 | if (!spitz_snd_device) | 336 | if (!spitz_snd_device) |
378 | return -ENOMEM; | 337 | return -ENOMEM; |
379 | 338 | ||
380 | platform_set_drvdata(spitz_snd_device, &spitz_snd_devdata); | 339 | platform_set_drvdata(spitz_snd_device, &snd_soc_spitz); |
381 | spitz_snd_devdata.dev = &spitz_snd_device->dev; | ||
382 | ret = platform_device_add(spitz_snd_device); | 340 | ret = platform_device_add(spitz_snd_device); |
383 | 341 | ||
384 | if (ret) | 342 | if (ret) |
diff --git a/sound/soc/pxa/tosa.c b/sound/soc/pxa/tosa.c index dbbd3e9d1637..a3bfb2e8b70f 100644 --- a/sound/soc/pxa/tosa.c +++ b/sound/soc/pxa/tosa.c | |||
@@ -33,7 +33,6 @@ | |||
33 | #include <mach/audio.h> | 33 | #include <mach/audio.h> |
34 | 34 | ||
35 | #include "../codecs/wm9712.h" | 35 | #include "../codecs/wm9712.h" |
36 | #include "pxa2xx-pcm.h" | ||
37 | #include "pxa2xx-ac97.h" | 36 | #include "pxa2xx-ac97.h" |
38 | 37 | ||
39 | static struct snd_soc_card tosa; | 38 | static struct snd_soc_card tosa; |
@@ -80,7 +79,7 @@ static void tosa_ext_control(struct snd_soc_codec *codec) | |||
80 | static int tosa_startup(struct snd_pcm_substream *substream) | 79 | static int tosa_startup(struct snd_pcm_substream *substream) |
81 | { | 80 | { |
82 | struct snd_soc_pcm_runtime *rtd = substream->private_data; | 81 | struct snd_soc_pcm_runtime *rtd = substream->private_data; |
83 | struct snd_soc_codec *codec = rtd->socdev->card->codec; | 82 | struct snd_soc_codec *codec = rtd->card->codec; |
84 | 83 | ||
85 | /* check the jack status at stream startup */ | 84 | /* check the jack status at stream startup */ |
86 | tosa_ext_control(codec); | 85 | tosa_ext_control(codec); |
@@ -184,8 +183,9 @@ static const struct snd_kcontrol_new tosa_controls[] = { | |||
184 | tosa_set_spk), | 183 | tosa_set_spk), |
185 | }; | 184 | }; |
186 | 185 | ||
187 | static int tosa_ac97_init(struct snd_soc_codec *codec) | 186 | static int tosa_ac97_init(struct snd_soc_pcm_runtime *rtd) |
188 | { | 187 | { |
188 | struct snd_soc_codec *codec = rtd->codec; | ||
189 | int err; | 189 | int err; |
190 | 190 | ||
191 | snd_soc_dapm_nc_pin(codec, "OUT3"); | 191 | snd_soc_dapm_nc_pin(codec, "OUT3"); |
@@ -212,16 +212,20 @@ static struct snd_soc_dai_link tosa_dai[] = { | |||
212 | { | 212 | { |
213 | .name = "AC97", | 213 | .name = "AC97", |
214 | .stream_name = "AC97 HiFi", | 214 | .stream_name = "AC97 HiFi", |
215 | .cpu_dai = &pxa_ac97_dai[PXA2XX_DAI_AC97_HIFI], | 215 | .cpu_dai_name = "pxa-ac97.0", |
216 | .codec_dai = &wm9712_dai[WM9712_DAI_AC97_HIFI], | 216 | .codec_dai_name = "wm9712-hifi", |
217 | .platform_name = "pxa-pcm-audio", | ||
218 | .codec_name = "wm9712-codec", | ||
217 | .init = tosa_ac97_init, | 219 | .init = tosa_ac97_init, |
218 | .ops = &tosa_ops, | 220 | .ops = &tosa_ops, |
219 | }, | 221 | }, |
220 | { | 222 | { |
221 | .name = "AC97 Aux", | 223 | .name = "AC97 Aux", |
222 | .stream_name = "AC97 Aux", | 224 | .stream_name = "AC97 Aux", |
223 | .cpu_dai = &pxa_ac97_dai[PXA2XX_DAI_AC97_AUX], | 225 | .cpu_dai_name = "pxa-ac97.1", |
224 | .codec_dai = &wm9712_dai[WM9712_DAI_AC97_AUX], | 226 | .codec_dai_name = "wm9712-aux", |
227 | .platform_name = "pxa-pcm-audio", | ||
228 | .codec_name = "wm9712-codec", | ||
225 | .ops = &tosa_ops, | 229 | .ops = &tosa_ops, |
226 | }, | 230 | }, |
227 | }; | 231 | }; |
@@ -248,18 +252,12 @@ static int tosa_remove(struct platform_device *dev) | |||
248 | 252 | ||
249 | static struct snd_soc_card tosa = { | 253 | static struct snd_soc_card tosa = { |
250 | .name = "Tosa", | 254 | .name = "Tosa", |
251 | .platform = &pxa2xx_soc_platform, | ||
252 | .dai_link = tosa_dai, | 255 | .dai_link = tosa_dai, |
253 | .num_links = ARRAY_SIZE(tosa_dai), | 256 | .num_links = ARRAY_SIZE(tosa_dai), |
254 | .probe = tosa_probe, | 257 | .probe = tosa_probe, |
255 | .remove = tosa_remove, | 258 | .remove = tosa_remove, |
256 | }; | 259 | }; |
257 | 260 | ||
258 | static struct snd_soc_device tosa_snd_devdata = { | ||
259 | .card = &tosa, | ||
260 | .codec_dev = &soc_codec_dev_wm9712, | ||
261 | }; | ||
262 | |||
263 | static struct platform_device *tosa_snd_device; | 261 | static struct platform_device *tosa_snd_device; |
264 | 262 | ||
265 | static int __init tosa_init(void) | 263 | static int __init tosa_init(void) |
@@ -275,8 +273,7 @@ static int __init tosa_init(void) | |||
275 | goto err_alloc; | 273 | goto err_alloc; |
276 | } | 274 | } |
277 | 275 | ||
278 | platform_set_drvdata(tosa_snd_device, &tosa_snd_devdata); | 276 | platform_set_drvdata(tosa_snd_device, &tosa); |
279 | tosa_snd_devdata.dev = &tosa_snd_device->dev; | ||
280 | ret = platform_device_add(tosa_snd_device); | 277 | ret = platform_device_add(tosa_snd_device); |
281 | 278 | ||
282 | if (!ret) | 279 | if (!ret) |
diff --git a/sound/soc/pxa/z2.c b/sound/soc/pxa/z2.c index 4e4d2fa8ddc5..704f74b56ab6 100644 --- a/sound/soc/pxa/z2.c +++ b/sound/soc/pxa/z2.c | |||
@@ -30,7 +30,6 @@ | |||
30 | #include <mach/z2.h> | 30 | #include <mach/z2.h> |
31 | 31 | ||
32 | #include "../codecs/wm8750.h" | 32 | #include "../codecs/wm8750.h" |
33 | #include "pxa2xx-pcm.h" | ||
34 | #include "pxa2xx-i2s.h" | 33 | #include "pxa2xx-i2s.h" |
35 | 34 | ||
36 | static struct snd_soc_card snd_soc_z2; | 35 | static struct snd_soc_card snd_soc_z2; |
@@ -39,8 +38,8 @@ static int z2_hw_params(struct snd_pcm_substream *substream, | |||
39 | struct snd_pcm_hw_params *params) | 38 | struct snd_pcm_hw_params *params) |
40 | { | 39 | { |
41 | struct snd_soc_pcm_runtime *rtd = substream->private_data; | 40 | struct snd_soc_pcm_runtime *rtd = substream->private_data; |
42 | struct snd_soc_dai *codec_dai = rtd->dai->codec_dai; | 41 | struct snd_soc_dai *codec_dai = rtd->codec_dai; |
43 | struct snd_soc_dai *cpu_dai = rtd->dai->cpu_dai; | 42 | struct snd_soc_dai *cpu_dai = rtd->cpu_dai; |
44 | unsigned int clk = 0; | 43 | unsigned int clk = 0; |
45 | int ret = 0; | 44 | int ret = 0; |
46 | 45 | ||
@@ -138,8 +137,9 @@ static const struct snd_soc_dapm_route audio_map[] = { | |||
138 | /* | 137 | /* |
139 | * Logic for a wm8750 as connected on a Z2 Device | 138 | * Logic for a wm8750 as connected on a Z2 Device |
140 | */ | 139 | */ |
141 | static int z2_wm8750_init(struct snd_soc_codec *codec) | 140 | static int z2_wm8750_init(struct snd_soc_pcm_runtime *rtd) |
142 | { | 141 | { |
142 | struct snd_soc_codec *codec = rtd->codec; | ||
143 | int ret; | 143 | int ret; |
144 | 144 | ||
145 | /* NC codec pins */ | 145 | /* NC codec pins */ |
@@ -160,7 +160,7 @@ static int z2_wm8750_init(struct snd_soc_codec *codec) | |||
160 | goto err; | 160 | goto err; |
161 | 161 | ||
162 | /* Jack detection API stuff */ | 162 | /* Jack detection API stuff */ |
163 | ret = snd_soc_jack_new(&snd_soc_z2, "Headset Jack", SND_JACK_HEADSET, | 163 | ret = snd_soc_jack_new(codec, "Headset Jack", SND_JACK_HEADSET, |
164 | &hs_jack); | 164 | &hs_jack); |
165 | if (ret) | 165 | if (ret) |
166 | goto err; | 166 | goto err; |
@@ -189,8 +189,10 @@ static struct snd_soc_ops z2_ops = { | |||
189 | static struct snd_soc_dai_link z2_dai = { | 189 | static struct snd_soc_dai_link z2_dai = { |
190 | .name = "wm8750", | 190 | .name = "wm8750", |
191 | .stream_name = "WM8750", | 191 | .stream_name = "WM8750", |
192 | .cpu_dai = &pxa_i2s_dai, | 192 | .cpu_dai_name = "pxa-i2s", |
193 | .codec_dai = &wm8750_dai, | 193 | .codec_dai_name = "wm8750-hifi", |
194 | .platform_name = "pxa-pcm-audio", | ||
195 | .codec_name = "wm8750-codec.0-001a", | ||
194 | .init = z2_wm8750_init, | 196 | .init = z2_wm8750_init, |
195 | .ops = &z2_ops, | 197 | .ops = &z2_ops, |
196 | }; | 198 | }; |
@@ -198,17 +200,10 @@ static struct snd_soc_dai_link z2_dai = { | |||
198 | /* z2 audio machine driver */ | 200 | /* z2 audio machine driver */ |
199 | static struct snd_soc_card snd_soc_z2 = { | 201 | static struct snd_soc_card snd_soc_z2 = { |
200 | .name = "Z2", | 202 | .name = "Z2", |
201 | .platform = &pxa2xx_soc_platform, | ||
202 | .dai_link = &z2_dai, | 203 | .dai_link = &z2_dai, |
203 | .num_links = 1, | 204 | .num_links = 1, |
204 | }; | 205 | }; |
205 | 206 | ||
206 | /* z2 audio subsystem */ | ||
207 | static struct snd_soc_device z2_snd_devdata = { | ||
208 | .card = &snd_soc_z2, | ||
209 | .codec_dev = &soc_codec_dev_wm8750, | ||
210 | }; | ||
211 | |||
212 | static struct platform_device *z2_snd_device; | 207 | static struct platform_device *z2_snd_device; |
213 | 208 | ||
214 | static int __init z2_init(void) | 209 | static int __init z2_init(void) |
@@ -222,8 +217,7 @@ static int __init z2_init(void) | |||
222 | if (!z2_snd_device) | 217 | if (!z2_snd_device) |
223 | return -ENOMEM; | 218 | return -ENOMEM; |
224 | 219 | ||
225 | platform_set_drvdata(z2_snd_device, &z2_snd_devdata); | 220 | platform_set_drvdata(z2_snd_device, &snd_soc_z2); |
226 | z2_snd_devdata.dev = &z2_snd_device->dev; | ||
227 | ret = platform_device_add(z2_snd_device); | 221 | ret = platform_device_add(z2_snd_device); |
228 | 222 | ||
229 | if (ret) | 223 | if (ret) |
diff --git a/sound/soc/pxa/zylonite.c b/sound/soc/pxa/zylonite.c index dd678ae24398..d27e05af7759 100644 --- a/sound/soc/pxa/zylonite.c +++ b/sound/soc/pxa/zylonite.c | |||
@@ -23,7 +23,6 @@ | |||
23 | #include <sound/soc-dapm.h> | 23 | #include <sound/soc-dapm.h> |
24 | 24 | ||
25 | #include "../codecs/wm9713.h" | 25 | #include "../codecs/wm9713.h" |
26 | #include "pxa2xx-pcm.h" | ||
27 | #include "pxa2xx-ac97.h" | 26 | #include "pxa2xx-ac97.h" |
28 | #include "pxa-ssp.h" | 27 | #include "pxa-ssp.h" |
29 | 28 | ||
@@ -71,10 +70,12 @@ static const struct snd_soc_dapm_route audio_map[] = { | |||
71 | { "Multiactor", NULL, "SPKR" }, | 70 | { "Multiactor", NULL, "SPKR" }, |
72 | }; | 71 | }; |
73 | 72 | ||
74 | static int zylonite_wm9713_init(struct snd_soc_codec *codec) | 73 | static int zylonite_wm9713_init(struct snd_soc_pcm_runtime *rtd) |
75 | { | 74 | { |
75 | struct snd_soc_codec *codec = rtd->codec; | ||
76 | |||
76 | if (clk_pout) | 77 | if (clk_pout) |
77 | snd_soc_dai_set_pll(&codec->dai[0], 0, 0, | 78 | snd_soc_dai_set_pll(rtd->codec_dai, 0, 0, |
78 | clk_get_rate(pout), 0); | 79 | clk_get_rate(pout), 0); |
79 | 80 | ||
80 | snd_soc_dapm_new_controls(codec, zylonite_dapm_widgets, | 81 | snd_soc_dapm_new_controls(codec, zylonite_dapm_widgets, |
@@ -94,8 +95,8 @@ static int zylonite_voice_hw_params(struct snd_pcm_substream *substream, | |||
94 | struct snd_pcm_hw_params *params) | 95 | struct snd_pcm_hw_params *params) |
95 | { | 96 | { |
96 | struct snd_soc_pcm_runtime *rtd = substream->private_data; | 97 | struct snd_soc_pcm_runtime *rtd = substream->private_data; |
97 | struct snd_soc_dai *codec_dai = rtd->dai->codec_dai; | 98 | struct snd_soc_dai *codec_dai = rtd->codec_dai; |
98 | struct snd_soc_dai *cpu_dai = rtd->dai->cpu_dai; | 99 | struct snd_soc_dai *cpu_dai = rtd->cpu_dai; |
99 | unsigned int pll_out = 0; | 100 | unsigned int pll_out = 0; |
100 | unsigned int wm9713_div = 0; | 101 | unsigned int wm9713_div = 0; |
101 | int ret = 0; | 102 | int ret = 0; |
@@ -163,21 +164,27 @@ static struct snd_soc_dai_link zylonite_dai[] = { | |||
163 | { | 164 | { |
164 | .name = "AC97", | 165 | .name = "AC97", |
165 | .stream_name = "AC97 HiFi", | 166 | .stream_name = "AC97 HiFi", |
166 | .cpu_dai = &pxa_ac97_dai[PXA2XX_DAI_AC97_HIFI], | 167 | .codec_name = "wm9713-codec", |
167 | .codec_dai = &wm9713_dai[WM9713_DAI_AC97_HIFI], | 168 | .platform_name = "pxa-pcm-audio", |
169 | .cpu_dai_name = "pxa-ac97.0", | ||
170 | .codec_name = "wm9713-hifi", | ||
168 | .init = zylonite_wm9713_init, | 171 | .init = zylonite_wm9713_init, |
169 | }, | 172 | }, |
170 | { | 173 | { |
171 | .name = "AC97 Aux", | 174 | .name = "AC97 Aux", |
172 | .stream_name = "AC97 Aux", | 175 | .stream_name = "AC97 Aux", |
173 | .cpu_dai = &pxa_ac97_dai[PXA2XX_DAI_AC97_AUX], | 176 | .codec_name = "wm9713-codec", |
174 | .codec_dai = &wm9713_dai[WM9713_DAI_AC97_AUX], | 177 | .platform_name = "pxa-pcm-audio", |
178 | .cpu_dai_name = "pxa-ac97.1", | ||
179 | .codec_name = "wm9713-aux", | ||
175 | }, | 180 | }, |
176 | { | 181 | { |
177 | .name = "WM9713 Voice", | 182 | .name = "WM9713 Voice", |
178 | .stream_name = "WM9713 Voice", | 183 | .stream_name = "WM9713 Voice", |
179 | .cpu_dai = &pxa_ssp_dai[PXA_DAI_SSP3], | 184 | .codec_name = "wm9713-codec", |
180 | .codec_dai = &wm9713_dai[WM9713_DAI_PCM_VOICE], | 185 | .platform_name = "pxa-pcm-audio", |
186 | .cpu_dai_name = "pxa-ssp-dai.2", | ||
187 | .codec_name = "wm9713-voice", | ||
181 | .ops = &zylonite_voice_ops, | 188 | .ops = &zylonite_voice_ops, |
182 | }, | 189 | }, |
183 | }; | 190 | }; |
@@ -248,14 +255,9 @@ static struct snd_soc_card zylonite = { | |||
248 | .remove = &zylonite_remove, | 255 | .remove = &zylonite_remove, |
249 | .suspend_post = &zylonite_suspend_post, | 256 | .suspend_post = &zylonite_suspend_post, |
250 | .resume_pre = &zylonite_resume_pre, | 257 | .resume_pre = &zylonite_resume_pre, |
251 | .platform = &pxa2xx_soc_platform, | ||
252 | .dai_link = zylonite_dai, | 258 | .dai_link = zylonite_dai, |
253 | .num_links = ARRAY_SIZE(zylonite_dai), | 259 | .num_links = ARRAY_SIZE(zylonite_dai), |
254 | }; | 260 | .owner = THIS_MODULE, |
255 | |||
256 | static struct snd_soc_device zylonite_snd_ac97_devdata = { | ||
257 | .card = &zylonite, | ||
258 | .codec_dev = &soc_codec_dev_wm9713, | ||
259 | }; | 261 | }; |
260 | 262 | ||
261 | static struct platform_device *zylonite_snd_ac97_device; | 263 | static struct platform_device *zylonite_snd_ac97_device; |
@@ -268,9 +270,7 @@ static int __init zylonite_init(void) | |||
268 | if (!zylonite_snd_ac97_device) | 270 | if (!zylonite_snd_ac97_device) |
269 | return -ENOMEM; | 271 | return -ENOMEM; |
270 | 272 | ||
271 | platform_set_drvdata(zylonite_snd_ac97_device, | 273 | platform_set_drvdata(zylonite_snd_ac97_device, &zylonite); |
272 | &zylonite_snd_ac97_devdata); | ||
273 | zylonite_snd_ac97_devdata.dev = &zylonite_snd_ac97_device->dev; | ||
274 | 274 | ||
275 | ret = platform_device_add(zylonite_snd_ac97_device); | 275 | ret = platform_device_add(zylonite_snd_ac97_device); |
276 | if (ret != 0) | 276 | if (ret != 0) |
diff --git a/sound/soc/s3c24xx/Kconfig b/sound/soc/s3c24xx/Kconfig index 213963ac3c28..1cdc37bd58f4 100644 --- a/sound/soc/s3c24xx/Kconfig +++ b/sound/soc/s3c24xx/Kconfig | |||
@@ -131,3 +131,21 @@ config SND_S3C64XX_SOC_SMARTQ | |||
131 | depends on SND_S3C24XX_SOC && MACH_SMARTQ | 131 | depends on SND_S3C24XX_SOC && MACH_SMARTQ |
132 | select SND_S3C64XX_SOC_I2S | 132 | select SND_S3C64XX_SOC_I2S |
133 | select SND_SOC_WM8750 | 133 | select SND_SOC_WM8750 |
134 | |||
135 | config SND_S5PC110_SOC_AQUILA_WM8994 | ||
136 | tristate "SoC I2S Audio support for AQUILA - WM8994" | ||
137 | depends on SND_S3C24XX_SOC && MACH_AQUILA | ||
138 | select SND_S3C64XX_SOC_I2S_V4 | ||
139 | select SND_SOC_WM8994 | ||
140 | help | ||
141 | Say Y if you want to add support for SoC audio on aquila | ||
142 | with the WM8994. | ||
143 | |||
144 | config SND_S5PV210_SOC_GONI_WM8994 | ||
145 | tristate "SoC I2S Audio support for GONI - WM8994" | ||
146 | depends on SND_S3C24XX_SOC && MACH_GONI | ||
147 | select SND_S3C64XX_SOC_I2S_V4 | ||
148 | select SND_SOC_WM8994 | ||
149 | help | ||
150 | Say Y if you want to add support for SoC audio on goni | ||
151 | with the WM8994. | ||
diff --git a/sound/soc/s3c24xx/Makefile b/sound/soc/s3c24xx/Makefile index 50172c385d90..47ed6d70b90b 100644 --- a/sound/soc/s3c24xx/Makefile +++ b/sound/soc/s3c24xx/Makefile | |||
@@ -30,6 +30,8 @@ snd-soc-s3c24xx-simtec-tlv320aic23-objs := s3c24xx_simtec_tlv320aic23.o | |||
30 | snd-soc-smdk64xx-wm8580-objs := smdk64xx_wm8580.o | 30 | snd-soc-smdk64xx-wm8580-objs := smdk64xx_wm8580.o |
31 | snd-soc-smdk-wm9713-objs := smdk_wm9713.o | 31 | snd-soc-smdk-wm9713-objs := smdk_wm9713.o |
32 | snd-soc-s3c64xx-smartq-wm8987-objs := smartq_wm8987.o | 32 | snd-soc-s3c64xx-smartq-wm8987-objs := smartq_wm8987.o |
33 | snd-soc-aquila-wm8994-objs := aquila_wm8994.o | ||
34 | snd-soc-goni-wm8994-objs := goni_wm8994.o | ||
33 | 35 | ||
34 | obj-$(CONFIG_SND_S3C24XX_SOC_JIVE_WM8750) += snd-soc-jive-wm8750.o | 36 | obj-$(CONFIG_SND_S3C24XX_SOC_JIVE_WM8750) += snd-soc-jive-wm8750.o |
35 | obj-$(CONFIG_SND_S3C24XX_SOC_NEO1973_WM8753) += snd-soc-neo1973-wm8753.o | 37 | obj-$(CONFIG_SND_S3C24XX_SOC_NEO1973_WM8753) += snd-soc-neo1973-wm8753.o |
@@ -43,3 +45,5 @@ obj-$(CONFIG_SND_S3C24XX_SOC_SIMTEC_TLV320AIC23) += snd-soc-s3c24xx-simtec-tlv32 | |||
43 | obj-$(CONFIG_SND_S3C64XX_SOC_WM8580) += snd-soc-smdk64xx-wm8580.o | 45 | obj-$(CONFIG_SND_S3C64XX_SOC_WM8580) += snd-soc-smdk64xx-wm8580.o |
44 | obj-$(CONFIG_SND_SOC_SMDK_WM9713) += snd-soc-smdk-wm9713.o | 46 | obj-$(CONFIG_SND_SOC_SMDK_WM9713) += snd-soc-smdk-wm9713.o |
45 | obj-$(CONFIG_SND_S3C64XX_SOC_SMARTQ) += snd-soc-s3c64xx-smartq-wm8987.o | 47 | obj-$(CONFIG_SND_S3C64XX_SOC_SMARTQ) += snd-soc-s3c64xx-smartq-wm8987.o |
48 | obj-$(CONFIG_SND_S5PC110_SOC_AQUILA_WM8994) += snd-soc-aquila-wm8994.o | ||
49 | obj-$(CONFIG_SND_S5PV210_SOC_GONI_WM8994) += snd-soc-goni-wm8994.o | ||
diff --git a/sound/soc/s3c24xx/aquila_wm8994.c b/sound/soc/s3c24xx/aquila_wm8994.c new file mode 100644 index 000000000000..235d1973f7d0 --- /dev/null +++ b/sound/soc/s3c24xx/aquila_wm8994.c | |||
@@ -0,0 +1,295 @@ | |||
1 | /* | ||
2 | * aquila_wm8994.c | ||
3 | * | ||
4 | * Copyright (C) 2010 Samsung Electronics Co.Ltd | ||
5 | * Author: Chanwoo Choi <cw00.choi@samsung.com> | ||
6 | * | ||
7 | * This program is free software; you can redistribute it and/or modify it | ||
8 | * under the terms of the GNU General Public License as published by the | ||
9 | * Free Software Foundation; either version 2 of the License, or (at your | ||
10 | * option) any later version. | ||
11 | * | ||
12 | */ | ||
13 | |||
14 | #include <linux/module.h> | ||
15 | #include <linux/moduleparam.h> | ||
16 | #include <linux/io.h> | ||
17 | #include <linux/platform_device.h> | ||
18 | #include <sound/soc.h> | ||
19 | #include <sound/soc-dapm.h> | ||
20 | #include <sound/jack.h> | ||
21 | #include <asm/mach-types.h> | ||
22 | #include <mach/gpio.h> | ||
23 | #include <mach/regs-clock.h> | ||
24 | |||
25 | #include <linux/mfd/wm8994/core.h> | ||
26 | #include <linux/mfd/wm8994/registers.h> | ||
27 | #include "../codecs/wm8994.h" | ||
28 | #include "s3c-dma.h" | ||
29 | #include "s3c64xx-i2s.h" | ||
30 | |||
31 | static struct snd_soc_card aquila; | ||
32 | static struct platform_device *aquila_snd_device; | ||
33 | |||
34 | /* 3.5 pie jack */ | ||
35 | static struct snd_soc_jack jack; | ||
36 | |||
37 | /* 3.5 pie jack detection DAPM pins */ | ||
38 | static struct snd_soc_jack_pin jack_pins[] = { | ||
39 | { | ||
40 | .pin = "Headset Mic", | ||
41 | .mask = SND_JACK_MICROPHONE, | ||
42 | }, { | ||
43 | .pin = "Headset Stereophone", | ||
44 | .mask = SND_JACK_HEADPHONE | SND_JACK_MECHANICAL | | ||
45 | SND_JACK_AVOUT, | ||
46 | }, | ||
47 | }; | ||
48 | |||
49 | /* 3.5 pie jack detection gpios */ | ||
50 | static struct snd_soc_jack_gpio jack_gpios[] = { | ||
51 | { | ||
52 | .gpio = S5PV210_GPH0(6), | ||
53 | .name = "DET_3.5", | ||
54 | .report = SND_JACK_HEADSET | SND_JACK_MECHANICAL | | ||
55 | SND_JACK_AVOUT, | ||
56 | .debounce_time = 200, | ||
57 | }, | ||
58 | }; | ||
59 | |||
60 | static const struct snd_soc_dapm_widget aquila_dapm_widgets[] = { | ||
61 | SND_SOC_DAPM_SPK("Ext Spk", NULL), | ||
62 | SND_SOC_DAPM_SPK("Ext Rcv", NULL), | ||
63 | SND_SOC_DAPM_HP("Headset Stereophone", NULL), | ||
64 | SND_SOC_DAPM_MIC("Headset Mic", NULL), | ||
65 | SND_SOC_DAPM_MIC("Main Mic", NULL), | ||
66 | SND_SOC_DAPM_MIC("2nd Mic", NULL), | ||
67 | SND_SOC_DAPM_LINE("Radio In", NULL), | ||
68 | }; | ||
69 | |||
70 | static const struct snd_soc_dapm_route aquila_dapm_routes[] = { | ||
71 | {"Ext Spk", NULL, "SPKOUTLP"}, | ||
72 | {"Ext Spk", NULL, "SPKOUTLN"}, | ||
73 | |||
74 | {"Ext Rcv", NULL, "HPOUT2N"}, | ||
75 | {"Ext Rcv", NULL, "HPOUT2P"}, | ||
76 | |||
77 | {"Headset Stereophone", NULL, "HPOUT1L"}, | ||
78 | {"Headset Stereophone", NULL, "HPOUT1R"}, | ||
79 | |||
80 | {"IN1RN", NULL, "Headset Mic"}, | ||
81 | {"IN1RP", NULL, "Headset Mic"}, | ||
82 | |||
83 | {"IN1RN", NULL, "2nd Mic"}, | ||
84 | {"IN1RP", NULL, "2nd Mic"}, | ||
85 | |||
86 | {"IN1LN", NULL, "Main Mic"}, | ||
87 | {"IN1LP", NULL, "Main Mic"}, | ||
88 | |||
89 | {"IN2LN", NULL, "Radio In"}, | ||
90 | {"IN2RN", NULL, "Radio In"}, | ||
91 | }; | ||
92 | |||
93 | static int aquila_wm8994_init(struct snd_soc_pcm_runtime *rtd) | ||
94 | { | ||
95 | struct snd_soc_codec *codec = rtd->codec; | ||
96 | int ret; | ||
97 | |||
98 | /* add aquila specific widgets */ | ||
99 | snd_soc_dapm_new_controls(codec, aquila_dapm_widgets, | ||
100 | ARRAY_SIZE(aquila_dapm_widgets)); | ||
101 | |||
102 | /* set up aquila specific audio routes */ | ||
103 | snd_soc_dapm_add_routes(codec, aquila_dapm_routes, | ||
104 | ARRAY_SIZE(aquila_dapm_routes)); | ||
105 | |||
106 | /* set endpoints to not connected */ | ||
107 | snd_soc_dapm_nc_pin(codec, "IN2LP:VXRN"); | ||
108 | snd_soc_dapm_nc_pin(codec, "IN2RP:VXRP"); | ||
109 | snd_soc_dapm_nc_pin(codec, "LINEOUT1N"); | ||
110 | snd_soc_dapm_nc_pin(codec, "LINEOUT1P"); | ||
111 | snd_soc_dapm_nc_pin(codec, "LINEOUT2N"); | ||
112 | snd_soc_dapm_nc_pin(codec, "LINEOUT2P"); | ||
113 | snd_soc_dapm_nc_pin(codec, "SPKOUTRN"); | ||
114 | snd_soc_dapm_nc_pin(codec, "SPKOUTRP"); | ||
115 | |||
116 | snd_soc_dapm_sync(codec); | ||
117 | |||
118 | /* Headset jack detection */ | ||
119 | ret = snd_soc_jack_new(&aquila, "Headset Jack", | ||
120 | SND_JACK_HEADSET | SND_JACK_MECHANICAL | SND_JACK_AVOUT, | ||
121 | &jack); | ||
122 | if (ret) | ||
123 | return ret; | ||
124 | |||
125 | ret = snd_soc_jack_add_pins(&jack, ARRAY_SIZE(jack_pins), jack_pins); | ||
126 | if (ret) | ||
127 | return ret; | ||
128 | |||
129 | ret = snd_soc_jack_add_gpios(&jack, ARRAY_SIZE(jack_gpios), jack_gpios); | ||
130 | if (ret) | ||
131 | return ret; | ||
132 | |||
133 | return 0; | ||
134 | } | ||
135 | |||
136 | static int aquila_hifi_hw_params(struct snd_pcm_substream *substream, | ||
137 | struct snd_pcm_hw_params *params) | ||
138 | { | ||
139 | struct snd_soc_pcm_runtime *rtd = substream->private_data; | ||
140 | struct snd_soc_dai *codec_dai = rtd->codec_dai; | ||
141 | struct snd_soc_dai *cpu_dai = rtd->cpu_dai; | ||
142 | unsigned int pll_out = 24000000; | ||
143 | int ret = 0; | ||
144 | |||
145 | /* set the cpu DAI configuration */ | ||
146 | ret = snd_soc_dai_set_fmt(cpu_dai, SND_SOC_DAIFMT_I2S | | ||
147 | SND_SOC_DAIFMT_NB_NF | SND_SOC_DAIFMT_CBM_CFM); | ||
148 | if (ret < 0) | ||
149 | return ret; | ||
150 | |||
151 | /* set the cpu system clock */ | ||
152 | ret = snd_soc_dai_set_sysclk(cpu_dai, S3C64XX_CLKSRC_PCLK, | ||
153 | 0, SND_SOC_CLOCK_IN); | ||
154 | if (ret < 0) | ||
155 | return ret; | ||
156 | |||
157 | /* set codec DAI configuration */ | ||
158 | ret = snd_soc_dai_set_fmt(codec_dai, SND_SOC_DAIFMT_I2S | | ||
159 | SND_SOC_DAIFMT_NB_NF | SND_SOC_DAIFMT_CBM_CFM); | ||
160 | if (ret < 0) | ||
161 | return ret; | ||
162 | |||
163 | /* set the codec FLL */ | ||
164 | ret = snd_soc_dai_set_pll(codec_dai, WM8994_FLL1, 0, pll_out, | ||
165 | params_rate(params) * 256); | ||
166 | if (ret < 0) | ||
167 | return ret; | ||
168 | |||
169 | /* set the codec system clock */ | ||
170 | ret = snd_soc_dai_set_sysclk(codec_dai, WM8994_SYSCLK_FLL1, | ||
171 | params_rate(params) * 256, SND_SOC_CLOCK_IN); | ||
172 | if (ret < 0) | ||
173 | return ret; | ||
174 | |||
175 | return 0; | ||
176 | } | ||
177 | |||
178 | static struct snd_soc_ops aquila_hifi_ops = { | ||
179 | .hw_params = aquila_hifi_hw_params, | ||
180 | }; | ||
181 | |||
182 | static int aquila_voice_hw_params(struct snd_pcm_substream *substream, | ||
183 | struct snd_pcm_hw_params *params) | ||
184 | { | ||
185 | struct snd_soc_pcm_runtime *rtd = substream->private_data; | ||
186 | struct snd_soc_dai *codec_dai = rtd->codec_dai; | ||
187 | unsigned int pll_out = 24000000; | ||
188 | int ret = 0; | ||
189 | |||
190 | if (params_rate(params) != 8000) | ||
191 | return -EINVAL; | ||
192 | |||
193 | /* set codec DAI configuration */ | ||
194 | ret = snd_soc_dai_set_fmt(codec_dai, SND_SOC_DAIFMT_LEFT_J | | ||
195 | SND_SOC_DAIFMT_IB_IF | SND_SOC_DAIFMT_CBM_CFM); | ||
196 | if (ret < 0) | ||
197 | return ret; | ||
198 | |||
199 | /* set the codec FLL */ | ||
200 | ret = snd_soc_dai_set_pll(codec_dai, WM8994_FLL2, 0, pll_out, | ||
201 | params_rate(params) * 256); | ||
202 | if (ret < 0) | ||
203 | return ret; | ||
204 | |||
205 | /* set the codec system clock */ | ||
206 | ret = snd_soc_dai_set_sysclk(codec_dai, WM8994_SYSCLK_FLL2, | ||
207 | params_rate(params) * 256, SND_SOC_CLOCK_IN); | ||
208 | if (ret < 0) | ||
209 | return ret; | ||
210 | |||
211 | return 0; | ||
212 | } | ||
213 | |||
214 | static struct snd_soc_dai_driver voice_dai = { | ||
215 | .name = "aquila-voice-dai", | ||
216 | .playback = { | ||
217 | .channels_min = 1, | ||
218 | .channels_max = 2, | ||
219 | .rates = SNDRV_PCM_RATE_8000, | ||
220 | .formats = SNDRV_PCM_FMTBIT_S16_LE,}, | ||
221 | .capture = { | ||
222 | .channels_min = 1, | ||
223 | .channels_max = 2, | ||
224 | .rates = SNDRV_PCM_RATE_8000, | ||
225 | .formats = SNDRV_PCM_FMTBIT_S16_LE,}, | ||
226 | }; | ||
227 | |||
228 | static struct snd_soc_ops aquila_voice_ops = { | ||
229 | .hw_params = aquila_voice_hw_params, | ||
230 | }; | ||
231 | |||
232 | static struct snd_soc_dai_link aquila_dai[] = { | ||
233 | { | ||
234 | .name = "WM8994", | ||
235 | .stream_name = "WM8994 HiFi", | ||
236 | .cpu_dai_name = "s3c64xx-i2s-v4", | ||
237 | .codec_dai_name = "wm8994-hifi", | ||
238 | .platform_name = "s3c24xx-pcm-audio", | ||
239 | .codec_name = "wm8994-codec.0-0x1a", | ||
240 | .init = aquila_wm8994_init, | ||
241 | .ops = &aquila_hifi_ops, | ||
242 | }, { | ||
243 | .name = "WM8994 Voice", | ||
244 | .stream_name = "Voice", | ||
245 | .cpu_dai_name = "aquila-voice-dai", | ||
246 | .codec_dai_name = "wm8994-voice", | ||
247 | .platform_name = "s3c24xx-pcm-audio", | ||
248 | .codec_name = "wm8994-codec.0-0x1a", | ||
249 | .ops = &aquila_voice_ops, | ||
250 | }, | ||
251 | }; | ||
252 | |||
253 | static struct snd_soc_card aquila = { | ||
254 | .name = "aquila", | ||
255 | .dai_link = aquila_dai, | ||
256 | .num_links = ARRAY_SIZE(aquila_dai), | ||
257 | }; | ||
258 | |||
259 | static int __init aquila_init(void) | ||
260 | { | ||
261 | int ret; | ||
262 | |||
263 | if (!machine_is_aquila()) | ||
264 | return -ENODEV; | ||
265 | |||
266 | aquila_snd_device = platform_device_alloc("soc-audio", -1); | ||
267 | if (!aquila_snd_device) | ||
268 | return -ENOMEM; | ||
269 | |||
270 | /* register voice DAI here */ | ||
271 | ret = snd_soc_register_dai(&aquila_snd_device->dev, &voice_dai); | ||
272 | if (ret) | ||
273 | return ret; | ||
274 | |||
275 | platform_set_drvdata(aquila_snd_device, &aquila); | ||
276 | ret = platform_device_add(aquila_snd_device); | ||
277 | |||
278 | if (ret) | ||
279 | platform_device_put(aquila_snd_device); | ||
280 | |||
281 | return ret; | ||
282 | } | ||
283 | |||
284 | static void __exit aquila_exit(void) | ||
285 | { | ||
286 | platform_device_unregister(aquila_snd_device); | ||
287 | } | ||
288 | |||
289 | module_init(aquila_init); | ||
290 | module_exit(aquila_exit); | ||
291 | |||
292 | /* Module information */ | ||
293 | MODULE_DESCRIPTION("ALSA SoC WM8994 Aquila(S5PC110)"); | ||
294 | MODULE_AUTHOR("Chanwoo Choi <cw00.choi@samsung.com>"); | ||
295 | MODULE_LICENSE("GPL"); | ||
diff --git a/sound/soc/s3c24xx/goni_wm8994.c b/sound/soc/s3c24xx/goni_wm8994.c new file mode 100644 index 000000000000..694f702cc8e2 --- /dev/null +++ b/sound/soc/s3c24xx/goni_wm8994.c | |||
@@ -0,0 +1,298 @@ | |||
1 | /* | ||
2 | * goni_wm8994.c | ||
3 | * | ||
4 | * Copyright (C) 2010 Samsung Electronics Co.Ltd | ||
5 | * Author: Chanwoo Choi <cw00.choi@samsung.com> | ||
6 | * | ||
7 | * This program is free software; you can redistribute it and/or modify it | ||
8 | * under the terms of the GNU General Public License as published by the | ||
9 | * Free Software Foundation; either version 2 of the License, or (at your | ||
10 | * option) any later version. | ||
11 | * | ||
12 | */ | ||
13 | |||
14 | #include <linux/module.h> | ||
15 | #include <linux/moduleparam.h> | ||
16 | #include <linux/io.h> | ||
17 | #include <linux/platform_device.h> | ||
18 | #include <sound/soc.h> | ||
19 | #include <sound/soc-dapm.h> | ||
20 | #include <sound/jack.h> | ||
21 | #include <asm/mach-types.h> | ||
22 | #include <mach/gpio.h> | ||
23 | #include <mach/regs-clock.h> | ||
24 | |||
25 | #include <linux/mfd/wm8994/core.h> | ||
26 | #include <linux/mfd/wm8994/registers.h> | ||
27 | #include "../codecs/wm8994.h" | ||
28 | #include "s3c-dma.h" | ||
29 | #include "s3c64xx-i2s.h" | ||
30 | |||
31 | static struct snd_soc_card goni; | ||
32 | static struct platform_device *goni_snd_device; | ||
33 | |||
34 | /* 3.5 pie jack */ | ||
35 | static struct snd_soc_jack jack; | ||
36 | |||
37 | /* 3.5 pie jack detection DAPM pins */ | ||
38 | static struct snd_soc_jack_pin jack_pins[] = { | ||
39 | { | ||
40 | .pin = "Headset Mic", | ||
41 | .mask = SND_JACK_MICROPHONE, | ||
42 | }, { | ||
43 | .pin = "Headset Stereophone", | ||
44 | .mask = SND_JACK_HEADPHONE | SND_JACK_MECHANICAL | | ||
45 | SND_JACK_AVOUT, | ||
46 | }, | ||
47 | }; | ||
48 | |||
49 | /* 3.5 pie jack detection gpios */ | ||
50 | static struct snd_soc_jack_gpio jack_gpios[] = { | ||
51 | { | ||
52 | .gpio = S5PV210_GPH0(6), | ||
53 | .name = "DET_3.5", | ||
54 | .report = SND_JACK_HEADSET | SND_JACK_MECHANICAL | | ||
55 | SND_JACK_AVOUT, | ||
56 | .debounce_time = 200, | ||
57 | }, | ||
58 | }; | ||
59 | |||
60 | static const struct snd_soc_dapm_widget goni_dapm_widgets[] = { | ||
61 | SND_SOC_DAPM_SPK("Ext Left Spk", NULL), | ||
62 | SND_SOC_DAPM_SPK("Ext Right Spk", NULL), | ||
63 | SND_SOC_DAPM_SPK("Ext Rcv", NULL), | ||
64 | SND_SOC_DAPM_HP("Headset Stereophone", NULL), | ||
65 | SND_SOC_DAPM_MIC("Headset Mic", NULL), | ||
66 | SND_SOC_DAPM_MIC("Main Mic", NULL), | ||
67 | SND_SOC_DAPM_MIC("2nd Mic", NULL), | ||
68 | SND_SOC_DAPM_LINE("Radio In", NULL), | ||
69 | }; | ||
70 | |||
71 | static const struct snd_soc_dapm_route goni_dapm_routes[] = { | ||
72 | {"Ext Left Spk", NULL, "SPKOUTLP"}, | ||
73 | {"Ext Left Spk", NULL, "SPKOUTLN"}, | ||
74 | |||
75 | {"Ext Right Spk", NULL, "SPKOUTRP"}, | ||
76 | {"Ext Right Spk", NULL, "SPKOUTRN"}, | ||
77 | |||
78 | {"Ext Rcv", NULL, "HPOUT2N"}, | ||
79 | {"Ext Rcv", NULL, "HPOUT2P"}, | ||
80 | |||
81 | {"Headset Stereophone", NULL, "HPOUT1L"}, | ||
82 | {"Headset Stereophone", NULL, "HPOUT1R"}, | ||
83 | |||
84 | {"IN1RN", NULL, "Headset Mic"}, | ||
85 | {"IN1RP", NULL, "Headset Mic"}, | ||
86 | |||
87 | {"IN1RN", NULL, "2nd Mic"}, | ||
88 | {"IN1RP", NULL, "2nd Mic"}, | ||
89 | |||
90 | {"IN1LN", NULL, "Main Mic"}, | ||
91 | {"IN1LP", NULL, "Main Mic"}, | ||
92 | |||
93 | {"IN2LN", NULL, "Radio In"}, | ||
94 | {"IN2RN", NULL, "Radio In"}, | ||
95 | }; | ||
96 | |||
97 | static int goni_wm8994_init(struct snd_soc_pcm_runtime *rtd) | ||
98 | { | ||
99 | struct snd_soc_codec *codec = rtd->codec; | ||
100 | int ret; | ||
101 | |||
102 | /* add goni specific widgets */ | ||
103 | snd_soc_dapm_new_controls(codec, goni_dapm_widgets, | ||
104 | ARRAY_SIZE(goni_dapm_widgets)); | ||
105 | |||
106 | /* set up goni specific audio routes */ | ||
107 | snd_soc_dapm_add_routes(codec, goni_dapm_routes, | ||
108 | ARRAY_SIZE(goni_dapm_routes)); | ||
109 | |||
110 | /* set endpoints to not connected */ | ||
111 | snd_soc_dapm_nc_pin(codec, "IN2LP:VXRN"); | ||
112 | snd_soc_dapm_nc_pin(codec, "IN2RP:VXRP"); | ||
113 | snd_soc_dapm_nc_pin(codec, "LINEOUT1N"); | ||
114 | snd_soc_dapm_nc_pin(codec, "LINEOUT1P"); | ||
115 | snd_soc_dapm_nc_pin(codec, "LINEOUT2N"); | ||
116 | snd_soc_dapm_nc_pin(codec, "LINEOUT2P"); | ||
117 | |||
118 | snd_soc_dapm_sync(codec); | ||
119 | |||
120 | /* Headset jack detection */ | ||
121 | ret = snd_soc_jack_new(&goni, "Headset Jack", | ||
122 | SND_JACK_HEADSET | SND_JACK_MECHANICAL | SND_JACK_AVOUT, | ||
123 | &jack); | ||
124 | if (ret) | ||
125 | return ret; | ||
126 | |||
127 | ret = snd_soc_jack_add_pins(&jack, ARRAY_SIZE(jack_pins), jack_pins); | ||
128 | if (ret) | ||
129 | return ret; | ||
130 | |||
131 | ret = snd_soc_jack_add_gpios(&jack, ARRAY_SIZE(jack_gpios), jack_gpios); | ||
132 | if (ret) | ||
133 | return ret; | ||
134 | |||
135 | return 0; | ||
136 | } | ||
137 | |||
138 | static int goni_hifi_hw_params(struct snd_pcm_substream *substream, | ||
139 | struct snd_pcm_hw_params *params) | ||
140 | { | ||
141 | struct snd_soc_pcm_runtime *rtd = substream->private_data; | ||
142 | struct snd_soc_dai *codec_dai = rtd->codec_dai; | ||
143 | struct snd_soc_dai *cpu_dai = rtd->cpu_dai; | ||
144 | unsigned int pll_out = 24000000; | ||
145 | int ret = 0; | ||
146 | |||
147 | /* set the cpu DAI configuration */ | ||
148 | ret = snd_soc_dai_set_fmt(cpu_dai, SND_SOC_DAIFMT_I2S | | ||
149 | SND_SOC_DAIFMT_NB_NF | SND_SOC_DAIFMT_CBM_CFM); | ||
150 | if (ret < 0) | ||
151 | return ret; | ||
152 | |||
153 | /* set the cpu system clock */ | ||
154 | ret = snd_soc_dai_set_sysclk(cpu_dai, S3C64XX_CLKSRC_PCLK, | ||
155 | 0, SND_SOC_CLOCK_IN); | ||
156 | if (ret < 0) | ||
157 | return ret; | ||
158 | |||
159 | /* set codec DAI configuration */ | ||
160 | ret = snd_soc_dai_set_fmt(codec_dai, SND_SOC_DAIFMT_I2S | | ||
161 | SND_SOC_DAIFMT_NB_NF | SND_SOC_DAIFMT_CBM_CFM); | ||
162 | if (ret < 0) | ||
163 | return ret; | ||
164 | |||
165 | /* set the codec FLL */ | ||
166 | ret = snd_soc_dai_set_pll(codec_dai, WM8994_FLL1, 0, pll_out, | ||
167 | params_rate(params) * 256); | ||
168 | if (ret < 0) | ||
169 | return ret; | ||
170 | |||
171 | /* set the codec system clock */ | ||
172 | ret = snd_soc_dai_set_sysclk(codec_dai, WM8994_SYSCLK_FLL1, | ||
173 | params_rate(params) * 256, SND_SOC_CLOCK_IN); | ||
174 | if (ret < 0) | ||
175 | return ret; | ||
176 | |||
177 | return 0; | ||
178 | } | ||
179 | |||
180 | static struct snd_soc_ops goni_hifi_ops = { | ||
181 | .hw_params = goni_hifi_hw_params, | ||
182 | }; | ||
183 | |||
184 | static int goni_voice_hw_params(struct snd_pcm_substream *substream, | ||
185 | struct snd_pcm_hw_params *params) | ||
186 | { | ||
187 | struct snd_soc_pcm_runtime *rtd = substream->private_data; | ||
188 | struct snd_soc_dai *codec_dai = rtd->codec_dai; | ||
189 | unsigned int pll_out = 24000000; | ||
190 | int ret = 0; | ||
191 | |||
192 | if (params_rate(params) != 8000) | ||
193 | return -EINVAL; | ||
194 | |||
195 | /* set codec DAI configuration */ | ||
196 | ret = snd_soc_dai_set_fmt(codec_dai, SND_SOC_DAIFMT_LEFT_J | | ||
197 | SND_SOC_DAIFMT_IB_IF | SND_SOC_DAIFMT_CBM_CFM); | ||
198 | if (ret < 0) | ||
199 | return ret; | ||
200 | |||
201 | /* set the codec FLL */ | ||
202 | ret = snd_soc_dai_set_pll(codec_dai, WM8994_FLL2, 0, pll_out, | ||
203 | params_rate(params) * 256); | ||
204 | if (ret < 0) | ||
205 | return ret; | ||
206 | |||
207 | /* set the codec system clock */ | ||
208 | ret = snd_soc_dai_set_sysclk(codec_dai, WM8994_SYSCLK_FLL2, | ||
209 | params_rate(params) * 256, SND_SOC_CLOCK_IN); | ||
210 | if (ret < 0) | ||
211 | return ret; | ||
212 | |||
213 | return 0; | ||
214 | } | ||
215 | |||
216 | static struct snd_soc_dai_driver voice_dai = { | ||
217 | .name = "goni-voice-dai", | ||
218 | .id = 0, | ||
219 | .playback = { | ||
220 | .channels_min = 1, | ||
221 | .channels_max = 2, | ||
222 | .rates = SNDRV_PCM_RATE_8000, | ||
223 | .formats = SNDRV_PCM_FMTBIT_S16_LE,}, | ||
224 | .capture = { | ||
225 | .channels_min = 1, | ||
226 | .channels_max = 2, | ||
227 | .rates = SNDRV_PCM_RATE_8000, | ||
228 | .formats = SNDRV_PCM_FMTBIT_S16_LE,}, | ||
229 | }; | ||
230 | |||
231 | static struct snd_soc_ops goni_voice_ops = { | ||
232 | .hw_params = goni_voice_hw_params, | ||
233 | }; | ||
234 | |||
235 | static struct snd_soc_dai_link goni_dai[] = { | ||
236 | { | ||
237 | .name = "WM8994", | ||
238 | .stream_name = "WM8994 HiFi", | ||
239 | .cpu_dai_name = "s3c64xx-i2s-v4", | ||
240 | .codec_dai_name = "wm8994-hifi", | ||
241 | .platform_name = "s3c24xx-pcm-audio", | ||
242 | .codec_name = "wm8994-codec.0-0x1a", | ||
243 | .init = goni_wm8994_init, | ||
244 | .ops = &goni_hifi_ops, | ||
245 | }, { | ||
246 | .name = "WM8994 Voice", | ||
247 | .stream_name = "Voice", | ||
248 | .cpu_dai_name = "goni-voice-dai", | ||
249 | .codec_dai_name = "wm8994-voice", | ||
250 | .platform_name = "s3c24xx-pcm-audio", | ||
251 | .codec_name = "wm8994-codec.0-0x1a", | ||
252 | .ops = &goni_voice_ops, | ||
253 | }, | ||
254 | }; | ||
255 | |||
256 | static struct snd_soc_card goni = { | ||
257 | .name = "goni", | ||
258 | .dai_link = goni_dai, | ||
259 | .num_links = ARRAY_SIZE(goni_dai), | ||
260 | }; | ||
261 | |||
262 | static int __init goni_init(void) | ||
263 | { | ||
264 | int ret; | ||
265 | |||
266 | if (!machine_is_goni()) | ||
267 | return -ENODEV; | ||
268 | |||
269 | goni_snd_device = platform_device_alloc("soc-audio", -1); | ||
270 | if (!goni_snd_device) | ||
271 | return -ENOMEM; | ||
272 | |||
273 | /* register voice DAI here */ | ||
274 | ret = snd_soc_register_dai(&goni_snd_device->dev, &voice_dai); | ||
275 | if (ret) | ||
276 | return ret; | ||
277 | |||
278 | platform_set_drvdata(goni_snd_device, &goni); | ||
279 | ret = platform_device_add(goni_snd_device); | ||
280 | |||
281 | if (ret) | ||
282 | platform_device_put(goni_snd_device); | ||
283 | |||
284 | return ret; | ||
285 | } | ||
286 | |||
287 | static void __exit goni_exit(void) | ||
288 | { | ||
289 | platform_device_unregister(goni_snd_device); | ||
290 | } | ||
291 | |||
292 | module_init(goni_init); | ||
293 | module_exit(goni_exit); | ||
294 | |||
295 | /* Module information */ | ||
296 | MODULE_DESCRIPTION("ALSA SoC WM8994 GONI(S5PV210)"); | ||
297 | MODULE_AUTHOR("Chanwoo Choi <cw00.choi@samsung.com>"); | ||
298 | MODULE_LICENSE("GPL"); | ||
diff --git a/sound/soc/s3c24xx/jive_wm8750.c b/sound/soc/s3c24xx/jive_wm8750.c index 8c108b121c10..49605cd83947 100644 --- a/sound/soc/s3c24xx/jive_wm8750.c +++ b/sound/soc/s3c24xx/jive_wm8750.c | |||
@@ -49,8 +49,8 @@ static int jive_hw_params(struct snd_pcm_substream *substream, | |||
49 | struct snd_pcm_hw_params *params) | 49 | struct snd_pcm_hw_params *params) |
50 | { | 50 | { |
51 | struct snd_soc_pcm_runtime *rtd = substream->private_data; | 51 | struct snd_soc_pcm_runtime *rtd = substream->private_data; |
52 | struct snd_soc_dai *codec_dai = rtd->dai->codec_dai; | 52 | struct snd_soc_dai *codec_dai = rtd->codec_dai; |
53 | struct snd_soc_dai *cpu_dai = rtd->dai->cpu_dai; | 53 | struct snd_soc_dai *cpu_dai = rtd->cpu_dai; |
54 | struct s3c_i2sv2_rate_calc div; | 54 | struct s3c_i2sv2_rate_calc div; |
55 | unsigned int clk = 0; | 55 | unsigned int clk = 0; |
56 | int ret = 0; | 56 | int ret = 0; |
@@ -108,8 +108,9 @@ static struct snd_soc_ops jive_ops = { | |||
108 | .hw_params = jive_hw_params, | 108 | .hw_params = jive_hw_params, |
109 | }; | 109 | }; |
110 | 110 | ||
111 | static int jive_wm8750_init(struct snd_soc_codec *codec) | 111 | static int jive_wm8750_init(struct snd_soc_pcm_runtime *rtd) |
112 | { | 112 | { |
113 | struct snd_soc_codec *codec = rtd->codec; | ||
113 | int err; | 114 | int err; |
114 | 115 | ||
115 | /* These endpoints are not being used. */ | 116 | /* These endpoints are not being used. */ |
@@ -138,8 +139,10 @@ static int jive_wm8750_init(struct snd_soc_codec *codec) | |||
138 | static struct snd_soc_dai_link jive_dai = { | 139 | static struct snd_soc_dai_link jive_dai = { |
139 | .name = "wm8750", | 140 | .name = "wm8750", |
140 | .stream_name = "WM8750", | 141 | .stream_name = "WM8750", |
141 | .cpu_dai = &s3c2412_i2s_dai, | 142 | .cpu_dai_name = "s3c2412-i2s", |
142 | .codec_dai = &wm8750_dai, | 143 | .codec_dai_name = "wm8750-hifi", |
144 | .platform_name = "s3c24xx-pcm-audio", | ||
145 | .codec_name = "wm8750-codec.0-0x1a", | ||
143 | .init = jive_wm8750_init, | 146 | .init = jive_wm8750_init, |
144 | .ops = &jive_ops, | 147 | .ops = &jive_ops, |
145 | }; | 148 | }; |
@@ -147,17 +150,10 @@ static struct snd_soc_dai_link jive_dai = { | |||
147 | /* jive audio machine driver */ | 150 | /* jive audio machine driver */ |
148 | static struct snd_soc_card snd_soc_machine_jive = { | 151 | static struct snd_soc_card snd_soc_machine_jive = { |
149 | .name = "Jive", | 152 | .name = "Jive", |
150 | .platform = &s3c24xx_soc_platform, | ||
151 | .dai_link = &jive_dai, | 153 | .dai_link = &jive_dai, |
152 | .num_links = 1, | 154 | .num_links = 1, |
153 | }; | 155 | }; |
154 | 156 | ||
155 | /* jive audio subsystem */ | ||
156 | static struct snd_soc_device jive_snd_devdata = { | ||
157 | .card = &snd_soc_machine_jive, | ||
158 | .codec_dev = &soc_codec_dev_wm8750, | ||
159 | }; | ||
160 | |||
161 | static struct platform_device *jive_snd_device; | 157 | static struct platform_device *jive_snd_device; |
162 | 158 | ||
163 | static int __init jive_init(void) | 159 | static int __init jive_init(void) |
@@ -173,8 +169,7 @@ static int __init jive_init(void) | |||
173 | if (!jive_snd_device) | 169 | if (!jive_snd_device) |
174 | return -ENOMEM; | 170 | return -ENOMEM; |
175 | 171 | ||
176 | platform_set_drvdata(jive_snd_device, &jive_snd_devdata); | 172 | platform_set_drvdata(jive_snd_device, &snd_soc_machine_jive); |
177 | jive_snd_devdata.dev = &jive_snd_device->dev; | ||
178 | ret = platform_device_add(jive_snd_device); | 173 | ret = platform_device_add(jive_snd_device); |
179 | 174 | ||
180 | if (ret) | 175 | if (ret) |
diff --git a/sound/soc/s3c24xx/ln2440sbc_alc650.c b/sound/soc/s3c24xx/ln2440sbc_alc650.c index ffa954fe6931..abe64abe8c84 100644 --- a/sound/soc/s3c24xx/ln2440sbc_alc650.c +++ b/sound/soc/s3c24xx/ln2440sbc_alc650.c | |||
@@ -23,7 +23,6 @@ | |||
23 | #include <sound/soc.h> | 23 | #include <sound/soc.h> |
24 | #include <sound/soc-dapm.h> | 24 | #include <sound/soc-dapm.h> |
25 | 25 | ||
26 | #include "../codecs/ac97.h" | ||
27 | #include "s3c-dma.h" | 26 | #include "s3c-dma.h" |
28 | #include "s3c-ac97.h" | 27 | #include "s3c-ac97.h" |
29 | 28 | ||
@@ -33,23 +32,19 @@ static struct snd_soc_dai_link ln2440sbc_dai[] = { | |||
33 | { | 32 | { |
34 | .name = "AC97", | 33 | .name = "AC97", |
35 | .stream_name = "AC97 HiFi", | 34 | .stream_name = "AC97 HiFi", |
36 | .cpu_dai = &s3c_ac97_dai[S3C_AC97_DAI_PCM], | 35 | .cpu_dai_name = "s3c-ac97", |
37 | .codec_dai = &ac97_dai, | 36 | .codec_dai_name = "ac97-hifi", |
37 | .codec_name = "ac97-codec", | ||
38 | .platform_name = "s3c24xx-pcm-audio", | ||
38 | }, | 39 | }, |
39 | }; | 40 | }; |
40 | 41 | ||
41 | static struct snd_soc_card ln2440sbc = { | 42 | static struct snd_soc_card ln2440sbc = { |
42 | .name = "LN2440SBC", | 43 | .name = "LN2440SBC", |
43 | .platform = &s3c24xx_soc_platform, | ||
44 | .dai_link = ln2440sbc_dai, | 44 | .dai_link = ln2440sbc_dai, |
45 | .num_links = ARRAY_SIZE(ln2440sbc_dai), | 45 | .num_links = ARRAY_SIZE(ln2440sbc_dai), |
46 | }; | 46 | }; |
47 | 47 | ||
48 | static struct snd_soc_device ln2440sbc_snd_ac97_devdata = { | ||
49 | .card = &ln2440sbc, | ||
50 | .codec_dev = &soc_codec_dev_ac97, | ||
51 | }; | ||
52 | |||
53 | static struct platform_device *ln2440sbc_snd_ac97_device; | 48 | static struct platform_device *ln2440sbc_snd_ac97_device; |
54 | 49 | ||
55 | static int __init ln2440sbc_init(void) | 50 | static int __init ln2440sbc_init(void) |
@@ -60,9 +55,7 @@ static int __init ln2440sbc_init(void) | |||
60 | if (!ln2440sbc_snd_ac97_device) | 55 | if (!ln2440sbc_snd_ac97_device) |
61 | return -ENOMEM; | 56 | return -ENOMEM; |
62 | 57 | ||
63 | platform_set_drvdata(ln2440sbc_snd_ac97_device, | 58 | platform_set_drvdata(ln2440sbc_snd_ac97_device, &ln2440sbc); |
64 | &ln2440sbc_snd_ac97_devdata); | ||
65 | ln2440sbc_snd_ac97_devdata.dev = &ln2440sbc_snd_ac97_device->dev; | ||
66 | ret = platform_device_add(ln2440sbc_snd_ac97_device); | 59 | ret = platform_device_add(ln2440sbc_snd_ac97_device); |
67 | 60 | ||
68 | if (ret) | 61 | if (ret) |
diff --git a/sound/soc/s3c24xx/neo1973_gta02_wm8753.c b/sound/soc/s3c24xx/neo1973_gta02_wm8753.c index 209c25994c7e..c457bfd8297c 100644 --- a/sound/soc/s3c24xx/neo1973_gta02_wm8753.c +++ b/sound/soc/s3c24xx/neo1973_gta02_wm8753.c | |||
@@ -41,8 +41,8 @@ static int neo1973_gta02_hifi_hw_params(struct snd_pcm_substream *substream, | |||
41 | struct snd_pcm_hw_params *params) | 41 | struct snd_pcm_hw_params *params) |
42 | { | 42 | { |
43 | struct snd_soc_pcm_runtime *rtd = substream->private_data; | 43 | struct snd_soc_pcm_runtime *rtd = substream->private_data; |
44 | struct snd_soc_dai *codec_dai = rtd->dai->codec_dai; | 44 | struct snd_soc_dai *codec_dai = rtd->codec_dai; |
45 | struct snd_soc_dai *cpu_dai = rtd->dai->cpu_dai; | 45 | struct snd_soc_dai *cpu_dai = rtd->cpu_dai; |
46 | unsigned int pll_out = 0, bclk = 0; | 46 | unsigned int pll_out = 0, bclk = 0; |
47 | int ret = 0; | 47 | int ret = 0; |
48 | unsigned long iis_clkrate; | 48 | unsigned long iis_clkrate; |
@@ -130,7 +130,7 @@ static int neo1973_gta02_hifi_hw_params(struct snd_pcm_substream *substream, | |||
130 | static int neo1973_gta02_hifi_hw_free(struct snd_pcm_substream *substream) | 130 | static int neo1973_gta02_hifi_hw_free(struct snd_pcm_substream *substream) |
131 | { | 131 | { |
132 | struct snd_soc_pcm_runtime *rtd = substream->private_data; | 132 | struct snd_soc_pcm_runtime *rtd = substream->private_data; |
133 | struct snd_soc_dai *codec_dai = rtd->dai->codec_dai; | 133 | struct snd_soc_dai *codec_dai = rtd->codec_dai; |
134 | 134 | ||
135 | /* disable the PLL */ | 135 | /* disable the PLL */ |
136 | return snd_soc_dai_set_pll(codec_dai, WM8753_PLL1, 0, 0, 0); | 136 | return snd_soc_dai_set_pll(codec_dai, WM8753_PLL1, 0, 0, 0); |
@@ -149,7 +149,7 @@ static int neo1973_gta02_voice_hw_params( | |||
149 | struct snd_pcm_hw_params *params) | 149 | struct snd_pcm_hw_params *params) |
150 | { | 150 | { |
151 | struct snd_soc_pcm_runtime *rtd = substream->private_data; | 151 | struct snd_soc_pcm_runtime *rtd = substream->private_data; |
152 | struct snd_soc_dai *codec_dai = rtd->dai->codec_dai; | 152 | struct snd_soc_dai *codec_dai = rtd->codec_dai; |
153 | unsigned int pcmdiv = 0; | 153 | unsigned int pcmdiv = 0; |
154 | int ret = 0; | 154 | int ret = 0; |
155 | unsigned long iis_clkrate; | 155 | unsigned long iis_clkrate; |
@@ -194,7 +194,7 @@ static int neo1973_gta02_voice_hw_params( | |||
194 | static int neo1973_gta02_voice_hw_free(struct snd_pcm_substream *substream) | 194 | static int neo1973_gta02_voice_hw_free(struct snd_pcm_substream *substream) |
195 | { | 195 | { |
196 | struct snd_soc_pcm_runtime *rtd = substream->private_data; | 196 | struct snd_soc_pcm_runtime *rtd = substream->private_data; |
197 | struct snd_soc_dai *codec_dai = rtd->dai->codec_dai; | 197 | struct snd_soc_dai *codec_dai = rtd->codec_dai; |
198 | 198 | ||
199 | /* disable the PLL */ | 199 | /* disable the PLL */ |
200 | return snd_soc_dai_set_pll(codec_dai, WM8753_PLL2, 0, 0, 0); | 200 | return snd_soc_dai_set_pll(codec_dai, WM8753_PLL2, 0, 0, 0); |
@@ -262,7 +262,7 @@ static int lm4853_event(struct snd_soc_dapm_widget *w, | |||
262 | struct snd_kcontrol *k, | 262 | struct snd_kcontrol *k, |
263 | int event) | 263 | int event) |
264 | { | 264 | { |
265 | gpio_set_value(GTA02_GPIO_AMP_SHUT, SND_SOC_DAPM_EVENT_OFF(value)); | 265 | gpio_set_value(GTA02_GPIO_AMP_SHUT, SND_SOC_DAPM_EVENT_OFF(event)); |
266 | 266 | ||
267 | return 0; | 267 | return 0; |
268 | } | 268 | } |
@@ -330,8 +330,9 @@ static const struct snd_kcontrol_new wm8753_neo1973_gta02_controls[] = { | |||
330 | * This is an example machine initialisation for a wm8753 connected to a | 330 | * This is an example machine initialisation for a wm8753 connected to a |
331 | * neo1973 GTA02. | 331 | * neo1973 GTA02. |
332 | */ | 332 | */ |
333 | static int neo1973_gta02_wm8753_init(struct snd_soc_codec *codec) | 333 | static int neo1973_gta02_wm8753_init(struct snd_soc_pcm_runtime *rtd) |
334 | { | 334 | { |
335 | struct snd_soc_codec *codec = rtd->codec; | ||
335 | int err; | 336 | int err; |
336 | 337 | ||
337 | /* set up NC codec pins */ | 338 | /* set up NC codec pins */ |
@@ -378,9 +379,8 @@ static int neo1973_gta02_wm8753_init(struct snd_soc_codec *codec) | |||
378 | /* | 379 | /* |
379 | * BT Codec DAI | 380 | * BT Codec DAI |
380 | */ | 381 | */ |
381 | static struct snd_soc_dai bt_dai = { | 382 | static struct snd_soc_dai_driver bt_dai = { |
382 | .name = "Bluetooth", | 383 | .name = "bluetooth-dai", |
383 | .id = 0, | ||
384 | .playback = { | 384 | .playback = { |
385 | .channels_min = 1, | 385 | .channels_min = 1, |
386 | .channels_max = 1, | 386 | .channels_max = 1, |
@@ -397,32 +397,30 @@ static struct snd_soc_dai_link neo1973_gta02_dai[] = { | |||
397 | { /* Hifi Playback - for similatious use with voice below */ | 397 | { /* Hifi Playback - for similatious use with voice below */ |
398 | .name = "WM8753", | 398 | .name = "WM8753", |
399 | .stream_name = "WM8753 HiFi", | 399 | .stream_name = "WM8753 HiFi", |
400 | .cpu_dai = &s3c24xx_i2s_dai, | 400 | .cpu_dai_name = "s3c24xx-i2s", |
401 | .codec_dai = &wm8753_dai[WM8753_DAI_HIFI], | 401 | .codec_dai_name = "wm8753-hifi", |
402 | .init = neo1973_gta02_wm8753_init, | 402 | .init = neo1973_gta02_wm8753_init, |
403 | .platform_name = "s3c24xx-pcm-audio", | ||
404 | .codec_name = "wm8753-codec.0-0x1a", | ||
403 | .ops = &neo1973_gta02_hifi_ops, | 405 | .ops = &neo1973_gta02_hifi_ops, |
404 | }, | 406 | }, |
405 | { /* Voice via BT */ | 407 | { /* Voice via BT */ |
406 | .name = "Bluetooth", | 408 | .name = "Bluetooth", |
407 | .stream_name = "Voice", | 409 | .stream_name = "Voice", |
408 | .cpu_dai = &bt_dai, | 410 | .cpu_dai_name = "bluetooth-dai", |
409 | .codec_dai = &wm8753_dai[WM8753_DAI_VOICE], | 411 | .codec_dai_name = "wm8753-voice", |
410 | .ops = &neo1973_gta02_voice_ops, | 412 | .ops = &neo1973_gta02_voice_ops, |
413 | .codec_name = "wm8753-codec.0-0x1a", | ||
414 | .platform_name = "s3c24xx-pcm-audio", | ||
411 | }, | 415 | }, |
412 | }; | 416 | }; |
413 | 417 | ||
414 | static struct snd_soc_card neo1973_gta02 = { | 418 | static struct snd_soc_card neo1973_gta02 = { |
415 | .name = "neo1973-gta02", | 419 | .name = "neo1973-gta02", |
416 | .platform = &s3c24xx_soc_platform, | ||
417 | .dai_link = neo1973_gta02_dai, | 420 | .dai_link = neo1973_gta02_dai, |
418 | .num_links = ARRAY_SIZE(neo1973_gta02_dai), | 421 | .num_links = ARRAY_SIZE(neo1973_gta02_dai), |
419 | }; | 422 | }; |
420 | 423 | ||
421 | static struct snd_soc_device neo1973_gta02_snd_devdata = { | ||
422 | .card = &neo1973_gta02, | ||
423 | .codec_dev = &soc_codec_dev_wm8753, | ||
424 | }; | ||
425 | |||
426 | static struct platform_device *neo1973_gta02_snd_device; | 424 | static struct platform_device *neo1973_gta02_snd_device; |
427 | 425 | ||
428 | static int __init neo1973_gta02_init(void) | 426 | static int __init neo1973_gta02_init(void) |
@@ -435,18 +433,18 @@ static int __init neo1973_gta02_init(void) | |||
435 | return -ENODEV; | 433 | return -ENODEV; |
436 | } | 434 | } |
437 | 435 | ||
438 | /* register bluetooth DAI here */ | ||
439 | ret = snd_soc_register_dai(&bt_dai); | ||
440 | if (ret) | ||
441 | return ret; | ||
442 | |||
443 | neo1973_gta02_snd_device = platform_device_alloc("soc-audio", -1); | 436 | neo1973_gta02_snd_device = platform_device_alloc("soc-audio", -1); |
444 | if (!neo1973_gta02_snd_device) | 437 | if (!neo1973_gta02_snd_device) |
445 | return -ENOMEM; | 438 | return -ENOMEM; |
446 | 439 | ||
447 | platform_set_drvdata(neo1973_gta02_snd_device, | 440 | /* register bluetooth DAI here */ |
448 | &neo1973_gta02_snd_devdata); | 441 | ret = snd_soc_register_dai(&neo1973_gta02_snd_device->dev, -1, &bt_dai); |
449 | neo1973_gta02_snd_devdata.dev = &neo1973_gta02_snd_device->dev; | 442 | if (ret) { |
443 | platform_device_put(neo1973_gta02_snd_device); | ||
444 | return ret; | ||
445 | } | ||
446 | |||
447 | platform_set_drvdata(neo1973_gta02_snd_device, &neo1973_gta02); | ||
450 | ret = platform_device_add(neo1973_gta02_snd_device); | 448 | ret = platform_device_add(neo1973_gta02_snd_device); |
451 | 449 | ||
452 | if (ret) { | 450 | if (ret) { |
@@ -461,7 +459,7 @@ static int __init neo1973_gta02_init(void) | |||
461 | goto err_unregister_device; | 459 | goto err_unregister_device; |
462 | } | 460 | } |
463 | 461 | ||
464 | ret = gpio_direction_output(GTA02_GPIO_AMP_HP_IN, 1); | 462 | ret = gpio_direction_output(GTA02_GPIO_HP_IN, 1); |
465 | if (ret) { | 463 | if (ret) { |
466 | pr_err("gta02_wm8753: Failed to configure GPIO %d\n", GTA02_GPIO_HP_IN); | 464 | pr_err("gta02_wm8753: Failed to configure GPIO %d\n", GTA02_GPIO_HP_IN); |
467 | goto err_free_gpio_hp_in; | 465 | goto err_free_gpio_hp_in; |
@@ -493,7 +491,7 @@ module_init(neo1973_gta02_init); | |||
493 | 491 | ||
494 | static void __exit neo1973_gta02_exit(void) | 492 | static void __exit neo1973_gta02_exit(void) |
495 | { | 493 | { |
496 | snd_soc_unregister_dai(&bt_dai); | 494 | snd_soc_unregister_dai(&neo1973_gta02_snd_device->dev, -1); |
497 | platform_device_unregister(neo1973_gta02_snd_device); | 495 | platform_device_unregister(neo1973_gta02_snd_device); |
498 | gpio_free(GTA02_GPIO_HP_IN); | 496 | gpio_free(GTA02_GPIO_HP_IN); |
499 | gpio_free(GTA02_GPIO_AMP_SHUT); | 497 | gpio_free(GTA02_GPIO_AMP_SHUT); |
diff --git a/sound/soc/s3c24xx/neo1973_wm8753.c b/sound/soc/s3c24xx/neo1973_wm8753.c index 0cb4f86f6d1e..d7a39a0fe99b 100644 --- a/sound/soc/s3c24xx/neo1973_wm8753.c +++ b/sound/soc/s3c24xx/neo1973_wm8753.c | |||
@@ -57,8 +57,8 @@ static int neo1973_hifi_hw_params(struct snd_pcm_substream *substream, | |||
57 | struct snd_pcm_hw_params *params) | 57 | struct snd_pcm_hw_params *params) |
58 | { | 58 | { |
59 | struct snd_soc_pcm_runtime *rtd = substream->private_data; | 59 | struct snd_soc_pcm_runtime *rtd = substream->private_data; |
60 | struct snd_soc_dai *codec_dai = rtd->dai->codec_dai; | 60 | struct snd_soc_dai *codec_dai = rtd->codec_dai; |
61 | struct snd_soc_dai *cpu_dai = rtd->dai->cpu_dai; | 61 | struct snd_soc_dai *cpu_dai = rtd->cpu_dai; |
62 | unsigned int pll_out = 0, bclk = 0; | 62 | unsigned int pll_out = 0, bclk = 0; |
63 | int ret = 0; | 63 | int ret = 0; |
64 | unsigned long iis_clkrate; | 64 | unsigned long iis_clkrate; |
@@ -147,7 +147,7 @@ static int neo1973_hifi_hw_params(struct snd_pcm_substream *substream, | |||
147 | static int neo1973_hifi_hw_free(struct snd_pcm_substream *substream) | 147 | static int neo1973_hifi_hw_free(struct snd_pcm_substream *substream) |
148 | { | 148 | { |
149 | struct snd_soc_pcm_runtime *rtd = substream->private_data; | 149 | struct snd_soc_pcm_runtime *rtd = substream->private_data; |
150 | struct snd_soc_dai *codec_dai = rtd->dai->codec_dai; | 150 | struct snd_soc_dai *codec_dai = rtd->codec_dai; |
151 | 151 | ||
152 | pr_debug("Entered %s\n", __func__); | 152 | pr_debug("Entered %s\n", __func__); |
153 | 153 | ||
@@ -167,7 +167,7 @@ static int neo1973_voice_hw_params(struct snd_pcm_substream *substream, | |||
167 | struct snd_pcm_hw_params *params) | 167 | struct snd_pcm_hw_params *params) |
168 | { | 168 | { |
169 | struct snd_soc_pcm_runtime *rtd = substream->private_data; | 169 | struct snd_soc_pcm_runtime *rtd = substream->private_data; |
170 | struct snd_soc_dai *codec_dai = rtd->dai->codec_dai; | 170 | struct snd_soc_dai *codec_dai = rtd->codec_dai; |
171 | unsigned int pcmdiv = 0; | 171 | unsigned int pcmdiv = 0; |
172 | int ret = 0; | 172 | int ret = 0; |
173 | unsigned long iis_clkrate; | 173 | unsigned long iis_clkrate; |
@@ -213,7 +213,7 @@ static int neo1973_voice_hw_params(struct snd_pcm_substream *substream, | |||
213 | static int neo1973_voice_hw_free(struct snd_pcm_substream *substream) | 213 | static int neo1973_voice_hw_free(struct snd_pcm_substream *substream) |
214 | { | 214 | { |
215 | struct snd_soc_pcm_runtime *rtd = substream->private_data; | 215 | struct snd_soc_pcm_runtime *rtd = substream->private_data; |
216 | struct snd_soc_dai *codec_dai = rtd->dai->codec_dai; | 216 | struct snd_soc_dai *codec_dai = rtd->codec_dai; |
217 | 217 | ||
218 | pr_debug("Entered %s\n", __func__); | 218 | pr_debug("Entered %s\n", __func__); |
219 | 219 | ||
@@ -499,8 +499,9 @@ static const struct snd_kcontrol_new wm8753_neo1973_controls[] = { | |||
499 | * neo1973 II. It is missing logic to detect hp/mic insertions and logic | 499 | * neo1973 II. It is missing logic to detect hp/mic insertions and logic |
500 | * to re-route the audio in such an event. | 500 | * to re-route the audio in such an event. |
501 | */ | 501 | */ |
502 | static int neo1973_wm8753_init(struct snd_soc_codec *codec) | 502 | static int neo1973_wm8753_init(struct snd_soc_pcm_runtime *rtd) |
503 | { | 503 | { |
504 | struct snd_soc_codec *codec = rtd->codec; | ||
504 | int err; | 505 | int err; |
505 | 506 | ||
506 | pr_debug("Entered %s\n", __func__); | 507 | pr_debug("Entered %s\n", __func__); |
@@ -538,8 +539,7 @@ static int neo1973_wm8753_init(struct snd_soc_codec *codec) | |||
538 | * BT Codec DAI | 539 | * BT Codec DAI |
539 | */ | 540 | */ |
540 | static struct snd_soc_dai bt_dai = { | 541 | static struct snd_soc_dai bt_dai = { |
541 | .name = "Bluetooth", | 542 | .name = "bluetooth-dai", |
542 | .id = 0, | ||
543 | .playback = { | 543 | .playback = { |
544 | .channels_min = 1, | 544 | .channels_min = 1, |
545 | .channels_max = 1, | 545 | .channels_max = 1, |
@@ -556,32 +556,30 @@ static struct snd_soc_dai_link neo1973_dai[] = { | |||
556 | { /* Hifi Playback - for similatious use with voice below */ | 556 | { /* Hifi Playback - for similatious use with voice below */ |
557 | .name = "WM8753", | 557 | .name = "WM8753", |
558 | .stream_name = "WM8753 HiFi", | 558 | .stream_name = "WM8753 HiFi", |
559 | .cpu_dai = &s3c24xx_i2s_dai, | 559 | .platform_name = "s3c24xx-pcm-audio", |
560 | .codec_dai = &wm8753_dai[WM8753_DAI_HIFI], | 560 | .cpu_dai_name = "s3c24xx-i2s", |
561 | .codec_dai_name = "wm8753-hifi", | ||
562 | .codec_name = "wm8753-codec.0-0x1a", | ||
561 | .init = neo1973_wm8753_init, | 563 | .init = neo1973_wm8753_init, |
562 | .ops = &neo1973_hifi_ops, | 564 | .ops = &neo1973_hifi_ops, |
563 | }, | 565 | }, |
564 | { /* Voice via BT */ | 566 | { /* Voice via BT */ |
565 | .name = "Bluetooth", | 567 | .name = "Bluetooth", |
566 | .stream_name = "Voice", | 568 | .stream_name = "Voice", |
567 | .cpu_dai = &bt_dai, | 569 | .platform_name = "s3c24xx-pcm-audio", |
568 | .codec_dai = &wm8753_dai[WM8753_DAI_VOICE], | 570 | .cpu_dai_name = "bluetooth-dai", |
571 | .codec_dai_name = "wm8753-voice", | ||
572 | .codec_name = "wm8753-codec.0-0x1a", | ||
569 | .ops = &neo1973_voice_ops, | 573 | .ops = &neo1973_voice_ops, |
570 | }, | 574 | }, |
571 | }; | 575 | }; |
572 | 576 | ||
573 | static struct snd_soc_card neo1973 = { | 577 | static struct snd_soc_card neo1973 = { |
574 | .name = "neo1973", | 578 | .name = "neo1973", |
575 | .platform = &s3c24xx_soc_platform, | ||
576 | .dai_link = neo1973_dai, | 579 | .dai_link = neo1973_dai, |
577 | .num_links = ARRAY_SIZE(neo1973_dai), | 580 | .num_links = ARRAY_SIZE(neo1973_dai), |
578 | }; | 581 | }; |
579 | 582 | ||
580 | static struct snd_soc_device neo1973_snd_devdata = { | ||
581 | .card = &neo1973, | ||
582 | .codec_dev = &soc_codec_dev_wm8753, | ||
583 | }; | ||
584 | |||
585 | static int lm4857_i2c_probe(struct i2c_client *client, | 583 | static int lm4857_i2c_probe(struct i2c_client *client, |
586 | const struct i2c_device_id *id) | 584 | const struct i2c_device_id *id) |
587 | { | 585 | { |
@@ -673,8 +671,7 @@ static int __init neo1973_init(void) | |||
673 | if (!neo1973_snd_device) | 671 | if (!neo1973_snd_device) |
674 | return -ENOMEM; | 672 | return -ENOMEM; |
675 | 673 | ||
676 | platform_set_drvdata(neo1973_snd_device, &neo1973_snd_devdata); | 674 | platform_set_drvdata(neo1973_snd_device, &neo1973); |
677 | neo1973_snd_devdata.dev = &neo1973_snd_device->dev; | ||
678 | ret = platform_device_add(neo1973_snd_device); | 675 | ret = platform_device_add(neo1973_snd_device); |
679 | 676 | ||
680 | if (ret) { | 677 | if (ret) { |
diff --git a/sound/soc/s3c24xx/s3c-ac97.c b/sound/soc/s3c24xx/s3c-ac97.c index 31f6d45b6384..26f4ed90a0ee 100644 --- a/sound/soc/s3c24xx/s3c-ac97.c +++ b/sound/soc/s3c24xx/s3c-ac97.c | |||
@@ -222,7 +222,7 @@ static int s3c_ac97_hw_params(struct snd_pcm_substream *substream, | |||
222 | struct snd_soc_dai *dai) | 222 | struct snd_soc_dai *dai) |
223 | { | 223 | { |
224 | struct snd_soc_pcm_runtime *rtd = substream->private_data; | 224 | struct snd_soc_pcm_runtime *rtd = substream->private_data; |
225 | struct snd_soc_dai *cpu_dai = rtd->dai->cpu_dai; | 225 | struct snd_soc_dai *cpu_dai = rtd->cpu_dai; |
226 | struct s3c_dma_params *dma_data; | 226 | struct s3c_dma_params *dma_data; |
227 | 227 | ||
228 | if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) | 228 | if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) |
@@ -241,7 +241,7 @@ static int s3c_ac97_trigger(struct snd_pcm_substream *substream, int cmd, | |||
241 | u32 ac_glbctrl; | 241 | u32 ac_glbctrl; |
242 | struct snd_soc_pcm_runtime *rtd = substream->private_data; | 242 | struct snd_soc_pcm_runtime *rtd = substream->private_data; |
243 | struct s3c_dma_params *dma_data = | 243 | struct s3c_dma_params *dma_data = |
244 | snd_soc_dai_get_dma_data(rtd->dai->cpu_dai, substream); | 244 | snd_soc_dai_get_dma_data(rtd->cpu_dai, substream); |
245 | 245 | ||
246 | ac_glbctrl = readl(s3c_ac97.regs + S3C_AC97_GLBCTRL); | 246 | ac_glbctrl = readl(s3c_ac97.regs + S3C_AC97_GLBCTRL); |
247 | if (substream->stream == SNDRV_PCM_STREAM_CAPTURE) | 247 | if (substream->stream == SNDRV_PCM_STREAM_CAPTURE) |
@@ -277,7 +277,7 @@ static int s3c_ac97_hw_mic_params(struct snd_pcm_substream *substream, | |||
277 | struct snd_soc_dai *dai) | 277 | struct snd_soc_dai *dai) |
278 | { | 278 | { |
279 | struct snd_soc_pcm_runtime *rtd = substream->private_data; | 279 | struct snd_soc_pcm_runtime *rtd = substream->private_data; |
280 | struct snd_soc_dai *cpu_dai = rtd->dai->cpu_dai; | 280 | struct snd_soc_dai *cpu_dai = rtd->cpu_dai; |
281 | 281 | ||
282 | if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) | 282 | if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) |
283 | return -ENODEV; | 283 | return -ENODEV; |
@@ -293,7 +293,7 @@ static int s3c_ac97_mic_trigger(struct snd_pcm_substream *substream, | |||
293 | u32 ac_glbctrl; | 293 | u32 ac_glbctrl; |
294 | struct snd_soc_pcm_runtime *rtd = substream->private_data; | 294 | struct snd_soc_pcm_runtime *rtd = substream->private_data; |
295 | struct s3c_dma_params *dma_data = | 295 | struct s3c_dma_params *dma_data = |
296 | snd_soc_dai_get_dma_data(rtd->dai->cpu_dai, substream); | 296 | snd_soc_dai_get_dma_data(rtd->cpu_dai, substream); |
297 | 297 | ||
298 | ac_glbctrl = readl(s3c_ac97.regs + S3C_AC97_GLBCTRL); | 298 | ac_glbctrl = readl(s3c_ac97.regs + S3C_AC97_GLBCTRL); |
299 | ac_glbctrl &= ~S3C_AC97_GLBCTRL_MICINTM_MASK; | 299 | ac_glbctrl &= ~S3C_AC97_GLBCTRL_MICINTM_MASK; |
@@ -328,10 +328,9 @@ static struct snd_soc_dai_ops s3c_ac97_mic_dai_ops = { | |||
328 | .trigger = s3c_ac97_mic_trigger, | 328 | .trigger = s3c_ac97_mic_trigger, |
329 | }; | 329 | }; |
330 | 330 | ||
331 | struct snd_soc_dai s3c_ac97_dai[] = { | 331 | static struct snd_soc_dai_driver s3c_ac97_dai[] = { |
332 | [S3C_AC97_DAI_PCM] = { | 332 | [S3C_AC97_DAI_PCM] = { |
333 | .name = "s3c-ac97", | 333 | .name = "s3c-ac97", |
334 | .id = S3C_AC97_DAI_PCM, | ||
335 | .ac97_control = 1, | 334 | .ac97_control = 1, |
336 | .playback = { | 335 | .playback = { |
337 | .stream_name = "AC97 Playback", | 336 | .stream_name = "AC97 Playback", |
@@ -349,7 +348,6 @@ struct snd_soc_dai s3c_ac97_dai[] = { | |||
349 | }, | 348 | }, |
350 | [S3C_AC97_DAI_MIC] = { | 349 | [S3C_AC97_DAI_MIC] = { |
351 | .name = "s3c-ac97-mic", | 350 | .name = "s3c-ac97-mic", |
352 | .id = S3C_AC97_DAI_MIC, | ||
353 | .ac97_control = 1, | 351 | .ac97_control = 1, |
354 | .capture = { | 352 | .capture = { |
355 | .stream_name = "AC97 Mic Capture", | 353 | .stream_name = "AC97 Mic Capture", |
@@ -360,7 +358,6 @@ struct snd_soc_dai s3c_ac97_dai[] = { | |||
360 | .ops = &s3c_ac97_mic_dai_ops, | 358 | .ops = &s3c_ac97_mic_dai_ops, |
361 | }, | 359 | }, |
362 | }; | 360 | }; |
363 | EXPORT_SYMBOL_GPL(s3c_ac97_dai); | ||
364 | 361 | ||
365 | static __devinit int s3c_ac97_probe(struct platform_device *pdev) | 362 | static __devinit int s3c_ac97_probe(struct platform_device *pdev) |
366 | { | 363 | { |
@@ -449,10 +446,8 @@ static __devinit int s3c_ac97_probe(struct platform_device *pdev) | |||
449 | goto err4; | 446 | goto err4; |
450 | } | 447 | } |
451 | 448 | ||
452 | s3c_ac97_dai[S3C_AC97_DAI_PCM].dev = &pdev->dev; | 449 | ret = snd_soc_register_dais(&pdev->dev, s3c_ac97_dai, |
453 | s3c_ac97_dai[S3C_AC97_DAI_MIC].dev = &pdev->dev; | 450 | ARRAY_SIZE(s3c_ac97_dai)); |
454 | |||
455 | ret = snd_soc_register_dais(s3c_ac97_dai, ARRAY_SIZE(s3c_ac97_dai)); | ||
456 | if (ret) | 451 | if (ret) |
457 | goto err5; | 452 | goto err5; |
458 | 453 | ||
@@ -476,7 +471,7 @@ static __devexit int s3c_ac97_remove(struct platform_device *pdev) | |||
476 | { | 471 | { |
477 | struct resource *mem_res, *irq_res; | 472 | struct resource *mem_res, *irq_res; |
478 | 473 | ||
479 | snd_soc_unregister_dais(s3c_ac97_dai, ARRAY_SIZE(s3c_ac97_dai)); | 474 | snd_soc_unregister_dais(&pdev->dev, ARRAY_SIZE(s3c_ac97_dai)); |
480 | 475 | ||
481 | irq_res = platform_get_resource(pdev, IORESOURCE_IRQ, 0); | 476 | irq_res = platform_get_resource(pdev, IORESOURCE_IRQ, 0); |
482 | if (irq_res) | 477 | if (irq_res) |
@@ -518,3 +513,4 @@ module_exit(s3c_ac97_exit); | |||
518 | MODULE_AUTHOR("Jaswinder Singh, <jassi.brar@samsung.com>"); | 513 | MODULE_AUTHOR("Jaswinder Singh, <jassi.brar@samsung.com>"); |
519 | MODULE_DESCRIPTION("AC97 driver for the Samsung SoC"); | 514 | MODULE_DESCRIPTION("AC97 driver for the Samsung SoC"); |
520 | MODULE_LICENSE("GPL"); | 515 | MODULE_LICENSE("GPL"); |
516 | MODULE_ALIAS("platform:s3c-ac97"); | ||
diff --git a/sound/soc/s3c24xx/s3c-ac97.h b/sound/soc/s3c24xx/s3c-ac97.h index 278198379def..5dcedd07fdbb 100644 --- a/sound/soc/s3c24xx/s3c-ac97.h +++ b/sound/soc/s3c24xx/s3c-ac97.h | |||
@@ -18,6 +18,4 @@ | |||
18 | #define S3C_AC97_DAI_PCM 0 | 18 | #define S3C_AC97_DAI_PCM 0 |
19 | #define S3C_AC97_DAI_MIC 1 | 19 | #define S3C_AC97_DAI_MIC 1 |
20 | 20 | ||
21 | extern struct snd_soc_dai s3c_ac97_dai[]; | ||
22 | |||
23 | #endif /* __S3C_AC97_H_ */ | 21 | #endif /* __S3C_AC97_H_ */ |
diff --git a/sound/soc/s3c24xx/s3c-dma.c b/sound/soc/s3c24xx/s3c-dma.c index 1b61c23ff300..54bff83c98b4 100644 --- a/sound/soc/s3c24xx/s3c-dma.c +++ b/sound/soc/s3c24xx/s3c-dma.c | |||
@@ -147,7 +147,7 @@ static int s3c_dma_hw_params(struct snd_pcm_substream *substream, | |||
147 | struct snd_soc_pcm_runtime *rtd = substream->private_data; | 147 | struct snd_soc_pcm_runtime *rtd = substream->private_data; |
148 | unsigned long totbytes = params_buffer_bytes(params); | 148 | unsigned long totbytes = params_buffer_bytes(params); |
149 | struct s3c_dma_params *dma = | 149 | struct s3c_dma_params *dma = |
150 | snd_soc_dai_get_dma_data(rtd->dai->cpu_dai, substream); | 150 | snd_soc_dai_get_dma_data(rtd->cpu_dai, substream); |
151 | int ret = 0; | 151 | int ret = 0; |
152 | 152 | ||
153 | 153 | ||
@@ -441,14 +441,14 @@ static int s3c_dma_new(struct snd_card *card, | |||
441 | if (!card->dev->coherent_dma_mask) | 441 | if (!card->dev->coherent_dma_mask) |
442 | card->dev->coherent_dma_mask = 0xffffffff; | 442 | card->dev->coherent_dma_mask = 0xffffffff; |
443 | 443 | ||
444 | if (dai->playback.channels_min) { | 444 | if (dai->driver->playback.channels_min) { |
445 | ret = s3c_preallocate_dma_buffer(pcm, | 445 | ret = s3c_preallocate_dma_buffer(pcm, |
446 | SNDRV_PCM_STREAM_PLAYBACK); | 446 | SNDRV_PCM_STREAM_PLAYBACK); |
447 | if (ret) | 447 | if (ret) |
448 | goto out; | 448 | goto out; |
449 | } | 449 | } |
450 | 450 | ||
451 | if (dai->capture.channels_min) { | 451 | if (dai->driver->capture.channels_min) { |
452 | ret = s3c_preallocate_dma_buffer(pcm, | 452 | ret = s3c_preallocate_dma_buffer(pcm, |
453 | SNDRV_PCM_STREAM_CAPTURE); | 453 | SNDRV_PCM_STREAM_CAPTURE); |
454 | if (ret) | 454 | if (ret) |
@@ -458,26 +458,46 @@ static int s3c_dma_new(struct snd_card *card, | |||
458 | return ret; | 458 | return ret; |
459 | } | 459 | } |
460 | 460 | ||
461 | struct snd_soc_platform s3c24xx_soc_platform = { | 461 | static struct snd_soc_platform_driver s3c24xx_soc_platform = { |
462 | .name = "s3c24xx-audio", | 462 | .ops = &s3c_dma_ops, |
463 | .pcm_ops = &s3c_dma_ops, | ||
464 | .pcm_new = s3c_dma_new, | 463 | .pcm_new = s3c_dma_new, |
465 | .pcm_free = s3c_dma_free_dma_buffers, | 464 | .pcm_free = s3c_dma_free_dma_buffers, |
466 | }; | 465 | }; |
467 | EXPORT_SYMBOL_GPL(s3c24xx_soc_platform); | ||
468 | 466 | ||
469 | static int __init s3c24xx_soc_platform_init(void) | 467 | static int __devinit s3c24xx_soc_platform_probe(struct platform_device *pdev) |
470 | { | 468 | { |
471 | return snd_soc_register_platform(&s3c24xx_soc_platform); | 469 | return snd_soc_register_platform(&pdev->dev, &s3c24xx_soc_platform); |
472 | } | 470 | } |
473 | module_init(s3c24xx_soc_platform_init); | ||
474 | 471 | ||
475 | static void __exit s3c24xx_soc_platform_exit(void) | 472 | static int __devexit s3c24xx_soc_platform_remove(struct platform_device *pdev) |
476 | { | 473 | { |
477 | snd_soc_unregister_platform(&s3c24xx_soc_platform); | 474 | snd_soc_unregister_platform(&pdev->dev); |
475 | return 0; | ||
476 | } | ||
477 | |||
478 | static struct platform_driver s3c24xx_pcm_driver = { | ||
479 | .driver = { | ||
480 | .name = "s3c24xx-pcm-audio", | ||
481 | .owner = THIS_MODULE, | ||
482 | }, | ||
483 | |||
484 | .probe = s3c24xx_soc_platform_probe, | ||
485 | .remove = __devexit_p(s3c24xx_soc_platform_remove), | ||
486 | }; | ||
487 | |||
488 | static int __init snd_s3c24xx_pcm_init(void) | ||
489 | { | ||
490 | return platform_driver_register(&s3c24xx_pcm_driver); | ||
491 | } | ||
492 | module_init(snd_s3c24xx_pcm_init); | ||
493 | |||
494 | static void __exit snd_s3c24xx_pcm_exit(void) | ||
495 | { | ||
496 | platform_driver_unregister(&s3c24xx_pcm_driver); | ||
478 | } | 497 | } |
479 | module_exit(s3c24xx_soc_platform_exit); | 498 | module_exit(snd_s3c24xx_pcm_exit); |
480 | 499 | ||
481 | MODULE_AUTHOR("Ben Dooks, <ben@simtec.co.uk>"); | 500 | MODULE_AUTHOR("Ben Dooks, <ben@simtec.co.uk>"); |
482 | MODULE_DESCRIPTION("Samsung S3C Audio DMA module"); | 501 | MODULE_DESCRIPTION("Samsung S3C Audio DMA module"); |
483 | MODULE_LICENSE("GPL"); | 502 | MODULE_LICENSE("GPL"); |
503 | MODULE_ALIAS("platform:s3c24xx-pcm-audio"); | ||
diff --git a/sound/soc/s3c24xx/s3c-dma.h b/sound/soc/s3c24xx/s3c-dma.h index 69bb6bf6fc1c..748c07d7c075 100644 --- a/sound/soc/s3c24xx/s3c-dma.h +++ b/sound/soc/s3c24xx/s3c-dma.h | |||
@@ -25,7 +25,6 @@ struct s3c_dma_params { | |||
25 | #define S3C24XX_DAI_I2S 0 | 25 | #define S3C24XX_DAI_I2S 0 |
26 | 26 | ||
27 | /* platform data */ | 27 | /* platform data */ |
28 | extern struct snd_soc_platform s3c24xx_soc_platform; | ||
29 | extern struct snd_ac97_bus_ops s3c24xx_ac97_ops; | 28 | extern struct snd_ac97_bus_ops s3c24xx_ac97_ops; |
30 | 29 | ||
31 | #endif | 30 | #endif |
diff --git a/sound/soc/s3c24xx/s3c-i2s-v2.c b/sound/soc/s3c24xx/s3c-i2s-v2.c index 64376b2aac73..b3866d5b19e9 100644 --- a/sound/soc/s3c24xx/s3c-i2s-v2.c +++ b/sound/soc/s3c24xx/s3c-i2s-v2.c | |||
@@ -49,7 +49,7 @@ | |||
49 | 49 | ||
50 | static inline struct s3c_i2sv2_info *to_info(struct snd_soc_dai *cpu_dai) | 50 | static inline struct s3c_i2sv2_info *to_info(struct snd_soc_dai *cpu_dai) |
51 | { | 51 | { |
52 | return cpu_dai->private_data; | 52 | return snd_soc_dai_get_drvdata(cpu_dai); |
53 | } | 53 | } |
54 | 54 | ||
55 | #define bit_set(v, b) (((v) & (b)) ? 1 : 0) | 55 | #define bit_set(v, b) (((v) & (b)) ? 1 : 0) |
@@ -307,11 +307,9 @@ static int s3c2412_i2s_set_fmt(struct snd_soc_dai *cpu_dai, | |||
307 | 307 | ||
308 | static int s3c_i2sv2_hw_params(struct snd_pcm_substream *substream, | 308 | static int s3c_i2sv2_hw_params(struct snd_pcm_substream *substream, |
309 | struct snd_pcm_hw_params *params, | 309 | struct snd_pcm_hw_params *params, |
310 | struct snd_soc_dai *socdai) | 310 | struct snd_soc_dai *dai) |
311 | { | 311 | { |
312 | struct snd_soc_pcm_runtime *rtd = substream->private_data; | 312 | struct s3c_i2sv2_info *i2s = to_info(dai); |
313 | struct snd_soc_dai_link *dai = rtd->dai; | ||
314 | struct s3c_i2sv2_info *i2s = to_info(dai->cpu_dai); | ||
315 | struct s3c_dma_params *dma_data; | 313 | struct s3c_dma_params *dma_data; |
316 | u32 iismod; | 314 | u32 iismod; |
317 | 315 | ||
@@ -322,7 +320,7 @@ static int s3c_i2sv2_hw_params(struct snd_pcm_substream *substream, | |||
322 | else | 320 | else |
323 | dma_data = i2s->dma_capture; | 321 | dma_data = i2s->dma_capture; |
324 | 322 | ||
325 | snd_soc_dai_set_dma_data(dai->cpu_dai, substream, dma_data); | 323 | snd_soc_dai_set_dma_data(dai, substream, dma_data); |
326 | 324 | ||
327 | /* Working copies of register */ | 325 | /* Working copies of register */ |
328 | iismod = readl(i2s->regs + S3C2412_IISMOD); | 326 | iismod = readl(i2s->regs + S3C2412_IISMOD); |
@@ -396,12 +394,12 @@ static int s3c2412_i2s_trigger(struct snd_pcm_substream *substream, int cmd, | |||
396 | struct snd_soc_dai *dai) | 394 | struct snd_soc_dai *dai) |
397 | { | 395 | { |
398 | struct snd_soc_pcm_runtime *rtd = substream->private_data; | 396 | struct snd_soc_pcm_runtime *rtd = substream->private_data; |
399 | struct s3c_i2sv2_info *i2s = to_info(rtd->dai->cpu_dai); | 397 | struct s3c_i2sv2_info *i2s = to_info(rtd->cpu_dai); |
400 | int capture = (substream->stream == SNDRV_PCM_STREAM_CAPTURE); | 398 | int capture = (substream->stream == SNDRV_PCM_STREAM_CAPTURE); |
401 | unsigned long irqs; | 399 | unsigned long irqs; |
402 | int ret = 0; | 400 | int ret = 0; |
403 | struct s3c_dma_params *dma_data = | 401 | struct s3c_dma_params *dma_data = |
404 | snd_soc_dai_get_dma_data(rtd->dai->cpu_dai, substream); | 402 | snd_soc_dai_get_dma_data(rtd->cpu_dai, substream); |
405 | 403 | ||
406 | pr_debug("Entered %s\n", __func__); | 404 | pr_debug("Entered %s\n", __func__); |
407 | 405 | ||
@@ -640,36 +638,17 @@ int s3c_i2sv2_iis_calc_rate(struct s3c_i2sv2_rate_calc *info, | |||
640 | } | 638 | } |
641 | EXPORT_SYMBOL_GPL(s3c_i2sv2_iis_calc_rate); | 639 | EXPORT_SYMBOL_GPL(s3c_i2sv2_iis_calc_rate); |
642 | 640 | ||
643 | int s3c_i2sv2_probe(struct platform_device *pdev, | 641 | int s3c_i2sv2_probe(struct snd_soc_dai *dai, |
644 | struct snd_soc_dai *dai, | ||
645 | struct s3c_i2sv2_info *i2s, | 642 | struct s3c_i2sv2_info *i2s, |
646 | unsigned long base) | 643 | unsigned long base) |
647 | { | 644 | { |
648 | struct device *dev = &pdev->dev; | 645 | struct device *dev = dai->dev; |
649 | unsigned int iismod; | 646 | unsigned int iismod; |
650 | 647 | ||
651 | i2s->dev = dev; | 648 | i2s->dev = dev; |
652 | 649 | ||
653 | /* record our i2s structure for later use in the callbacks */ | 650 | /* record our i2s structure for later use in the callbacks */ |
654 | dai->private_data = i2s; | 651 | snd_soc_dai_set_drvdata(dai, i2s); |
655 | |||
656 | if (!base) { | ||
657 | struct resource *res = platform_get_resource(pdev, | ||
658 | IORESOURCE_MEM, | ||
659 | 0); | ||
660 | if (!res) { | ||
661 | dev_err(dev, "Unable to get register resource\n"); | ||
662 | return -ENXIO; | ||
663 | } | ||
664 | |||
665 | if (!request_mem_region(res->start, resource_size(res), | ||
666 | "s3c64xx-i2s-v4")) { | ||
667 | dev_err(dev, "Unable to request register region\n"); | ||
668 | return -EBUSY; | ||
669 | } | ||
670 | |||
671 | base = res->start; | ||
672 | } | ||
673 | 652 | ||
674 | i2s->regs = ioremap(base, 0x100); | 653 | i2s->regs = ioremap(base, 0x100); |
675 | if (i2s->regs == NULL) { | 654 | if (i2s->regs == NULL) { |
@@ -752,9 +731,10 @@ static int s3c2412_i2s_resume(struct snd_soc_dai *dai) | |||
752 | #define s3c2412_i2s_resume NULL | 731 | #define s3c2412_i2s_resume NULL |
753 | #endif | 732 | #endif |
754 | 733 | ||
755 | int s3c_i2sv2_register_dai(struct snd_soc_dai *dai) | 734 | int s3c_i2sv2_register_dai(struct device *dev, int id, |
735 | struct snd_soc_dai_driver *drv) | ||
756 | { | 736 | { |
757 | struct snd_soc_dai_ops *ops = dai->ops; | 737 | struct snd_soc_dai_ops *ops = drv->ops; |
758 | 738 | ||
759 | ops->trigger = s3c2412_i2s_trigger; | 739 | ops->trigger = s3c2412_i2s_trigger; |
760 | if (!ops->hw_params) | 740 | if (!ops->hw_params) |
@@ -767,10 +747,10 @@ int s3c_i2sv2_register_dai(struct snd_soc_dai *dai) | |||
767 | if (!ops->delay) | 747 | if (!ops->delay) |
768 | ops->delay = s3c2412_i2s_delay; | 748 | ops->delay = s3c2412_i2s_delay; |
769 | 749 | ||
770 | dai->suspend = s3c2412_i2s_suspend; | 750 | drv->suspend = s3c2412_i2s_suspend; |
771 | dai->resume = s3c2412_i2s_resume; | 751 | drv->resume = s3c2412_i2s_resume; |
772 | 752 | ||
773 | return snd_soc_register_dai(dai); | 753 | return snd_soc_register_dai(dev, drv); |
774 | } | 754 | } |
775 | EXPORT_SYMBOL_GPL(s3c_i2sv2_register_dai); | 755 | EXPORT_SYMBOL_GPL(s3c_i2sv2_register_dai); |
776 | 756 | ||
diff --git a/sound/soc/s3c24xx/s3c-i2s-v2.h b/sound/soc/s3c24xx/s3c-i2s-v2.h index 766f43a13d8b..d45830151484 100644 --- a/sound/soc/s3c24xx/s3c-i2s-v2.h +++ b/sound/soc/s3c24xx/s3c-i2s-v2.h | |||
@@ -66,6 +66,8 @@ struct s3c_i2sv2_info { | |||
66 | u32 suspend_iismod; | 66 | u32 suspend_iismod; |
67 | u32 suspend_iiscon; | 67 | u32 suspend_iiscon; |
68 | u32 suspend_iispsr; | 68 | u32 suspend_iispsr; |
69 | |||
70 | unsigned long base; | ||
69 | }; | 71 | }; |
70 | 72 | ||
71 | extern struct clk *s3c_i2sv2_get_clock(struct snd_soc_dai *cpu_dai); | 73 | extern struct clk *s3c_i2sv2_get_clock(struct snd_soc_dai *cpu_dai); |
@@ -81,23 +83,24 @@ extern int s3c_i2sv2_iis_calc_rate(struct s3c_i2sv2_rate_calc *info, | |||
81 | 83 | ||
82 | /** | 84 | /** |
83 | * s3c_i2sv2_probe - probe for i2s device helper | 85 | * s3c_i2sv2_probe - probe for i2s device helper |
84 | * @pdev: The platform device supplied to the original probe. | ||
85 | * @dai: The ASoC DAI structure supplied to the original probe. | 86 | * @dai: The ASoC DAI structure supplied to the original probe. |
86 | * @i2s: Our local i2s structure to fill in. | 87 | * @i2s: Our local i2s structure to fill in. |
87 | * @base: The base address for the registers. | 88 | * @base: The base address for the registers. |
88 | */ | 89 | */ |
89 | extern int s3c_i2sv2_probe(struct platform_device *pdev, | 90 | extern int s3c_i2sv2_probe(struct snd_soc_dai *dai, |
90 | struct snd_soc_dai *dai, | ||
91 | struct s3c_i2sv2_info *i2s, | 91 | struct s3c_i2sv2_info *i2s, |
92 | unsigned long base); | 92 | unsigned long base); |
93 | 93 | ||
94 | /** | 94 | /** |
95 | * s3c_i2sv2_register_dai - register dai with soc core | 95 | * s3c_i2sv2_register_dai - register dai with soc core |
96 | * @dai: The snd_soc_dai structure to register | 96 | * @dev: DAI device |
97 | * @id: DAI ID | ||
98 | * @drv: The driver structure to register | ||
97 | * | 99 | * |
98 | * Fill in any missing fields and then register the given dai with the | 100 | * Fill in any missing fields and then register the given dai with the |
99 | * soc core. | 101 | * soc core. |
100 | */ | 102 | */ |
101 | extern int s3c_i2sv2_register_dai(struct snd_soc_dai *dai); | 103 | extern int s3c_i2sv2_register_dai(struct device *dev, int id, |
104 | struct snd_soc_dai_driver *drv); | ||
102 | 105 | ||
103 | #endif /* __SND_SOC_S3C24XX_S3C_I2SV2_I2S_H */ | 106 | #endif /* __SND_SOC_S3C24XX_S3C_I2SV2_I2S_H */ |
diff --git a/sound/soc/s3c24xx/s3c-pcm.c b/sound/soc/s3c24xx/s3c-pcm.c index 326f0a9e7e30..6174e26e433e 100644 --- a/sound/soc/s3c24xx/s3c-pcm.c +++ b/sound/soc/s3c24xx/s3c-pcm.c | |||
@@ -64,11 +64,6 @@ static struct s3c_dma_params s3c_pcm_stereo_in[] = { | |||
64 | 64 | ||
65 | static struct s3c_pcm_info s3c_pcm[2]; | 65 | static struct s3c_pcm_info s3c_pcm[2]; |
66 | 66 | ||
67 | static inline struct s3c_pcm_info *to_info(struct snd_soc_dai *cpu_dai) | ||
68 | { | ||
69 | return cpu_dai->private_data; | ||
70 | } | ||
71 | |||
72 | static void s3c_pcm_snd_txctrl(struct s3c_pcm_info *pcm, int on) | 67 | static void s3c_pcm_snd_txctrl(struct s3c_pcm_info *pcm, int on) |
73 | { | 68 | { |
74 | void __iomem *regs = pcm->regs; | 69 | void __iomem *regs = pcm->regs; |
@@ -132,7 +127,7 @@ static int s3c_pcm_trigger(struct snd_pcm_substream *substream, int cmd, | |||
132 | struct snd_soc_dai *dai) | 127 | struct snd_soc_dai *dai) |
133 | { | 128 | { |
134 | struct snd_soc_pcm_runtime *rtd = substream->private_data; | 129 | struct snd_soc_pcm_runtime *rtd = substream->private_data; |
135 | struct s3c_pcm_info *pcm = to_info(rtd->dai->cpu_dai); | 130 | struct s3c_pcm_info *pcm = snd_soc_dai_get_drvdata(rtd->cpu_dai); |
136 | unsigned long flags; | 131 | unsigned long flags; |
137 | 132 | ||
138 | dev_dbg(pcm->dev, "Entered %s\n", __func__); | 133 | dev_dbg(pcm->dev, "Entered %s\n", __func__); |
@@ -176,8 +171,7 @@ static int s3c_pcm_hw_params(struct snd_pcm_substream *substream, | |||
176 | struct snd_soc_dai *socdai) | 171 | struct snd_soc_dai *socdai) |
177 | { | 172 | { |
178 | struct snd_soc_pcm_runtime *rtd = substream->private_data; | 173 | struct snd_soc_pcm_runtime *rtd = substream->private_data; |
179 | struct snd_soc_dai_link *dai = rtd->dai; | 174 | struct s3c_pcm_info *pcm = snd_soc_dai_get_drvdata(rtd->cpu_dai); |
180 | struct s3c_pcm_info *pcm = to_info(dai->cpu_dai); | ||
181 | struct s3c_dma_params *dma_data; | 175 | struct s3c_dma_params *dma_data; |
182 | void __iomem *regs = pcm->regs; | 176 | void __iomem *regs = pcm->regs; |
183 | struct clk *clk; | 177 | struct clk *clk; |
@@ -192,7 +186,7 @@ static int s3c_pcm_hw_params(struct snd_pcm_substream *substream, | |||
192 | else | 186 | else |
193 | dma_data = pcm->dma_capture; | 187 | dma_data = pcm->dma_capture; |
194 | 188 | ||
195 | snd_soc_dai_set_dma_data(dai->cpu_dai, substream, dma_data); | 189 | snd_soc_dai_set_dma_data(rtd->cpu_dai, substream, dma_data); |
196 | 190 | ||
197 | /* Strictly check for sample size */ | 191 | /* Strictly check for sample size */ |
198 | switch (params_format(params)) { | 192 | switch (params_format(params)) { |
@@ -242,7 +236,7 @@ static int s3c_pcm_hw_params(struct snd_pcm_substream *substream, | |||
242 | static int s3c_pcm_set_fmt(struct snd_soc_dai *cpu_dai, | 236 | static int s3c_pcm_set_fmt(struct snd_soc_dai *cpu_dai, |
243 | unsigned int fmt) | 237 | unsigned int fmt) |
244 | { | 238 | { |
245 | struct s3c_pcm_info *pcm = to_info(cpu_dai); | 239 | struct s3c_pcm_info *pcm = snd_soc_dai_get_drvdata(cpu_dai); |
246 | void __iomem *regs = pcm->regs; | 240 | void __iomem *regs = pcm->regs; |
247 | unsigned long flags; | 241 | unsigned long flags; |
248 | int ret = 0; | 242 | int ret = 0; |
@@ -313,7 +307,7 @@ exit: | |||
313 | static int s3c_pcm_set_clkdiv(struct snd_soc_dai *cpu_dai, | 307 | static int s3c_pcm_set_clkdiv(struct snd_soc_dai *cpu_dai, |
314 | int div_id, int div) | 308 | int div_id, int div) |
315 | { | 309 | { |
316 | struct s3c_pcm_info *pcm = to_info(cpu_dai); | 310 | struct s3c_pcm_info *pcm = snd_soc_dai_get_drvdata(cpu_dai); |
317 | 311 | ||
318 | switch (div_id) { | 312 | switch (div_id) { |
319 | case S3C_PCM_SCLK_PER_FS: | 313 | case S3C_PCM_SCLK_PER_FS: |
@@ -330,7 +324,7 @@ static int s3c_pcm_set_clkdiv(struct snd_soc_dai *cpu_dai, | |||
330 | static int s3c_pcm_set_sysclk(struct snd_soc_dai *cpu_dai, | 324 | static int s3c_pcm_set_sysclk(struct snd_soc_dai *cpu_dai, |
331 | int clk_id, unsigned int freq, int dir) | 325 | int clk_id, unsigned int freq, int dir) |
332 | { | 326 | { |
333 | struct s3c_pcm_info *pcm = to_info(cpu_dai); | 327 | struct s3c_pcm_info *pcm = snd_soc_dai_get_drvdata(cpu_dai); |
334 | void __iomem *regs = pcm->regs; | 328 | void __iomem *regs = pcm->regs; |
335 | u32 clkctl = readl(regs + S3C_PCM_CLKCTL); | 329 | u32 clkctl = readl(regs + S3C_PCM_CLKCTL); |
336 | 330 | ||
@@ -366,10 +360,9 @@ static struct snd_soc_dai_ops s3c_pcm_dai_ops = { | |||
366 | 360 | ||
367 | #define S3C_PCM_RATES SNDRV_PCM_RATE_8000_96000 | 361 | #define S3C_PCM_RATES SNDRV_PCM_RATE_8000_96000 |
368 | 362 | ||
369 | #define S3C_PCM_DECLARE(n) \ | 363 | #define S3C_PCM_DAI_DECLARE \ |
370 | { \ | 364 | { \ |
371 | .name = "samsung-pcm", \ | 365 | .name = "samsung-dai", \ |
372 | .id = (n), \ | ||
373 | .symmetric_rates = 1, \ | 366 | .symmetric_rates = 1, \ |
374 | .ops = &s3c_pcm_dai_ops, \ | 367 | .ops = &s3c_pcm_dai_ops, \ |
375 | .playback = { \ | 368 | .playback = { \ |
@@ -386,16 +379,15 @@ static struct snd_soc_dai_ops s3c_pcm_dai_ops = { | |||
386 | }, \ | 379 | }, \ |
387 | } | 380 | } |
388 | 381 | ||
389 | struct snd_soc_dai s3c_pcm_dai[] = { | 382 | struct snd_soc_dai_driver s3c_pcm_dai[] = { |
390 | S3C_PCM_DECLARE(0), | 383 | S3C_PCM_DAI_DECLARE, |
391 | S3C_PCM_DECLARE(1), | 384 | S3C_PCM_DAI_DECLARE, |
392 | }; | 385 | }; |
393 | EXPORT_SYMBOL_GPL(s3c_pcm_dai); | 386 | EXPORT_SYMBOL_GPL(s3c_pcm_dai); |
394 | 387 | ||
395 | static __devinit int s3c_pcm_dev_probe(struct platform_device *pdev) | 388 | static __devinit int s3c_pcm_dev_probe(struct platform_device *pdev) |
396 | { | 389 | { |
397 | struct s3c_pcm_info *pcm; | 390 | struct s3c_pcm_info *pcm; |
398 | struct snd_soc_dai *dai; | ||
399 | struct resource *mem_res, *dmatx_res, *dmarx_res; | 391 | struct resource *mem_res, *dmatx_res, *dmarx_res; |
400 | struct s3c_audio_pdata *pcm_pdata; | 392 | struct s3c_audio_pdata *pcm_pdata; |
401 | int ret; | 393 | int ret; |
@@ -437,9 +429,6 @@ static __devinit int s3c_pcm_dev_probe(struct platform_device *pdev) | |||
437 | 429 | ||
438 | spin_lock_init(&pcm->lock); | 430 | spin_lock_init(&pcm->lock); |
439 | 431 | ||
440 | dai = &s3c_pcm_dai[pdev->id]; | ||
441 | dai->dev = &pdev->dev; | ||
442 | |||
443 | /* Default is 128fs */ | 432 | /* Default is 128fs */ |
444 | pcm->sclk_per_fs = 128; | 433 | pcm->sclk_per_fs = 128; |
445 | 434 | ||
@@ -452,7 +441,7 @@ static __devinit int s3c_pcm_dev_probe(struct platform_device *pdev) | |||
452 | clk_enable(pcm->cclk); | 441 | clk_enable(pcm->cclk); |
453 | 442 | ||
454 | /* record our pcm structure for later use in the callbacks */ | 443 | /* record our pcm structure for later use in the callbacks */ |
455 | dai->private_data = pcm; | 444 | dev_set_drvdata(&pdev->dev, pcm); |
456 | 445 | ||
457 | if (!request_mem_region(mem_res->start, | 446 | if (!request_mem_region(mem_res->start, |
458 | resource_size(mem_res), "samsung-pcm")) { | 447 | resource_size(mem_res), "samsung-pcm")) { |
@@ -476,7 +465,7 @@ static __devinit int s3c_pcm_dev_probe(struct platform_device *pdev) | |||
476 | } | 465 | } |
477 | clk_enable(pcm->pclk); | 466 | clk_enable(pcm->pclk); |
478 | 467 | ||
479 | ret = snd_soc_register_dai(dai); | 468 | ret = snd_soc_register_dai(&pdev->dev, s3c_pcm_dai); |
480 | if (ret != 0) { | 469 | if (ret != 0) { |
481 | dev_err(&pdev->dev, "failed to get pcm_clock\n"); | 470 | dev_err(&pdev->dev, "failed to get pcm_clock\n"); |
482 | goto err5; | 471 | goto err5; |
@@ -514,6 +503,8 @@ static __devexit int s3c_pcm_dev_remove(struct platform_device *pdev) | |||
514 | struct s3c_pcm_info *pcm = &s3c_pcm[pdev->id]; | 503 | struct s3c_pcm_info *pcm = &s3c_pcm[pdev->id]; |
515 | struct resource *mem_res; | 504 | struct resource *mem_res; |
516 | 505 | ||
506 | snd_soc_unregister_dai(&pdev->dev); | ||
507 | |||
517 | iounmap(pcm->regs); | 508 | iounmap(pcm->regs); |
518 | 509 | ||
519 | mem_res = platform_get_resource(pdev, IORESOURCE_MEM, 0); | 510 | mem_res = platform_get_resource(pdev, IORESOURCE_MEM, 0); |
@@ -531,7 +522,7 @@ static struct platform_driver s3c_pcm_driver = { | |||
531 | .probe = s3c_pcm_dev_probe, | 522 | .probe = s3c_pcm_dev_probe, |
532 | .remove = s3c_pcm_dev_remove, | 523 | .remove = s3c_pcm_dev_remove, |
533 | .driver = { | 524 | .driver = { |
534 | .name = "samsung-pcm", | 525 | .name = "samsung-pcm-audio", |
535 | .owner = THIS_MODULE, | 526 | .owner = THIS_MODULE, |
536 | }, | 527 | }, |
537 | }; | 528 | }; |
@@ -552,3 +543,4 @@ module_exit(s3c_pcm_exit); | |||
552 | MODULE_AUTHOR("Jaswinder Singh, <jassi.brar@samsung.com>"); | 543 | MODULE_AUTHOR("Jaswinder Singh, <jassi.brar@samsung.com>"); |
553 | MODULE_DESCRIPTION("S3C PCM Controller Driver"); | 544 | MODULE_DESCRIPTION("S3C PCM Controller Driver"); |
554 | MODULE_LICENSE("GPL"); | 545 | MODULE_LICENSE("GPL"); |
546 | MODULE_ALIAS("platform:samsung-pcm-audio"); | ||
diff --git a/sound/soc/s3c24xx/s3c2412-i2s.c b/sound/soc/s3c24xx/s3c2412-i2s.c index 709adef9d043..4a861cfa52c5 100644 --- a/sound/soc/s3c24xx/s3c2412-i2s.c +++ b/sound/soc/s3c24xx/s3c2412-i2s.c | |||
@@ -65,26 +65,20 @@ static struct s3c_dma_params s3c2412_i2s_pcm_stereo_in = { | |||
65 | 65 | ||
66 | static struct s3c_i2sv2_info s3c2412_i2s; | 66 | static struct s3c_i2sv2_info s3c2412_i2s; |
67 | 67 | ||
68 | static inline struct s3c_i2sv2_info *to_info(struct snd_soc_dai *cpu_dai) | 68 | static int s3c2412_i2s_probe(struct snd_soc_dai *dai) |
69 | { | ||
70 | return cpu_dai->private_data; | ||
71 | } | ||
72 | |||
73 | static int s3c2412_i2s_probe(struct platform_device *pdev, | ||
74 | struct snd_soc_dai *dai) | ||
75 | { | 69 | { |
76 | int ret; | 70 | int ret; |
77 | 71 | ||
78 | pr_debug("Entered %s\n", __func__); | 72 | pr_debug("Entered %s\n", __func__); |
79 | 73 | ||
80 | ret = s3c_i2sv2_probe(pdev, dai, &s3c2412_i2s, S3C2410_PA_IIS); | 74 | ret = s3c_i2sv2_probe(dai, &s3c2412_i2s, S3C2410_PA_IIS); |
81 | if (ret) | 75 | if (ret) |
82 | return ret; | 76 | return ret; |
83 | 77 | ||
84 | s3c2412_i2s.dma_capture = &s3c2412_i2s_pcm_stereo_in; | 78 | s3c2412_i2s.dma_capture = &s3c2412_i2s_pcm_stereo_in; |
85 | s3c2412_i2s.dma_playback = &s3c2412_i2s_pcm_stereo_out; | 79 | s3c2412_i2s.dma_playback = &s3c2412_i2s_pcm_stereo_out; |
86 | 80 | ||
87 | s3c2412_i2s.iis_cclk = clk_get(&pdev->dev, "i2sclk"); | 81 | s3c2412_i2s.iis_cclk = clk_get(dai->dev, "i2sclk"); |
88 | if (s3c2412_i2s.iis_cclk == NULL) { | 82 | if (s3c2412_i2s.iis_cclk == NULL) { |
89 | pr_err("failed to get i2sclk clock\n"); | 83 | pr_err("failed to get i2sclk clock\n"); |
90 | iounmap(s3c2412_i2s.regs); | 84 | iounmap(s3c2412_i2s.regs); |
@@ -108,11 +102,20 @@ static int s3c2412_i2s_probe(struct platform_device *pdev, | |||
108 | return 0; | 102 | return 0; |
109 | } | 103 | } |
110 | 104 | ||
105 | static int s3c2412_i2s_remove(struct snd_soc_dai *dai) | ||
106 | { | ||
107 | clk_disable(s3c2412_i2s.iis_cclk); | ||
108 | clk_put(s3c2412_i2s.iis_cclk); | ||
109 | iounmap(s3c2412_i2s.regs); | ||
110 | |||
111 | return 0; | ||
112 | } | ||
113 | |||
111 | static int s3c2412_i2s_hw_params(struct snd_pcm_substream *substream, | 114 | static int s3c2412_i2s_hw_params(struct snd_pcm_substream *substream, |
112 | struct snd_pcm_hw_params *params, | 115 | struct snd_pcm_hw_params *params, |
113 | struct snd_soc_dai *cpu_dai) | 116 | struct snd_soc_dai *cpu_dai) |
114 | { | 117 | { |
115 | struct s3c_i2sv2_info *i2s = to_info(cpu_dai); | 118 | struct s3c_i2sv2_info *i2s = snd_soc_dai_get_drvdata(cpu_dai); |
116 | struct s3c_dma_params *dma_data; | 119 | struct s3c_dma_params *dma_data; |
117 | u32 iismod; | 120 | u32 iismod; |
118 | 121 | ||
@@ -152,10 +155,9 @@ static struct snd_soc_dai_ops s3c2412_i2s_dai_ops = { | |||
152 | .hw_params = s3c2412_i2s_hw_params, | 155 | .hw_params = s3c2412_i2s_hw_params, |
153 | }; | 156 | }; |
154 | 157 | ||
155 | struct snd_soc_dai s3c2412_i2s_dai = { | 158 | static struct snd_soc_dai_driver s3c2412_i2s_dai = { |
156 | .name = "s3c2412-i2s", | ||
157 | .id = 0, | ||
158 | .probe = s3c2412_i2s_probe, | 159 | .probe = s3c2412_i2s_probe, |
160 | .remove = s3c2412_i2s_remove, | ||
159 | .playback = { | 161 | .playback = { |
160 | .channels_min = 2, | 162 | .channels_min = 2, |
161 | .channels_max = 2, | 163 | .channels_max = 2, |
@@ -170,17 +172,36 @@ struct snd_soc_dai s3c2412_i2s_dai = { | |||
170 | }, | 172 | }, |
171 | .ops = &s3c2412_i2s_dai_ops, | 173 | .ops = &s3c2412_i2s_dai_ops, |
172 | }; | 174 | }; |
173 | EXPORT_SYMBOL_GPL(s3c2412_i2s_dai); | 175 | |
176 | static __devinit int s3c2412_iis_dev_probe(struct platform_device *pdev) | ||
177 | { | ||
178 | return snd_soc_register_dai(&pdev->dev, &s3c2412_i2s_dai); | ||
179 | } | ||
180 | |||
181 | static __devexit int s3c2412_iis_dev_remove(struct platform_device *pdev) | ||
182 | { | ||
183 | snd_soc_unregister_dai(&pdev->dev); | ||
184 | return 0; | ||
185 | } | ||
186 | |||
187 | static struct platform_driver s3c2412_iis_driver = { | ||
188 | .probe = s3c2412_iis_dev_probe, | ||
189 | .remove = s3c2412_iis_dev_remove, | ||
190 | .driver = { | ||
191 | .name = "s3c2412-iis", | ||
192 | .owner = THIS_MODULE, | ||
193 | }, | ||
194 | }; | ||
174 | 195 | ||
175 | static int __init s3c2412_i2s_init(void) | 196 | static int __init s3c2412_i2s_init(void) |
176 | { | 197 | { |
177 | return s3c_i2sv2_register_dai(&s3c2412_i2s_dai); | 198 | return platform_driver_register(&s3c2412_iis_driver); |
178 | } | 199 | } |
179 | module_init(s3c2412_i2s_init); | 200 | module_init(s3c2412_i2s_init); |
180 | 201 | ||
181 | static void __exit s3c2412_i2s_exit(void) | 202 | static void __exit s3c2412_i2s_exit(void) |
182 | { | 203 | { |
183 | snd_soc_unregister_dai(&s3c2412_i2s_dai); | 204 | platform_driver_unregister(&s3c2412_iis_driver); |
184 | } | 205 | } |
185 | module_exit(s3c2412_i2s_exit); | 206 | module_exit(s3c2412_i2s_exit); |
186 | 207 | ||
@@ -188,3 +209,4 @@ module_exit(s3c2412_i2s_exit); | |||
188 | MODULE_AUTHOR("Ben Dooks, <ben@simtec.co.uk>"); | 209 | MODULE_AUTHOR("Ben Dooks, <ben@simtec.co.uk>"); |
189 | MODULE_DESCRIPTION("S3C2412 I2S SoC Interface"); | 210 | MODULE_DESCRIPTION("S3C2412 I2S SoC Interface"); |
190 | MODULE_LICENSE("GPL"); | 211 | MODULE_LICENSE("GPL"); |
212 | MODULE_ALIAS("platform:s3c2412-iis"); | ||
diff --git a/sound/soc/s3c24xx/s3c2412-i2s.h b/sound/soc/s3c24xx/s3c2412-i2s.h index 0b5686b4d5c3..01a0471ac65c 100644 --- a/sound/soc/s3c24xx/s3c2412-i2s.h +++ b/sound/soc/s3c24xx/s3c2412-i2s.h | |||
@@ -24,6 +24,4 @@ | |||
24 | #define S3C2412_CLKSRC_PCLK S3C_I2SV2_CLKSRC_PCLK | 24 | #define S3C2412_CLKSRC_PCLK S3C_I2SV2_CLKSRC_PCLK |
25 | #define S3C2412_CLKSRC_I2SCLK S3C_I2SV2_CLKSRC_AUDIOBUS | 25 | #define S3C2412_CLKSRC_I2SCLK S3C_I2SV2_CLKSRC_AUDIOBUS |
26 | 26 | ||
27 | extern struct snd_soc_dai s3c2412_i2s_dai; | ||
28 | |||
29 | #endif /* __SND_SOC_S3C24XX_S3C2412_I2S_H */ | 27 | #endif /* __SND_SOC_S3C24XX_S3C2412_I2S_H */ |
diff --git a/sound/soc/s3c24xx/s3c24xx-i2s.c b/sound/soc/s3c24xx/s3c24xx-i2s.c index c3ac890a3986..e060daaa458f 100644 --- a/sound/soc/s3c24xx/s3c24xx-i2s.c +++ b/sound/soc/s3c24xx/s3c24xx-i2s.c | |||
@@ -252,7 +252,7 @@ static int s3c24xx_i2s_hw_params(struct snd_pcm_substream *substream, | |||
252 | else | 252 | else |
253 | dma_data = &s3c24xx_i2s_pcm_stereo_in; | 253 | dma_data = &s3c24xx_i2s_pcm_stereo_in; |
254 | 254 | ||
255 | snd_soc_dai_set_dma_data(rtd->dai->cpu_dai, substream, dma_data); | 255 | snd_soc_dai_set_dma_data(rtd->cpu_dai, substream, dma_data); |
256 | 256 | ||
257 | /* Working copies of register */ | 257 | /* Working copies of register */ |
258 | iismod = readl(s3c24xx_i2s.regs + S3C2410_IISMOD); | 258 | iismod = readl(s3c24xx_i2s.regs + S3C2410_IISMOD); |
@@ -280,9 +280,8 @@ static int s3c24xx_i2s_trigger(struct snd_pcm_substream *substream, int cmd, | |||
280 | struct snd_soc_dai *dai) | 280 | struct snd_soc_dai *dai) |
281 | { | 281 | { |
282 | int ret = 0; | 282 | int ret = 0; |
283 | struct snd_soc_pcm_runtime *rtd = substream->private_data; | ||
284 | struct s3c_dma_params *dma_data = | 283 | struct s3c_dma_params *dma_data = |
285 | snd_soc_dai_get_dma_data(rtd->dai->cpu_dai, substream); | 284 | snd_soc_dai_get_dma_data(dai, substream); |
286 | 285 | ||
287 | pr_debug("Entered %s\n", __func__); | 286 | pr_debug("Entered %s\n", __func__); |
288 | 287 | ||
@@ -387,8 +386,7 @@ u32 s3c24xx_i2s_get_clockrate(void) | |||
387 | } | 386 | } |
388 | EXPORT_SYMBOL_GPL(s3c24xx_i2s_get_clockrate); | 387 | EXPORT_SYMBOL_GPL(s3c24xx_i2s_get_clockrate); |
389 | 388 | ||
390 | static int s3c24xx_i2s_probe(struct platform_device *pdev, | 389 | static int s3c24xx_i2s_probe(struct snd_soc_dai *dai) |
391 | struct snd_soc_dai *dai) | ||
392 | { | 390 | { |
393 | pr_debug("Entered %s\n", __func__); | 391 | pr_debug("Entered %s\n", __func__); |
394 | 392 | ||
@@ -396,7 +394,7 @@ static int s3c24xx_i2s_probe(struct platform_device *pdev, | |||
396 | if (s3c24xx_i2s.regs == NULL) | 394 | if (s3c24xx_i2s.regs == NULL) |
397 | return -ENXIO; | 395 | return -ENXIO; |
398 | 396 | ||
399 | s3c24xx_i2s.iis_clk = clk_get(&pdev->dev, "iis"); | 397 | s3c24xx_i2s.iis_clk = clk_get(dai->dev, "iis"); |
400 | if (s3c24xx_i2s.iis_clk == NULL) { | 398 | if (s3c24xx_i2s.iis_clk == NULL) { |
401 | pr_err("failed to get iis_clock\n"); | 399 | pr_err("failed to get iis_clock\n"); |
402 | iounmap(s3c24xx_i2s.regs); | 400 | iounmap(s3c24xx_i2s.regs); |
@@ -465,9 +463,7 @@ static struct snd_soc_dai_ops s3c24xx_i2s_dai_ops = { | |||
465 | .set_sysclk = s3c24xx_i2s_set_sysclk, | 463 | .set_sysclk = s3c24xx_i2s_set_sysclk, |
466 | }; | 464 | }; |
467 | 465 | ||
468 | struct snd_soc_dai s3c24xx_i2s_dai = { | 466 | static struct snd_soc_dai_driver s3c24xx_i2s_dai = { |
469 | .name = "s3c24xx-i2s", | ||
470 | .id = 0, | ||
471 | .probe = s3c24xx_i2s_probe, | 467 | .probe = s3c24xx_i2s_probe, |
472 | .suspend = s3c24xx_i2s_suspend, | 468 | .suspend = s3c24xx_i2s_suspend, |
473 | .resume = s3c24xx_i2s_resume, | 469 | .resume = s3c24xx_i2s_resume, |
@@ -483,17 +479,36 @@ struct snd_soc_dai s3c24xx_i2s_dai = { | |||
483 | .formats = SNDRV_PCM_FMTBIT_S8 | SNDRV_PCM_FMTBIT_S16_LE,}, | 479 | .formats = SNDRV_PCM_FMTBIT_S8 | SNDRV_PCM_FMTBIT_S16_LE,}, |
484 | .ops = &s3c24xx_i2s_dai_ops, | 480 | .ops = &s3c24xx_i2s_dai_ops, |
485 | }; | 481 | }; |
486 | EXPORT_SYMBOL_GPL(s3c24xx_i2s_dai); | 482 | |
483 | static __devinit int s3c24xx_iis_dev_probe(struct platform_device *pdev) | ||
484 | { | ||
485 | return snd_soc_register_dai(&pdev->dev, &s3c24xx_i2s_dai); | ||
486 | } | ||
487 | |||
488 | static __devexit int s3c24xx_iis_dev_remove(struct platform_device *pdev) | ||
489 | { | ||
490 | snd_soc_unregister_dai(&pdev->dev); | ||
491 | return 0; | ||
492 | } | ||
493 | |||
494 | static struct platform_driver s3c24xx_iis_driver = { | ||
495 | .probe = s3c24xx_iis_dev_probe, | ||
496 | .remove = s3c24xx_iis_dev_remove, | ||
497 | .driver = { | ||
498 | .name = "s3c24xx-iis", | ||
499 | .owner = THIS_MODULE, | ||
500 | }, | ||
501 | }; | ||
487 | 502 | ||
488 | static int __init s3c24xx_i2s_init(void) | 503 | static int __init s3c24xx_i2s_init(void) |
489 | { | 504 | { |
490 | return snd_soc_register_dai(&s3c24xx_i2s_dai); | 505 | return platform_driver_register(&s3c24xx_iis_driver); |
491 | } | 506 | } |
492 | module_init(s3c24xx_i2s_init); | 507 | module_init(s3c24xx_i2s_init); |
493 | 508 | ||
494 | static void __exit s3c24xx_i2s_exit(void) | 509 | static void __exit s3c24xx_i2s_exit(void) |
495 | { | 510 | { |
496 | snd_soc_unregister_dai(&s3c24xx_i2s_dai); | 511 | platform_driver_unregister(&s3c24xx_iis_driver); |
497 | } | 512 | } |
498 | module_exit(s3c24xx_i2s_exit); | 513 | module_exit(s3c24xx_i2s_exit); |
499 | 514 | ||
@@ -501,3 +516,4 @@ module_exit(s3c24xx_i2s_exit); | |||
501 | MODULE_AUTHOR("Ben Dooks, <ben@simtec.co.uk>"); | 516 | MODULE_AUTHOR("Ben Dooks, <ben@simtec.co.uk>"); |
502 | MODULE_DESCRIPTION("s3c24xx I2S SoC Interface"); | 517 | MODULE_DESCRIPTION("s3c24xx I2S SoC Interface"); |
503 | MODULE_LICENSE("GPL"); | 518 | MODULE_LICENSE("GPL"); |
519 | MODULE_ALIAS("platform:s3c24xx-iis"); | ||
diff --git a/sound/soc/s3c24xx/s3c24xx-i2s.h b/sound/soc/s3c24xx/s3c24xx-i2s.h index 726d91cf4e1c..f9ca04edacb7 100644 --- a/sound/soc/s3c24xx/s3c24xx-i2s.h +++ b/sound/soc/s3c24xx/s3c24xx-i2s.h | |||
@@ -32,6 +32,4 @@ | |||
32 | 32 | ||
33 | u32 s3c24xx_i2s_get_clockrate(void); | 33 | u32 s3c24xx_i2s_get_clockrate(void); |
34 | 34 | ||
35 | extern struct snd_soc_dai s3c24xx_i2s_dai; | ||
36 | |||
37 | #endif /*S3C24XXI2S_H_*/ | 35 | #endif /*S3C24XXI2S_H_*/ |
diff --git a/sound/soc/s3c24xx/s3c24xx_simtec.c b/sound/soc/s3c24xx/s3c24xx_simtec.c index 4984754f3298..c4c111442010 100644 --- a/sound/soc/s3c24xx/s3c24xx_simtec.c +++ b/sound/soc/s3c24xx/s3c24xx_simtec.c | |||
@@ -139,8 +139,10 @@ static const struct snd_kcontrol_new amp_unmute_controls[] = { | |||
139 | speaker_unmute_get, speaker_unmute_put), | 139 | speaker_unmute_get, speaker_unmute_put), |
140 | }; | 140 | }; |
141 | 141 | ||
142 | void simtec_audio_init(struct snd_soc_codec *codec) | 142 | void simtec_audio_init(struct snd_soc_pcm_runtime *rtd) |
143 | { | 143 | { |
144 | struct snd_soc_codec *codec = rtd->codec; | ||
145 | |||
144 | if (pdata->amp_gpio > 0) { | 146 | if (pdata->amp_gpio > 0) { |
145 | pr_debug("%s: adding amp routes\n", __func__); | 147 | pr_debug("%s: adding amp routes\n", __func__); |
146 | 148 | ||
@@ -170,8 +172,8 @@ static int simtec_hw_params(struct snd_pcm_substream *substream, | |||
170 | struct snd_pcm_hw_params *params) | 172 | struct snd_pcm_hw_params *params) |
171 | { | 173 | { |
172 | struct snd_soc_pcm_runtime *rtd = substream->private_data; | 174 | struct snd_soc_pcm_runtime *rtd = substream->private_data; |
173 | struct snd_soc_dai *codec_dai = rtd->dai->codec_dai; | 175 | struct snd_soc_dai *codec_dai = rtd->codec_dai; |
174 | struct snd_soc_dai *cpu_dai = rtd->dai->cpu_dai; | 176 | struct snd_soc_dai *cpu_dai = rtd->cpu_dai; |
175 | int ret; | 177 | int ret; |
176 | 178 | ||
177 | /* Set the CODEC as the bus clock master, I2S */ | 179 | /* Set the CODEC as the bus clock master, I2S */ |
@@ -319,12 +321,12 @@ EXPORT_SYMBOL_GPL(simtec_audio_pmops); | |||
319 | #endif | 321 | #endif |
320 | 322 | ||
321 | int __devinit simtec_audio_core_probe(struct platform_device *pdev, | 323 | int __devinit simtec_audio_core_probe(struct platform_device *pdev, |
322 | struct snd_soc_device *socdev) | 324 | struct snd_soc_card *card) |
323 | { | 325 | { |
324 | struct platform_device *snd_dev; | 326 | struct platform_device *snd_dev; |
325 | int ret; | 327 | int ret; |
326 | 328 | ||
327 | socdev->card->dai_link->ops = &simtec_snd_ops; | 329 | card->dai_link->ops = &simtec_snd_ops; |
328 | 330 | ||
329 | pdata = pdev->dev.platform_data; | 331 | pdata = pdev->dev.platform_data; |
330 | if (!pdata) { | 332 | if (!pdata) { |
@@ -353,8 +355,7 @@ int __devinit simtec_audio_core_probe(struct platform_device *pdev, | |||
353 | goto err_gpio; | 355 | goto err_gpio; |
354 | } | 356 | } |
355 | 357 | ||
356 | platform_set_drvdata(snd_dev, socdev); | 358 | platform_set_drvdata(snd_dev, card); |
357 | socdev->dev = &snd_dev->dev; | ||
358 | 359 | ||
359 | ret = platform_device_add(snd_dev); | 360 | ret = platform_device_add(snd_dev); |
360 | if (ret) { | 361 | if (ret) { |
diff --git a/sound/soc/s3c24xx/s3c24xx_simtec.h b/sound/soc/s3c24xx/s3c24xx_simtec.h index e18faee30cce..e63d5ff9c41f 100644 --- a/sound/soc/s3c24xx/s3c24xx_simtec.h +++ b/sound/soc/s3c24xx/s3c24xx_simtec.h | |||
@@ -7,10 +7,10 @@ | |||
7 | * published by the Free Software Foundation. | 7 | * published by the Free Software Foundation. |
8 | */ | 8 | */ |
9 | 9 | ||
10 | extern void simtec_audio_init(struct snd_soc_codec *codec); | 10 | extern void simtec_audio_init(struct snd_soc_pcm_runtime *rtd); |
11 | 11 | ||
12 | extern int simtec_audio_core_probe(struct platform_device *pdev, | 12 | extern int simtec_audio_core_probe(struct platform_device *pdev, |
13 | struct snd_soc_device *socdev); | 13 | struct snd_soc_card *card); |
14 | 14 | ||
15 | extern int simtec_audio_remove(struct platform_device *pdev); | 15 | extern int simtec_audio_remove(struct platform_device *pdev); |
16 | 16 | ||
diff --git a/sound/soc/s3c24xx/s3c24xx_simtec_hermes.c b/sound/soc/s3c24xx/s3c24xx_simtec_hermes.c index bdf8951af8e3..f88453735ae2 100644 --- a/sound/soc/s3c24xx/s3c24xx_simtec_hermes.c +++ b/sound/soc/s3c24xx/s3c24xx_simtec_hermes.c | |||
@@ -73,8 +73,10 @@ static const struct snd_soc_dapm_route base_map[] = { | |||
73 | * Attach our controls and configure the necessary codec | 73 | * Attach our controls and configure the necessary codec |
74 | * mappings for our sound card instance. | 74 | * mappings for our sound card instance. |
75 | */ | 75 | */ |
76 | static int simtec_hermes_init(struct snd_soc_codec *codec) | 76 | static int simtec_hermes_init(struct snd_soc_pcm_runtime *rtd) |
77 | { | 77 | { |
78 | struct snd_soc_codec *codec = rtd->codec; | ||
79 | |||
78 | snd_soc_dapm_new_controls(codec, dapm_widgets, | 80 | snd_soc_dapm_new_controls(codec, dapm_widgets, |
79 | ARRAY_SIZE(dapm_widgets)); | 81 | ARRAY_SIZE(dapm_widgets)); |
80 | 82 | ||
@@ -85,42 +87,33 @@ static int simtec_hermes_init(struct snd_soc_codec *codec) | |||
85 | snd_soc_dapm_enable_pin(codec, "Line Out"); | 87 | snd_soc_dapm_enable_pin(codec, "Line Out"); |
86 | snd_soc_dapm_enable_pin(codec, "Mic Jack"); | 88 | snd_soc_dapm_enable_pin(codec, "Mic Jack"); |
87 | 89 | ||
88 | simtec_audio_init(codec); | 90 | simtec_audio_init(rtd); |
89 | snd_soc_dapm_sync(codec); | 91 | snd_soc_dapm_sync(codec); |
90 | 92 | ||
91 | return 0; | 93 | return 0; |
92 | } | 94 | } |
93 | 95 | ||
94 | static struct aic3x_setup_data codec_setup = { | ||
95 | }; | ||
96 | |||
97 | static struct snd_soc_dai_link simtec_dai_aic33 = { | 96 | static struct snd_soc_dai_link simtec_dai_aic33 = { |
98 | .name = "tlv320aic33", | 97 | .name = "tlv320aic33", |
99 | .stream_name = "TLV320AIC33", | 98 | .stream_name = "TLV320AIC33", |
100 | .cpu_dai = &s3c24xx_i2s_dai, | 99 | .codec_name = "tlv320aic3x-codec.0-0x1a", |
101 | .codec_dai = &aic3x_dai, | 100 | .cpu_dai_name = "s3c24xx-i2s", |
101 | .codec_dai_name = "tlv320aic3x-hifi", | ||
102 | .platform_name = "s3c24xx-pcm-audio", | ||
102 | .init = simtec_hermes_init, | 103 | .init = simtec_hermes_init, |
103 | }; | 104 | }; |
104 | 105 | ||
105 | /* simtec audio machine driver */ | 106 | /* simtec audio machine driver */ |
106 | static struct snd_soc_card snd_soc_machine_simtec_aic33 = { | 107 | static struct snd_soc_card snd_soc_machine_simtec_aic33 = { |
107 | .name = "Simtec-Hermes", | 108 | .name = "Simtec-Hermes", |
108 | .platform = &s3c24xx_soc_platform, | ||
109 | .dai_link = &simtec_dai_aic33, | 109 | .dai_link = &simtec_dai_aic33, |
110 | .num_links = 1, | 110 | .num_links = 1, |
111 | }; | 111 | }; |
112 | 112 | ||
113 | /* simtec audio subsystem */ | ||
114 | static struct snd_soc_device simtec_snd_devdata_aic33 = { | ||
115 | .card = &snd_soc_machine_simtec_aic33, | ||
116 | .codec_dev = &soc_codec_dev_aic3x, | ||
117 | .codec_data = &codec_setup, | ||
118 | }; | ||
119 | |||
120 | static int __devinit simtec_audio_hermes_probe(struct platform_device *pd) | 113 | static int __devinit simtec_audio_hermes_probe(struct platform_device *pd) |
121 | { | 114 | { |
122 | dev_info(&pd->dev, "probing....\n"); | 115 | dev_info(&pd->dev, "probing....\n"); |
123 | return simtec_audio_core_probe(pd, &simtec_snd_devdata_aic33); | 116 | return simtec_audio_core_probe(pd, &snd_soc_machine_simtec_aic33); |
124 | } | 117 | } |
125 | 118 | ||
126 | static struct platform_driver simtec_audio_hermes_platdrv = { | 119 | static struct platform_driver simtec_audio_hermes_platdrv = { |
diff --git a/sound/soc/s3c24xx/s3c24xx_simtec_tlv320aic23.c b/sound/soc/s3c24xx/s3c24xx_simtec_tlv320aic23.c index 185c0acb5ce6..c0967593510d 100644 --- a/sound/soc/s3c24xx/s3c24xx_simtec_tlv320aic23.c +++ b/sound/soc/s3c24xx/s3c24xx_simtec_tlv320aic23.c | |||
@@ -62,8 +62,10 @@ static const struct snd_soc_dapm_route base_map[] = { | |||
62 | * Attach our controls and configure the necessary codec | 62 | * Attach our controls and configure the necessary codec |
63 | * mappings for our sound card instance. | 63 | * mappings for our sound card instance. |
64 | */ | 64 | */ |
65 | static int simtec_tlv320aic23_init(struct snd_soc_codec *codec) | 65 | static int simtec_tlv320aic23_init(struct snd_soc_pcm_runtime *rtd) |
66 | { | 66 | { |
67 | struct snd_soc_codec *codec = rtd->codec; | ||
68 | |||
67 | snd_soc_dapm_new_controls(codec, dapm_widgets, | 69 | snd_soc_dapm_new_controls(codec, dapm_widgets, |
68 | ARRAY_SIZE(dapm_widgets)); | 70 | ARRAY_SIZE(dapm_widgets)); |
69 | 71 | ||
@@ -74,7 +76,7 @@ static int simtec_tlv320aic23_init(struct snd_soc_codec *codec) | |||
74 | snd_soc_dapm_enable_pin(codec, "Line Out"); | 76 | snd_soc_dapm_enable_pin(codec, "Line Out"); |
75 | snd_soc_dapm_enable_pin(codec, "Mic Jack"); | 77 | snd_soc_dapm_enable_pin(codec, "Mic Jack"); |
76 | 78 | ||
77 | simtec_audio_init(codec); | 79 | simtec_audio_init(rtd); |
78 | snd_soc_dapm_sync(codec); | 80 | snd_soc_dapm_sync(codec); |
79 | 81 | ||
80 | return 0; | 82 | return 0; |
@@ -83,28 +85,23 @@ static int simtec_tlv320aic23_init(struct snd_soc_codec *codec) | |||
83 | static struct snd_soc_dai_link simtec_dai_aic23 = { | 85 | static struct snd_soc_dai_link simtec_dai_aic23 = { |
84 | .name = "tlv320aic23", | 86 | .name = "tlv320aic23", |
85 | .stream_name = "TLV320AIC23", | 87 | .stream_name = "TLV320AIC23", |
86 | .cpu_dai = &s3c24xx_i2s_dai, | 88 | .codec_name = "tlv320aic3x-codec.0-0x1a", |
87 | .codec_dai = &tlv320aic23_dai, | 89 | .cpu_dai_name = "s3c24xx-i2s", |
90 | .codec_dai_name = "tlv320aic3x-hifi", | ||
91 | .platform_name = "s3c24xx-pcm-audio", | ||
88 | .init = simtec_tlv320aic23_init, | 92 | .init = simtec_tlv320aic23_init, |
89 | }; | 93 | }; |
90 | 94 | ||
91 | /* simtec audio machine driver */ | 95 | /* simtec audio machine driver */ |
92 | static struct snd_soc_card snd_soc_machine_simtec_aic23 = { | 96 | static struct snd_soc_card snd_soc_machine_simtec_aic23 = { |
93 | .name = "Simtec", | 97 | .name = "Simtec", |
94 | .platform = &s3c24xx_soc_platform, | ||
95 | .dai_link = &simtec_dai_aic23, | 98 | .dai_link = &simtec_dai_aic23, |
96 | .num_links = 1, | 99 | .num_links = 1, |
97 | }; | 100 | }; |
98 | 101 | ||
99 | /* simtec audio subsystem */ | ||
100 | static struct snd_soc_device simtec_snd_devdata_aic23 = { | ||
101 | .card = &snd_soc_machine_simtec_aic23, | ||
102 | .codec_dev = &soc_codec_dev_tlv320aic23, | ||
103 | }; | ||
104 | |||
105 | static int __devinit simtec_audio_tlv320aic23_probe(struct platform_device *pd) | 102 | static int __devinit simtec_audio_tlv320aic23_probe(struct platform_device *pd) |
106 | { | 103 | { |
107 | return simtec_audio_core_probe(pd, &simtec_snd_devdata_aic23); | 104 | return simtec_audio_core_probe(pd, &snd_soc_machine_simtec_aic23); |
108 | } | 105 | } |
109 | 106 | ||
110 | static struct platform_driver simtec_audio_tlv320aic23_platdrv = { | 107 | static struct platform_driver simtec_audio_tlv320aic23_platdrv = { |
diff --git a/sound/soc/s3c24xx/s3c24xx_uda134x.c b/sound/soc/s3c24xx/s3c24xx_uda134x.c index 052d59659c29..bd48ffbde880 100644 --- a/sound/soc/s3c24xx/s3c24xx_uda134x.c +++ b/sound/soc/s3c24xx/s3c24xx_uda134x.c | |||
@@ -133,8 +133,8 @@ static int s3c24xx_uda134x_hw_params(struct snd_pcm_substream *substream, | |||
133 | struct snd_pcm_hw_params *params) | 133 | struct snd_pcm_hw_params *params) |
134 | { | 134 | { |
135 | struct snd_soc_pcm_runtime *rtd = substream->private_data; | 135 | struct snd_soc_pcm_runtime *rtd = substream->private_data; |
136 | struct snd_soc_dai *codec_dai = rtd->dai->codec_dai; | 136 | struct snd_soc_dai *codec_dai = rtd->codec_dai; |
137 | struct snd_soc_dai *cpu_dai = rtd->dai->cpu_dai; | 137 | struct snd_soc_dai *cpu_dai = rtd->cpu_dai; |
138 | unsigned int clk = 0; | 138 | unsigned int clk = 0; |
139 | int ret = 0; | 139 | int ret = 0; |
140 | int clk_source, fs_mode; | 140 | int clk_source, fs_mode; |
@@ -227,14 +227,15 @@ static struct snd_soc_ops s3c24xx_uda134x_ops = { | |||
227 | static struct snd_soc_dai_link s3c24xx_uda134x_dai_link = { | 227 | static struct snd_soc_dai_link s3c24xx_uda134x_dai_link = { |
228 | .name = "UDA134X", | 228 | .name = "UDA134X", |
229 | .stream_name = "UDA134X", | 229 | .stream_name = "UDA134X", |
230 | .codec_dai = &uda134x_dai, | 230 | .codec_name = "uda134x-hifi", |
231 | .cpu_dai = &s3c24xx_i2s_dai, | 231 | .codec_dai_name = "uda134x-hifi", |
232 | .cpu_dai_name = "s3c24xx-i2s", | ||
232 | .ops = &s3c24xx_uda134x_ops, | 233 | .ops = &s3c24xx_uda134x_ops, |
234 | .platform_name = "s3c24xx-pcm-audio", | ||
233 | }; | 235 | }; |
234 | 236 | ||
235 | static struct snd_soc_card snd_soc_s3c24xx_uda134x = { | 237 | static struct snd_soc_card snd_soc_s3c24xx_uda134x = { |
236 | .name = "S3C24XX_UDA134X", | 238 | .name = "S3C24XX_UDA134X", |
237 | .platform = &s3c24xx_soc_platform, | ||
238 | .dai_link = &s3c24xx_uda134x_dai_link, | 239 | .dai_link = &s3c24xx_uda134x_dai_link, |
239 | .num_links = 1, | 240 | .num_links = 1, |
240 | }; | 241 | }; |
@@ -256,6 +257,7 @@ static void setmode(int v) | |||
256 | gpio_set_value(s3c24xx_uda134x_l3_pins->l3_mode, v > 0); | 257 | gpio_set_value(s3c24xx_uda134x_l3_pins->l3_mode, v > 0); |
257 | } | 258 | } |
258 | 259 | ||
260 | /* FIXME - This must be codec platform data but in which board file ?? */ | ||
259 | static struct uda134x_platform_data s3c24xx_uda134x = { | 261 | static struct uda134x_platform_data s3c24xx_uda134x = { |
260 | .l3 = { | 262 | .l3 = { |
261 | .setdat = setdat, | 263 | .setdat = setdat, |
@@ -270,12 +272,6 @@ static struct uda134x_platform_data s3c24xx_uda134x = { | |||
270 | }, | 272 | }, |
271 | }; | 273 | }; |
272 | 274 | ||
273 | static struct snd_soc_device s3c24xx_uda134x_snd_devdata = { | ||
274 | .card = &snd_soc_s3c24xx_uda134x, | ||
275 | .codec_dev = &soc_codec_dev_uda134x, | ||
276 | .codec_data = &s3c24xx_uda134x, | ||
277 | }; | ||
278 | |||
279 | static int s3c24xx_uda134x_setup_pin(int pin, char *fun) | 275 | static int s3c24xx_uda134x_setup_pin(int pin, char *fun) |
280 | { | 276 | { |
281 | if (gpio_request(pin, "s3c24xx_uda134x") < 0) { | 277 | if (gpio_request(pin, "s3c24xx_uda134x") < 0) { |
@@ -325,8 +321,7 @@ static int s3c24xx_uda134x_probe(struct platform_device *pdev) | |||
325 | } | 321 | } |
326 | 322 | ||
327 | platform_set_drvdata(s3c24xx_uda134x_snd_device, | 323 | platform_set_drvdata(s3c24xx_uda134x_snd_device, |
328 | &s3c24xx_uda134x_snd_devdata); | 324 | &snd_soc_s3c24xx_uda134x); |
329 | s3c24xx_uda134x_snd_devdata.dev = &s3c24xx_uda134x_snd_device->dev; | ||
330 | ret = platform_device_add(s3c24xx_uda134x_snd_device); | 325 | ret = platform_device_add(s3c24xx_uda134x_snd_device); |
331 | if (ret) { | 326 | if (ret) { |
332 | printk(KERN_ERR "S3C24XX_UDA134X SoC Audio: Unable to add\n"); | 327 | printk(KERN_ERR "S3C24XX_UDA134X SoC Audio: Unable to add\n"); |
diff --git a/sound/soc/s3c24xx/s3c64xx-i2s-v4.c b/sound/soc/s3c24xx/s3c64xx-i2s-v4.c index 06db130030a1..a13415a85a45 100644 --- a/sound/soc/s3c24xx/s3c64xx-i2s-v4.c +++ b/sound/soc/s3c24xx/s3c64xx-i2s-v4.c | |||
@@ -16,9 +16,7 @@ | |||
16 | #include <sound/soc.h> | 16 | #include <sound/soc.h> |
17 | #include <sound/pcm_params.h> | 17 | #include <sound/pcm_params.h> |
18 | 18 | ||
19 | #include <mach/gpio-bank-c.h> | 19 | #include <plat/audio.h> |
20 | #include <mach/gpio-bank-h.h> | ||
21 | #include <plat/gpio-cfg.h> | ||
22 | 20 | ||
23 | #include <mach/map.h> | 21 | #include <mach/map.h> |
24 | #include <mach/dma.h> | 22 | #include <mach/dma.h> |
@@ -39,34 +37,23 @@ static struct s3c_dma_params s3c64xx_i2sv4_pcm_stereo_out; | |||
39 | static struct s3c_dma_params s3c64xx_i2sv4_pcm_stereo_in; | 37 | static struct s3c_dma_params s3c64xx_i2sv4_pcm_stereo_in; |
40 | static struct s3c_i2sv2_info s3c64xx_i2sv4; | 38 | static struct s3c_i2sv2_info s3c64xx_i2sv4; |
41 | 39 | ||
42 | struct snd_soc_dai s3c64xx_i2s_v4_dai; | 40 | static int s3c64xx_i2sv4_probe(struct snd_soc_dai *dai) |
43 | EXPORT_SYMBOL_GPL(s3c64xx_i2s_v4_dai); | ||
44 | |||
45 | static inline struct s3c_i2sv2_info *to_info(struct snd_soc_dai *cpu_dai) | ||
46 | { | 41 | { |
47 | return cpu_dai->private_data; | 42 | struct s3c_i2sv2_info *i2s = &s3c64xx_i2sv4; |
48 | } | 43 | int ret = 0; |
49 | 44 | ||
50 | static int s3c64xx_i2sv4_probe(struct platform_device *pdev, | 45 | snd_soc_dai_set_drvdata(dai, i2s); |
51 | struct snd_soc_dai *dai) | ||
52 | { | ||
53 | /* configure GPIO for i2s port */ | ||
54 | s3c_gpio_cfgpin(S3C64XX_GPC(4), S3C64XX_GPC4_I2S_V40_DO0); | ||
55 | s3c_gpio_cfgpin(S3C64XX_GPC(5), S3C64XX_GPC5_I2S_V40_DO1); | ||
56 | s3c_gpio_cfgpin(S3C64XX_GPC(7), S3C64XX_GPC7_I2S_V40_DO2); | ||
57 | s3c_gpio_cfgpin(S3C64XX_GPH(6), S3C64XX_GPH6_I2S_V40_BCLK); | ||
58 | s3c_gpio_cfgpin(S3C64XX_GPH(7), S3C64XX_GPH7_I2S_V40_CDCLK); | ||
59 | s3c_gpio_cfgpin(S3C64XX_GPH(8), S3C64XX_GPH8_I2S_V40_LRCLK); | ||
60 | s3c_gpio_cfgpin(S3C64XX_GPH(9), S3C64XX_GPH9_I2S_V40_DI); | ||
61 | 46 | ||
62 | return 0; | 47 | ret = s3c_i2sv2_probe(dai, i2s, i2s->base); |
48 | |||
49 | return ret; | ||
63 | } | 50 | } |
64 | 51 | ||
65 | static int s3c_i2sv4_hw_params(struct snd_pcm_substream *substream, | 52 | static int s3c_i2sv4_hw_params(struct snd_pcm_substream *substream, |
66 | struct snd_pcm_hw_params *params, | 53 | struct snd_pcm_hw_params *params, |
67 | struct snd_soc_dai *cpu_dai) | 54 | struct snd_soc_dai *cpu_dai) |
68 | { | 55 | { |
69 | struct s3c_i2sv2_info *i2s = to_info(cpu_dai); | 56 | struct s3c_i2sv2_info *i2s = snd_soc_dai_get_drvdata(cpu_dai); |
70 | struct s3c_dma_params *dma_data; | 57 | struct s3c_dma_params *dma_data; |
71 | u32 iismod; | 58 | u32 iismod; |
72 | 59 | ||
@@ -104,51 +91,79 @@ static struct snd_soc_dai_ops s3c64xx_i2sv4_dai_ops = { | |||
104 | .hw_params = s3c_i2sv4_hw_params, | 91 | .hw_params = s3c_i2sv4_hw_params, |
105 | }; | 92 | }; |
106 | 93 | ||
94 | static struct snd_soc_dai_driver s3c64xx_i2s_v4_dai = { | ||
95 | .symmetric_rates = 1, | ||
96 | .playback = { | ||
97 | .channels_min = 2, | ||
98 | .channels_max = 2, | ||
99 | .rates = S3C64XX_I2S_RATES, | ||
100 | .formats = S3C64XX_I2S_FMTS, | ||
101 | }, | ||
102 | .capture = { | ||
103 | .channels_min = 2, | ||
104 | .channels_max = 2, | ||
105 | .rates = S3C64XX_I2S_RATES, | ||
106 | .formats = S3C64XX_I2S_FMTS, | ||
107 | }, | ||
108 | .probe = s3c64xx_i2sv4_probe, | ||
109 | .ops = &s3c64xx_i2sv4_dai_ops, | ||
110 | }; | ||
111 | |||
107 | static __devinit int s3c64xx_i2sv4_dev_probe(struct platform_device *pdev) | 112 | static __devinit int s3c64xx_i2sv4_dev_probe(struct platform_device *pdev) |
108 | { | 113 | { |
114 | struct s3c_audio_pdata *i2s_pdata; | ||
109 | struct s3c_i2sv2_info *i2s; | 115 | struct s3c_i2sv2_info *i2s; |
110 | struct snd_soc_dai *dai; | 116 | struct resource *res; |
111 | int ret; | 117 | int ret; |
112 | 118 | ||
113 | i2s = &s3c64xx_i2sv4; | 119 | i2s = &s3c64xx_i2sv4; |
114 | dai = &s3c64xx_i2s_v4_dai; | ||
115 | |||
116 | if (dai->dev) { | ||
117 | dev_dbg(dai->dev, "%s: \ | ||
118 | I2Sv4 instance already registered!\n", __func__); | ||
119 | return -EBUSY; | ||
120 | } | ||
121 | |||
122 | dai->dev = &pdev->dev; | ||
123 | dai->name = "s3c64xx-i2s-v4"; | ||
124 | dai->id = 0; | ||
125 | dai->symmetric_rates = 1; | ||
126 | dai->playback.channels_min = 2; | ||
127 | dai->playback.channels_max = 2; | ||
128 | dai->playback.rates = S3C64XX_I2S_RATES; | ||
129 | dai->playback.formats = S3C64XX_I2S_FMTS; | ||
130 | dai->capture.channels_min = 2; | ||
131 | dai->capture.channels_max = 2; | ||
132 | dai->capture.rates = S3C64XX_I2S_RATES; | ||
133 | dai->capture.formats = S3C64XX_I2S_FMTS; | ||
134 | dai->probe = s3c64xx_i2sv4_probe; | ||
135 | dai->ops = &s3c64xx_i2sv4_dai_ops; | ||
136 | 120 | ||
137 | i2s->feature |= S3C_FEATURE_CDCLKCON; | 121 | i2s->feature |= S3C_FEATURE_CDCLKCON; |
138 | 122 | ||
139 | i2s->dma_capture = &s3c64xx_i2sv4_pcm_stereo_in; | 123 | i2s->dma_capture = &s3c64xx_i2sv4_pcm_stereo_in; |
140 | i2s->dma_playback = &s3c64xx_i2sv4_pcm_stereo_out; | 124 | i2s->dma_playback = &s3c64xx_i2sv4_pcm_stereo_out; |
141 | 125 | ||
142 | i2s->dma_capture->channel = DMACH_HSI_I2SV40_RX; | 126 | res = platform_get_resource(pdev, IORESOURCE_DMA, 0); |
143 | i2s->dma_capture->dma_addr = S3C64XX_PA_IISV4 + S3C2412_IISRXD; | 127 | if (!res) { |
144 | i2s->dma_playback->channel = DMACH_HSI_I2SV40_TX; | 128 | dev_err(&pdev->dev, "Unable to get I2S-TX dma resource\n"); |
145 | i2s->dma_playback->dma_addr = S3C64XX_PA_IISV4 + S3C2412_IISTXD; | 129 | return -ENXIO; |
130 | } | ||
131 | i2s->dma_playback->channel = res->start; | ||
132 | |||
133 | res = platform_get_resource(pdev, IORESOURCE_DMA, 1); | ||
134 | if (!res) { | ||
135 | dev_err(&pdev->dev, "Unable to get I2S-RX dma resource\n"); | ||
136 | return -ENXIO; | ||
137 | } | ||
138 | i2s->dma_capture->channel = res->start; | ||
139 | |||
140 | res = platform_get_resource(pdev, IORESOURCE_MEM, 0); | ||
141 | if (!res) { | ||
142 | dev_err(&pdev->dev, "Unable to get I2S SFR address\n"); | ||
143 | return -ENXIO; | ||
144 | } | ||
145 | |||
146 | if (!request_mem_region(res->start, resource_size(res), | ||
147 | "s3c64xx-i2s-v4")) { | ||
148 | dev_err(&pdev->dev, "Unable to request SFR region\n"); | ||
149 | return -EBUSY; | ||
150 | } | ||
151 | i2s->dma_capture->dma_addr = res->start + S3C2412_IISRXD; | ||
152 | i2s->dma_playback->dma_addr = res->start + S3C2412_IISTXD; | ||
146 | 153 | ||
147 | i2s->dma_capture->client = &s3c64xx_dma_client_in; | 154 | i2s->dma_capture->client = &s3c64xx_dma_client_in; |
148 | i2s->dma_capture->dma_size = 4; | 155 | i2s->dma_capture->dma_size = 4; |
149 | i2s->dma_playback->client = &s3c64xx_dma_client_out; | 156 | i2s->dma_playback->client = &s3c64xx_dma_client_out; |
150 | i2s->dma_playback->dma_size = 4; | 157 | i2s->dma_playback->dma_size = 4; |
151 | 158 | ||
159 | i2s->base = res->start; | ||
160 | |||
161 | i2s_pdata = pdev->dev.platform_data; | ||
162 | if (i2s_pdata && i2s_pdata->cfg_gpio && i2s_pdata->cfg_gpio(pdev)) { | ||
163 | dev_err(&pdev->dev, "Unable to configure gpio\n"); | ||
164 | return -EINVAL; | ||
165 | } | ||
166 | |||
152 | i2s->iis_cclk = clk_get(&pdev->dev, "audio-bus"); | 167 | i2s->iis_cclk = clk_get(&pdev->dev, "audio-bus"); |
153 | if (IS_ERR(i2s->iis_cclk)) { | 168 | if (IS_ERR(i2s->iis_cclk)) { |
154 | dev_err(&pdev->dev, "failed to get audio-bus\n"); | 169 | dev_err(&pdev->dev, "failed to get audio-bus\n"); |
@@ -158,19 +173,13 @@ static __devinit int s3c64xx_i2sv4_dev_probe(struct platform_device *pdev) | |||
158 | 173 | ||
159 | clk_enable(i2s->iis_cclk); | 174 | clk_enable(i2s->iis_cclk); |
160 | 175 | ||
161 | ret = s3c_i2sv2_probe(pdev, dai, i2s, 0); | 176 | ret = s3c_i2sv2_register_dai(&pdev->dev, pdev->id, &s3c64xx_i2s_v4_dai); |
162 | if (ret) | ||
163 | goto err_clk; | ||
164 | |||
165 | ret = s3c_i2sv2_register_dai(dai); | ||
166 | if (ret != 0) | 177 | if (ret != 0) |
167 | goto err_i2sv2; | 178 | goto err_i2sv2; |
168 | 179 | ||
169 | return 0; | 180 | return 0; |
170 | 181 | ||
171 | err_i2sv2: | 182 | err_i2sv2: |
172 | /* Not implemented for I2Sv2 core yet */ | ||
173 | err_clk: | ||
174 | clk_put(i2s->iis_cclk); | 183 | clk_put(i2s->iis_cclk); |
175 | err: | 184 | err: |
176 | return ret; | 185 | return ret; |
@@ -178,7 +187,7 @@ err: | |||
178 | 187 | ||
179 | static __devexit int s3c64xx_i2sv4_dev_remove(struct platform_device *pdev) | 188 | static __devexit int s3c64xx_i2sv4_dev_remove(struct platform_device *pdev) |
180 | { | 189 | { |
181 | dev_err(&pdev->dev, "Device removal not yet supported\n"); | 190 | snd_soc_unregister_dai(&pdev->dev); |
182 | return 0; | 191 | return 0; |
183 | } | 192 | } |
184 | 193 | ||
@@ -207,3 +216,4 @@ module_exit(s3c64xx_i2sv4_exit); | |||
207 | MODULE_AUTHOR("Jaswinder Singh, <jassi.brar@samsung.com>"); | 216 | MODULE_AUTHOR("Jaswinder Singh, <jassi.brar@samsung.com>"); |
208 | MODULE_DESCRIPTION("S3C64XX I2Sv4 SoC Interface"); | 217 | MODULE_DESCRIPTION("S3C64XX I2Sv4 SoC Interface"); |
209 | MODULE_LICENSE("GPL"); | 218 | MODULE_LICENSE("GPL"); |
219 | MODULE_ALIAS("platform:s3c64xx-iis-v4"); | ||
diff --git a/sound/soc/s3c24xx/s3c64xx-i2s.c b/sound/soc/s3c24xx/s3c64xx-i2s.c index 1d85cb85a7d2..ae7acb6c4f1d 100644 --- a/sound/soc/s3c24xx/s3c64xx-i2s.c +++ b/sound/soc/s3c24xx/s3c64xx-i2s.c | |||
@@ -12,15 +12,15 @@ | |||
12 | * published by the Free Software Foundation. | 12 | * published by the Free Software Foundation. |
13 | */ | 13 | */ |
14 | 14 | ||
15 | #include <linux/module.h> | ||
15 | #include <linux/clk.h> | 16 | #include <linux/clk.h> |
16 | #include <linux/gpio.h> | 17 | #include <linux/gpio.h> |
17 | #include <linux/io.h> | 18 | #include <linux/io.h> |
19 | #include <linux/slab.h> | ||
18 | 20 | ||
19 | #include <sound/soc.h> | 21 | #include <sound/soc.h> |
20 | 22 | ||
21 | #include <mach/gpio-bank-d.h> | 23 | #include <plat/audio.h> |
22 | #include <mach/gpio-bank-e.h> | ||
23 | #include <plat/gpio-cfg.h> | ||
24 | 24 | ||
25 | #include <mach/map.h> | 25 | #include <mach/map.h> |
26 | #include <mach/dma.h> | 26 | #include <mach/dma.h> |
@@ -46,45 +46,107 @@ static struct s3c_dma_params s3c64xx_i2s_pcm_stereo_out[MAX_I2SV3]; | |||
46 | static struct s3c_dma_params s3c64xx_i2s_pcm_stereo_in[MAX_I2SV3]; | 46 | static struct s3c_dma_params s3c64xx_i2s_pcm_stereo_in[MAX_I2SV3]; |
47 | static struct s3c_i2sv2_info s3c64xx_i2s[MAX_I2SV3]; | 47 | static struct s3c_i2sv2_info s3c64xx_i2s[MAX_I2SV3]; |
48 | 48 | ||
49 | struct snd_soc_dai s3c64xx_i2s_dai[MAX_I2SV3]; | 49 | struct clk *s3c64xx_i2s_get_clock(struct snd_soc_dai *dai) |
50 | EXPORT_SYMBOL_GPL(s3c64xx_i2s_dai); | ||
51 | |||
52 | static inline struct s3c_i2sv2_info *to_info(struct snd_soc_dai *cpu_dai) | ||
53 | { | 50 | { |
54 | return cpu_dai->private_data; | 51 | struct s3c_i2sv2_info *i2s = snd_soc_dai_get_drvdata(dai); |
52 | u32 iismod = readl(i2s->regs + S3C2412_IISMOD); | ||
53 | |||
54 | if (iismod & S3C2412_IISMOD_IMS_SYSMUX) | ||
55 | return i2s->iis_cclk; | ||
56 | else | ||
57 | return i2s->iis_pclk; | ||
55 | } | 58 | } |
59 | EXPORT_SYMBOL_GPL(s3c64xx_i2s_get_clock); | ||
56 | 60 | ||
57 | static int s3c64xx_i2s_probe(struct platform_device *pdev, | 61 | static int s3c64xx_i2s_probe(struct snd_soc_dai *dai) |
58 | struct snd_soc_dai *dai) | ||
59 | { | 62 | { |
60 | /* configure GPIO for i2s port */ | 63 | struct s3c_i2sv2_info *i2s; |
61 | switch (dai->id) { | 64 | int ret; |
62 | case 0: | 65 | |
63 | s3c_gpio_cfgpin(S3C64XX_GPD(0), S3C64XX_GPD0_I2S0_CLK); | 66 | if (dai->id >= MAX_I2SV3) { |
64 | s3c_gpio_cfgpin(S3C64XX_GPD(1), S3C64XX_GPD1_I2S0_CDCLK); | 67 | dev_err(dai->dev, "id %d out of range\n", dai->id); |
65 | s3c_gpio_cfgpin(S3C64XX_GPD(2), S3C64XX_GPD2_I2S0_LRCLK); | 68 | return -EINVAL; |
66 | s3c_gpio_cfgpin(S3C64XX_GPD(3), S3C64XX_GPD3_I2S0_DI); | 69 | } |
67 | s3c_gpio_cfgpin(S3C64XX_GPD(4), S3C64XX_GPD4_I2S0_D0); | 70 | |
68 | break; | 71 | i2s = &s3c64xx_i2s[dai->id]; |
69 | case 1: | 72 | snd_soc_dai_set_drvdata(dai, i2s); |
70 | s3c_gpio_cfgpin(S3C64XX_GPE(0), S3C64XX_GPE0_I2S1_CLK); | 73 | |
71 | s3c_gpio_cfgpin(S3C64XX_GPE(1), S3C64XX_GPE1_I2S1_CDCLK); | 74 | i2s->iis_cclk = clk_get(dai->dev, "audio-bus"); |
72 | s3c_gpio_cfgpin(S3C64XX_GPE(2), S3C64XX_GPE2_I2S1_LRCLK); | 75 | if (IS_ERR(i2s->iis_cclk)) { |
73 | s3c_gpio_cfgpin(S3C64XX_GPE(3), S3C64XX_GPE3_I2S1_DI); | 76 | dev_err(dai->dev, "failed to get audio-bus\n"); |
74 | s3c_gpio_cfgpin(S3C64XX_GPE(4), S3C64XX_GPE4_I2S1_D0); | 77 | ret = PTR_ERR(i2s->iis_cclk); |
78 | goto err; | ||
75 | } | 79 | } |
76 | 80 | ||
81 | clk_enable(i2s->iis_cclk); | ||
82 | |||
83 | ret = s3c_i2sv2_probe(dai, i2s, i2s->base); | ||
84 | if (ret) | ||
85 | goto err_clk; | ||
86 | |||
77 | return 0; | 87 | return 0; |
88 | |||
89 | err_clk: | ||
90 | clk_disable(i2s->iis_cclk); | ||
91 | clk_put(i2s->iis_cclk); | ||
92 | err: | ||
93 | kfree(i2s); | ||
94 | return ret; | ||
78 | } | 95 | } |
79 | 96 | ||
97 | static int s3c64xx_i2s_remove(struct snd_soc_dai *dai) | ||
98 | { | ||
99 | struct s3c_i2sv2_info *i2s = snd_soc_dai_get_drvdata(dai); | ||
100 | |||
101 | clk_disable(i2s->iis_cclk); | ||
102 | clk_put(i2s->iis_cclk); | ||
103 | kfree(i2s); | ||
104 | return 0; | ||
105 | } | ||
80 | 106 | ||
81 | static struct snd_soc_dai_ops s3c64xx_i2s_dai_ops; | 107 | static struct snd_soc_dai_ops s3c64xx_i2s_dai_ops; |
82 | 108 | ||
109 | static struct snd_soc_dai_driver s3c64xx_i2s_dai[MAX_I2SV3] = { | ||
110 | { | ||
111 | .name = "s3c64xx-i2s-0", | ||
112 | .probe = s3c64xx_i2s_probe, | ||
113 | .remove = s3c64xx_i2s_remove, | ||
114 | .playback = { | ||
115 | .channels_min = 2, | ||
116 | .channels_max = 2, | ||
117 | .rates = S3C64XX_I2S_RATES, | ||
118 | .formats = S3C64XX_I2S_FMTS,}, | ||
119 | .capture = { | ||
120 | .channels_min = 2, | ||
121 | .channels_max = 2, | ||
122 | .rates = S3C64XX_I2S_RATES, | ||
123 | .formats = S3C64XX_I2S_FMTS,}, | ||
124 | .ops = &s3c64xx_i2s_dai_ops, | ||
125 | .symmetric_rates = 1, | ||
126 | }, { | ||
127 | .name = "s3c64xx-i2s-1", | ||
128 | .probe = s3c64xx_i2s_probe, | ||
129 | .remove = s3c64xx_i2s_remove, | ||
130 | .playback = { | ||
131 | .channels_min = 2, | ||
132 | .channels_max = 2, | ||
133 | .rates = S3C64XX_I2S_RATES, | ||
134 | .formats = S3C64XX_I2S_FMTS,}, | ||
135 | .capture = { | ||
136 | .channels_min = 2, | ||
137 | .channels_max = 2, | ||
138 | .rates = S3C64XX_I2S_RATES, | ||
139 | .formats = S3C64XX_I2S_FMTS,}, | ||
140 | .ops = &s3c64xx_i2s_dai_ops, | ||
141 | .symmetric_rates = 1, | ||
142 | },}; | ||
143 | |||
83 | static __devinit int s3c64xx_iis_dev_probe(struct platform_device *pdev) | 144 | static __devinit int s3c64xx_iis_dev_probe(struct platform_device *pdev) |
84 | { | 145 | { |
146 | struct s3c_audio_pdata *i2s_pdata; | ||
85 | struct s3c_i2sv2_info *i2s; | 147 | struct s3c_i2sv2_info *i2s; |
86 | struct snd_soc_dai *dai; | 148 | struct resource *res; |
87 | int ret; | 149 | int i, ret; |
88 | 150 | ||
89 | if (pdev->id >= MAX_I2SV3) { | 151 | if (pdev->id >= MAX_I2SV3) { |
90 | dev_err(&pdev->dev, "id %d out of range\n", pdev->id); | 152 | dev_err(&pdev->dev, "id %d out of range\n", pdev->id); |
@@ -92,74 +154,63 @@ static __devinit int s3c64xx_iis_dev_probe(struct platform_device *pdev) | |||
92 | } | 154 | } |
93 | 155 | ||
94 | i2s = &s3c64xx_i2s[pdev->id]; | 156 | i2s = &s3c64xx_i2s[pdev->id]; |
95 | dai = &s3c64xx_i2s_dai[pdev->id]; | ||
96 | dai->dev = &pdev->dev; | ||
97 | dai->name = "s3c64xx-i2s"; | ||
98 | dai->id = pdev->id; | ||
99 | dai->symmetric_rates = 1; | ||
100 | dai->playback.channels_min = 2; | ||
101 | dai->playback.channels_max = 2; | ||
102 | dai->playback.rates = S3C64XX_I2S_RATES; | ||
103 | dai->playback.formats = S3C64XX_I2S_FMTS; | ||
104 | dai->capture.channels_min = 2; | ||
105 | dai->capture.channels_max = 2; | ||
106 | dai->capture.rates = S3C64XX_I2S_RATES; | ||
107 | dai->capture.formats = S3C64XX_I2S_FMTS; | ||
108 | dai->probe = s3c64xx_i2s_probe; | ||
109 | dai->ops = &s3c64xx_i2s_dai_ops; | ||
110 | |||
111 | i2s->feature |= S3C_FEATURE_CDCLKCON; | ||
112 | 157 | ||
113 | i2s->dma_capture = &s3c64xx_i2s_pcm_stereo_in[pdev->id]; | 158 | i2s->dma_capture = &s3c64xx_i2s_pcm_stereo_in[pdev->id]; |
114 | i2s->dma_playback = &s3c64xx_i2s_pcm_stereo_out[pdev->id]; | 159 | i2s->dma_playback = &s3c64xx_i2s_pcm_stereo_out[pdev->id]; |
115 | 160 | ||
116 | if (pdev->id == 0) { | 161 | res = platform_get_resource(pdev, IORESOURCE_DMA, 0); |
117 | i2s->dma_capture->channel = DMACH_I2S0_IN; | 162 | if (!res) { |
118 | i2s->dma_capture->dma_addr = S3C64XX_PA_IIS0 + S3C2412_IISRXD; | 163 | dev_err(&pdev->dev, "Unable to get I2S-TX dma resource\n"); |
119 | i2s->dma_playback->channel = DMACH_I2S0_OUT; | 164 | return -ENXIO; |
120 | i2s->dma_playback->dma_addr = S3C64XX_PA_IIS0 + S3C2412_IISTXD; | 165 | } |
121 | } else { | 166 | i2s->dma_playback->channel = res->start; |
122 | i2s->dma_capture->channel = DMACH_I2S1_IN; | 167 | |
123 | i2s->dma_capture->dma_addr = S3C64XX_PA_IIS1 + S3C2412_IISRXD; | 168 | res = platform_get_resource(pdev, IORESOURCE_DMA, 1); |
124 | i2s->dma_playback->channel = DMACH_I2S1_OUT; | 169 | if (!res) { |
125 | i2s->dma_playback->dma_addr = S3C64XX_PA_IIS1 + S3C2412_IISTXD; | 170 | dev_err(&pdev->dev, "Unable to get I2S-RX dma resource\n"); |
171 | return -ENXIO; | ||
172 | } | ||
173 | i2s->dma_capture->channel = res->start; | ||
174 | |||
175 | res = platform_get_resource(pdev, IORESOURCE_MEM, 0); | ||
176 | if (!res) { | ||
177 | dev_err(&pdev->dev, "Unable to get I2S SFR address\n"); | ||
178 | return -ENXIO; | ||
126 | } | 179 | } |
127 | 180 | ||
181 | if (!request_mem_region(res->start, resource_size(res), | ||
182 | "s3c64xx-i2s")) { | ||
183 | dev_err(&pdev->dev, "Unable to request SFR region\n"); | ||
184 | return -EBUSY; | ||
185 | } | ||
186 | i2s->base = res->start; | ||
187 | |||
188 | i2s_pdata = pdev->dev.platform_data; | ||
189 | if (i2s_pdata && i2s_pdata->cfg_gpio && i2s_pdata->cfg_gpio(pdev)) { | ||
190 | dev_err(&pdev->dev, "Unable to configure gpio\n"); | ||
191 | return -EINVAL; | ||
192 | } | ||
193 | i2s->dma_capture->dma_addr = res->start + S3C2412_IISRXD; | ||
194 | i2s->dma_playback->dma_addr = res->start + S3C2412_IISTXD; | ||
195 | |||
128 | i2s->dma_capture->client = &s3c64xx_dma_client_in; | 196 | i2s->dma_capture->client = &s3c64xx_dma_client_in; |
129 | i2s->dma_capture->dma_size = 4; | 197 | i2s->dma_capture->dma_size = 4; |
130 | i2s->dma_playback->client = &s3c64xx_dma_client_out; | 198 | i2s->dma_playback->client = &s3c64xx_dma_client_out; |
131 | i2s->dma_playback->dma_size = 4; | 199 | i2s->dma_playback->dma_size = 4; |
132 | 200 | ||
133 | i2s->iis_cclk = clk_get(&pdev->dev, "audio-bus"); | 201 | for (i = 0; i < ARRAY_SIZE(s3c64xx_i2s_dai); i++) { |
134 | if (IS_ERR(i2s->iis_cclk)) { | 202 | ret = s3c_i2sv2_register_dai(&pdev->dev, i, |
135 | dev_err(&pdev->dev, "failed to get audio-bus\n"); | 203 | &s3c64xx_i2s_dai[i]); |
136 | ret = PTR_ERR(i2s->iis_cclk); | 204 | if (ret != 0) |
137 | goto err; | 205 | return ret; |
138 | } | 206 | } |
139 | 207 | ||
140 | clk_enable(i2s->iis_cclk); | ||
141 | |||
142 | ret = s3c_i2sv2_probe(pdev, dai, i2s, 0); | ||
143 | if (ret) | ||
144 | goto err_clk; | ||
145 | |||
146 | ret = s3c_i2sv2_register_dai(dai); | ||
147 | if (ret != 0) | ||
148 | goto err_i2sv2; | ||
149 | |||
150 | return 0; | 208 | return 0; |
151 | |||
152 | err_i2sv2: | ||
153 | /* Not implemented for I2Sv2 core yet */ | ||
154 | err_clk: | ||
155 | clk_put(i2s->iis_cclk); | ||
156 | err: | ||
157 | return ret; | ||
158 | } | 209 | } |
159 | 210 | ||
160 | static __devexit int s3c64xx_iis_dev_remove(struct platform_device *pdev) | 211 | static __devexit int s3c64xx_iis_dev_remove(struct platform_device *pdev) |
161 | { | 212 | { |
162 | dev_err(&pdev->dev, "Device removal not yet supported\n"); | 213 | snd_soc_unregister_dais(&pdev->dev, ARRAY_SIZE(s3c64xx_i2s_dai)); |
163 | return 0; | 214 | return 0; |
164 | } | 215 | } |
165 | 216 | ||
@@ -188,3 +239,4 @@ module_exit(s3c64xx_i2s_exit); | |||
188 | MODULE_AUTHOR("Ben Dooks, <ben@simtec.co.uk>"); | 239 | MODULE_AUTHOR("Ben Dooks, <ben@simtec.co.uk>"); |
189 | MODULE_DESCRIPTION("S3C64XX I2S SoC Interface"); | 240 | MODULE_DESCRIPTION("S3C64XX I2S SoC Interface"); |
190 | MODULE_LICENSE("GPL"); | 241 | MODULE_LICENSE("GPL"); |
242 | MODULE_ALIAS("platform:s3c64xx-iis"); | ||
diff --git a/sound/soc/s3c24xx/s3c64xx-i2s.h b/sound/soc/s3c24xx/s3c64xx-i2s.h index 7a40f43d1d51..19bd444bf8a6 100644 --- a/sound/soc/s3c24xx/s3c64xx-i2s.h +++ b/sound/soc/s3c24xx/s3c64xx-i2s.h | |||
@@ -36,7 +36,5 @@ struct clk; | |||
36 | (SNDRV_PCM_FMTBIT_S8 | SNDRV_PCM_FMTBIT_S16_LE |\ | 36 | (SNDRV_PCM_FMTBIT_S8 | SNDRV_PCM_FMTBIT_S16_LE |\ |
37 | SNDRV_PCM_FMTBIT_S24_LE) | 37 | SNDRV_PCM_FMTBIT_S24_LE) |
38 | 38 | ||
39 | extern struct snd_soc_dai s3c64xx_i2s_dai[]; | ||
40 | extern struct snd_soc_dai s3c64xx_i2s_v4_dai; | ||
41 | 39 | ||
42 | #endif /* __SND_SOC_S3C24XX_S3C64XX_I2S_H */ | 40 | #endif /* __SND_SOC_S3C24XX_S3C64XX_I2S_H */ |
diff --git a/sound/soc/s3c24xx/smartq_wm8987.c b/sound/soc/s3c24xx/smartq_wm8987.c index b480348140b0..dd20ca7f4681 100644 --- a/sound/soc/s3c24xx/smartq_wm8987.c +++ b/sound/soc/s3c24xx/smartq_wm8987.c | |||
@@ -211,8 +211,10 @@ static struct snd_soc_dai_link smartq_dai[] = { | |||
211 | { | 211 | { |
212 | .name = "wm8987", | 212 | .name = "wm8987", |
213 | .stream_name = "SmartQ Hi-Fi", | 213 | .stream_name = "SmartQ Hi-Fi", |
214 | .cpu_dai = &s3c64xx_i2s_dai[0], | 214 | .cpu_dai_name = "s3c64xx-i2s.0", |
215 | .codec_dai = &wm8750_dai, | 215 | .codec_dai_name = "wm8750-hifi", |
216 | .platform_name = "s3c24xx-pcm-audio", | ||
217 | .codec_name = "wm8750-codec.0-0x1a", | ||
216 | .init = smartq_wm8987_init, | 218 | .init = smartq_wm8987_init, |
217 | .ops = &smartq_hifi_ops, | 219 | .ops = &smartq_hifi_ops, |
218 | }, | 220 | }, |
@@ -220,16 +222,10 @@ static struct snd_soc_dai_link smartq_dai[] = { | |||
220 | 222 | ||
221 | static struct snd_soc_card snd_soc_smartq = { | 223 | static struct snd_soc_card snd_soc_smartq = { |
222 | .name = "SmartQ", | 224 | .name = "SmartQ", |
223 | .platform = &s3c24xx_soc_platform, | ||
224 | .dai_link = smartq_dai, | 225 | .dai_link = smartq_dai, |
225 | .num_links = ARRAY_SIZE(smartq_dai), | 226 | .num_links = ARRAY_SIZE(smartq_dai), |
226 | }; | 227 | }; |
227 | 228 | ||
228 | static struct snd_soc_device smartq_snd_devdata = { | ||
229 | .card = &snd_soc_smartq, | ||
230 | .codec_dev = &soc_codec_dev_wm8750, | ||
231 | }; | ||
232 | |||
233 | static struct platform_device *smartq_snd_device; | 229 | static struct platform_device *smartq_snd_device; |
234 | 230 | ||
235 | static int __init smartq_init(void) | 231 | static int __init smartq_init(void) |
@@ -245,8 +241,7 @@ static int __init smartq_init(void) | |||
245 | if (!smartq_snd_device) | 241 | if (!smartq_snd_device) |
246 | return -ENOMEM; | 242 | return -ENOMEM; |
247 | 243 | ||
248 | platform_set_drvdata(smartq_snd_device, &smartq_snd_devdata); | 244 | platform_set_drvdata(smartq_snd_device, &snd_soc_smartq); |
249 | smartq_snd_devdata.dev = &smartq_snd_device->dev; | ||
250 | 245 | ||
251 | ret = platform_device_add(smartq_snd_device); | 246 | ret = platform_device_add(smartq_snd_device); |
252 | if (ret) { | 247 | if (ret) { |
diff --git a/sound/soc/s3c24xx/smdk2443_wm9710.c b/sound/soc/s3c24xx/smdk2443_wm9710.c index 362258835e8d..66f9e222220b 100644 --- a/sound/soc/s3c24xx/smdk2443_wm9710.c +++ b/sound/soc/s3c24xx/smdk2443_wm9710.c | |||
@@ -19,7 +19,6 @@ | |||
19 | #include <sound/soc.h> | 19 | #include <sound/soc.h> |
20 | #include <sound/soc-dapm.h> | 20 | #include <sound/soc-dapm.h> |
21 | 21 | ||
22 | #include "../codecs/ac97.h" | ||
23 | #include "s3c-dma.h" | 22 | #include "s3c-dma.h" |
24 | #include "s3c-ac97.h" | 23 | #include "s3c-ac97.h" |
25 | 24 | ||
@@ -29,23 +28,19 @@ static struct snd_soc_dai_link smdk2443_dai[] = { | |||
29 | { | 28 | { |
30 | .name = "AC97", | 29 | .name = "AC97", |
31 | .stream_name = "AC97 HiFi", | 30 | .stream_name = "AC97 HiFi", |
32 | .cpu_dai = &s3c_ac97_dai[S3C_AC97_DAI_PCM], | 31 | .cpu_dai_name = "s3c-ac97-dai", |
33 | .codec_dai = &ac97_dai, | 32 | .codec_dai_name = "ac97-hifi", |
33 | .codec_name = "ac97-codec", | ||
34 | .platform_name = "s3c24xx-pcm-audio", | ||
34 | }, | 35 | }, |
35 | }; | 36 | }; |
36 | 37 | ||
37 | static struct snd_soc_card smdk2443 = { | 38 | static struct snd_soc_card smdk2443 = { |
38 | .name = "SMDK2443", | 39 | .name = "SMDK2443", |
39 | .platform = &s3c24xx_soc_platform, | ||
40 | .dai_link = smdk2443_dai, | 40 | .dai_link = smdk2443_dai, |
41 | .num_links = ARRAY_SIZE(smdk2443_dai), | 41 | .num_links = ARRAY_SIZE(smdk2443_dai), |
42 | }; | 42 | }; |
43 | 43 | ||
44 | static struct snd_soc_device smdk2443_snd_ac97_devdata = { | ||
45 | .card = &smdk2443, | ||
46 | .codec_dev = &soc_codec_dev_ac97, | ||
47 | }; | ||
48 | |||
49 | static struct platform_device *smdk2443_snd_ac97_device; | 44 | static struct platform_device *smdk2443_snd_ac97_device; |
50 | 45 | ||
51 | static int __init smdk2443_init(void) | 46 | static int __init smdk2443_init(void) |
@@ -56,9 +51,7 @@ static int __init smdk2443_init(void) | |||
56 | if (!smdk2443_snd_ac97_device) | 51 | if (!smdk2443_snd_ac97_device) |
57 | return -ENOMEM; | 52 | return -ENOMEM; |
58 | 53 | ||
59 | platform_set_drvdata(smdk2443_snd_ac97_device, | 54 | platform_set_drvdata(smdk2443_snd_ac97_device, &smdk2443); |
60 | &smdk2443_snd_ac97_devdata); | ||
61 | smdk2443_snd_ac97_devdata.dev = &smdk2443_snd_ac97_device->dev; | ||
62 | ret = platform_device_add(smdk2443_snd_ac97_device); | 55 | ret = platform_device_add(smdk2443_snd_ac97_device); |
63 | 56 | ||
64 | if (ret) | 57 | if (ret) |
diff --git a/sound/soc/s3c24xx/smdk64xx_wm8580.c b/sound/soc/s3c24xx/smdk64xx_wm8580.c index 4926acaaa8b0..5c21e26da075 100644 --- a/sound/soc/s3c24xx/smdk64xx_wm8580.c +++ b/sound/soc/s3c24xx/smdk64xx_wm8580.c | |||
@@ -35,8 +35,8 @@ static int smdk64xx_hw_params(struct snd_pcm_substream *substream, | |||
35 | struct snd_pcm_hw_params *params) | 35 | struct snd_pcm_hw_params *params) |
36 | { | 36 | { |
37 | struct snd_soc_pcm_runtime *rtd = substream->private_data; | 37 | struct snd_soc_pcm_runtime *rtd = substream->private_data; |
38 | struct snd_soc_dai *cpu_dai = rtd->dai->cpu_dai; | 38 | struct snd_soc_dai *cpu_dai = rtd->cpu_dai; |
39 | struct snd_soc_dai *codec_dai = rtd->dai->codec_dai; | 39 | struct snd_soc_dai *codec_dai = rtd->codec_dai; |
40 | unsigned int pll_out; | 40 | unsigned int pll_out; |
41 | int bfs, rfs, ret; | 41 | int bfs, rfs, ret; |
42 | 42 | ||
@@ -180,8 +180,10 @@ static const struct snd_soc_dapm_route audio_map_rx[] = { | |||
180 | {"Rear", NULL, "VOUT3R"}, | 180 | {"Rear", NULL, "VOUT3R"}, |
181 | }; | 181 | }; |
182 | 182 | ||
183 | static int smdk64xx_wm8580_init_paiftx(struct snd_soc_codec *codec) | 183 | static int smdk64xx_wm8580_init_paiftx(struct snd_soc_pcm_runtime *rtd) |
184 | { | 184 | { |
185 | struct snd_soc_codec *codec = rtd->codec; | ||
186 | |||
185 | /* Add smdk64xx specific Capture widgets */ | 187 | /* Add smdk64xx specific Capture widgets */ |
186 | snd_soc_dapm_new_controls(codec, wm8580_dapm_widgets_cpt, | 188 | snd_soc_dapm_new_controls(codec, wm8580_dapm_widgets_cpt, |
187 | ARRAY_SIZE(wm8580_dapm_widgets_cpt)); | 189 | ARRAY_SIZE(wm8580_dapm_widgets_cpt)); |
@@ -200,8 +202,10 @@ static int smdk64xx_wm8580_init_paiftx(struct snd_soc_codec *codec) | |||
200 | return 0; | 202 | return 0; |
201 | } | 203 | } |
202 | 204 | ||
203 | static int smdk64xx_wm8580_init_paifrx(struct snd_soc_codec *codec) | 205 | static int smdk64xx_wm8580_init_paifrx(struct snd_soc_pcm_runtime *rtd) |
204 | { | 206 | { |
207 | struct snd_soc_codec *codec = rtd->codec; | ||
208 | |||
205 | /* Add smdk64xx specific Playback widgets */ | 209 | /* Add smdk64xx specific Playback widgets */ |
206 | snd_soc_dapm_new_controls(codec, wm8580_dapm_widgets_pbk, | 210 | snd_soc_dapm_new_controls(codec, wm8580_dapm_widgets_pbk, |
207 | ARRAY_SIZE(wm8580_dapm_widgets_pbk)); | 211 | ARRAY_SIZE(wm8580_dapm_widgets_pbk)); |
@@ -219,16 +223,20 @@ static struct snd_soc_dai_link smdk64xx_dai[] = { | |||
219 | { /* Primary Playback i/f */ | 223 | { /* Primary Playback i/f */ |
220 | .name = "WM8580 PAIF RX", | 224 | .name = "WM8580 PAIF RX", |
221 | .stream_name = "Playback", | 225 | .stream_name = "Playback", |
222 | .cpu_dai = &s3c64xx_i2s_v4_dai, | 226 | .cpu_dai_name = "s3c64xx-iis-v4", |
223 | .codec_dai = &wm8580_dai[WM8580_DAI_PAIFRX], | 227 | .codec_dai_name = "wm8580-hifi-playback", |
228 | .platform_name = "s3c24xx-pcm-audio", | ||
229 | .codec_name = "wm8580-codec.0-001b", | ||
224 | .init = smdk64xx_wm8580_init_paifrx, | 230 | .init = smdk64xx_wm8580_init_paifrx, |
225 | .ops = &smdk64xx_ops, | 231 | .ops = &smdk64xx_ops, |
226 | }, | 232 | }, |
227 | { /* Primary Capture i/f */ | 233 | { /* Primary Capture i/f */ |
228 | .name = "WM8580 PAIF TX", | 234 | .name = "WM8580 PAIF TX", |
229 | .stream_name = "Capture", | 235 | .stream_name = "Capture", |
230 | .cpu_dai = &s3c64xx_i2s_v4_dai, | 236 | .cpu_dai_name = "s3c64xx-iis-v4", |
231 | .codec_dai = &wm8580_dai[WM8580_DAI_PAIFTX], | 237 | .codec_dai_name = "wm8580-hifi-capture", |
238 | .platform_name = "s3c24xx-pcm-audio", | ||
239 | .codec_name = "wm8580-codec.0-001b", | ||
232 | .init = smdk64xx_wm8580_init_paiftx, | 240 | .init = smdk64xx_wm8580_init_paiftx, |
233 | .ops = &smdk64xx_ops, | 241 | .ops = &smdk64xx_ops, |
234 | }, | 242 | }, |
@@ -236,16 +244,10 @@ static struct snd_soc_dai_link smdk64xx_dai[] = { | |||
236 | 244 | ||
237 | static struct snd_soc_card smdk64xx = { | 245 | static struct snd_soc_card smdk64xx = { |
238 | .name = "smdk64xx", | 246 | .name = "smdk64xx", |
239 | .platform = &s3c24xx_soc_platform, | ||
240 | .dai_link = smdk64xx_dai, | 247 | .dai_link = smdk64xx_dai, |
241 | .num_links = ARRAY_SIZE(smdk64xx_dai), | 248 | .num_links = ARRAY_SIZE(smdk64xx_dai), |
242 | }; | 249 | }; |
243 | 250 | ||
244 | static struct snd_soc_device smdk64xx_snd_devdata = { | ||
245 | .card = &smdk64xx, | ||
246 | .codec_dev = &soc_codec_dev_wm8580, | ||
247 | }; | ||
248 | |||
249 | static struct platform_device *smdk64xx_snd_device; | 251 | static struct platform_device *smdk64xx_snd_device; |
250 | 252 | ||
251 | static int __init smdk64xx_audio_init(void) | 253 | static int __init smdk64xx_audio_init(void) |
@@ -256,8 +258,7 @@ static int __init smdk64xx_audio_init(void) | |||
256 | if (!smdk64xx_snd_device) | 258 | if (!smdk64xx_snd_device) |
257 | return -ENOMEM; | 259 | return -ENOMEM; |
258 | 260 | ||
259 | platform_set_drvdata(smdk64xx_snd_device, &smdk64xx_snd_devdata); | 261 | platform_set_drvdata(smdk64xx_snd_device, &smdk64xx); |
260 | smdk64xx_snd_devdata.dev = &smdk64xx_snd_device->dev; | ||
261 | ret = platform_device_add(smdk64xx_snd_device); | 262 | ret = platform_device_add(smdk64xx_snd_device); |
262 | 263 | ||
263 | if (ret) | 264 | if (ret) |
diff --git a/sound/soc/s3c24xx/smdk_wm9713.c b/sound/soc/s3c24xx/smdk_wm9713.c index 5527b9e88c98..90108a7a0a8e 100644 --- a/sound/soc/s3c24xx/smdk_wm9713.c +++ b/sound/soc/s3c24xx/smdk_wm9713.c | |||
@@ -46,40 +46,50 @@ static struct snd_soc_card smdk; | |||
46 | static struct snd_soc_dai_link smdk_dai = { | 46 | static struct snd_soc_dai_link smdk_dai = { |
47 | .name = "AC97", | 47 | .name = "AC97", |
48 | .stream_name = "AC97 PCM", | 48 | .stream_name = "AC97 PCM", |
49 | .cpu_dai = &s3c_ac97_dai[S3C_AC97_DAI_PCM], | 49 | .platform_name = "s3c24xx-pcm-audio", |
50 | .codec_dai = &wm9713_dai[WM9713_DAI_AC97_HIFI], | 50 | .cpu_dai_name = "s3c-ac97-dai", |
51 | .codec_dai_name = "wm9713-hifi", | ||
52 | .codec_name = "wm9713-codec", | ||
51 | }; | 53 | }; |
52 | 54 | ||
53 | static struct snd_soc_card smdk = { | 55 | static struct snd_soc_card smdk = { |
54 | .name = "SMDK", | 56 | .name = "SMDK", |
55 | .platform = &s3c24xx_soc_platform, | ||
56 | .dai_link = &smdk_dai, | 57 | .dai_link = &smdk_dai, |
57 | .num_links = 1, | 58 | .num_links = 1, |
58 | }; | 59 | }; |
59 | 60 | ||
60 | static struct snd_soc_device smdk_snd_ac97_devdata = { | 61 | static struct platform_device *smdk_snd_wm9713_device; |
61 | .card = &smdk, | ||
62 | .codec_dev = &soc_codec_dev_wm9713, | ||
63 | }; | ||
64 | |||
65 | static struct platform_device *smdk_snd_ac97_device; | 62 | static struct platform_device *smdk_snd_ac97_device; |
66 | 63 | ||
67 | static int __init smdk_init(void) | 64 | static int __init smdk_init(void) |
68 | { | 65 | { |
69 | int ret; | 66 | int ret; |
70 | 67 | ||
71 | smdk_snd_ac97_device = platform_device_alloc("soc-audio", -1); | 68 | smdk_snd_wm9713_device = platform_device_alloc("wm9713-codec", -1); |
72 | if (!smdk_snd_ac97_device) | 69 | if (!smdk_snd_wm9713_device) |
73 | return -ENOMEM; | 70 | return -ENOMEM; |
74 | 71 | ||
75 | platform_set_drvdata(smdk_snd_ac97_device, | 72 | ret = platform_device_add(smdk_snd_wm9713_device); |
76 | &smdk_snd_ac97_devdata); | 73 | if (ret) |
77 | smdk_snd_ac97_devdata.dev = &smdk_snd_ac97_device->dev; | 74 | goto err; |
75 | |||
76 | smdk_snd_ac97_device = platform_device_alloc("soc-audio", -1); | ||
77 | if (!smdk_snd_ac97_device) { | ||
78 | ret = -ENOMEM; | ||
79 | goto err; | ||
80 | } | ||
81 | |||
82 | platform_set_drvdata(smdk_snd_ac97_device, &smdk); | ||
78 | 83 | ||
79 | ret = platform_device_add(smdk_snd_ac97_device); | 84 | ret = platform_device_add(smdk_snd_ac97_device); |
80 | if (ret) | 85 | if (ret) { |
81 | platform_device_put(smdk_snd_ac97_device); | 86 | platform_device_put(smdk_snd_ac97_device); |
87 | goto err; | ||
88 | } | ||
82 | 89 | ||
90 | return 0; | ||
91 | err: | ||
92 | platform_device_put(smdk_snd_wm9713_device); | ||
83 | return ret; | 93 | return ret; |
84 | } | 94 | } |
85 | 95 | ||
diff --git a/sound/soc/s6000/s6000-i2s.c b/sound/soc/s6000/s6000-i2s.c index 59e3fa7bcb05..8778faa174a6 100644 --- a/sound/soc/s6000/s6000-i2s.c +++ b/sound/soc/s6000/s6000-i2s.c | |||
@@ -140,7 +140,7 @@ static void s6000_i2s_stop_channel(struct s6000_i2s_dev *dev, int channel) | |||
140 | static void s6000_i2s_start(struct snd_pcm_substream *substream) | 140 | static void s6000_i2s_start(struct snd_pcm_substream *substream) |
141 | { | 141 | { |
142 | struct snd_soc_pcm_runtime *rtd = substream->private_data; | 142 | struct snd_soc_pcm_runtime *rtd = substream->private_data; |
143 | struct s6000_i2s_dev *dev = rtd->dai->cpu_dai->private_data; | 143 | struct s6000_i2s_dev *dev = snd_soc_dai_get_drvdata(rtd->cpu_dai); |
144 | int channel; | 144 | int channel; |
145 | 145 | ||
146 | channel = (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) ? | 146 | channel = (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) ? |
@@ -152,7 +152,7 @@ static void s6000_i2s_start(struct snd_pcm_substream *substream) | |||
152 | static void s6000_i2s_stop(struct snd_pcm_substream *substream) | 152 | static void s6000_i2s_stop(struct snd_pcm_substream *substream) |
153 | { | 153 | { |
154 | struct snd_soc_pcm_runtime *rtd = substream->private_data; | 154 | struct snd_soc_pcm_runtime *rtd = substream->private_data; |
155 | struct s6000_i2s_dev *dev = rtd->dai->cpu_dai->private_data; | 155 | struct s6000_i2s_dev *dev = snd_soc_dai_get_drvdata(rtd->cpu_dai); |
156 | int channel; | 156 | int channel; |
157 | 157 | ||
158 | channel = (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) ? | 158 | channel = (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) ? |
@@ -194,7 +194,7 @@ static unsigned int s6000_i2s_int_sources(struct s6000_i2s_dev *dev) | |||
194 | 194 | ||
195 | static unsigned int s6000_i2s_check_xrun(struct snd_soc_dai *cpu_dai) | 195 | static unsigned int s6000_i2s_check_xrun(struct snd_soc_dai *cpu_dai) |
196 | { | 196 | { |
197 | struct s6000_i2s_dev *dev = cpu_dai->private_data; | 197 | struct s6000_i2s_dev *dev = snd_soc_dai_get_drvdata(cpu_dai); |
198 | unsigned int errors; | 198 | unsigned int errors; |
199 | unsigned int ret; | 199 | unsigned int ret; |
200 | 200 | ||
@@ -232,7 +232,7 @@ static void s6000_i2s_wait_disabled(struct s6000_i2s_dev *dev) | |||
232 | static int s6000_i2s_set_dai_fmt(struct snd_soc_dai *cpu_dai, | 232 | static int s6000_i2s_set_dai_fmt(struct snd_soc_dai *cpu_dai, |
233 | unsigned int fmt) | 233 | unsigned int fmt) |
234 | { | 234 | { |
235 | struct s6000_i2s_dev *dev = cpu_dai->private_data; | 235 | struct s6000_i2s_dev *dev = snd_soc_dai_get_drvdata(cpu_dai); |
236 | u32 w; | 236 | u32 w; |
237 | 237 | ||
238 | switch (fmt & SND_SOC_DAIFMT_MASTER_MASK) { | 238 | switch (fmt & SND_SOC_DAIFMT_MASTER_MASK) { |
@@ -273,7 +273,7 @@ static int s6000_i2s_set_dai_fmt(struct snd_soc_dai *cpu_dai, | |||
273 | 273 | ||
274 | static int s6000_i2s_set_clkdiv(struct snd_soc_dai *dai, int div_id, int div) | 274 | static int s6000_i2s_set_clkdiv(struct snd_soc_dai *dai, int div_id, int div) |
275 | { | 275 | { |
276 | struct s6000_i2s_dev *dev = dai->private_data; | 276 | struct s6000_i2s_dev *dev = snd_soc_dai_get_drvdata(dai); |
277 | 277 | ||
278 | if (!div || (div & 1) || div > (S6_I2S_DIV_MASK + 1) * 2) | 278 | if (!div || (div & 1) || div > (S6_I2S_DIV_MASK + 1) * 2) |
279 | return -EINVAL; | 279 | return -EINVAL; |
@@ -287,7 +287,7 @@ static int s6000_i2s_hw_params(struct snd_pcm_substream *substream, | |||
287 | struct snd_pcm_hw_params *params, | 287 | struct snd_pcm_hw_params *params, |
288 | struct snd_soc_dai *dai) | 288 | struct snd_soc_dai *dai) |
289 | { | 289 | { |
290 | struct s6000_i2s_dev *dev = dai->private_data; | 290 | struct s6000_i2s_dev *dev = snd_soc_dai_get_drvdata(dai); |
291 | int interf; | 291 | int interf; |
292 | u32 w = 0; | 292 | u32 w = 0; |
293 | 293 | ||
@@ -326,15 +326,17 @@ static int s6000_i2s_hw_params(struct snd_pcm_substream *substream, | |||
326 | return 0; | 326 | return 0; |
327 | } | 327 | } |
328 | 328 | ||
329 | static int s6000_i2s_dai_probe(struct platform_device *pdev, | 329 | static int s6000_i2s_dai_probe(struct snd_soc_dai *dai) |
330 | struct snd_soc_dai *dai) | ||
331 | { | 330 | { |
332 | struct s6000_i2s_dev *dev = dai->private_data; | 331 | struct s6000_i2s_dev *dev = snd_soc_dai_get_drvdata(dai); |
333 | struct s6000_snd_platform_data *pdata = pdev->dev.platform_data; | 332 | struct s6000_snd_platform_data *pdata = dai->dev->platform_data; |
334 | 333 | ||
335 | if (!pdata) | 334 | if (!pdata) |
336 | return -EINVAL; | 335 | return -EINVAL; |
337 | 336 | ||
337 | dai->capture_dma_data = &dev->dma_params; | ||
338 | dai->playback_dma_data = &dev->dma_params; | ||
339 | |||
338 | dev->wide = pdata->wide; | 340 | dev->wide = pdata->wide; |
339 | dev->channel_in = pdata->channel_in; | 341 | dev->channel_in = pdata->channel_in; |
340 | dev->channel_out = pdata->channel_out; | 342 | dev->channel_out = pdata->channel_out; |
@@ -352,10 +354,10 @@ static int s6000_i2s_dai_probe(struct platform_device *pdev, | |||
352 | 354 | ||
353 | dev->channel_in = 0; | 355 | dev->channel_in = 0; |
354 | dev->channel_out = 1; | 356 | dev->channel_out = 1; |
355 | dai->capture.channels_min = 2 * dev->lines_in; | 357 | dai->driver->capture.channels_min = 2 * dev->lines_in; |
356 | dai->capture.channels_max = dai->capture.channels_min; | 358 | dai->driver->capture.channels_max = dai->driver->capture.channels_min; |
357 | dai->playback.channels_min = 2 * dev->lines_out; | 359 | dai->driver->playback.channels_min = 2 * dev->lines_out; |
358 | dai->playback.channels_max = dai->playback.channels_min; | 360 | dai->driver->playback.channels_max = dai->driver->playback.channels_min; |
359 | 361 | ||
360 | for (i = 0; i < dev->lines_out; i++) | 362 | for (i = 0; i < dev->lines_out; i++) |
361 | s6_i2s_write_reg(dev, S6_I2S_DATA_CFG(i), S6_I2S_OUT); | 363 | s6_i2s_write_reg(dev, S6_I2S_DATA_CFG(i), S6_I2S_OUT); |
@@ -372,10 +374,10 @@ static int s6000_i2s_dai_probe(struct platform_device *pdev, | |||
372 | if (dev->lines_in > 1 || dev->lines_out > 1) | 374 | if (dev->lines_in > 1 || dev->lines_out > 1) |
373 | return -EINVAL; | 375 | return -EINVAL; |
374 | 376 | ||
375 | dai->capture.channels_min = 2 * dev->lines_in; | 377 | dai->driver->capture.channels_min = 2 * dev->lines_in; |
376 | dai->capture.channels_max = 8 * dev->lines_in; | 378 | dai->driver->capture.channels_max = 8 * dev->lines_in; |
377 | dai->playback.channels_min = 2 * dev->lines_out; | 379 | dai->driver->playback.channels_min = 2 * dev->lines_out; |
378 | dai->playback.channels_max = 8 * dev->lines_out; | 380 | dai->driver->playback.channels_max = 8 * dev->lines_out; |
379 | 381 | ||
380 | if (dev->lines_in) | 382 | if (dev->lines_in) |
381 | cfg[dev->channel_in] = S6_I2S_IN; | 383 | cfg[dev->channel_in] = S6_I2S_IN; |
@@ -413,9 +415,7 @@ static struct snd_soc_dai_ops s6000_i2s_dai_ops = { | |||
413 | .hw_params = s6000_i2s_hw_params, | 415 | .hw_params = s6000_i2s_hw_params, |
414 | }; | 416 | }; |
415 | 417 | ||
416 | struct snd_soc_dai s6000_i2s_dai = { | 418 | static struct snd_soc_dai_driver s6000_i2s_dai = { |
417 | .name = "s6000-i2s", | ||
418 | .id = 0, | ||
419 | .probe = s6000_i2s_dai_probe, | 419 | .probe = s6000_i2s_dai_probe, |
420 | .playback = { | 420 | .playback = { |
421 | .channels_min = 2, | 421 | .channels_min = 2, |
@@ -435,7 +435,6 @@ struct snd_soc_dai s6000_i2s_dai = { | |||
435 | }, | 435 | }, |
436 | .ops = &s6000_i2s_dai_ops, | 436 | .ops = &s6000_i2s_dai_ops, |
437 | } | 437 | } |
438 | EXPORT_SYMBOL_GPL(s6000_i2s_dai); | ||
439 | 438 | ||
440 | static int __devinit s6000_i2s_probe(struct platform_device *pdev) | 439 | static int __devinit s6000_i2s_probe(struct platform_device *pdev) |
441 | { | 440 | { |
@@ -513,11 +512,7 @@ static int __devinit s6000_i2s_probe(struct platform_device *pdev) | |||
513 | ret = -ENOMEM; | 512 | ret = -ENOMEM; |
514 | goto err_release_dma2; | 513 | goto err_release_dma2; |
515 | } | 514 | } |
516 | 515 | dev_set_drvdata(&pdev->dev, dev); | |
517 | s6000_i2s_dai.dev = &pdev->dev; | ||
518 | s6000_i2s_dai.private_data = dev; | ||
519 | s6000_i2s_dai.capture.dma_data = &dev->dma_params; | ||
520 | s6000_i2s_dai.playback.dma_data = &dev->dma_params; | ||
521 | 516 | ||
522 | dev->sifbase = sifmem->start; | 517 | dev->sifbase = sifmem->start; |
523 | dev->scbbase = mmio; | 518 | dev->scbbase = mmio; |
@@ -548,7 +543,7 @@ static int __devinit s6000_i2s_probe(struct platform_device *pdev) | |||
548 | S6_I2S_INT_UNDERRUN | | 543 | S6_I2S_INT_UNDERRUN | |
549 | S6_I2S_INT_OVERRUN); | 544 | S6_I2S_INT_OVERRUN); |
550 | 545 | ||
551 | ret = snd_soc_register_dai(&s6000_i2s_dai); | 546 | ret = snd_soc_register_dai(&pdev->dev, &s6000_i2s_dai); |
552 | if (ret) | 547 | if (ret) |
553 | goto err_release_dev; | 548 | goto err_release_dev; |
554 | 549 | ||
@@ -573,17 +568,16 @@ err_release_none: | |||
573 | 568 | ||
574 | static void __devexit s6000_i2s_remove(struct platform_device *pdev) | 569 | static void __devexit s6000_i2s_remove(struct platform_device *pdev) |
575 | { | 570 | { |
576 | struct s6000_i2s_dev *dev = s6000_i2s_dai.private_data; | 571 | struct s6000_i2s_dev *dev = dev_get_drvdata(&pdev->dev); |
577 | struct resource *region; | 572 | struct resource *region; |
578 | void __iomem *mmio = dev->scbbase; | 573 | void __iomem *mmio = dev->scbbase; |
579 | 574 | ||
580 | snd_soc_unregister_dai(&s6000_i2s_dai); | 575 | snd_soc_unregister_dai(&pdev->dev); |
581 | 576 | ||
582 | s6000_i2s_stop_channel(dev, 0); | 577 | s6000_i2s_stop_channel(dev, 0); |
583 | s6000_i2s_stop_channel(dev, 1); | 578 | s6000_i2s_stop_channel(dev, 1); |
584 | 579 | ||
585 | s6_i2s_write_reg(dev, S6_I2S_INTERRUPT_ENABLE, 0); | 580 | s6_i2s_write_reg(dev, S6_I2S_INTERRUPT_ENABLE, 0); |
586 | s6000_i2s_dai.private_data = 0; | ||
587 | kfree(dev); | 581 | kfree(dev); |
588 | 582 | ||
589 | region = platform_get_resource(pdev, IORESOURCE_DMA, 0); | 583 | region = platform_get_resource(pdev, IORESOURCE_DMA, 0); |
diff --git a/sound/soc/s6000/s6000-i2s.h b/sound/soc/s6000/s6000-i2s.h index 2375fdfe6dba..86aa1921c89e 100644 --- a/sound/soc/s6000/s6000-i2s.h +++ b/sound/soc/s6000/s6000-i2s.h | |||
@@ -12,8 +12,6 @@ | |||
12 | #ifndef _S6000_I2S_H | 12 | #ifndef _S6000_I2S_H |
13 | #define _S6000_I2S_H | 13 | #define _S6000_I2S_H |
14 | 14 | ||
15 | extern struct snd_soc_dai s6000_i2s_dai; | ||
16 | |||
17 | struct s6000_snd_platform_data { | 15 | struct s6000_snd_platform_data { |
18 | int lines_in; | 16 | int lines_in; |
19 | int lines_out; | 17 | int lines_out; |
diff --git a/sound/soc/s6000/s6000-pcm.c b/sound/soc/s6000/s6000-pcm.c index 9c7f7f00cebb..271fd222bf19 100644 --- a/sound/soc/s6000/s6000-pcm.c +++ b/sound/soc/s6000/s6000-pcm.c | |||
@@ -65,7 +65,7 @@ static void s6000_pcm_enqueue_dma(struct snd_pcm_substream *substream) | |||
65 | dma_addr_t dma_pos; | 65 | dma_addr_t dma_pos; |
66 | dma_addr_t src, dst; | 66 | dma_addr_t src, dst; |
67 | 67 | ||
68 | par = snd_soc_dai_get_dma_data(soc_runtime->dai->cpu_dai, substream); | 68 | par = snd_soc_dai_get_dma_data(soc_runtime->cpu_dai, substream); |
69 | 69 | ||
70 | period_size = snd_pcm_lib_period_bytes(substream); | 70 | period_size = snd_pcm_lib_period_bytes(substream); |
71 | dma_offset = prtd->period * period_size; | 71 | dma_offset = prtd->period * period_size; |
@@ -103,23 +103,25 @@ static irqreturn_t s6000_pcm_irq(int irq, void *data) | |||
103 | { | 103 | { |
104 | struct snd_pcm *pcm = data; | 104 | struct snd_pcm *pcm = data; |
105 | struct snd_soc_pcm_runtime *runtime = pcm->private_data; | 105 | struct snd_soc_pcm_runtime *runtime = pcm->private_data; |
106 | struct s6000_pcm_dma_params *params = | ||
107 | snd_soc_dai_get_dma_data(soc_runtime->dai->cpu_dai, substream); | ||
108 | struct s6000_runtime_data *prtd; | 106 | struct s6000_runtime_data *prtd; |
109 | unsigned int has_xrun; | 107 | unsigned int has_xrun; |
110 | int i, ret = IRQ_NONE; | 108 | int i, ret = IRQ_NONE; |
111 | u32 channel[2] = { | ||
112 | [SNDRV_PCM_STREAM_PLAYBACK] = params->dma_out, | ||
113 | [SNDRV_PCM_STREAM_CAPTURE] = params->dma_in | ||
114 | }; | ||
115 | |||
116 | has_xrun = params->check_xrun(runtime->dai->cpu_dai); | ||
117 | 109 | ||
118 | for (i = 0; i < ARRAY_SIZE(channel); ++i) { | 110 | for (i = 0; i < 2; ++i) { |
119 | struct snd_pcm_substream *substream = pcm->streams[i].substream; | 111 | struct snd_pcm_substream *substream = pcm->streams[i].substream; |
112 | struct s6000_pcm_dma_params *params = | ||
113 | snd_soc_dai_get_dma_data(runtime->cpu_dai, substream); | ||
114 | u32 channel; | ||
120 | unsigned int pending; | 115 | unsigned int pending; |
121 | 116 | ||
122 | if (!channel[i]) | 117 | if (substream == SNDRV_PCM_STREAM_PLAYBACK) |
118 | channel = params->dma_out; | ||
119 | else | ||
120 | channel = params->dma_in; | ||
121 | |||
122 | has_xrun = params->check_xrun(runtime->cpu_dai); | ||
123 | |||
124 | if (!channel) | ||
123 | continue; | 125 | continue; |
124 | 126 | ||
125 | if (unlikely(has_xrun & (1 << i)) && | 127 | if (unlikely(has_xrun & (1 << i)) && |
@@ -130,8 +132,8 @@ static irqreturn_t s6000_pcm_irq(int irq, void *data) | |||
130 | ret = IRQ_HANDLED; | 132 | ret = IRQ_HANDLED; |
131 | } | 133 | } |
132 | 134 | ||
133 | pending = s6dmac_int_sources(DMA_MASK_DMAC(channel[i]), | 135 | pending = s6dmac_int_sources(DMA_MASK_DMAC(channel), |
134 | DMA_INDEX_CHNL(channel[i])); | 136 | DMA_INDEX_CHNL(channel)); |
135 | 137 | ||
136 | if (pending & 1) { | 138 | if (pending & 1) { |
137 | ret = IRQ_HANDLED; | 139 | ret = IRQ_HANDLED; |
@@ -139,10 +141,10 @@ static irqreturn_t s6000_pcm_irq(int irq, void *data) | |||
139 | snd_pcm_running(substream))) { | 141 | snd_pcm_running(substream))) { |
140 | snd_pcm_period_elapsed(substream); | 142 | snd_pcm_period_elapsed(substream); |
141 | dev_dbg(pcm->dev, "period elapsed %x %x\n", | 143 | dev_dbg(pcm->dev, "period elapsed %x %x\n", |
142 | s6dmac_cur_src(DMA_MASK_DMAC(channel[i]), | 144 | s6dmac_cur_src(DMA_MASK_DMAC(channel), |
143 | DMA_INDEX_CHNL(channel[i])), | 145 | DMA_INDEX_CHNL(channel)), |
144 | s6dmac_cur_dst(DMA_MASK_DMAC(channel[i]), | 146 | s6dmac_cur_dst(DMA_MASK_DMAC(channel), |
145 | DMA_INDEX_CHNL(channel[i]))); | 147 | DMA_INDEX_CHNL(channel))); |
146 | prtd = substream->runtime->private_data; | 148 | prtd = substream->runtime->private_data; |
147 | spin_lock(&prtd->lock); | 149 | spin_lock(&prtd->lock); |
148 | s6000_pcm_enqueue_dma(substream); | 150 | s6000_pcm_enqueue_dma(substream); |
@@ -154,16 +156,16 @@ static irqreturn_t s6000_pcm_irq(int irq, void *data) | |||
154 | if (pending & (1 << 3)) | 156 | if (pending & (1 << 3)) |
155 | printk(KERN_WARNING | 157 | printk(KERN_WARNING |
156 | "s6000-pcm: DMA %x Underflow\n", | 158 | "s6000-pcm: DMA %x Underflow\n", |
157 | channel[i]); | 159 | channel); |
158 | if (pending & (1 << 4)) | 160 | if (pending & (1 << 4)) |
159 | printk(KERN_WARNING | 161 | printk(KERN_WARNING |
160 | "s6000-pcm: DMA %x Overflow\n", | 162 | "s6000-pcm: DMA %x Overflow\n", |
161 | channel[i]); | 163 | channel); |
162 | if (pending & 0x1e0) | 164 | if (pending & 0x1e0) |
163 | printk(KERN_WARNING | 165 | printk(KERN_WARNING |
164 | "s6000-pcm: DMA %x Master Error " | 166 | "s6000-pcm: DMA %x Master Error " |
165 | "(mask %x)\n", | 167 | "(mask %x)\n", |
166 | channel[i], pending >> 5); | 168 | channel, pending >> 5); |
167 | 169 | ||
168 | } | 170 | } |
169 | } | 171 | } |
@@ -180,7 +182,7 @@ static int s6000_pcm_start(struct snd_pcm_substream *substream) | |||
180 | int srcinc; | 182 | int srcinc; |
181 | u32 dma; | 183 | u32 dma; |
182 | 184 | ||
183 | par = snd_soc_dai_get_dma_data(soc_runtime->dai->cpu_dai, substream); | 185 | par = snd_soc_dai_get_dma_data(soc_runtime->cpu_dai, substream); |
184 | 186 | ||
185 | spin_lock_irqsave(&prtd->lock, flags); | 187 | spin_lock_irqsave(&prtd->lock, flags); |
186 | 188 | ||
@@ -221,7 +223,7 @@ static int s6000_pcm_stop(struct snd_pcm_substream *substream) | |||
221 | unsigned long flags; | 223 | unsigned long flags; |
222 | u32 channel; | 224 | u32 channel; |
223 | 225 | ||
224 | par = snd_soc_dai_get_dma_data(soc_runtime->dai->cpu_dai, substream); | 226 | par = snd_soc_dai_get_dma_data(soc_runtime->cpu_dai, substream); |
225 | 227 | ||
226 | if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) | 228 | if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) |
227 | channel = par->dma_out; | 229 | channel = par->dma_out; |
@@ -246,7 +248,7 @@ static int s6000_pcm_trigger(struct snd_pcm_substream *substream, int cmd) | |||
246 | struct s6000_pcm_dma_params *par; | 248 | struct s6000_pcm_dma_params *par; |
247 | int ret; | 249 | int ret; |
248 | 250 | ||
249 | par = snd_soc_dai_get_dma_data(soc_runtime->dai->cpu_dai, substream); | 251 | par = snd_soc_dai_get_dma_data(soc_runtime->cpu_dai, substream); |
250 | 252 | ||
251 | ret = par->trigger(substream, cmd, 0); | 253 | ret = par->trigger(substream, cmd, 0); |
252 | if (ret < 0) | 254 | if (ret < 0) |
@@ -291,7 +293,7 @@ static snd_pcm_uframes_t s6000_pcm_pointer(struct snd_pcm_substream *substream) | |||
291 | unsigned int offset; | 293 | unsigned int offset; |
292 | dma_addr_t count; | 294 | dma_addr_t count; |
293 | 295 | ||
294 | par = snd_soc_dai_get_dma_data(soc_runtime->dai->cpu_dai, substream); | 296 | par = snd_soc_dai_get_dma_data(soc_runtime->cpu_dai, substream); |
295 | 297 | ||
296 | spin_lock_irqsave(&prtd->lock, flags); | 298 | spin_lock_irqsave(&prtd->lock, flags); |
297 | 299 | ||
@@ -321,7 +323,7 @@ static int s6000_pcm_open(struct snd_pcm_substream *substream) | |||
321 | struct s6000_runtime_data *prtd; | 323 | struct s6000_runtime_data *prtd; |
322 | int ret; | 324 | int ret; |
323 | 325 | ||
324 | par = snd_soc_dai_get_dma_data(soc_runtime->dai->cpu_dai, substream); | 326 | par = snd_soc_dai_get_dma_data(soc_runtime->cpu_dai, substream); |
325 | snd_soc_set_runtime_hwparams(substream, &s6000_pcm_hardware); | 327 | snd_soc_set_runtime_hwparams(substream, &s6000_pcm_hardware); |
326 | 328 | ||
327 | ret = snd_pcm_hw_constraint_step(runtime, 0, | 329 | ret = snd_pcm_hw_constraint_step(runtime, 0, |
@@ -385,7 +387,7 @@ static int s6000_pcm_hw_params(struct snd_pcm_substream *substream, | |||
385 | return ret; | 387 | return ret; |
386 | } | 388 | } |
387 | 389 | ||
388 | par = snd_soc_dai_get_dma_data(soc_runtime->dai->cpu_dai, substream); | 390 | par = snd_soc_dai_get_dma_data(soc_runtime->cpu_dai, substream); |
389 | 391 | ||
390 | if (par->same_rate) { | 392 | if (par->same_rate) { |
391 | spin_lock(&par->lock); | 393 | spin_lock(&par->lock); |
@@ -407,7 +409,7 @@ static int s6000_pcm_hw_free(struct snd_pcm_substream *substream) | |||
407 | { | 409 | { |
408 | struct snd_soc_pcm_runtime *soc_runtime = substream->private_data; | 410 | struct snd_soc_pcm_runtime *soc_runtime = substream->private_data; |
409 | struct s6000_pcm_dma_params *par = | 411 | struct s6000_pcm_dma_params *par = |
410 | snd_soc_dai_get_dma_data(soc_runtime->dai->cpu_dai, substream); | 412 | snd_soc_dai_get_dma_data(soc_runtime->cpu_dai, substream); |
411 | 413 | ||
412 | spin_lock(&par->lock); | 414 | spin_lock(&par->lock); |
413 | par->in_use &= ~(1 << substream->stream); | 415 | par->in_use &= ~(1 << substream->stream); |
@@ -433,7 +435,7 @@ static void s6000_pcm_free(struct snd_pcm *pcm) | |||
433 | { | 435 | { |
434 | struct snd_soc_pcm_runtime *runtime = pcm->private_data; | 436 | struct snd_soc_pcm_runtime *runtime = pcm->private_data; |
435 | struct s6000_pcm_dma_params *params = | 437 | struct s6000_pcm_dma_params *params = |
436 | snd_soc_dai_get_dma_data(soc_runtime->dai->cpu_dai, substream); | 438 | snd_soc_dai_get_dma_data(runtime->cpu_dai, pcm->streams[0].substream); |
437 | 439 | ||
438 | free_irq(params->irq, pcm); | 440 | free_irq(params->irq, pcm); |
439 | snd_pcm_lib_preallocate_free_for_all(pcm); | 441 | snd_pcm_lib_preallocate_free_for_all(pcm); |
@@ -448,7 +450,8 @@ static int s6000_pcm_new(struct snd_card *card, | |||
448 | struct s6000_pcm_dma_params *params; | 450 | struct s6000_pcm_dma_params *params; |
449 | int res; | 451 | int res; |
450 | 452 | ||
451 | params = snd_soc_dai_get_dma_data(soc_runtime->dai->cpu_dai, substream); | 453 | params = snd_soc_dai_get_dma_data(runtime->cpu_dai, |
454 | pcm->streams[0].substream); | ||
452 | 455 | ||
453 | if (!card->dev->dma_mask) | 456 | if (!card->dev->dma_mask) |
454 | card->dev->dma_mask = &s6000_pcm_dmamask; | 457 | card->dev->dma_mask = &s6000_pcm_dmamask; |
@@ -490,25 +493,44 @@ static int s6000_pcm_new(struct snd_card *card, | |||
490 | return 0; | 493 | return 0; |
491 | } | 494 | } |
492 | 495 | ||
493 | struct snd_soc_platform s6000_soc_platform = { | 496 | static struct snd_soc_platform_driver s6000_soc_platform = { |
494 | .name = "s6000-audio", | 497 | .ops = &s6000_pcm_ops, |
495 | .pcm_ops = &s6000_pcm_ops, | ||
496 | .pcm_new = s6000_pcm_new, | 498 | .pcm_new = s6000_pcm_new, |
497 | .pcm_free = s6000_pcm_free, | 499 | .pcm_free = s6000_pcm_free, |
498 | }; | 500 | }; |
499 | EXPORT_SYMBOL_GPL(s6000_soc_platform); | ||
500 | 501 | ||
501 | static int __init s6000_pcm_init(void) | 502 | static int __devinit s6000_soc_platform_probe(struct platform_device *pdev) |
503 | { | ||
504 | return snd_soc_register_platform(&pdev->dev, &s6000_soc_platform); | ||
505 | } | ||
506 | |||
507 | static int __devexit s6000_soc_platform_remove(struct platform_device *pdev) | ||
508 | { | ||
509 | snd_soc_unregister_platform(&pdev->dev); | ||
510 | return 0; | ||
511 | } | ||
512 | |||
513 | static struct platform_driver s6000_pcm_driver = { | ||
514 | .driver = { | ||
515 | .name = "s6000-pcm-audio", | ||
516 | .owner = THIS_MODULE, | ||
517 | }, | ||
518 | |||
519 | .probe = s6000_soc_platform_probe, | ||
520 | .remove = __devexit_p(s6000_soc_platform_remove), | ||
521 | }; | ||
522 | |||
523 | static int __init snd_s6000_pcm_init(void) | ||
502 | { | 524 | { |
503 | return snd_soc_register_platform(&s6000_soc_platform); | 525 | return platform_driver_register(&s6000_pcm_driver); |
504 | } | 526 | } |
505 | module_init(s6000_pcm_init); | 527 | module_init(snd_s6000_pcm_init); |
506 | 528 | ||
507 | static void __exit s6000_pcm_exit(void) | 529 | static void __exit snd_s6000_pcm_exit(void) |
508 | { | 530 | { |
509 | snd_soc_unregister_platform(&s6000_soc_platform); | 531 | platform_driver_unregister(&s6000_pcm_driver); |
510 | } | 532 | } |
511 | module_exit(s6000_pcm_exit); | 533 | module_exit(snd_s6000_pcm_exit); |
512 | 534 | ||
513 | MODULE_AUTHOR("Daniel Gloeckner"); | 535 | MODULE_AUTHOR("Daniel Gloeckner"); |
514 | MODULE_DESCRIPTION("Stretch s6000 family PCM DMA module"); | 536 | MODULE_DESCRIPTION("Stretch s6000 family PCM DMA module"); |
diff --git a/sound/soc/s6000/s6000-pcm.h b/sound/soc/s6000/s6000-pcm.h index 96f23f6f52bf..09d9b883e58b 100644 --- a/sound/soc/s6000/s6000-pcm.h +++ b/sound/soc/s6000/s6000-pcm.h | |||
@@ -30,6 +30,4 @@ struct s6000_pcm_dma_params { | |||
30 | int rate; | 30 | int rate; |
31 | }; | 31 | }; |
32 | 32 | ||
33 | extern struct snd_soc_platform s6000_soc_platform; | ||
34 | |||
35 | #endif | 33 | #endif |
diff --git a/sound/soc/s6000/s6105-ipcam.c b/sound/soc/s6000/s6105-ipcam.c index c1b40ac22c05..96c05e137538 100644 --- a/sound/soc/s6000/s6105-ipcam.c +++ b/sound/soc/s6000/s6105-ipcam.c | |||
@@ -32,8 +32,8 @@ static int s6105_hw_params(struct snd_pcm_substream *substream, | |||
32 | struct snd_pcm_hw_params *params) | 32 | struct snd_pcm_hw_params *params) |
33 | { | 33 | { |
34 | struct snd_soc_pcm_runtime *rtd = substream->private_data; | 34 | struct snd_soc_pcm_runtime *rtd = substream->private_data; |
35 | struct snd_soc_dai *codec_dai = rtd->dai->codec_dai; | 35 | struct snd_soc_dai *codec_dai = rtd->codec_dai; |
36 | struct snd_soc_dai *cpu_dai = rtd->dai->cpu_dai; | 36 | struct snd_soc_dai *cpu_dai = rtd->cpu_dai; |
37 | int ret = 0; | 37 | int ret = 0; |
38 | 38 | ||
39 | /* set codec DAI configuration */ | 39 | /* set codec DAI configuration */ |
@@ -134,8 +134,10 @@ static const struct snd_kcontrol_new audio_out_mux = { | |||
134 | }; | 134 | }; |
135 | 135 | ||
136 | /* Logic for a aic3x as connected on the s6105 ip camera ref design */ | 136 | /* Logic for a aic3x as connected on the s6105 ip camera ref design */ |
137 | static int s6105_aic3x_init(struct snd_soc_codec *codec) | 137 | static int s6105_aic3x_init(struct snd_soc_pcm_runtime *rtd) |
138 | { | 138 | { |
139 | struct snd_soc_codec *codec = rtd->codec; | ||
140 | |||
139 | /* Add s6105 specific widgets */ | 141 | /* Add s6105 specific widgets */ |
140 | snd_soc_dapm_new_controls(codec, aic3x_dapm_widgets, | 142 | snd_soc_dapm_new_controls(codec, aic3x_dapm_widgets, |
141 | ARRAY_SIZE(aic3x_dapm_widgets)); | 143 | ARRAY_SIZE(aic3x_dapm_widgets)); |
@@ -165,7 +167,7 @@ static int s6105_aic3x_init(struct snd_soc_codec *codec) | |||
165 | 167 | ||
166 | snd_soc_dapm_sync(codec); | 168 | snd_soc_dapm_sync(codec); |
167 | 169 | ||
168 | snd_ctl_add(codec->card, snd_ctl_new1(&audio_out_mux, codec)); | 170 | snd_ctl_add(codec->snd_card, snd_ctl_new1(&audio_out_mux, codec)); |
169 | 171 | ||
170 | return 0; | 172 | return 0; |
171 | } | 173 | } |
@@ -174,8 +176,10 @@ static int s6105_aic3x_init(struct snd_soc_codec *codec) | |||
174 | static struct snd_soc_dai_link s6105_dai = { | 176 | static struct snd_soc_dai_link s6105_dai = { |
175 | .name = "TLV320AIC31", | 177 | .name = "TLV320AIC31", |
176 | .stream_name = "AIC31", | 178 | .stream_name = "AIC31", |
177 | .cpu_dai = &s6000_i2s_dai, | 179 | .cpu_dai_name = "s6000-i2s", |
178 | .codec_dai = &aic3x_dai, | 180 | .codec_dai_name = "tlv320aic3x-hifi", |
181 | .platform_name = "s6000-pcm-audio", | ||
182 | .codec_name = "tlv320aic3x-codec.0-001a", | ||
179 | .init = s6105_aic3x_init, | 183 | .init = s6105_aic3x_init, |
180 | .ops = &s6105_ops, | 184 | .ops = &s6105_ops, |
181 | }; | 185 | }; |
@@ -183,22 +187,10 @@ static struct snd_soc_dai_link s6105_dai = { | |||
183 | /* s6105 audio machine driver */ | 187 | /* s6105 audio machine driver */ |
184 | static struct snd_soc_card snd_soc_card_s6105 = { | 188 | static struct snd_soc_card snd_soc_card_s6105 = { |
185 | .name = "Stretch IP Camera", | 189 | .name = "Stretch IP Camera", |
186 | .platform = &s6000_soc_platform, | ||
187 | .dai_link = &s6105_dai, | 190 | .dai_link = &s6105_dai, |
188 | .num_links = 1, | 191 | .num_links = 1, |
189 | }; | 192 | }; |
190 | 193 | ||
191 | /* s6105 audio private data */ | ||
192 | static struct aic3x_setup_data s6105_aic3x_setup = { | ||
193 | }; | ||
194 | |||
195 | /* s6105 audio subsystem */ | ||
196 | static struct snd_soc_device s6105_snd_devdata = { | ||
197 | .card = &snd_soc_card_s6105, | ||
198 | .codec_dev = &soc_codec_dev_aic3x, | ||
199 | .codec_data = &s6105_aic3x_setup, | ||
200 | }; | ||
201 | |||
202 | static struct s6000_snd_platform_data __initdata s6105_snd_data = { | 194 | static struct s6000_snd_platform_data __initdata s6105_snd_data = { |
203 | .wide = 0, | 195 | .wide = 0, |
204 | .channel_in = 0, | 196 | .channel_in = 0, |
@@ -227,8 +219,7 @@ static int __init s6105_init(void) | |||
227 | if (!s6105_snd_device) | 219 | if (!s6105_snd_device) |
228 | return -ENOMEM; | 220 | return -ENOMEM; |
229 | 221 | ||
230 | platform_set_drvdata(s6105_snd_device, &s6105_snd_devdata); | 222 | platform_set_drvdata(s6105_snd_device, &snd_soc_card_s6105); |
231 | s6105_snd_devdata.dev = &s6105_snd_device->dev; | ||
232 | platform_device_add_data(s6105_snd_device, &s6105_snd_data, | 223 | platform_device_add_data(s6105_snd_device, &s6105_snd_data, |
233 | sizeof(s6105_snd_data)); | 224 | sizeof(s6105_snd_data)); |
234 | 225 | ||
diff --git a/sound/soc/sh/dma-sh7760.c b/sound/soc/sh/dma-sh7760.c index 0d8bdf07729c..c326d29992fe 100644 --- a/sound/soc/sh/dma-sh7760.c +++ b/sound/soc/sh/dma-sh7760.c | |||
@@ -137,7 +137,7 @@ static void camelot_rxdma(void *data) | |||
137 | static int camelot_pcm_open(struct snd_pcm_substream *substream) | 137 | static int camelot_pcm_open(struct snd_pcm_substream *substream) |
138 | { | 138 | { |
139 | struct snd_soc_pcm_runtime *rtd = substream->private_data; | 139 | struct snd_soc_pcm_runtime *rtd = substream->private_data; |
140 | struct camelot_pcm *cam = &cam_pcm_data[rtd->dai->cpu_dai->id]; | 140 | struct camelot_pcm *cam = &cam_pcm_data[rtd->cpu_dai->id]; |
141 | int recv = substream->stream == SNDRV_PCM_STREAM_PLAYBACK ? 0:1; | 141 | int recv = substream->stream == SNDRV_PCM_STREAM_PLAYBACK ? 0:1; |
142 | int ret, dmairq; | 142 | int ret, dmairq; |
143 | 143 | ||
@@ -150,7 +150,7 @@ static int camelot_pcm_open(struct snd_pcm_substream *substream) | |||
150 | ret = dmabrg_request_irq(dmairq, camelot_rxdma, cam); | 150 | ret = dmabrg_request_irq(dmairq, camelot_rxdma, cam); |
151 | if (unlikely(ret)) { | 151 | if (unlikely(ret)) { |
152 | pr_debug("audio unit %d irqs already taken!\n", | 152 | pr_debug("audio unit %d irqs already taken!\n", |
153 | rtd->dai->cpu_dai->id); | 153 | rtd->cpu_dai->id); |
154 | return -EBUSY; | 154 | return -EBUSY; |
155 | } | 155 | } |
156 | (void)dmabrg_request_irq(dmairq + 1,camelot_rxdma, cam); | 156 | (void)dmabrg_request_irq(dmairq + 1,camelot_rxdma, cam); |
@@ -159,7 +159,7 @@ static int camelot_pcm_open(struct snd_pcm_substream *substream) | |||
159 | ret = dmabrg_request_irq(dmairq, camelot_txdma, cam); | 159 | ret = dmabrg_request_irq(dmairq, camelot_txdma, cam); |
160 | if (unlikely(ret)) { | 160 | if (unlikely(ret)) { |
161 | pr_debug("audio unit %d irqs already taken!\n", | 161 | pr_debug("audio unit %d irqs already taken!\n", |
162 | rtd->dai->cpu_dai->id); | 162 | rtd->cpu_dai->id); |
163 | return -EBUSY; | 163 | return -EBUSY; |
164 | } | 164 | } |
165 | (void)dmabrg_request_irq(dmairq + 1, camelot_txdma, cam); | 165 | (void)dmabrg_request_irq(dmairq + 1, camelot_txdma, cam); |
@@ -170,7 +170,7 @@ static int camelot_pcm_open(struct snd_pcm_substream *substream) | |||
170 | static int camelot_pcm_close(struct snd_pcm_substream *substream) | 170 | static int camelot_pcm_close(struct snd_pcm_substream *substream) |
171 | { | 171 | { |
172 | struct snd_soc_pcm_runtime *rtd = substream->private_data; | 172 | struct snd_soc_pcm_runtime *rtd = substream->private_data; |
173 | struct camelot_pcm *cam = &cam_pcm_data[rtd->dai->cpu_dai->id]; | 173 | struct camelot_pcm *cam = &cam_pcm_data[rtd->cpu_dai->id]; |
174 | int recv = substream->stream == SNDRV_PCM_STREAM_PLAYBACK ? 0:1; | 174 | int recv = substream->stream == SNDRV_PCM_STREAM_PLAYBACK ? 0:1; |
175 | int dmairq; | 175 | int dmairq; |
176 | 176 | ||
@@ -191,7 +191,7 @@ static int camelot_hw_params(struct snd_pcm_substream *substream, | |||
191 | struct snd_pcm_hw_params *hw_params) | 191 | struct snd_pcm_hw_params *hw_params) |
192 | { | 192 | { |
193 | struct snd_soc_pcm_runtime *rtd = substream->private_data; | 193 | struct snd_soc_pcm_runtime *rtd = substream->private_data; |
194 | struct camelot_pcm *cam = &cam_pcm_data[rtd->dai->cpu_dai->id]; | 194 | struct camelot_pcm *cam = &cam_pcm_data[rtd->cpu_dai->id]; |
195 | int recv = substream->stream == SNDRV_PCM_STREAM_PLAYBACK ? 0:1; | 195 | int recv = substream->stream == SNDRV_PCM_STREAM_PLAYBACK ? 0:1; |
196 | int ret; | 196 | int ret; |
197 | 197 | ||
@@ -219,7 +219,7 @@ static int camelot_prepare(struct snd_pcm_substream *substream) | |||
219 | { | 219 | { |
220 | struct snd_pcm_runtime *runtime = substream->runtime; | 220 | struct snd_pcm_runtime *runtime = substream->runtime; |
221 | struct snd_soc_pcm_runtime *rtd = substream->private_data; | 221 | struct snd_soc_pcm_runtime *rtd = substream->private_data; |
222 | struct camelot_pcm *cam = &cam_pcm_data[rtd->dai->cpu_dai->id]; | 222 | struct camelot_pcm *cam = &cam_pcm_data[rtd->cpu_dai->id]; |
223 | 223 | ||
224 | pr_debug("PCM data: addr 0x%08ulx len %d\n", | 224 | pr_debug("PCM data: addr 0x%08ulx len %d\n", |
225 | (u32)runtime->dma_addr, runtime->dma_bytes); | 225 | (u32)runtime->dma_addr, runtime->dma_bytes); |
@@ -266,7 +266,7 @@ static inline void dmabrg_rec_dma_stop(struct camelot_pcm *cam) | |||
266 | static int camelot_trigger(struct snd_pcm_substream *substream, int cmd) | 266 | static int camelot_trigger(struct snd_pcm_substream *substream, int cmd) |
267 | { | 267 | { |
268 | struct snd_soc_pcm_runtime *rtd = substream->private_data; | 268 | struct snd_soc_pcm_runtime *rtd = substream->private_data; |
269 | struct camelot_pcm *cam = &cam_pcm_data[rtd->dai->cpu_dai->id]; | 269 | struct camelot_pcm *cam = &cam_pcm_data[rtd->cpu_dai->id]; |
270 | int recv = substream->stream == SNDRV_PCM_STREAM_PLAYBACK ? 0:1; | 270 | int recv = substream->stream == SNDRV_PCM_STREAM_PLAYBACK ? 0:1; |
271 | 271 | ||
272 | switch (cmd) { | 272 | switch (cmd) { |
@@ -293,7 +293,7 @@ static snd_pcm_uframes_t camelot_pos(struct snd_pcm_substream *substream) | |||
293 | { | 293 | { |
294 | struct snd_pcm_runtime *runtime = substream->runtime; | 294 | struct snd_pcm_runtime *runtime = substream->runtime; |
295 | struct snd_soc_pcm_runtime *rtd = substream->private_data; | 295 | struct snd_soc_pcm_runtime *rtd = substream->private_data; |
296 | struct camelot_pcm *cam = &cam_pcm_data[rtd->dai->cpu_dai->id]; | 296 | struct camelot_pcm *cam = &cam_pcm_data[rtd->cpu_dai->id]; |
297 | int recv = substream->stream == SNDRV_PCM_STREAM_PLAYBACK ? 0:1; | 297 | int recv = substream->stream == SNDRV_PCM_STREAM_PLAYBACK ? 0:1; |
298 | unsigned long pos; | 298 | unsigned long pos; |
299 | 299 | ||
@@ -342,25 +342,44 @@ static int camelot_pcm_new(struct snd_card *card, | |||
342 | return 0; | 342 | return 0; |
343 | } | 343 | } |
344 | 344 | ||
345 | struct snd_soc_platform sh7760_soc_platform = { | 345 | static struct snd_soc_platform sh7760_soc_platform = { |
346 | .name = "sh7760-pcm", | ||
347 | .pcm_ops = &camelot_pcm_ops, | 346 | .pcm_ops = &camelot_pcm_ops, |
348 | .pcm_new = camelot_pcm_new, | 347 | .pcm_new = camelot_pcm_new, |
349 | .pcm_free = camelot_pcm_free, | 348 | .pcm_free = camelot_pcm_free, |
350 | }; | 349 | }; |
351 | EXPORT_SYMBOL_GPL(sh7760_soc_platform); | ||
352 | 350 | ||
353 | static int __init sh7760_soc_platform_init(void) | 351 | static int __devinit sh7760_soc_platform_probe(struct platform_device *pdev) |
354 | { | 352 | { |
355 | return snd_soc_register_platform(&sh7760_soc_platform); | 353 | return snd_soc_register_platform(&pdev->dev, &sh7760_soc_platform); |
356 | } | 354 | } |
357 | module_init(sh7760_soc_platform_init); | ||
358 | 355 | ||
359 | static void __exit sh7760_soc_platform_exit(void) | 356 | static int __devexit sh7760_soc_platform_remove(struct platform_device *pdev) |
360 | { | 357 | { |
361 | snd_soc_unregister_platform(&sh7760_soc_platform); | 358 | snd_soc_unregister_platform(&pdev->dev); |
359 | return 0; | ||
360 | } | ||
361 | |||
362 | static struct platform_driver sh7760_pcm_driver = { | ||
363 | .driver = { | ||
364 | .name = "sh7760-pcm-audio", | ||
365 | .owner = THIS_MODULE, | ||
366 | }, | ||
367 | |||
368 | .probe = sh7760_soc_platform_probe, | ||
369 | .remove = __devexit_p(sh7760_soc_platform_remove), | ||
370 | }; | ||
371 | |||
372 | static int __init snd_sh7760_pcm_init(void) | ||
373 | { | ||
374 | return platform_driver_register(&sh7760_pcm_driver); | ||
375 | } | ||
376 | module_init(snd_sh7760_pcm_init); | ||
377 | |||
378 | static void __exit snd_sh7760_pcm_exit(void) | ||
379 | { | ||
380 | platform_driver_unregister(&sh7760_pcm_driver); | ||
362 | } | 381 | } |
363 | module_exit(sh7760_soc_platform_exit); | 382 | module_exit(snd_sh7760_pcm_exit); |
364 | 383 | ||
365 | MODULE_LICENSE("GPL"); | 384 | MODULE_LICENSE("GPL"); |
366 | MODULE_DESCRIPTION("SH7760 Audio DMA (DMABRG) driver"); | 385 | MODULE_DESCRIPTION("SH7760 Audio DMA (DMABRG) driver"); |
diff --git a/sound/soc/sh/fsi-ak4642.c b/sound/soc/sh/fsi-ak4642.c index dad575a22622..9e107a9c4010 100644 --- a/sound/soc/sh/fsi-ak4642.c +++ b/sound/soc/sh/fsi-ak4642.c | |||
@@ -11,17 +11,17 @@ | |||
11 | 11 | ||
12 | #include <linux/platform_device.h> | 12 | #include <linux/platform_device.h> |
13 | #include <sound/sh_fsi.h> | 13 | #include <sound/sh_fsi.h> |
14 | #include <../sound/soc/codecs/ak4642.h> | ||
15 | 14 | ||
16 | static int fsi_ak4642_dai_init(struct snd_soc_codec *codec) | 15 | static int fsi_ak4642_dai_init(struct snd_soc_pcm_runtime *rtd) |
17 | { | 16 | { |
17 | struct snd_soc_dai *dai = rtd->codec_dai; | ||
18 | int ret; | 18 | int ret; |
19 | 19 | ||
20 | ret = snd_soc_dai_set_fmt(&ak4642_dai, SND_SOC_DAIFMT_CBM_CFM); | 20 | ret = snd_soc_dai_set_fmt(dai, SND_SOC_DAIFMT_CBM_CFM); |
21 | if (ret < 0) | 21 | if (ret < 0) |
22 | return ret; | 22 | return ret; |
23 | 23 | ||
24 | ret = snd_soc_dai_set_sysclk(&ak4642_dai, 0, 11289600, 0); | 24 | ret = snd_soc_dai_set_sysclk(dai, 0, 11289600, 0); |
25 | 25 | ||
26 | return ret; | 26 | return ret; |
27 | } | 27 | } |
@@ -29,24 +29,20 @@ static int fsi_ak4642_dai_init(struct snd_soc_codec *codec) | |||
29 | static struct snd_soc_dai_link fsi_dai_link = { | 29 | static struct snd_soc_dai_link fsi_dai_link = { |
30 | .name = "AK4642", | 30 | .name = "AK4642", |
31 | .stream_name = "AK4642", | 31 | .stream_name = "AK4642", |
32 | .cpu_dai = &fsi_soc_dai[FSI_PORT_A], | 32 | .cpu_dai_name = "fsia-dai", /* fsi A */ |
33 | .codec_dai = &ak4642_dai, | 33 | .codec_dai_name = "ak4642-hifi", |
34 | .platform_name = "fsi-pcm-audio", | ||
35 | .codec_name = "ak4642-codec.0-0012", | ||
34 | .init = fsi_ak4642_dai_init, | 36 | .init = fsi_ak4642_dai_init, |
35 | .ops = NULL, | 37 | .ops = NULL, |
36 | }; | 38 | }; |
37 | 39 | ||
38 | static struct snd_soc_card fsi_soc_card = { | 40 | static struct snd_soc_card fsi_soc_card = { |
39 | .name = "FSI", | 41 | .name = "FSI", |
40 | .platform = &fsi_soc_platform, | ||
41 | .dai_link = &fsi_dai_link, | 42 | .dai_link = &fsi_dai_link, |
42 | .num_links = 1, | 43 | .num_links = 1, |
43 | }; | 44 | }; |
44 | 45 | ||
45 | static struct snd_soc_device fsi_snd_devdata = { | ||
46 | .card = &fsi_soc_card, | ||
47 | .codec_dev = &soc_codec_dev_ak4642, | ||
48 | }; | ||
49 | |||
50 | static struct platform_device *fsi_snd_device; | 46 | static struct platform_device *fsi_snd_device; |
51 | 47 | ||
52 | static int __init fsi_ak4642_init(void) | 48 | static int __init fsi_ak4642_init(void) |
@@ -57,9 +53,7 @@ static int __init fsi_ak4642_init(void) | |||
57 | if (!fsi_snd_device) | 53 | if (!fsi_snd_device) |
58 | goto out; | 54 | goto out; |
59 | 55 | ||
60 | platform_set_drvdata(fsi_snd_device, | 56 | platform_set_drvdata(fsi_snd_device, &fsi_soc_card); |
61 | &fsi_snd_devdata); | ||
62 | fsi_snd_devdata.dev = &fsi_snd_device->dev; | ||
63 | ret = platform_device_add(fsi_snd_device); | 57 | ret = platform_device_add(fsi_snd_device); |
64 | 58 | ||
65 | if (ret) | 59 | if (ret) |
diff --git a/sound/soc/sh/fsi-da7210.c b/sound/soc/sh/fsi-da7210.c index 121bbb07bb03..4f9298f45215 100644 --- a/sound/soc/sh/fsi-da7210.c +++ b/sound/soc/sh/fsi-da7210.c | |||
@@ -12,11 +12,12 @@ | |||
12 | 12 | ||
13 | #include <linux/platform_device.h> | 13 | #include <linux/platform_device.h> |
14 | #include <sound/sh_fsi.h> | 14 | #include <sound/sh_fsi.h> |
15 | #include "../codecs/da7210.h" | ||
16 | 15 | ||
17 | static int fsi_da7210_init(struct snd_soc_codec *codec) | 16 | static int fsi_da7210_init(struct snd_soc_pcm_runtime *rtd) |
18 | { | 17 | { |
19 | return snd_soc_dai_set_fmt(&da7210_dai, | 18 | struct snd_soc_dai *dai = rtd->codec_dai; |
19 | |||
20 | return snd_soc_dai_set_fmt(dai, | ||
20 | SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_NB_NF | | 21 | SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_NB_NF | |
21 | SND_SOC_DAIFMT_CBM_CFM); | 22 | SND_SOC_DAIFMT_CBM_CFM); |
22 | } | 23 | } |
@@ -24,23 +25,19 @@ static int fsi_da7210_init(struct snd_soc_codec *codec) | |||
24 | static struct snd_soc_dai_link fsi_da7210_dai = { | 25 | static struct snd_soc_dai_link fsi_da7210_dai = { |
25 | .name = "DA7210", | 26 | .name = "DA7210", |
26 | .stream_name = "DA7210", | 27 | .stream_name = "DA7210", |
27 | .cpu_dai = &fsi_soc_dai[FSI_PORT_B], | 28 | .cpu_dai_name = "fsib-dai", /* FSI B */ |
28 | .codec_dai = &da7210_dai, | 29 | .codec_dai_name = "da7210-hifi", |
30 | .platform_name = "fsi-pcm-audio", | ||
31 | .codec_name = "da7210-codec.0-001a", | ||
29 | .init = fsi_da7210_init, | 32 | .init = fsi_da7210_init, |
30 | }; | 33 | }; |
31 | 34 | ||
32 | static struct snd_soc_card fsi_soc_card = { | 35 | static struct snd_soc_card fsi_soc_card = { |
33 | .name = "FSI", | 36 | .name = "FSI", |
34 | .platform = &fsi_soc_platform, | ||
35 | .dai_link = &fsi_da7210_dai, | 37 | .dai_link = &fsi_da7210_dai, |
36 | .num_links = 1, | 38 | .num_links = 1, |
37 | }; | 39 | }; |
38 | 40 | ||
39 | static struct snd_soc_device fsi_da7210_snd_devdata = { | ||
40 | .card = &fsi_soc_card, | ||
41 | .codec_dev = &soc_codec_dev_da7210, | ||
42 | }; | ||
43 | |||
44 | static struct platform_device *fsi_da7210_snd_device; | 41 | static struct platform_device *fsi_da7210_snd_device; |
45 | 42 | ||
46 | static int __init fsi_da7210_sound_init(void) | 43 | static int __init fsi_da7210_sound_init(void) |
@@ -51,8 +48,7 @@ static int __init fsi_da7210_sound_init(void) | |||
51 | if (!fsi_da7210_snd_device) | 48 | if (!fsi_da7210_snd_device) |
52 | return -ENOMEM; | 49 | return -ENOMEM; |
53 | 50 | ||
54 | platform_set_drvdata(fsi_da7210_snd_device, &fsi_da7210_snd_devdata); | 51 | platform_set_drvdata(fsi_da7210_snd_device, &fsi_soc_card); |
55 | fsi_da7210_snd_devdata.dev = &fsi_da7210_snd_device->dev; | ||
56 | ret = platform_device_add(fsi_da7210_snd_device); | 52 | ret = platform_device_add(fsi_da7210_snd_device); |
57 | if (ret) | 53 | if (ret) |
58 | platform_device_put(fsi_da7210_snd_device); | 54 | platform_device_put(fsi_da7210_snd_device); |
diff --git a/sound/soc/sh/fsi.c b/sound/soc/sh/fsi.c index 58c6bec642de..abc6d8309609 100644 --- a/sound/soc/sh/fsi.c +++ b/sound/soc/sh/fsi.c | |||
@@ -271,16 +271,19 @@ static int fsi_is_port_a(struct fsi_priv *fsi) | |||
271 | static struct snd_soc_dai *fsi_get_dai(struct snd_pcm_substream *substream) | 271 | static struct snd_soc_dai *fsi_get_dai(struct snd_pcm_substream *substream) |
272 | { | 272 | { |
273 | struct snd_soc_pcm_runtime *rtd = substream->private_data; | 273 | struct snd_soc_pcm_runtime *rtd = substream->private_data; |
274 | struct snd_soc_dai_link *machine = rtd->dai; | ||
275 | 274 | ||
276 | return machine->cpu_dai; | 275 | return rtd->cpu_dai; |
277 | } | 276 | } |
278 | 277 | ||
279 | static struct fsi_priv *fsi_get_priv(struct snd_pcm_substream *substream) | 278 | static struct fsi_priv *fsi_get_priv(struct snd_pcm_substream *substream) |
280 | { | 279 | { |
281 | struct snd_soc_dai *dai = fsi_get_dai(substream); | 280 | struct snd_soc_dai *dai = fsi_get_dai(substream); |
281 | struct fsi_master *master = snd_soc_dai_get_drvdata(dai); | ||
282 | 282 | ||
283 | return dai->private_data; | 283 | if (dai->id == 0) |
284 | return &master->fsia; | ||
285 | else | ||
286 | return &master->fsib; | ||
284 | } | 287 | } |
285 | 288 | ||
286 | static u32 fsi_get_info_flags(struct fsi_priv *fsi) | 289 | static u32 fsi_get_info_flags(struct fsi_priv *fsi) |
@@ -1025,10 +1028,9 @@ static int fsi_pcm_new(struct snd_card *card, | |||
1025 | 1028 | ||
1026 | 1029 | ||
1027 | ************************************************************************/ | 1030 | ************************************************************************/ |
1028 | struct snd_soc_dai fsi_soc_dai[] = { | 1031 | static struct snd_soc_dai_driver fsi_soc_dai[] = { |
1029 | { | 1032 | { |
1030 | .name = "FSIA", | 1033 | .name = "fsia-dai", |
1031 | .id = 0, | ||
1032 | .playback = { | 1034 | .playback = { |
1033 | .rates = FSI_RATES, | 1035 | .rates = FSI_RATES, |
1034 | .formats = FSI_FMTS, | 1036 | .formats = FSI_FMTS, |
@@ -1044,8 +1046,7 @@ struct snd_soc_dai fsi_soc_dai[] = { | |||
1044 | .ops = &fsi_dai_ops, | 1046 | .ops = &fsi_dai_ops, |
1045 | }, | 1047 | }, |
1046 | { | 1048 | { |
1047 | .name = "FSIB", | 1049 | .name = "fsib-dai", |
1048 | .id = 1, | ||
1049 | .playback = { | 1050 | .playback = { |
1050 | .rates = FSI_RATES, | 1051 | .rates = FSI_RATES, |
1051 | .formats = FSI_FMTS, | 1052 | .formats = FSI_FMTS, |
@@ -1061,15 +1062,12 @@ struct snd_soc_dai fsi_soc_dai[] = { | |||
1061 | .ops = &fsi_dai_ops, | 1062 | .ops = &fsi_dai_ops, |
1062 | }, | 1063 | }, |
1063 | }; | 1064 | }; |
1064 | EXPORT_SYMBOL_GPL(fsi_soc_dai); | ||
1065 | 1065 | ||
1066 | struct snd_soc_platform fsi_soc_platform = { | 1066 | static struct snd_soc_platform_driver fsi_soc_platform = { |
1067 | .name = "fsi-pcm", | 1067 | .ops = &fsi_pcm_ops, |
1068 | .pcm_ops = &fsi_pcm_ops, | ||
1069 | .pcm_new = fsi_pcm_new, | 1068 | .pcm_new = fsi_pcm_new, |
1070 | .pcm_free = fsi_pcm_free, | 1069 | .pcm_free = fsi_pcm_free, |
1071 | }; | 1070 | }; |
1072 | EXPORT_SYMBOL_GPL(fsi_soc_platform); | ||
1073 | 1071 | ||
1074 | /************************************************************************ | 1072 | /************************************************************************ |
1075 | 1073 | ||
@@ -1132,11 +1130,7 @@ static int fsi_probe(struct platform_device *pdev) | |||
1132 | 1130 | ||
1133 | pm_runtime_enable(&pdev->dev); | 1131 | pm_runtime_enable(&pdev->dev); |
1134 | pm_runtime_resume(&pdev->dev); | 1132 | pm_runtime_resume(&pdev->dev); |
1135 | 1133 | dev_set_drvdata(&pdev->dev, master); | |
1136 | fsi_soc_dai[0].dev = &pdev->dev; | ||
1137 | fsi_soc_dai[0].private_data = &master->fsia; | ||
1138 | fsi_soc_dai[1].dev = &pdev->dev; | ||
1139 | fsi_soc_dai[1].private_data = &master->fsib; | ||
1140 | 1134 | ||
1141 | fsi_soft_all_reset(master); | 1135 | fsi_soft_all_reset(master); |
1142 | 1136 | ||
@@ -1147,13 +1141,13 @@ static int fsi_probe(struct platform_device *pdev) | |||
1147 | goto exit_iounmap; | 1141 | goto exit_iounmap; |
1148 | } | 1142 | } |
1149 | 1143 | ||
1150 | ret = snd_soc_register_platform(&fsi_soc_platform); | 1144 | ret = snd_soc_register_platform(&pdev->dev, &fsi_soc_platform); |
1151 | if (ret < 0) { | 1145 | if (ret < 0) { |
1152 | dev_err(&pdev->dev, "cannot snd soc register\n"); | 1146 | dev_err(&pdev->dev, "cannot snd soc register\n"); |
1153 | goto exit_free_irq; | 1147 | goto exit_free_irq; |
1154 | } | 1148 | } |
1155 | 1149 | ||
1156 | return snd_soc_register_dais(fsi_soc_dai, ARRAY_SIZE(fsi_soc_dai)); | 1150 | return snd_soc_register_dais(&pdev->dev, fsi_soc_dai, ARRAY_SIZE(fsi_soc_dai)); |
1157 | 1151 | ||
1158 | exit_free_irq: | 1152 | exit_free_irq: |
1159 | free_irq(irq, master); | 1153 | free_irq(irq, master); |
@@ -1171,10 +1165,10 @@ static int fsi_remove(struct platform_device *pdev) | |||
1171 | { | 1165 | { |
1172 | struct fsi_master *master; | 1166 | struct fsi_master *master; |
1173 | 1167 | ||
1174 | master = fsi_get_master(fsi_soc_dai[0].private_data); | 1168 | master = dev_get_drvdata(&pdev->dev); |
1175 | 1169 | ||
1176 | snd_soc_unregister_dais(fsi_soc_dai, ARRAY_SIZE(fsi_soc_dai)); | 1170 | snd_soc_unregister_dais(&pdev->dev, ARRAY_SIZE(fsi_soc_dai)); |
1177 | snd_soc_unregister_platform(&fsi_soc_platform); | 1171 | snd_soc_unregister_platform(&pdev->dev); |
1178 | 1172 | ||
1179 | pm_runtime_disable(&pdev->dev); | 1173 | pm_runtime_disable(&pdev->dev); |
1180 | 1174 | ||
@@ -1183,11 +1177,6 @@ static int fsi_remove(struct platform_device *pdev) | |||
1183 | iounmap(master->base); | 1177 | iounmap(master->base); |
1184 | kfree(master); | 1178 | kfree(master); |
1185 | 1179 | ||
1186 | fsi_soc_dai[0].dev = NULL; | ||
1187 | fsi_soc_dai[0].private_data = NULL; | ||
1188 | fsi_soc_dai[1].dev = NULL; | ||
1189 | fsi_soc_dai[1].private_data = NULL; | ||
1190 | |||
1191 | return 0; | 1180 | return 0; |
1192 | } | 1181 | } |
1193 | 1182 | ||
@@ -1233,7 +1222,7 @@ static struct platform_device_id fsi_id_table[] = { | |||
1233 | 1222 | ||
1234 | static struct platform_driver fsi_driver = { | 1223 | static struct platform_driver fsi_driver = { |
1235 | .driver = { | 1224 | .driver = { |
1236 | .name = "sh_fsi", | 1225 | .name = "fsi-pcm-audio", |
1237 | .pm = &fsi_pm_ops, | 1226 | .pm = &fsi_pm_ops, |
1238 | }, | 1227 | }, |
1239 | .probe = fsi_probe, | 1228 | .probe = fsi_probe, |
diff --git a/sound/soc/sh/hac.c b/sound/soc/sh/hac.c index 41db75af3c69..c87e3ff28a0a 100644 --- a/sound/soc/sh/hac.c +++ b/sound/soc/sh/hac.c | |||
@@ -239,8 +239,7 @@ static int hac_hw_params(struct snd_pcm_substream *substream, | |||
239 | struct snd_pcm_hw_params *params, | 239 | struct snd_pcm_hw_params *params, |
240 | struct snd_soc_dai *dai) | 240 | struct snd_soc_dai *dai) |
241 | { | 241 | { |
242 | struct snd_soc_pcm_runtime *rtd = substream->private_data; | 242 | struct hac_priv *hac = &hac_cpu_data[dai->id]; |
243 | struct hac_priv *hac = &hac_cpu_data[rtd->dai->cpu_dai->id]; | ||
244 | int d = substream->stream == SNDRV_PCM_STREAM_PLAYBACK ? 0 : 1; | 243 | int d = substream->stream == SNDRV_PCM_STREAM_PLAYBACK ? 0 : 1; |
245 | 244 | ||
246 | switch (params->msbits) { | 245 | switch (params->msbits) { |
@@ -271,10 +270,9 @@ static struct snd_soc_dai_ops hac_dai_ops = { | |||
271 | .hw_params = hac_hw_params, | 270 | .hw_params = hac_hw_params, |
272 | }; | 271 | }; |
273 | 272 | ||
274 | struct snd_soc_dai sh4_hac_dai[] = { | 273 | static struct snd_soc_dai_driver sh4_hac_dai[] = { |
275 | { | 274 | { |
276 | .name = "HAC0", | 275 | .name = "hac-dai.0", |
277 | .id = 0, | ||
278 | .ac97_control = 1, | 276 | .ac97_control = 1, |
279 | .playback = { | 277 | .playback = { |
280 | .rates = AC97_RATES, | 278 | .rates = AC97_RATES, |
@@ -292,8 +290,7 @@ struct snd_soc_dai sh4_hac_dai[] = { | |||
292 | }, | 290 | }, |
293 | #ifdef CONFIG_CPU_SUBTYPE_SH7760 | 291 | #ifdef CONFIG_CPU_SUBTYPE_SH7760 |
294 | { | 292 | { |
295 | .name = "HAC1", | 293 | .name = "hac-dai.1", |
296 | .ac97_control = 1, | ||
297 | .id = 1, | 294 | .id = 1, |
298 | .playback = { | 295 | .playback = { |
299 | .rates = AC97_RATES, | 296 | .rates = AC97_RATES, |
@@ -312,19 +309,40 @@ struct snd_soc_dai sh4_hac_dai[] = { | |||
312 | }, | 309 | }, |
313 | #endif | 310 | #endif |
314 | }; | 311 | }; |
315 | EXPORT_SYMBOL_GPL(sh4_hac_dai); | ||
316 | 312 | ||
317 | static int __init sh4_hac_init(void) | 313 | static int __devinit hac_soc_platform_probe(struct platform_device *pdev) |
314 | { | ||
315 | return snd_soc_register_dais(&pdev->dev, sh4_hac_dai, | ||
316 | ARRAY_SIZE(sh4_hac_dai)); | ||
317 | } | ||
318 | |||
319 | static int __devexit hac_soc_platform_remove(struct platform_device *pdev) | ||
320 | { | ||
321 | snd_soc_unregister_dais(&pdev->dev, ARRAY_SIZE(sh4_hac_dai)); | ||
322 | return 0; | ||
323 | } | ||
324 | |||
325 | static struct platform_driver hac_pcm_driver = { | ||
326 | .driver = { | ||
327 | .name = "hac-pcm-audio", | ||
328 | .owner = THIS_MODULE, | ||
329 | }, | ||
330 | |||
331 | .probe = hac_soc_platform_probe, | ||
332 | .remove = __devexit_p(hac_soc_platform_remove), | ||
333 | }; | ||
334 | |||
335 | static int __init sh4_hac_pcm_init(void) | ||
318 | { | 336 | { |
319 | return snd_soc_register_dais(sh4_hac_dai, ARRAY_SIZE(sh4_hac_dai)); | 337 | return platform_driver_register(&hac_pcm_driver); |
320 | } | 338 | } |
321 | module_init(sh4_hac_init); | 339 | module_init(sh4_hac_pcm_init); |
322 | 340 | ||
323 | static void __exit sh4_hac_exit(void) | 341 | static void __exit sh4_hac_pcm_exit(void) |
324 | { | 342 | { |
325 | snd_soc_unregister_dais(sh4_hac_dai, ARRAY_SIZE(sh4_hac_dai)); | 343 | platform_driver_unregister(&hac_pcm_driver); |
326 | } | 344 | } |
327 | module_exit(sh4_hac_exit); | 345 | module_exit(sh4_hac_pcm_exit); |
328 | 346 | ||
329 | MODULE_LICENSE("GPL"); | 347 | MODULE_LICENSE("GPL"); |
330 | MODULE_DESCRIPTION("SuperH onchip HAC (AC97) audio driver"); | 348 | MODULE_DESCRIPTION("SuperH onchip HAC (AC97) audio driver"); |
diff --git a/sound/soc/sh/migor.c b/sound/soc/sh/migor.c index b823a5c9b9bc..866d78fb8398 100644 --- a/sound/soc/sh/migor.c +++ b/sound/soc/sh/migor.c | |||
@@ -50,7 +50,7 @@ static int migor_hw_params(struct snd_pcm_substream *substream, | |||
50 | struct snd_pcm_hw_params *params) | 50 | struct snd_pcm_hw_params *params) |
51 | { | 51 | { |
52 | struct snd_soc_pcm_runtime *rtd = substream->private_data; | 52 | struct snd_soc_pcm_runtime *rtd = substream->private_data; |
53 | struct snd_soc_dai *codec_dai = rtd->dai->codec_dai; | 53 | struct snd_soc_dai *codec_dai = rtd->codec_dai; |
54 | int ret; | 54 | int ret; |
55 | unsigned int rate = params_rate(params); | 55 | unsigned int rate = params_rate(params); |
56 | 56 | ||
@@ -68,7 +68,7 @@ static int migor_hw_params(struct snd_pcm_substream *substream, | |||
68 | if (ret < 0) | 68 | if (ret < 0) |
69 | return ret; | 69 | return ret; |
70 | 70 | ||
71 | ret = snd_soc_dai_set_fmt(rtd->dai->cpu_dai, SND_SOC_DAIFMT_NB_IF | | 71 | ret = snd_soc_dai_set_fmt(rtd->cpu_dai, SND_SOC_DAIFMT_NB_IF | |
72 | SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_CBS_CFS); | 72 | SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_CBS_CFS); |
73 | if (ret < 0) | 73 | if (ret < 0) |
74 | return ret; | 74 | return ret; |
@@ -81,7 +81,7 @@ static int migor_hw_params(struct snd_pcm_substream *substream, | |||
81 | clk_set_rate(&siumckb_clk, codec_freq); | 81 | clk_set_rate(&siumckb_clk, codec_freq); |
82 | dev_dbg(codec_dai->dev, "%s: configure %luHz\n", __func__, codec_freq); | 82 | dev_dbg(codec_dai->dev, "%s: configure %luHz\n", __func__, codec_freq); |
83 | 83 | ||
84 | ret = snd_soc_dai_set_sysclk(rtd->dai->cpu_dai, SIU_CLKB_EXT, | 84 | ret = snd_soc_dai_set_sysclk(rtd->cpu_dai, SIU_CLKB_EXT, |
85 | codec_freq / 2, SND_SOC_CLOCK_IN); | 85 | codec_freq / 2, SND_SOC_CLOCK_IN); |
86 | 86 | ||
87 | if (!ret) | 87 | if (!ret) |
@@ -93,7 +93,7 @@ static int migor_hw_params(struct snd_pcm_substream *substream, | |||
93 | static int migor_hw_free(struct snd_pcm_substream *substream) | 93 | static int migor_hw_free(struct snd_pcm_substream *substream) |
94 | { | 94 | { |
95 | struct snd_soc_pcm_runtime *rtd = substream->private_data; | 95 | struct snd_soc_pcm_runtime *rtd = substream->private_data; |
96 | struct snd_soc_dai *codec_dai = rtd->dai->codec_dai; | 96 | struct snd_soc_dai *codec_dai = rtd->codec_dai; |
97 | 97 | ||
98 | if (use_count) { | 98 | if (use_count) { |
99 | use_count--; | 99 | use_count--; |
@@ -136,8 +136,10 @@ static const struct snd_soc_dapm_route audio_map[] = { | |||
136 | { "Mic Bias", NULL, "External Microphone" }, | 136 | { "Mic Bias", NULL, "External Microphone" }, |
137 | }; | 137 | }; |
138 | 138 | ||
139 | static int migor_dai_init(struct snd_soc_codec *codec) | 139 | static int migor_dai_init(struct snd_soc_pcm_runtime *rtd) |
140 | { | 140 | { |
141 | struct snd_soc_codec *codec = rtd->codec; | ||
142 | |||
141 | snd_soc_dapm_new_controls(codec, migor_dapm_widgets, | 143 | snd_soc_dapm_new_controls(codec, migor_dapm_widgets, |
142 | ARRAY_SIZE(migor_dapm_widgets)); | 144 | ARRAY_SIZE(migor_dapm_widgets)); |
143 | 145 | ||
@@ -150,8 +152,10 @@ static int migor_dai_init(struct snd_soc_codec *codec) | |||
150 | static struct snd_soc_dai_link migor_dai = { | 152 | static struct snd_soc_dai_link migor_dai = { |
151 | .name = "wm8978", | 153 | .name = "wm8978", |
152 | .stream_name = "WM8978", | 154 | .stream_name = "WM8978", |
153 | .cpu_dai = &siu_i2s_dai, | 155 | .cpu_dai_name = "siu-i2s-dai", |
154 | .codec_dai = &wm8978_dai, | 156 | .codec_dai_name = "wm8978-hifi", |
157 | .platform_name = "siu-pcm-audio", | ||
158 | .codec_name = "wm8978-codec.0-001a", | ||
155 | .ops = &migor_dai_ops, | 159 | .ops = &migor_dai_ops, |
156 | .init = migor_dai_init, | 160 | .init = migor_dai_init, |
157 | }; | 161 | }; |
@@ -159,17 +163,10 @@ static struct snd_soc_dai_link migor_dai = { | |||
159 | /* migor audio machine driver */ | 163 | /* migor audio machine driver */ |
160 | static struct snd_soc_card snd_soc_migor = { | 164 | static struct snd_soc_card snd_soc_migor = { |
161 | .name = "Migo-R", | 165 | .name = "Migo-R", |
162 | .platform = &siu_platform, | ||
163 | .dai_link = &migor_dai, | 166 | .dai_link = &migor_dai, |
164 | .num_links = 1, | 167 | .num_links = 1, |
165 | }; | 168 | }; |
166 | 169 | ||
167 | /* migor audio subsystem */ | ||
168 | static struct snd_soc_device migor_snd_devdata = { | ||
169 | .card = &snd_soc_migor, | ||
170 | .codec_dev = &soc_codec_dev_wm8978, | ||
171 | }; | ||
172 | |||
173 | static struct platform_device *migor_snd_device; | 170 | static struct platform_device *migor_snd_device; |
174 | 171 | ||
175 | static int __init migor_init(void) | 172 | static int __init migor_init(void) |
@@ -187,9 +184,7 @@ static int __init migor_init(void) | |||
187 | goto epdevalloc; | 184 | goto epdevalloc; |
188 | } | 185 | } |
189 | 186 | ||
190 | platform_set_drvdata(migor_snd_device, &migor_snd_devdata); | 187 | platform_set_drvdata(migor_snd_device, &snd_soc_migor); |
191 | |||
192 | migor_snd_devdata.dev = &migor_snd_device->dev; | ||
193 | 188 | ||
194 | ret = platform_device_add(migor_snd_device); | 189 | ret = platform_device_add(migor_snd_device); |
195 | if (ret) | 190 | if (ret) |
diff --git a/sound/soc/sh/sh7760-ac97.c b/sound/soc/sh/sh7760-ac97.c index ce7f95b59de3..b897f7b96d89 100644 --- a/sound/soc/sh/sh7760-ac97.c +++ b/sound/soc/sh/sh7760-ac97.c | |||
@@ -15,41 +15,35 @@ | |||
15 | #include <sound/soc-dapm.h> | 15 | #include <sound/soc-dapm.h> |
16 | #include <asm/io.h> | 16 | #include <asm/io.h> |
17 | 17 | ||
18 | #include "../codecs/ac97.h" | ||
19 | |||
20 | #define IPSEL 0xFE400034 | 18 | #define IPSEL 0xFE400034 |
21 | 19 | ||
22 | /* platform specific structs can be declared here */ | 20 | /* platform specific structs can be declared here */ |
23 | extern struct snd_soc_dai sh4_hac_dai[2]; | 21 | extern struct snd_soc_dai_driver sh4_hac_dai[2]; |
24 | extern struct snd_soc_platform sh7760_soc_platform; | 22 | extern struct snd_soc_platform_driver sh7760_soc_platform; |
25 | 23 | ||
26 | static int machine_init(struct snd_soc_codec *codec) | 24 | static int machine_init(struct snd_soc_pcm_runtime *rtd) |
27 | { | 25 | { |
28 | snd_soc_dapm_sync(codec); | 26 | snd_soc_dapm_sync(rtd->codec); |
29 | return 0; | 27 | return 0; |
30 | } | 28 | } |
31 | 29 | ||
32 | static struct snd_soc_dai_link sh7760_ac97_dai = { | 30 | static struct snd_soc_dai_link sh7760_ac97_dai = { |
33 | .name = "AC97", | 31 | .name = "AC97", |
34 | .stream_name = "AC97 HiFi", | 32 | .stream_name = "AC97 HiFi", |
35 | .cpu_dai = &sh4_hac_dai[0], /* HAC0 */ | 33 | .cpu_dai_name = "hac-dai.0", /* HAC0 */ |
36 | .codec_dai = &ac97_dai, | 34 | .codec_dai_name = "ac97-hifi", |
35 | .platform_name = "sh7760-pcm-audio", | ||
36 | .codec_name = "ac97-codec", | ||
37 | .init = machine_init, | 37 | .init = machine_init, |
38 | .ops = NULL, | 38 | .ops = NULL, |
39 | }; | 39 | }; |
40 | 40 | ||
41 | static struct snd_soc_card sh7760_ac97_soc_machine = { | 41 | static struct snd_soc_card sh7760_ac97_soc_machine = { |
42 | .name = "SH7760 AC97", | 42 | .name = "SH7760 AC97", |
43 | .platform = &sh7760_soc_platform, | ||
44 | .dai_link = &sh7760_ac97_dai, | 43 | .dai_link = &sh7760_ac97_dai, |
45 | .num_links = 1, | 44 | .num_links = 1, |
46 | }; | 45 | }; |
47 | 46 | ||
48 | static struct snd_soc_device sh7760_ac97_snd_devdata = { | ||
49 | .card = &sh7760_ac97_soc_machine, | ||
50 | .codec_dev = &soc_codec_dev_ac97, | ||
51 | }; | ||
52 | |||
53 | static struct platform_device *sh7760_ac97_snd_device; | 47 | static struct platform_device *sh7760_ac97_snd_device; |
54 | 48 | ||
55 | static int __init sh7760_ac97_init(void) | 49 | static int __init sh7760_ac97_init(void) |
@@ -67,8 +61,7 @@ static int __init sh7760_ac97_init(void) | |||
67 | goto out; | 61 | goto out; |
68 | 62 | ||
69 | platform_set_drvdata(sh7760_ac97_snd_device, | 63 | platform_set_drvdata(sh7760_ac97_snd_device, |
70 | &sh7760_ac97_snd_devdata); | 64 | &sh7760_ac97_soc_machine); |
71 | sh7760_ac97_snd_devdata.dev = &sh7760_ac97_snd_device->dev; | ||
72 | ret = platform_device_add(sh7760_ac97_snd_device); | 65 | ret = platform_device_add(sh7760_ac97_snd_device); |
73 | 66 | ||
74 | if (ret) | 67 | if (ret) |
diff --git a/sound/soc/sh/siu.h b/sound/soc/sh/siu.h index 492b1cae24cc..aa239ff7310d 100644 --- a/sound/soc/sh/siu.h +++ b/sound/soc/sh/siu.h | |||
@@ -181,8 +181,9 @@ static inline u32 siu_read32(u32 __iomem *addr) | |||
181 | #define SIU_BRGBSEL (0x108 / sizeof(u32)) | 181 | #define SIU_BRGBSEL (0x108 / sizeof(u32)) |
182 | #define SIU_BRRB (0x10c / sizeof(u32)) | 182 | #define SIU_BRRB (0x10c / sizeof(u32)) |
183 | 183 | ||
184 | extern struct snd_soc_platform siu_platform; | 184 | extern struct snd_soc_platform_driver siu_platform; |
185 | extern struct snd_soc_dai siu_i2s_dai; | 185 | extern struct snd_soc_dai_driver siu_i2s_dai; |
186 | extern struct siu_info *siu_i2s_data; | ||
186 | 187 | ||
187 | int siu_init_port(int port, struct siu_port **port_info, struct snd_card *card); | 188 | int siu_init_port(int port, struct siu_port **port_info, struct snd_card *card); |
188 | void siu_free_port(struct siu_port *port_info); | 189 | void siu_free_port(struct siu_port *port_info); |
diff --git a/sound/soc/sh/siu_dai.c b/sound/soc/sh/siu_dai.c index eeed5edd722b..827940a8e248 100644 --- a/sound/soc/sh/siu_dai.c +++ b/sound/soc/sh/siu_dai.c | |||
@@ -71,6 +71,9 @@ struct port_flag { | |||
71 | struct format_flag capture; | 71 | struct format_flag capture; |
72 | }; | 72 | }; |
73 | 73 | ||
74 | struct siu_info *siu_i2s_data = NULL; | ||
75 | EXPORT_SYMBOL_GPL(siu_i2s_data); | ||
76 | |||
74 | static struct port_flag siu_flags[SIU_PORT_NUM] = { | 77 | static struct port_flag siu_flags[SIU_PORT_NUM] = { |
75 | [SIU_PORT_A] = { | 78 | [SIU_PORT_A] = { |
76 | .playback = { | 79 | .playback = { |
@@ -104,13 +107,13 @@ static struct port_flag siu_flags[SIU_PORT_NUM] = { | |||
104 | 107 | ||
105 | static void siu_dai_start(struct siu_port *port_info) | 108 | static void siu_dai_start(struct siu_port *port_info) |
106 | { | 109 | { |
107 | struct siu_info *info = siu_i2s_dai.private_data; | 110 | struct siu_info *info = siu_i2s_data; |
108 | u32 __iomem *base = info->reg; | 111 | u32 __iomem *base = info->reg; |
109 | 112 | ||
110 | dev_dbg(port_info->pcm->card->dev, "%s\n", __func__); | 113 | dev_dbg(port_info->pcm->card->dev, "%s\n", __func__); |
111 | 114 | ||
112 | /* Turn on SIU clock */ | 115 | /* Turn on SIU clock */ |
113 | pm_runtime_get_sync(siu_i2s_dai.dev); | 116 | pm_runtime_get_sync(port_info->pcm->card->dev); |
114 | 117 | ||
115 | /* Issue software reset to siu */ | 118 | /* Issue software reset to siu */ |
116 | siu_write32(base + SIU_SRCTL, 0); | 119 | siu_write32(base + SIU_SRCTL, 0); |
@@ -148,21 +151,21 @@ static void siu_dai_start(struct siu_port *port_info) | |||
148 | siu_write32(base + SIU_SBDVCB, port_info->capture.volume); | 151 | siu_write32(base + SIU_SBDVCB, port_info->capture.volume); |
149 | } | 152 | } |
150 | 153 | ||
151 | static void siu_dai_stop(void) | 154 | static void siu_dai_stop(struct siu_port *port_info) |
152 | { | 155 | { |
153 | struct siu_info *info = siu_i2s_dai.private_data; | 156 | struct siu_info *info = siu_i2s_data; |
154 | u32 __iomem *base = info->reg; | 157 | u32 __iomem *base = info->reg; |
155 | 158 | ||
156 | /* SIU software reset */ | 159 | /* SIU software reset */ |
157 | siu_write32(base + SIU_SRCTL, 0); | 160 | siu_write32(base + SIU_SRCTL, 0); |
158 | 161 | ||
159 | /* Turn off SIU clock */ | 162 | /* Turn off SIU clock */ |
160 | pm_runtime_put_sync(siu_i2s_dai.dev); | 163 | pm_runtime_put_sync(port_info->pcm->card->dev); |
161 | } | 164 | } |
162 | 165 | ||
163 | static void siu_dai_spbAselect(struct siu_port *port_info) | 166 | static void siu_dai_spbAselect(struct siu_port *port_info) |
164 | { | 167 | { |
165 | struct siu_info *info = siu_i2s_dai.private_data; | 168 | struct siu_info *info = siu_i2s_data; |
166 | struct siu_firmware *fw = &info->fw; | 169 | struct siu_firmware *fw = &info->fw; |
167 | u32 *ydef = fw->yram0; | 170 | u32 *ydef = fw->yram0; |
168 | u32 idx; | 171 | u32 idx; |
@@ -187,7 +190,7 @@ static void siu_dai_spbAselect(struct siu_port *port_info) | |||
187 | 190 | ||
188 | static void siu_dai_spbBselect(struct siu_port *port_info) | 191 | static void siu_dai_spbBselect(struct siu_port *port_info) |
189 | { | 192 | { |
190 | struct siu_info *info = siu_i2s_dai.private_data; | 193 | struct siu_info *info = siu_i2s_data; |
191 | struct siu_firmware *fw = &info->fw; | 194 | struct siu_firmware *fw = &info->fw; |
192 | u32 *ydef = fw->yram0; | 195 | u32 *ydef = fw->yram0; |
193 | u32 idx; | 196 | u32 idx; |
@@ -207,7 +210,7 @@ static void siu_dai_spbBselect(struct siu_port *port_info) | |||
207 | 210 | ||
208 | static void siu_dai_open(struct siu_stream *siu_stream) | 211 | static void siu_dai_open(struct siu_stream *siu_stream) |
209 | { | 212 | { |
210 | struct siu_info *info = siu_i2s_dai.private_data; | 213 | struct siu_info *info = siu_i2s_data; |
211 | u32 __iomem *base = info->reg; | 214 | u32 __iomem *base = info->reg; |
212 | u32 srctl, ifctl; | 215 | u32 srctl, ifctl; |
213 | 216 | ||
@@ -238,7 +241,7 @@ static void siu_dai_open(struct siu_stream *siu_stream) | |||
238 | */ | 241 | */ |
239 | static void siu_dai_pcmdatapack(struct siu_stream *siu_stream) | 242 | static void siu_dai_pcmdatapack(struct siu_stream *siu_stream) |
240 | { | 243 | { |
241 | struct siu_info *info = siu_i2s_dai.private_data; | 244 | struct siu_info *info = siu_i2s_data; |
242 | u32 __iomem *base = info->reg; | 245 | u32 __iomem *base = info->reg; |
243 | u32 dpak; | 246 | u32 dpak; |
244 | 247 | ||
@@ -258,7 +261,7 @@ static void siu_dai_pcmdatapack(struct siu_stream *siu_stream) | |||
258 | 261 | ||
259 | static int siu_dai_spbstart(struct siu_port *port_info) | 262 | static int siu_dai_spbstart(struct siu_port *port_info) |
260 | { | 263 | { |
261 | struct siu_info *info = siu_i2s_dai.private_data; | 264 | struct siu_info *info = siu_i2s_data; |
262 | u32 __iomem *base = info->reg; | 265 | u32 __iomem *base = info->reg; |
263 | struct siu_firmware *fw = &info->fw; | 266 | struct siu_firmware *fw = &info->fw; |
264 | u32 *ydef = fw->yram0; | 267 | u32 *ydef = fw->yram0; |
@@ -323,7 +326,7 @@ static int siu_dai_spbstart(struct siu_port *port_info) | |||
323 | 326 | ||
324 | static void siu_dai_spbstop(struct siu_port *port_info) | 327 | static void siu_dai_spbstop(struct siu_port *port_info) |
325 | { | 328 | { |
326 | struct siu_info *info = siu_i2s_dai.private_data; | 329 | struct siu_info *info = siu_i2s_data; |
327 | u32 __iomem *base = info->reg; | 330 | u32 __iomem *base = info->reg; |
328 | 331 | ||
329 | siu_write32(base + SIU_SBACTIV, 0); | 332 | siu_write32(base + SIU_SBACTIV, 0); |
@@ -402,7 +405,7 @@ static int siu_dai_put_volume(struct snd_kcontrol *kctrl, | |||
402 | { | 405 | { |
403 | struct siu_port *port_info = snd_kcontrol_chip(kctrl); | 406 | struct siu_port *port_info = snd_kcontrol_chip(kctrl); |
404 | struct device *dev = port_info->pcm->card->dev; | 407 | struct device *dev = port_info->pcm->card->dev; |
405 | struct siu_info *info = siu_i2s_dai.private_data; | 408 | struct siu_info *info = siu_i2s_data; |
406 | u32 __iomem *base = info->reg; | 409 | u32 __iomem *base = info->reg; |
407 | u32 new_vol; | 410 | u32 new_vol; |
408 | u32 cur_vol; | 411 | u32 cur_vol; |
@@ -510,7 +513,7 @@ void siu_free_port(struct siu_port *port_info) | |||
510 | static int siu_dai_startup(struct snd_pcm_substream *substream, | 513 | static int siu_dai_startup(struct snd_pcm_substream *substream, |
511 | struct snd_soc_dai *dai) | 514 | struct snd_soc_dai *dai) |
512 | { | 515 | { |
513 | struct siu_info *info = siu_i2s_dai.private_data; | 516 | struct siu_info *info = snd_soc_dai_get_drvdata(dai); |
514 | struct snd_pcm_runtime *rt = substream->runtime; | 517 | struct snd_pcm_runtime *rt = substream->runtime; |
515 | struct siu_port *port_info = siu_port_info(substream); | 518 | struct siu_port *port_info = siu_port_info(substream); |
516 | int ret; | 519 | int ret; |
@@ -532,7 +535,7 @@ static int siu_dai_startup(struct snd_pcm_substream *substream, | |||
532 | static void siu_dai_shutdown(struct snd_pcm_substream *substream, | 535 | static void siu_dai_shutdown(struct snd_pcm_substream *substream, |
533 | struct snd_soc_dai *dai) | 536 | struct snd_soc_dai *dai) |
534 | { | 537 | { |
535 | struct siu_info *info = siu_i2s_dai.private_data; | 538 | struct siu_info *info = snd_soc_dai_get_drvdata(dai); |
536 | struct siu_port *port_info = siu_port_info(substream); | 539 | struct siu_port *port_info = siu_port_info(substream); |
537 | 540 | ||
538 | dev_dbg(substream->pcm->card->dev, "%s: port=%d@%p\n", __func__, | 541 | dev_dbg(substream->pcm->card->dev, "%s: port=%d@%p\n", __func__, |
@@ -548,7 +551,7 @@ static void siu_dai_shutdown(struct snd_pcm_substream *substream, | |||
548 | /* during stmread or stmwrite ? */ | 551 | /* during stmread or stmwrite ? */ |
549 | BUG_ON(port_info->playback.rw_flg || port_info->capture.rw_flg); | 552 | BUG_ON(port_info->playback.rw_flg || port_info->capture.rw_flg); |
550 | siu_dai_spbstop(port_info); | 553 | siu_dai_spbstop(port_info); |
551 | siu_dai_stop(); | 554 | siu_dai_stop(port_info); |
552 | } | 555 | } |
553 | } | 556 | } |
554 | 557 | ||
@@ -556,7 +559,7 @@ static void siu_dai_shutdown(struct snd_pcm_substream *substream, | |||
556 | static int siu_dai_prepare(struct snd_pcm_substream *substream, | 559 | static int siu_dai_prepare(struct snd_pcm_substream *substream, |
557 | struct snd_soc_dai *dai) | 560 | struct snd_soc_dai *dai) |
558 | { | 561 | { |
559 | struct siu_info *info = siu_i2s_dai.private_data; | 562 | struct siu_info *info = snd_soc_dai_get_drvdata(dai); |
560 | struct snd_pcm_runtime *rt = substream->runtime; | 563 | struct snd_pcm_runtime *rt = substream->runtime; |
561 | struct siu_port *port_info = siu_port_info(substream); | 564 | struct siu_port *port_info = siu_port_info(substream); |
562 | struct siu_stream *siu_stream; | 565 | struct siu_stream *siu_stream; |
@@ -605,7 +608,7 @@ fail: | |||
605 | static int siu_dai_set_fmt(struct snd_soc_dai *dai, | 608 | static int siu_dai_set_fmt(struct snd_soc_dai *dai, |
606 | unsigned int fmt) | 609 | unsigned int fmt) |
607 | { | 610 | { |
608 | struct siu_info *info = siu_i2s_dai.private_data; | 611 | struct siu_info *info = snd_soc_dai_get_drvdata(dai); |
609 | u32 __iomem *base = info->reg; | 612 | u32 __iomem *base = info->reg; |
610 | u32 ifctl; | 613 | u32 ifctl; |
611 | 614 | ||
@@ -671,11 +674,11 @@ static int siu_dai_set_sysclk(struct snd_soc_dai *dai, int clk_id, | |||
671 | return -EINVAL; | 674 | return -EINVAL; |
672 | } | 675 | } |
673 | 676 | ||
674 | siu_clk = clk_get(siu_i2s_dai.dev, siu_name); | 677 | siu_clk = clk_get(dai->dev, siu_name); |
675 | if (IS_ERR(siu_clk)) | 678 | if (IS_ERR(siu_clk)) |
676 | return PTR_ERR(siu_clk); | 679 | return PTR_ERR(siu_clk); |
677 | 680 | ||
678 | parent_clk = clk_get(siu_i2s_dai.dev, parent_name); | 681 | parent_clk = clk_get(dai->dev, parent_name); |
679 | if (!IS_ERR(parent_clk)) { | 682 | if (!IS_ERR(parent_clk)) { |
680 | ret = clk_set_parent(siu_clk, parent_clk); | 683 | ret = clk_set_parent(siu_clk, parent_clk); |
681 | if (!ret) | 684 | if (!ret) |
@@ -696,9 +699,8 @@ static struct snd_soc_dai_ops siu_dai_ops = { | |||
696 | .set_fmt = siu_dai_set_fmt, | 699 | .set_fmt = siu_dai_set_fmt, |
697 | }; | 700 | }; |
698 | 701 | ||
699 | struct snd_soc_dai siu_i2s_dai = { | 702 | static struct snd_soc_dai_driver siu_i2s_dai = { |
700 | .name = "sh-siu", | 703 | .name = "sui-i2s-dai", |
701 | .id = 0, | ||
702 | .playback = { | 704 | .playback = { |
703 | .channels_min = 2, | 705 | .channels_min = 2, |
704 | .channels_max = 2, | 706 | .channels_max = 2, |
@@ -713,7 +715,6 @@ struct snd_soc_dai siu_i2s_dai = { | |||
713 | }, | 715 | }, |
714 | .ops = &siu_dai_ops, | 716 | .ops = &siu_dai_ops, |
715 | }; | 717 | }; |
716 | EXPORT_SYMBOL_GPL(siu_i2s_dai); | ||
717 | 718 | ||
718 | static int __devinit siu_probe(struct platform_device *pdev) | 719 | static int __devinit siu_probe(struct platform_device *pdev) |
719 | { | 720 | { |
@@ -725,6 +726,7 @@ static int __devinit siu_probe(struct platform_device *pdev) | |||
725 | info = kmalloc(sizeof(*info), GFP_KERNEL); | 726 | info = kmalloc(sizeof(*info), GFP_KERNEL); |
726 | if (!info) | 727 | if (!info) |
727 | return -ENOMEM; | 728 | return -ENOMEM; |
729 | siu_i2s_data = info; | ||
728 | 730 | ||
729 | ret = request_firmware(&fw_entry, "siu_spb.bin", &pdev->dev); | 731 | ret = request_firmware(&fw_entry, "siu_spb.bin", &pdev->dev); |
730 | if (ret) | 732 | if (ret) |
@@ -767,14 +769,14 @@ static int __devinit siu_probe(struct platform_device *pdev) | |||
767 | if (!info->reg) | 769 | if (!info->reg) |
768 | goto emapreg; | 770 | goto emapreg; |
769 | 771 | ||
770 | siu_i2s_dai.dev = &pdev->dev; | 772 | dev_set_drvdata(&pdev->dev, info); |
771 | siu_i2s_dai.private_data = info; | ||
772 | 773 | ||
773 | ret = snd_soc_register_dais(&siu_i2s_dai, 1); | 774 | /* register using ARRAY version so we can keep dai name */ |
775 | ret = snd_soc_register_dais(&pdev->dev, &siu_i2s_dai, 1); | ||
774 | if (ret < 0) | 776 | if (ret < 0) |
775 | goto edaiinit; | 777 | goto edaiinit; |
776 | 778 | ||
777 | ret = snd_soc_register_platform(&siu_platform); | 779 | ret = snd_soc_register_platform(&pdev->dev, &siu_platform); |
778 | if (ret < 0) | 780 | if (ret < 0) |
779 | goto esocregp; | 781 | goto esocregp; |
780 | 782 | ||
@@ -783,7 +785,7 @@ static int __devinit siu_probe(struct platform_device *pdev) | |||
783 | return ret; | 785 | return ret; |
784 | 786 | ||
785 | esocregp: | 787 | esocregp: |
786 | snd_soc_unregister_dais(&siu_i2s_dai, 1); | 788 | snd_soc_unregister_dai(&pdev->dev); |
787 | edaiinit: | 789 | edaiinit: |
788 | iounmap(info->reg); | 790 | iounmap(info->reg); |
789 | emapreg: | 791 | emapreg: |
@@ -804,13 +806,13 @@ ereqfw: | |||
804 | 806 | ||
805 | static int __devexit siu_remove(struct platform_device *pdev) | 807 | static int __devexit siu_remove(struct platform_device *pdev) |
806 | { | 808 | { |
807 | struct siu_info *info = siu_i2s_dai.private_data; | 809 | struct siu_info *info = dev_get_drvdata(&pdev->dev); |
808 | struct resource *res; | 810 | struct resource *res; |
809 | 811 | ||
810 | pm_runtime_disable(&pdev->dev); | 812 | pm_runtime_disable(&pdev->dev); |
811 | 813 | ||
812 | snd_soc_unregister_platform(&siu_platform); | 814 | snd_soc_unregister_platform(&pdev->dev); |
813 | snd_soc_unregister_dais(&siu_i2s_dai, 1); | 815 | snd_soc_unregister_dai(&pdev->dev); |
814 | 816 | ||
815 | iounmap(info->reg); | 817 | iounmap(info->reg); |
816 | iounmap(info->yram); | 818 | iounmap(info->yram); |
@@ -826,7 +828,7 @@ static int __devexit siu_remove(struct platform_device *pdev) | |||
826 | 828 | ||
827 | static struct platform_driver siu_driver = { | 829 | static struct platform_driver siu_driver = { |
828 | .driver = { | 830 | .driver = { |
829 | .name = "sh_siu", | 831 | .name = "siu-pcm-audio", |
830 | }, | 832 | }, |
831 | .probe = siu_probe, | 833 | .probe = siu_probe, |
832 | .remove = __devexit_p(siu_remove), | 834 | .remove = __devexit_p(siu_remove), |
diff --git a/sound/soc/sh/siu_pcm.c b/sound/soc/sh/siu_pcm.c index 36170be15aa7..440476993325 100644 --- a/sound/soc/sh/siu_pcm.c +++ b/sound/soc/sh/siu_pcm.c | |||
@@ -48,7 +48,7 @@ struct siu_port *siu_ports[SIU_PORT_NUM]; | |||
48 | /* transfersize is number of u32 dma transfers per period */ | 48 | /* transfersize is number of u32 dma transfers per period */ |
49 | static int siu_pcm_stmwrite_stop(struct siu_port *port_info) | 49 | static int siu_pcm_stmwrite_stop(struct siu_port *port_info) |
50 | { | 50 | { |
51 | struct siu_info *info = siu_i2s_dai.private_data; | 51 | struct siu_info *info = siu_i2s_data; |
52 | u32 __iomem *base = info->reg; | 52 | u32 __iomem *base = info->reg; |
53 | struct siu_stream *siu_stream = &port_info->playback; | 53 | struct siu_stream *siu_stream = &port_info->playback; |
54 | u32 stfifo; | 54 | u32 stfifo; |
@@ -114,7 +114,7 @@ static void siu_dma_tx_complete(void *arg) | |||
114 | static int siu_pcm_wr_set(struct siu_port *port_info, | 114 | static int siu_pcm_wr_set(struct siu_port *port_info, |
115 | dma_addr_t buff, u32 size) | 115 | dma_addr_t buff, u32 size) |
116 | { | 116 | { |
117 | struct siu_info *info = siu_i2s_dai.private_data; | 117 | struct siu_info *info = siu_i2s_data; |
118 | u32 __iomem *base = info->reg; | 118 | u32 __iomem *base = info->reg; |
119 | struct siu_stream *siu_stream = &port_info->playback; | 119 | struct siu_stream *siu_stream = &port_info->playback; |
120 | struct snd_pcm_substream *substream = siu_stream->substream; | 120 | struct snd_pcm_substream *substream = siu_stream->substream; |
@@ -161,7 +161,7 @@ static int siu_pcm_wr_set(struct siu_port *port_info, | |||
161 | static int siu_pcm_rd_set(struct siu_port *port_info, | 161 | static int siu_pcm_rd_set(struct siu_port *port_info, |
162 | dma_addr_t buff, size_t size) | 162 | dma_addr_t buff, size_t size) |
163 | { | 163 | { |
164 | struct siu_info *info = siu_i2s_dai.private_data; | 164 | struct siu_info *info = siu_i2s_data; |
165 | u32 __iomem *base = info->reg; | 165 | u32 __iomem *base = info->reg; |
166 | struct siu_stream *siu_stream = &port_info->capture; | 166 | struct siu_stream *siu_stream = &port_info->capture; |
167 | struct snd_pcm_substream *substream = siu_stream->substream; | 167 | struct snd_pcm_substream *substream = siu_stream->substream; |
@@ -270,7 +270,7 @@ static int siu_pcm_stmread_start(struct siu_port *port_info) | |||
270 | 270 | ||
271 | static int siu_pcm_stmread_stop(struct siu_port *port_info) | 271 | static int siu_pcm_stmread_stop(struct siu_port *port_info) |
272 | { | 272 | { |
273 | struct siu_info *info = siu_i2s_dai.private_data; | 273 | struct siu_info *info = siu_i2s_data; |
274 | u32 __iomem *base = info->reg; | 274 | u32 __iomem *base = info->reg; |
275 | struct siu_stream *siu_stream = &port_info->capture; | 275 | struct siu_stream *siu_stream = &port_info->capture; |
276 | struct device *dev = siu_stream->substream->pcm->card->dev; | 276 | struct device *dev = siu_stream->substream->pcm->card->dev; |
@@ -294,7 +294,7 @@ static int siu_pcm_stmread_stop(struct siu_port *port_info) | |||
294 | static int siu_pcm_hw_params(struct snd_pcm_substream *ss, | 294 | static int siu_pcm_hw_params(struct snd_pcm_substream *ss, |
295 | struct snd_pcm_hw_params *hw_params) | 295 | struct snd_pcm_hw_params *hw_params) |
296 | { | 296 | { |
297 | struct siu_info *info = siu_i2s_dai.private_data; | 297 | struct siu_info *info = siu_i2s_data; |
298 | struct device *dev = ss->pcm->card->dev; | 298 | struct device *dev = ss->pcm->card->dev; |
299 | int ret; | 299 | int ret; |
300 | 300 | ||
@@ -309,7 +309,7 @@ static int siu_pcm_hw_params(struct snd_pcm_substream *ss, | |||
309 | 309 | ||
310 | static int siu_pcm_hw_free(struct snd_pcm_substream *ss) | 310 | static int siu_pcm_hw_free(struct snd_pcm_substream *ss) |
311 | { | 311 | { |
312 | struct siu_info *info = siu_i2s_dai.private_data; | 312 | struct siu_info *info = siu_i2s_data; |
313 | struct siu_port *port_info = siu_port_info(ss); | 313 | struct siu_port *port_info = siu_port_info(ss); |
314 | struct device *dev = ss->pcm->card->dev; | 314 | struct device *dev = ss->pcm->card->dev; |
315 | struct siu_stream *siu_stream; | 315 | struct siu_stream *siu_stream; |
@@ -340,11 +340,12 @@ static bool filter(struct dma_chan *chan, void *slave) | |||
340 | static int siu_pcm_open(struct snd_pcm_substream *ss) | 340 | static int siu_pcm_open(struct snd_pcm_substream *ss) |
341 | { | 341 | { |
342 | /* Playback / Capture */ | 342 | /* Playback / Capture */ |
343 | struct siu_info *info = siu_i2s_dai.private_data; | 343 | struct snd_soc_pcm_runtime *rtd = ss->private_data; |
344 | struct siu_platform *pdata = snd_soc_platform_get_drvdata(rtd->platform); | ||
345 | struct siu_info *info = siu_i2s_data; | ||
344 | struct siu_port *port_info = siu_port_info(ss); | 346 | struct siu_port *port_info = siu_port_info(ss); |
345 | struct siu_stream *siu_stream; | 347 | struct siu_stream *siu_stream; |
346 | u32 port = info->port_id; | 348 | u32 port = info->port_id; |
347 | struct siu_platform *pdata = siu_i2s_dai.dev->platform_data; | ||
348 | struct device *dev = ss->pcm->card->dev; | 349 | struct device *dev = ss->pcm->card->dev; |
349 | dma_cap_mask_t mask; | 350 | dma_cap_mask_t mask; |
350 | struct sh_dmae_slave *param; | 351 | struct sh_dmae_slave *param; |
@@ -381,7 +382,7 @@ static int siu_pcm_open(struct snd_pcm_substream *ss) | |||
381 | 382 | ||
382 | static int siu_pcm_close(struct snd_pcm_substream *ss) | 383 | static int siu_pcm_close(struct snd_pcm_substream *ss) |
383 | { | 384 | { |
384 | struct siu_info *info = siu_i2s_dai.private_data; | 385 | struct siu_info *info = siu_i2s_data; |
385 | struct device *dev = ss->pcm->card->dev; | 386 | struct device *dev = ss->pcm->card->dev; |
386 | struct siu_port *port_info = siu_port_info(ss); | 387 | struct siu_port *port_info = siu_port_info(ss); |
387 | struct siu_stream *siu_stream; | 388 | struct siu_stream *siu_stream; |
@@ -403,7 +404,7 @@ static int siu_pcm_close(struct snd_pcm_substream *ss) | |||
403 | 404 | ||
404 | static int siu_pcm_prepare(struct snd_pcm_substream *ss) | 405 | static int siu_pcm_prepare(struct snd_pcm_substream *ss) |
405 | { | 406 | { |
406 | struct siu_info *info = siu_i2s_dai.private_data; | 407 | struct siu_info *info = siu_i2s_data; |
407 | struct siu_port *port_info = siu_port_info(ss); | 408 | struct siu_port *port_info = siu_port_info(ss); |
408 | struct device *dev = ss->pcm->card->dev; | 409 | struct device *dev = ss->pcm->card->dev; |
409 | struct snd_pcm_runtime *rt = ss->runtime; | 410 | struct snd_pcm_runtime *rt = ss->runtime; |
@@ -449,7 +450,7 @@ static int siu_pcm_prepare(struct snd_pcm_substream *ss) | |||
449 | 450 | ||
450 | static int siu_pcm_trigger(struct snd_pcm_substream *ss, int cmd) | 451 | static int siu_pcm_trigger(struct snd_pcm_substream *ss, int cmd) |
451 | { | 452 | { |
452 | struct siu_info *info = siu_i2s_dai.private_data; | 453 | struct siu_info *info = siu_i2s_data; |
453 | struct device *dev = ss->pcm->card->dev; | 454 | struct device *dev = ss->pcm->card->dev; |
454 | struct siu_port *port_info = siu_port_info(ss); | 455 | struct siu_port *port_info = siu_port_info(ss); |
455 | int ret; | 456 | int ret; |
@@ -492,7 +493,7 @@ static int siu_pcm_trigger(struct snd_pcm_substream *ss, int cmd) | |||
492 | static snd_pcm_uframes_t siu_pcm_pointer_dma(struct snd_pcm_substream *ss) | 493 | static snd_pcm_uframes_t siu_pcm_pointer_dma(struct snd_pcm_substream *ss) |
493 | { | 494 | { |
494 | struct device *dev = ss->pcm->card->dev; | 495 | struct device *dev = ss->pcm->card->dev; |
495 | struct siu_info *info = siu_i2s_dai.private_data; | 496 | struct siu_info *info = siu_i2s_data; |
496 | u32 __iomem *base = info->reg; | 497 | u32 __iomem *base = info->reg; |
497 | struct siu_port *port_info = siu_port_info(ss); | 498 | struct siu_port *port_info = siu_port_info(ss); |
498 | struct snd_pcm_runtime *rt = ss->runtime; | 499 | struct snd_pcm_runtime *rt = ss->runtime; |
@@ -528,7 +529,7 @@ static int siu_pcm_new(struct snd_card *card, struct snd_soc_dai *dai, | |||
528 | struct snd_pcm *pcm) | 529 | struct snd_pcm *pcm) |
529 | { | 530 | { |
530 | /* card->dev == socdev->dev, see snd_soc_new_pcms() */ | 531 | /* card->dev == socdev->dev, see snd_soc_new_pcms() */ |
531 | struct siu_info *info = siu_i2s_dai.private_data; | 532 | struct siu_info *info = siu_i2s_data; |
532 | struct platform_device *pdev = to_platform_device(card->dev); | 533 | struct platform_device *pdev = to_platform_device(card->dev); |
533 | int ret; | 534 | int ret; |
534 | int i; | 535 | int i; |
@@ -605,9 +606,8 @@ static struct snd_pcm_ops siu_pcm_ops = { | |||
605 | .pointer = siu_pcm_pointer_dma, | 606 | .pointer = siu_pcm_pointer_dma, |
606 | }; | 607 | }; |
607 | 608 | ||
608 | struct snd_soc_platform siu_platform = { | 609 | struct snd_soc_platform_driver siu_platform = { |
609 | .name = "siu-audio", | 610 | .ops = &siu_pcm_ops, |
610 | .pcm_ops = &siu_pcm_ops, | ||
611 | .pcm_new = siu_pcm_new, | 611 | .pcm_new = siu_pcm_new, |
612 | .pcm_free = siu_pcm_free, | 612 | .pcm_free = siu_pcm_free, |
613 | }; | 613 | }; |
diff --git a/sound/soc/sh/ssi.c b/sound/soc/sh/ssi.c index b378096cadb1..40bbdf1591dc 100644 --- a/sound/soc/sh/ssi.c +++ b/sound/soc/sh/ssi.c | |||
@@ -92,8 +92,7 @@ struct ssi_priv { | |||
92 | static int ssi_startup(struct snd_pcm_substream *substream, | 92 | static int ssi_startup(struct snd_pcm_substream *substream, |
93 | struct snd_soc_dai *dai) | 93 | struct snd_soc_dai *dai) |
94 | { | 94 | { |
95 | struct snd_soc_pcm_runtime *rtd = substream->private_data; | 95 | struct ssi_priv *ssi = &ssi_cpu_data[dai->id]; |
96 | struct ssi_priv *ssi = &ssi_cpu_data[rtd->dai->cpu_dai->id]; | ||
97 | if (ssi->inuse) { | 96 | if (ssi->inuse) { |
98 | pr_debug("ssi: already in use!\n"); | 97 | pr_debug("ssi: already in use!\n"); |
99 | return -EBUSY; | 98 | return -EBUSY; |
@@ -105,8 +104,7 @@ static int ssi_startup(struct snd_pcm_substream *substream, | |||
105 | static void ssi_shutdown(struct snd_pcm_substream *substream, | 104 | static void ssi_shutdown(struct snd_pcm_substream *substream, |
106 | struct snd_soc_dai *dai) | 105 | struct snd_soc_dai *dai) |
107 | { | 106 | { |
108 | struct snd_soc_pcm_runtime *rtd = substream->private_data; | 107 | struct ssi_priv *ssi = &ssi_cpu_data[dai->id]; |
109 | struct ssi_priv *ssi = &ssi_cpu_data[rtd->dai->cpu_dai->id]; | ||
110 | 108 | ||
111 | ssi->inuse = 0; | 109 | ssi->inuse = 0; |
112 | } | 110 | } |
@@ -114,8 +112,7 @@ static void ssi_shutdown(struct snd_pcm_substream *substream, | |||
114 | static int ssi_trigger(struct snd_pcm_substream *substream, int cmd, | 112 | static int ssi_trigger(struct snd_pcm_substream *substream, int cmd, |
115 | struct snd_soc_dai *dai) | 113 | struct snd_soc_dai *dai) |
116 | { | 114 | { |
117 | struct snd_soc_pcm_runtime *rtd = substream->private_data; | 115 | struct ssi_priv *ssi = &ssi_cpu_data[dai->id]; |
118 | struct ssi_priv *ssi = &ssi_cpu_data[rtd->dai->cpu_dai->id]; | ||
119 | 116 | ||
120 | switch (cmd) { | 117 | switch (cmd) { |
121 | case SNDRV_PCM_TRIGGER_START: | 118 | case SNDRV_PCM_TRIGGER_START: |
@@ -135,8 +132,7 @@ static int ssi_hw_params(struct snd_pcm_substream *substream, | |||
135 | struct snd_pcm_hw_params *params, | 132 | struct snd_pcm_hw_params *params, |
136 | struct snd_soc_dai *dai) | 133 | struct snd_soc_dai *dai) |
137 | { | 134 | { |
138 | struct snd_soc_pcm_runtime *rtd = substream->private_data; | 135 | struct ssi_priv *ssi = &ssi_cpu_data[dai->id]; |
139 | struct ssi_priv *ssi = &ssi_cpu_data[rtd->dai->cpu_dai->id]; | ||
140 | unsigned long ssicr = SSIREG(SSICR); | 136 | unsigned long ssicr = SSIREG(SSICR); |
141 | unsigned int bits, channels, swl, recv, i; | 137 | unsigned int bits, channels, swl, recv, i; |
142 | 138 | ||
@@ -346,10 +342,9 @@ static struct snd_soc_dai_ops ssi_dai_ops = { | |||
346 | .set_fmt = ssi_set_fmt, | 342 | .set_fmt = ssi_set_fmt, |
347 | }; | 343 | }; |
348 | 344 | ||
349 | struct snd_soc_dai sh4_ssi_dai[] = { | 345 | struct snd_soc_dai_driver sh4_ssi_dai[] = { |
350 | { | 346 | { |
351 | .name = "SSI0", | 347 | .name = "ssi-dai.0", |
352 | .id = 0, | ||
353 | .playback = { | 348 | .playback = { |
354 | .rates = SSI_RATES, | 349 | .rates = SSI_RATES, |
355 | .formats = SSI_FMTS, | 350 | .formats = SSI_FMTS, |
@@ -366,8 +361,7 @@ struct snd_soc_dai sh4_ssi_dai[] = { | |||
366 | }, | 361 | }, |
367 | #ifdef CONFIG_CPU_SUBTYPE_SH7760 | 362 | #ifdef CONFIG_CPU_SUBTYPE_SH7760 |
368 | { | 363 | { |
369 | .name = "SSI1", | 364 | .name = "ssi-dai.1", |
370 | .id = 1, | ||
371 | .playback = { | 365 | .playback = { |
372 | .rates = SSI_RATES, | 366 | .rates = SSI_RATES, |
373 | .formats = SSI_FMTS, | 367 | .formats = SSI_FMTS, |
@@ -384,19 +378,40 @@ struct snd_soc_dai sh4_ssi_dai[] = { | |||
384 | }, | 378 | }, |
385 | #endif | 379 | #endif |
386 | }; | 380 | }; |
387 | EXPORT_SYMBOL_GPL(sh4_ssi_dai); | ||
388 | 381 | ||
389 | static int __init sh4_ssi_init(void) | 382 | static int __devinit sh4_soc_dai_probe(struct platform_device *pdev) |
383 | { | ||
384 | return snd_soc_register_dais(&pdev->dev, sh4_ssi_dai, | ||
385 | ARRAY_SIZE(sh4_ssi_dai)); | ||
386 | } | ||
387 | |||
388 | static int __devexit sh4_soc_dai_remove(struct platform_device *pdev) | ||
389 | { | ||
390 | snd_soc_unregister_dai(&pdev->dev, ARRAY_SIZE(sh4_ssi_dai)); | ||
391 | return 0; | ||
392 | } | ||
393 | |||
394 | static struct platform_driver sh4_ssi_driver = { | ||
395 | .driver = { | ||
396 | .name = "sh4-ssi-dai", | ||
397 | .owner = THIS_MODULE, | ||
398 | }, | ||
399 | |||
400 | .probe = sh4_soc_dai_probe, | ||
401 | .remove = __devexit_p(sh4_soc_dai_remove), | ||
402 | }; | ||
403 | |||
404 | static int __init snd_sh4_ssi_init(void) | ||
390 | { | 405 | { |
391 | return snd_soc_register_dais(sh4_ssi_dai, ARRAY_SIZE(sh4_ssi_dai)); | 406 | return platform_driver_register(&sh4_ssi_driver); |
392 | } | 407 | } |
393 | module_init(sh4_ssi_init); | 408 | module_init(snd_sh4_ssi_init); |
394 | 409 | ||
395 | static void __exit sh4_ssi_exit(void) | 410 | static void __exit snd_sh4_ssi_exit(void) |
396 | { | 411 | { |
397 | snd_soc_unregister_dais(sh4_ssi_dai, ARRAY_SIZE(sh4_ssi_dai)); | 412 | platform_driver_unregister(&sh4_ssi_driver); |
398 | } | 413 | } |
399 | module_exit(sh4_ssi_exit); | 414 | module_exit(snd_sh4_ssi_exit); |
400 | 415 | ||
401 | MODULE_LICENSE("GPL"); | 416 | MODULE_LICENSE("GPL"); |
402 | MODULE_DESCRIPTION("SuperH onchip SSI (I2S) audio driver"); | 417 | MODULE_DESCRIPTION("SuperH onchip SSI (I2S) audio driver"); |
diff --git a/sound/soc/soc-cache.c b/sound/soc/soc-cache.c index 472af38188c1..b856177ea281 100644 --- a/sound/soc/soc-cache.c +++ b/sound/soc/soc-cache.c | |||
@@ -19,7 +19,7 @@ static unsigned int snd_soc_4_12_read(struct snd_soc_codec *codec, | |||
19 | unsigned int reg) | 19 | unsigned int reg) |
20 | { | 20 | { |
21 | u16 *cache = codec->reg_cache; | 21 | u16 *cache = codec->reg_cache; |
22 | if (reg >= codec->reg_cache_size) | 22 | if (reg >= codec->driver->reg_cache_size) |
23 | return -1; | 23 | return -1; |
24 | return cache[reg]; | 24 | return cache[reg]; |
25 | } | 25 | } |
@@ -31,12 +31,12 @@ static int snd_soc_4_12_write(struct snd_soc_codec *codec, unsigned int reg, | |||
31 | u8 data[2]; | 31 | u8 data[2]; |
32 | int ret; | 32 | int ret; |
33 | 33 | ||
34 | BUG_ON(codec->volatile_register); | 34 | BUG_ON(codec->driver->volatile_register); |
35 | 35 | ||
36 | data[0] = (reg << 4) | ((value >> 8) & 0x000f); | 36 | data[0] = (reg << 4) | ((value >> 8) & 0x000f); |
37 | data[1] = value & 0x00ff; | 37 | data[1] = value & 0x00ff; |
38 | 38 | ||
39 | if (reg < codec->reg_cache_size) | 39 | if (reg < codec->driver->reg_cache_size) |
40 | cache[reg] = value; | 40 | cache[reg] = value; |
41 | 41 | ||
42 | if (codec->cache_only) { | 42 | if (codec->cache_only) { |
@@ -89,7 +89,7 @@ static unsigned int snd_soc_7_9_read(struct snd_soc_codec *codec, | |||
89 | unsigned int reg) | 89 | unsigned int reg) |
90 | { | 90 | { |
91 | u16 *cache = codec->reg_cache; | 91 | u16 *cache = codec->reg_cache; |
92 | if (reg >= codec->reg_cache_size) | 92 | if (reg >= codec->driver->reg_cache_size) |
93 | return -1; | 93 | return -1; |
94 | return cache[reg]; | 94 | return cache[reg]; |
95 | } | 95 | } |
@@ -101,12 +101,12 @@ static int snd_soc_7_9_write(struct snd_soc_codec *codec, unsigned int reg, | |||
101 | u8 data[2]; | 101 | u8 data[2]; |
102 | int ret; | 102 | int ret; |
103 | 103 | ||
104 | BUG_ON(codec->volatile_register); | 104 | BUG_ON(codec->driver->volatile_register); |
105 | 105 | ||
106 | data[0] = (reg << 1) | ((value >> 8) & 0x0001); | 106 | data[0] = (reg << 1) | ((value >> 8) & 0x0001); |
107 | data[1] = value & 0x00ff; | 107 | data[1] = value & 0x00ff; |
108 | 108 | ||
109 | if (reg < codec->reg_cache_size) | 109 | if (reg < codec->driver->reg_cache_size) |
110 | cache[reg] = value; | 110 | cache[reg] = value; |
111 | 111 | ||
112 | if (codec->cache_only) { | 112 | if (codec->cache_only) { |
@@ -161,13 +161,13 @@ static int snd_soc_8_8_write(struct snd_soc_codec *codec, unsigned int reg, | |||
161 | u8 *cache = codec->reg_cache; | 161 | u8 *cache = codec->reg_cache; |
162 | u8 data[2]; | 162 | u8 data[2]; |
163 | 163 | ||
164 | BUG_ON(codec->volatile_register); | 164 | BUG_ON(codec->driver->volatile_register); |
165 | 165 | ||
166 | reg &= 0xff; | 166 | reg &= 0xff; |
167 | data[0] = reg; | 167 | data[0] = reg; |
168 | data[1] = value & 0xff; | 168 | data[1] = value & 0xff; |
169 | 169 | ||
170 | if (reg < codec->reg_cache_size) | 170 | if (reg < codec->driver->reg_cache_size) |
171 | cache[reg] = value; | 171 | cache[reg] = value; |
172 | 172 | ||
173 | if (codec->cache_only) { | 173 | if (codec->cache_only) { |
@@ -188,7 +188,7 @@ static unsigned int snd_soc_8_8_read(struct snd_soc_codec *codec, | |||
188 | { | 188 | { |
189 | u8 *cache = codec->reg_cache; | 189 | u8 *cache = codec->reg_cache; |
190 | reg &= 0xff; | 190 | reg &= 0xff; |
191 | if (reg >= codec->reg_cache_size) | 191 | if (reg >= codec->driver->reg_cache_size) |
192 | return -1; | 192 | return -1; |
193 | return cache[reg]; | 193 | return cache[reg]; |
194 | } | 194 | } |
@@ -224,7 +224,7 @@ static unsigned int snd_soc_8_16_read(struct snd_soc_codec *codec, | |||
224 | { | 224 | { |
225 | u16 *cache = codec->reg_cache; | 225 | u16 *cache = codec->reg_cache; |
226 | 226 | ||
227 | if (reg >= codec->reg_cache_size || | 227 | if (reg >= codec->driver->reg_cache_size || |
228 | snd_soc_codec_volatile_register(codec, reg)) { | 228 | snd_soc_codec_volatile_register(codec, reg)) { |
229 | if (codec->cache_only) | 229 | if (codec->cache_only) |
230 | return -EINVAL; | 230 | return -EINVAL; |
@@ -343,7 +343,7 @@ static unsigned int snd_soc_16_8_read(struct snd_soc_codec *codec, | |||
343 | u16 *cache = codec->reg_cache; | 343 | u16 *cache = codec->reg_cache; |
344 | 344 | ||
345 | reg &= 0xff; | 345 | reg &= 0xff; |
346 | if (reg >= codec->reg_cache_size) | 346 | if (reg >= codec->driver->reg_cache_size) |
347 | return -1; | 347 | return -1; |
348 | return cache[reg]; | 348 | return cache[reg]; |
349 | } | 349 | } |
@@ -355,14 +355,14 @@ static int snd_soc_16_8_write(struct snd_soc_codec *codec, unsigned int reg, | |||
355 | u8 data[3]; | 355 | u8 data[3]; |
356 | int ret; | 356 | int ret; |
357 | 357 | ||
358 | BUG_ON(codec->volatile_register); | 358 | BUG_ON(codec->driver->volatile_register); |
359 | 359 | ||
360 | data[0] = (reg >> 8) & 0xff; | 360 | data[0] = (reg >> 8) & 0xff; |
361 | data[1] = reg & 0xff; | 361 | data[1] = reg & 0xff; |
362 | data[2] = value; | 362 | data[2] = value; |
363 | 363 | ||
364 | reg &= 0xff; | 364 | reg &= 0xff; |
365 | if (reg < codec->reg_cache_size) | 365 | if (reg < codec->driver->reg_cache_size) |
366 | cache[reg] = value; | 366 | cache[reg] = value; |
367 | 367 | ||
368 | if (codec->cache_only) { | 368 | if (codec->cache_only) { |
@@ -451,7 +451,7 @@ static unsigned int snd_soc_16_16_read(struct snd_soc_codec *codec, | |||
451 | { | 451 | { |
452 | u16 *cache = codec->reg_cache; | 452 | u16 *cache = codec->reg_cache; |
453 | 453 | ||
454 | if (reg >= codec->reg_cache_size || | 454 | if (reg >= codec->driver->reg_cache_size || |
455 | snd_soc_codec_volatile_register(codec, reg)) { | 455 | snd_soc_codec_volatile_register(codec, reg)) { |
456 | if (codec->cache_only) | 456 | if (codec->cache_only) |
457 | return -EINVAL; | 457 | return -EINVAL; |
@@ -474,7 +474,7 @@ static int snd_soc_16_16_write(struct snd_soc_codec *codec, unsigned int reg, | |||
474 | data[2] = (value >> 8) & 0xff; | 474 | data[2] = (value >> 8) & 0xff; |
475 | data[3] = value & 0xff; | 475 | data[3] = value & 0xff; |
476 | 476 | ||
477 | if (reg < codec->reg_cache_size) | 477 | if (reg < codec->driver->reg_cache_size) |
478 | cache[reg] = value; | 478 | cache[reg] = value; |
479 | 479 | ||
480 | if (codec->cache_only) { | 480 | if (codec->cache_only) { |
@@ -571,8 +571,8 @@ int snd_soc_codec_set_cache_io(struct snd_soc_codec *codec, | |||
571 | return -EINVAL; | 571 | return -EINVAL; |
572 | } | 572 | } |
573 | 573 | ||
574 | codec->write = io_types[i].write; | 574 | codec->driver->write = io_types[i].write; |
575 | codec->read = io_types[i].read; | 575 | codec->driver->read = io_types[i].read; |
576 | 576 | ||
577 | switch (control) { | 577 | switch (control) { |
578 | case SND_SOC_CUSTOM: | 578 | case SND_SOC_CUSTOM: |
@@ -584,11 +584,19 @@ int snd_soc_codec_set_cache_io(struct snd_soc_codec *codec, | |||
584 | #endif | 584 | #endif |
585 | if (io_types[i].i2c_read) | 585 | if (io_types[i].i2c_read) |
586 | codec->hw_read = io_types[i].i2c_read; | 586 | codec->hw_read = io_types[i].i2c_read; |
587 | |||
588 | codec->control_data = container_of(codec->dev, | ||
589 | struct i2c_client, | ||
590 | dev); | ||
587 | break; | 591 | break; |
588 | 592 | ||
589 | case SND_SOC_SPI: | 593 | case SND_SOC_SPI: |
590 | if (io_types[i].spi_write) | 594 | if (io_types[i].spi_write) |
591 | codec->hw_write = io_types[i].spi_write; | 595 | codec->hw_write = io_types[i].spi_write; |
596 | |||
597 | codec->control_data = container_of(codec->dev, | ||
598 | struct spi_device, | ||
599 | dev); | ||
592 | break; | 600 | break; |
593 | } | 601 | } |
594 | 602 | ||
diff --git a/sound/soc/soc-core.c b/sound/soc/soc-core.c index 5299932db0b6..a004876a39a9 100644 --- a/sound/soc/soc-core.c +++ b/sound/soc/soc-core.c | |||
@@ -3,6 +3,8 @@ | |||
3 | * | 3 | * |
4 | * Copyright 2005 Wolfson Microelectronics PLC. | 4 | * Copyright 2005 Wolfson Microelectronics PLC. |
5 | * Copyright 2005 Openedhand Ltd. | 5 | * Copyright 2005 Openedhand Ltd. |
6 | * Copyright (C) 2010 Slimlogic Ltd. | ||
7 | * Copyright (C) 2010 Texas Instruments Inc. | ||
6 | * | 8 | * |
7 | * Author: Liam Girdwood <lrg@slimlogic.co.uk> | 9 | * Author: Liam Girdwood <lrg@slimlogic.co.uk> |
8 | * with code, comments and ideas from :- | 10 | * with code, comments and ideas from :- |
@@ -37,6 +39,8 @@ | |||
37 | #include <sound/soc-dapm.h> | 39 | #include <sound/soc-dapm.h> |
38 | #include <sound/initval.h> | 40 | #include <sound/initval.h> |
39 | 41 | ||
42 | #define NAME_SIZE 32 | ||
43 | |||
40 | static DEFINE_MUTEX(pcm_mutex); | 44 | static DEFINE_MUTEX(pcm_mutex); |
41 | static DECLARE_WAIT_QUEUE_HEAD(soc_pm_waitq); | 45 | static DECLARE_WAIT_QUEUE_HEAD(soc_pm_waitq); |
42 | 46 | ||
@@ -52,6 +56,7 @@ static LIST_HEAD(codec_list); | |||
52 | 56 | ||
53 | static int snd_soc_register_card(struct snd_soc_card *card); | 57 | static int snd_soc_register_card(struct snd_soc_card *card); |
54 | static int snd_soc_unregister_card(struct snd_soc_card *card); | 58 | static int snd_soc_unregister_card(struct snd_soc_card *card); |
59 | static int soc_new_pcm(struct snd_soc_pcm_runtime *rtd, int num); | ||
55 | 60 | ||
56 | /* | 61 | /* |
57 | * This is a timeout to do a DAPM powerdown after a stream is closed(). | 62 | * This is a timeout to do a DAPM powerdown after a stream is closed(). |
@@ -86,30 +91,30 @@ static ssize_t soc_codec_reg_show(struct snd_soc_codec *codec, char *buf) | |||
86 | { | 91 | { |
87 | int ret, i, step = 1, count = 0; | 92 | int ret, i, step = 1, count = 0; |
88 | 93 | ||
89 | if (!codec->reg_cache_size) | 94 | if (!codec->driver->reg_cache_size) |
90 | return 0; | 95 | return 0; |
91 | 96 | ||
92 | if (codec->reg_cache_step) | 97 | if (codec->driver->reg_cache_step) |
93 | step = codec->reg_cache_step; | 98 | step = codec->driver->reg_cache_step; |
94 | 99 | ||
95 | count += sprintf(buf, "%s registers\n", codec->name); | 100 | count += sprintf(buf, "%s registers\n", codec->name); |
96 | for (i = 0; i < codec->reg_cache_size; i += step) { | 101 | for (i = 0; i < codec->driver->reg_cache_size; i += step) { |
97 | if (codec->readable_register && !codec->readable_register(i)) | 102 | if (codec->driver->readable_register && !codec->driver->readable_register(i)) |
98 | continue; | 103 | continue; |
99 | 104 | ||
100 | count += sprintf(buf + count, "%2x: ", i); | 105 | count += sprintf(buf + count, "%2x: ", i); |
101 | if (count >= PAGE_SIZE - 1) | 106 | if (count >= PAGE_SIZE - 1) |
102 | break; | 107 | break; |
103 | 108 | ||
104 | if (codec->display_register) { | 109 | if (codec->driver->display_register) { |
105 | count += codec->display_register(codec, buf + count, | 110 | count += codec->driver->display_register(codec, buf + count, |
106 | PAGE_SIZE - count, i); | 111 | PAGE_SIZE - count, i); |
107 | } else { | 112 | } else { |
108 | /* If the read fails it's almost certainly due to | 113 | /* If the read fails it's almost certainly due to |
109 | * the register being volatile and the device being | 114 | * the register being volatile and the device being |
110 | * powered off. | 115 | * powered off. |
111 | */ | 116 | */ |
112 | ret = codec->read(codec, i); | 117 | ret = codec->driver->read(codec, i); |
113 | if (ret >= 0) | 118 | if (ret >= 0) |
114 | count += snprintf(buf + count, | 119 | count += snprintf(buf + count, |
115 | PAGE_SIZE - count, | 120 | PAGE_SIZE - count, |
@@ -137,8 +142,10 @@ static ssize_t soc_codec_reg_show(struct snd_soc_codec *codec, char *buf) | |||
137 | static ssize_t codec_reg_show(struct device *dev, | 142 | static ssize_t codec_reg_show(struct device *dev, |
138 | struct device_attribute *attr, char *buf) | 143 | struct device_attribute *attr, char *buf) |
139 | { | 144 | { |
140 | struct snd_soc_device *devdata = dev_get_drvdata(dev); | 145 | struct snd_soc_pcm_runtime *rtd = |
141 | return soc_codec_reg_show(devdata->card->codec, buf); | 146 | container_of(dev, struct snd_soc_pcm_runtime, dev); |
147 | |||
148 | return soc_codec_reg_show(rtd->codec, buf); | ||
142 | } | 149 | } |
143 | 150 | ||
144 | static DEVICE_ATTR(codec_reg, 0444, codec_reg_show, NULL); | 151 | static DEVICE_ATTR(codec_reg, 0444, codec_reg_show, NULL); |
@@ -146,20 +153,20 @@ static DEVICE_ATTR(codec_reg, 0444, codec_reg_show, NULL); | |||
146 | static ssize_t pmdown_time_show(struct device *dev, | 153 | static ssize_t pmdown_time_show(struct device *dev, |
147 | struct device_attribute *attr, char *buf) | 154 | struct device_attribute *attr, char *buf) |
148 | { | 155 | { |
149 | struct snd_soc_device *socdev = dev_get_drvdata(dev); | 156 | struct snd_soc_pcm_runtime *rtd = |
150 | struct snd_soc_card *card = socdev->card; | 157 | container_of(dev, struct snd_soc_pcm_runtime, dev); |
151 | 158 | ||
152 | return sprintf(buf, "%ld\n", card->pmdown_time); | 159 | return sprintf(buf, "%ld\n", rtd->pmdown_time); |
153 | } | 160 | } |
154 | 161 | ||
155 | static ssize_t pmdown_time_set(struct device *dev, | 162 | static ssize_t pmdown_time_set(struct device *dev, |
156 | struct device_attribute *attr, | 163 | struct device_attribute *attr, |
157 | const char *buf, size_t count) | 164 | const char *buf, size_t count) |
158 | { | 165 | { |
159 | struct snd_soc_device *socdev = dev_get_drvdata(dev); | 166 | struct snd_soc_pcm_runtime *rtd = |
160 | struct snd_soc_card *card = socdev->card; | 167 | container_of(dev, struct snd_soc_pcm_runtime, dev); |
161 | 168 | ||
162 | strict_strtol(buf, 10, &card->pmdown_time); | 169 | strict_strtol(buf, 10, &rtd->pmdown_time); |
163 | 170 | ||
164 | return count; | 171 | return count; |
165 | } | 172 | } |
@@ -203,19 +210,19 @@ static ssize_t codec_reg_write_file(struct file *file, | |||
203 | return -EFAULT; | 210 | return -EFAULT; |
204 | buf[buf_size] = 0; | 211 | buf[buf_size] = 0; |
205 | 212 | ||
206 | if (codec->reg_cache_step) | 213 | if (codec->driver->reg_cache_step) |
207 | step = codec->reg_cache_step; | 214 | step = codec->driver->reg_cache_step; |
208 | 215 | ||
209 | while (*start == ' ') | 216 | while (*start == ' ') |
210 | start++; | 217 | start++; |
211 | reg = simple_strtoul(start, &start, 16); | 218 | reg = simple_strtoul(start, &start, 16); |
212 | if ((reg >= codec->reg_cache_size) || (reg % step)) | 219 | if ((reg >= codec->driver->reg_cache_size) || (reg % step)) |
213 | return -EINVAL; | 220 | return -EINVAL; |
214 | while (*start == ' ') | 221 | while (*start == ' ') |
215 | start++; | 222 | start++; |
216 | if (strict_strtoul(start, 16, &value)) | 223 | if (strict_strtoul(start, 16, &value)) |
217 | return -EINVAL; | 224 | return -EINVAL; |
218 | codec->write(codec, reg, value); | 225 | codec->driver->write(codec, reg, value); |
219 | return buf_size; | 226 | return buf_size; |
220 | } | 227 | } |
221 | 228 | ||
@@ -305,7 +312,7 @@ static int soc_ac97_dev_register(struct snd_soc_codec *codec) | |||
305 | codec->ac97->dev.release = soc_ac97_device_release; | 312 | codec->ac97->dev.release = soc_ac97_device_release; |
306 | 313 | ||
307 | dev_set_name(&codec->ac97->dev, "%d-%d:%s", | 314 | dev_set_name(&codec->ac97->dev, "%d-%d:%s", |
308 | codec->card->number, 0, codec->name); | 315 | codec->card->snd_card->number, 0, codec->name); |
309 | err = device_register(&codec->ac97->dev); | 316 | err = device_register(&codec->ac97->dev); |
310 | if (err < 0) { | 317 | if (err < 0) { |
311 | snd_printk(KERN_ERR "Can't register ac97 bus\n"); | 318 | snd_printk(KERN_ERR "Can't register ac97 bus\n"); |
@@ -319,24 +326,21 @@ static int soc_ac97_dev_register(struct snd_soc_codec *codec) | |||
319 | static int soc_pcm_apply_symmetry(struct snd_pcm_substream *substream) | 326 | static int soc_pcm_apply_symmetry(struct snd_pcm_substream *substream) |
320 | { | 327 | { |
321 | struct snd_soc_pcm_runtime *rtd = substream->private_data; | 328 | struct snd_soc_pcm_runtime *rtd = substream->private_data; |
322 | struct snd_soc_device *socdev = rtd->socdev; | 329 | struct snd_soc_dai *cpu_dai = rtd->cpu_dai; |
323 | struct snd_soc_card *card = socdev->card; | 330 | struct snd_soc_dai *codec_dai = rtd->codec_dai; |
324 | struct snd_soc_dai_link *machine = rtd->dai; | ||
325 | struct snd_soc_dai *cpu_dai = machine->cpu_dai; | ||
326 | struct snd_soc_dai *codec_dai = machine->codec_dai; | ||
327 | int ret; | 331 | int ret; |
328 | 332 | ||
329 | if (codec_dai->symmetric_rates || cpu_dai->symmetric_rates || | 333 | if (codec_dai->driver->symmetric_rates || cpu_dai->driver->symmetric_rates || |
330 | machine->symmetric_rates) { | 334 | rtd->dai_link->symmetric_rates) { |
331 | dev_dbg(card->dev, "Symmetry forces %dHz rate\n", | 335 | dev_dbg(&rtd->dev, "Symmetry forces %dHz rate\n", |
332 | machine->rate); | 336 | rtd->rate); |
333 | 337 | ||
334 | ret = snd_pcm_hw_constraint_minmax(substream->runtime, | 338 | ret = snd_pcm_hw_constraint_minmax(substream->runtime, |
335 | SNDRV_PCM_HW_PARAM_RATE, | 339 | SNDRV_PCM_HW_PARAM_RATE, |
336 | machine->rate, | 340 | rtd->rate, |
337 | machine->rate); | 341 | rtd->rate); |
338 | if (ret < 0) { | 342 | if (ret < 0) { |
339 | dev_err(card->dev, | 343 | dev_err(&rtd->dev, |
340 | "Unable to apply rate symmetry constraint: %d\n", ret); | 344 | "Unable to apply rate symmetry constraint: %d\n", ret); |
341 | return ret; | 345 | return ret; |
342 | } | 346 | } |
@@ -353,20 +357,19 @@ static int soc_pcm_apply_symmetry(struct snd_pcm_substream *substream) | |||
353 | static int soc_pcm_open(struct snd_pcm_substream *substream) | 357 | static int soc_pcm_open(struct snd_pcm_substream *substream) |
354 | { | 358 | { |
355 | struct snd_soc_pcm_runtime *rtd = substream->private_data; | 359 | struct snd_soc_pcm_runtime *rtd = substream->private_data; |
356 | struct snd_soc_device *socdev = rtd->socdev; | ||
357 | struct snd_soc_card *card = socdev->card; | ||
358 | struct snd_pcm_runtime *runtime = substream->runtime; | 360 | struct snd_pcm_runtime *runtime = substream->runtime; |
359 | struct snd_soc_dai_link *machine = rtd->dai; | 361 | struct snd_soc_platform *platform = rtd->platform; |
360 | struct snd_soc_platform *platform = card->platform; | 362 | struct snd_soc_dai *cpu_dai = rtd->cpu_dai; |
361 | struct snd_soc_dai *cpu_dai = machine->cpu_dai; | 363 | struct snd_soc_dai *codec_dai = rtd->codec_dai; |
362 | struct snd_soc_dai *codec_dai = machine->codec_dai; | 364 | struct snd_soc_dai_driver *cpu_dai_drv = cpu_dai->driver; |
365 | struct snd_soc_dai_driver *codec_dai_drv = codec_dai->driver; | ||
363 | int ret = 0; | 366 | int ret = 0; |
364 | 367 | ||
365 | mutex_lock(&pcm_mutex); | 368 | mutex_lock(&pcm_mutex); |
366 | 369 | ||
367 | /* startup the audio subsystem */ | 370 | /* startup the audio subsystem */ |
368 | if (cpu_dai->ops->startup) { | 371 | if (cpu_dai->driver->ops->startup) { |
369 | ret = cpu_dai->ops->startup(substream, cpu_dai); | 372 | ret = cpu_dai->driver->ops->startup(substream, cpu_dai); |
370 | if (ret < 0) { | 373 | if (ret < 0) { |
371 | printk(KERN_ERR "asoc: can't open interface %s\n", | 374 | printk(KERN_ERR "asoc: can't open interface %s\n", |
372 | cpu_dai->name); | 375 | cpu_dai->name); |
@@ -374,16 +377,16 @@ static int soc_pcm_open(struct snd_pcm_substream *substream) | |||
374 | } | 377 | } |
375 | } | 378 | } |
376 | 379 | ||
377 | if (platform->pcm_ops->open) { | 380 | if (platform->driver->ops->open) { |
378 | ret = platform->pcm_ops->open(substream); | 381 | ret = platform->driver->ops->open(substream); |
379 | if (ret < 0) { | 382 | if (ret < 0) { |
380 | printk(KERN_ERR "asoc: can't open platform %s\n", platform->name); | 383 | printk(KERN_ERR "asoc: can't open platform %s\n", platform->name); |
381 | goto platform_err; | 384 | goto platform_err; |
382 | } | 385 | } |
383 | } | 386 | } |
384 | 387 | ||
385 | if (codec_dai->ops->startup) { | 388 | if (codec_dai->driver->ops->startup) { |
386 | ret = codec_dai->ops->startup(substream, codec_dai); | 389 | ret = codec_dai->driver->ops->startup(substream, codec_dai); |
387 | if (ret < 0) { | 390 | if (ret < 0) { |
388 | printk(KERN_ERR "asoc: can't open codec %s\n", | 391 | printk(KERN_ERR "asoc: can't open codec %s\n", |
389 | codec_dai->name); | 392 | codec_dai->name); |
@@ -391,10 +394,10 @@ static int soc_pcm_open(struct snd_pcm_substream *substream) | |||
391 | } | 394 | } |
392 | } | 395 | } |
393 | 396 | ||
394 | if (machine->ops && machine->ops->startup) { | 397 | if (rtd->dai_link->ops && rtd->dai_link->ops->startup) { |
395 | ret = machine->ops->startup(substream); | 398 | ret = rtd->dai_link->ops->startup(substream); |
396 | if (ret < 0) { | 399 | if (ret < 0) { |
397 | printk(KERN_ERR "asoc: %s startup failed\n", machine->name); | 400 | printk(KERN_ERR "asoc: %s startup failed\n", rtd->dai_link->name); |
398 | goto machine_err; | 401 | goto machine_err; |
399 | } | 402 | } |
400 | } | 403 | } |
@@ -402,50 +405,50 @@ static int soc_pcm_open(struct snd_pcm_substream *substream) | |||
402 | /* Check that the codec and cpu DAI's are compatible */ | 405 | /* Check that the codec and cpu DAI's are compatible */ |
403 | if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) { | 406 | if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) { |
404 | runtime->hw.rate_min = | 407 | runtime->hw.rate_min = |
405 | max(codec_dai->playback.rate_min, | 408 | max(codec_dai_drv->playback.rate_min, |
406 | cpu_dai->playback.rate_min); | 409 | cpu_dai_drv->playback.rate_min); |
407 | runtime->hw.rate_max = | 410 | runtime->hw.rate_max = |
408 | min(codec_dai->playback.rate_max, | 411 | min(codec_dai_drv->playback.rate_max, |
409 | cpu_dai->playback.rate_max); | 412 | cpu_dai_drv->playback.rate_max); |
410 | runtime->hw.channels_min = | 413 | runtime->hw.channels_min = |
411 | max(codec_dai->playback.channels_min, | 414 | max(codec_dai_drv->playback.channels_min, |
412 | cpu_dai->playback.channels_min); | 415 | cpu_dai_drv->playback.channels_min); |
413 | runtime->hw.channels_max = | 416 | runtime->hw.channels_max = |
414 | min(codec_dai->playback.channels_max, | 417 | min(codec_dai_drv->playback.channels_max, |
415 | cpu_dai->playback.channels_max); | 418 | cpu_dai_drv->playback.channels_max); |
416 | runtime->hw.formats = | 419 | runtime->hw.formats = |
417 | codec_dai->playback.formats & cpu_dai->playback.formats; | 420 | codec_dai_drv->playback.formats & cpu_dai_drv->playback.formats; |
418 | runtime->hw.rates = | 421 | runtime->hw.rates = |
419 | codec_dai->playback.rates & cpu_dai->playback.rates; | 422 | codec_dai_drv->playback.rates & cpu_dai_drv->playback.rates; |
420 | if (codec_dai->playback.rates | 423 | if (codec_dai_drv->playback.rates |
421 | & (SNDRV_PCM_RATE_KNOT | SNDRV_PCM_RATE_CONTINUOUS)) | 424 | & (SNDRV_PCM_RATE_KNOT | SNDRV_PCM_RATE_CONTINUOUS)) |
422 | runtime->hw.rates |= cpu_dai->playback.rates; | 425 | runtime->hw.rates |= cpu_dai_drv->playback.rates; |
423 | if (cpu_dai->playback.rates | 426 | if (cpu_dai_drv->playback.rates |
424 | & (SNDRV_PCM_RATE_KNOT | SNDRV_PCM_RATE_CONTINUOUS)) | 427 | & (SNDRV_PCM_RATE_KNOT | SNDRV_PCM_RATE_CONTINUOUS)) |
425 | runtime->hw.rates |= codec_dai->playback.rates; | 428 | runtime->hw.rates |= codec_dai_drv->playback.rates; |
426 | } else { | 429 | } else { |
427 | runtime->hw.rate_min = | 430 | runtime->hw.rate_min = |
428 | max(codec_dai->capture.rate_min, | 431 | max(codec_dai_drv->capture.rate_min, |
429 | cpu_dai->capture.rate_min); | 432 | cpu_dai_drv->capture.rate_min); |
430 | runtime->hw.rate_max = | 433 | runtime->hw.rate_max = |
431 | min(codec_dai->capture.rate_max, | 434 | min(codec_dai_drv->capture.rate_max, |
432 | cpu_dai->capture.rate_max); | 435 | cpu_dai_drv->capture.rate_max); |
433 | runtime->hw.channels_min = | 436 | runtime->hw.channels_min = |
434 | max(codec_dai->capture.channels_min, | 437 | max(codec_dai_drv->capture.channels_min, |
435 | cpu_dai->capture.channels_min); | 438 | cpu_dai_drv->capture.channels_min); |
436 | runtime->hw.channels_max = | 439 | runtime->hw.channels_max = |
437 | min(codec_dai->capture.channels_max, | 440 | min(codec_dai_drv->capture.channels_max, |
438 | cpu_dai->capture.channels_max); | 441 | cpu_dai_drv->capture.channels_max); |
439 | runtime->hw.formats = | 442 | runtime->hw.formats = |
440 | codec_dai->capture.formats & cpu_dai->capture.formats; | 443 | codec_dai_drv->capture.formats & cpu_dai_drv->capture.formats; |
441 | runtime->hw.rates = | 444 | runtime->hw.rates = |
442 | codec_dai->capture.rates & cpu_dai->capture.rates; | 445 | codec_dai_drv->capture.rates & cpu_dai_drv->capture.rates; |
443 | if (codec_dai->capture.rates | 446 | if (codec_dai_drv->capture.rates |
444 | & (SNDRV_PCM_RATE_KNOT | SNDRV_PCM_RATE_CONTINUOUS)) | 447 | & (SNDRV_PCM_RATE_KNOT | SNDRV_PCM_RATE_CONTINUOUS)) |
445 | runtime->hw.rates |= cpu_dai->capture.rates; | 448 | runtime->hw.rates |= cpu_dai_drv->capture.rates; |
446 | if (cpu_dai->capture.rates | 449 | if (cpu_dai_drv->capture.rates |
447 | & (SNDRV_PCM_RATE_KNOT | SNDRV_PCM_RATE_CONTINUOUS)) | 450 | & (SNDRV_PCM_RATE_KNOT | SNDRV_PCM_RATE_CONTINUOUS)) |
448 | runtime->hw.rates |= codec_dai->capture.rates; | 451 | runtime->hw.rates |= codec_dai_drv->capture.rates; |
449 | } | 452 | } |
450 | 453 | ||
451 | snd_pcm_limit_hw_rates(runtime); | 454 | snd_pcm_limit_hw_rates(runtime); |
@@ -461,7 +464,7 @@ static int soc_pcm_open(struct snd_pcm_substream *substream) | |||
461 | } | 464 | } |
462 | if (!runtime->hw.channels_min || !runtime->hw.channels_max) { | 465 | if (!runtime->hw.channels_min || !runtime->hw.channels_max) { |
463 | printk(KERN_ERR "asoc: %s <-> %s No matching channels\n", | 466 | printk(KERN_ERR "asoc: %s <-> %s No matching channels\n", |
464 | codec_dai->name, cpu_dai->name); | 467 | codec_dai->name, cpu_dai->name); |
465 | goto config_err; | 468 | goto config_err; |
466 | } | 469 | } |
467 | 470 | ||
@@ -472,7 +475,8 @@ static int soc_pcm_open(struct snd_pcm_substream *substream) | |||
472 | goto config_err; | 475 | goto config_err; |
473 | } | 476 | } |
474 | 477 | ||
475 | pr_debug("asoc: %s <-> %s info:\n", codec_dai->name, cpu_dai->name); | 478 | pr_debug("asoc: %s <-> %s info:\n", |
479 | codec_dai->name, cpu_dai->name); | ||
476 | pr_debug("asoc: rate mask 0x%x\n", runtime->hw.rates); | 480 | pr_debug("asoc: rate mask 0x%x\n", runtime->hw.rates); |
477 | pr_debug("asoc: min ch %d max ch %d\n", runtime->hw.channels_min, | 481 | pr_debug("asoc: min ch %d max ch %d\n", runtime->hw.channels_min, |
478 | runtime->hw.channels_max); | 482 | runtime->hw.channels_max); |
@@ -480,33 +484,33 @@ static int soc_pcm_open(struct snd_pcm_substream *substream) | |||
480 | runtime->hw.rate_max); | 484 | runtime->hw.rate_max); |
481 | 485 | ||
482 | if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) { | 486 | if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) { |
483 | cpu_dai->playback.active++; | 487 | cpu_dai->playback_active++; |
484 | codec_dai->playback.active++; | 488 | codec_dai->playback_active++; |
485 | } else { | 489 | } else { |
486 | cpu_dai->capture.active++; | 490 | cpu_dai->capture_active++; |
487 | codec_dai->capture.active++; | 491 | codec_dai->capture_active++; |
488 | } | 492 | } |
489 | cpu_dai->active++; | 493 | cpu_dai->active++; |
490 | codec_dai->active++; | 494 | codec_dai->active++; |
491 | card->codec->active++; | 495 | rtd->codec->active++; |
492 | mutex_unlock(&pcm_mutex); | 496 | mutex_unlock(&pcm_mutex); |
493 | return 0; | 497 | return 0; |
494 | 498 | ||
495 | config_err: | 499 | config_err: |
496 | if (machine->ops && machine->ops->shutdown) | 500 | if (rtd->dai_link->ops && rtd->dai_link->ops->shutdown) |
497 | machine->ops->shutdown(substream); | 501 | rtd->dai_link->ops->shutdown(substream); |
498 | 502 | ||
499 | machine_err: | 503 | machine_err: |
500 | if (codec_dai->ops->shutdown) | 504 | if (codec_dai->driver->ops->shutdown) |
501 | codec_dai->ops->shutdown(substream, codec_dai); | 505 | codec_dai->driver->ops->shutdown(substream, codec_dai); |
502 | 506 | ||
503 | codec_dai_err: | 507 | codec_dai_err: |
504 | if (platform->pcm_ops->close) | 508 | if (platform->driver->ops->close) |
505 | platform->pcm_ops->close(substream); | 509 | platform->driver->ops->close(substream); |
506 | 510 | ||
507 | platform_err: | 511 | platform_err: |
508 | if (cpu_dai->ops->shutdown) | 512 | if (cpu_dai->driver->ops->shutdown) |
509 | cpu_dai->ops->shutdown(substream, cpu_dai); | 513 | cpu_dai->driver->ops->shutdown(substream, cpu_dai); |
510 | out: | 514 | out: |
511 | mutex_unlock(&pcm_mutex); | 515 | mutex_unlock(&pcm_mutex); |
512 | return ret; | 516 | return ret; |
@@ -519,29 +523,25 @@ out: | |||
519 | */ | 523 | */ |
520 | static void close_delayed_work(struct work_struct *work) | 524 | static void close_delayed_work(struct work_struct *work) |
521 | { | 525 | { |
522 | struct snd_soc_card *card = container_of(work, struct snd_soc_card, | 526 | struct snd_soc_pcm_runtime *rtd = |
523 | delayed_work.work); | 527 | container_of(work, struct snd_soc_pcm_runtime, delayed_work.work); |
524 | struct snd_soc_codec *codec = card->codec; | 528 | struct snd_soc_dai *codec_dai = rtd->codec_dai; |
525 | struct snd_soc_dai *codec_dai; | ||
526 | int i; | ||
527 | 529 | ||
528 | mutex_lock(&pcm_mutex); | 530 | mutex_lock(&pcm_mutex); |
529 | for (i = 0; i < codec->num_dai; i++) { | 531 | |
530 | codec_dai = &codec->dai[i]; | 532 | pr_debug("pop wq checking: %s status: %s waiting: %s\n", |
531 | 533 | codec_dai->driver->playback.stream_name, | |
532 | pr_debug("pop wq checking: %s status: %s waiting: %s\n", | 534 | codec_dai->playback_active ? "active" : "inactive", |
533 | codec_dai->playback.stream_name, | 535 | codec_dai->pop_wait ? "yes" : "no"); |
534 | codec_dai->playback.active ? "active" : "inactive", | 536 | |
535 | codec_dai->pop_wait ? "yes" : "no"); | 537 | /* are we waiting on this codec DAI stream */ |
536 | 538 | if (codec_dai->pop_wait == 1) { | |
537 | /* are we waiting on this codec DAI stream */ | 539 | codec_dai->pop_wait = 0; |
538 | if (codec_dai->pop_wait == 1) { | 540 | snd_soc_dapm_stream_event(rtd, |
539 | codec_dai->pop_wait = 0; | 541 | codec_dai->driver->playback.stream_name, |
540 | snd_soc_dapm_stream_event(codec, | 542 | SND_SOC_DAPM_STREAM_STOP); |
541 | codec_dai->playback.stream_name, | ||
542 | SND_SOC_DAPM_STREAM_STOP); | ||
543 | } | ||
544 | } | 543 | } |
544 | |||
545 | mutex_unlock(&pcm_mutex); | 545 | mutex_unlock(&pcm_mutex); |
546 | } | 546 | } |
547 | 547 | ||
@@ -553,22 +553,19 @@ static void close_delayed_work(struct work_struct *work) | |||
553 | static int soc_codec_close(struct snd_pcm_substream *substream) | 553 | static int soc_codec_close(struct snd_pcm_substream *substream) |
554 | { | 554 | { |
555 | struct snd_soc_pcm_runtime *rtd = substream->private_data; | 555 | struct snd_soc_pcm_runtime *rtd = substream->private_data; |
556 | struct snd_soc_device *socdev = rtd->socdev; | 556 | struct snd_soc_platform *platform = rtd->platform; |
557 | struct snd_soc_card *card = socdev->card; | 557 | struct snd_soc_dai *cpu_dai = rtd->cpu_dai; |
558 | struct snd_soc_dai_link *machine = rtd->dai; | 558 | struct snd_soc_dai *codec_dai = rtd->codec_dai; |
559 | struct snd_soc_platform *platform = card->platform; | 559 | struct snd_soc_codec *codec = rtd->codec; |
560 | struct snd_soc_dai *cpu_dai = machine->cpu_dai; | ||
561 | struct snd_soc_dai *codec_dai = machine->codec_dai; | ||
562 | struct snd_soc_codec *codec = card->codec; | ||
563 | 560 | ||
564 | mutex_lock(&pcm_mutex); | 561 | mutex_lock(&pcm_mutex); |
565 | 562 | ||
566 | if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) { | 563 | if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) { |
567 | cpu_dai->playback.active--; | 564 | cpu_dai->playback_active--; |
568 | codec_dai->playback.active--; | 565 | codec_dai->playback_active--; |
569 | } else { | 566 | } else { |
570 | cpu_dai->capture.active--; | 567 | cpu_dai->capture_active--; |
571 | codec_dai->capture.active--; | 568 | codec_dai->capture_active--; |
572 | } | 569 | } |
573 | 570 | ||
574 | cpu_dai->active--; | 571 | cpu_dai->active--; |
@@ -581,27 +578,28 @@ static int soc_codec_close(struct snd_pcm_substream *substream) | |||
581 | if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) | 578 | if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) |
582 | snd_soc_dai_digital_mute(codec_dai, 1); | 579 | snd_soc_dai_digital_mute(codec_dai, 1); |
583 | 580 | ||
584 | if (cpu_dai->ops->shutdown) | 581 | if (cpu_dai->driver->ops->shutdown) |
585 | cpu_dai->ops->shutdown(substream, cpu_dai); | 582 | cpu_dai->driver->ops->shutdown(substream, cpu_dai); |
586 | 583 | ||
587 | if (codec_dai->ops->shutdown) | 584 | if (codec_dai->driver->ops->shutdown) |
588 | codec_dai->ops->shutdown(substream, codec_dai); | 585 | codec_dai->driver->ops->shutdown(substream, codec_dai); |
589 | 586 | ||
590 | if (machine->ops && machine->ops->shutdown) | 587 | if (rtd->dai_link->ops && rtd->dai_link->ops->shutdown) |
591 | machine->ops->shutdown(substream); | 588 | rtd->dai_link->ops->shutdown(substream); |
592 | 589 | ||
593 | if (platform->pcm_ops->close) | 590 | if (platform->driver->ops->close) |
594 | platform->pcm_ops->close(substream); | 591 | platform->driver->ops->close(substream); |
592 | cpu_dai->runtime = NULL; | ||
595 | 593 | ||
596 | if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) { | 594 | if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) { |
597 | /* start delayed pop wq here for playback streams */ | 595 | /* start delayed pop wq here for playback streams */ |
598 | codec_dai->pop_wait = 1; | 596 | codec_dai->pop_wait = 1; |
599 | schedule_delayed_work(&card->delayed_work, | 597 | schedule_delayed_work(&rtd->delayed_work, |
600 | msecs_to_jiffies(card->pmdown_time)); | 598 | msecs_to_jiffies(rtd->pmdown_time)); |
601 | } else { | 599 | } else { |
602 | /* capture streams can be powered down now */ | 600 | /* capture streams can be powered down now */ |
603 | snd_soc_dapm_stream_event(codec, | 601 | snd_soc_dapm_stream_event(rtd, |
604 | codec_dai->capture.stream_name, | 602 | codec_dai->driver->capture.stream_name, |
605 | SND_SOC_DAPM_STREAM_STOP); | 603 | SND_SOC_DAPM_STREAM_STOP); |
606 | } | 604 | } |
607 | 605 | ||
@@ -617,43 +615,39 @@ static int soc_codec_close(struct snd_pcm_substream *substream) | |||
617 | static int soc_pcm_prepare(struct snd_pcm_substream *substream) | 615 | static int soc_pcm_prepare(struct snd_pcm_substream *substream) |
618 | { | 616 | { |
619 | struct snd_soc_pcm_runtime *rtd = substream->private_data; | 617 | struct snd_soc_pcm_runtime *rtd = substream->private_data; |
620 | struct snd_soc_device *socdev = rtd->socdev; | 618 | struct snd_soc_platform *platform = rtd->platform; |
621 | struct snd_soc_card *card = socdev->card; | 619 | struct snd_soc_dai *cpu_dai = rtd->cpu_dai; |
622 | struct snd_soc_dai_link *machine = rtd->dai; | 620 | struct snd_soc_dai *codec_dai = rtd->codec_dai; |
623 | struct snd_soc_platform *platform = card->platform; | ||
624 | struct snd_soc_dai *cpu_dai = machine->cpu_dai; | ||
625 | struct snd_soc_dai *codec_dai = machine->codec_dai; | ||
626 | struct snd_soc_codec *codec = card->codec; | ||
627 | int ret = 0; | 621 | int ret = 0; |
628 | 622 | ||
629 | mutex_lock(&pcm_mutex); | 623 | mutex_lock(&pcm_mutex); |
630 | 624 | ||
631 | if (machine->ops && machine->ops->prepare) { | 625 | if (rtd->dai_link->ops && rtd->dai_link->ops->prepare) { |
632 | ret = machine->ops->prepare(substream); | 626 | ret = rtd->dai_link->ops->prepare(substream); |
633 | if (ret < 0) { | 627 | if (ret < 0) { |
634 | printk(KERN_ERR "asoc: machine prepare error\n"); | 628 | printk(KERN_ERR "asoc: machine prepare error\n"); |
635 | goto out; | 629 | goto out; |
636 | } | 630 | } |
637 | } | 631 | } |
638 | 632 | ||
639 | if (platform->pcm_ops->prepare) { | 633 | if (platform->driver->ops->prepare) { |
640 | ret = platform->pcm_ops->prepare(substream); | 634 | ret = platform->driver->ops->prepare(substream); |
641 | if (ret < 0) { | 635 | if (ret < 0) { |
642 | printk(KERN_ERR "asoc: platform prepare error\n"); | 636 | printk(KERN_ERR "asoc: platform prepare error\n"); |
643 | goto out; | 637 | goto out; |
644 | } | 638 | } |
645 | } | 639 | } |
646 | 640 | ||
647 | if (codec_dai->ops->prepare) { | 641 | if (codec_dai->driver->ops->prepare) { |
648 | ret = codec_dai->ops->prepare(substream, codec_dai); | 642 | ret = codec_dai->driver->ops->prepare(substream, codec_dai); |
649 | if (ret < 0) { | 643 | if (ret < 0) { |
650 | printk(KERN_ERR "asoc: codec DAI prepare error\n"); | 644 | printk(KERN_ERR "asoc: codec DAI prepare error\n"); |
651 | goto out; | 645 | goto out; |
652 | } | 646 | } |
653 | } | 647 | } |
654 | 648 | ||
655 | if (cpu_dai->ops->prepare) { | 649 | if (cpu_dai->driver->ops->prepare) { |
656 | ret = cpu_dai->ops->prepare(substream, cpu_dai); | 650 | ret = cpu_dai->driver->ops->prepare(substream, cpu_dai); |
657 | if (ret < 0) { | 651 | if (ret < 0) { |
658 | printk(KERN_ERR "asoc: cpu DAI prepare error\n"); | 652 | printk(KERN_ERR "asoc: cpu DAI prepare error\n"); |
659 | goto out; | 653 | goto out; |
@@ -664,16 +658,16 @@ static int soc_pcm_prepare(struct snd_pcm_substream *substream) | |||
664 | if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK && | 658 | if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK && |
665 | codec_dai->pop_wait) { | 659 | codec_dai->pop_wait) { |
666 | codec_dai->pop_wait = 0; | 660 | codec_dai->pop_wait = 0; |
667 | cancel_delayed_work(&card->delayed_work); | 661 | cancel_delayed_work(&rtd->delayed_work); |
668 | } | 662 | } |
669 | 663 | ||
670 | if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) | 664 | if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) |
671 | snd_soc_dapm_stream_event(codec, | 665 | snd_soc_dapm_stream_event(rtd, |
672 | codec_dai->playback.stream_name, | 666 | codec_dai->driver->playback.stream_name, |
673 | SND_SOC_DAPM_STREAM_START); | 667 | SND_SOC_DAPM_STREAM_START); |
674 | else | 668 | else |
675 | snd_soc_dapm_stream_event(codec, | 669 | snd_soc_dapm_stream_event(rtd, |
676 | codec_dai->capture.stream_name, | 670 | codec_dai->driver->capture.stream_name, |
677 | SND_SOC_DAPM_STREAM_START); | 671 | SND_SOC_DAPM_STREAM_START); |
678 | 672 | ||
679 | snd_soc_dai_digital_mute(codec_dai, 0); | 673 | snd_soc_dai_digital_mute(codec_dai, 0); |
@@ -692,26 +686,23 @@ static int soc_pcm_hw_params(struct snd_pcm_substream *substream, | |||
692 | struct snd_pcm_hw_params *params) | 686 | struct snd_pcm_hw_params *params) |
693 | { | 687 | { |
694 | struct snd_soc_pcm_runtime *rtd = substream->private_data; | 688 | struct snd_soc_pcm_runtime *rtd = substream->private_data; |
695 | struct snd_soc_device *socdev = rtd->socdev; | 689 | struct snd_soc_platform *platform = rtd->platform; |
696 | struct snd_soc_dai_link *machine = rtd->dai; | 690 | struct snd_soc_dai *cpu_dai = rtd->cpu_dai; |
697 | struct snd_soc_card *card = socdev->card; | 691 | struct snd_soc_dai *codec_dai = rtd->codec_dai; |
698 | struct snd_soc_platform *platform = card->platform; | ||
699 | struct snd_soc_dai *cpu_dai = machine->cpu_dai; | ||
700 | struct snd_soc_dai *codec_dai = machine->codec_dai; | ||
701 | int ret = 0; | 692 | int ret = 0; |
702 | 693 | ||
703 | mutex_lock(&pcm_mutex); | 694 | mutex_lock(&pcm_mutex); |
704 | 695 | ||
705 | if (machine->ops && machine->ops->hw_params) { | 696 | if (rtd->dai_link->ops && rtd->dai_link->ops->hw_params) { |
706 | ret = machine->ops->hw_params(substream, params); | 697 | ret = rtd->dai_link->ops->hw_params(substream, params); |
707 | if (ret < 0) { | 698 | if (ret < 0) { |
708 | printk(KERN_ERR "asoc: machine hw_params failed\n"); | 699 | printk(KERN_ERR "asoc: machine hw_params failed\n"); |
709 | goto out; | 700 | goto out; |
710 | } | 701 | } |
711 | } | 702 | } |
712 | 703 | ||
713 | if (codec_dai->ops->hw_params) { | 704 | if (codec_dai->driver->ops->hw_params) { |
714 | ret = codec_dai->ops->hw_params(substream, params, codec_dai); | 705 | ret = codec_dai->driver->ops->hw_params(substream, params, codec_dai); |
715 | if (ret < 0) { | 706 | if (ret < 0) { |
716 | printk(KERN_ERR "asoc: can't set codec %s hw params\n", | 707 | printk(KERN_ERR "asoc: can't set codec %s hw params\n", |
717 | codec_dai->name); | 708 | codec_dai->name); |
@@ -719,8 +710,8 @@ static int soc_pcm_hw_params(struct snd_pcm_substream *substream, | |||
719 | } | 710 | } |
720 | } | 711 | } |
721 | 712 | ||
722 | if (cpu_dai->ops->hw_params) { | 713 | if (cpu_dai->driver->ops->hw_params) { |
723 | ret = cpu_dai->ops->hw_params(substream, params, cpu_dai); | 714 | ret = cpu_dai->driver->ops->hw_params(substream, params, cpu_dai); |
724 | if (ret < 0) { | 715 | if (ret < 0) { |
725 | printk(KERN_ERR "asoc: interface %s hw params failed\n", | 716 | printk(KERN_ERR "asoc: interface %s hw params failed\n", |
726 | cpu_dai->name); | 717 | cpu_dai->name); |
@@ -728,8 +719,8 @@ static int soc_pcm_hw_params(struct snd_pcm_substream *substream, | |||
728 | } | 719 | } |
729 | } | 720 | } |
730 | 721 | ||
731 | if (platform->pcm_ops->hw_params) { | 722 | if (platform->driver->ops->hw_params) { |
732 | ret = platform->pcm_ops->hw_params(substream, params); | 723 | ret = platform->driver->ops->hw_params(substream, params); |
733 | if (ret < 0) { | 724 | if (ret < 0) { |
734 | printk(KERN_ERR "asoc: platform %s hw params failed\n", | 725 | printk(KERN_ERR "asoc: platform %s hw params failed\n", |
735 | platform->name); | 726 | platform->name); |
@@ -737,23 +728,23 @@ static int soc_pcm_hw_params(struct snd_pcm_substream *substream, | |||
737 | } | 728 | } |
738 | } | 729 | } |
739 | 730 | ||
740 | machine->rate = params_rate(params); | 731 | rtd->rate = params_rate(params); |
741 | 732 | ||
742 | out: | 733 | out: |
743 | mutex_unlock(&pcm_mutex); | 734 | mutex_unlock(&pcm_mutex); |
744 | return ret; | 735 | return ret; |
745 | 736 | ||
746 | platform_err: | 737 | platform_err: |
747 | if (cpu_dai->ops->hw_free) | 738 | if (cpu_dai->driver->ops->hw_free) |
748 | cpu_dai->ops->hw_free(substream, cpu_dai); | 739 | cpu_dai->driver->ops->hw_free(substream, cpu_dai); |
749 | 740 | ||
750 | interface_err: | 741 | interface_err: |
751 | if (codec_dai->ops->hw_free) | 742 | if (codec_dai->driver->ops->hw_free) |
752 | codec_dai->ops->hw_free(substream, codec_dai); | 743 | codec_dai->driver->ops->hw_free(substream, codec_dai); |
753 | 744 | ||
754 | codec_err: | 745 | codec_err: |
755 | if (machine->ops && machine->ops->hw_free) | 746 | if (rtd->dai_link->ops && rtd->dai_link->ops->hw_free) |
756 | machine->ops->hw_free(substream); | 747 | rtd->dai_link->ops->hw_free(substream); |
757 | 748 | ||
758 | mutex_unlock(&pcm_mutex); | 749 | mutex_unlock(&pcm_mutex); |
759 | return ret; | 750 | return ret; |
@@ -765,13 +756,10 @@ codec_err: | |||
765 | static int soc_pcm_hw_free(struct snd_pcm_substream *substream) | 756 | static int soc_pcm_hw_free(struct snd_pcm_substream *substream) |
766 | { | 757 | { |
767 | struct snd_soc_pcm_runtime *rtd = substream->private_data; | 758 | struct snd_soc_pcm_runtime *rtd = substream->private_data; |
768 | struct snd_soc_device *socdev = rtd->socdev; | 759 | struct snd_soc_platform *platform = rtd->platform; |
769 | struct snd_soc_dai_link *machine = rtd->dai; | 760 | struct snd_soc_dai *cpu_dai = rtd->cpu_dai; |
770 | struct snd_soc_card *card = socdev->card; | 761 | struct snd_soc_dai *codec_dai = rtd->codec_dai; |
771 | struct snd_soc_platform *platform = card->platform; | 762 | struct snd_soc_codec *codec = rtd->codec; |
772 | struct snd_soc_dai *cpu_dai = machine->cpu_dai; | ||
773 | struct snd_soc_dai *codec_dai = machine->codec_dai; | ||
774 | struct snd_soc_codec *codec = card->codec; | ||
775 | 763 | ||
776 | mutex_lock(&pcm_mutex); | 764 | mutex_lock(&pcm_mutex); |
777 | 765 | ||
@@ -780,19 +768,19 @@ static int soc_pcm_hw_free(struct snd_pcm_substream *substream) | |||
780 | snd_soc_dai_digital_mute(codec_dai, 1); | 768 | snd_soc_dai_digital_mute(codec_dai, 1); |
781 | 769 | ||
782 | /* free any machine hw params */ | 770 | /* free any machine hw params */ |
783 | if (machine->ops && machine->ops->hw_free) | 771 | if (rtd->dai_link->ops && rtd->dai_link->ops->hw_free) |
784 | machine->ops->hw_free(substream); | 772 | rtd->dai_link->ops->hw_free(substream); |
785 | 773 | ||
786 | /* free any DMA resources */ | 774 | /* free any DMA resources */ |
787 | if (platform->pcm_ops->hw_free) | 775 | if (platform->driver->ops->hw_free) |
788 | platform->pcm_ops->hw_free(substream); | 776 | platform->driver->ops->hw_free(substream); |
789 | 777 | ||
790 | /* now free hw params for the DAI's */ | 778 | /* now free hw params for the DAI's */ |
791 | if (codec_dai->ops->hw_free) | 779 | if (codec_dai->driver->ops->hw_free) |
792 | codec_dai->ops->hw_free(substream, codec_dai); | 780 | codec_dai->driver->ops->hw_free(substream, codec_dai); |
793 | 781 | ||
794 | if (cpu_dai->ops->hw_free) | 782 | if (cpu_dai->driver->ops->hw_free) |
795 | cpu_dai->ops->hw_free(substream, cpu_dai); | 783 | cpu_dai->driver->ops->hw_free(substream, cpu_dai); |
796 | 784 | ||
797 | mutex_unlock(&pcm_mutex); | 785 | mutex_unlock(&pcm_mutex); |
798 | return 0; | 786 | return 0; |
@@ -801,28 +789,25 @@ static int soc_pcm_hw_free(struct snd_pcm_substream *substream) | |||
801 | static int soc_pcm_trigger(struct snd_pcm_substream *substream, int cmd) | 789 | static int soc_pcm_trigger(struct snd_pcm_substream *substream, int cmd) |
802 | { | 790 | { |
803 | struct snd_soc_pcm_runtime *rtd = substream->private_data; | 791 | struct snd_soc_pcm_runtime *rtd = substream->private_data; |
804 | struct snd_soc_device *socdev = rtd->socdev; | 792 | struct snd_soc_platform *platform = rtd->platform; |
805 | struct snd_soc_card *card= socdev->card; | 793 | struct snd_soc_dai *cpu_dai = rtd->cpu_dai; |
806 | struct snd_soc_dai_link *machine = rtd->dai; | 794 | struct snd_soc_dai *codec_dai = rtd->codec_dai; |
807 | struct snd_soc_platform *platform = card->platform; | ||
808 | struct snd_soc_dai *cpu_dai = machine->cpu_dai; | ||
809 | struct snd_soc_dai *codec_dai = machine->codec_dai; | ||
810 | int ret; | 795 | int ret; |
811 | 796 | ||
812 | if (codec_dai->ops->trigger) { | 797 | if (codec_dai->driver->ops->trigger) { |
813 | ret = codec_dai->ops->trigger(substream, cmd, codec_dai); | 798 | ret = codec_dai->driver->ops->trigger(substream, cmd, codec_dai); |
814 | if (ret < 0) | 799 | if (ret < 0) |
815 | return ret; | 800 | return ret; |
816 | } | 801 | } |
817 | 802 | ||
818 | if (platform->pcm_ops->trigger) { | 803 | if (platform->driver->ops->trigger) { |
819 | ret = platform->pcm_ops->trigger(substream, cmd); | 804 | ret = platform->driver->ops->trigger(substream, cmd); |
820 | if (ret < 0) | 805 | if (ret < 0) |
821 | return ret; | 806 | return ret; |
822 | } | 807 | } |
823 | 808 | ||
824 | if (cpu_dai->ops->trigger) { | 809 | if (cpu_dai->driver->ops->trigger) { |
825 | ret = cpu_dai->ops->trigger(substream, cmd, cpu_dai); | 810 | ret = cpu_dai->driver->ops->trigger(substream, cmd, cpu_dai); |
826 | if (ret < 0) | 811 | if (ret < 0) |
827 | return ret; | 812 | return ret; |
828 | } | 813 | } |
@@ -837,27 +822,24 @@ static int soc_pcm_trigger(struct snd_pcm_substream *substream, int cmd) | |||
837 | static snd_pcm_uframes_t soc_pcm_pointer(struct snd_pcm_substream *substream) | 822 | static snd_pcm_uframes_t soc_pcm_pointer(struct snd_pcm_substream *substream) |
838 | { | 823 | { |
839 | struct snd_soc_pcm_runtime *rtd = substream->private_data; | 824 | struct snd_soc_pcm_runtime *rtd = substream->private_data; |
840 | struct snd_soc_device *socdev = rtd->socdev; | 825 | struct snd_soc_platform *platform = rtd->platform; |
841 | struct snd_soc_card *card = socdev->card; | 826 | struct snd_soc_dai *cpu_dai = rtd->cpu_dai; |
842 | struct snd_soc_platform *platform = card->platform; | 827 | struct snd_soc_dai *codec_dai = rtd->codec_dai; |
843 | struct snd_soc_dai_link *machine = rtd->dai; | ||
844 | struct snd_soc_dai *cpu_dai = machine->cpu_dai; | ||
845 | struct snd_soc_dai *codec_dai = machine->codec_dai; | ||
846 | struct snd_pcm_runtime *runtime = substream->runtime; | 828 | struct snd_pcm_runtime *runtime = substream->runtime; |
847 | snd_pcm_uframes_t offset = 0; | 829 | snd_pcm_uframes_t offset = 0; |
848 | snd_pcm_sframes_t delay = 0; | 830 | snd_pcm_sframes_t delay = 0; |
849 | 831 | ||
850 | if (platform->pcm_ops->pointer) | 832 | if (platform->driver->ops->pointer) |
851 | offset = platform->pcm_ops->pointer(substream); | 833 | offset = platform->driver->ops->pointer(substream); |
852 | 834 | ||
853 | if (cpu_dai->ops->delay) | 835 | if (cpu_dai->driver->ops->delay) |
854 | delay += cpu_dai->ops->delay(substream, cpu_dai); | 836 | delay += cpu_dai->driver->ops->delay(substream, cpu_dai); |
855 | 837 | ||
856 | if (codec_dai->ops->delay) | 838 | if (codec_dai->driver->ops->delay) |
857 | delay += codec_dai->ops->delay(substream, codec_dai); | 839 | delay += codec_dai->driver->ops->delay(substream, codec_dai); |
858 | 840 | ||
859 | if (platform->delay) | 841 | if (platform->driver->delay) |
860 | delay += platform->delay(substream, codec_dai); | 842 | delay += platform->driver->delay(substream, codec_dai); |
861 | 843 | ||
862 | runtime->delay = delay; | 844 | runtime->delay = delay; |
863 | 845 | ||
@@ -880,104 +862,111 @@ static struct snd_pcm_ops soc_pcm_ops = { | |||
880 | static int soc_suspend(struct device *dev) | 862 | static int soc_suspend(struct device *dev) |
881 | { | 863 | { |
882 | struct platform_device *pdev = to_platform_device(dev); | 864 | struct platform_device *pdev = to_platform_device(dev); |
883 | struct snd_soc_device *socdev = platform_get_drvdata(pdev); | 865 | struct snd_soc_card *card = platform_get_drvdata(pdev); |
884 | struct snd_soc_card *card = socdev->card; | ||
885 | struct snd_soc_platform *platform = card->platform; | ||
886 | struct snd_soc_codec_device *codec_dev = socdev->codec_dev; | ||
887 | struct snd_soc_codec *codec = card->codec; | ||
888 | int i; | 866 | int i; |
889 | 867 | ||
890 | /* If the initialization of this soc device failed, there is no codec | 868 | /* If the initialization of this soc device failed, there is no codec |
891 | * associated with it. Just bail out in this case. | 869 | * associated with it. Just bail out in this case. |
892 | */ | 870 | */ |
893 | if (!codec) | 871 | if (list_empty(&card->codec_dev_list)) |
894 | return 0; | 872 | return 0; |
895 | 873 | ||
896 | /* Due to the resume being scheduled into a workqueue we could | 874 | /* Due to the resume being scheduled into a workqueue we could |
897 | * suspend before that's finished - wait for it to complete. | 875 | * suspend before that's finished - wait for it to complete. |
898 | */ | 876 | */ |
899 | snd_power_lock(codec->card); | 877 | snd_power_lock(card->snd_card); |
900 | snd_power_wait(codec->card, SNDRV_CTL_POWER_D0); | 878 | snd_power_wait(card->snd_card, SNDRV_CTL_POWER_D0); |
901 | snd_power_unlock(codec->card); | 879 | snd_power_unlock(card->snd_card); |
902 | 880 | ||
903 | /* we're going to block userspace touching us until resume completes */ | 881 | /* we're going to block userspace touching us until resume completes */ |
904 | snd_power_change_state(codec->card, SNDRV_CTL_POWER_D3hot); | 882 | snd_power_change_state(card->snd_card, SNDRV_CTL_POWER_D3hot); |
905 | 883 | ||
906 | /* mute any active DAC's */ | 884 | /* mute any active DAC's */ |
907 | for (i = 0; i < card->num_links; i++) { | 885 | for (i = 0; i < card->num_rtd; i++) { |
908 | struct snd_soc_dai *dai = card->dai_link[i].codec_dai; | 886 | struct snd_soc_dai *dai = card->rtd[i].codec_dai; |
887 | struct snd_soc_dai_driver *drv = dai->driver; | ||
909 | 888 | ||
910 | if (card->dai_link[i].ignore_suspend) | 889 | if (card->rtd[i].dai_link->ignore_suspend) |
911 | continue; | 890 | continue; |
912 | 891 | ||
913 | if (dai->ops->digital_mute && dai->playback.active) | 892 | if (drv->ops->digital_mute && dai->playback_active) |
914 | dai->ops->digital_mute(dai, 1); | 893 | drv->ops->digital_mute(dai, 1); |
915 | } | 894 | } |
916 | 895 | ||
917 | /* suspend all pcms */ | 896 | /* suspend all pcms */ |
918 | for (i = 0; i < card->num_links; i++) { | 897 | for (i = 0; i < card->num_rtd; i++) { |
919 | if (card->dai_link[i].ignore_suspend) | 898 | if (card->rtd[i].dai_link->ignore_suspend) |
920 | continue; | 899 | continue; |
921 | 900 | ||
922 | snd_pcm_suspend_all(card->dai_link[i].pcm); | 901 | snd_pcm_suspend_all(card->rtd[i].pcm); |
923 | } | 902 | } |
924 | 903 | ||
925 | if (card->suspend_pre) | 904 | if (card->suspend_pre) |
926 | card->suspend_pre(pdev, PMSG_SUSPEND); | 905 | card->suspend_pre(pdev, PMSG_SUSPEND); |
927 | 906 | ||
928 | for (i = 0; i < card->num_links; i++) { | 907 | for (i = 0; i < card->num_rtd; i++) { |
929 | struct snd_soc_dai *cpu_dai = card->dai_link[i].cpu_dai; | 908 | struct snd_soc_dai *cpu_dai = card->rtd[i].cpu_dai; |
909 | struct snd_soc_platform *platform = card->rtd[i].platform; | ||
930 | 910 | ||
931 | if (card->dai_link[i].ignore_suspend) | 911 | if (card->rtd[i].dai_link->ignore_suspend) |
932 | continue; | 912 | continue; |
933 | 913 | ||
934 | if (cpu_dai->suspend && !cpu_dai->ac97_control) | 914 | if (cpu_dai->driver->suspend && !cpu_dai->driver->ac97_control) |
935 | cpu_dai->suspend(cpu_dai); | 915 | cpu_dai->driver->suspend(cpu_dai); |
936 | if (platform->suspend) | 916 | if (platform->driver->suspend && !platform->suspended) { |
937 | platform->suspend(&card->dai_link[i]); | 917 | platform->driver->suspend(cpu_dai); |
918 | platform->suspended = 1; | ||
919 | } | ||
938 | } | 920 | } |
939 | 921 | ||
940 | /* close any waiting streams and save state */ | 922 | /* close any waiting streams and save state */ |
941 | run_delayed_work(&card->delayed_work); | 923 | for (i = 0; i < card->num_rtd; i++) { |
942 | codec->suspend_bias_level = codec->bias_level; | 924 | run_delayed_work(&card->rtd[i].delayed_work); |
925 | card->rtd[i].codec->suspend_bias_level = card->rtd[i].codec->bias_level; | ||
926 | } | ||
943 | 927 | ||
944 | for (i = 0; i < codec->num_dai; i++) { | 928 | for (i = 0; i < card->num_rtd; i++) { |
945 | char *stream = codec->dai[i].playback.stream_name; | 929 | struct snd_soc_dai_driver *driver = card->rtd[i].codec_dai->driver; |
946 | 930 | ||
947 | if (card->dai_link[i].ignore_suspend) | 931 | if (card->rtd[i].dai_link->ignore_suspend) |
948 | continue; | 932 | continue; |
949 | 933 | ||
950 | if (stream != NULL) | 934 | if (driver->playback.stream_name != NULL) |
951 | snd_soc_dapm_stream_event(codec, stream, | 935 | snd_soc_dapm_stream_event(&card->rtd[i], driver->playback.stream_name, |
952 | SND_SOC_DAPM_STREAM_SUSPEND); | 936 | SND_SOC_DAPM_STREAM_SUSPEND); |
953 | stream = codec->dai[i].capture.stream_name; | 937 | |
954 | if (stream != NULL) | 938 | if (driver->capture.stream_name != NULL) |
955 | snd_soc_dapm_stream_event(codec, stream, | 939 | snd_soc_dapm_stream_event(&card->rtd[i], driver->capture.stream_name, |
956 | SND_SOC_DAPM_STREAM_SUSPEND); | 940 | SND_SOC_DAPM_STREAM_SUSPEND); |
957 | } | 941 | } |
958 | 942 | ||
959 | /* If there are paths active then the CODEC will be held with | 943 | /* suspend all CODECs */ |
960 | * bias _ON and should not be suspended. */ | 944 | for (i = 0; i < card->num_rtd; i++) { |
961 | if (codec_dev->suspend) { | 945 | struct snd_soc_codec *codec = card->rtd[i].codec; |
962 | switch (codec->bias_level) { | 946 | /* If there are paths active then the CODEC will be held with |
963 | case SND_SOC_BIAS_STANDBY: | 947 | * bias _ON and should not be suspended. */ |
964 | case SND_SOC_BIAS_OFF: | 948 | if (!codec->suspended && codec->driver->suspend) { |
965 | codec_dev->suspend(pdev, PMSG_SUSPEND); | 949 | switch (codec->bias_level) { |
966 | break; | 950 | case SND_SOC_BIAS_STANDBY: |
967 | default: | 951 | case SND_SOC_BIAS_OFF: |
968 | dev_dbg(socdev->dev, "CODEC is on over suspend\n"); | 952 | codec->driver->suspend(codec, PMSG_SUSPEND); |
969 | break; | 953 | codec->suspended = 1; |
954 | break; | ||
955 | default: | ||
956 | dev_dbg(codec->dev, "CODEC is on over suspend\n"); | ||
957 | break; | ||
958 | } | ||
970 | } | 959 | } |
971 | } | 960 | } |
972 | 961 | ||
973 | for (i = 0; i < card->num_links; i++) { | 962 | for (i = 0; i < card->num_rtd; i++) { |
974 | struct snd_soc_dai *cpu_dai = card->dai_link[i].cpu_dai; | 963 | struct snd_soc_dai *cpu_dai = card->rtd[i].cpu_dai; |
975 | 964 | ||
976 | if (card->dai_link[i].ignore_suspend) | 965 | if (card->rtd[i].dai_link->ignore_suspend) |
977 | continue; | 966 | continue; |
978 | 967 | ||
979 | if (cpu_dai->suspend && cpu_dai->ac97_control) | 968 | if (cpu_dai->driver->suspend && cpu_dai->driver->ac97_control) |
980 | cpu_dai->suspend(cpu_dai); | 969 | cpu_dai->driver->suspend(cpu_dai); |
981 | } | 970 | } |
982 | 971 | ||
983 | if (card->suspend_post) | 972 | if (card->suspend_post) |
@@ -991,127 +980,127 @@ static int soc_suspend(struct device *dev) | |||
991 | */ | 980 | */ |
992 | static void soc_resume_deferred(struct work_struct *work) | 981 | static void soc_resume_deferred(struct work_struct *work) |
993 | { | 982 | { |
994 | struct snd_soc_card *card = container_of(work, | 983 | struct snd_soc_card *card = |
995 | struct snd_soc_card, | 984 | container_of(work, struct snd_soc_card, deferred_resume_work); |
996 | deferred_resume_work); | 985 | struct platform_device *pdev = to_platform_device(card->dev); |
997 | struct snd_soc_device *socdev = card->socdev; | ||
998 | struct snd_soc_platform *platform = card->platform; | ||
999 | struct snd_soc_codec_device *codec_dev = socdev->codec_dev; | ||
1000 | struct snd_soc_codec *codec = card->codec; | ||
1001 | struct platform_device *pdev = to_platform_device(socdev->dev); | ||
1002 | int i; | 986 | int i; |
1003 | 987 | ||
1004 | /* our power state is still SNDRV_CTL_POWER_D3hot from suspend time, | 988 | /* our power state is still SNDRV_CTL_POWER_D3hot from suspend time, |
1005 | * so userspace apps are blocked from touching us | 989 | * so userspace apps are blocked from touching us |
1006 | */ | 990 | */ |
1007 | 991 | ||
1008 | dev_dbg(socdev->dev, "starting resume work\n"); | 992 | dev_dbg(card->dev, "starting resume work\n"); |
1009 | 993 | ||
1010 | /* Bring us up into D2 so that DAPM starts enabling things */ | 994 | /* Bring us up into D2 so that DAPM starts enabling things */ |
1011 | snd_power_change_state(codec->card, SNDRV_CTL_POWER_D2); | 995 | snd_power_change_state(card->snd_card, SNDRV_CTL_POWER_D2); |
1012 | 996 | ||
1013 | if (card->resume_pre) | 997 | if (card->resume_pre) |
1014 | card->resume_pre(pdev); | 998 | card->resume_pre(pdev); |
1015 | 999 | ||
1016 | for (i = 0; i < card->num_links; i++) { | 1000 | /* resume AC97 DAIs */ |
1017 | struct snd_soc_dai *cpu_dai = card->dai_link[i].cpu_dai; | 1001 | for (i = 0; i < card->num_rtd; i++) { |
1002 | struct snd_soc_dai *cpu_dai = card->rtd[i].cpu_dai; | ||
1018 | 1003 | ||
1019 | if (card->dai_link[i].ignore_suspend) | 1004 | if (card->rtd[i].dai_link->ignore_suspend) |
1020 | continue; | 1005 | continue; |
1021 | 1006 | ||
1022 | if (cpu_dai->resume && cpu_dai->ac97_control) | 1007 | if (cpu_dai->driver->resume && cpu_dai->driver->ac97_control) |
1023 | cpu_dai->resume(cpu_dai); | 1008 | cpu_dai->driver->resume(cpu_dai); |
1024 | } | 1009 | } |
1025 | 1010 | ||
1026 | /* If the CODEC was idle over suspend then it will have been | 1011 | for (i = 0; i < card->num_rtd; i++) { |
1027 | * left with bias OFF or STANDBY and suspended so we must now | 1012 | struct snd_soc_codec *codec = card->rtd[i].codec; |
1028 | * resume. Otherwise the suspend was suppressed. | 1013 | /* If the CODEC was idle over suspend then it will have been |
1029 | */ | 1014 | * left with bias OFF or STANDBY and suspended so we must now |
1030 | if (codec_dev->resume) { | 1015 | * resume. Otherwise the suspend was suppressed. |
1031 | switch (codec->bias_level) { | 1016 | */ |
1032 | case SND_SOC_BIAS_STANDBY: | 1017 | if (codec->driver->resume && codec->suspended) { |
1033 | case SND_SOC_BIAS_OFF: | 1018 | switch (codec->bias_level) { |
1034 | codec_dev->resume(pdev); | 1019 | case SND_SOC_BIAS_STANDBY: |
1035 | break; | 1020 | case SND_SOC_BIAS_OFF: |
1036 | default: | 1021 | codec->driver->resume(codec); |
1037 | dev_dbg(socdev->dev, "CODEC was on over suspend\n"); | 1022 | codec->suspended = 0; |
1038 | break; | 1023 | break; |
1024 | default: | ||
1025 | dev_dbg(codec->dev, "CODEC was on over suspend\n"); | ||
1026 | break; | ||
1027 | } | ||
1039 | } | 1028 | } |
1040 | } | 1029 | } |
1041 | 1030 | ||
1042 | for (i = 0; i < codec->num_dai; i++) { | 1031 | for (i = 0; i < card->num_rtd; i++) { |
1043 | char *stream = codec->dai[i].playback.stream_name; | 1032 | struct snd_soc_dai_driver *driver = card->rtd[i].codec_dai->driver; |
1044 | 1033 | ||
1045 | if (card->dai_link[i].ignore_suspend) | 1034 | if (card->rtd[i].dai_link->ignore_suspend) |
1046 | continue; | 1035 | continue; |
1047 | 1036 | ||
1048 | if (stream != NULL) | 1037 | if (driver->playback.stream_name != NULL) |
1049 | snd_soc_dapm_stream_event(codec, stream, | 1038 | snd_soc_dapm_stream_event(&card->rtd[i], driver->playback.stream_name, |
1050 | SND_SOC_DAPM_STREAM_RESUME); | 1039 | SND_SOC_DAPM_STREAM_RESUME); |
1051 | stream = codec->dai[i].capture.stream_name; | 1040 | |
1052 | if (stream != NULL) | 1041 | if (driver->capture.stream_name != NULL) |
1053 | snd_soc_dapm_stream_event(codec, stream, | 1042 | snd_soc_dapm_stream_event(&card->rtd[i], driver->capture.stream_name, |
1054 | SND_SOC_DAPM_STREAM_RESUME); | 1043 | SND_SOC_DAPM_STREAM_RESUME); |
1055 | } | 1044 | } |
1056 | 1045 | ||
1057 | /* unmute any active DACs */ | 1046 | /* unmute any active DACs */ |
1058 | for (i = 0; i < card->num_links; i++) { | 1047 | for (i = 0; i < card->num_rtd; i++) { |
1059 | struct snd_soc_dai *dai = card->dai_link[i].codec_dai; | 1048 | struct snd_soc_dai *dai = card->rtd[i].codec_dai; |
1049 | struct snd_soc_dai_driver *drv = dai->driver; | ||
1060 | 1050 | ||
1061 | if (card->dai_link[i].ignore_suspend) | 1051 | if (card->rtd[i].dai_link->ignore_suspend) |
1062 | continue; | 1052 | continue; |
1063 | 1053 | ||
1064 | if (dai->ops->digital_mute && dai->playback.active) | 1054 | if (drv->ops->digital_mute && dai->playback_active) |
1065 | dai->ops->digital_mute(dai, 0); | 1055 | drv->ops->digital_mute(dai, 0); |
1066 | } | 1056 | } |
1067 | 1057 | ||
1068 | for (i = 0; i < card->num_links; i++) { | 1058 | for (i = 0; i < card->num_rtd; i++) { |
1069 | struct snd_soc_dai *cpu_dai = card->dai_link[i].cpu_dai; | 1059 | struct snd_soc_dai *cpu_dai = card->rtd[i].cpu_dai; |
1060 | struct snd_soc_platform *platform = card->rtd[i].platform; | ||
1070 | 1061 | ||
1071 | if (card->dai_link[i].ignore_suspend) | 1062 | if (card->rtd[i].dai_link->ignore_suspend) |
1072 | continue; | 1063 | continue; |
1073 | 1064 | ||
1074 | if (cpu_dai->resume && !cpu_dai->ac97_control) | 1065 | if (cpu_dai->driver->resume && !cpu_dai->driver->ac97_control) |
1075 | cpu_dai->resume(cpu_dai); | 1066 | cpu_dai->driver->resume(cpu_dai); |
1076 | if (platform->resume) | 1067 | if (platform->driver->resume && platform->suspended) { |
1077 | platform->resume(&card->dai_link[i]); | 1068 | platform->driver->resume(cpu_dai); |
1069 | platform->suspended = 0; | ||
1070 | } | ||
1078 | } | 1071 | } |
1079 | 1072 | ||
1080 | if (card->resume_post) | 1073 | if (card->resume_post) |
1081 | card->resume_post(pdev); | 1074 | card->resume_post(pdev); |
1082 | 1075 | ||
1083 | dev_dbg(socdev->dev, "resume work completed\n"); | 1076 | dev_dbg(card->dev, "resume work completed\n"); |
1084 | 1077 | ||
1085 | /* userspace can access us now we are back as we were before */ | 1078 | /* userspace can access us now we are back as we were before */ |
1086 | snd_power_change_state(codec->card, SNDRV_CTL_POWER_D0); | 1079 | snd_power_change_state(card->snd_card, SNDRV_CTL_POWER_D0); |
1087 | } | 1080 | } |
1088 | 1081 | ||
1089 | /* powers up audio subsystem after a suspend */ | 1082 | /* powers up audio subsystem after a suspend */ |
1090 | static int soc_resume(struct device *dev) | 1083 | static int soc_resume(struct device *dev) |
1091 | { | 1084 | { |
1092 | struct platform_device *pdev = to_platform_device(dev); | 1085 | struct platform_device *pdev = to_platform_device(dev); |
1093 | struct snd_soc_device *socdev = platform_get_drvdata(pdev); | 1086 | struct snd_soc_card *card = platform_get_drvdata(pdev); |
1094 | struct snd_soc_card *card = socdev->card; | 1087 | int i; |
1095 | struct snd_soc_dai *cpu_dai = card->dai_link[0].cpu_dai; | ||
1096 | |||
1097 | /* If the initialization of this soc device failed, there is no codec | ||
1098 | * associated with it. Just bail out in this case. | ||
1099 | */ | ||
1100 | if (!card->codec) | ||
1101 | return 0; | ||
1102 | 1088 | ||
1103 | /* AC97 devices might have other drivers hanging off them so | 1089 | /* AC97 devices might have other drivers hanging off them so |
1104 | * need to resume immediately. Other drivers don't have that | 1090 | * need to resume immediately. Other drivers don't have that |
1105 | * problem and may take a substantial amount of time to resume | 1091 | * problem and may take a substantial amount of time to resume |
1106 | * due to I/O costs and anti-pop so handle them out of line. | 1092 | * due to I/O costs and anti-pop so handle them out of line. |
1107 | */ | 1093 | */ |
1108 | if (cpu_dai->ac97_control) { | 1094 | for (i = 0; i < card->num_rtd; i++) { |
1109 | dev_dbg(socdev->dev, "Resuming AC97 immediately\n"); | 1095 | struct snd_soc_dai *cpu_dai = card->rtd[i].cpu_dai; |
1110 | soc_resume_deferred(&card->deferred_resume_work); | 1096 | if (cpu_dai->driver->ac97_control) { |
1111 | } else { | 1097 | dev_dbg(dev, "Resuming AC97 immediately\n"); |
1112 | dev_dbg(socdev->dev, "Scheduling resume work\n"); | 1098 | soc_resume_deferred(&card->deferred_resume_work); |
1113 | if (!schedule_work(&card->deferred_resume_work)) | 1099 | } else { |
1114 | dev_err(socdev->dev, "resume work item may be lost\n"); | 1100 | dev_dbg(dev, "Scheduling resume work\n"); |
1101 | if (!schedule_work(&card->deferred_resume_work)) | ||
1102 | dev_err(dev, "resume work item may be lost\n"); | ||
1103 | } | ||
1115 | } | 1104 | } |
1116 | 1105 | ||
1117 | return 0; | 1106 | return 0; |
@@ -1124,198 +1113,429 @@ static int soc_resume(struct device *dev) | |||
1124 | static struct snd_soc_dai_ops null_dai_ops = { | 1113 | static struct snd_soc_dai_ops null_dai_ops = { |
1125 | }; | 1114 | }; |
1126 | 1115 | ||
1127 | static void snd_soc_instantiate_card(struct snd_soc_card *card) | 1116 | static int soc_bind_dai_link(struct snd_soc_card *card, int num) |
1128 | { | 1117 | { |
1129 | struct platform_device *pdev = container_of(card->dev, | 1118 | struct snd_soc_dai_link *dai_link = &card->dai_link[num]; |
1130 | struct platform_device, | 1119 | struct snd_soc_pcm_runtime *rtd = &card->rtd[num]; |
1131 | dev); | ||
1132 | struct snd_soc_codec_device *codec_dev = card->socdev->codec_dev; | ||
1133 | struct snd_soc_codec *codec; | 1120 | struct snd_soc_codec *codec; |
1134 | struct snd_soc_platform *platform; | 1121 | struct snd_soc_platform *platform; |
1135 | struct snd_soc_dai *dai; | 1122 | struct snd_soc_dai *codec_dai, *cpu_dai; |
1136 | int i, found, ret, ac97; | ||
1137 | 1123 | ||
1138 | if (card->instantiated) | 1124 | if (rtd->complete) |
1139 | return; | 1125 | return 1; |
1126 | dev_dbg(card->dev, "binding %s at idx %d\n", dai_link->name, num); | ||
1140 | 1127 | ||
1141 | found = 0; | 1128 | /* do we already have the CPU DAI for this link ? */ |
1142 | list_for_each_entry(platform, &platform_list, list) | 1129 | if (rtd->cpu_dai) { |
1143 | if (card->platform == platform) { | 1130 | goto find_codec; |
1144 | found = 1; | 1131 | } |
1145 | break; | 1132 | /* no, then find CPU DAI from registered DAIs*/ |
1133 | list_for_each_entry(cpu_dai, &dai_list, list) { | ||
1134 | if (!strcmp(cpu_dai->name, dai_link->cpu_dai_name)) { | ||
1135 | |||
1136 | if (!try_module_get(cpu_dai->dev->driver->owner)) | ||
1137 | return -ENODEV; | ||
1138 | |||
1139 | rtd->cpu_dai = cpu_dai; | ||
1140 | goto find_codec; | ||
1146 | } | 1141 | } |
1147 | if (!found) { | ||
1148 | dev_dbg(card->dev, "Platform %s not registered\n", | ||
1149 | card->platform->name); | ||
1150 | return; | ||
1151 | } | 1142 | } |
1143 | dev_dbg(card->dev, "CPU DAI %s not registered\n", | ||
1144 | dai_link->cpu_dai_name); | ||
1152 | 1145 | ||
1153 | ac97 = 0; | 1146 | find_codec: |
1154 | for (i = 0; i < card->num_links; i++) { | 1147 | /* do we already have the CODEC for this link ? */ |
1155 | found = 0; | 1148 | if (rtd->codec) { |
1156 | list_for_each_entry(dai, &dai_list, list) | 1149 | goto find_platform; |
1157 | if (card->dai_link[i].cpu_dai == dai) { | 1150 | } |
1158 | found = 1; | 1151 | |
1159 | break; | 1152 | /* no, then find CODEC from registered CODECs*/ |
1153 | list_for_each_entry(codec, &codec_list, list) { | ||
1154 | if (!strcmp(codec->name, dai_link->codec_name)) { | ||
1155 | rtd->codec = codec; | ||
1156 | |||
1157 | if (!try_module_get(codec->dev->driver->owner)) | ||
1158 | return -ENODEV; | ||
1159 | |||
1160 | /* CODEC found, so find CODEC DAI from registered DAIs from this CODEC*/ | ||
1161 | list_for_each_entry(codec_dai, &dai_list, list) { | ||
1162 | if (codec->dev == codec_dai->dev && | ||
1163 | !strcmp(codec_dai->name, dai_link->codec_dai_name)) { | ||
1164 | rtd->codec_dai = codec_dai; | ||
1165 | goto find_platform; | ||
1166 | } | ||
1160 | } | 1167 | } |
1161 | if (!found) { | 1168 | dev_dbg(card->dev, "CODEC DAI %s not registered\n", |
1162 | dev_dbg(card->dev, "DAI %s not registered\n", | 1169 | dai_link->codec_dai_name); |
1163 | card->dai_link[i].cpu_dai->name); | 1170 | |
1164 | return; | 1171 | goto find_platform; |
1165 | } | 1172 | } |
1173 | } | ||
1174 | dev_dbg(card->dev, "CODEC %s not registered\n", | ||
1175 | dai_link->codec_name); | ||
1166 | 1176 | ||
1167 | if (card->dai_link[i].cpu_dai->ac97_control) | 1177 | find_platform: |
1168 | ac97 = 1; | 1178 | /* do we already have the CODEC DAI for this link ? */ |
1179 | if (rtd->platform) { | ||
1180 | goto out; | ||
1169 | } | 1181 | } |
1182 | /* no, then find CPU DAI from registered DAIs*/ | ||
1183 | list_for_each_entry(platform, &platform_list, list) { | ||
1184 | if (!strcmp(platform->name, dai_link->platform_name)) { | ||
1170 | 1185 | ||
1171 | for (i = 0; i < card->num_links; i++) { | 1186 | if (!try_module_get(platform->dev->driver->owner)) |
1172 | if (!card->dai_link[i].codec_dai->ops) | 1187 | return -ENODEV; |
1173 | card->dai_link[i].codec_dai->ops = &null_dai_ops; | 1188 | |
1189 | rtd->platform = platform; | ||
1190 | goto out; | ||
1191 | } | ||
1174 | } | 1192 | } |
1175 | 1193 | ||
1176 | /* If we have AC97 in the system then don't wait for the | 1194 | dev_dbg(card->dev, "platform %s not registered\n", |
1177 | * codec. This will need revisiting if we have to handle | 1195 | dai_link->platform_name); |
1178 | * systems with mixed AC97 and non-AC97 parts. Only check for | 1196 | return 0; |
1179 | * DAIs currently; we can't do this per link since some AC97 | 1197 | |
1180 | * codecs have non-AC97 DAIs. | 1198 | out: |
1181 | */ | 1199 | /* mark rtd as complete if we found all 4 of our client devices */ |
1182 | if (!ac97) | 1200 | if (rtd->codec && rtd->codec_dai && rtd->platform && rtd->cpu_dai) { |
1183 | for (i = 0; i < card->num_links; i++) { | 1201 | rtd->complete = 1; |
1184 | found = 0; | 1202 | card->num_rtd++; |
1185 | list_for_each_entry(dai, &dai_list, list) | 1203 | } |
1186 | if (card->dai_link[i].codec_dai == dai) { | 1204 | return 1; |
1187 | found = 1; | 1205 | } |
1188 | break; | 1206 | |
1189 | } | 1207 | static void soc_remove_dai_link(struct snd_soc_card *card, int num) |
1190 | if (!found) { | 1208 | { |
1191 | dev_dbg(card->dev, "DAI %s not registered\n", | 1209 | struct snd_soc_pcm_runtime *rtd = &card->rtd[num]; |
1192 | card->dai_link[i].codec_dai->name); | 1210 | struct snd_soc_codec *codec = rtd->codec; |
1193 | return; | 1211 | struct snd_soc_platform *platform = rtd->platform; |
1194 | } | 1212 | struct snd_soc_dai *codec_dai = rtd->codec_dai, *cpu_dai = rtd->cpu_dai; |
1213 | int err; | ||
1214 | |||
1215 | /* unregister the rtd device */ | ||
1216 | if (rtd->dev_registered) { | ||
1217 | device_remove_file(&rtd->dev, &dev_attr_pmdown_time); | ||
1218 | device_unregister(&rtd->dev); | ||
1219 | rtd->dev_registered = 0; | ||
1220 | } | ||
1221 | |||
1222 | /* remove the CODEC DAI */ | ||
1223 | if (codec_dai && codec_dai->probed) { | ||
1224 | if (codec_dai->driver->remove) { | ||
1225 | err = codec_dai->driver->remove(codec_dai); | ||
1226 | if (err < 0) | ||
1227 | printk(KERN_ERR "asoc: failed to remove %s\n", codec_dai->name); | ||
1195 | } | 1228 | } |
1229 | codec_dai->probed = 0; | ||
1230 | list_del(&codec_dai->card_list); | ||
1231 | } | ||
1196 | 1232 | ||
1197 | /* Note that we do not current check for codec components */ | 1233 | /* remove the platform */ |
1234 | if (platform && platform->probed) { | ||
1235 | if (platform->driver->remove) { | ||
1236 | err = platform->driver->remove(platform); | ||
1237 | if (err < 0) | ||
1238 | printk(KERN_ERR "asoc: failed to remove %s\n", platform->name); | ||
1239 | } | ||
1240 | platform->probed = 0; | ||
1241 | list_del(&platform->card_list); | ||
1242 | module_put(platform->dev->driver->owner); | ||
1243 | } | ||
1198 | 1244 | ||
1199 | dev_dbg(card->dev, "All components present, instantiating\n"); | 1245 | /* remove the CODEC */ |
1246 | if (codec && codec->probed) { | ||
1247 | if (codec->driver->remove) { | ||
1248 | err = codec->driver->remove(codec); | ||
1249 | if (err < 0) | ||
1250 | printk(KERN_ERR "asoc: failed to remove %s\n", codec->name); | ||
1251 | } | ||
1200 | 1252 | ||
1201 | /* Found everything, bring it up */ | 1253 | /* Make sure all DAPM widgets are freed */ |
1202 | card->pmdown_time = pmdown_time; | 1254 | snd_soc_dapm_free(codec); |
1203 | 1255 | ||
1204 | if (card->probe) { | 1256 | soc_cleanup_codec_debugfs(codec); |
1205 | ret = card->probe(pdev); | 1257 | device_remove_file(&rtd->dev, &dev_attr_codec_reg); |
1206 | if (ret < 0) | 1258 | codec->probed = 0; |
1207 | return; | 1259 | list_del(&codec->card_list); |
1260 | module_put(codec->dev->driver->owner); | ||
1208 | } | 1261 | } |
1209 | 1262 | ||
1210 | for (i = 0; i < card->num_links; i++) { | 1263 | /* remove the cpu_dai */ |
1211 | struct snd_soc_dai *cpu_dai = card->dai_link[i].cpu_dai; | 1264 | if (cpu_dai && cpu_dai->probed) { |
1212 | if (cpu_dai->probe) { | 1265 | if (cpu_dai->driver->remove) { |
1213 | ret = cpu_dai->probe(pdev, cpu_dai); | 1266 | err = cpu_dai->driver->remove(cpu_dai); |
1214 | if (ret < 0) | 1267 | if (err < 0) |
1215 | goto cpu_dai_err; | 1268 | printk(KERN_ERR "asoc: failed to remove %s\n", cpu_dai->name); |
1216 | } | 1269 | } |
1270 | cpu_dai->probed = 0; | ||
1271 | list_del(&cpu_dai->card_list); | ||
1272 | module_put(cpu_dai->dev->driver->owner); | ||
1217 | } | 1273 | } |
1274 | } | ||
1218 | 1275 | ||
1219 | if (codec_dev->probe) { | 1276 | static void rtd_release(struct device *dev) {} |
1220 | ret = codec_dev->probe(pdev); | 1277 | |
1221 | if (ret < 0) | 1278 | static int soc_probe_dai_link(struct snd_soc_card *card, int num) |
1222 | goto cpu_dai_err; | 1279 | { |
1280 | struct snd_soc_dai_link *dai_link = &card->dai_link[num]; | ||
1281 | struct snd_soc_pcm_runtime *rtd = &card->rtd[num]; | ||
1282 | struct snd_soc_codec *codec = rtd->codec; | ||
1283 | struct snd_soc_platform *platform = rtd->platform; | ||
1284 | struct snd_soc_dai *codec_dai = rtd->codec_dai, *cpu_dai = rtd->cpu_dai; | ||
1285 | int ret; | ||
1286 | |||
1287 | dev_dbg(card->dev, "probe %s dai link %d\n", card->name, num); | ||
1288 | |||
1289 | /* config components */ | ||
1290 | codec_dai->codec = codec; | ||
1291 | codec->card = card; | ||
1292 | cpu_dai->platform = platform; | ||
1293 | rtd->card = card; | ||
1294 | rtd->dev.parent = card->dev; | ||
1295 | codec_dai->card = card; | ||
1296 | cpu_dai->card = card; | ||
1297 | |||
1298 | /* set default power off timeout */ | ||
1299 | rtd->pmdown_time = pmdown_time; | ||
1300 | |||
1301 | /* probe the cpu_dai */ | ||
1302 | if (!cpu_dai->probed) { | ||
1303 | if (cpu_dai->driver->probe) { | ||
1304 | ret = cpu_dai->driver->probe(cpu_dai); | ||
1305 | if (ret < 0) { | ||
1306 | printk(KERN_ERR "asoc: failed to probe CPU DAI %s\n", | ||
1307 | cpu_dai->name); | ||
1308 | return ret; | ||
1309 | } | ||
1310 | } | ||
1311 | cpu_dai->probed = 1; | ||
1312 | /* mark cpu_dai as probed and add to card cpu_dai list */ | ||
1313 | list_add(&cpu_dai->card_list, &card->dai_dev_list); | ||
1223 | } | 1314 | } |
1224 | codec = card->codec; | ||
1225 | 1315 | ||
1226 | if (platform->probe) { | 1316 | /* probe the CODEC */ |
1227 | ret = platform->probe(pdev); | 1317 | if (!codec->probed) { |
1228 | if (ret < 0) | 1318 | if (codec->driver->probe) { |
1229 | goto platform_err; | 1319 | ret = codec->driver->probe(codec); |
1320 | if (ret < 0) { | ||
1321 | printk(KERN_ERR "asoc: failed to probe CODEC %s\n", | ||
1322 | codec->name); | ||
1323 | return ret; | ||
1324 | } | ||
1325 | } | ||
1326 | /* mark codec as probed and add to card codec list */ | ||
1327 | codec->probed = 1; | ||
1328 | list_add(&codec->card_list, &card->codec_dev_list); | ||
1230 | } | 1329 | } |
1231 | 1330 | ||
1232 | /* DAPM stream work */ | 1331 | /* probe the platform */ |
1233 | INIT_DELAYED_WORK(&card->delayed_work, close_delayed_work); | 1332 | if (!platform->probed) { |
1234 | #ifdef CONFIG_PM | 1333 | if (platform->driver->probe) { |
1235 | /* deferred resume work */ | 1334 | ret = platform->driver->probe(platform); |
1236 | INIT_WORK(&card->deferred_resume_work, soc_resume_deferred); | 1335 | if (ret < 0) { |
1237 | #endif | 1336 | printk(KERN_ERR "asoc: failed to probe platform %s\n", |
1337 | platform->name); | ||
1338 | return ret; | ||
1339 | } | ||
1340 | } | ||
1341 | /* mark platform as probed and add to card platform list */ | ||
1342 | platform->probed = 1; | ||
1343 | list_add(&platform->card_list, &card->platform_dev_list); | ||
1344 | } | ||
1238 | 1345 | ||
1239 | for (i = 0; i < card->num_links; i++) { | 1346 | /* probe the CODEC DAI */ |
1240 | if (card->dai_link[i].init) { | 1347 | if (!codec_dai->probed) { |
1241 | ret = card->dai_link[i].init(codec); | 1348 | if (codec_dai->driver->probe) { |
1349 | ret = codec_dai->driver->probe(codec_dai); | ||
1242 | if (ret < 0) { | 1350 | if (ret < 0) { |
1243 | printk(KERN_ERR "asoc: failed to init %s\n", | 1351 | printk(KERN_ERR "asoc: failed to probe CODEC DAI %s\n", |
1244 | card->dai_link[i].stream_name); | 1352 | codec_dai->name); |
1245 | continue; | 1353 | return ret; |
1246 | } | 1354 | } |
1247 | } | 1355 | } |
1248 | if (card->dai_link[i].codec_dai->ac97_control) | 1356 | |
1249 | ac97 = 1; | 1357 | /* mark cpu_dai as probed and add to card cpu_dai list */ |
1358 | codec_dai->probed = 1; | ||
1359 | list_add(&codec_dai->card_list, &card->dai_dev_list); | ||
1250 | } | 1360 | } |
1251 | 1361 | ||
1252 | snprintf(codec->card->shortname, sizeof(codec->card->shortname), | 1362 | /* DAPM dai link stream work */ |
1253 | "%s", card->name); | 1363 | INIT_DELAYED_WORK(&rtd->delayed_work, close_delayed_work); |
1254 | snprintf(codec->card->longname, sizeof(codec->card->longname), | 1364 | |
1255 | "%s (%s)", card->name, codec->name); | 1365 | /* now that all clients have probed, initialise the DAI link */ |
1366 | if (dai_link->init) { | ||
1367 | ret = dai_link->init(rtd); | ||
1368 | if (ret < 0) { | ||
1369 | printk(KERN_ERR "asoc: failed to init %s\n", dai_link->stream_name); | ||
1370 | return ret; | ||
1371 | } | ||
1372 | } | ||
1256 | 1373 | ||
1257 | /* Make sure all DAPM widgets are instantiated */ | 1374 | /* Make sure all DAPM widgets are instantiated */ |
1258 | snd_soc_dapm_new_widgets(codec); | 1375 | snd_soc_dapm_new_widgets(codec); |
1376 | snd_soc_dapm_sync(codec); | ||
1259 | 1377 | ||
1260 | ret = snd_card_register(codec->card); | 1378 | /* register the rtd device */ |
1379 | rtd->dev.init_name = rtd->dai_link->stream_name; | ||
1380 | rtd->dev.release = rtd_release; | ||
1381 | rtd->dev.init_name = dai_link->name; | ||
1382 | ret = device_register(&rtd->dev); | ||
1261 | if (ret < 0) { | 1383 | if (ret < 0) { |
1262 | printk(KERN_ERR "asoc: failed to register soundcard for %s\n", | 1384 | printk(KERN_ERR "asoc: failed to register DAI runtime device %d\n", ret); |
1263 | codec->name); | 1385 | return ret; |
1264 | goto card_err; | ||
1265 | } | 1386 | } |
1266 | 1387 | ||
1267 | mutex_lock(&codec->mutex); | 1388 | rtd->dev_registered = 1; |
1389 | ret = device_create_file(&rtd->dev, &dev_attr_pmdown_time); | ||
1390 | if (ret < 0) | ||
1391 | printk(KERN_WARNING "asoc: failed to add pmdown_time sysfs\n"); | ||
1392 | |||
1393 | /* add DAPM sysfs entries for this codec */ | ||
1394 | ret = snd_soc_dapm_sys_add(&rtd->dev); | ||
1395 | if (ret < 0) | ||
1396 | printk(KERN_WARNING "asoc: failed to add codec dapm sysfs entries\n"); | ||
1397 | |||
1398 | /* add codec sysfs entries */ | ||
1399 | ret = device_create_file(&rtd->dev, &dev_attr_codec_reg); | ||
1400 | if (ret < 0) | ||
1401 | printk(KERN_WARNING "asoc: failed to add codec sysfs files\n"); | ||
1402 | |||
1403 | soc_init_codec_debugfs(codec); | ||
1404 | |||
1405 | /* create the pcm */ | ||
1406 | ret = soc_new_pcm(rtd, num); | ||
1407 | if (ret < 0) { | ||
1408 | printk(KERN_ERR "asoc: can't create pcm %s\n", dai_link->stream_name); | ||
1409 | return ret; | ||
1410 | } | ||
1411 | |||
1412 | /* add platform data for AC97 devices */ | ||
1413 | if (rtd->codec_dai->driver->ac97_control) | ||
1414 | snd_ac97_dev_add_pdata(codec->ac97, rtd->cpu_dai->ac97_pdata); | ||
1415 | |||
1416 | return 0; | ||
1417 | } | ||
1418 | |||
1268 | #ifdef CONFIG_SND_SOC_AC97_BUS | 1419 | #ifdef CONFIG_SND_SOC_AC97_BUS |
1420 | static int soc_register_ac97_dai_link(struct snd_soc_pcm_runtime *rtd) | ||
1421 | { | ||
1422 | int ret; | ||
1423 | |||
1269 | /* Only instantiate AC97 if not already done by the adaptor | 1424 | /* Only instantiate AC97 if not already done by the adaptor |
1270 | * for the generic AC97 subsystem. | 1425 | * for the generic AC97 subsystem. |
1271 | */ | 1426 | */ |
1272 | if (ac97 && strcmp(codec->name, "AC97") != 0) { | 1427 | if (rtd->codec_dai->driver->ac97_control && !rtd->codec->ac97_registered) { |
1273 | ret = soc_ac97_dev_register(codec); | 1428 | |
1429 | ret = soc_ac97_dev_register(rtd->codec); | ||
1274 | if (ret < 0) { | 1430 | if (ret < 0) { |
1275 | printk(KERN_ERR "asoc: AC97 device register failed\n"); | 1431 | printk(KERN_ERR "asoc: AC97 device register failed\n"); |
1276 | snd_card_free(codec->card); | 1432 | return ret; |
1277 | mutex_unlock(&codec->mutex); | ||
1278 | goto card_err; | ||
1279 | } | 1433 | } |
1434 | |||
1435 | rtd->codec->ac97_registered = 1; | ||
1280 | } | 1436 | } |
1437 | return 0; | ||
1438 | } | ||
1439 | |||
1440 | static void soc_unregister_ac97_dai_link(struct snd_soc_codec *codec) | ||
1441 | { | ||
1442 | if (codec->ac97_registered) { | ||
1443 | soc_ac97_dev_unregister(codec); | ||
1444 | codec->ac97_registered = 0; | ||
1445 | } | ||
1446 | } | ||
1281 | #endif | 1447 | #endif |
1282 | 1448 | ||
1283 | ret = snd_soc_dapm_sys_add(card->socdev->dev); | 1449 | static void snd_soc_instantiate_card(struct snd_soc_card *card) |
1284 | if (ret < 0) | 1450 | { |
1285 | printk(KERN_WARNING "asoc: failed to add dapm sysfs entries\n"); | 1451 | struct platform_device *pdev = to_platform_device(card->dev); |
1452 | int ret, i; | ||
1286 | 1453 | ||
1287 | ret = device_create_file(card->socdev->dev, &dev_attr_pmdown_time); | 1454 | mutex_lock(&card->mutex); |
1288 | if (ret < 0) | ||
1289 | printk(KERN_WARNING "asoc: failed to add pmdown_time sysfs\n"); | ||
1290 | 1455 | ||
1291 | ret = device_create_file(card->socdev->dev, &dev_attr_codec_reg); | 1456 | if (card->instantiated) { |
1292 | if (ret < 0) | 1457 | mutex_unlock(&card->mutex); |
1293 | printk(KERN_WARNING "asoc: failed to add codec sysfs files\n"); | 1458 | return; |
1459 | } | ||
1294 | 1460 | ||
1295 | soc_init_codec_debugfs(codec); | 1461 | /* bind DAIs */ |
1296 | mutex_unlock(&codec->mutex); | 1462 | for (i = 0; i < card->num_links; i++) |
1463 | soc_bind_dai_link(card, i); | ||
1297 | 1464 | ||
1298 | card->instantiated = 1; | 1465 | /* bind completed ? */ |
1466 | if (card->num_rtd != card->num_links) { | ||
1467 | mutex_unlock(&card->mutex); | ||
1468 | return; | ||
1469 | } | ||
1299 | 1470 | ||
1300 | return; | 1471 | /* card bind complete so register a sound card */ |
1472 | ret = snd_card_create(SNDRV_DEFAULT_IDX1, SNDRV_DEFAULT_STR1, | ||
1473 | card->owner, 0, &card->snd_card); | ||
1474 | if (ret < 0) { | ||
1475 | printk(KERN_ERR "asoc: can't create sound card for card %s\n", | ||
1476 | card->name); | ||
1477 | mutex_unlock(&card->mutex); | ||
1478 | return; | ||
1479 | } | ||
1480 | card->snd_card->dev = card->dev; | ||
1481 | |||
1482 | #ifdef CONFIG_PM | ||
1483 | /* deferred resume work */ | ||
1484 | INIT_WORK(&card->deferred_resume_work, soc_resume_deferred); | ||
1485 | #endif | ||
1301 | 1486 | ||
1302 | card_err: | 1487 | /* initialise the sound card only once */ |
1303 | if (platform->remove) | 1488 | if (card->probe) { |
1304 | platform->remove(pdev); | 1489 | ret = card->probe(pdev); |
1490 | if (ret < 0) | ||
1491 | goto card_probe_error; | ||
1492 | } | ||
1305 | 1493 | ||
1306 | platform_err: | 1494 | for (i = 0; i < card->num_links; i++) { |
1307 | if (codec_dev->remove) | 1495 | ret = soc_probe_dai_link(card, i); |
1308 | codec_dev->remove(pdev); | 1496 | if (ret < 0) { |
1497 | printk(KERN_ERR "asoc: failed to instanciate card %s\n", card->name); | ||
1498 | goto probe_dai_err; | ||
1499 | } | ||
1500 | } | ||
1309 | 1501 | ||
1310 | cpu_dai_err: | 1502 | snprintf(card->snd_card->shortname, sizeof(card->snd_card->shortname), |
1311 | for (i--; i >= 0; i--) { | 1503 | "%s", card->name); |
1312 | struct snd_soc_dai *cpu_dai = card->dai_link[i].cpu_dai; | 1504 | snprintf(card->snd_card->longname, sizeof(card->snd_card->longname), |
1313 | if (cpu_dai->remove) | 1505 | "%s", card->name); |
1314 | cpu_dai->remove(pdev, cpu_dai); | 1506 | |
1507 | ret = snd_card_register(card->snd_card); | ||
1508 | if (ret < 0) { | ||
1509 | printk(KERN_ERR "asoc: failed to register soundcard for %s\n", card->name); | ||
1510 | goto probe_dai_err; | ||
1315 | } | 1511 | } |
1316 | 1512 | ||
1513 | #ifdef CONFIG_SND_SOC_AC97_BUS | ||
1514 | /* register any AC97 codecs */ | ||
1515 | for (i = 0; i < card->num_rtd; i++) { | ||
1516 | ret = soc_register_ac97_dai_link(&card->rtd[i]); | ||
1517 | if (ret < 0) { | ||
1518 | printk(KERN_ERR "asoc: failed to register AC97 %s\n", card->name); | ||
1519 | goto probe_dai_err; | ||
1520 | } | ||
1521 | } | ||
1522 | #endif | ||
1523 | |||
1524 | card->instantiated = 1; | ||
1525 | mutex_unlock(&card->mutex); | ||
1526 | return; | ||
1527 | |||
1528 | probe_dai_err: | ||
1529 | for (i = 0; i < card->num_links; i++) | ||
1530 | soc_remove_dai_link(card, i); | ||
1531 | |||
1532 | card_probe_error: | ||
1317 | if (card->remove) | 1533 | if (card->remove) |
1318 | card->remove(pdev); | 1534 | card->remove(pdev); |
1535 | |||
1536 | snd_card_free(card->snd_card); | ||
1537 | |||
1538 | mutex_unlock(&card->mutex); | ||
1319 | } | 1539 | } |
1320 | 1540 | ||
1321 | /* | 1541 | /* |
@@ -1332,15 +1552,15 @@ static void snd_soc_instantiate_cards(void) | |||
1332 | /* probes a new socdev */ | 1552 | /* probes a new socdev */ |
1333 | static int soc_probe(struct platform_device *pdev) | 1553 | static int soc_probe(struct platform_device *pdev) |
1334 | { | 1554 | { |
1555 | struct snd_soc_card *card = platform_get_drvdata(pdev); | ||
1335 | int ret = 0; | 1556 | int ret = 0; |
1336 | struct snd_soc_device *socdev = platform_get_drvdata(pdev); | ||
1337 | struct snd_soc_card *card = socdev->card; | ||
1338 | |||
1339 | /* Bodge while we push things out of socdev */ | ||
1340 | card->socdev = socdev; | ||
1341 | 1557 | ||
1342 | /* Bodge while we unpick instantiation */ | 1558 | /* Bodge while we unpick instantiation */ |
1343 | card->dev = &pdev->dev; | 1559 | card->dev = &pdev->dev; |
1560 | INIT_LIST_HEAD(&card->dai_dev_list); | ||
1561 | INIT_LIST_HEAD(&card->codec_dev_list); | ||
1562 | INIT_LIST_HEAD(&card->platform_dev_list); | ||
1563 | |||
1344 | ret = snd_soc_register_card(card); | 1564 | ret = snd_soc_register_card(card); |
1345 | if (ret != 0) { | 1565 | if (ret != 0) { |
1346 | dev_err(&pdev->dev, "Failed to register card\n"); | 1566 | dev_err(&pdev->dev, "Failed to register card\n"); |
@@ -1353,50 +1573,49 @@ static int soc_probe(struct platform_device *pdev) | |||
1353 | /* removes a socdev */ | 1573 | /* removes a socdev */ |
1354 | static int soc_remove(struct platform_device *pdev) | 1574 | static int soc_remove(struct platform_device *pdev) |
1355 | { | 1575 | { |
1576 | struct snd_soc_card *card = platform_get_drvdata(pdev); | ||
1356 | int i; | 1577 | int i; |
1357 | struct snd_soc_device *socdev = platform_get_drvdata(pdev); | ||
1358 | struct snd_soc_card *card = socdev->card; | ||
1359 | struct snd_soc_platform *platform = card->platform; | ||
1360 | struct snd_soc_codec_device *codec_dev = socdev->codec_dev; | ||
1361 | 1578 | ||
1362 | if (card->instantiated) { | 1579 | if (card->instantiated) { |
1363 | run_delayed_work(&card->delayed_work); | ||
1364 | 1580 | ||
1365 | if (platform->remove) | 1581 | /* make sure any delayed work runs */ |
1366 | platform->remove(pdev); | 1582 | for (i = 0; i < card->num_rtd; i++) { |
1367 | 1583 | struct snd_soc_pcm_runtime *rtd = &card->rtd[i]; | |
1368 | if (codec_dev->remove) | 1584 | run_delayed_work(&rtd->delayed_work); |
1369 | codec_dev->remove(pdev); | ||
1370 | |||
1371 | for (i = 0; i < card->num_links; i++) { | ||
1372 | struct snd_soc_dai *cpu_dai = card->dai_link[i].cpu_dai; | ||
1373 | if (cpu_dai->remove) | ||
1374 | cpu_dai->remove(pdev, cpu_dai); | ||
1375 | } | 1585 | } |
1376 | 1586 | ||
1587 | /* remove and free each DAI */ | ||
1588 | for (i = 0; i < card->num_rtd; i++) | ||
1589 | soc_remove_dai_link(card, i); | ||
1590 | |||
1591 | /* remove the card */ | ||
1377 | if (card->remove) | 1592 | if (card->remove) |
1378 | card->remove(pdev); | 1593 | card->remove(pdev); |
1379 | } | ||
1380 | 1594 | ||
1595 | kfree(card->rtd); | ||
1596 | snd_card_free(card->snd_card); | ||
1597 | } | ||
1381 | snd_soc_unregister_card(card); | 1598 | snd_soc_unregister_card(card); |
1382 | |||
1383 | return 0; | 1599 | return 0; |
1384 | } | 1600 | } |
1385 | 1601 | ||
1386 | static int soc_poweroff(struct device *dev) | 1602 | static int soc_poweroff(struct device *dev) |
1387 | { | 1603 | { |
1388 | struct platform_device *pdev = to_platform_device(dev); | 1604 | struct platform_device *pdev = to_platform_device(dev); |
1389 | struct snd_soc_device *socdev = platform_get_drvdata(pdev); | 1605 | struct snd_soc_card *card = platform_get_drvdata(pdev); |
1390 | struct snd_soc_card *card = socdev->card; | 1606 | int i; |
1391 | 1607 | ||
1392 | if (!card->instantiated) | 1608 | if (!card->instantiated) |
1393 | return 0; | 1609 | return 0; |
1394 | 1610 | ||
1395 | /* Flush out pmdown_time work - we actually do want to run it | 1611 | /* Flush out pmdown_time work - we actually do want to run it |
1396 | * now, we're shutting down so no imminent restart. */ | 1612 | * now, we're shutting down so no imminent restart. */ |
1397 | run_delayed_work(&card->delayed_work); | 1613 | for (i = 0; i < card->num_rtd; i++) { |
1614 | struct snd_soc_pcm_runtime *rtd = &card->rtd[i]; | ||
1615 | run_delayed_work(&rtd->delayed_work); | ||
1616 | } | ||
1398 | 1617 | ||
1399 | snd_soc_dapm_shutdown(socdev); | 1618 | snd_soc_dapm_shutdown(card); |
1400 | 1619 | ||
1401 | return 0; | 1620 | return 0; |
1402 | } | 1621 | } |
@@ -1419,53 +1638,42 @@ static struct platform_driver soc_driver = { | |||
1419 | }; | 1638 | }; |
1420 | 1639 | ||
1421 | /* create a new pcm */ | 1640 | /* create a new pcm */ |
1422 | static int soc_new_pcm(struct snd_soc_device *socdev, | 1641 | static int soc_new_pcm(struct snd_soc_pcm_runtime *rtd, int num) |
1423 | struct snd_soc_dai_link *dai_link, int num) | 1642 | { |
1424 | { | 1643 | struct snd_soc_codec *codec = rtd->codec; |
1425 | struct snd_soc_card *card = socdev->card; | 1644 | struct snd_soc_platform *platform = rtd->platform; |
1426 | struct snd_soc_codec *codec = card->codec; | 1645 | struct snd_soc_dai *codec_dai = rtd->codec_dai; |
1427 | struct snd_soc_platform *platform = card->platform; | 1646 | struct snd_soc_dai *cpu_dai = rtd->cpu_dai; |
1428 | struct snd_soc_dai *codec_dai = dai_link->codec_dai; | ||
1429 | struct snd_soc_dai *cpu_dai = dai_link->cpu_dai; | ||
1430 | struct snd_soc_pcm_runtime *rtd; | ||
1431 | struct snd_pcm *pcm; | 1647 | struct snd_pcm *pcm; |
1432 | char new_name[64]; | 1648 | char new_name[64]; |
1433 | int ret = 0, playback = 0, capture = 0; | 1649 | int ret = 0, playback = 0, capture = 0; |
1434 | 1650 | ||
1435 | rtd = kzalloc(sizeof(struct snd_soc_pcm_runtime), GFP_KERNEL); | ||
1436 | if (rtd == NULL) | ||
1437 | return -ENOMEM; | ||
1438 | |||
1439 | rtd->dai = dai_link; | ||
1440 | rtd->socdev = socdev; | ||
1441 | codec_dai->codec = card->codec; | ||
1442 | |||
1443 | /* check client and interface hw capabilities */ | 1651 | /* check client and interface hw capabilities */ |
1444 | snprintf(new_name, sizeof(new_name), "%s %s-%d", | 1652 | snprintf(new_name, sizeof(new_name), "%s %s-%d", |
1445 | dai_link->stream_name, codec_dai->name, num); | 1653 | rtd->dai_link->stream_name, codec_dai->name, num); |
1446 | 1654 | ||
1447 | if (codec_dai->playback.channels_min) | 1655 | if (codec_dai->driver->playback.channels_min) |
1448 | playback = 1; | 1656 | playback = 1; |
1449 | if (codec_dai->capture.channels_min) | 1657 | if (codec_dai->driver->capture.channels_min) |
1450 | capture = 1; | 1658 | capture = 1; |
1451 | 1659 | ||
1452 | ret = snd_pcm_new(codec->card, new_name, codec->pcm_devs++, playback, | 1660 | dev_dbg(rtd->card->dev, "registered pcm #%d %s\n",num,new_name); |
1453 | capture, &pcm); | 1661 | ret = snd_pcm_new(rtd->card->snd_card, new_name, |
1662 | num, playback, capture, &pcm); | ||
1454 | if (ret < 0) { | 1663 | if (ret < 0) { |
1455 | printk(KERN_ERR "asoc: can't create pcm for codec %s\n", | 1664 | printk(KERN_ERR "asoc: can't create pcm for codec %s\n", codec->name); |
1456 | codec->name); | ||
1457 | kfree(rtd); | ||
1458 | return ret; | 1665 | return ret; |
1459 | } | 1666 | } |
1460 | 1667 | ||
1461 | dai_link->pcm = pcm; | 1668 | rtd->pcm = pcm; |
1462 | pcm->private_data = rtd; | 1669 | pcm->private_data = rtd; |
1463 | soc_pcm_ops.mmap = platform->pcm_ops->mmap; | 1670 | soc_pcm_ops.mmap = platform->driver->ops->mmap; |
1464 | soc_pcm_ops.ioctl = platform->pcm_ops->ioctl; | 1671 | soc_pcm_ops.pointer = platform->driver->ops->pointer; |
1465 | soc_pcm_ops.copy = platform->pcm_ops->copy; | 1672 | soc_pcm_ops.ioctl = platform->driver->ops->ioctl; |
1466 | soc_pcm_ops.silence = platform->pcm_ops->silence; | 1673 | soc_pcm_ops.copy = platform->driver->ops->copy; |
1467 | soc_pcm_ops.ack = platform->pcm_ops->ack; | 1674 | soc_pcm_ops.silence = platform->driver->ops->silence; |
1468 | soc_pcm_ops.page = platform->pcm_ops->page; | 1675 | soc_pcm_ops.ack = platform->driver->ops->ack; |
1676 | soc_pcm_ops.page = platform->driver->ops->page; | ||
1469 | 1677 | ||
1470 | if (playback) | 1678 | if (playback) |
1471 | snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_PLAYBACK, &soc_pcm_ops); | 1679 | snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_PLAYBACK, &soc_pcm_ops); |
@@ -1473,14 +1681,13 @@ static int soc_new_pcm(struct snd_soc_device *socdev, | |||
1473 | if (capture) | 1681 | if (capture) |
1474 | snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_CAPTURE, &soc_pcm_ops); | 1682 | snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_CAPTURE, &soc_pcm_ops); |
1475 | 1683 | ||
1476 | ret = platform->pcm_new(codec->card, codec_dai, pcm); | 1684 | ret = platform->driver->pcm_new(rtd->card->snd_card, codec_dai, pcm); |
1477 | if (ret < 0) { | 1685 | if (ret < 0) { |
1478 | printk(KERN_ERR "asoc: platform pcm constructor failed\n"); | 1686 | printk(KERN_ERR "asoc: platform pcm constructor failed\n"); |
1479 | kfree(rtd); | ||
1480 | return ret; | 1687 | return ret; |
1481 | } | 1688 | } |
1482 | 1689 | ||
1483 | pcm->private_free = platform->pcm_free; | 1690 | pcm->private_free = platform->driver->pcm_free; |
1484 | printk(KERN_INFO "asoc: %s <-> %s mapping ok\n", codec_dai->name, | 1691 | printk(KERN_INFO "asoc: %s <-> %s mapping ok\n", codec_dai->name, |
1485 | cpu_dai->name); | 1692 | cpu_dai->name); |
1486 | return ret; | 1693 | return ret; |
@@ -1496,8 +1703,8 @@ static int soc_new_pcm(struct snd_soc_device *socdev, | |||
1496 | */ | 1703 | */ |
1497 | int snd_soc_codec_volatile_register(struct snd_soc_codec *codec, int reg) | 1704 | int snd_soc_codec_volatile_register(struct snd_soc_codec *codec, int reg) |
1498 | { | 1705 | { |
1499 | if (codec->volatile_register) | 1706 | if (codec->driver->volatile_register) |
1500 | return codec->volatile_register(reg); | 1707 | return codec->driver->volatile_register(reg); |
1501 | else | 1708 | else |
1502 | return 0; | 1709 | return 0; |
1503 | } | 1710 | } |
@@ -1532,7 +1739,6 @@ int snd_soc_new_ac97_codec(struct snd_soc_codec *codec, | |||
1532 | 1739 | ||
1533 | codec->ac97->bus->ops = ops; | 1740 | codec->ac97->bus->ops = ops; |
1534 | codec->ac97->num = num; | 1741 | codec->ac97->num = num; |
1535 | codec->dev = &codec->ac97->dev; | ||
1536 | mutex_unlock(&codec->mutex); | 1742 | mutex_unlock(&codec->mutex); |
1537 | return 0; | 1743 | return 0; |
1538 | } | 1744 | } |
@@ -1547,6 +1753,9 @@ EXPORT_SYMBOL_GPL(snd_soc_new_ac97_codec); | |||
1547 | void snd_soc_free_ac97_codec(struct snd_soc_codec *codec) | 1753 | void snd_soc_free_ac97_codec(struct snd_soc_codec *codec) |
1548 | { | 1754 | { |
1549 | mutex_lock(&codec->mutex); | 1755 | mutex_lock(&codec->mutex); |
1756 | #ifdef CONFIG_SND_SOC_AC97_BUS | ||
1757 | soc_unregister_ac97_dai_link(codec); | ||
1758 | #endif | ||
1550 | kfree(codec->ac97->bus); | 1759 | kfree(codec->ac97->bus); |
1551 | kfree(codec->ac97); | 1760 | kfree(codec->ac97); |
1552 | codec->ac97 = NULL; | 1761 | codec->ac97 = NULL; |
@@ -1633,95 +1842,6 @@ int snd_soc_test_bits(struct snd_soc_codec *codec, unsigned short reg, | |||
1633 | EXPORT_SYMBOL_GPL(snd_soc_test_bits); | 1842 | EXPORT_SYMBOL_GPL(snd_soc_test_bits); |
1634 | 1843 | ||
1635 | /** | 1844 | /** |
1636 | * snd_soc_new_pcms - create new sound card and pcms | ||
1637 | * @socdev: the SoC audio device | ||
1638 | * @idx: ALSA card index | ||
1639 | * @xid: card identification | ||
1640 | * | ||
1641 | * Create a new sound card based upon the codec and interface pcms. | ||
1642 | * | ||
1643 | * Returns 0 for success, else error. | ||
1644 | */ | ||
1645 | int snd_soc_new_pcms(struct snd_soc_device *socdev, int idx, const char *xid) | ||
1646 | { | ||
1647 | struct snd_soc_card *card = socdev->card; | ||
1648 | struct snd_soc_codec *codec = card->codec; | ||
1649 | int ret, i; | ||
1650 | |||
1651 | mutex_lock(&codec->mutex); | ||
1652 | |||
1653 | /* register a sound card */ | ||
1654 | ret = snd_card_create(idx, xid, codec->owner, 0, &codec->card); | ||
1655 | if (ret < 0) { | ||
1656 | printk(KERN_ERR "asoc: can't create sound card for codec %s\n", | ||
1657 | codec->name); | ||
1658 | mutex_unlock(&codec->mutex); | ||
1659 | return ret; | ||
1660 | } | ||
1661 | |||
1662 | codec->socdev = socdev; | ||
1663 | codec->card->dev = socdev->dev; | ||
1664 | codec->card->private_data = codec; | ||
1665 | strncpy(codec->card->driver, codec->name, sizeof(codec->card->driver)); | ||
1666 | |||
1667 | /* create the pcms */ | ||
1668 | for (i = 0; i < card->num_links; i++) { | ||
1669 | ret = soc_new_pcm(socdev, &card->dai_link[i], i); | ||
1670 | if (ret < 0) { | ||
1671 | printk(KERN_ERR "asoc: can't create pcm %s\n", | ||
1672 | card->dai_link[i].stream_name); | ||
1673 | mutex_unlock(&codec->mutex); | ||
1674 | return ret; | ||
1675 | } | ||
1676 | /* Check for codec->ac97 to handle the ac97.c fun */ | ||
1677 | if (card->dai_link[i].codec_dai->ac97_control && codec->ac97) { | ||
1678 | snd_ac97_dev_add_pdata(codec->ac97, | ||
1679 | card->dai_link[i].cpu_dai->ac97_pdata); | ||
1680 | } | ||
1681 | } | ||
1682 | |||
1683 | mutex_unlock(&codec->mutex); | ||
1684 | return ret; | ||
1685 | } | ||
1686 | EXPORT_SYMBOL_GPL(snd_soc_new_pcms); | ||
1687 | |||
1688 | /** | ||
1689 | * snd_soc_free_pcms - free sound card and pcms | ||
1690 | * @socdev: the SoC audio device | ||
1691 | * | ||
1692 | * Frees sound card and pcms associated with the socdev. | ||
1693 | * Also unregister the codec if it is an AC97 device. | ||
1694 | */ | ||
1695 | void snd_soc_free_pcms(struct snd_soc_device *socdev) | ||
1696 | { | ||
1697 | struct snd_soc_codec *codec = socdev->card->codec; | ||
1698 | #ifdef CONFIG_SND_SOC_AC97_BUS | ||
1699 | struct snd_soc_dai *codec_dai; | ||
1700 | int i; | ||
1701 | #endif | ||
1702 | |||
1703 | mutex_lock(&codec->mutex); | ||
1704 | soc_cleanup_codec_debugfs(codec); | ||
1705 | #ifdef CONFIG_SND_SOC_AC97_BUS | ||
1706 | for (i = 0; i < codec->num_dai; i++) { | ||
1707 | codec_dai = &codec->dai[i]; | ||
1708 | if (codec_dai->ac97_control && codec->ac97 && | ||
1709 | strcmp(codec->name, "AC97") != 0) { | ||
1710 | soc_ac97_dev_unregister(codec); | ||
1711 | goto free_card; | ||
1712 | } | ||
1713 | } | ||
1714 | free_card: | ||
1715 | #endif | ||
1716 | |||
1717 | if (codec->card) | ||
1718 | snd_card_free(codec->card); | ||
1719 | device_remove_file(socdev->dev, &dev_attr_codec_reg); | ||
1720 | mutex_unlock(&codec->mutex); | ||
1721 | } | ||
1722 | EXPORT_SYMBOL_GPL(snd_soc_free_pcms); | ||
1723 | |||
1724 | /** | ||
1725 | * snd_soc_set_runtime_hwparams - set the runtime hardware parameters | 1845 | * snd_soc_set_runtime_hwparams - set the runtime hardware parameters |
1726 | * @substream: the pcm substream | 1846 | * @substream: the pcm substream |
1727 | * @hw: the hardware parameters | 1847 | * @hw: the hardware parameters |
@@ -1782,7 +1902,7 @@ EXPORT_SYMBOL_GPL(snd_soc_cnew); | |||
1782 | int snd_soc_add_controls(struct snd_soc_codec *codec, | 1902 | int snd_soc_add_controls(struct snd_soc_codec *codec, |
1783 | const struct snd_kcontrol_new *controls, int num_controls) | 1903 | const struct snd_kcontrol_new *controls, int num_controls) |
1784 | { | 1904 | { |
1785 | struct snd_card *card = codec->card; | 1905 | struct snd_card *card = codec->card->snd_card; |
1786 | int err, i; | 1906 | int err, i; |
1787 | 1907 | ||
1788 | for (i = 0; i < num_controls; i++) { | 1908 | for (i = 0; i < num_controls; i++) { |
@@ -2337,7 +2457,7 @@ EXPORT_SYMBOL_GPL(snd_soc_put_volsw_s8); | |||
2337 | int snd_soc_limit_volume(struct snd_soc_codec *codec, | 2457 | int snd_soc_limit_volume(struct snd_soc_codec *codec, |
2338 | const char *name, int max) | 2458 | const char *name, int max) |
2339 | { | 2459 | { |
2340 | struct snd_card *card = codec->card; | 2460 | struct snd_card *card = codec->card->snd_card; |
2341 | struct snd_kcontrol *kctl; | 2461 | struct snd_kcontrol *kctl; |
2342 | struct soc_mixer_control *mc; | 2462 | struct soc_mixer_control *mc; |
2343 | int found = 0; | 2463 | int found = 0; |
@@ -2469,8 +2589,8 @@ EXPORT_SYMBOL_GPL(snd_soc_put_volsw_2r_sx); | |||
2469 | int snd_soc_dai_set_sysclk(struct snd_soc_dai *dai, int clk_id, | 2589 | int snd_soc_dai_set_sysclk(struct snd_soc_dai *dai, int clk_id, |
2470 | unsigned int freq, int dir) | 2590 | unsigned int freq, int dir) |
2471 | { | 2591 | { |
2472 | if (dai->ops && dai->ops->set_sysclk) | 2592 | if (dai->driver && dai->driver->ops->set_sysclk) |
2473 | return dai->ops->set_sysclk(dai, clk_id, freq, dir); | 2593 | return dai->driver->ops->set_sysclk(dai, clk_id, freq, dir); |
2474 | else | 2594 | else |
2475 | return -EINVAL; | 2595 | return -EINVAL; |
2476 | } | 2596 | } |
@@ -2489,8 +2609,8 @@ EXPORT_SYMBOL_GPL(snd_soc_dai_set_sysclk); | |||
2489 | int snd_soc_dai_set_clkdiv(struct snd_soc_dai *dai, | 2609 | int snd_soc_dai_set_clkdiv(struct snd_soc_dai *dai, |
2490 | int div_id, int div) | 2610 | int div_id, int div) |
2491 | { | 2611 | { |
2492 | if (dai->ops && dai->ops->set_clkdiv) | 2612 | if (dai->driver && dai->driver->ops->set_clkdiv) |
2493 | return dai->ops->set_clkdiv(dai, div_id, div); | 2613 | return dai->driver->ops->set_clkdiv(dai, div_id, div); |
2494 | else | 2614 | else |
2495 | return -EINVAL; | 2615 | return -EINVAL; |
2496 | } | 2616 | } |
@@ -2509,8 +2629,8 @@ EXPORT_SYMBOL_GPL(snd_soc_dai_set_clkdiv); | |||
2509 | int snd_soc_dai_set_pll(struct snd_soc_dai *dai, int pll_id, int source, | 2629 | int snd_soc_dai_set_pll(struct snd_soc_dai *dai, int pll_id, int source, |
2510 | unsigned int freq_in, unsigned int freq_out) | 2630 | unsigned int freq_in, unsigned int freq_out) |
2511 | { | 2631 | { |
2512 | if (dai->ops && dai->ops->set_pll) | 2632 | if (dai->driver && dai->driver->ops->set_pll) |
2513 | return dai->ops->set_pll(dai, pll_id, source, | 2633 | return dai->driver->ops->set_pll(dai, pll_id, source, |
2514 | freq_in, freq_out); | 2634 | freq_in, freq_out); |
2515 | else | 2635 | else |
2516 | return -EINVAL; | 2636 | return -EINVAL; |
@@ -2526,8 +2646,8 @@ EXPORT_SYMBOL_GPL(snd_soc_dai_set_pll); | |||
2526 | */ | 2646 | */ |
2527 | int snd_soc_dai_set_fmt(struct snd_soc_dai *dai, unsigned int fmt) | 2647 | int snd_soc_dai_set_fmt(struct snd_soc_dai *dai, unsigned int fmt) |
2528 | { | 2648 | { |
2529 | if (dai->ops && dai->ops->set_fmt) | 2649 | if (dai->driver && dai->driver->ops->set_fmt) |
2530 | return dai->ops->set_fmt(dai, fmt); | 2650 | return dai->driver->ops->set_fmt(dai, fmt); |
2531 | else | 2651 | else |
2532 | return -EINVAL; | 2652 | return -EINVAL; |
2533 | } | 2653 | } |
@@ -2547,8 +2667,8 @@ EXPORT_SYMBOL_GPL(snd_soc_dai_set_fmt); | |||
2547 | int snd_soc_dai_set_tdm_slot(struct snd_soc_dai *dai, | 2667 | int snd_soc_dai_set_tdm_slot(struct snd_soc_dai *dai, |
2548 | unsigned int tx_mask, unsigned int rx_mask, int slots, int slot_width) | 2668 | unsigned int tx_mask, unsigned int rx_mask, int slots, int slot_width) |
2549 | { | 2669 | { |
2550 | if (dai->ops && dai->ops->set_tdm_slot) | 2670 | if (dai->driver && dai->driver->ops->set_tdm_slot) |
2551 | return dai->ops->set_tdm_slot(dai, tx_mask, rx_mask, | 2671 | return dai->driver->ops->set_tdm_slot(dai, tx_mask, rx_mask, |
2552 | slots, slot_width); | 2672 | slots, slot_width); |
2553 | else | 2673 | else |
2554 | return -EINVAL; | 2674 | return -EINVAL; |
@@ -2571,8 +2691,8 @@ int snd_soc_dai_set_channel_map(struct snd_soc_dai *dai, | |||
2571 | unsigned int tx_num, unsigned int *tx_slot, | 2691 | unsigned int tx_num, unsigned int *tx_slot, |
2572 | unsigned int rx_num, unsigned int *rx_slot) | 2692 | unsigned int rx_num, unsigned int *rx_slot) |
2573 | { | 2693 | { |
2574 | if (dai->ops && dai->ops->set_channel_map) | 2694 | if (dai->driver && dai->driver->ops->set_channel_map) |
2575 | return dai->ops->set_channel_map(dai, tx_num, tx_slot, | 2695 | return dai->driver->ops->set_channel_map(dai, tx_num, tx_slot, |
2576 | rx_num, rx_slot); | 2696 | rx_num, rx_slot); |
2577 | else | 2697 | else |
2578 | return -EINVAL; | 2698 | return -EINVAL; |
@@ -2588,8 +2708,8 @@ EXPORT_SYMBOL_GPL(snd_soc_dai_set_channel_map); | |||
2588 | */ | 2708 | */ |
2589 | int snd_soc_dai_set_tristate(struct snd_soc_dai *dai, int tristate) | 2709 | int snd_soc_dai_set_tristate(struct snd_soc_dai *dai, int tristate) |
2590 | { | 2710 | { |
2591 | if (dai->ops && dai->ops->set_tristate) | 2711 | if (dai->driver && dai->driver->ops->set_tristate) |
2592 | return dai->ops->set_tristate(dai, tristate); | 2712 | return dai->driver->ops->set_tristate(dai, tristate); |
2593 | else | 2713 | else |
2594 | return -EINVAL; | 2714 | return -EINVAL; |
2595 | } | 2715 | } |
@@ -2604,8 +2724,8 @@ EXPORT_SYMBOL_GPL(snd_soc_dai_set_tristate); | |||
2604 | */ | 2724 | */ |
2605 | int snd_soc_dai_digital_mute(struct snd_soc_dai *dai, int mute) | 2725 | int snd_soc_dai_digital_mute(struct snd_soc_dai *dai, int mute) |
2606 | { | 2726 | { |
2607 | if (dai->ops && dai->ops->digital_mute) | 2727 | if (dai->driver && dai->driver->ops->digital_mute) |
2608 | return dai->ops->digital_mute(dai, mute); | 2728 | return dai->driver->ops->digital_mute(dai, mute); |
2609 | else | 2729 | else |
2610 | return -EINVAL; | 2730 | return -EINVAL; |
2611 | } | 2731 | } |
@@ -2622,11 +2742,22 @@ EXPORT_SYMBOL_GPL(snd_soc_dai_digital_mute); | |||
2622 | */ | 2742 | */ |
2623 | static int snd_soc_register_card(struct snd_soc_card *card) | 2743 | static int snd_soc_register_card(struct snd_soc_card *card) |
2624 | { | 2744 | { |
2745 | int i; | ||
2746 | |||
2625 | if (!card->name || !card->dev) | 2747 | if (!card->name || !card->dev) |
2626 | return -EINVAL; | 2748 | return -EINVAL; |
2627 | 2749 | ||
2750 | card->rtd = kzalloc(sizeof(struct snd_soc_pcm_runtime) * card->num_links, | ||
2751 | GFP_KERNEL); | ||
2752 | if (card->rtd == NULL) | ||
2753 | return -ENOMEM; | ||
2754 | |||
2755 | for (i = 0; i < card->num_links; i++) | ||
2756 | card->rtd[i].dai_link = &card->dai_link[i]; | ||
2757 | |||
2628 | INIT_LIST_HEAD(&card->list); | 2758 | INIT_LIST_HEAD(&card->list); |
2629 | card->instantiated = 0; | 2759 | card->instantiated = 0; |
2760 | mutex_init(&card->mutex); | ||
2630 | 2761 | ||
2631 | mutex_lock(&client_mutex); | 2762 | mutex_lock(&client_mutex); |
2632 | list_add(&card->list, &card_list); | 2763 | list_add(&card->list, &card_list); |
@@ -2652,30 +2783,97 @@ static int snd_soc_unregister_card(struct snd_soc_card *card) | |||
2652 | mutex_lock(&client_mutex); | 2783 | mutex_lock(&client_mutex); |
2653 | list_del(&card->list); | 2784 | list_del(&card->list); |
2654 | mutex_unlock(&client_mutex); | 2785 | mutex_unlock(&client_mutex); |
2655 | |||
2656 | dev_dbg(card->dev, "Unregistered card '%s'\n", card->name); | 2786 | dev_dbg(card->dev, "Unregistered card '%s'\n", card->name); |
2657 | 2787 | ||
2658 | return 0; | 2788 | return 0; |
2659 | } | 2789 | } |
2660 | 2790 | ||
2791 | /* | ||
2792 | * Simplify DAI link configuration by removing ".-1" from device names | ||
2793 | * and sanitizing names. | ||
2794 | */ | ||
2795 | static inline char *fmt_single_name(struct device *dev, int *id) | ||
2796 | { | ||
2797 | char *found, name[NAME_SIZE]; | ||
2798 | int id1, id2; | ||
2799 | |||
2800 | if (dev_name(dev) == NULL) | ||
2801 | return NULL; | ||
2802 | |||
2803 | strncpy(name, dev_name(dev), NAME_SIZE); | ||
2804 | |||
2805 | /* are we a "%s.%d" name (platform and SPI components) */ | ||
2806 | found = strstr(name, dev->driver->name); | ||
2807 | if (found) { | ||
2808 | /* get ID */ | ||
2809 | if (sscanf(&found[strlen(dev->driver->name)], ".%d", id) == 1) { | ||
2810 | |||
2811 | /* discard ID from name if ID == -1 */ | ||
2812 | if (*id == -1) | ||
2813 | found[strlen(dev->driver->name)] = '\0'; | ||
2814 | } | ||
2815 | |||
2816 | } else { | ||
2817 | /* I2C component devices are named "bus-addr" */ | ||
2818 | if (sscanf(name, "%x-%x", &id1, &id2) == 2) { | ||
2819 | char tmp[NAME_SIZE]; | ||
2820 | |||
2821 | /* create unique ID number from I2C addr and bus */ | ||
2822 | *id = ((id1 && 0xffff) << 16) + id2; | ||
2823 | |||
2824 | /* sanitize component name for DAI link creation */ | ||
2825 | snprintf(tmp, NAME_SIZE, "%s.%s", dev->driver->name, name); | ||
2826 | strncpy(name, tmp, NAME_SIZE); | ||
2827 | } else | ||
2828 | *id = 0; | ||
2829 | } | ||
2830 | |||
2831 | return kstrdup(name, GFP_KERNEL); | ||
2832 | } | ||
2833 | |||
2834 | /* | ||
2835 | * Simplify DAI link naming for single devices with multiple DAIs by removing | ||
2836 | * any ".-1" and using the DAI name (instead of device name). | ||
2837 | */ | ||
2838 | static inline char *fmt_multiple_name(struct device *dev, | ||
2839 | struct snd_soc_dai_driver *dai_drv) | ||
2840 | { | ||
2841 | if (dai_drv->name == NULL) { | ||
2842 | printk(KERN_ERR "asoc: error - multiple DAI %s registered with no name\n", | ||
2843 | dev_name(dev)); | ||
2844 | return NULL; | ||
2845 | } | ||
2846 | |||
2847 | return kstrdup(dai_drv->name, GFP_KERNEL); | ||
2848 | } | ||
2849 | |||
2661 | /** | 2850 | /** |
2662 | * snd_soc_register_dai - Register a DAI with the ASoC core | 2851 | * snd_soc_register_dai - Register a DAI with the ASoC core |
2663 | * | 2852 | * |
2664 | * @dai: DAI to register | 2853 | * @dai: DAI to register |
2665 | */ | 2854 | */ |
2666 | int snd_soc_register_dai(struct snd_soc_dai *dai) | 2855 | int snd_soc_register_dai(struct device *dev, |
2856 | struct snd_soc_dai_driver *dai_drv) | ||
2667 | { | 2857 | { |
2668 | if (!dai->name) | 2858 | struct snd_soc_dai *dai; |
2669 | return -EINVAL; | 2859 | |
2860 | dev_dbg(dev, "dai register %s\n", dev_name(dev)); | ||
2670 | 2861 | ||
2671 | /* The device should become mandatory over time */ | 2862 | dai = kzalloc(sizeof(struct snd_soc_dai), GFP_KERNEL); |
2672 | if (!dai->dev) | 2863 | if (dai == NULL) |
2673 | printk(KERN_WARNING "No device for DAI %s\n", dai->name); | 2864 | return -ENOMEM; |
2674 | 2865 | ||
2675 | if (!dai->ops) | 2866 | /* create DAI component name */ |
2676 | dai->ops = &null_dai_ops; | 2867 | dai->name = fmt_single_name(dev, &dai->id); |
2868 | if (dai->name == NULL) { | ||
2869 | kfree(dai); | ||
2870 | return -ENOMEM; | ||
2871 | } | ||
2677 | 2872 | ||
2678 | INIT_LIST_HEAD(&dai->list); | 2873 | dai->dev = dev; |
2874 | dai->driver = dai_drv; | ||
2875 | if (!dai->driver->ops) | ||
2876 | dai->driver->ops = &null_dai_ops; | ||
2679 | 2877 | ||
2680 | mutex_lock(&client_mutex); | 2878 | mutex_lock(&client_mutex); |
2681 | list_add(&dai->list, &dai_list); | 2879 | list_add(&dai->list, &dai_list); |
@@ -2693,13 +2891,24 @@ EXPORT_SYMBOL_GPL(snd_soc_register_dai); | |||
2693 | * | 2891 | * |
2694 | * @dai: DAI to unregister | 2892 | * @dai: DAI to unregister |
2695 | */ | 2893 | */ |
2696 | void snd_soc_unregister_dai(struct snd_soc_dai *dai) | 2894 | void snd_soc_unregister_dai(struct device *dev) |
2697 | { | 2895 | { |
2896 | struct snd_soc_dai *dai; | ||
2897 | |||
2898 | list_for_each_entry(dai, &dai_list, list) { | ||
2899 | if (dev == dai->dev) | ||
2900 | goto found; | ||
2901 | } | ||
2902 | return; | ||
2903 | |||
2904 | found: | ||
2698 | mutex_lock(&client_mutex); | 2905 | mutex_lock(&client_mutex); |
2699 | list_del(&dai->list); | 2906 | list_del(&dai->list); |
2700 | mutex_unlock(&client_mutex); | 2907 | mutex_unlock(&client_mutex); |
2701 | 2908 | ||
2702 | pr_debug("Unregistered DAI '%s'\n", dai->name); | 2909 | pr_debug("Unregistered DAI '%s'\n", dai->name); |
2910 | kfree(dai->name); | ||
2911 | kfree(dai); | ||
2703 | } | 2912 | } |
2704 | EXPORT_SYMBOL_GPL(snd_soc_unregister_dai); | 2913 | EXPORT_SYMBOL_GPL(snd_soc_unregister_dai); |
2705 | 2914 | ||
@@ -2709,21 +2918,47 @@ EXPORT_SYMBOL_GPL(snd_soc_unregister_dai); | |||
2709 | * @dai: Array of DAIs to register | 2918 | * @dai: Array of DAIs to register |
2710 | * @count: Number of DAIs | 2919 | * @count: Number of DAIs |
2711 | */ | 2920 | */ |
2712 | int snd_soc_register_dais(struct snd_soc_dai *dai, size_t count) | 2921 | int snd_soc_register_dais(struct device *dev, |
2922 | struct snd_soc_dai_driver *dai_drv, size_t count) | ||
2713 | { | 2923 | { |
2714 | int i, ret; | 2924 | struct snd_soc_dai *dai; |
2925 | int i, ret = 0; | ||
2926 | |||
2927 | dev_dbg(dev, "dai register %s #%d\n", dev_name(dev), count); | ||
2715 | 2928 | ||
2716 | for (i = 0; i < count; i++) { | 2929 | for (i = 0; i < count; i++) { |
2717 | ret = snd_soc_register_dai(&dai[i]); | 2930 | |
2718 | if (ret != 0) | 2931 | dai = kzalloc(sizeof(struct snd_soc_dai), GFP_KERNEL); |
2932 | if (dai == NULL) | ||
2933 | return -ENOMEM; | ||
2934 | |||
2935 | /* create DAI component name */ | ||
2936 | dai->name = fmt_multiple_name(dev, &dai_drv[i]); | ||
2937 | if (dai->name == NULL) { | ||
2938 | kfree(dai); | ||
2939 | ret = -EINVAL; | ||
2719 | goto err; | 2940 | goto err; |
2941 | } | ||
2942 | |||
2943 | dai->dev = dev; | ||
2944 | dai->id = i; | ||
2945 | dai->driver = &dai_drv[i]; | ||
2946 | if (!dai->driver->ops) | ||
2947 | dai->driver->ops = &null_dai_ops; | ||
2948 | |||
2949 | mutex_lock(&client_mutex); | ||
2950 | list_add(&dai->list, &dai_list); | ||
2951 | mutex_unlock(&client_mutex); | ||
2952 | |||
2953 | pr_debug("Registered DAI '%s'\n", dai->name); | ||
2720 | } | 2954 | } |
2721 | 2955 | ||
2956 | snd_soc_instantiate_cards(); | ||
2722 | return 0; | 2957 | return 0; |
2723 | 2958 | ||
2724 | err: | 2959 | err: |
2725 | for (i--; i >= 0; i--) | 2960 | for (i--; i >= 0; i--) |
2726 | snd_soc_unregister_dai(&dai[i]); | 2961 | snd_soc_unregister_dai(dev); |
2727 | 2962 | ||
2728 | return ret; | 2963 | return ret; |
2729 | } | 2964 | } |
@@ -2735,12 +2970,12 @@ EXPORT_SYMBOL_GPL(snd_soc_register_dais); | |||
2735 | * @dai: Array of DAIs to unregister | 2970 | * @dai: Array of DAIs to unregister |
2736 | * @count: Number of DAIs | 2971 | * @count: Number of DAIs |
2737 | */ | 2972 | */ |
2738 | void snd_soc_unregister_dais(struct snd_soc_dai *dai, size_t count) | 2973 | void snd_soc_unregister_dais(struct device *dev, size_t count) |
2739 | { | 2974 | { |
2740 | int i; | 2975 | int i; |
2741 | 2976 | ||
2742 | for (i = 0; i < count; i++) | 2977 | for (i = 0; i < count; i++) |
2743 | snd_soc_unregister_dai(&dai[i]); | 2978 | snd_soc_unregister_dai(dev); |
2744 | } | 2979 | } |
2745 | EXPORT_SYMBOL_GPL(snd_soc_unregister_dais); | 2980 | EXPORT_SYMBOL_GPL(snd_soc_unregister_dais); |
2746 | 2981 | ||
@@ -2749,12 +2984,26 @@ EXPORT_SYMBOL_GPL(snd_soc_unregister_dais); | |||
2749 | * | 2984 | * |
2750 | * @platform: platform to register | 2985 | * @platform: platform to register |
2751 | */ | 2986 | */ |
2752 | int snd_soc_register_platform(struct snd_soc_platform *platform) | 2987 | int snd_soc_register_platform(struct device *dev, |
2988 | struct snd_soc_platform_driver *platform_drv) | ||
2753 | { | 2989 | { |
2754 | if (!platform->name) | 2990 | struct snd_soc_platform *platform; |
2755 | return -EINVAL; | 2991 | |
2992 | dev_dbg(dev, "platform register %s\n", dev_name(dev)); | ||
2993 | |||
2994 | platform = kzalloc(sizeof(struct snd_soc_platform), GFP_KERNEL); | ||
2995 | if (platform == NULL) | ||
2996 | return -ENOMEM; | ||
2997 | |||
2998 | /* create platform component name */ | ||
2999 | platform->name = fmt_single_name(dev, &platform->id); | ||
3000 | if (platform->name == NULL) { | ||
3001 | kfree(platform); | ||
3002 | return -ENOMEM; | ||
3003 | } | ||
2756 | 3004 | ||
2757 | INIT_LIST_HEAD(&platform->list); | 3005 | platform->dev = dev; |
3006 | platform->driver = platform_drv; | ||
2758 | 3007 | ||
2759 | mutex_lock(&client_mutex); | 3008 | mutex_lock(&client_mutex); |
2760 | list_add(&platform->list, &platform_list); | 3009 | list_add(&platform->list, &platform_list); |
@@ -2772,13 +3021,24 @@ EXPORT_SYMBOL_GPL(snd_soc_register_platform); | |||
2772 | * | 3021 | * |
2773 | * @platform: platform to unregister | 3022 | * @platform: platform to unregister |
2774 | */ | 3023 | */ |
2775 | void snd_soc_unregister_platform(struct snd_soc_platform *platform) | 3024 | void snd_soc_unregister_platform(struct device *dev) |
2776 | { | 3025 | { |
3026 | struct snd_soc_platform *platform; | ||
3027 | |||
3028 | list_for_each_entry(platform, &platform_list, list) { | ||
3029 | if (dev == platform->dev) | ||
3030 | goto found; | ||
3031 | } | ||
3032 | return; | ||
3033 | |||
3034 | found: | ||
2777 | mutex_lock(&client_mutex); | 3035 | mutex_lock(&client_mutex); |
2778 | list_del(&platform->list); | 3036 | list_del(&platform->list); |
2779 | mutex_unlock(&client_mutex); | 3037 | mutex_unlock(&client_mutex); |
2780 | 3038 | ||
2781 | pr_debug("Unregistered platform '%s'\n", platform->name); | 3039 | pr_debug("Unregistered platform '%s'\n", platform->name); |
3040 | kfree(platform->name); | ||
3041 | kfree(platform); | ||
2782 | } | 3042 | } |
2783 | EXPORT_SYMBOL_GPL(snd_soc_unregister_platform); | 3043 | EXPORT_SYMBOL_GPL(snd_soc_unregister_platform); |
2784 | 3044 | ||
@@ -2820,32 +3080,78 @@ static void fixup_codec_formats(struct snd_soc_pcm_stream *stream) | |||
2820 | * | 3080 | * |
2821 | * @codec: codec to register | 3081 | * @codec: codec to register |
2822 | */ | 3082 | */ |
2823 | int snd_soc_register_codec(struct snd_soc_codec *codec) | 3083 | int snd_soc_register_codec(struct device *dev, |
3084 | struct snd_soc_codec_driver *codec_drv, | ||
3085 | struct snd_soc_dai_driver *dai_drv, int num_dai) | ||
2824 | { | 3086 | { |
2825 | int i; | 3087 | struct snd_soc_codec *codec; |
3088 | int ret, i; | ||
2826 | 3089 | ||
2827 | if (!codec->name) | 3090 | dev_dbg(dev, "codec register %s\n", dev_name(dev)); |
2828 | return -EINVAL; | 3091 | |
3092 | codec = kzalloc(sizeof(struct snd_soc_codec), GFP_KERNEL); | ||
3093 | if (codec == NULL) | ||
3094 | return -ENOMEM; | ||
2829 | 3095 | ||
2830 | /* The device should become mandatory over time */ | 3096 | /* create CODEC component name */ |
2831 | if (!codec->dev) | 3097 | codec->name = fmt_single_name(dev, &codec->id); |
2832 | printk(KERN_WARNING "No device for codec %s\n", codec->name); | 3098 | if (codec->name == NULL) { |
3099 | kfree(codec); | ||
3100 | return -ENOMEM; | ||
3101 | } | ||
3102 | |||
3103 | /* allocate CODEC register cache */ | ||
3104 | if (codec_drv->reg_cache_size && codec_drv->reg_word_size) { | ||
2833 | 3105 | ||
2834 | INIT_LIST_HEAD(&codec->list); | 3106 | if (codec_drv->reg_cache_default) |
3107 | codec->reg_cache = kmemdup(codec_drv->reg_cache_default, | ||
3108 | codec_drv->reg_cache_size * codec_drv->reg_word_size, GFP_KERNEL); | ||
3109 | else | ||
3110 | codec->reg_cache = kzalloc(codec_drv->reg_cache_size * | ||
3111 | codec_drv->reg_word_size, GFP_KERNEL); | ||
2835 | 3112 | ||
2836 | for (i = 0; i < codec->num_dai; i++) { | 3113 | if (codec->reg_cache == NULL) { |
2837 | fixup_codec_formats(&codec->dai[i].playback); | 3114 | kfree(codec->name); |
2838 | fixup_codec_formats(&codec->dai[i].capture); | 3115 | kfree(codec); |
3116 | return -ENOMEM; | ||
3117 | } | ||
2839 | } | 3118 | } |
2840 | 3119 | ||
3120 | codec->dev = dev; | ||
3121 | codec->driver = codec_drv; | ||
3122 | codec->bias_level = SND_SOC_BIAS_OFF; | ||
3123 | codec->num_dai = num_dai; | ||
3124 | mutex_init(&codec->mutex); | ||
3125 | INIT_LIST_HEAD(&codec->dapm_widgets); | ||
3126 | INIT_LIST_HEAD(&codec->dapm_paths); | ||
3127 | |||
3128 | for (i = 0; i < num_dai; i++) { | ||
3129 | fixup_codec_formats(&dai_drv[i].playback); | ||
3130 | fixup_codec_formats(&dai_drv[i].capture); | ||
3131 | } | ||
3132 | |||
3133 | /* register DAIs */ | ||
3134 | ret = snd_soc_register_dais(dev, dai_drv, num_dai); | ||
3135 | if (ret < 0) | ||
3136 | goto error; | ||
3137 | |||
2841 | mutex_lock(&client_mutex); | 3138 | mutex_lock(&client_mutex); |
2842 | list_add(&codec->list, &codec_list); | 3139 | list_add(&codec->list, &codec_list); |
2843 | snd_soc_instantiate_cards(); | 3140 | snd_soc_instantiate_cards(); |
2844 | mutex_unlock(&client_mutex); | 3141 | mutex_unlock(&client_mutex); |
2845 | 3142 | ||
2846 | pr_debug("Registered codec '%s'\n", codec->name); | 3143 | pr_debug("Registered codec '%s'\n", codec->name); |
2847 | |||
2848 | return 0; | 3144 | return 0; |
3145 | |||
3146 | error: | ||
3147 | for (i--; i >= 0; i--) | ||
3148 | snd_soc_unregister_dai(dev); | ||
3149 | |||
3150 | if (codec->reg_cache) | ||
3151 | kfree(codec->reg_cache); | ||
3152 | kfree(codec->name); | ||
3153 | kfree(codec); | ||
3154 | return ret; | ||
2849 | } | 3155 | } |
2850 | EXPORT_SYMBOL_GPL(snd_soc_register_codec); | 3156 | EXPORT_SYMBOL_GPL(snd_soc_register_codec); |
2851 | 3157 | ||
@@ -2854,13 +3160,30 @@ EXPORT_SYMBOL_GPL(snd_soc_register_codec); | |||
2854 | * | 3160 | * |
2855 | * @codec: codec to unregister | 3161 | * @codec: codec to unregister |
2856 | */ | 3162 | */ |
2857 | void snd_soc_unregister_codec(struct snd_soc_codec *codec) | 3163 | void snd_soc_unregister_codec(struct device *dev) |
2858 | { | 3164 | { |
3165 | struct snd_soc_codec *codec; | ||
3166 | int i; | ||
3167 | |||
3168 | list_for_each_entry(codec, &codec_list, list) { | ||
3169 | if (dev == codec->dev) | ||
3170 | goto found; | ||
3171 | } | ||
3172 | return; | ||
3173 | |||
3174 | found: | ||
3175 | for (i = 0; i < codec->num_dai; i++) | ||
3176 | snd_soc_unregister_dai(dev); | ||
3177 | |||
2859 | mutex_lock(&client_mutex); | 3178 | mutex_lock(&client_mutex); |
2860 | list_del(&codec->list); | 3179 | list_del(&codec->list); |
2861 | mutex_unlock(&client_mutex); | 3180 | mutex_unlock(&client_mutex); |
2862 | 3181 | ||
2863 | pr_debug("Unregistered codec '%s'\n", codec->name); | 3182 | pr_debug("Unregistered codec '%s'\n", codec->name); |
3183 | |||
3184 | if (codec->reg_cache) | ||
3185 | kfree(codec->reg_cache); | ||
3186 | kfree(codec); | ||
2864 | } | 3187 | } |
2865 | EXPORT_SYMBOL_GPL(snd_soc_unregister_codec); | 3188 | EXPORT_SYMBOL_GPL(snd_soc_unregister_codec); |
2866 | 3189 | ||
diff --git a/sound/soc/soc-dapm.c b/sound/soc/soc-dapm.c index 03cb7c05ebec..035cab85cb66 100644 --- a/sound/soc/soc-dapm.c +++ b/sound/soc/soc-dapm.c | |||
@@ -112,43 +112,41 @@ static inline struct snd_soc_dapm_widget *dapm_cnew_widget( | |||
112 | 112 | ||
113 | /** | 113 | /** |
114 | * snd_soc_dapm_set_bias_level - set the bias level for the system | 114 | * snd_soc_dapm_set_bias_level - set the bias level for the system |
115 | * @socdev: audio device | 115 | * @card: audio device |
116 | * @level: level to configure | 116 | * @level: level to configure |
117 | * | 117 | * |
118 | * Configure the bias (power) levels for the SoC audio device. | 118 | * Configure the bias (power) levels for the SoC audio device. |
119 | * | 119 | * |
120 | * Returns 0 for success else error. | 120 | * Returns 0 for success else error. |
121 | */ | 121 | */ |
122 | static int snd_soc_dapm_set_bias_level(struct snd_soc_device *socdev, | 122 | static int snd_soc_dapm_set_bias_level(struct snd_soc_card *card, |
123 | enum snd_soc_bias_level level) | 123 | struct snd_soc_codec *codec, enum snd_soc_bias_level level) |
124 | { | 124 | { |
125 | struct snd_soc_card *card = socdev->card; | ||
126 | struct snd_soc_codec *codec = socdev->card->codec; | ||
127 | int ret = 0; | 125 | int ret = 0; |
128 | 126 | ||
129 | switch (level) { | 127 | switch (level) { |
130 | case SND_SOC_BIAS_ON: | 128 | case SND_SOC_BIAS_ON: |
131 | dev_dbg(socdev->dev, "Setting full bias\n"); | 129 | dev_dbg(codec->dev, "Setting full bias\n"); |
132 | break; | 130 | break; |
133 | case SND_SOC_BIAS_PREPARE: | 131 | case SND_SOC_BIAS_PREPARE: |
134 | dev_dbg(socdev->dev, "Setting bias prepare\n"); | 132 | dev_dbg(codec->dev, "Setting bias prepare\n"); |
135 | break; | 133 | break; |
136 | case SND_SOC_BIAS_STANDBY: | 134 | case SND_SOC_BIAS_STANDBY: |
137 | dev_dbg(socdev->dev, "Setting standby bias\n"); | 135 | dev_dbg(codec->dev, "Setting standby bias\n"); |
138 | break; | 136 | break; |
139 | case SND_SOC_BIAS_OFF: | 137 | case SND_SOC_BIAS_OFF: |
140 | dev_dbg(socdev->dev, "Setting bias off\n"); | 138 | dev_dbg(codec->dev, "Setting bias off\n"); |
141 | break; | 139 | break; |
142 | default: | 140 | default: |
143 | dev_err(socdev->dev, "Setting invalid bias %d\n", level); | 141 | dev_err(codec->dev, "Setting invalid bias %d\n", level); |
144 | return -EINVAL; | 142 | return -EINVAL; |
145 | } | 143 | } |
146 | 144 | ||
147 | if (card->set_bias_level) | 145 | if (card && card->set_bias_level) |
148 | ret = card->set_bias_level(card, level); | 146 | ret = card->set_bias_level(card, level); |
149 | if (ret == 0) { | 147 | if (ret == 0) { |
150 | if (codec->set_bias_level) | 148 | if (codec->driver->set_bias_level) |
151 | ret = codec->set_bias_level(codec, level); | 149 | ret = codec->driver->set_bias_level(codec, level); |
152 | else | 150 | else |
153 | codec->bias_level = level; | 151 | codec->bias_level = level; |
154 | } | 152 | } |
@@ -370,7 +368,7 @@ static int dapm_new_mixer(struct snd_soc_codec *codec, | |||
370 | 368 | ||
371 | path->kcontrol = snd_soc_cnew(&w->kcontrols[i], w, | 369 | path->kcontrol = snd_soc_cnew(&w->kcontrols[i], w, |
372 | path->long_name); | 370 | path->long_name); |
373 | ret = snd_ctl_add(codec->card, path->kcontrol); | 371 | ret = snd_ctl_add(codec->card->snd_card, path->kcontrol); |
374 | if (ret < 0) { | 372 | if (ret < 0) { |
375 | printk(KERN_ERR "asoc: failed to add dapm kcontrol %s: %d\n", | 373 | printk(KERN_ERR "asoc: failed to add dapm kcontrol %s: %d\n", |
376 | path->long_name, | 374 | path->long_name, |
@@ -398,7 +396,7 @@ static int dapm_new_mux(struct snd_soc_codec *codec, | |||
398 | } | 396 | } |
399 | 397 | ||
400 | kcontrol = snd_soc_cnew(&w->kcontrols[0], w, w->name); | 398 | kcontrol = snd_soc_cnew(&w->kcontrols[0], w, w->name); |
401 | ret = snd_ctl_add(codec->card, kcontrol); | 399 | ret = snd_ctl_add(codec->card->snd_card, kcontrol); |
402 | if (ret < 0) | 400 | if (ret < 0) |
403 | goto err; | 401 | goto err; |
404 | 402 | ||
@@ -437,9 +435,9 @@ static inline void dapm_clear_walk(struct snd_soc_codec *codec) | |||
437 | */ | 435 | */ |
438 | static int snd_soc_dapm_suspend_check(struct snd_soc_dapm_widget *widget) | 436 | static int snd_soc_dapm_suspend_check(struct snd_soc_dapm_widget *widget) |
439 | { | 437 | { |
440 | struct snd_soc_codec *codec = widget->codec; | 438 | int level = snd_power_get_state(widget->codec->card->snd_card); |
441 | 439 | ||
442 | switch (snd_power_get_state(codec->card)) { | 440 | switch (level) { |
443 | case SNDRV_CTL_POWER_D3hot: | 441 | case SNDRV_CTL_POWER_D3hot: |
444 | case SNDRV_CTL_POWER_D3cold: | 442 | case SNDRV_CTL_POWER_D3cold: |
445 | if (widget->ignore_suspend) | 443 | if (widget->ignore_suspend) |
@@ -893,7 +891,7 @@ static void dapm_seq_run(struct snd_soc_codec *codec, struct list_head *list, | |||
893 | */ | 891 | */ |
894 | static int dapm_power_widgets(struct snd_soc_codec *codec, int event) | 892 | static int dapm_power_widgets(struct snd_soc_codec *codec, int event) |
895 | { | 893 | { |
896 | struct snd_soc_device *socdev = codec->socdev; | 894 | struct snd_soc_card *card = codec->card; |
897 | struct snd_soc_dapm_widget *w; | 895 | struct snd_soc_dapm_widget *w; |
898 | LIST_HEAD(up_list); | 896 | LIST_HEAD(up_list); |
899 | LIST_HEAD(down_list); | 897 | LIST_HEAD(down_list); |
@@ -966,7 +964,7 @@ static int dapm_power_widgets(struct snd_soc_codec *codec, int event) | |||
966 | } | 964 | } |
967 | 965 | ||
968 | if (sys_power && codec->bias_level == SND_SOC_BIAS_OFF) { | 966 | if (sys_power && codec->bias_level == SND_SOC_BIAS_OFF) { |
969 | ret = snd_soc_dapm_set_bias_level(socdev, | 967 | ret = snd_soc_dapm_set_bias_level(card, codec, |
970 | SND_SOC_BIAS_STANDBY); | 968 | SND_SOC_BIAS_STANDBY); |
971 | if (ret != 0) | 969 | if (ret != 0) |
972 | pr_err("Failed to turn on bias: %d\n", ret); | 970 | pr_err("Failed to turn on bias: %d\n", ret); |
@@ -975,8 +973,7 @@ static int dapm_power_widgets(struct snd_soc_codec *codec, int event) | |||
975 | /* If we're changing to all on or all off then prepare */ | 973 | /* If we're changing to all on or all off then prepare */ |
976 | if ((sys_power && codec->bias_level == SND_SOC_BIAS_STANDBY) || | 974 | if ((sys_power && codec->bias_level == SND_SOC_BIAS_STANDBY) || |
977 | (!sys_power && codec->bias_level == SND_SOC_BIAS_ON)) { | 975 | (!sys_power && codec->bias_level == SND_SOC_BIAS_ON)) { |
978 | ret = snd_soc_dapm_set_bias_level(socdev, | 976 | ret = snd_soc_dapm_set_bias_level(card, codec, SND_SOC_BIAS_PREPARE); |
979 | SND_SOC_BIAS_PREPARE); | ||
980 | if (ret != 0) | 977 | if (ret != 0) |
981 | pr_err("Failed to prepare bias: %d\n", ret); | 978 | pr_err("Failed to prepare bias: %d\n", ret); |
982 | } | 979 | } |
@@ -989,8 +986,7 @@ static int dapm_power_widgets(struct snd_soc_codec *codec, int event) | |||
989 | 986 | ||
990 | /* If we just powered the last thing off drop to standby bias */ | 987 | /* If we just powered the last thing off drop to standby bias */ |
991 | if (codec->bias_level == SND_SOC_BIAS_PREPARE && !sys_power) { | 988 | if (codec->bias_level == SND_SOC_BIAS_PREPARE && !sys_power) { |
992 | ret = snd_soc_dapm_set_bias_level(socdev, | 989 | ret = snd_soc_dapm_set_bias_level(card, codec, SND_SOC_BIAS_STANDBY); |
993 | SND_SOC_BIAS_STANDBY); | ||
994 | if (ret != 0) | 990 | if (ret != 0) |
995 | pr_err("Failed to apply standby bias: %d\n", ret); | 991 | pr_err("Failed to apply standby bias: %d\n", ret); |
996 | } | 992 | } |
@@ -998,15 +994,14 @@ static int dapm_power_widgets(struct snd_soc_codec *codec, int event) | |||
998 | /* If we're in standby and can support bias off then do that */ | 994 | /* If we're in standby and can support bias off then do that */ |
999 | if (codec->bias_level == SND_SOC_BIAS_STANDBY && | 995 | if (codec->bias_level == SND_SOC_BIAS_STANDBY && |
1000 | codec->idle_bias_off) { | 996 | codec->idle_bias_off) { |
1001 | ret = snd_soc_dapm_set_bias_level(socdev, SND_SOC_BIAS_OFF); | 997 | ret = snd_soc_dapm_set_bias_level(card, codec, SND_SOC_BIAS_OFF); |
1002 | if (ret != 0) | 998 | if (ret != 0) |
1003 | pr_err("Failed to turn off bias: %d\n", ret); | 999 | pr_err("Failed to turn off bias: %d\n", ret); |
1004 | } | 1000 | } |
1005 | 1001 | ||
1006 | /* If we just powered up then move to active bias */ | 1002 | /* If we just powered up then move to active bias */ |
1007 | if (codec->bias_level == SND_SOC_BIAS_PREPARE && sys_power) { | 1003 | if (codec->bias_level == SND_SOC_BIAS_PREPARE && sys_power) { |
1008 | ret = snd_soc_dapm_set_bias_level(socdev, | 1004 | ret = snd_soc_dapm_set_bias_level(card, codec, SND_SOC_BIAS_ON); |
1009 | SND_SOC_BIAS_ON); | ||
1010 | if (ret != 0) | 1005 | if (ret != 0) |
1011 | pr_err("Failed to apply active bias: %d\n", ret); | 1006 | pr_err("Failed to apply active bias: %d\n", ret); |
1012 | } | 1007 | } |
@@ -1188,8 +1183,9 @@ static int dapm_mixer_update_power(struct snd_soc_dapm_widget *widget, | |||
1188 | static ssize_t dapm_widget_show(struct device *dev, | 1183 | static ssize_t dapm_widget_show(struct device *dev, |
1189 | struct device_attribute *attr, char *buf) | 1184 | struct device_attribute *attr, char *buf) |
1190 | { | 1185 | { |
1191 | struct snd_soc_device *devdata = dev_get_drvdata(dev); | 1186 | struct snd_soc_pcm_runtime *rtd = |
1192 | struct snd_soc_codec *codec = devdata->card->codec; | 1187 | container_of(dev, struct snd_soc_pcm_runtime, dev); |
1188 | struct snd_soc_codec *codec =rtd->codec; | ||
1193 | struct snd_soc_dapm_widget *w; | 1189 | struct snd_soc_dapm_widget *w; |
1194 | int count = 0; | 1190 | int count = 0; |
1195 | char *state = "not set"; | 1191 | char *state = "not set"; |
@@ -1998,9 +1994,10 @@ EXPORT_SYMBOL_GPL(snd_soc_dapm_new_controls); | |||
1998 | * | 1994 | * |
1999 | * Returns 0 for success else error. | 1995 | * Returns 0 for success else error. |
2000 | */ | 1996 | */ |
2001 | int snd_soc_dapm_stream_event(struct snd_soc_codec *codec, | 1997 | int snd_soc_dapm_stream_event(struct snd_soc_pcm_runtime *rtd, |
2002 | char *stream, int event) | 1998 | const char *stream, int event) |
2003 | { | 1999 | { |
2000 | struct snd_soc_codec *codec = rtd->codec; | ||
2004 | struct snd_soc_dapm_widget *w; | 2001 | struct snd_soc_dapm_widget *w; |
2005 | 2002 | ||
2006 | if (stream == NULL) | 2003 | if (stream == NULL) |
@@ -2168,25 +2165,19 @@ EXPORT_SYMBOL_GPL(snd_soc_dapm_ignore_suspend); | |||
2168 | 2165 | ||
2169 | /** | 2166 | /** |
2170 | * snd_soc_dapm_free - free dapm resources | 2167 | * snd_soc_dapm_free - free dapm resources |
2171 | * @socdev: SoC device | 2168 | * @card: SoC device |
2172 | * | 2169 | * |
2173 | * Free all dapm widgets and resources. | 2170 | * Free all dapm widgets and resources. |
2174 | */ | 2171 | */ |
2175 | void snd_soc_dapm_free(struct snd_soc_device *socdev) | 2172 | void snd_soc_dapm_free(struct snd_soc_codec *codec) |
2176 | { | 2173 | { |
2177 | struct snd_soc_codec *codec = socdev->card->codec; | 2174 | snd_soc_dapm_sys_remove(codec->dev); |
2178 | |||
2179 | snd_soc_dapm_sys_remove(socdev->dev); | ||
2180 | dapm_free_widgets(codec); | 2175 | dapm_free_widgets(codec); |
2181 | } | 2176 | } |
2182 | EXPORT_SYMBOL_GPL(snd_soc_dapm_free); | 2177 | EXPORT_SYMBOL_GPL(snd_soc_dapm_free); |
2183 | 2178 | ||
2184 | /* | 2179 | static void soc_dapm_shutdown_codec(struct snd_soc_codec *codec) |
2185 | * snd_soc_dapm_shutdown - callback for system shutdown | ||
2186 | */ | ||
2187 | void snd_soc_dapm_shutdown(struct snd_soc_device *socdev) | ||
2188 | { | 2180 | { |
2189 | struct snd_soc_codec *codec = socdev->card->codec; | ||
2190 | struct snd_soc_dapm_widget *w; | 2181 | struct snd_soc_dapm_widget *w; |
2191 | LIST_HEAD(down_list); | 2182 | LIST_HEAD(down_list); |
2192 | int powerdown = 0; | 2183 | int powerdown = 0; |
@@ -2203,12 +2194,23 @@ void snd_soc_dapm_shutdown(struct snd_soc_device *socdev) | |||
2203 | * standby. | 2194 | * standby. |
2204 | */ | 2195 | */ |
2205 | if (powerdown) { | 2196 | if (powerdown) { |
2206 | snd_soc_dapm_set_bias_level(socdev, SND_SOC_BIAS_PREPARE); | 2197 | snd_soc_dapm_set_bias_level(NULL, codec, SND_SOC_BIAS_PREPARE); |
2207 | dapm_seq_run(codec, &down_list, 0, dapm_down_seq); | 2198 | dapm_seq_run(codec, &down_list, 0, dapm_down_seq); |
2208 | snd_soc_dapm_set_bias_level(socdev, SND_SOC_BIAS_STANDBY); | 2199 | snd_soc_dapm_set_bias_level(NULL, codec, SND_SOC_BIAS_STANDBY); |
2209 | } | 2200 | } |
2201 | } | ||
2202 | |||
2203 | /* | ||
2204 | * snd_soc_dapm_shutdown - callback for system shutdown | ||
2205 | */ | ||
2206 | void snd_soc_dapm_shutdown(struct snd_soc_card *card) | ||
2207 | { | ||
2208 | struct snd_soc_codec *codec; | ||
2209 | |||
2210 | list_for_each_entry(codec, &card->codec_dev_list, list) | ||
2211 | soc_dapm_shutdown_codec(codec); | ||
2210 | 2212 | ||
2211 | snd_soc_dapm_set_bias_level(socdev, SND_SOC_BIAS_OFF); | 2213 | snd_soc_dapm_set_bias_level(card, codec, SND_SOC_BIAS_OFF); |
2212 | } | 2214 | } |
2213 | 2215 | ||
2214 | /* Module information */ | 2216 | /* Module information */ |
diff --git a/sound/soc/soc-jack.c b/sound/soc/soc-jack.c index 29159e1781d0..8862770aa221 100644 --- a/sound/soc/soc-jack.c +++ b/sound/soc/soc-jack.c | |||
@@ -32,14 +32,14 @@ | |||
32 | * Returns zero if successful, or a negative error code on failure. | 32 | * Returns zero if successful, or a negative error code on failure. |
33 | * On success jack will be initialised. | 33 | * On success jack will be initialised. |
34 | */ | 34 | */ |
35 | int snd_soc_jack_new(struct snd_soc_card *card, const char *id, int type, | 35 | int snd_soc_jack_new(struct snd_soc_codec *codec, const char *id, int type, |
36 | struct snd_soc_jack *jack) | 36 | struct snd_soc_jack *jack) |
37 | { | 37 | { |
38 | jack->card = card; | 38 | jack->codec = codec; |
39 | INIT_LIST_HEAD(&jack->pins); | 39 | INIT_LIST_HEAD(&jack->pins); |
40 | BLOCKING_INIT_NOTIFIER_HEAD(&jack->notifier); | 40 | BLOCKING_INIT_NOTIFIER_HEAD(&jack->notifier); |
41 | 41 | ||
42 | return snd_jack_new(card->codec->card, id, type, &jack->jack); | 42 | return snd_jack_new(codec->card->snd_card, id, type, &jack->jack); |
43 | } | 43 | } |
44 | EXPORT_SYMBOL_GPL(snd_soc_jack_new); | 44 | EXPORT_SYMBOL_GPL(snd_soc_jack_new); |
45 | 45 | ||
@@ -67,7 +67,7 @@ void snd_soc_jack_report(struct snd_soc_jack *jack, int status, int mask) | |||
67 | if (!jack) | 67 | if (!jack) |
68 | return; | 68 | return; |
69 | 69 | ||
70 | codec = jack->card->codec; | 70 | codec = jack->codec; |
71 | 71 | ||
72 | mutex_lock(&codec->mutex); | 72 | mutex_lock(&codec->mutex); |
73 | 73 | ||
@@ -268,7 +268,7 @@ int snd_soc_jack_add_gpios(struct snd_soc_jack *jack, int count, | |||
268 | ret = request_irq(gpio_to_irq(gpios[i].gpio), | 268 | ret = request_irq(gpio_to_irq(gpios[i].gpio), |
269 | gpio_handler, | 269 | gpio_handler, |
270 | IRQF_TRIGGER_RISING | IRQF_TRIGGER_FALLING, | 270 | IRQF_TRIGGER_RISING | IRQF_TRIGGER_FALLING, |
271 | jack->card->dev->driver->name, | 271 | jack->codec->dev->driver->name, |
272 | &gpios[i]); | 272 | &gpios[i]); |
273 | if (ret) | 273 | if (ret) |
274 | goto err; | 274 | goto err; |
diff --git a/sound/soc/txx9/txx9aclc-ac97.c b/sound/soc/txx9/txx9aclc-ac97.c index 0ec20b68e8cb..743d07b82c06 100644 --- a/sound/soc/txx9/txx9aclc-ac97.c +++ b/sound/soc/txx9/txx9aclc-ac97.c | |||
@@ -36,13 +36,11 @@ | |||
36 | 36 | ||
37 | static DECLARE_WAIT_QUEUE_HEAD(ac97_waitq); | 37 | static DECLARE_WAIT_QUEUE_HEAD(ac97_waitq); |
38 | 38 | ||
39 | /* REVISIT: How to find txx9aclc_soc_device from snd_ac97? */ | 39 | /* REVISIT: How to find txx9aclc_drvdata from snd_ac97? */ |
40 | static struct txx9aclc_soc_device *txx9aclc_soc_dev; | 40 | static struct txx9aclc_plat_drvdata *txx9aclc_drvdata; |
41 | 41 | ||
42 | static int txx9aclc_regready(struct txx9aclc_soc_device *dev) | 42 | static int txx9aclc_regready(struct txx9aclc_plat_drvdata *drvdata) |
43 | { | 43 | { |
44 | struct txx9aclc_plat_drvdata *drvdata = txx9aclc_get_plat_drvdata(dev); | ||
45 | |||
46 | return __raw_readl(drvdata->base + ACINTSTS) & ACINT_REGACCRDY; | 44 | return __raw_readl(drvdata->base + ACINTSTS) & ACINT_REGACCRDY; |
47 | } | 45 | } |
48 | 46 | ||
@@ -50,8 +48,7 @@ static int txx9aclc_regready(struct txx9aclc_soc_device *dev) | |||
50 | static unsigned short txx9aclc_ac97_read(struct snd_ac97 *ac97, | 48 | static unsigned short txx9aclc_ac97_read(struct snd_ac97 *ac97, |
51 | unsigned short reg) | 49 | unsigned short reg) |
52 | { | 50 | { |
53 | struct txx9aclc_soc_device *dev = txx9aclc_soc_dev; | 51 | struct txx9aclc_plat_drvdata *drvdata = txx9aclc_drvdata; |
54 | struct txx9aclc_plat_drvdata *drvdata = txx9aclc_get_plat_drvdata(dev); | ||
55 | void __iomem *base = drvdata->base; | 52 | void __iomem *base = drvdata->base; |
56 | u32 dat; | 53 | u32 dat; |
57 | 54 | ||
@@ -61,15 +58,15 @@ static unsigned short txx9aclc_ac97_read(struct snd_ac97 *ac97, | |||
61 | dat = (reg << ACREGACC_REG_SHIFT) | ACREGACC_READ; | 58 | dat = (reg << ACREGACC_REG_SHIFT) | ACREGACC_READ; |
62 | __raw_writel(dat, base + ACREGACC); | 59 | __raw_writel(dat, base + ACREGACC); |
63 | __raw_writel(ACINT_REGACCRDY, base + ACINTEN); | 60 | __raw_writel(ACINT_REGACCRDY, base + ACINTEN); |
64 | if (!wait_event_timeout(ac97_waitq, txx9aclc_regready(dev), HZ)) { | 61 | if (!wait_event_timeout(ac97_waitq, txx9aclc_regready(txx9aclc_drvdata), HZ)) { |
65 | __raw_writel(ACINT_REGACCRDY, base + ACINTDIS); | 62 | __raw_writel(ACINT_REGACCRDY, base + ACINTDIS); |
66 | dev_err(dev->soc_dev.dev, "ac97 read timeout (reg %#x)\n", reg); | 63 | printk(KERN_ERR "ac97 read timeout (reg %#x)\n", reg); |
67 | dat = 0xffff; | 64 | dat = 0xffff; |
68 | goto done; | 65 | goto done; |
69 | } | 66 | } |
70 | dat = __raw_readl(base + ACREGACC); | 67 | dat = __raw_readl(base + ACREGACC); |
71 | if (((dat >> ACREGACC_REG_SHIFT) & 0xff) != reg) { | 68 | if (((dat >> ACREGACC_REG_SHIFT) & 0xff) != reg) { |
72 | dev_err(dev->soc_dev.dev, "reg mismatch %x with %x\n", | 69 | printk(KERN_ERR "reg mismatch %x with %x\n", |
73 | dat, reg); | 70 | dat, reg); |
74 | dat = 0xffff; | 71 | dat = 0xffff; |
75 | goto done; | 72 | goto done; |
@@ -84,16 +81,15 @@ done: | |||
84 | static void txx9aclc_ac97_write(struct snd_ac97 *ac97, unsigned short reg, | 81 | static void txx9aclc_ac97_write(struct snd_ac97 *ac97, unsigned short reg, |
85 | unsigned short val) | 82 | unsigned short val) |
86 | { | 83 | { |
87 | struct txx9aclc_soc_device *dev = txx9aclc_soc_dev; | 84 | struct txx9aclc_plat_drvdata *drvdata = txx9aclc_drvdata; |
88 | struct txx9aclc_plat_drvdata *drvdata = txx9aclc_get_plat_drvdata(dev); | ||
89 | void __iomem *base = drvdata->base; | 85 | void __iomem *base = drvdata->base; |
90 | 86 | ||
91 | __raw_writel(((reg | (ac97->num << 7)) << ACREGACC_REG_SHIFT) | | 87 | __raw_writel(((reg | (ac97->num << 7)) << ACREGACC_REG_SHIFT) | |
92 | (val << ACREGACC_DAT_SHIFT), | 88 | (val << ACREGACC_DAT_SHIFT), |
93 | base + ACREGACC); | 89 | base + ACREGACC); |
94 | __raw_writel(ACINT_REGACCRDY, base + ACINTEN); | 90 | __raw_writel(ACINT_REGACCRDY, base + ACINTEN); |
95 | if (!wait_event_timeout(ac97_waitq, txx9aclc_regready(dev), HZ)) { | 91 | if (!wait_event_timeout(ac97_waitq, txx9aclc_regready(txx9aclc_drvdata), HZ)) { |
96 | dev_err(dev->soc_dev.dev, | 92 | printk(KERN_ERR |
97 | "ac97 write timeout (reg %#x)\n", reg); | 93 | "ac97 write timeout (reg %#x)\n", reg); |
98 | } | 94 | } |
99 | __raw_writel(ACINT_REGACCRDY, base + ACINTDIS); | 95 | __raw_writel(ACINT_REGACCRDY, base + ACINTDIS); |
@@ -101,8 +97,7 @@ static void txx9aclc_ac97_write(struct snd_ac97 *ac97, unsigned short reg, | |||
101 | 97 | ||
102 | static void txx9aclc_ac97_cold_reset(struct snd_ac97 *ac97) | 98 | static void txx9aclc_ac97_cold_reset(struct snd_ac97 *ac97) |
103 | { | 99 | { |
104 | struct txx9aclc_soc_device *dev = txx9aclc_soc_dev; | 100 | struct txx9aclc_plat_drvdata *drvdata = txx9aclc_drvdata; |
105 | struct txx9aclc_plat_drvdata *drvdata = txx9aclc_get_plat_drvdata(dev); | ||
106 | void __iomem *base = drvdata->base; | 101 | void __iomem *base = drvdata->base; |
107 | u32 ready = ACINT_CODECRDY(ac97->num) | ACINT_REGACCRDY; | 102 | u32 ready = ACINT_CODECRDY(ac97->num) | ACINT_REGACCRDY; |
108 | 103 | ||
@@ -141,31 +136,23 @@ static irqreturn_t txx9aclc_ac97_irq(int irq, void *dev_id) | |||
141 | return IRQ_HANDLED; | 136 | return IRQ_HANDLED; |
142 | } | 137 | } |
143 | 138 | ||
144 | static int txx9aclc_ac97_probe(struct platform_device *pdev, | 139 | static int txx9aclc_ac97_probe(struct snd_soc_dai *dai) |
145 | struct snd_soc_dai *dai) | ||
146 | { | 140 | { |
147 | struct snd_soc_device *socdev = platform_get_drvdata(pdev); | 141 | txx9aclc_drvdata = snd_soc_dai_get_drvdata(dai); |
148 | struct txx9aclc_soc_device *dev = | ||
149 | container_of(socdev, struct txx9aclc_soc_device, soc_dev); | ||
150 | |||
151 | dev->aclc_pdev = to_platform_device(dai->dev); | ||
152 | txx9aclc_soc_dev = dev; | ||
153 | return 0; | 142 | return 0; |
154 | } | 143 | } |
155 | 144 | ||
156 | static void txx9aclc_ac97_remove(struct platform_device *pdev, | 145 | static int txx9aclc_ac97_remove(struct snd_soc_dai *dai) |
157 | struct snd_soc_dai *dai) | ||
158 | { | 146 | { |
159 | struct platform_device *aclc_pdev = to_platform_device(dai->dev); | 147 | struct txx9aclc_plat_drvdata *drvdata = snd_soc_dai_get_drvdata(dai); |
160 | struct txx9aclc_plat_drvdata *drvdata = platform_get_drvdata(aclc_pdev); | ||
161 | 148 | ||
162 | /* disable AC-link */ | 149 | /* disable AC-link */ |
163 | __raw_writel(ACCTL_ENLINK, drvdata->base + ACCTLDIS); | 150 | __raw_writel(ACCTL_ENLINK, drvdata->base + ACCTLDIS); |
164 | txx9aclc_soc_dev = NULL; | 151 | txx9aclc_drvdata = NULL; |
152 | return 0; | ||
165 | } | 153 | } |
166 | 154 | ||
167 | struct snd_soc_dai txx9aclc_ac97_dai = { | 155 | static struct snd_soc_dai_driver txx9aclc_ac97_dai = { |
168 | .name = "txx9aclc_ac97", | ||
169 | .ac97_control = 1, | 156 | .ac97_control = 1, |
170 | .probe = txx9aclc_ac97_probe, | 157 | .probe = txx9aclc_ac97_probe, |
171 | .remove = txx9aclc_ac97_remove, | 158 | .remove = txx9aclc_ac97_remove, |
@@ -182,7 +169,6 @@ struct snd_soc_dai txx9aclc_ac97_dai = { | |||
182 | .channels_max = 2, | 169 | .channels_max = 2, |
183 | }, | 170 | }, |
184 | }; | 171 | }; |
185 | EXPORT_SYMBOL_GPL(txx9aclc_ac97_dai); | ||
186 | 172 | ||
187 | static int __devinit txx9aclc_ac97_dev_probe(struct platform_device *pdev) | 173 | static int __devinit txx9aclc_ac97_dev_probe(struct platform_device *pdev) |
188 | { | 174 | { |
@@ -219,13 +205,12 @@ static int __devinit txx9aclc_ac97_dev_probe(struct platform_device *pdev) | |||
219 | if (err < 0) | 205 | if (err < 0) |
220 | return err; | 206 | return err; |
221 | 207 | ||
222 | txx9aclc_ac97_dai.dev = &pdev->dev; | 208 | return snd_soc_register_dai(&pdev->dev, &txx9aclc_ac97_dai); |
223 | return snd_soc_register_dai(&txx9aclc_ac97_dai); | ||
224 | } | 209 | } |
225 | 210 | ||
226 | static int __devexit txx9aclc_ac97_dev_remove(struct platform_device *pdev) | 211 | static int __devexit txx9aclc_ac97_dev_remove(struct platform_device *pdev) |
227 | { | 212 | { |
228 | snd_soc_unregister_dai(&txx9aclc_ac97_dai); | 213 | snd_soc_unregister_dai(&pdev->dev); |
229 | return 0; | 214 | return 0; |
230 | } | 215 | } |
231 | 216 | ||
diff --git a/sound/soc/txx9/txx9aclc-generic.c b/sound/soc/txx9/txx9aclc-generic.c index 95b17f731aec..6770e7166be4 100644 --- a/sound/soc/txx9/txx9aclc-generic.c +++ b/sound/soc/txx9/txx9aclc-generic.c | |||
@@ -19,54 +19,44 @@ | |||
19 | #include <sound/core.h> | 19 | #include <sound/core.h> |
20 | #include <sound/pcm.h> | 20 | #include <sound/pcm.h> |
21 | #include <sound/soc.h> | 21 | #include <sound/soc.h> |
22 | #include "../codecs/ac97.h" | ||
23 | #include "txx9aclc.h" | 22 | #include "txx9aclc.h" |
24 | 23 | ||
25 | static struct snd_soc_dai_link txx9aclc_generic_dai = { | 24 | static struct snd_soc_dai_link txx9aclc_generic_dai = { |
26 | .name = "AC97", | 25 | .name = "AC97", |
27 | .stream_name = "AC97 HiFi", | 26 | .stream_name = "AC97 HiFi", |
28 | .cpu_dai = &txx9aclc_ac97_dai, | 27 | .cpu_dai_name = "txx9aclc-ac97", |
29 | .codec_dai = &ac97_dai, | 28 | .codec_dai_name = "ac97-hifi", |
29 | .platform_name = "txx9aclc-pcm-audio", | ||
30 | .codec_name = "ac97-codec", | ||
30 | }; | 31 | }; |
31 | 32 | ||
32 | static struct snd_soc_card txx9aclc_generic_card = { | 33 | static struct snd_soc_card txx9aclc_generic_card = { |
33 | .name = "Generic TXx9 ACLC Audio", | 34 | .name = "Generic TXx9 ACLC Audio", |
34 | .platform = &txx9aclc_soc_platform, | ||
35 | .dai_link = &txx9aclc_generic_dai, | 35 | .dai_link = &txx9aclc_generic_dai, |
36 | .num_links = 1, | 36 | .num_links = 1, |
37 | }; | 37 | }; |
38 | 38 | ||
39 | static struct txx9aclc_soc_device txx9aclc_generic_soc_device = { | 39 | static struct platform_device *soc_pdev; |
40 | .soc_dev = { | ||
41 | .card = &txx9aclc_generic_card, | ||
42 | .codec_dev = &soc_codec_dev_ac97, | ||
43 | }, | ||
44 | }; | ||
45 | 40 | ||
46 | static int __init txx9aclc_generic_probe(struct platform_device *pdev) | 41 | static int __init txx9aclc_generic_probe(struct platform_device *pdev) |
47 | { | 42 | { |
48 | struct txx9aclc_soc_device *dev = &txx9aclc_generic_soc_device; | ||
49 | struct platform_device *soc_pdev; | ||
50 | int ret; | 43 | int ret; |
51 | 44 | ||
52 | soc_pdev = platform_device_alloc("soc-audio", -1); | 45 | soc_pdev = platform_device_alloc("soc-audio", -1); |
53 | if (!soc_pdev) | 46 | if (!soc_pdev) |
54 | return -ENOMEM; | 47 | return -ENOMEM; |
55 | platform_set_drvdata(soc_pdev, &dev->soc_dev); | 48 | platform_set_drvdata(soc_pdev, &txx9aclc_generic_card); |
56 | dev->soc_dev.dev = &soc_pdev->dev; | ||
57 | ret = platform_device_add(soc_pdev); | 49 | ret = platform_device_add(soc_pdev); |
58 | if (ret) { | 50 | if (ret) { |
59 | platform_device_put(soc_pdev); | 51 | platform_device_put(soc_pdev); |
60 | return ret; | 52 | return ret; |
61 | } | 53 | } |
62 | platform_set_drvdata(pdev, soc_pdev); | 54 | |
63 | return 0; | 55 | return 0; |
64 | } | 56 | } |
65 | 57 | ||
66 | static int __exit txx9aclc_generic_remove(struct platform_device *pdev) | 58 | static int __exit txx9aclc_generic_remove(struct platform_device *pdev) |
67 | { | 59 | { |
68 | struct platform_device *soc_pdev = platform_get_drvdata(pdev); | ||
69 | |||
70 | platform_device_unregister(soc_pdev); | 60 | platform_device_unregister(soc_pdev); |
71 | return 0; | 61 | return 0; |
72 | } | 62 | } |
diff --git a/sound/soc/txx9/txx9aclc.c b/sound/soc/txx9/txx9aclc.c index 0e3452303ea6..f4aa4e03c888 100644 --- a/sound/soc/txx9/txx9aclc.c +++ b/sound/soc/txx9/txx9aclc.c | |||
@@ -22,6 +22,16 @@ | |||
22 | #include <sound/soc.h> | 22 | #include <sound/soc.h> |
23 | #include "txx9aclc.h" | 23 | #include "txx9aclc.h" |
24 | 24 | ||
25 | static struct txx9aclc_soc_device { | ||
26 | struct txx9aclc_dmadata dmadata[2]; | ||
27 | } txx9aclc_soc_device; | ||
28 | |||
29 | /* REVISIT: How to find txx9aclc_drvdata from snd_ac97? */ | ||
30 | static struct txx9aclc_plat_drvdata *txx9aclc_drvdata; | ||
31 | |||
32 | static int txx9aclc_dma_init(struct txx9aclc_soc_device *dev, | ||
33 | struct txx9aclc_dmadata *dmadata); | ||
34 | |||
25 | static const struct snd_pcm_hardware txx9aclc_pcm_hardware = { | 35 | static const struct snd_pcm_hardware txx9aclc_pcm_hardware = { |
26 | /* | 36 | /* |
27 | * REVISIT: SNDRV_PCM_INFO_MMAP | SNDRV_PCM_INFO_MMAP_VALID | 37 | * REVISIT: SNDRV_PCM_INFO_MMAP | SNDRV_PCM_INFO_MMAP_VALID |
@@ -46,7 +56,6 @@ static int txx9aclc_pcm_hw_params(struct snd_pcm_substream *substream, | |||
46 | struct snd_pcm_hw_params *params) | 56 | struct snd_pcm_hw_params *params) |
47 | { | 57 | { |
48 | struct snd_soc_pcm_runtime *rtd = snd_pcm_substream_chip(substream); | 58 | struct snd_soc_pcm_runtime *rtd = snd_pcm_substream_chip(substream); |
49 | struct snd_soc_device *socdev = rtd->socdev; | ||
50 | struct snd_pcm_runtime *runtime = substream->runtime; | 59 | struct snd_pcm_runtime *runtime = substream->runtime; |
51 | struct txx9aclc_dmadata *dmadata = runtime->private_data; | 60 | struct txx9aclc_dmadata *dmadata = runtime->private_data; |
52 | int ret; | 61 | int ret; |
@@ -55,13 +64,13 @@ static int txx9aclc_pcm_hw_params(struct snd_pcm_substream *substream, | |||
55 | if (ret < 0) | 64 | if (ret < 0) |
56 | return ret; | 65 | return ret; |
57 | 66 | ||
58 | dev_dbg(socdev->dev, | 67 | dev_dbg(rtd->platform->dev, |
59 | "runtime->dma_area = %#lx dma_addr = %#lx dma_bytes = %zd " | 68 | "runtime->dma_area = %#lx dma_addr = %#lx dma_bytes = %zd " |
60 | "runtime->min_align %ld\n", | 69 | "runtime->min_align %ld\n", |
61 | (unsigned long)runtime->dma_area, | 70 | (unsigned long)runtime->dma_area, |
62 | (unsigned long)runtime->dma_addr, runtime->dma_bytes, | 71 | (unsigned long)runtime->dma_addr, runtime->dma_bytes, |
63 | runtime->min_align); | 72 | runtime->min_align); |
64 | dev_dbg(socdev->dev, | 73 | dev_dbg(rtd->platform->dev, |
65 | "periods %d period_bytes %d stream %d\n", | 74 | "periods %d period_bytes %d stream %d\n", |
66 | params_periods(params), params_period_bytes(params), | 75 | params_periods(params), params_period_bytes(params), |
67 | substream->stream); | 76 | substream->stream); |
@@ -152,11 +161,7 @@ static void txx9aclc_dma_tasklet(unsigned long data) | |||
152 | 161 | ||
153 | spin_lock_irqsave(&dmadata->dma_lock, flags); | 162 | spin_lock_irqsave(&dmadata->dma_lock, flags); |
154 | if (dmadata->frag_count < 0) { | 163 | if (dmadata->frag_count < 0) { |
155 | struct txx9aclc_soc_device *dev = | 164 | struct txx9aclc_plat_drvdata *drvdata = txx9aclc_drvdata; |
156 | container_of(dmadata, struct txx9aclc_soc_device, | ||
157 | dmadata[substream->stream]); | ||
158 | struct txx9aclc_plat_drvdata *drvdata = | ||
159 | txx9aclc_get_plat_drvdata(dev); | ||
160 | void __iomem *base = drvdata->base; | 165 | void __iomem *base = drvdata->base; |
161 | 166 | ||
162 | spin_unlock_irqrestore(&dmadata->dma_lock, flags); | 167 | spin_unlock_irqrestore(&dmadata->dma_lock, flags); |
@@ -202,10 +207,7 @@ static void txx9aclc_dma_tasklet(unsigned long data) | |||
202 | static int txx9aclc_pcm_trigger(struct snd_pcm_substream *substream, int cmd) | 207 | static int txx9aclc_pcm_trigger(struct snd_pcm_substream *substream, int cmd) |
203 | { | 208 | { |
204 | struct txx9aclc_dmadata *dmadata = substream->runtime->private_data; | 209 | struct txx9aclc_dmadata *dmadata = substream->runtime->private_data; |
205 | struct snd_soc_pcm_runtime *rtd = substream->private_data; | 210 | struct txx9aclc_plat_drvdata *drvdata =txx9aclc_drvdata; |
206 | struct txx9aclc_soc_device *dev = | ||
207 | container_of(rtd->socdev, struct txx9aclc_soc_device, soc_dev); | ||
208 | struct txx9aclc_plat_drvdata *drvdata = txx9aclc_get_plat_drvdata(dev); | ||
209 | void __iomem *base = drvdata->base; | 211 | void __iomem *base = drvdata->base; |
210 | unsigned long flags; | 212 | unsigned long flags; |
211 | int ret = 0; | 213 | int ret = 0; |
@@ -244,9 +246,7 @@ txx9aclc_pcm_pointer(struct snd_pcm_substream *substream) | |||
244 | 246 | ||
245 | static int txx9aclc_pcm_open(struct snd_pcm_substream *substream) | 247 | static int txx9aclc_pcm_open(struct snd_pcm_substream *substream) |
246 | { | 248 | { |
247 | struct snd_soc_pcm_runtime *rtd = substream->private_data; | 249 | struct txx9aclc_soc_device *dev = &txx9aclc_soc_device; |
248 | struct txx9aclc_soc_device *dev = | ||
249 | container_of(rtd->socdev, struct txx9aclc_soc_device, soc_dev); | ||
250 | struct txx9aclc_dmadata *dmadata = &dev->dmadata[substream->stream]; | 250 | struct txx9aclc_dmadata *dmadata = &dev->dmadata[substream->stream]; |
251 | int ret; | 251 | int ret; |
252 | 252 | ||
@@ -291,8 +291,38 @@ static void txx9aclc_pcm_free_dma_buffers(struct snd_pcm *pcm) | |||
291 | static int txx9aclc_pcm_new(struct snd_card *card, struct snd_soc_dai *dai, | 291 | static int txx9aclc_pcm_new(struct snd_card *card, struct snd_soc_dai *dai, |
292 | struct snd_pcm *pcm) | 292 | struct snd_pcm *pcm) |
293 | { | 293 | { |
294 | struct platform_device *pdev = to_platform_device(dai->platform->dev); | ||
295 | struct txx9aclc_soc_device *dev; | ||
296 | struct resource *r; | ||
297 | int i; | ||
298 | int ret; | ||
299 | |||
300 | /* at this point onwards the AC97 component has probed and this will be valid */ | ||
301 | dev = snd_soc_dai_get_drvdata(dai); | ||
302 | |||
303 | dev->dmadata[0].stream = SNDRV_PCM_STREAM_PLAYBACK; | ||
304 | dev->dmadata[1].stream = SNDRV_PCM_STREAM_CAPTURE; | ||
305 | for (i = 0; i < 2; i++) { | ||
306 | r = platform_get_resource(pdev, IORESOURCE_DMA, i); | ||
307 | if (!r) { | ||
308 | ret = -EBUSY; | ||
309 | goto exit; | ||
310 | } | ||
311 | dev->dmadata[i].dma_res = r; | ||
312 | ret = txx9aclc_dma_init(dev, &dev->dmadata[i]); | ||
313 | if (ret) | ||
314 | goto exit; | ||
315 | } | ||
294 | return snd_pcm_lib_preallocate_pages_for_all(pcm, SNDRV_DMA_TYPE_DEV, | 316 | return snd_pcm_lib_preallocate_pages_for_all(pcm, SNDRV_DMA_TYPE_DEV, |
295 | card->dev, 64 * 1024, 4 * 1024 * 1024); | 317 | card->dev, 64 * 1024, 4 * 1024 * 1024); |
318 | |||
319 | exit: | ||
320 | for (i = 0; i < 2; i++) { | ||
321 | if (dev->dmadata[i].dma_chan) | ||
322 | dma_release_channel(dev->dmadata[i].dma_chan); | ||
323 | dev->dmadata[i].dma_chan = NULL; | ||
324 | } | ||
325 | return ret; | ||
296 | } | 326 | } |
297 | 327 | ||
298 | static bool filter(struct dma_chan *chan, void *param) | 328 | static bool filter(struct dma_chan *chan, void *param) |
@@ -314,7 +344,7 @@ static bool filter(struct dma_chan *chan, void *param) | |||
314 | static int txx9aclc_dma_init(struct txx9aclc_soc_device *dev, | 344 | static int txx9aclc_dma_init(struct txx9aclc_soc_device *dev, |
315 | struct txx9aclc_dmadata *dmadata) | 345 | struct txx9aclc_dmadata *dmadata) |
316 | { | 346 | { |
317 | struct txx9aclc_plat_drvdata *drvdata = txx9aclc_get_plat_drvdata(dev); | 347 | struct txx9aclc_plat_drvdata *drvdata =txx9aclc_drvdata; |
318 | struct txx9dmac_slave *ds = &dmadata->dma_slave; | 348 | struct txx9dmac_slave *ds = &dmadata->dma_slave; |
319 | dma_cap_mask_t mask; | 349 | dma_cap_mask_t mask; |
320 | 350 | ||
@@ -334,7 +364,7 @@ static int txx9aclc_dma_init(struct txx9aclc_soc_device *dev, | |||
334 | dma_cap_set(DMA_SLAVE, mask); | 364 | dma_cap_set(DMA_SLAVE, mask); |
335 | dmadata->dma_chan = dma_request_channel(mask, filter, dmadata); | 365 | dmadata->dma_chan = dma_request_channel(mask, filter, dmadata); |
336 | if (!dmadata->dma_chan) { | 366 | if (!dmadata->dma_chan) { |
337 | dev_err(dev->soc_dev.dev, | 367 | printk(KERN_ERR |
338 | "DMA channel for %s is not available\n", | 368 | "DMA channel for %s is not available\n", |
339 | dmadata->stream == SNDRV_PCM_STREAM_PLAYBACK ? | 369 | dmadata->stream == SNDRV_PCM_STREAM_PLAYBACK ? |
340 | "playback" : "capture"); | 370 | "playback" : "capture"); |
@@ -345,45 +375,16 @@ static int txx9aclc_dma_init(struct txx9aclc_soc_device *dev, | |||
345 | return 0; | 375 | return 0; |
346 | } | 376 | } |
347 | 377 | ||
348 | static int txx9aclc_pcm_probe(struct platform_device *pdev) | 378 | static int txx9aclc_pcm_probe(struct snd_soc_platform *platform) |
349 | { | 379 | { |
350 | struct snd_soc_device *socdev = platform_get_drvdata(pdev); | 380 | snd_soc_platform_set_drvdata(platform, &txx9aclc_soc_device); |
351 | struct txx9aclc_soc_device *dev = | ||
352 | container_of(socdev, struct txx9aclc_soc_device, soc_dev); | ||
353 | struct resource *r; | ||
354 | int i; | ||
355 | int ret; | ||
356 | |||
357 | dev->dmadata[0].stream = SNDRV_PCM_STREAM_PLAYBACK; | ||
358 | dev->dmadata[1].stream = SNDRV_PCM_STREAM_CAPTURE; | ||
359 | for (i = 0; i < 2; i++) { | ||
360 | r = platform_get_resource(dev->aclc_pdev, IORESOURCE_DMA, i); | ||
361 | if (!r) { | ||
362 | ret = -EBUSY; | ||
363 | goto exit; | ||
364 | } | ||
365 | dev->dmadata[i].dma_res = r; | ||
366 | ret = txx9aclc_dma_init(dev, &dev->dmadata[i]); | ||
367 | if (ret) | ||
368 | goto exit; | ||
369 | } | ||
370 | return 0; | 381 | return 0; |
371 | |||
372 | exit: | ||
373 | for (i = 0; i < 2; i++) { | ||
374 | if (dev->dmadata[i].dma_chan) | ||
375 | dma_release_channel(dev->dmadata[i].dma_chan); | ||
376 | dev->dmadata[i].dma_chan = NULL; | ||
377 | } | ||
378 | return ret; | ||
379 | } | 382 | } |
380 | 383 | ||
381 | static int txx9aclc_pcm_remove(struct platform_device *pdev) | 384 | static int txx9aclc_pcm_remove(struct snd_soc_platform *platform) |
382 | { | 385 | { |
383 | struct snd_soc_device *socdev = platform_get_drvdata(pdev); | 386 | struct txx9aclc_soc_device *dev = snd_soc_platform_get_drvdata(platform); |
384 | struct txx9aclc_soc_device *dev = | 387 | struct txx9aclc_plat_drvdata *drvdata = txx9aclc_drvdata; |
385 | container_of(socdev, struct txx9aclc_soc_device, soc_dev); | ||
386 | struct txx9aclc_plat_drvdata *drvdata = txx9aclc_get_plat_drvdata(dev); | ||
387 | void __iomem *base = drvdata->base; | 388 | void __iomem *base = drvdata->base; |
388 | int i; | 389 | int i; |
389 | 390 | ||
@@ -406,28 +407,46 @@ static int txx9aclc_pcm_remove(struct platform_device *pdev) | |||
406 | return 0; | 407 | return 0; |
407 | } | 408 | } |
408 | 409 | ||
409 | struct snd_soc_platform txx9aclc_soc_platform = { | 410 | static struct snd_soc_platform_driver txx9aclc_soc_platform = { |
410 | .name = "txx9aclc-audio", | ||
411 | .probe = txx9aclc_pcm_probe, | 411 | .probe = txx9aclc_pcm_probe, |
412 | .remove = txx9aclc_pcm_remove, | 412 | .remove = txx9aclc_pcm_remove, |
413 | .pcm_ops = &txx9aclc_pcm_ops, | 413 | .ops = &txx9aclc_pcm_ops, |
414 | .pcm_new = txx9aclc_pcm_new, | 414 | .pcm_new = txx9aclc_pcm_new, |
415 | .pcm_free = txx9aclc_pcm_free_dma_buffers, | 415 | .pcm_free = txx9aclc_pcm_free_dma_buffers, |
416 | }; | 416 | }; |
417 | EXPORT_SYMBOL_GPL(txx9aclc_soc_platform); | ||
418 | 417 | ||
419 | static int __init txx9aclc_soc_platform_init(void) | 418 | static int __devinit txx9aclc_soc_platform_probe(struct platform_device *pdev) |
420 | { | 419 | { |
421 | return snd_soc_register_platform(&txx9aclc_soc_platform); | 420 | return snd_soc_register_platform(&pdev->dev, &txx9aclc_soc_platform); |
422 | } | 421 | } |
423 | 422 | ||
424 | static void __exit txx9aclc_soc_platform_exit(void) | 423 | static int __devexit txx9aclc_soc_platform_remove(struct platform_device *pdev) |
425 | { | 424 | { |
426 | snd_soc_unregister_platform(&txx9aclc_soc_platform); | 425 | snd_soc_unregister_platform(&pdev->dev); |
426 | return 0; | ||
427 | } | 427 | } |
428 | 428 | ||
429 | module_init(txx9aclc_soc_platform_init); | 429 | static struct platform_driver txx9aclc_pcm_driver = { |
430 | module_exit(txx9aclc_soc_platform_exit); | 430 | .driver = { |
431 | .name = "txx9aclc-pcm-audio", | ||
432 | .owner = THIS_MODULE, | ||
433 | }, | ||
434 | |||
435 | .probe = txx9aclc_soc_platform_probe, | ||
436 | .remove = __devexit_p(txx9aclc_soc_platform_remove), | ||
437 | }; | ||
438 | |||
439 | static int __init snd_txx9aclc_pcm_init(void) | ||
440 | { | ||
441 | return platform_driver_register(&txx9aclc_pcm_driver); | ||
442 | } | ||
443 | module_init(snd_txx9aclc_pcm_init); | ||
444 | |||
445 | static void __exit snd_txx9aclc_pcm_exit(void) | ||
446 | { | ||
447 | platform_driver_unregister(&txx9aclc_pcm_driver); | ||
448 | } | ||
449 | module_exit(snd_txx9aclc_pcm_exit); | ||
431 | 450 | ||
432 | MODULE_AUTHOR("Atsushi Nemoto <anemo@mba.ocn.ne.jp>"); | 451 | MODULE_AUTHOR("Atsushi Nemoto <anemo@mba.ocn.ne.jp>"); |
433 | MODULE_DESCRIPTION("TXx9 ACLC Audio DMA driver"); | 452 | MODULE_DESCRIPTION("TXx9 ACLC Audio DMA driver"); |
diff --git a/sound/soc/txx9/txx9aclc.h b/sound/soc/txx9/txx9aclc.h index 6769aab41b33..9c2de84fec3b 100644 --- a/sound/soc/txx9/txx9aclc.h +++ b/sound/soc/txx9/txx9aclc.h | |||
@@ -65,19 +65,10 @@ struct txx9aclc_plat_drvdata { | |||
65 | u64 physbase; | 65 | u64 physbase; |
66 | }; | 66 | }; |
67 | 67 | ||
68 | struct txx9aclc_soc_device { | ||
69 | struct snd_soc_device soc_dev; | ||
70 | struct platform_device *aclc_pdev; /* for ioresources, drvdata */ | ||
71 | struct txx9aclc_dmadata dmadata[2]; | ||
72 | }; | ||
73 | |||
74 | static inline struct txx9aclc_plat_drvdata *txx9aclc_get_plat_drvdata( | 68 | static inline struct txx9aclc_plat_drvdata *txx9aclc_get_plat_drvdata( |
75 | struct txx9aclc_soc_device *sdev) | 69 | struct snd_soc_dai *dai) |
76 | { | 70 | { |
77 | return platform_get_drvdata(sdev->aclc_pdev); | 71 | return dev_get_drvdata(dai->dev); |
78 | } | 72 | } |
79 | 73 | ||
80 | extern struct snd_soc_platform txx9aclc_soc_platform; | ||
81 | extern struct snd_soc_dai txx9aclc_ac97_dai; | ||
82 | |||
83 | #endif /* __TXX9ACLC_H */ | 74 | #endif /* __TXX9ACLC_H */ |