diff options
author | Kuninori Morimoto <kuninori.morimoto.gx@renesas.com> | 2015-09-10 03:04:45 -0400 |
---|---|---|
committer | Mark Brown <broonie@kernel.org> | 2015-09-14 14:47:32 -0400 |
commit | 2a46db4a3787edb0dc07276f21f33bbaf01938f1 (patch) | |
tree | 7fa59f097d8dd632f92fa31af52c4a874f428dcc | |
parent | 248e88c2fb5a09eb87b21b00fd4167cc99c05759 (diff) |
ASoC: rsnd: add AUDIO_CLKOUT support
Renesas sound has AUDIO_CLKOUT (in Gen1/Gen2) AUDIO_CLKOUT1/2/3 (in Gen3)
This patch support these patches as clock provider.
Signed-off-by: Kuninori Morimoto <kuninori.morimoto.gx@renesas.com>
Signed-off-by: Mark Brown <broonie@kernel.org>
-rw-r--r-- | Documentation/devicetree/bindings/sound/renesas,rsnd.txt | 3 | ||||
-rw-r--r-- | sound/soc/sh/rcar/adg.c | 98 |
2 files changed, 97 insertions, 4 deletions
diff --git a/Documentation/devicetree/bindings/sound/renesas,rsnd.txt b/Documentation/devicetree/bindings/sound/renesas,rsnd.txt index bf6fd1af0a11..c57cbd65736c 100644 --- a/Documentation/devicetree/bindings/sound/renesas,rsnd.txt +++ b/Documentation/devicetree/bindings/sound/renesas,rsnd.txt | |||
@@ -34,6 +34,9 @@ Required properties: | |||
34 | see below for detail. | 34 | see below for detail. |
35 | - #sound-dai-cells : it must be 0 if your system is using single DAI | 35 | - #sound-dai-cells : it must be 0 if your system is using single DAI |
36 | it must be 1 if your system is using multi DAI | 36 | it must be 1 if your system is using multi DAI |
37 | - #clock-cells : it must be 0 if your system has audio_clkout | ||
38 | it must be 1 if your system has audio_clkout0/1/2/3 | ||
39 | - clock-frequency : for all audio_clkout0/1/2/3 | ||
37 | 40 | ||
38 | SSI subnode properties: | 41 | SSI subnode properties: |
39 | - interrupts : Should contain SSI interrupt for PIO transfer | 42 | - interrupts : Should contain SSI interrupt for PIO transfer |
diff --git a/sound/soc/sh/rcar/adg.c b/sound/soc/sh/rcar/adg.c index d4fb11a3ce64..3fecb87f45ba 100644 --- a/sound/soc/sh/rcar/adg.c +++ b/sound/soc/sh/rcar/adg.c | |||
@@ -7,6 +7,7 @@ | |||
7 | * License. See the file "COPYING" in the main directory of this archive | 7 | * License. See the file "COPYING" in the main directory of this archive |
8 | * for more details. | 8 | * for more details. |
9 | */ | 9 | */ |
10 | #include <linux/clk-provider.h> | ||
10 | #include "rsnd.h" | 11 | #include "rsnd.h" |
11 | 12 | ||
12 | #define CLKA 0 | 13 | #define CLKA 0 |
@@ -15,6 +16,12 @@ | |||
15 | #define CLKI 3 | 16 | #define CLKI 3 |
16 | #define CLKMAX 4 | 17 | #define CLKMAX 4 |
17 | 18 | ||
19 | #define CLKOUT 0 | ||
20 | #define CLKOUT1 1 | ||
21 | #define CLKOUT2 2 | ||
22 | #define CLKOUT3 3 | ||
23 | #define CLKOUTMAX 4 | ||
24 | |||
18 | #define BRRx_MASK(x) (0x3FF & x) | 25 | #define BRRx_MASK(x) (0x3FF & x) |
19 | 26 | ||
20 | static struct rsnd_mod_ops adg_ops = { | 27 | static struct rsnd_mod_ops adg_ops = { |
@@ -23,6 +30,8 @@ static struct rsnd_mod_ops adg_ops = { | |||
23 | 30 | ||
24 | struct rsnd_adg { | 31 | struct rsnd_adg { |
25 | struct clk *clk[CLKMAX]; | 32 | struct clk *clk[CLKMAX]; |
33 | struct clk *clkout[CLKOUTMAX]; | ||
34 | struct clk_onecell_data onecell; | ||
26 | struct rsnd_mod mod; | 35 | struct rsnd_mod mod; |
27 | 36 | ||
28 | int rbga_rate_for_441khz; /* RBGA */ | 37 | int rbga_rate_for_441khz; /* RBGA */ |
@@ -34,6 +43,11 @@ struct rsnd_adg { | |||
34 | (i < CLKMAX) && \ | 43 | (i < CLKMAX) && \ |
35 | ((pos) = adg->clk[i]); \ | 44 | ((pos) = adg->clk[i]); \ |
36 | i++) | 45 | i++) |
46 | #define for_each_rsnd_clkout(pos, adg, i) \ | ||
47 | for (i = 0; \ | ||
48 | (i < CLKOUTMAX) && \ | ||
49 | ((pos) = adg->clkout[i]); \ | ||
50 | i++) | ||
37 | #define rsnd_priv_to_adg(priv) ((struct rsnd_adg *)(priv)->adg) | 51 | #define rsnd_priv_to_adg(priv) ((struct rsnd_adg *)(priv)->adg) |
38 | 52 | ||
39 | static u32 rsnd_adg_calculate_rbgx(unsigned long div) | 53 | static u32 rsnd_adg_calculate_rbgx(unsigned long div) |
@@ -416,14 +430,25 @@ static void rsnd_adg_get_clkin(struct rsnd_priv *priv, | |||
416 | dev_dbg(dev, "clk %d : %p : %ld\n", i, clk, clk_get_rate(clk)); | 430 | dev_dbg(dev, "clk %d : %p : %ld\n", i, clk, clk_get_rate(clk)); |
417 | } | 431 | } |
418 | 432 | ||
419 | static void rsnd_adg_ssi_clk_init(struct rsnd_priv *priv, struct rsnd_adg *adg) | 433 | static void rsnd_adg_get_clkout(struct rsnd_priv *priv, |
434 | struct rsnd_adg *adg) | ||
420 | { | 435 | { |
421 | struct clk *clk; | 436 | struct clk *clk; |
422 | struct rsnd_mod *adg_mod = rsnd_mod_get(adg); | 437 | struct rsnd_mod *adg_mod = rsnd_mod_get(adg); |
423 | struct device *dev = rsnd_priv_to_dev(priv); | 438 | struct device *dev = rsnd_priv_to_dev(priv); |
424 | unsigned long rate, div; | 439 | struct device_node *np = dev->of_node; |
425 | u32 ckr, rbgx, rbga, rbgb; | 440 | u32 ckr, rbgx, rbga, rbgb; |
441 | u32 rate, req_rate, div; | ||
442 | uint32_t count = 0; | ||
443 | unsigned long req_48kHz_rate, req_441kHz_rate; | ||
426 | int i; | 444 | int i; |
445 | const char *parent_clk_name = NULL; | ||
446 | static const char * const clkout_name[] = { | ||
447 | [CLKOUT] = "audio_clkout", | ||
448 | [CLKOUT1] = "audio_clkout1", | ||
449 | [CLKOUT2] = "audio_clkout2", | ||
450 | [CLKOUT3] = "audio_clkout3", | ||
451 | }; | ||
427 | int brg_table[] = { | 452 | int brg_table[] = { |
428 | [CLKA] = 0x0, | 453 | [CLKA] = 0x0, |
429 | [CLKB] = 0x1, | 454 | [CLKB] = 0x1, |
@@ -431,6 +456,20 @@ static void rsnd_adg_ssi_clk_init(struct rsnd_priv *priv, struct rsnd_adg *adg) | |||
431 | [CLKI] = 0x2, | 456 | [CLKI] = 0x2, |
432 | }; | 457 | }; |
433 | 458 | ||
459 | of_property_read_u32(np, "#clock-cells", &count); | ||
460 | |||
461 | /* | ||
462 | * ADG supports BRRA/BRRB output only | ||
463 | * this means all clkout0/1/2/3 will be same rate | ||
464 | */ | ||
465 | of_property_read_u32(np, "clock-frequency", &req_rate); | ||
466 | req_48kHz_rate = 0; | ||
467 | req_441kHz_rate = 0; | ||
468 | if (0 == (req_rate % 44100)) | ||
469 | req_441kHz_rate = req_rate; | ||
470 | if (0 == (req_rate % 48000)) | ||
471 | req_48kHz_rate = req_rate; | ||
472 | |||
434 | /* | 473 | /* |
435 | * This driver is assuming that AUDIO_CLKA/AUDIO_CLKB/AUDIO_CLKC | 474 | * This driver is assuming that AUDIO_CLKA/AUDIO_CLKB/AUDIO_CLKC |
436 | * have 44.1kHz or 48kHz base clocks for now. | 475 | * have 44.1kHz or 48kHz base clocks for now. |
@@ -454,22 +493,72 @@ static void rsnd_adg_ssi_clk_init(struct rsnd_priv *priv, struct rsnd_adg *adg) | |||
454 | /* RBGA */ | 493 | /* RBGA */ |
455 | if (!adg->rbga_rate_for_441khz && (0 == rate % 44100)) { | 494 | if (!adg->rbga_rate_for_441khz && (0 == rate % 44100)) { |
456 | div = 6; | 495 | div = 6; |
496 | if (req_441kHz_rate) | ||
497 | div = rate / req_441kHz_rate; | ||
457 | rbgx = rsnd_adg_calculate_rbgx(div); | 498 | rbgx = rsnd_adg_calculate_rbgx(div); |
458 | if (BRRx_MASK(rbgx) == rbgx) { | 499 | if (BRRx_MASK(rbgx) == rbgx) { |
459 | rbga = rbgx; | 500 | rbga = rbgx; |
460 | adg->rbga_rate_for_441khz = rate / div; | 501 | adg->rbga_rate_for_441khz = rate / div; |
461 | ckr |= brg_table[i] << 20; | 502 | ckr |= brg_table[i] << 20; |
503 | if (req_441kHz_rate) | ||
504 | parent_clk_name = __clk_get_name(clk); | ||
462 | } | 505 | } |
463 | } | 506 | } |
464 | 507 | ||
465 | /* RBGB */ | 508 | /* RBGB */ |
466 | if (!adg->rbgb_rate_for_48khz && (0 == rate % 48000)) { | 509 | if (!adg->rbgb_rate_for_48khz && (0 == rate % 48000)) { |
467 | div = 6; | 510 | div = 6; |
511 | if (req_48kHz_rate) | ||
512 | div = rate / req_48kHz_rate; | ||
468 | rbgx = rsnd_adg_calculate_rbgx(div); | 513 | rbgx = rsnd_adg_calculate_rbgx(div); |
469 | if (BRRx_MASK(rbgx) == rbgx) { | 514 | if (BRRx_MASK(rbgx) == rbgx) { |
470 | rbgb = rbgx; | 515 | rbgb = rbgx; |
471 | adg->rbgb_rate_for_48khz = rate / div; | 516 | adg->rbgb_rate_for_48khz = rate / div; |
472 | ckr |= brg_table[i] << 16; | 517 | ckr |= brg_table[i] << 16; |
518 | if (req_48kHz_rate) { | ||
519 | parent_clk_name = __clk_get_name(clk); | ||
520 | ckr |= 0x80000000; | ||
521 | } | ||
522 | } | ||
523 | } | ||
524 | } | ||
525 | |||
526 | /* | ||
527 | * ADG supports BRRA/BRRB output only. | ||
528 | * this means all clkout0/1/2/3 will be * same rate | ||
529 | */ | ||
530 | |||
531 | /* | ||
532 | * for clkout | ||
533 | */ | ||
534 | if (!count) { | ||
535 | clk = clk_register_fixed_rate(dev, clkout_name[i], | ||
536 | parent_clk_name, | ||
537 | (parent_clk_name) ? | ||
538 | 0 : CLK_IS_ROOT, req_rate); | ||
539 | if (!IS_ERR(clk)) { | ||
540 | adg->clkout[CLKOUT] = clk; | ||
541 | of_clk_add_provider(np, of_clk_src_simple_get, clk); | ||
542 | } | ||
543 | } | ||
544 | /* | ||
545 | * for clkout0/1/2/3 | ||
546 | */ | ||
547 | else { | ||
548 | for (i = 0; i < CLKOUTMAX; i++) { | ||
549 | clk = clk_register_fixed_rate(dev, clkout_name[i], | ||
550 | parent_clk_name, | ||
551 | (parent_clk_name) ? | ||
552 | 0 : CLK_IS_ROOT, | ||
553 | req_rate); | ||
554 | if (!IS_ERR(clk)) { | ||
555 | adg->onecell.clks = adg->clkout; | ||
556 | adg->onecell.clk_num = CLKOUTMAX; | ||
557 | |||
558 | adg->clkout[i] = clk; | ||
559 | |||
560 | of_clk_add_provider(np, of_clk_src_onecell_get, | ||
561 | &adg->onecell); | ||
473 | } | 562 | } |
474 | } | 563 | } |
475 | } | 564 | } |
@@ -478,6 +567,8 @@ static void rsnd_adg_ssi_clk_init(struct rsnd_priv *priv, struct rsnd_adg *adg) | |||
478 | rsnd_mod_write(adg_mod, BRRA, rbga); | 567 | rsnd_mod_write(adg_mod, BRRA, rbga); |
479 | rsnd_mod_write(adg_mod, BRRB, rbgb); | 568 | rsnd_mod_write(adg_mod, BRRB, rbgb); |
480 | 569 | ||
570 | for_each_rsnd_clkout(clk, adg, i) | ||
571 | dev_dbg(dev, "clkout %d : %p : %ld\n", i, clk, clk_get_rate(clk)); | ||
481 | dev_dbg(dev, "SSICKR = 0x%08x, BRRA/BRRB = 0x%x/0x%x\n", | 572 | dev_dbg(dev, "SSICKR = 0x%08x, BRRA/BRRB = 0x%x/0x%x\n", |
482 | ckr, rbga, rbgb); | 573 | ckr, rbga, rbgb); |
483 | } | 574 | } |
@@ -504,8 +595,7 @@ int rsnd_adg_probe(struct platform_device *pdev, | |||
504 | adg->mod.priv = priv; | 595 | adg->mod.priv = priv; |
505 | 596 | ||
506 | rsnd_adg_get_clkin(priv, adg); | 597 | rsnd_adg_get_clkin(priv, adg); |
507 | 598 | rsnd_adg_get_clkout(priv, adg); | |
508 | rsnd_adg_ssi_clk_init(priv, adg); | ||
509 | 599 | ||
510 | priv->adg = adg; | 600 | priv->adg = adg; |
511 | 601 | ||