aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorLars-Peter Clausen <lars@metafoo.de>2016-06-15 09:07:27 -0400
committerMark Brown <broonie@kernel.org>2016-06-15 09:42:40 -0400
commit5d76de61dd8cb89b7189ef7456fba921c547c398 (patch)
tree3d85cae578faa5a1137227bad4ad2eb355c30728
parent0eadaa9ce2aacdcc3cf050d98c25aacabadc557f (diff)
ASoC: adau17x1: Add support for specifying the MCLK using the CCF
The devices from the ADAU17X1 family all have a MCLK clock input which supplies the master clock for the device. The master clock is used as the input clock for the PLL. Currently the MCLK rate as well as the desired PLL output frequency need to be supplied by calling snd_soc_dai_set_pll() form a machine driver. Add support for specifying the MCLK using the common clock framework. In addition to that also automatically configure the PLL to a suitable rate if the master clock was provided using the CCW. This allows to use the CODEC driver without any special configuration requirements from the machine driver. While the PLL output frequency can be configured over a (more or less) continuous range the narrowness of the range and the other constraints of the clocking tree usually only result in two output frequencies that will actually be chosen. One for 44.1kHz based rates and one for 48kHz based rates, these are the rates that the automatic PLL configuration will use. For the rare case where a non-standard setup is required a machine driver can disable the auto-configuration and configure a custom frequency using the existing mechanisms. If the common clock framework is not enabled clk_get() will return NULL and the driver will function as before and the clock rate needs to be configured manually. Signed-off-by: Lars-Peter Clausen <lars@metafoo.de> Signed-off-by: Mark Brown <broonie@kernel.org>
-rw-r--r--Documentation/devicetree/bindings/sound/adi,adau17x1.txt8
-rw-r--r--sound/soc/codecs/adau1761-i2c.c2
-rw-r--r--sound/soc/codecs/adau1761-spi.c2
-rw-r--r--sound/soc/codecs/adau1781-i2c.c2
-rw-r--r--sound/soc/codecs/adau1781-spi.c2
-rw-r--r--sound/soc/codecs/adau17x1.c219
-rw-r--r--sound/soc/codecs/adau17x1.h6
7 files changed, 179 insertions, 62 deletions
diff --git a/Documentation/devicetree/bindings/sound/adi,adau17x1.txt b/Documentation/devicetree/bindings/sound/adi,adau17x1.txt
index 8dbce0e18dda..1447dec28125 100644
--- a/Documentation/devicetree/bindings/sound/adi,adau17x1.txt
+++ b/Documentation/devicetree/bindings/sound/adi,adau17x1.txt
@@ -13,6 +13,11 @@ Required properties:
13 - reg: The i2c address. Value depends on the state of ADDR0 13 - reg: The i2c address. Value depends on the state of ADDR0
14 and ADDR1, as wired in hardware. 14 and ADDR1, as wired in hardware.
15 15
16Optional properties:
17 - clock-names: If provided must be "mclk".
18 - clocks: phandle + clock-specifiers for the clock that provides
19 the audio master clock for the device.
20
16Examples: 21Examples:
17#include <dt-bindings/sound/adau17x1.h> 22#include <dt-bindings/sound/adau17x1.h>
18 23
@@ -20,5 +25,8 @@ Examples:
20 adau1361@38 { 25 adau1361@38 {
21 compatible = "adi,adau1761"; 26 compatible = "adi,adau1761";
22 reg = <0x38>; 27 reg = <0x38>;
28
29 clock-names = "mclk";
30 clocks = <&audio_clock>;
23 }; 31 };
24 }; 32 };
diff --git a/sound/soc/codecs/adau1761-i2c.c b/sound/soc/codecs/adau1761-i2c.c
index 8de010f758cd..9e7f257f17f8 100644
--- a/sound/soc/codecs/adau1761-i2c.c
+++ b/sound/soc/codecs/adau1761-i2c.c
@@ -31,7 +31,7 @@ static int adau1761_i2c_probe(struct i2c_client *client,
31 31
32static int adau1761_i2c_remove(struct i2c_client *client) 32static int adau1761_i2c_remove(struct i2c_client *client)
33{ 33{
34 snd_soc_unregister_codec(&client->dev); 34 adau17x1_remove(&client->dev);
35 return 0; 35 return 0;
36} 36}
37 37
diff --git a/sound/soc/codecs/adau1761-spi.c b/sound/soc/codecs/adau1761-spi.c
index d9171245bd9f..a0b214be759a 100644
--- a/sound/soc/codecs/adau1761-spi.c
+++ b/sound/soc/codecs/adau1761-spi.c
@@ -48,7 +48,7 @@ static int adau1761_spi_probe(struct spi_device *spi)
48 48
49static int adau1761_spi_remove(struct spi_device *spi) 49static int adau1761_spi_remove(struct spi_device *spi)
50{ 50{
51 snd_soc_unregister_codec(&spi->dev); 51 adau17x1_remove(&spi->dev);
52 return 0; 52 return 0;
53} 53}
54 54
diff --git a/sound/soc/codecs/adau1781-i2c.c b/sound/soc/codecs/adau1781-i2c.c
index 06cbca84cf02..7b9d1802d159 100644
--- a/sound/soc/codecs/adau1781-i2c.c
+++ b/sound/soc/codecs/adau1781-i2c.c
@@ -31,7 +31,7 @@ static int adau1781_i2c_probe(struct i2c_client *client,
31 31
32static int adau1781_i2c_remove(struct i2c_client *client) 32static int adau1781_i2c_remove(struct i2c_client *client)
33{ 33{
34 snd_soc_unregister_codec(&client->dev); 34 adau17x1_remove(&client->dev);
35 return 0; 35 return 0;
36} 36}
37 37
diff --git a/sound/soc/codecs/adau1781-spi.c b/sound/soc/codecs/adau1781-spi.c
index 3d965a01b99c..9b233544d2e8 100644
--- a/sound/soc/codecs/adau1781-spi.c
+++ b/sound/soc/codecs/adau1781-spi.c
@@ -48,7 +48,7 @@ static int adau1781_spi_probe(struct spi_device *spi)
48 48
49static int adau1781_spi_remove(struct spi_device *spi) 49static int adau1781_spi_remove(struct spi_device *spi)
50{ 50{
51 snd_soc_unregister_codec(&spi->dev); 51 adau17x1_remove(&spi->dev);
52 return 0; 52 return 0;
53} 53}
54 54
diff --git a/sound/soc/codecs/adau17x1.c b/sound/soc/codecs/adau17x1.c
index 66a6e061923d..439aa3ff1f99 100644
--- a/sound/soc/codecs/adau17x1.c
+++ b/sound/soc/codecs/adau17x1.c
@@ -9,6 +9,7 @@
9 9
10#include <linux/module.h> 10#include <linux/module.h>
11#include <linux/init.h> 11#include <linux/init.h>
12#include <linux/clk.h>
12#include <linux/delay.h> 13#include <linux/delay.h>
13#include <linux/slab.h> 14#include <linux/slab.h>
14#include <sound/core.h> 15#include <sound/core.h>
@@ -303,6 +304,116 @@ bool adau17x1_has_dsp(struct adau *adau)
303} 304}
304EXPORT_SYMBOL_GPL(adau17x1_has_dsp); 305EXPORT_SYMBOL_GPL(adau17x1_has_dsp);
305 306
307static int adau17x1_set_dai_pll(struct snd_soc_dai *dai, int pll_id,
308 int source, unsigned int freq_in, unsigned int freq_out)
309{
310 struct snd_soc_codec *codec = dai->codec;
311 struct adau *adau = snd_soc_codec_get_drvdata(codec);
312 int ret;
313
314 if (freq_in < 8000000 || freq_in > 27000000)
315 return -EINVAL;
316
317 ret = adau_calc_pll_cfg(freq_in, freq_out, adau->pll_regs);
318 if (ret < 0)
319 return ret;
320
321 /* The PLL register is 6 bytes long and can only be written at once. */
322 ret = regmap_raw_write(adau->regmap, ADAU17X1_PLL_CONTROL,
323 adau->pll_regs, ARRAY_SIZE(adau->pll_regs));
324 if (ret)
325 return ret;
326
327 adau->pll_freq = freq_out;
328
329 return 0;
330}
331
332static int adau17x1_set_dai_sysclk(struct snd_soc_dai *dai,
333 int clk_id, unsigned int freq, int dir)
334{
335 struct snd_soc_dapm_context *dapm = snd_soc_codec_get_dapm(dai->codec);
336 struct adau *adau = snd_soc_codec_get_drvdata(dai->codec);
337 bool is_pll;
338 bool was_pll;
339
340 switch (clk_id) {
341 case ADAU17X1_CLK_SRC_MCLK:
342 is_pll = false;
343 break;
344 case ADAU17X1_CLK_SRC_PLL_AUTO:
345 if (!adau->mclk)
346 return -EINVAL;
347 /* Fall-through */
348 case ADAU17X1_CLK_SRC_PLL:
349 is_pll = true;
350 break;
351 default:
352 return -EINVAL;
353 }
354
355 switch (adau->clk_src) {
356 case ADAU17X1_CLK_SRC_MCLK:
357 was_pll = false;
358 break;
359 case ADAU17X1_CLK_SRC_PLL:
360 case ADAU17X1_CLK_SRC_PLL_AUTO:
361 was_pll = true;
362 break;
363 default:
364 return -EINVAL;
365 }
366
367 adau->sysclk = freq;
368
369 if (is_pll != was_pll) {
370 if (is_pll) {
371 snd_soc_dapm_add_routes(dapm,
372 &adau17x1_dapm_pll_route, 1);
373 } else {
374 snd_soc_dapm_del_routes(dapm,
375 &adau17x1_dapm_pll_route, 1);
376 }
377 }
378
379 adau->clk_src = clk_id;
380
381 return 0;
382}
383
384static int adau17x1_auto_pll(struct snd_soc_dai *dai,
385 struct snd_pcm_hw_params *params)
386{
387 struct adau *adau = snd_soc_dai_get_drvdata(dai);
388 unsigned int pll_rate;
389
390 switch (params_rate(params)) {
391 case 48000:
392 case 8000:
393 case 12000:
394 case 16000:
395 case 24000:
396 case 32000:
397 case 96000:
398 pll_rate = 48000 * 1024;
399 break;
400 case 44100:
401 case 7350:
402 case 11025:
403 case 14700:
404 case 22050:
405 case 29400:
406 case 88200:
407 pll_rate = 44100 * 1024;
408 break;
409 default:
410 return -EINVAL;
411 }
412
413 return adau17x1_set_dai_pll(dai, ADAU17X1_PLL, ADAU17X1_PLL_SRC_MCLK,
414 clk_get_rate(adau->mclk), pll_rate);
415}
416
306static int adau17x1_hw_params(struct snd_pcm_substream *substream, 417static int adau17x1_hw_params(struct snd_pcm_substream *substream,
307 struct snd_pcm_hw_params *params, struct snd_soc_dai *dai) 418 struct snd_pcm_hw_params *params, struct snd_soc_dai *dai)
308{ 419{
@@ -312,10 +423,19 @@ static int adau17x1_hw_params(struct snd_pcm_substream *substream,
312 unsigned int freq; 423 unsigned int freq;
313 int ret; 424 int ret;
314 425
315 if (adau->clk_src == ADAU17X1_CLK_SRC_PLL) 426 switch (adau->clk_src) {
427 case ADAU17X1_CLK_SRC_PLL_AUTO:
428 ret = adau17x1_auto_pll(dai, params);
429 if (ret)
430 return ret;
431 /* Fall-through */
432 case ADAU17X1_CLK_SRC_PLL:
316 freq = adau->pll_freq; 433 freq = adau->pll_freq;
317 else 434 break;
435 default:
318 freq = adau->sysclk; 436 freq = adau->sysclk;
437 break;
438 }
319 439
320 if (freq % params_rate(params) != 0) 440 if (freq % params_rate(params) != 0)
321 return -EINVAL; 441 return -EINVAL;
@@ -387,62 +507,6 @@ static int adau17x1_hw_params(struct snd_pcm_substream *substream,
387 ADAU17X1_SERIAL_PORT1_DELAY_MASK, val); 507 ADAU17X1_SERIAL_PORT1_DELAY_MASK, val);
388} 508}
389 509
390static int adau17x1_set_dai_pll(struct snd_soc_dai *dai, int pll_id,
391 int source, unsigned int freq_in, unsigned int freq_out)
392{
393 struct snd_soc_codec *codec = dai->codec;
394 struct adau *adau = snd_soc_codec_get_drvdata(codec);
395 int ret;
396
397 if (freq_in < 8000000 || freq_in > 27000000)
398 return -EINVAL;
399
400 ret = adau_calc_pll_cfg(freq_in, freq_out, adau->pll_regs);
401 if (ret < 0)
402 return ret;
403
404 /* The PLL register is 6 bytes long and can only be written at once. */
405 ret = regmap_raw_write(adau->regmap, ADAU17X1_PLL_CONTROL,
406 adau->pll_regs, ARRAY_SIZE(adau->pll_regs));
407 if (ret)
408 return ret;
409
410 adau->pll_freq = freq_out;
411
412 return 0;
413}
414
415static int adau17x1_set_dai_sysclk(struct snd_soc_dai *dai,
416 int clk_id, unsigned int freq, int dir)
417{
418 struct snd_soc_dapm_context *dapm = snd_soc_codec_get_dapm(dai->codec);
419 struct adau *adau = snd_soc_codec_get_drvdata(dai->codec);
420
421 switch (clk_id) {
422 case ADAU17X1_CLK_SRC_MCLK:
423 case ADAU17X1_CLK_SRC_PLL:
424 break;
425 default:
426 return -EINVAL;
427 }
428
429 adau->sysclk = freq;
430
431 if (adau->clk_src != clk_id) {
432 if (clk_id == ADAU17X1_CLK_SRC_PLL) {
433 snd_soc_dapm_add_routes(dapm,
434 &adau17x1_dapm_pll_route, 1);
435 } else {
436 snd_soc_dapm_del_routes(dapm,
437 &adau17x1_dapm_pll_route, 1);
438 }
439 }
440
441 adau->clk_src = clk_id;
442
443 return 0;
444}
445
446static int adau17x1_set_dai_fmt(struct snd_soc_dai *dai, 510static int adau17x1_set_dai_fmt(struct snd_soc_dai *dai,
447 unsigned int fmt) 511 unsigned int fmt)
448{ 512{
@@ -827,6 +891,10 @@ int adau17x1_add_routes(struct snd_soc_codec *codec)
827 ret = snd_soc_dapm_add_routes(dapm, adau17x1_no_dsp_dapm_routes, 891 ret = snd_soc_dapm_add_routes(dapm, adau17x1_no_dsp_dapm_routes,
828 ARRAY_SIZE(adau17x1_no_dsp_dapm_routes)); 892 ARRAY_SIZE(adau17x1_no_dsp_dapm_routes));
829 } 893 }
894
895 if (adau->clk_src != ADAU17X1_CLK_SRC_MCLK)
896 snd_soc_dapm_add_routes(dapm, &adau17x1_dapm_pll_route, 1);
897
830 return ret; 898 return ret;
831} 899}
832EXPORT_SYMBOL_GPL(adau17x1_add_routes); 900EXPORT_SYMBOL_GPL(adau17x1_add_routes);
@@ -849,6 +917,7 @@ int adau17x1_probe(struct device *dev, struct regmap *regmap,
849 const char *firmware_name) 917 const char *firmware_name)
850{ 918{
851 struct adau *adau; 919 struct adau *adau;
920 int ret;
852 921
853 if (IS_ERR(regmap)) 922 if (IS_ERR(regmap))
854 return PTR_ERR(regmap); 923 return PTR_ERR(regmap);
@@ -857,6 +926,30 @@ int adau17x1_probe(struct device *dev, struct regmap *regmap,
857 if (!adau) 926 if (!adau)
858 return -ENOMEM; 927 return -ENOMEM;
859 928
929 adau->mclk = devm_clk_get(dev, "mclk");
930 if (IS_ERR(adau->mclk)) {
931 if (PTR_ERR(adau->mclk) != -ENOENT)
932 return PTR_ERR(adau->mclk);
933 /* Clock is optional (for the driver) */
934 adau->mclk = NULL;
935 } else if (adau->mclk) {
936 adau->clk_src = ADAU17X1_CLK_SRC_PLL_AUTO;
937
938 /*
939 * Any valid PLL output rate will work at this point, use one
940 * that is likely to be chosen later as well. The register will
941 * be written when the PLL is powered up for the first time.
942 */
943 ret = adau_calc_pll_cfg(clk_get_rate(adau->mclk), 48000 * 1024,
944 adau->pll_regs);
945 if (ret < 0)
946 return ret;
947
948 ret = clk_prepare_enable(adau->mclk);
949 if (ret)
950 return ret;
951 }
952
860 adau->regmap = regmap; 953 adau->regmap = regmap;
861 adau->switch_mode = switch_mode; 954 adau->switch_mode = switch_mode;
862 adau->type = type; 955 adau->type = type;
@@ -880,6 +973,16 @@ int adau17x1_probe(struct device *dev, struct regmap *regmap,
880} 973}
881EXPORT_SYMBOL_GPL(adau17x1_probe); 974EXPORT_SYMBOL_GPL(adau17x1_probe);
882 975
976void adau17x1_remove(struct device *dev)
977{
978 struct adau *adau = dev_get_drvdata(dev);
979
980 snd_soc_unregister_codec(dev);
981 if (adau->mclk)
982 clk_disable_unprepare(adau->mclk);
983}
984EXPORT_SYMBOL_GPL(adau17x1_remove);
985
883MODULE_DESCRIPTION("ASoC ADAU1X61/ADAU1X81 common code"); 986MODULE_DESCRIPTION("ASoC ADAU1X61/ADAU1X81 common code");
884MODULE_AUTHOR("Lars-Peter Clausen <lars@metafoo.de>"); 987MODULE_AUTHOR("Lars-Peter Clausen <lars@metafoo.de>");
885MODULE_LICENSE("GPL"); 988MODULE_LICENSE("GPL");
diff --git a/sound/soc/codecs/adau17x1.h b/sound/soc/codecs/adau17x1.h
index 5ae87a084d97..bf04b7efee40 100644
--- a/sound/soc/codecs/adau17x1.h
+++ b/sound/soc/codecs/adau17x1.h
@@ -22,13 +22,18 @@ enum adau17x1_pll_src {
22}; 22};
23 23
24enum adau17x1_clk_src { 24enum adau17x1_clk_src {
25 /* Automatically configure PLL based on the sample rate */
26 ADAU17X1_CLK_SRC_PLL_AUTO,
25 ADAU17X1_CLK_SRC_MCLK, 27 ADAU17X1_CLK_SRC_MCLK,
26 ADAU17X1_CLK_SRC_PLL, 28 ADAU17X1_CLK_SRC_PLL,
27}; 29};
28 30
31struct clk;
32
29struct adau { 33struct adau {
30 unsigned int sysclk; 34 unsigned int sysclk;
31 unsigned int pll_freq; 35 unsigned int pll_freq;
36 struct clk *mclk;
32 37
33 enum adau17x1_clk_src clk_src; 38 enum adau17x1_clk_src clk_src;
34 enum adau17x1_type type; 39 enum adau17x1_type type;
@@ -52,6 +57,7 @@ int adau17x1_add_routes(struct snd_soc_codec *codec);
52int adau17x1_probe(struct device *dev, struct regmap *regmap, 57int adau17x1_probe(struct device *dev, struct regmap *regmap,
53 enum adau17x1_type type, void (*switch_mode)(struct device *dev), 58 enum adau17x1_type type, void (*switch_mode)(struct device *dev),
54 const char *firmware_name); 59 const char *firmware_name);
60void adau17x1_remove(struct device *dev);
55int adau17x1_set_micbias_voltage(struct snd_soc_codec *codec, 61int adau17x1_set_micbias_voltage(struct snd_soc_codec *codec,
56 enum adau17x1_micbias_voltage micbias); 62 enum adau17x1_micbias_voltage micbias);
57bool adau17x1_readable_register(struct device *dev, unsigned int reg); 63bool adau17x1_readable_register(struct device *dev, unsigned int reg);