aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--sound/soc/codecs/Kconfig5
-rw-r--r--sound/soc/codecs/Makefile2
-rw-r--r--sound/soc/codecs/adau-utils.c61
-rw-r--r--sound/soc/codecs/adau-utils.h7
-rw-r--r--sound/soc/codecs/adau1373.c38
-rw-r--r--sound/soc/codecs/adau17x1.c38
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
269config SND_SOC_AD73311 269config SND_SOC_AD73311
270 tristate 270 tristate
271 271
272config SND_SOC_ADAU_UTILS
273 tristate
274
272config SND_SOC_ADAU1373 275config SND_SOC_ADAU1373
273 tristate 276 tristate
277 select SND_SOC_ADAU_UTILS
274 278
275config SND_SOC_ADAU1701 279config SND_SOC_ADAU1701
276 tristate "Analog Devices ADAU1701 CODEC" 280 tristate "Analog Devices ADAU1701 CODEC"
@@ -280,6 +284,7 @@ config SND_SOC_ADAU1701
280config SND_SOC_ADAU17X1 284config 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
284config SND_SOC_ADAU1761 289config 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
7snd-soc-ad193x-i2c-objs := ad193x-i2c.o 7snd-soc-ad193x-i2c-objs := ad193x-i2c.o
8snd-soc-ad1980-objs := ad1980.o 8snd-soc-ad1980-objs := ad1980.o
9snd-soc-ad73311-objs := ad73311.o 9snd-soc-ad73311-objs := ad73311.o
10snd-soc-adau-utils-objs := adau-utils.o
10snd-soc-adau1373-objs := adau1373.o 11snd-soc-adau1373-objs := adau1373.o
11snd-soc-adau1701-objs := adau1701.o 12snd-soc-adau1701-objs := adau1701.o
12snd-soc-adau17x1-objs := adau17x1.o 13snd-soc-adau17x1-objs := adau17x1.o
@@ -220,6 +221,7 @@ obj-$(CONFIG_SND_SOC_AD193X_SPI) += snd-soc-ad193x-spi.o
220obj-$(CONFIG_SND_SOC_AD193X_I2C) += snd-soc-ad193x-i2c.o 221obj-$(CONFIG_SND_SOC_AD193X_I2C) += snd-soc-ad193x-i2c.o
221obj-$(CONFIG_SND_SOC_AD1980) += snd-soc-ad1980.o 222obj-$(CONFIG_SND_SOC_AD1980) += snd-soc-ad1980.o
222obj-$(CONFIG_SND_SOC_AD73311) += snd-soc-ad73311.o 223obj-$(CONFIG_SND_SOC_AD73311) += snd-soc-ad73311.o
224obj-$(CONFIG_SND_SOC_ADAU_UTILS) += snd-soc-adau-utils.o
223obj-$(CONFIG_SND_SOC_ADAU1373) += snd-soc-adau1373.o 225obj-$(CONFIG_SND_SOC_ADAU1373) += snd-soc-adau1373.o
224obj-$(CONFIG_SND_SOC_ADAU1701) += snd-soc-adau1701.o 226obj-$(CONFIG_SND_SOC_ADAU1701) += snd-soc-adau1701.o
225obj-$(CONFIG_SND_SOC_ADAU17X1) += snd-soc-adau17x1.o 227obj-$(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
16int 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}
57EXPORT_SYMBOL_GPL(adau_calc_pll_cfg);
58
59MODULE_DESCRIPTION("ASoC ADAU audio CODECs shared helper functions");
60MODULE_AUTHOR("Lars-Peter Clausen <lars@metafoo.de>");
61MODULE_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
4int 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
27struct adau1373_dai { 28struct 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
27static const char * const adau17x1_capture_mixer_boost_text[] = { 28static 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,