1 // SPDX-License-Identifier: GPL-2.0 2 // 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 0 11 #define CLKB 1 12 #define CLKC 2 13 #define CLKI 3 14 #define CLKINMAX 4 15 16 #define CLKOUT 0 17 #define CLKOUT1 1 18 #define CLKOUT2 2 19 #define CLKOUT3 3 20 #define CLKOUTMAX 4 21 22 #define BRRx_MASK(x) (0x3FF & x) 23 24 static struct rsnd_mod_ops adg_ops = { 25 .name = "adg", 26 }; 27 28 #define ADG_HZ_441 0 29 #define ADG_HZ_48 1 30 #define ADG_HZ_SIZE 2 31 32 struct 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 60 static const char * const clkin_name_gen4[] = { 61 [CLKA] = "clkin", 62 }; 63 64 static const char * const clkin_name_gen2[] = { 65 [CLKA] = "clk_a", 66 [CLKB] = "clk_b", 67 [CLKC] = "clk_c", 68 [CLKI] = "clk_i", 69 }; 70 71 static const char * const clkout_name_gen2[] = { 72 [CLKOUT] = "audio_clkout", 73 [CLKOUT1] = "audio_clkout1", 74 [CLKOUT2] = "audio_clkout2", 75 [CLKOUT3] = "audio_clkout3", 76 }; 77 78 static 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 94 static 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 = 8 118 */ 119 if (id == 9) 120 ws = 8; 121 } 122 123 return (0x6 + ws) << 8; 124 } 125 126 static 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_1101 166 * are out of order 167 */ 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 188 static 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 229 int 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 252 int 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_confirm_src(src_mod); 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 284 static 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_confirm_ssi(ssi_mod); 295 296 val = val << shift; 297 298 /* 299 * SSI 8 is not connected to ADG. 300 * it works with SSI 7 301 */ 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 310 int 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 from 324 * 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/BRGB 332 */ 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 342 int 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 349 int 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 377 void 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() under 396 * atomic context. Let's keep it when 397 * rsnd_adg_clk_enable() was called 398 */ 399 adg->clkin_rate[i] = clk_get_rate(clk); 400 } else { 401 clk_disable_unprepare(clk); 402 } 403 } 404 } 405 406 static 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 422 static 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 435 static 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 443 static 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 474 err: 475 dev_err(dev, "adg clock IN get failed\n"); 476 477 rsnd_adg_null_clk_clean(priv); 478 479 return -EIO; 480 } 481 482 static 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 492 static 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 only 521 * this means all clkout0/1/2/3 will be same rate 522 */ 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_CLKC 545 * have 44.1kHz or 48kHz base clocks for now. 546 * 547 * SSI itself can divide parent clock by 1/1 - 1/16 548 * see 549 * 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 * see 562 * - Minimum division of BRRA/BRRB 563 * - rsnd_ssi_clk_query() 564 * 565 * Sample Settings for TDM 8ch, 32bit width 566 * 567 * 8(ch) x 32(bit) x 44100(Hz) x 2<Note> = 22579200 568 * 8(ch) x 32(bit) x 48000(Hz) x 2<Note> = 24576000 569 * 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 rate 634 */ 635 636 of_property_read_u32(np, "#clock-cells", &count); 637 /* 638 * for clkout 639 */ 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/3 652 */ 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 670 rsnd_adg_get_clkout_end: 671 adg->ckr = ckr; 672 adg->brga = brga; 673 adg->brgb = brgb; 674 675 return 0; 676 677 err: 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) 687 static 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 else 700 dev_dbg(dev, "%s", msg); 701 } 702 703 void 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_31 722 */ 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 #else 728 #define rsnd_adg_clk_dbg_info(priv, m) 729 #endif 730 731 int 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 762 void 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
Linux® is a registered trademark of Linus Torvalds in the United States and other countries.
TOMOYO® is a registered trademark of NTT DATA CORPORATION.