Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

ASoC: ak4642: enable to use MCKO as fixed rate output pin on DT

ak4642 chip can output clock via MCKO pin as audio reference clock.
This patch supports it on DT

Signed-off-by: Kuninori Morimoto <kuninori.morimoto.gx@renesas.com>
Signed-off-by: Mark Brown <broonie@kernel.org>

authored by

Kuninori Morimoto and committed by
Mark Brown
171a0138 2719a752

+114 -49
+21 -1
Documentation/devicetree/bindings/sound/ak4642.txt
··· 7 7 - compatible : "asahi-kasei,ak4642" or "asahi-kasei,ak4643" or "asahi-kasei,ak4648" 8 8 - reg : The chip select number on the I2C bus 9 9 10 - Example: 10 + Optional properties: 11 + 12 + - #clock-cells : common clock binding; shall be set to 0 13 + - clocks : common clock binding; MCKI clock 14 + - clock-frequency : common clock binding; frequency of MCKO 15 + - clock-output-names : common clock binding; MCKO clock name 16 + 17 + Example 1: 11 18 12 19 &i2c { 13 20 ak4648: ak4648@0x12 { 14 21 compatible = "asahi-kasei,ak4642"; 15 22 reg = <0x12>; 23 + }; 24 + }; 25 + 26 + Example 2: 27 + 28 + &i2c { 29 + ak4643: codec@12 { 30 + compatible = "asahi-kasei,ak4643"; 31 + reg = <0x12>; 32 + #clock-cells = <0>; 33 + clocks = <&audio_clock>; 34 + clock-frequency = <12288000>; 35 + clock-output-names = "ak4643_mcko"; 16 36 }; 17 37 };
+93 -48
sound/soc/codecs/ak4642.c
··· 23 23 * AK4648 is tested. 24 24 */ 25 25 26 + #include <linux/clk.h> 27 + #include <linux/clk-provider.h> 26 28 #include <linux/delay.h> 27 29 #include <linux/i2c.h> 28 30 #include <linux/slab.h> ··· 130 128 #define I2S (3 << 0) 131 129 132 130 /* MD_CTL2 */ 133 - #define FS0 (1 << 0) 134 - #define FS1 (1 << 1) 135 - #define FS2 (1 << 2) 136 - #define FS3 (1 << 5) 137 - #define FS_MASK (FS0 | FS1 | FS2 | FS3) 131 + #define FS(val) (((val & 0x7) << 0) | ((val & 0x8) << 2)) 132 + #define PS(val) ((val & 0x3) << 6) 138 133 139 134 /* MD_CTL3 */ 140 135 #define BST1 (1 << 3) ··· 146 147 147 148 struct ak4642_priv { 148 149 const struct ak4642_drvdata *drvdata; 150 + struct clk *mcko; 149 151 }; 150 152 151 153 /* ··· 430 430 return 0; 431 431 } 432 432 433 + static int ak4642_set_mcko(struct snd_soc_codec *codec, 434 + u32 frequency) 435 + { 436 + u32 fs_list[] = { 437 + [0] = 8000, 438 + [1] = 12000, 439 + [2] = 16000, 440 + [3] = 24000, 441 + [4] = 7350, 442 + [5] = 11025, 443 + [6] = 14700, 444 + [7] = 22050, 445 + [10] = 32000, 446 + [11] = 48000, 447 + [14] = 29400, 448 + [15] = 44100, 449 + }; 450 + u32 ps_list[] = { 451 + [0] = 256, 452 + [1] = 128, 453 + [2] = 64, 454 + [3] = 32 455 + }; 456 + int ps, fs; 457 + 458 + for (ps = 0; ps < ARRAY_SIZE(ps_list); ps++) { 459 + for (fs = 0; fs < ARRAY_SIZE(fs_list); fs++) { 460 + if (frequency == ps_list[ps] * fs_list[fs]) { 461 + snd_soc_write(codec, MD_CTL2, PS(ps) | FS(fs)); 462 + return 0; 463 + } 464 + } 465 + } 466 + 467 + return 0; 468 + } 469 + 433 470 static int ak4642_dai_hw_params(struct snd_pcm_substream *substream, 434 471 struct snd_pcm_hw_params *params, 435 472 struct snd_soc_dai *dai) 436 473 { 437 474 struct snd_soc_codec *codec = dai->codec; 438 - u8 rate; 475 + struct ak4642_priv *priv = snd_soc_codec_get_drvdata(codec); 476 + u32 rate = clk_get_rate(priv->mcko); 439 477 440 - switch (params_rate(params)) { 441 - case 7350: 442 - rate = FS2; 443 - break; 444 - case 8000: 445 - rate = 0; 446 - break; 447 - case 11025: 448 - rate = FS2 | FS0; 449 - break; 450 - case 12000: 451 - rate = FS0; 452 - break; 453 - case 14700: 454 - rate = FS2 | FS1; 455 - break; 456 - case 16000: 457 - rate = FS1; 458 - break; 459 - case 22050: 460 - rate = FS2 | FS1 | FS0; 461 - break; 462 - case 24000: 463 - rate = FS1 | FS0; 464 - break; 465 - case 29400: 466 - rate = FS3 | FS2 | FS1; 467 - break; 468 - case 32000: 469 - rate = FS3 | FS1; 470 - break; 471 - case 44100: 472 - rate = FS3 | FS2 | FS1 | FS0; 473 - break; 474 - case 48000: 475 - rate = FS3 | FS1 | FS0; 476 - break; 477 - default: 478 - return -EINVAL; 479 - } 480 - snd_soc_update_bits(codec, MD_CTL2, FS_MASK, rate); 478 + if (!rate) 479 + rate = params_rate(params) * 256; 481 480 482 - return 0; 481 + return ak4642_set_mcko(codec, rate); 483 482 } 484 483 485 484 static int ak4642_set_bias_level(struct snd_soc_codec *codec, ··· 531 532 return 0; 532 533 } 533 534 535 + static int ak4642_probe(struct snd_soc_codec *codec) 536 + { 537 + struct ak4642_priv *priv = snd_soc_codec_get_drvdata(codec); 538 + 539 + if (priv->mcko) 540 + ak4642_set_mcko(codec, clk_get_rate(priv->mcko)); 541 + 542 + return 0; 543 + } 544 + 534 545 static struct snd_soc_codec_driver soc_codec_dev_ak4642 = { 546 + .probe = ak4642_probe, 535 547 .resume = ak4642_resume, 536 548 .set_bias_level = ak4642_set_bias_level, 537 549 .controls = ak4642_snd_controls, ··· 590 580 .extended_frequencies = 1, 591 581 }; 592 582 583 + #ifdef CONFIG_COMMON_CLK 584 + static struct clk *ak4642_of_parse_mcko(struct device *dev) 585 + { 586 + struct device_node *np = dev->of_node; 587 + struct clk *clk; 588 + const char *clk_name = np->name; 589 + const char *parent_clk_name = NULL; 590 + u32 rate; 591 + 592 + if (of_property_read_u32(np, "clock-frequency", &rate)) 593 + return NULL; 594 + 595 + if (of_property_read_bool(np, "clocks")) 596 + parent_clk_name = of_clk_get_parent_name(np, 0); 597 + 598 + of_property_read_string(np, "clock-output-names", &clk_name); 599 + 600 + clk = clk_register_fixed_rate(dev, clk_name, parent_clk_name, 601 + (parent_clk_name) ? 0 : CLK_IS_ROOT, 602 + rate); 603 + if (!IS_ERR(clk)) 604 + of_clk_add_provider(np, of_clk_src_simple_get, clk); 605 + 606 + return clk; 607 + } 608 + #else 609 + #define ak4642_of_parse_mcko(d) 0 610 + #endif 611 + 593 612 static const struct of_device_id ak4642_of_match[]; 594 613 static int ak4642_i2c_probe(struct i2c_client *i2c, 595 614 const struct i2c_device_id *id) ··· 628 589 const struct ak4642_drvdata *drvdata = NULL; 629 590 struct regmap *regmap; 630 591 struct ak4642_priv *priv; 592 + struct clk *mcko = NULL; 631 593 632 594 if (np) { 633 595 const struct of_device_id *of_id; 596 + 597 + mcko = ak4642_of_parse_mcko(dev); 598 + if (IS_ERR(mcko)) 599 + mcko = NULL; 634 600 635 601 of_id = of_match_device(ak4642_of_match, dev); 636 602 if (of_id) ··· 654 610 return -ENOMEM; 655 611 656 612 priv->drvdata = drvdata; 613 + priv->mcko = mcko; 657 614 658 615 i2c_set_clientdata(i2c, priv); 659 616