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