Skip to content

Commit 0eadaa9

Browse files
larsclausenbroonie
authored andcommitted
ASoC: adau: Factor out shared PLL configuration code
Multiple devices from the ADAU family share the same PLL structure and configuration register layout. Introduce a new helper module that can be used to calculated the PLL configuration registers based on a specified input frequency and the desired output frequency of the PLL. The ADAU1761/ADAU1781 and ADAU1373 drivers are updated to make use of this new helper module. But future drivers for additional devices from the ADAU family are also expected to make use of it. In anticipation of sharing more infrastructure code between different devices from the ADAU family the new module is called adau-utils. Signed-off-by: Lars-Peter Clausen <[email protected]> Signed-off-by: Mark Brown <[email protected]>
1 parent 1a695a9 commit 0eadaa9

File tree

6 files changed

+89
-62
lines changed

6 files changed

+89
-62
lines changed

sound/soc/codecs/Kconfig

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -269,8 +269,12 @@ config SND_SOC_AD1980
269269
config SND_SOC_AD73311
270270
tristate
271271

272+
config SND_SOC_ADAU_UTILS
273+
tristate
274+
272275
config SND_SOC_ADAU1373
273276
tristate
277+
select SND_SOC_ADAU_UTILS
274278

275279
config SND_SOC_ADAU1701
276280
tristate "Analog Devices ADAU1701 CODEC"
@@ -280,6 +284,7 @@ config SND_SOC_ADAU1701
280284
config SND_SOC_ADAU17X1
281285
tristate
282286
select SND_SOC_SIGMADSP_REGMAP
287+
select SND_SOC_ADAU_UTILS
283288

284289
config SND_SOC_ADAU1761
285290
tristate

sound/soc/codecs/Makefile

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@ snd-soc-ad193x-spi-objs := ad193x-spi.o
77
snd-soc-ad193x-i2c-objs := ad193x-i2c.o
88
snd-soc-ad1980-objs := ad1980.o
99
snd-soc-ad73311-objs := ad73311.o
10+
snd-soc-adau-utils-objs := adau-utils.o
1011
snd-soc-adau1373-objs := adau1373.o
1112
snd-soc-adau1701-objs := adau1701.o
1213
snd-soc-adau17x1-objs := adau17x1.o
@@ -220,6 +221,7 @@ obj-$(CONFIG_SND_SOC_AD193X_SPI) += snd-soc-ad193x-spi.o
220221
obj-$(CONFIG_SND_SOC_AD193X_I2C) += snd-soc-ad193x-i2c.o
221222
obj-$(CONFIG_SND_SOC_AD1980) += snd-soc-ad1980.o
222223
obj-$(CONFIG_SND_SOC_AD73311) += snd-soc-ad73311.o
224+
obj-$(CONFIG_SND_SOC_ADAU_UTILS) += snd-soc-adau-utils.o
223225
obj-$(CONFIG_SND_SOC_ADAU1373) += snd-soc-adau1373.o
224226
obj-$(CONFIG_SND_SOC_ADAU1701) += snd-soc-adau1701.o
225227
obj-$(CONFIG_SND_SOC_ADAU17X1) += snd-soc-adau17x1.o

sound/soc/codecs/adau-utils.c

Lines changed: 61 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -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 <[email protected]>
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 <[email protected]>");
61+
MODULE_LICENSE("GPL v2");

sound/soc/codecs/adau-utils.h

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -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

sound/soc/codecs/adau1373.c

Lines changed: 10 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,7 @@
2323
#include <sound/adau1373.h>
2424

2525
#include "adau1373.h"
26+
#include "adau-utils.h"
2627

2728
struct adau1373_dai {
2829
unsigned int clk_src;
@@ -1254,7 +1255,8 @@ static int adau1373_set_pll(struct snd_soc_codec *codec, int pll_id,
12541255
{
12551256
struct adau1373 *adau1373 = snd_soc_codec_get_drvdata(codec);
12561257
unsigned int dpll_div = 0;
1257-
unsigned int x, r, n, m, i, j, mode;
1258+
uint8_t pll_regs[5];
1259+
int ret;
12581260

12591261
switch (pll_id) {
12601262
case ADAU1373_PLL1:
@@ -1295,27 +1297,8 @@ static int adau1373_set_pll(struct snd_soc_codec *codec, int pll_id,
12951297
dpll_div++;
12961298
}
12971299

1298-
if (freq_out % freq_in != 0) {
1299-
/* fout = fin * (r + (n/m)) / x */
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)
1300+
ret = adau_calc_pll_cfg(freq_in, freq_out, pll_regs);
1301+
if (ret)
13191302
return -EINVAL;
13201303

13211304
if (dpll_div) {
@@ -1330,12 +1313,11 @@ static int adau1373_set_pll(struct snd_soc_codec *codec, int pll_id,
13301313

13311314
regmap_write(adau1373->regmap, ADAU1373_DPLL_CTRL(pll_id),
13321315
(source << 4) | dpll_div);
1333-
regmap_write(adau1373->regmap, ADAU1373_PLL_CTRL1(pll_id), (m >> 8) & 0xff);
1334-
regmap_write(adau1373->regmap, ADAU1373_PLL_CTRL2(pll_id), m & 0xff);
1335-
regmap_write(adau1373->regmap, ADAU1373_PLL_CTRL3(pll_id), (n >> 8) & 0xff);
1336-
regmap_write(adau1373->regmap, ADAU1373_PLL_CTRL4(pll_id), n & 0xff);
1337-
regmap_write(adau1373->regmap, ADAU1373_PLL_CTRL5(pll_id),
1338-
(r << 3) | (x << 1) | mode);
1316+
regmap_write(adau1373->regmap, ADAU1373_PLL_CTRL1(pll_id), pll_regs[0]);
1317+
regmap_write(adau1373->regmap, ADAU1373_PLL_CTRL2(pll_id), pll_regs[1]);
1318+
regmap_write(adau1373->regmap, ADAU1373_PLL_CTRL3(pll_id), pll_regs[2]);
1319+
regmap_write(adau1373->regmap, ADAU1373_PLL_CTRL4(pll_id), pll_regs[3]);
1320+
regmap_write(adau1373->regmap, ADAU1373_PLL_CTRL5(pll_id), pll_regs[4]);
13391321

13401322
/* Set sysclk to pll_rate / 4 */
13411323
regmap_update_bits(adau1373->regmap, ADAU1373_CLK_SRC_DIV(pll_id), 0x3f, 0x09);

sound/soc/codecs/adau17x1.c

Lines changed: 4 additions & 34 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,7 @@
2323

2424
#include "sigmadsp.h"
2525
#include "adau17x1.h"
26+
#include "adau-utils.h"
2627

2728
static const char * const adau17x1_capture_mixer_boost_text[] = {
2829
"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,
391392
{
392393
struct snd_soc_codec *codec = dai->codec;
393394
struct adau *adau = snd_soc_codec_get_drvdata(codec);
394-
unsigned int r, n, m, i, j;
395-
unsigned int div;
396395
int ret;
397396

398397
if (freq_in < 8000000 || freq_in > 27000000)
399398
return -EINVAL;
400399

401-
if (!freq_out) {
402-
r = 0;
403-
n = 0;
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 */
400+
ret = adau_calc_pll_cfg(freq_in, freq_out, adau->pll_regs);
401+
if (ret < 0)
402+
return ret;
433403

434404
/* The PLL register is 6 bytes long and can only be written at once. */
435405
ret = regmap_raw_write(adau->regmap, ADAU17X1_PLL_CONTROL,

0 commit comments

Comments
 (0)