Skip to content

Commit fd53c16

Browse files
committed
ASoC: rsnd: tidyup ADG
Merge series from Kuninori Morimoto <kuninori.morimoto.gx@renesas.com>: Renesas Sound has ADG for clock control. Basically it needs accurately divisible external input clock. But sometimes sometimes it doesn't have to be accurate for some reason. We can use ADG clk_i for such case. It came from CPG as very high rate clock, but is not accurately divisible for 48kHz/44.1kHz rate, but enough for approximate rate. This patch set support such use case.
2 parents ea2cb26 + 4acdf9a commit fd53c16

File tree

1 file changed

+55
-13
lines changed

1 file changed

+55
-13
lines changed

sound/soc/sh/rcar/adg.c

Lines changed: 55 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -358,8 +358,6 @@ int rsnd_adg_ssi_clk_try_start(struct rsnd_mod *ssi_mod, unsigned int rate)
358358
ckr = 0x80000000; /* BRGB output = 48kHz */
359359

360360
rsnd_mod_bset(adg_mod, BRGCKR, 0x80770000, adg->ckr | ckr);
361-
rsnd_mod_write(adg_mod, BRRA, adg->brga);
362-
rsnd_mod_write(adg_mod, BRRB, adg->brgb);
363361

364362
dev_dbg(dev, "CLKOUT is based on BRG%c (= %dHz)\n",
365363
(ckr) ? 'B' : 'A',
@@ -372,9 +370,16 @@ int rsnd_adg_ssi_clk_try_start(struct rsnd_mod *ssi_mod, unsigned int rate)
372370
void rsnd_adg_clk_control(struct rsnd_priv *priv, int enable)
373371
{
374372
struct rsnd_adg *adg = rsnd_priv_to_adg(priv);
373+
struct rsnd_mod *adg_mod = rsnd_mod_get(adg);
375374
struct clk *clk;
376375
int i;
377376

377+
if (enable) {
378+
rsnd_mod_bset(adg_mod, BRGCKR, 0x80770000, adg->ckr);
379+
rsnd_mod_write(adg_mod, BRRA, adg->brga);
380+
rsnd_mod_write(adg_mod, BRRB, adg->brgb);
381+
}
382+
378383
for_each_rsnd_clkin(clk, adg, i) {
379384
if (enable) {
380385
clk_prepare_enable(clk);
@@ -485,12 +490,12 @@ static int rsnd_adg_get_clkout(struct rsnd_priv *priv)
485490
struct device_node *np = dev->of_node;
486491
struct property *prop;
487492
u32 ckr, brgx, brga, brgb;
488-
u32 rate, div;
489493
u32 req_rate[ADG_HZ_SIZE] = {};
490494
uint32_t count = 0;
491495
unsigned long req_Hz[ADG_HZ_SIZE];
492496
int clkout_size;
493497
int i, req_size;
498+
int approximate = 0;
494499
const char *parent_clk_name = NULL;
495500
const char * const *clkout_name;
496501
int brg_table[] = {
@@ -501,8 +506,8 @@ static int rsnd_adg_get_clkout(struct rsnd_priv *priv)
501506
};
502507

503508
ckr = 0;
504-
brga = 2; /* default 1/6 */
505-
brgb = 2; /* default 1/6 */
509+
brga = 0xff; /* default */
510+
brgb = 0xff; /* default */
506511

507512
/*
508513
* ADG supports BRRA/BRRB output only
@@ -537,43 +542,80 @@ static int rsnd_adg_get_clkout(struct rsnd_priv *priv)
537542
* rsnd_adg_ssi_clk_try_start()
538543
* rsnd_ssi_master_clk_start()
539544
*/
545+
546+
/*
547+
* [APPROXIMATE]
548+
*
549+
* clk_i (internal clock) can't create accurate rate, it will be approximate rate.
550+
*
551+
* <Note>
552+
*
553+
* clk_i needs x2 of required maximum rate.
554+
* see
555+
* - Minimum division of BRRA/BRRB
556+
* - rsnd_ssi_clk_query()
557+
*
558+
* Sample Settings for TDM 8ch, 32bit width
559+
*
560+
* 8(ch) x 32(bit) x 44100(Hz) x 2<Note> = 22579200
561+
* 8(ch) x 32(bit) x 48000(Hz) x 2<Note> = 24576000
562+
*
563+
* clock-frequency = <22579200 24576000>;
564+
*/
540565
for_each_rsnd_clkin(clk, adg, i) {
566+
u32 rate, div;
567+
541568
rate = clk_get_rate(clk);
542569

543570
if (0 == rate) /* not used */
544571
continue;
545572

546573
/* BRGA */
547-
if (!adg->brg_rate[ADG_HZ_441] && (0 == rate % 44100)) {
548-
div = 6;
549-
if (req_Hz[ADG_HZ_441])
550-
div = rate / req_Hz[ADG_HZ_441];
574+
575+
if (i == CLKI)
576+
/* see [APPROXIMATE] */
577+
rate = (clk_get_rate(clk) / req_Hz[ADG_HZ_441]) * req_Hz[ADG_HZ_441];
578+
if (!adg->brg_rate[ADG_HZ_441] && req_Hz[ADG_HZ_441] && (0 == rate % 44100)) {
579+
div = rate / req_Hz[ADG_HZ_441];
551580
brgx = rsnd_adg_calculate_brgx(div);
552581
if (BRRx_MASK(brgx) == brgx) {
553582
brga = brgx;
554583
adg->brg_rate[ADG_HZ_441] = rate / div;
555584
ckr |= brg_table[i] << 20;
556585
if (req_Hz[ADG_HZ_441])
557586
parent_clk_name = __clk_get_name(clk);
587+
if (i == CLKI)
588+
approximate = 1;
558589
}
559590
}
560591

561592
/* BRGB */
562-
if (!adg->brg_rate[ADG_HZ_48] && (0 == rate % 48000)) {
563-
div = 6;
564-
if (req_Hz[ADG_HZ_48])
565-
div = rate / req_Hz[ADG_HZ_48];
593+
594+
if (i == CLKI)
595+
/* see [APPROXIMATE] */
596+
rate = (clk_get_rate(clk) / req_Hz[ADG_HZ_48]) * req_Hz[ADG_HZ_48];
597+
if (!adg->brg_rate[ADG_HZ_48] && req_Hz[ADG_HZ_48] && (0 == rate % 48000)) {
598+
div = rate / req_Hz[ADG_HZ_48];
566599
brgx = rsnd_adg_calculate_brgx(div);
567600
if (BRRx_MASK(brgx) == brgx) {
568601
brgb = brgx;
569602
adg->brg_rate[ADG_HZ_48] = rate / div;
570603
ckr |= brg_table[i] << 16;
571604
if (req_Hz[ADG_HZ_48])
572605
parent_clk_name = __clk_get_name(clk);
606+
if (i == CLKI)
607+
approximate = 1;
573608
}
574609
}
575610
}
576611

612+
if (!(adg->brg_rate[ADG_HZ_48] && req_Hz[ADG_HZ_48]) &&
613+
!(adg->brg_rate[ADG_HZ_441] && req_Hz[ADG_HZ_441]))
614+
goto rsnd_adg_get_clkout_end;
615+
616+
if (approximate)
617+
dev_info(dev, "It uses CLK_I as approximate rate");
618+
577619
clkout_name = clkout_name_gen2;
578620
clkout_size = ARRAY_SIZE(clkout_name_gen2);
579621
if (rsnd_is_gen4(priv))

0 commit comments

Comments
 (0)