2 * ASoC driver for PROTO AudioCODEC (with a WM8731)
3 * connected to a Raspberry Pi
5 * Author: Florian Meier, <koalo@koalo.de>
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.
13 #include <linux/module.h>
14 #include <linux/platform_device.h>
16 #include <sound/core.h>
17 #include <sound/pcm.h>
18 #include <sound/soc.h>
19 #include <sound/jack.h>
21 #include "../codecs/wm8731.h"
23 static const unsigned int wm8731_rates_12288000
[] = {
24 8000, 32000, 48000, 96000,
27 static struct snd_pcm_hw_constraint_list wm8731_constraints_12288000
= {
28 .list
= wm8731_rates_12288000
,
29 .count
= ARRAY_SIZE(wm8731_rates_12288000
),
32 static int snd_rpi_proto_startup(struct snd_pcm_substream
*substream
)
34 /* Setup constraints, because there is a 12.288 MHz XTAL on the board */
35 snd_pcm_hw_constraint_list(substream
->runtime
, 0,
36 SNDRV_PCM_HW_PARAM_RATE
,
37 &wm8731_constraints_12288000
);
41 static int snd_rpi_proto_hw_params(struct snd_pcm_substream
*substream
,
42 struct snd_pcm_hw_params
*params
)
44 struct snd_soc_pcm_runtime
*rtd
= substream
->private_data
;
45 struct snd_soc_codec
*codec
= rtd
->codec
;
46 struct snd_soc_dai
*codec_dai
= rtd
->codec_dai
;
47 struct snd_soc_dai
*cpu_dai
= rtd
->cpu_dai
;
48 int sysclk
= 12288000; /* This is fixed on this board */
51 int ret
= snd_soc_dai_set_bclk_ratio(cpu_dai
,32*2);
54 "Failed to set BCLK ratio %d\n", ret
);
58 /* Set proto sysclk */
59 ret
= snd_soc_dai_set_sysclk(codec_dai
, WM8731_SYSCLK_XTAL
,
60 sysclk
, SND_SOC_CLOCK_IN
);
63 "Failed to set WM8731 SYSCLK: %d\n", ret
);
70 /* machine stream operations */
71 static struct snd_soc_ops snd_rpi_proto_ops
= {
72 .startup
= snd_rpi_proto_startup
,
73 .hw_params
= snd_rpi_proto_hw_params
,
76 static struct snd_soc_dai_link snd_rpi_proto_dai
[] = {
79 .stream_name
= "WM8731 HiFi",
80 .cpu_dai_name
= "bcm2708-i2s.0",
81 .codec_dai_name
= "wm8731-hifi",
82 .platform_name
= "bcm2708-i2s.0",
83 .codec_name
= "wm8731.1-001a",
84 .dai_fmt
= SND_SOC_DAIFMT_I2S
85 | SND_SOC_DAIFMT_NB_NF
86 | SND_SOC_DAIFMT_CBM_CFM
,
87 .ops
= &snd_rpi_proto_ops
,
91 /* audio machine driver */
92 static struct snd_soc_card snd_rpi_proto
= {
93 .name
= "snd_rpi_proto",
95 .dai_link
= snd_rpi_proto_dai
,
96 .num_links
= ARRAY_SIZE(snd_rpi_proto_dai
),
99 static int snd_rpi_proto_probe(struct platform_device
*pdev
)
103 snd_rpi_proto
.dev
= &pdev
->dev
;
105 if (pdev
->dev
.of_node
) {
106 struct device_node
*i2s_node
;
107 struct snd_soc_dai_link
*dai
= &snd_rpi_proto_dai
[0];
108 i2s_node
= of_parse_phandle(pdev
->dev
.of_node
,
109 "i2s-controller", 0);
112 dai
->cpu_dai_name
= NULL
;
113 dai
->cpu_of_node
= i2s_node
;
114 dai
->platform_name
= NULL
;
115 dai
->platform_of_node
= i2s_node
;
119 ret
= snd_soc_register_card(&snd_rpi_proto
);
122 "snd_soc_register_card() failed: %d\n", ret
);
129 static int snd_rpi_proto_remove(struct platform_device
*pdev
)
131 return snd_soc_unregister_card(&snd_rpi_proto
);
134 static const struct of_device_id snd_rpi_proto_of_match
[] = {
135 { .compatible
= "rpi,rpi-proto", },
138 MODULE_DEVICE_TABLE(of
, snd_rpi_proto_of_match
);
140 static struct platform_driver snd_rpi_proto_driver
= {
142 .name
= "snd-rpi-proto",
143 .owner
= THIS_MODULE
,
144 .of_match_table
= snd_rpi_proto_of_match
,
146 .probe
= snd_rpi_proto_probe
,
147 .remove
= snd_rpi_proto_remove
,
150 module_platform_driver(snd_rpi_proto_driver
);
152 MODULE_AUTHOR("Florian Meier");
153 MODULE_DESCRIPTION("ASoC Driver for Raspberry Pi connected to PROTO board (WM8731)");
154 MODULE_LICENSE("GPL");