diff options
Diffstat (limited to 'sound/soc/codecs/ak4104.c')
-rw-r--r-- | sound/soc/codecs/ak4104.c | 65 |
1 files changed, 48 insertions, 17 deletions
diff --git a/sound/soc/codecs/ak4104.c b/sound/soc/codecs/ak4104.c index 31d4483245d0..4b11b82b2273 100644 --- a/sound/soc/codecs/ak4104.c +++ b/sound/soc/codecs/ak4104.c | |||
@@ -15,6 +15,8 @@ | |||
15 | #include <sound/soc.h> | 15 | #include <sound/soc.h> |
16 | #include <sound/initval.h> | 16 | #include <sound/initval.h> |
17 | #include <linux/spi/spi.h> | 17 | #include <linux/spi/spi.h> |
18 | #include <linux/of_device.h> | ||
19 | #include <linux/of_gpio.h> | ||
18 | #include <sound/asoundef.h> | 20 | #include <sound/asoundef.h> |
19 | 21 | ||
20 | /* AK4104 registers addresses */ | 22 | /* AK4104 registers addresses */ |
@@ -98,14 +100,32 @@ static int ak4104_hw_params(struct snd_pcm_substream *substream, | |||
98 | val = 0; | 100 | val = 0; |
99 | 101 | ||
100 | switch (params_rate(params)) { | 102 | switch (params_rate(params)) { |
103 | case 22050: | ||
104 | val |= IEC958_AES3_CON_FS_22050; | ||
105 | break; | ||
106 | case 24000: | ||
107 | val |= IEC958_AES3_CON_FS_24000; | ||
108 | break; | ||
109 | case 32000: | ||
110 | val |= IEC958_AES3_CON_FS_32000; | ||
111 | break; | ||
101 | case 44100: | 112 | case 44100: |
102 | val |= IEC958_AES3_CON_FS_44100; | 113 | val |= IEC958_AES3_CON_FS_44100; |
103 | break; | 114 | break; |
104 | case 48000: | 115 | case 48000: |
105 | val |= IEC958_AES3_CON_FS_48000; | 116 | val |= IEC958_AES3_CON_FS_48000; |
106 | break; | 117 | break; |
107 | case 32000: | 118 | case 88200: |
108 | val |= IEC958_AES3_CON_FS_32000; | 119 | val |= IEC958_AES3_CON_FS_88200; |
120 | break; | ||
121 | case 96000: | ||
122 | val |= IEC958_AES3_CON_FS_96000; | ||
123 | break; | ||
124 | case 176400: | ||
125 | val |= IEC958_AES3_CON_FS_176400; | ||
126 | break; | ||
127 | case 192000: | ||
128 | val |= IEC958_AES3_CON_FS_192000; | ||
109 | break; | 129 | break; |
110 | default: | 130 | default: |
111 | dev_err(codec->dev, "unsupported sampling rate\n"); | 131 | dev_err(codec->dev, "unsupported sampling rate\n"); |
@@ -186,6 +206,7 @@ static const struct regmap_config ak4104_regmap = { | |||
186 | 206 | ||
187 | static int ak4104_spi_probe(struct spi_device *spi) | 207 | static int ak4104_spi_probe(struct spi_device *spi) |
188 | { | 208 | { |
209 | struct device_node *np = spi->dev.of_node; | ||
189 | struct ak4104_private *ak4104; | 210 | struct ak4104_private *ak4104; |
190 | unsigned int val; | 211 | unsigned int val; |
191 | int ret; | 212 | int ret; |
@@ -201,49 +222,59 @@ static int ak4104_spi_probe(struct spi_device *spi) | |||
201 | if (ak4104 == NULL) | 222 | if (ak4104 == NULL) |
202 | return -ENOMEM; | 223 | return -ENOMEM; |
203 | 224 | ||
204 | ak4104->regmap = regmap_init_spi(spi, &ak4104_regmap); | 225 | ak4104->regmap = devm_regmap_init_spi(spi, &ak4104_regmap); |
205 | if (IS_ERR(ak4104->regmap)) { | 226 | if (IS_ERR(ak4104->regmap)) { |
206 | ret = PTR_ERR(ak4104->regmap); | 227 | ret = PTR_ERR(ak4104->regmap); |
207 | return ret; | 228 | return ret; |
208 | } | 229 | } |
209 | 230 | ||
231 | if (np) { | ||
232 | enum of_gpio_flags flags; | ||
233 | int gpio = of_get_named_gpio_flags(np, "reset-gpio", 0, &flags); | ||
234 | |||
235 | if (gpio_is_valid(gpio)) { | ||
236 | ret = devm_gpio_request_one(&spi->dev, gpio, | ||
237 | flags & OF_GPIO_ACTIVE_LOW ? | ||
238 | GPIOF_OUT_INIT_LOW : GPIOF_OUT_INIT_HIGH, | ||
239 | "ak4104 reset"); | ||
240 | if (ret < 0) | ||
241 | return ret; | ||
242 | } | ||
243 | } | ||
244 | |||
210 | /* read the 'reserved' register - according to the datasheet, it | 245 | /* read the 'reserved' register - according to the datasheet, it |
211 | * should contain 0x5b. Not a good way to verify the presence of | 246 | * should contain 0x5b. Not a good way to verify the presence of |
212 | * the device, but there is no hardware ID register. */ | 247 | * the device, but there is no hardware ID register. */ |
213 | ret = regmap_read(ak4104->regmap, AK4104_REG_RESERVED, &val); | 248 | ret = regmap_read(ak4104->regmap, AK4104_REG_RESERVED, &val); |
214 | if (ret != 0) | 249 | if (ret != 0) |
215 | goto err; | 250 | return ret; |
216 | if (val != AK4104_RESERVED_VAL) { | 251 | if (val != AK4104_RESERVED_VAL) |
217 | ret = -ENODEV; | 252 | return -ENODEV; |
218 | goto err; | ||
219 | } | ||
220 | 253 | ||
221 | spi_set_drvdata(spi, ak4104); | 254 | spi_set_drvdata(spi, ak4104); |
222 | 255 | ||
223 | ret = snd_soc_register_codec(&spi->dev, | 256 | ret = snd_soc_register_codec(&spi->dev, |
224 | &soc_codec_device_ak4104, &ak4104_dai, 1); | 257 | &soc_codec_device_ak4104, &ak4104_dai, 1); |
225 | if (ret != 0) | ||
226 | goto err; | ||
227 | |||
228 | return 0; | ||
229 | |||
230 | err: | ||
231 | regmap_exit(ak4104->regmap); | ||
232 | return ret; | 258 | return ret; |
233 | } | 259 | } |
234 | 260 | ||
235 | static int __devexit ak4104_spi_remove(struct spi_device *spi) | 261 | static int __devexit ak4104_spi_remove(struct spi_device *spi) |
236 | { | 262 | { |
237 | struct ak4104_private *ak4101 = spi_get_drvdata(spi); | ||
238 | regmap_exit(ak4101->regmap); | ||
239 | snd_soc_unregister_codec(&spi->dev); | 263 | snd_soc_unregister_codec(&spi->dev); |
240 | return 0; | 264 | return 0; |
241 | } | 265 | } |
242 | 266 | ||
267 | static const struct of_device_id ak4104_of_match[] = { | ||
268 | { .compatible = "asahi-kasei,ak4104", }, | ||
269 | { } | ||
270 | }; | ||
271 | MODULE_DEVICE_TABLE(of, ak4104_of_match); | ||
272 | |||
243 | static struct spi_driver ak4104_spi_driver = { | 273 | static struct spi_driver ak4104_spi_driver = { |
244 | .driver = { | 274 | .driver = { |
245 | .name = DRV_NAME, | 275 | .name = DRV_NAME, |
246 | .owner = THIS_MODULE, | 276 | .owner = THIS_MODULE, |
277 | .of_match_table = ak4104_of_match, | ||
247 | }, | 278 | }, |
248 | .probe = ak4104_spi_probe, | 279 | .probe = ak4104_spi_probe, |
249 | .remove = __devexit_p(ak4104_spi_remove), | 280 | .remove = __devexit_p(ak4104_spi_remove), |