linux/sound/soc/sh/rcar/dvc.c
<<
>>
Prefs
   1// SPDX-License-Identifier: GPL-2.0
   2//
   3// Renesas R-Car DVC support
   4//
   5// Copyright (C) 2014 Renesas Solutions Corp.
   6// Kuninori Morimoto <kuninori.morimoto.gx@renesas.com>
   7
   8/*
   9 * Playback Volume
  10 *      amixer set "DVC Out" 100%
  11 *
  12 * Capture Volume
  13 *      amixer set "DVC In" 100%
  14 *
  15 * Playback Mute
  16 *      amixer set "DVC Out Mute" on
  17 *
  18 * Capture Mute
  19 *      amixer set "DVC In Mute" on
  20 *
  21 * Volume Ramp
  22 *      amixer set "DVC Out Ramp Up Rate"   "0.125 dB/64 steps"
  23 *      amixer set "DVC Out Ramp Down Rate" "0.125 dB/512 steps"
  24 *      amixer set "DVC Out Ramp" on
  25 *      aplay xxx.wav &
  26 *      amixer set "DVC Out"  80%  // Volume Down
  27 *      amixer set "DVC Out" 100%  // Volume Up
  28 */
  29
  30#include "rsnd.h"
  31
  32#define RSND_DVC_NAME_SIZE      16
  33
  34#define DVC_NAME "dvc"
  35
  36struct rsnd_dvc {
  37        struct rsnd_mod mod;
  38        struct rsnd_kctrl_cfg_m volume;
  39        struct rsnd_kctrl_cfg_m mute;
  40        struct rsnd_kctrl_cfg_s ren;    /* Ramp Enable */
  41        struct rsnd_kctrl_cfg_s rup;    /* Ramp Rate Up */
  42        struct rsnd_kctrl_cfg_s rdown;  /* Ramp Rate Down */
  43        u32 flags;
  44};
  45
  46#define KCTRL_INITIALIZED       (1 << 0)
  47
  48#define rsnd_dvc_get(priv, id) ((struct rsnd_dvc *)(priv->dvc) + id)
  49#define rsnd_dvc_nr(priv) ((priv)->dvc_nr)
  50
  51#define rsnd_mod_to_dvc(_mod)   \
  52        container_of((_mod), struct rsnd_dvc, mod)
  53
  54#define for_each_rsnd_dvc(pos, priv, i)                         \
  55        for ((i) = 0;                                           \
  56             ((i) < rsnd_dvc_nr(priv)) &&                       \
  57             ((pos) = (struct rsnd_dvc *)(priv)->dvc + i);      \
  58             i++)
  59
  60static void rsnd_dvc_activation(struct rsnd_mod *mod)
  61{
  62        rsnd_mod_write(mod, DVC_SWRSR, 0);
  63        rsnd_mod_write(mod, DVC_SWRSR, 1);
  64}
  65
  66static void rsnd_dvc_halt(struct rsnd_mod *mod)
  67{
  68        rsnd_mod_write(mod, DVC_DVUIR, 1);
  69        rsnd_mod_write(mod, DVC_SWRSR, 0);
  70}
  71
  72#define rsnd_dvc_get_vrpdr(dvc) (rsnd_kctrl_vals(dvc->rup) << 8 | \
  73                                 rsnd_kctrl_vals(dvc->rdown))
  74#define rsnd_dvc_get_vrdbr(dvc) (0x3ff - (rsnd_kctrl_valm(dvc->volume, 0) >> 13))
  75
  76static void rsnd_dvc_volume_parameter(struct rsnd_dai_stream *io,
  77                                              struct rsnd_mod *mod)
  78{
  79        struct rsnd_dvc *dvc = rsnd_mod_to_dvc(mod);
  80        u32 val[RSND_MAX_CHANNELS];
  81        int i;
  82
  83        /* Enable Ramp */
  84        if (rsnd_kctrl_vals(dvc->ren))
  85                for (i = 0; i < RSND_MAX_CHANNELS; i++)
  86                        val[i] = rsnd_kctrl_max(dvc->volume);
  87        else
  88                for (i = 0; i < RSND_MAX_CHANNELS; i++)
  89                        val[i] = rsnd_kctrl_valm(dvc->volume, i);
  90
  91        /* Enable Digital Volume */
  92        rsnd_mod_write(mod, DVC_VOL0R, val[0]);
  93        rsnd_mod_write(mod, DVC_VOL1R, val[1]);
  94        rsnd_mod_write(mod, DVC_VOL2R, val[2]);
  95        rsnd_mod_write(mod, DVC_VOL3R, val[3]);
  96        rsnd_mod_write(mod, DVC_VOL4R, val[4]);
  97        rsnd_mod_write(mod, DVC_VOL5R, val[5]);
  98        rsnd_mod_write(mod, DVC_VOL6R, val[6]);
  99        rsnd_mod_write(mod, DVC_VOL7R, val[7]);
 100}
 101
 102static void rsnd_dvc_volume_init(struct rsnd_dai_stream *io,
 103                                 struct rsnd_mod *mod)
 104{
 105        struct rsnd_dvc *dvc = rsnd_mod_to_dvc(mod);
 106        u32 adinr = 0;
 107        u32 dvucr = 0;
 108        u32 vrctr = 0;
 109        u32 vrpdr = 0;
 110        u32 vrdbr = 0;
 111
 112        adinr = rsnd_get_adinr_bit(mod, io) |
 113                rsnd_runtime_channel_after_ctu(io);
 114
 115        /* Enable Digital Volume, Zero Cross Mute Mode */
 116        dvucr |= 0x101;
 117
 118        /* Enable Ramp */
 119        if (rsnd_kctrl_vals(dvc->ren)) {
 120                dvucr |= 0x10;
 121
 122                /*
 123                 * FIXME !!
 124                 * use scale-downed Digital Volume
 125                 * as Volume Ramp
 126                 * 7F FFFF -> 3FF
 127                 */
 128                vrctr = 0xff;
 129                vrpdr = rsnd_dvc_get_vrpdr(dvc);
 130                vrdbr = rsnd_dvc_get_vrdbr(dvc);
 131        }
 132
 133        /* Initialize operation */
 134        rsnd_mod_write(mod, DVC_DVUIR, 1);
 135
 136        /* General Information */
 137        rsnd_mod_write(mod, DVC_ADINR, adinr);
 138        rsnd_mod_write(mod, DVC_DVUCR, dvucr);
 139
 140        /* Volume Ramp Parameter */
 141        rsnd_mod_write(mod, DVC_VRCTR, vrctr);
 142        rsnd_mod_write(mod, DVC_VRPDR, vrpdr);
 143        rsnd_mod_write(mod, DVC_VRDBR, vrdbr);
 144
 145        /* Digital Volume Function Parameter */
 146        rsnd_dvc_volume_parameter(io, mod);
 147
 148        /* cancel operation */
 149        rsnd_mod_write(mod, DVC_DVUIR, 0);
 150}
 151
 152static void rsnd_dvc_volume_update(struct rsnd_dai_stream *io,
 153                                   struct rsnd_mod *mod)
 154{
 155        struct rsnd_dvc *dvc = rsnd_mod_to_dvc(mod);
 156        u32 zcmcr = 0;
 157        u32 vrpdr = 0;
 158        u32 vrdbr = 0;
 159        int i;
 160
 161        for (i = 0; i < rsnd_kctrl_size(dvc->mute); i++)
 162                zcmcr |= (!!rsnd_kctrl_valm(dvc->mute, i)) << i;
 163
 164        if (rsnd_kctrl_vals(dvc->ren)) {
 165                vrpdr = rsnd_dvc_get_vrpdr(dvc);
 166                vrdbr = rsnd_dvc_get_vrdbr(dvc);
 167        }
 168
 169        /* Disable DVC Register access */
 170        rsnd_mod_write(mod, DVC_DVUER, 0);
 171
 172        /* Zero Cross Mute Function */
 173        rsnd_mod_write(mod, DVC_ZCMCR, zcmcr);
 174
 175        /* Volume Ramp Function */
 176        rsnd_mod_write(mod, DVC_VRPDR, vrpdr);
 177        rsnd_mod_write(mod, DVC_VRDBR, vrdbr);
 178        /* add DVC_VRWTR here */
 179
 180        /* Digital Volume Function Parameter */
 181        rsnd_dvc_volume_parameter(io, mod);
 182
 183        /* Enable DVC Register access */
 184        rsnd_mod_write(mod, DVC_DVUER, 1);
 185}
 186
 187static int rsnd_dvc_probe_(struct rsnd_mod *mod,
 188                           struct rsnd_dai_stream *io,
 189                           struct rsnd_priv *priv)
 190{
 191        return rsnd_cmd_attach(io, rsnd_mod_id(mod));
 192}
 193
 194static int rsnd_dvc_init(struct rsnd_mod *mod,
 195                         struct rsnd_dai_stream *io,
 196                         struct rsnd_priv *priv)
 197{
 198        rsnd_mod_power_on(mod);
 199
 200        rsnd_dvc_activation(mod);
 201
 202        rsnd_dvc_volume_init(io, mod);
 203
 204        rsnd_dvc_volume_update(io, mod);
 205
 206        return 0;
 207}
 208
 209static int rsnd_dvc_quit(struct rsnd_mod *mod,
 210                         struct rsnd_dai_stream *io,
 211                         struct rsnd_priv *priv)
 212{
 213        rsnd_dvc_halt(mod);
 214
 215        rsnd_mod_power_off(mod);
 216
 217        return 0;
 218}
 219
 220static int rsnd_dvc_pcm_new(struct rsnd_mod *mod,
 221                            struct rsnd_dai_stream *io,
 222                            struct snd_soc_pcm_runtime *rtd)
 223{
 224        struct rsnd_dvc *dvc = rsnd_mod_to_dvc(mod);
 225        struct rsnd_dai *rdai = rsnd_io_to_rdai(io);
 226        int is_play = rsnd_io_is_play(io);
 227        int channels = rsnd_rdai_channels_get(rdai);
 228        int ret;
 229
 230        if (rsnd_flags_has(dvc, KCTRL_INITIALIZED))
 231                return 0;
 232
 233        /* Volume */
 234        ret = rsnd_kctrl_new_m(mod, io, rtd,
 235                        is_play ?
 236                        "DVC Out Playback Volume" : "DVC In Capture Volume",
 237                        rsnd_kctrl_accept_anytime,
 238                        rsnd_dvc_volume_update,
 239                        &dvc->volume, channels,
 240                        0x00800000 - 1);
 241        if (ret < 0)
 242                return ret;
 243
 244        /* Mute */
 245        ret = rsnd_kctrl_new_m(mod, io, rtd,
 246                        is_play ?
 247                        "DVC Out Mute Switch" : "DVC In Mute Switch",
 248                        rsnd_kctrl_accept_anytime,
 249                        rsnd_dvc_volume_update,
 250                        &dvc->mute, channels,
 251                        1);
 252        if (ret < 0)
 253                return ret;
 254
 255        /* Ramp */
 256        ret = rsnd_kctrl_new_s(mod, io, rtd,
 257                        is_play ?
 258                        "DVC Out Ramp Switch" : "DVC In Ramp Switch",
 259                        rsnd_kctrl_accept_anytime,
 260                        rsnd_dvc_volume_update,
 261                        &dvc->ren, 1);
 262        if (ret < 0)
 263                return ret;
 264
 265        ret = rsnd_kctrl_new_e(mod, io, rtd,
 266                        is_play ?
 267                        "DVC Out Ramp Up Rate" : "DVC In Ramp Up Rate",
 268                        rsnd_kctrl_accept_anytime,
 269                        rsnd_dvc_volume_update,
 270                        &dvc->rup,
 271                        volume_ramp_rate,
 272                        VOLUME_RAMP_MAX_DVC);
 273        if (ret < 0)
 274                return ret;
 275
 276        ret = rsnd_kctrl_new_e(mod, io, rtd,
 277                        is_play ?
 278                        "DVC Out Ramp Down Rate" : "DVC In Ramp Down Rate",
 279                        rsnd_kctrl_accept_anytime,
 280                        rsnd_dvc_volume_update,
 281                        &dvc->rdown,
 282                        volume_ramp_rate,
 283                        VOLUME_RAMP_MAX_DVC);
 284
 285        if (ret < 0)
 286                return ret;
 287
 288        rsnd_flags_set(dvc, KCTRL_INITIALIZED);
 289
 290        return 0;
 291}
 292
 293static struct dma_chan *rsnd_dvc_dma_req(struct rsnd_dai_stream *io,
 294                                         struct rsnd_mod *mod)
 295{
 296        struct rsnd_priv *priv = rsnd_mod_to_priv(mod);
 297
 298        return rsnd_dma_request_channel(rsnd_dvc_of_node(priv),
 299                                        mod, "tx");
 300}
 301
 302static struct rsnd_mod_ops rsnd_dvc_ops = {
 303        .name           = DVC_NAME,
 304        .dma_req        = rsnd_dvc_dma_req,
 305        .probe          = rsnd_dvc_probe_,
 306        .init           = rsnd_dvc_init,
 307        .quit           = rsnd_dvc_quit,
 308        .pcm_new        = rsnd_dvc_pcm_new,
 309};
 310
 311struct rsnd_mod *rsnd_dvc_mod_get(struct rsnd_priv *priv, int id)
 312{
 313        if (WARN_ON(id < 0 || id >= rsnd_dvc_nr(priv)))
 314                id = 0;
 315
 316        return rsnd_mod_get(rsnd_dvc_get(priv, id));
 317}
 318
 319int rsnd_dvc_probe(struct rsnd_priv *priv)
 320{
 321        struct device_node *node;
 322        struct device_node *np;
 323        struct device *dev = rsnd_priv_to_dev(priv);
 324        struct rsnd_dvc *dvc;
 325        struct clk *clk;
 326        char name[RSND_DVC_NAME_SIZE];
 327        int i, nr, ret;
 328
 329        /* This driver doesn't support Gen1 at this point */
 330        if (rsnd_is_gen1(priv))
 331                return 0;
 332
 333        node = rsnd_dvc_of_node(priv);
 334        if (!node)
 335                return 0; /* not used is not error */
 336
 337        nr = of_get_child_count(node);
 338        if (!nr) {
 339                ret = -EINVAL;
 340                goto rsnd_dvc_probe_done;
 341        }
 342
 343        dvc     = devm_kcalloc(dev, nr, sizeof(*dvc), GFP_KERNEL);
 344        if (!dvc) {
 345                ret = -ENOMEM;
 346                goto rsnd_dvc_probe_done;
 347        }
 348
 349        priv->dvc_nr    = nr;
 350        priv->dvc       = dvc;
 351
 352        i = 0;
 353        ret = 0;
 354        for_each_child_of_node(node, np) {
 355                dvc = rsnd_dvc_get(priv, i);
 356
 357                snprintf(name, RSND_DVC_NAME_SIZE, "%s.%d",
 358                         DVC_NAME, i);
 359
 360                clk = devm_clk_get(dev, name);
 361                if (IS_ERR(clk)) {
 362                        ret = PTR_ERR(clk);
 363                        of_node_put(np);
 364                        goto rsnd_dvc_probe_done;
 365                }
 366
 367                ret = rsnd_mod_init(priv, rsnd_mod_get(dvc), &rsnd_dvc_ops,
 368                                    clk, rsnd_mod_get_status, RSND_MOD_DVC, i);
 369                if (ret) {
 370                        of_node_put(np);
 371                        goto rsnd_dvc_probe_done;
 372                }
 373
 374                i++;
 375        }
 376
 377rsnd_dvc_probe_done:
 378        of_node_put(node);
 379
 380        return ret;
 381}
 382
 383void rsnd_dvc_remove(struct rsnd_priv *priv)
 384{
 385        struct rsnd_dvc *dvc;
 386        int i;
 387
 388        for_each_rsnd_dvc(dvc, priv, i) {
 389                rsnd_mod_quit(rsnd_mod_get(dvc));
 390        }
 391}
 392