]> git.proxmox.com Git - mirror_ubuntu-zesty-kernel.git/blob - sound/soc/bcm/rpi-proto.c
9db678e885efd63d84d60a098a84ed6772b19a2d
[mirror_ubuntu-zesty-kernel.git] / sound / soc / bcm / rpi-proto.c
1 /*
2 * ASoC driver for PROTO AudioCODEC (with a WM8731)
3 * connected to a Raspberry Pi
4 *
5 * Author: Florian Meier, <koalo@koalo.de>
6 * Copyright 2013
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 #include <linux/module.h>
14 #include <linux/platform_device.h>
15
16 #include <sound/core.h>
17 #include <sound/pcm.h>
18 #include <sound/soc.h>
19 #include <sound/jack.h>
20
21 #include "../codecs/wm8731.h"
22
23 static const unsigned int wm8731_rates_12288000[] = {
24 8000, 32000, 48000, 96000,
25 };
26
27 static struct snd_pcm_hw_constraint_list wm8731_constraints_12288000 = {
28 .list = wm8731_rates_12288000,
29 .count = ARRAY_SIZE(wm8731_rates_12288000),
30 };
31
32 static int snd_rpi_proto_startup(struct snd_pcm_substream *substream)
33 {
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);
38 return 0;
39 }
40
41 static int snd_rpi_proto_hw_params(struct snd_pcm_substream *substream,
42 struct snd_pcm_hw_params *params)
43 {
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 */
49
50 /* Set proto bclk */
51 int ret = snd_soc_dai_set_bclk_ratio(cpu_dai,32*2);
52 if (ret < 0){
53 dev_err(codec->dev,
54 "Failed to set BCLK ratio %d\n", ret);
55 return ret;
56 }
57
58 /* Set proto sysclk */
59 ret = snd_soc_dai_set_sysclk(codec_dai, WM8731_SYSCLK_XTAL,
60 sysclk, SND_SOC_CLOCK_IN);
61 if (ret < 0) {
62 dev_err(codec->dev,
63 "Failed to set WM8731 SYSCLK: %d\n", ret);
64 return ret;
65 }
66
67 return 0;
68 }
69
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,
74 };
75
76 static struct snd_soc_dai_link snd_rpi_proto_dai[] = {
77 {
78 .name = "WM8731",
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,
88 },
89 };
90
91 /* audio machine driver */
92 static struct snd_soc_card snd_rpi_proto = {
93 .name = "snd_rpi_proto",
94 .owner = THIS_MODULE,
95 .dai_link = snd_rpi_proto_dai,
96 .num_links = ARRAY_SIZE(snd_rpi_proto_dai),
97 };
98
99 static int snd_rpi_proto_probe(struct platform_device *pdev)
100 {
101 int ret = 0;
102
103 snd_rpi_proto.dev = &pdev->dev;
104
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);
110
111 if (i2s_node) {
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;
116 }
117 }
118
119 ret = snd_soc_register_card(&snd_rpi_proto);
120 if (ret) {
121 dev_err(&pdev->dev,
122 "snd_soc_register_card() failed: %d\n", ret);
123 }
124
125 return ret;
126 }
127
128
129 static int snd_rpi_proto_remove(struct platform_device *pdev)
130 {
131 return snd_soc_unregister_card(&snd_rpi_proto);
132 }
133
134 static const struct of_device_id snd_rpi_proto_of_match[] = {
135 { .compatible = "rpi,rpi-proto", },
136 {},
137 };
138 MODULE_DEVICE_TABLE(of, snd_rpi_proto_of_match);
139
140 static struct platform_driver snd_rpi_proto_driver = {
141 .driver = {
142 .name = "snd-rpi-proto",
143 .owner = THIS_MODULE,
144 .of_match_table = snd_rpi_proto_of_match,
145 },
146 .probe = snd_rpi_proto_probe,
147 .remove = snd_rpi_proto_remove,
148 };
149
150 module_platform_driver(snd_rpi_proto_driver);
151
152 MODULE_AUTHOR("Florian Meier");
153 MODULE_DESCRIPTION("ASoC Driver for Raspberry Pi connected to PROTO board (WM8731)");
154 MODULE_LICENSE("GPL");