diff options
-rw-r--r-- | sound/soc/codecs/Kconfig | 5 | ||||
-rw-r--r-- | sound/soc/codecs/Makefile | 2 | ||||
-rw-r--r-- | sound/soc/codecs/adau-utils.c | 61 | ||||
-rw-r--r-- | sound/soc/codecs/adau-utils.h | 7 | ||||
-rw-r--r-- | sound/soc/codecs/adau1373.c | 38 | ||||
-rw-r--r-- | sound/soc/codecs/adau17x1.c | 38 |
6 files changed, 89 insertions, 62 deletions
diff --git a/sound/soc/codecs/Kconfig b/sound/soc/codecs/Kconfig index 4d82a58ff6b0..3e215395a199 100644 --- a/sound/soc/codecs/Kconfig +++ b/sound/soc/codecs/Kconfig | |||
@@ -269,8 +269,12 @@ config SND_SOC_AD1980 | |||
269 | config SND_SOC_AD73311 | 269 | config SND_SOC_AD73311 |
270 | tristate | 270 | tristate |
271 | 271 | ||
272 | config SND_SOC_ADAU_UTILS | ||
273 | tristate | ||
274 | |||
272 | config SND_SOC_ADAU1373 | 275 | config SND_SOC_ADAU1373 |
273 | tristate | 276 | tristate |
277 | select SND_SOC_ADAU_UTILS | ||
274 | 278 | ||
275 | config SND_SOC_ADAU1701 | 279 | config SND_SOC_ADAU1701 |
276 | tristate "Analog Devices ADAU1701 CODEC" | 280 | tristate "Analog Devices ADAU1701 CODEC" |
@@ -280,6 +284,7 @@ config SND_SOC_ADAU1701 | |||
280 | config SND_SOC_ADAU17X1 | 284 | config SND_SOC_ADAU17X1 |
281 | tristate | 285 | tristate |
282 | select SND_SOC_SIGMADSP_REGMAP | 286 | select SND_SOC_SIGMADSP_REGMAP |
287 | select SND_SOC_ADAU_UTILS | ||
283 | 288 | ||
284 | config SND_SOC_ADAU1761 | 289 | config SND_SOC_ADAU1761 |
285 | tristate | 290 | tristate |
diff --git a/sound/soc/codecs/Makefile b/sound/soc/codecs/Makefile index 0f548fd34ca3..d61957f2618c 100644 --- a/sound/soc/codecs/Makefile +++ b/sound/soc/codecs/Makefile | |||
@@ -7,6 +7,7 @@ snd-soc-ad193x-spi-objs := ad193x-spi.o | |||
7 | snd-soc-ad193x-i2c-objs := ad193x-i2c.o | 7 | snd-soc-ad193x-i2c-objs := ad193x-i2c.o |
8 | snd-soc-ad1980-objs := ad1980.o | 8 | snd-soc-ad1980-objs := ad1980.o |
9 | snd-soc-ad73311-objs := ad73311.o | 9 | snd-soc-ad73311-objs := ad73311.o |
10 | snd-soc-adau-utils-objs := adau-utils.o | ||
10 | snd-soc-adau1373-objs := adau1373.o | 11 | snd-soc-adau1373-objs := adau1373.o |
11 | snd-soc-adau1701-objs := adau1701.o | 12 | snd-soc-adau1701-objs := adau1701.o |
12 | snd-soc-adau17x1-objs := adau17x1.o | 13 | snd-soc-adau17x1-objs := adau17x1.o |
@@ -220,6 +221,7 @@ obj-$(CONFIG_SND_SOC_AD193X_SPI) += snd-soc-ad193x-spi.o | |||
220 | obj-$(CONFIG_SND_SOC_AD193X_I2C) += snd-soc-ad193x-i2c.o | 221 | obj-$(CONFIG_SND_SOC_AD193X_I2C) += snd-soc-ad193x-i2c.o |
221 | obj-$(CONFIG_SND_SOC_AD1980) += snd-soc-ad1980.o | 222 | obj-$(CONFIG_SND_SOC_AD1980) += snd-soc-ad1980.o |
222 | obj-$(CONFIG_SND_SOC_AD73311) += snd-soc-ad73311.o | 223 | obj-$(CONFIG_SND_SOC_AD73311) += snd-soc-ad73311.o |
224 | obj-$(CONFIG_SND_SOC_ADAU_UTILS) += snd-soc-adau-utils.o | ||
223 | obj-$(CONFIG_SND_SOC_ADAU1373) += snd-soc-adau1373.o | 225 | obj-$(CONFIG_SND_SOC_ADAU1373) += snd-soc-adau1373.o |
224 | obj-$(CONFIG_SND_SOC_ADAU1701) += snd-soc-adau1701.o | 226 | obj-$(CONFIG_SND_SOC_ADAU1701) += snd-soc-adau1701.o |
225 | obj-$(CONFIG_SND_SOC_ADAU17X1) += snd-soc-adau17x1.o | 227 | obj-$(CONFIG_SND_SOC_ADAU17X1) += snd-soc-adau17x1.o |
diff --git a/sound/soc/codecs/adau-utils.c b/sound/soc/codecs/adau-utils.c new file mode 100644 index 000000000000..19d6a6f41b12 --- /dev/null +++ b/sound/soc/codecs/adau-utils.c | |||
@@ -0,0 +1,61 @@ | |||
1 | /* | ||
2 | * Shared helper functions for devices from the ADAU family | ||
3 | * | ||
4 | * Copyright 2011-2016 Analog Devices Inc. | ||
5 | * Author: Lars-Peter Clausen <lars@metafoo.de> | ||
6 | * | ||
7 | * Licensed under the GPL-2 or later. | ||
8 | */ | ||
9 | |||
10 | #include <linux/gcd.h> | ||
11 | #include <linux/kernel.h> | ||
12 | #include <linux/module.h> | ||
13 | |||
14 | #include "adau-utils.h" | ||
15 | |||
16 | int adau_calc_pll_cfg(unsigned int freq_in, unsigned int freq_out, | ||
17 | uint8_t regs[5]) | ||
18 | { | ||
19 | unsigned int r, n, m, i, j; | ||
20 | unsigned int div; | ||
21 | |||
22 | if (!freq_out) { | ||
23 | r = 0; | ||
24 | n = 0; | ||
25 | m = 0; | ||
26 | div = 0; | ||
27 | } else { | ||
28 | if (freq_out % freq_in != 0) { | ||
29 | div = DIV_ROUND_UP(freq_in, 13500000); | ||
30 | freq_in /= div; | ||
31 | r = freq_out / freq_in; | ||
32 | i = freq_out % freq_in; | ||
33 | j = gcd(i, freq_in); | ||
34 | n = i / j; | ||
35 | m = freq_in / j; | ||
36 | div--; | ||
37 | } else { | ||
38 | r = freq_out / freq_in; | ||
39 | n = 0; | ||
40 | m = 0; | ||
41 | div = 0; | ||
42 | } | ||
43 | if (n > 0xffff || m > 0xffff || div > 3 || r > 8 || r < 2) | ||
44 | return -EINVAL; | ||
45 | } | ||
46 | |||
47 | regs[0] = m >> 8; | ||
48 | regs[1] = m & 0xff; | ||
49 | regs[2] = n >> 8; | ||
50 | regs[3] = n & 0xff; | ||
51 | regs[4] = (r << 3) | (div << 1); | ||
52 | if (m != 0) | ||
53 | regs[4] |= 1; /* Fractional mode */ | ||
54 | |||
55 | return 0; | ||
56 | } | ||
57 | EXPORT_SYMBOL_GPL(adau_calc_pll_cfg); | ||
58 | |||
59 | MODULE_DESCRIPTION("ASoC ADAU audio CODECs shared helper functions"); | ||
60 | MODULE_AUTHOR("Lars-Peter Clausen <lars@metafoo.de>"); | ||
61 | MODULE_LICENSE("GPL v2"); | ||
diff --git a/sound/soc/codecs/adau-utils.h b/sound/soc/codecs/adau-utils.h new file mode 100644 index 000000000000..939b5f37762f --- /dev/null +++ b/sound/soc/codecs/adau-utils.h | |||
@@ -0,0 +1,7 @@ | |||
1 | #ifndef SOUND_SOC_CODECS_ADAU_PLL_H | ||
2 | #define SOUND_SOC_CODECS_ADAU_PLL_H | ||
3 | |||
4 | int adau_calc_pll_cfg(unsigned int freq_in, unsigned int freq_out, | ||
5 | uint8_t regs[5]); | ||
6 | |||
7 | #endif | ||
diff --git a/sound/soc/codecs/adau1373.c b/sound/soc/codecs/adau1373.c index fe1353a797b9..1556b360fa15 100644 --- a/sound/soc/codecs/adau1373.c +++ b/sound/soc/codecs/adau1373.c | |||
@@ -23,6 +23,7 @@ | |||
23 | #include <sound/adau1373.h> | 23 | #include <sound/adau1373.h> |
24 | 24 | ||
25 | #include "adau1373.h" | 25 | #include "adau1373.h" |
26 | #include "adau-utils.h" | ||
26 | 27 | ||
27 | struct adau1373_dai { | 28 | struct adau1373_dai { |
28 | unsigned int clk_src; | 29 | unsigned int clk_src; |
@@ -1254,7 +1255,8 @@ static int adau1373_set_pll(struct snd_soc_codec *codec, int pll_id, | |||
1254 | { | 1255 | { |
1255 | struct adau1373 *adau1373 = snd_soc_codec_get_drvdata(codec); | 1256 | struct adau1373 *adau1373 = snd_soc_codec_get_drvdata(codec); |
1256 | unsigned int dpll_div = 0; | 1257 | unsigned int dpll_div = 0; |
1257 | unsigned int x, r, n, m, i, j, mode; | 1258 | uint8_t pll_regs[5]; |
1259 | int ret; | ||
1258 | 1260 | ||
1259 | switch (pll_id) { | 1261 | switch (pll_id) { |
1260 | case ADAU1373_PLL1: | 1262 | case ADAU1373_PLL1: |
@@ -1295,27 +1297,8 @@ static int adau1373_set_pll(struct snd_soc_codec *codec, int pll_id, | |||
1295 | dpll_div++; | 1297 | dpll_div++; |
1296 | } | 1298 | } |
1297 | 1299 | ||
1298 | if (freq_out % freq_in != 0) { | 1300 | ret = adau_calc_pll_cfg(freq_in, freq_out, pll_regs); |
1299 | /* fout = fin * (r + (n/m)) / x */ | 1301 | if (ret) |
1300 | x = DIV_ROUND_UP(freq_in, 13500000); | ||
1301 | freq_in /= x; | ||
1302 | r = freq_out / freq_in; | ||
1303 | i = freq_out % freq_in; | ||
1304 | j = gcd(i, freq_in); | ||
1305 | n = i / j; | ||
1306 | m = freq_in / j; | ||
1307 | x--; | ||
1308 | mode = 1; | ||
1309 | } else { | ||
1310 | /* fout = fin / r */ | ||
1311 | r = freq_out / freq_in; | ||
1312 | n = 0; | ||
1313 | m = 0; | ||
1314 | x = 0; | ||
1315 | mode = 0; | ||
1316 | } | ||
1317 | |||
1318 | if (r < 2 || r > 8 || x > 3 || m > 0xffff || n > 0xffff) | ||
1319 | return -EINVAL; | 1302 | return -EINVAL; |
1320 | 1303 | ||
1321 | if (dpll_div) { | 1304 | if (dpll_div) { |
@@ -1330,12 +1313,11 @@ static int adau1373_set_pll(struct snd_soc_codec *codec, int pll_id, | |||
1330 | 1313 | ||
1331 | regmap_write(adau1373->regmap, ADAU1373_DPLL_CTRL(pll_id), | 1314 | regmap_write(adau1373->regmap, ADAU1373_DPLL_CTRL(pll_id), |
1332 | (source << 4) | dpll_div); | 1315 | (source << 4) | dpll_div); |
1333 | regmap_write(adau1373->regmap, ADAU1373_PLL_CTRL1(pll_id), (m >> 8) & 0xff); | 1316 | regmap_write(adau1373->regmap, ADAU1373_PLL_CTRL1(pll_id), pll_regs[0]); |
1334 | regmap_write(adau1373->regmap, ADAU1373_PLL_CTRL2(pll_id), m & 0xff); | 1317 | regmap_write(adau1373->regmap, ADAU1373_PLL_CTRL2(pll_id), pll_regs[1]); |
1335 | regmap_write(adau1373->regmap, ADAU1373_PLL_CTRL3(pll_id), (n >> 8) & 0xff); | 1318 | regmap_write(adau1373->regmap, ADAU1373_PLL_CTRL3(pll_id), pll_regs[2]); |
1336 | regmap_write(adau1373->regmap, ADAU1373_PLL_CTRL4(pll_id), n & 0xff); | 1319 | regmap_write(adau1373->regmap, ADAU1373_PLL_CTRL4(pll_id), pll_regs[3]); |
1337 | regmap_write(adau1373->regmap, ADAU1373_PLL_CTRL5(pll_id), | 1320 | regmap_write(adau1373->regmap, ADAU1373_PLL_CTRL5(pll_id), pll_regs[4]); |
1338 | (r << 3) | (x << 1) | mode); | ||
1339 | 1321 | ||
1340 | /* Set sysclk to pll_rate / 4 */ | 1322 | /* Set sysclk to pll_rate / 4 */ |
1341 | regmap_update_bits(adau1373->regmap, ADAU1373_CLK_SRC_DIV(pll_id), 0x3f, 0x09); | 1323 | regmap_update_bits(adau1373->regmap, ADAU1373_CLK_SRC_DIV(pll_id), 0x3f, 0x09); |
diff --git a/sound/soc/codecs/adau17x1.c b/sound/soc/codecs/adau17x1.c index fcf05b254ecd..66a6e061923d 100644 --- a/sound/soc/codecs/adau17x1.c +++ b/sound/soc/codecs/adau17x1.c | |||
@@ -23,6 +23,7 @@ | |||
23 | 23 | ||
24 | #include "sigmadsp.h" | 24 | #include "sigmadsp.h" |
25 | #include "adau17x1.h" | 25 | #include "adau17x1.h" |
26 | #include "adau-utils.h" | ||
26 | 27 | ||
27 | static const char * const adau17x1_capture_mixer_boost_text[] = { | 28 | static const char * const adau17x1_capture_mixer_boost_text[] = { |
28 | "Normal operation", "Boost Level 1", "Boost Level 2", "Boost Level 3", | 29 | "Normal operation", "Boost Level 1", "Boost Level 2", "Boost Level 3", |
@@ -391,45 +392,14 @@ static int adau17x1_set_dai_pll(struct snd_soc_dai *dai, int pll_id, | |||
391 | { | 392 | { |
392 | struct snd_soc_codec *codec = dai->codec; | 393 | struct snd_soc_codec *codec = dai->codec; |
393 | struct adau *adau = snd_soc_codec_get_drvdata(codec); | 394 | struct adau *adau = snd_soc_codec_get_drvdata(codec); |
394 | unsigned int r, n, m, i, j; | ||
395 | unsigned int div; | ||
396 | int ret; | 395 | int ret; |
397 | 396 | ||
398 | if (freq_in < 8000000 || freq_in > 27000000) | 397 | if (freq_in < 8000000 || freq_in > 27000000) |
399 | return -EINVAL; | 398 | return -EINVAL; |
400 | 399 | ||
401 | if (!freq_out) { | 400 | ret = adau_calc_pll_cfg(freq_in, freq_out, adau->pll_regs); |
402 | r = 0; | 401 | if (ret < 0) |
403 | n = 0; | 402 | return ret; |
404 | m = 0; | ||
405 | div = 0; | ||
406 | } else { | ||
407 | if (freq_out % freq_in != 0) { | ||
408 | div = DIV_ROUND_UP(freq_in, 13500000); | ||
409 | freq_in /= div; | ||
410 | r = freq_out / freq_in; | ||
411 | i = freq_out % freq_in; | ||
412 | j = gcd(i, freq_in); | ||
413 | n = i / j; | ||
414 | m = freq_in / j; | ||
415 | div--; | ||
416 | } else { | ||
417 | r = freq_out / freq_in; | ||
418 | n = 0; | ||
419 | m = 0; | ||
420 | div = 0; | ||
421 | } | ||
422 | if (n > 0xffff || m > 0xffff || div > 3 || r > 8 || r < 2) | ||
423 | return -EINVAL; | ||
424 | } | ||
425 | |||
426 | adau->pll_regs[0] = m >> 8; | ||
427 | adau->pll_regs[1] = m & 0xff; | ||
428 | adau->pll_regs[2] = n >> 8; | ||
429 | adau->pll_regs[3] = n & 0xff; | ||
430 | adau->pll_regs[4] = (r << 3) | (div << 1); | ||
431 | if (m != 0) | ||
432 | adau->pll_regs[4] |= 1; /* Fractional mode */ | ||
433 | 403 | ||
434 | /* The PLL register is 6 bytes long and can only be written at once. */ | 404 | /* The PLL register is 6 bytes long and can only be written at once. */ |
435 | ret = regmap_raw_write(adau->regmap, ADAU17X1_PLL_CONTROL, | 405 | ret = regmap_raw_write(adau->regmap, ADAU17X1_PLL_CONTROL, |