776 lines · c
1// SPDX-License-Identifier: GPL-2.02//3// Helper routines for R-Car sound ADG.4//5// Copyright (C) 2013 Kuninori Morimoto <kuninori.morimoto.gx@renesas.com>6#include <linux/clk-provider.h>7#include <linux/clkdev.h>8#include "rsnd.h"9 10#define CLKA 011#define CLKB 112#define CLKC 213#define CLKI 314#define CLKINMAX 415 16#define CLKOUT 017#define CLKOUT1 118#define CLKOUT2 219#define CLKOUT3 320#define CLKOUTMAX 421 22#define BRRx_MASK(x) (0x3FF & x)23 24static struct rsnd_mod_ops adg_ops = {25 .name = "adg",26};27 28#define ADG_HZ_441 029#define ADG_HZ_48 130#define ADG_HZ_SIZE 231 32struct rsnd_adg {33 struct clk *clkin[CLKINMAX];34 struct clk *clkout[CLKOUTMAX];35 struct clk *null_clk;36 struct clk_onecell_data onecell;37 struct rsnd_mod mod;38 int clkin_rate[CLKINMAX];39 int clkin_size;40 int clkout_size;41 u32 ckr;42 u32 brga;43 u32 brgb;44 45 int brg_rate[ADG_HZ_SIZE]; /* BRGA / BRGB */46};47 48#define for_each_rsnd_clkin(pos, adg, i) \49 for (i = 0; \50 (i < adg->clkin_size) && \51 ((pos) = adg->clkin[i]); \52 i++)53#define for_each_rsnd_clkout(pos, adg, i) \54 for (i = 0; \55 (i < adg->clkout_size) && \56 ((pos) = adg->clkout[i]); \57 i++)58#define rsnd_priv_to_adg(priv) ((struct rsnd_adg *)(priv)->adg)59 60static const char * const clkin_name_gen4[] = {61 [CLKA] = "clkin",62};63 64static const char * const clkin_name_gen2[] = {65 [CLKA] = "clk_a",66 [CLKB] = "clk_b",67 [CLKC] = "clk_c",68 [CLKI] = "clk_i",69};70 71static const char * const clkout_name_gen2[] = {72 [CLKOUT] = "audio_clkout",73 [CLKOUT1] = "audio_clkout1",74 [CLKOUT2] = "audio_clkout2",75 [CLKOUT3] = "audio_clkout3",76};77 78static u32 rsnd_adg_calculate_brgx(unsigned long div)79{80 int i;81 82 if (!div)83 return 0;84 85 for (i = 3; i >= 0; i--) {86 int ratio = 2 << (i * 2);87 if (0 == (div % ratio))88 return (u32)((i << 8) | ((div / ratio) - 1));89 }90 91 return ~0;92}93 94static u32 rsnd_adg_ssi_ws_timing_gen2(struct rsnd_dai_stream *io)95{96 struct rsnd_mod *ssi_mod = rsnd_io_to_mod_ssi(io);97 int id = rsnd_mod_id(ssi_mod);98 int ws = id;99 100 if (rsnd_ssi_is_pin_sharing(io)) {101 switch (id) {102 case 1:103 case 2:104 case 9:105 ws = 0;106 break;107 case 4:108 ws = 3;109 break;110 case 8:111 ws = 7;112 break;113 }114 } else {115 /*116 * SSI8 is not connected to ADG.117 * Thus SSI9 is using ws = 8118 */119 if (id == 9)120 ws = 8;121 }122 123 return (0x6 + ws) << 8;124}125 126static void __rsnd_adg_get_timesel_ratio(struct rsnd_priv *priv,127 struct rsnd_dai_stream *io,128 unsigned int target_rate,129 unsigned int *target_val,130 unsigned int *target_en)131{132 struct rsnd_adg *adg = rsnd_priv_to_adg(priv);133 struct device *dev = rsnd_priv_to_dev(priv);134 int sel;135 unsigned int val, en;136 unsigned int min, diff;137 unsigned int sel_rate[] = {138 adg->clkin_rate[CLKA], /* 0000: CLKA */139 adg->clkin_rate[CLKB], /* 0001: CLKB */140 adg->clkin_rate[CLKC], /* 0010: CLKC */141 adg->brg_rate[ADG_HZ_441], /* 0011: BRGA */142 adg->brg_rate[ADG_HZ_48], /* 0100: BRGB */143 };144 145 min = ~0;146 val = 0;147 en = 0;148 for (sel = 0; sel < ARRAY_SIZE(sel_rate); sel++) {149 int idx = 0;150 int step = 2;151 int div;152 153 if (!sel_rate[sel])154 continue;155 156 for (div = 2; div <= 98304; div += step) {157 diff = abs(target_rate - sel_rate[sel] / div);158 if (min > diff) {159 val = (sel << 8) | idx;160 min = diff;161 en = 1 << (sel + 1); /* fixme */162 }163 164 /*165 * step of 0_0000 / 0_0001 / 0_1101166 * are out of order167 */168 if ((idx > 2) && (idx % 2))169 step *= 2;170 if (idx == 0x1c) {171 div += step;172 step *= 2;173 }174 idx++;175 }176 }177 178 if (min == ~0) {179 dev_err(dev, "no Input clock\n");180 return;181 }182 183 *target_val = val;184 if (target_en)185 *target_en = en;186}187 188static void rsnd_adg_get_timesel_ratio(struct rsnd_priv *priv,189 struct rsnd_dai_stream *io,190 unsigned int in_rate,191 unsigned int out_rate,192 u32 *in, u32 *out, u32 *en)193{194 struct snd_pcm_runtime *runtime = rsnd_io_to_runtime(io);195 unsigned int target_rate;196 u32 *target_val;197 u32 _in;198 u32 _out;199 u32 _en;200 201 /* default = SSI WS */202 _in =203 _out = rsnd_adg_ssi_ws_timing_gen2(io);204 205 target_rate = 0;206 target_val = NULL;207 _en = 0;208 if (runtime->rate != in_rate) {209 target_rate = out_rate;210 target_val = &_out;211 } else if (runtime->rate != out_rate) {212 target_rate = in_rate;213 target_val = &_in;214 }215 216 if (target_rate)217 __rsnd_adg_get_timesel_ratio(priv, io,218 target_rate,219 target_val, &_en);220 221 if (in)222 *in = _in;223 if (out)224 *out = _out;225 if (en)226 *en = _en;227}228 229int rsnd_adg_set_cmd_timsel_gen2(struct rsnd_mod *cmd_mod,230 struct rsnd_dai_stream *io)231{232 struct rsnd_priv *priv = rsnd_mod_to_priv(cmd_mod);233 struct rsnd_adg *adg = rsnd_priv_to_adg(priv);234 struct rsnd_mod *adg_mod = rsnd_mod_get(adg);235 int id = rsnd_mod_id(cmd_mod);236 int shift = (id % 2) ? 16 : 0;237 u32 mask, val;238 239 rsnd_adg_get_timesel_ratio(priv, io,240 rsnd_src_get_in_rate(priv, io),241 rsnd_src_get_out_rate(priv, io),242 NULL, &val, NULL);243 244 val = val << shift;245 mask = 0x0f1f << shift;246 247 rsnd_mod_bset(adg_mod, CMDOUT_TIMSEL, mask, val);248 249 return 0;250}251 252int rsnd_adg_set_src_timesel_gen2(struct rsnd_mod *src_mod,253 struct rsnd_dai_stream *io,254 unsigned int in_rate,255 unsigned int out_rate)256{257 struct rsnd_priv *priv = rsnd_mod_to_priv(src_mod);258 struct rsnd_adg *adg = rsnd_priv_to_adg(priv);259 struct rsnd_mod *adg_mod = rsnd_mod_get(adg);260 u32 in, out;261 u32 mask, en;262 int id = rsnd_mod_id(src_mod);263 int shift = (id % 2) ? 16 : 0;264 265 rsnd_mod_make_sure(src_mod, RSND_MOD_SRC);266 267 rsnd_adg_get_timesel_ratio(priv, io,268 in_rate, out_rate,269 &in, &out, &en);270 271 in = in << shift;272 out = out << shift;273 mask = 0x0f1f << shift;274 275 rsnd_mod_bset(adg_mod, SRCIN_TIMSEL(id / 2), mask, in);276 rsnd_mod_bset(adg_mod, SRCOUT_TIMSEL(id / 2), mask, out);277 278 if (en)279 rsnd_mod_bset(adg_mod, DIV_EN, en, en);280 281 return 0;282}283 284static void rsnd_adg_set_ssi_clk(struct rsnd_mod *ssi_mod, u32 val)285{286 struct rsnd_priv *priv = rsnd_mod_to_priv(ssi_mod);287 struct rsnd_adg *adg = rsnd_priv_to_adg(priv);288 struct rsnd_mod *adg_mod = rsnd_mod_get(adg);289 struct device *dev = rsnd_priv_to_dev(priv);290 int id = rsnd_mod_id(ssi_mod);291 int shift = (id % 4) * 8;292 u32 mask = 0xFF << shift;293 294 rsnd_mod_make_sure(ssi_mod, RSND_MOD_SSI);295 296 val = val << shift;297 298 /*299 * SSI 8 is not connected to ADG.300 * it works with SSI 7301 */302 if (id == 8)303 return;304 305 rsnd_mod_bset(adg_mod, AUDIO_CLK_SEL(id / 4), mask, val);306 307 dev_dbg(dev, "AUDIO_CLK_SEL is 0x%x\n", val);308}309 310int rsnd_adg_clk_query(struct rsnd_priv *priv, unsigned int rate)311{312 struct rsnd_adg *adg = rsnd_priv_to_adg(priv);313 struct clk *clk;314 int i;315 int sel_table[] = {316 [CLKA] = 0x1,317 [CLKB] = 0x2,318 [CLKC] = 0x3,319 [CLKI] = 0x0,320 };321 322 /*323 * find suitable clock from324 * AUDIO_CLKA/AUDIO_CLKB/AUDIO_CLKC/AUDIO_CLKI.325 */326 for_each_rsnd_clkin(clk, adg, i)327 if (rate == adg->clkin_rate[i])328 return sel_table[i];329 330 /*331 * find divided clock from BRGA/BRGB332 */333 if (rate == adg->brg_rate[ADG_HZ_441])334 return 0x10;335 336 if (rate == adg->brg_rate[ADG_HZ_48])337 return 0x20;338 339 return -EIO;340}341 342int rsnd_adg_ssi_clk_stop(struct rsnd_mod *ssi_mod)343{344 rsnd_adg_set_ssi_clk(ssi_mod, 0);345 346 return 0;347}348 349int rsnd_adg_ssi_clk_try_start(struct rsnd_mod *ssi_mod, unsigned int rate)350{351 struct rsnd_priv *priv = rsnd_mod_to_priv(ssi_mod);352 struct rsnd_adg *adg = rsnd_priv_to_adg(priv);353 struct device *dev = rsnd_priv_to_dev(priv);354 struct rsnd_mod *adg_mod = rsnd_mod_get(adg);355 int data;356 u32 ckr = 0;357 358 data = rsnd_adg_clk_query(priv, rate);359 if (data < 0)360 return data;361 362 rsnd_adg_set_ssi_clk(ssi_mod, data);363 364 if (0 == (rate % 8000))365 ckr = 0x80000000; /* BRGB output = 48kHz */366 367 rsnd_mod_bset(adg_mod, BRGCKR, 0x80770000, adg->ckr | ckr);368 369 dev_dbg(dev, "CLKOUT is based on BRG%c (= %dHz)\n",370 (ckr) ? 'B' : 'A',371 (ckr) ? adg->brg_rate[ADG_HZ_48] :372 adg->brg_rate[ADG_HZ_441]);373 374 return 0;375}376 377void rsnd_adg_clk_control(struct rsnd_priv *priv, int enable)378{379 struct rsnd_adg *adg = rsnd_priv_to_adg(priv);380 struct rsnd_mod *adg_mod = rsnd_mod_get(adg);381 struct clk *clk;382 int i;383 384 if (enable) {385 rsnd_mod_bset(adg_mod, BRGCKR, 0x80770000, adg->ckr);386 rsnd_mod_write(adg_mod, BRRA, adg->brga);387 rsnd_mod_write(adg_mod, BRRB, adg->brgb);388 }389 390 for_each_rsnd_clkin(clk, adg, i) {391 if (enable) {392 clk_prepare_enable(clk);393 394 /*395 * We shouldn't use clk_get_rate() under396 * atomic context. Let's keep it when397 * rsnd_adg_clk_enable() was called398 */399 adg->clkin_rate[i] = clk_get_rate(clk);400 } else {401 clk_disable_unprepare(clk);402 }403 }404}405 406static struct clk *rsnd_adg_create_null_clk(struct rsnd_priv *priv,407 const char * const name,408 const char *parent)409{410 struct device *dev = rsnd_priv_to_dev(priv);411 struct clk *clk;412 413 clk = clk_register_fixed_rate(dev, name, parent, 0, 0);414 if (IS_ERR_OR_NULL(clk)) {415 dev_err(dev, "create null clk error\n");416 return ERR_CAST(clk);417 }418 419 return clk;420}421 422static struct clk *rsnd_adg_null_clk_get(struct rsnd_priv *priv)423{424 struct rsnd_adg *adg = priv->adg;425 426 if (!adg->null_clk) {427 static const char * const name = "rsnd_adg_null";428 429 adg->null_clk = rsnd_adg_create_null_clk(priv, name, NULL);430 }431 432 return adg->null_clk;433}434 435static void rsnd_adg_null_clk_clean(struct rsnd_priv *priv)436{437 struct rsnd_adg *adg = priv->adg;438 439 if (adg->null_clk)440 clk_unregister_fixed_rate(adg->null_clk);441}442 443static int rsnd_adg_get_clkin(struct rsnd_priv *priv)444{445 struct rsnd_adg *adg = priv->adg;446 struct device *dev = rsnd_priv_to_dev(priv);447 struct clk *clk;448 const char * const *clkin_name;449 int clkin_size;450 int i;451 452 clkin_name = clkin_name_gen2;453 clkin_size = ARRAY_SIZE(clkin_name_gen2);454 if (rsnd_is_gen4(priv)) {455 clkin_name = clkin_name_gen4;456 clkin_size = ARRAY_SIZE(clkin_name_gen4);457 }458 459 for (i = 0; i < clkin_size; i++) {460 clk = devm_clk_get(dev, clkin_name[i]);461 462 if (IS_ERR_OR_NULL(clk))463 clk = rsnd_adg_null_clk_get(priv);464 if (IS_ERR_OR_NULL(clk))465 goto err;466 467 adg->clkin[i] = clk;468 }469 470 adg->clkin_size = clkin_size;471 472 return 0;473 474err:475 dev_err(dev, "adg clock IN get failed\n");476 477 rsnd_adg_null_clk_clean(priv);478 479 return -EIO;480}481 482static void rsnd_adg_unregister_clkout(struct rsnd_priv *priv)483{484 struct rsnd_adg *adg = priv->adg;485 struct clk *clk;486 int i;487 488 for_each_rsnd_clkout(clk, adg, i)489 clk_unregister_fixed_rate(clk);490}491 492static int rsnd_adg_get_clkout(struct rsnd_priv *priv)493{494 struct rsnd_adg *adg = priv->adg;495 struct clk *clk;496 struct device *dev = rsnd_priv_to_dev(priv);497 struct device_node *np = dev->of_node;498 struct property *prop;499 u32 ckr, brgx, brga, brgb;500 u32 req_rate[ADG_HZ_SIZE] = {};501 uint32_t count = 0;502 unsigned long req_Hz[ADG_HZ_SIZE];503 int clkout_size;504 int i, req_size;505 int approximate = 0;506 const char *parent_clk_name = NULL;507 const char * const *clkout_name;508 int brg_table[] = {509 [CLKA] = 0x0,510 [CLKB] = 0x1,511 [CLKC] = 0x4,512 [CLKI] = 0x2,513 };514 515 ckr = 0;516 brga = 0xff; /* default */517 brgb = 0xff; /* default */518 519 /*520 * ADG supports BRRA/BRRB output only521 * this means all clkout0/1/2/3 will be same rate522 */523 prop = of_find_property(np, "clock-frequency", NULL);524 if (!prop)525 goto rsnd_adg_get_clkout_end;526 527 req_size = prop->length / sizeof(u32);528 if (req_size > ADG_HZ_SIZE) {529 dev_err(dev, "too many clock-frequency\n");530 return -EINVAL;531 }532 533 of_property_read_u32_array(np, "clock-frequency", req_rate, req_size);534 req_Hz[ADG_HZ_48] = 0;535 req_Hz[ADG_HZ_441] = 0;536 for (i = 0; i < req_size; i++) {537 if (0 == (req_rate[i] % 44100))538 req_Hz[ADG_HZ_441] = req_rate[i];539 if (0 == (req_rate[i] % 48000))540 req_Hz[ADG_HZ_48] = req_rate[i];541 }542 543 /*544 * This driver is assuming that AUDIO_CLKA/AUDIO_CLKB/AUDIO_CLKC545 * have 44.1kHz or 48kHz base clocks for now.546 *547 * SSI itself can divide parent clock by 1/1 - 1/16548 * see549 * rsnd_adg_ssi_clk_try_start()550 * rsnd_ssi_master_clk_start()551 */552 553 /*554 * [APPROXIMATE]555 *556 * clk_i (internal clock) can't create accurate rate, it will be approximate rate.557 *558 * <Note>559 *560 * clk_i needs x2 of required maximum rate.561 * see562 * - Minimum division of BRRA/BRRB563 * - rsnd_ssi_clk_query()564 *565 * Sample Settings for TDM 8ch, 32bit width566 *567 * 8(ch) x 32(bit) x 44100(Hz) x 2<Note> = 22579200568 * 8(ch) x 32(bit) x 48000(Hz) x 2<Note> = 24576000569 *570 * clock-frequency = <22579200 24576000>;571 */572 for_each_rsnd_clkin(clk, adg, i) {573 u32 rate, div;574 575 rate = clk_get_rate(clk);576 577 if (0 == rate) /* not used */578 continue;579 580 /* BRGA */581 582 if (i == CLKI)583 /* see [APPROXIMATE] */584 rate = (clk_get_rate(clk) / req_Hz[ADG_HZ_441]) * req_Hz[ADG_HZ_441];585 if (!adg->brg_rate[ADG_HZ_441] && req_Hz[ADG_HZ_441] && (0 == rate % 44100)) {586 div = rate / req_Hz[ADG_HZ_441];587 brgx = rsnd_adg_calculate_brgx(div);588 if (BRRx_MASK(brgx) == brgx) {589 brga = brgx;590 adg->brg_rate[ADG_HZ_441] = rate / div;591 ckr |= brg_table[i] << 20;592 if (req_Hz[ADG_HZ_441])593 parent_clk_name = __clk_get_name(clk);594 if (i == CLKI)595 approximate = 1;596 }597 }598 599 /* BRGB */600 601 if (i == CLKI)602 /* see [APPROXIMATE] */603 rate = (clk_get_rate(clk) / req_Hz[ADG_HZ_48]) * req_Hz[ADG_HZ_48];604 if (!adg->brg_rate[ADG_HZ_48] && req_Hz[ADG_HZ_48] && (0 == rate % 48000)) {605 div = rate / req_Hz[ADG_HZ_48];606 brgx = rsnd_adg_calculate_brgx(div);607 if (BRRx_MASK(brgx) == brgx) {608 brgb = brgx;609 adg->brg_rate[ADG_HZ_48] = rate / div;610 ckr |= brg_table[i] << 16;611 if (req_Hz[ADG_HZ_48])612 parent_clk_name = __clk_get_name(clk);613 if (i == CLKI)614 approximate = 1;615 }616 }617 }618 619 if (!(adg->brg_rate[ADG_HZ_48] && req_Hz[ADG_HZ_48]) &&620 !(adg->brg_rate[ADG_HZ_441] && req_Hz[ADG_HZ_441]))621 goto rsnd_adg_get_clkout_end;622 623 if (approximate)624 dev_info(dev, "It uses CLK_I as approximate rate");625 626 clkout_name = clkout_name_gen2;627 clkout_size = ARRAY_SIZE(clkout_name_gen2);628 if (rsnd_is_gen4(priv))629 clkout_size = 1; /* reuse clkout_name_gen2[] */630 631 /*632 * ADG supports BRRA/BRRB output only.633 * this means all clkout0/1/2/3 will be * same rate634 */635 636 of_property_read_u32(np, "#clock-cells", &count);637 /*638 * for clkout639 */640 if (!count) {641 clk = clk_register_fixed_rate(dev, clkout_name[CLKOUT],642 parent_clk_name, 0, req_rate[0]);643 if (IS_ERR_OR_NULL(clk))644 goto err;645 646 adg->clkout[CLKOUT] = clk;647 adg->clkout_size = 1;648 of_clk_add_provider(np, of_clk_src_simple_get, clk);649 }650 /*651 * for clkout0/1/2/3652 */653 else {654 for (i = 0; i < clkout_size; i++) {655 clk = clk_register_fixed_rate(dev, clkout_name[i],656 parent_clk_name, 0,657 req_rate[0]);658 if (IS_ERR_OR_NULL(clk))659 goto err;660 661 adg->clkout[i] = clk;662 }663 adg->onecell.clks = adg->clkout;664 adg->onecell.clk_num = clkout_size;665 adg->clkout_size = clkout_size;666 of_clk_add_provider(np, of_clk_src_onecell_get,667 &adg->onecell);668 }669 670rsnd_adg_get_clkout_end:671 adg->ckr = ckr;672 adg->brga = brga;673 adg->brgb = brgb;674 675 return 0;676 677err:678 dev_err(dev, "adg clock OUT get failed\n");679 680 rsnd_adg_unregister_clkout(priv);681 682 return -EIO;683}684 685#if defined(DEBUG) || defined(CONFIG_DEBUG_FS)686__printf(3, 4)687static void dbg_msg(struct device *dev, struct seq_file *m,688 const char *fmt, ...)689{690 char msg[128];691 va_list args;692 693 va_start(args, fmt);694 vsnprintf(msg, sizeof(msg), fmt, args);695 va_end(args);696 697 if (m)698 seq_puts(m, msg);699 else700 dev_dbg(dev, "%s", msg);701}702 703void rsnd_adg_clk_dbg_info(struct rsnd_priv *priv, struct seq_file *m)704{705 struct rsnd_adg *adg = rsnd_priv_to_adg(priv);706 struct device *dev = rsnd_priv_to_dev(priv);707 struct clk *clk;708 int i;709 710 for_each_rsnd_clkin(clk, adg, i)711 dbg_msg(dev, m, "%-18s : %pa : %ld\n",712 __clk_get_name(clk), clk, clk_get_rate(clk));713 714 dbg_msg(dev, m, "BRGCKR = 0x%08x, BRRA/BRRB = 0x%x/0x%x\n",715 adg->ckr, adg->brga, adg->brgb);716 dbg_msg(dev, m, "BRGA (for 44100 base) = %d\n", adg->brg_rate[ADG_HZ_441]);717 dbg_msg(dev, m, "BRGB (for 48000 base) = %d\n", adg->brg_rate[ADG_HZ_48]);718 719 /*720 * Actual CLKOUT will be exchanged in rsnd_adg_ssi_clk_try_start()721 * by BRGCKR::BRGCKR_31722 */723 for_each_rsnd_clkout(clk, adg, i)724 dbg_msg(dev, m, "%-18s : %pa : %ld\n",725 __clk_get_name(clk), clk, clk_get_rate(clk));726}727#else728#define rsnd_adg_clk_dbg_info(priv, m)729#endif730 731int rsnd_adg_probe(struct rsnd_priv *priv)732{733 struct rsnd_adg *adg;734 struct device *dev = rsnd_priv_to_dev(priv);735 int ret;736 737 adg = devm_kzalloc(dev, sizeof(*adg), GFP_KERNEL);738 if (!adg)739 return -ENOMEM;740 741 ret = rsnd_mod_init(priv, &adg->mod, &adg_ops,742 NULL, 0, 0);743 if (ret)744 return ret;745 746 priv->adg = adg;747 748 ret = rsnd_adg_get_clkin(priv);749 if (ret)750 return ret;751 752 ret = rsnd_adg_get_clkout(priv);753 if (ret)754 return ret;755 756 rsnd_adg_clk_enable(priv);757 rsnd_adg_clk_dbg_info(priv, NULL);758 759 return 0;760}761 762void rsnd_adg_remove(struct rsnd_priv *priv)763{764 struct device *dev = rsnd_priv_to_dev(priv);765 struct device_node *np = dev->of_node;766 767 rsnd_adg_unregister_clkout(priv);768 769 of_clk_del_provider(np);770 771 rsnd_adg_clk_disable(priv);772 773 /* It should be called after rsnd_adg_clk_disable() */774 rsnd_adg_null_clk_clean(priv);775}776