root/sound/soc/sh/rcar/ctu.c

/* [<][>][^][v][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. rsnd_ctu_activation
  2. rsnd_ctu_halt
  3. rsnd_ctu_probe_
  4. rsnd_ctu_value_init
  5. rsnd_ctu_value_reset
  6. rsnd_ctu_init
  7. rsnd_ctu_quit
  8. rsnd_ctu_pcm_new
  9. rsnd_ctu_id
  10. rsnd_ctu_id_sub
  11. rsnd_ctu_mod_get
  12. rsnd_ctu_probe
  13. rsnd_ctu_remove

   1 // SPDX-License-Identifier: GPL-2.0
   2 //
   3 // ctu.c
   4 //
   5 // Copyright (c) 2015 Kuninori Morimoto <kuninori.morimoto.gx@renesas.com>
   6 
   7 #include "rsnd.h"
   8 
   9 #define CTU_NAME_SIZE   16
  10 #define CTU_NAME "ctu"
  11 
  12 /*
  13  * User needs to setup CTU by amixer, and its settings are
  14  * based on below registers
  15  *
  16  * CTUn_CPMDR : amixser set "CTU Pass"
  17  * CTUn_SV0xR : amixser set "CTU SV0"
  18  * CTUn_SV1xR : amixser set "CTU SV1"
  19  * CTUn_SV2xR : amixser set "CTU SV2"
  20  * CTUn_SV3xR : amixser set "CTU SV3"
  21  *
  22  * [CTU Pass]
  23  * 0000: default
  24  * 0001: Connect input data of channel 0
  25  * 0010: Connect input data of channel 1
  26  * 0011: Connect input data of channel 2
  27  * 0100: Connect input data of channel 3
  28  * 0101: Connect input data of channel 4
  29  * 0110: Connect input data of channel 5
  30  * 0111: Connect input data of channel 6
  31  * 1000: Connect input data of channel 7
  32  * 1001: Connect calculated data by scale values of matrix row 0
  33  * 1010: Connect calculated data by scale values of matrix row 1
  34  * 1011: Connect calculated data by scale values of matrix row 2
  35  * 1100: Connect calculated data by scale values of matrix row 3
  36  *
  37  * [CTU SVx]
  38  * [Output0] = [SV00, SV01, SV02, SV03, SV04, SV05, SV06, SV07]
  39  * [Output1] = [SV10, SV11, SV12, SV13, SV14, SV15, SV16, SV17]
  40  * [Output2] = [SV20, SV21, SV22, SV23, SV24, SV25, SV26, SV27]
  41  * [Output3] = [SV30, SV31, SV32, SV33, SV34, SV35, SV36, SV37]
  42  * [Output4] = [ 0,   0,    0,    0,    0,    0,    0,    0   ]
  43  * [Output5] = [ 0,   0,    0,    0,    0,    0,    0,    0   ]
  44  * [Output6] = [ 0,   0,    0,    0,    0,    0,    0,    0   ]
  45  * [Output7] = [ 0,   0,    0,    0,    0,    0,    0,    0   ]
  46  *
  47  * [SVxx]
  48  * Plus                                 Minus
  49  * value        time            dB      value           time            dB
  50  * -----------------------------------------------------------------------
  51  * H'7F_FFFF    2               6       H'80_0000       2               6
  52  * ...
  53  * H'40_0000    1               0       H'C0_0000       1               0
  54  * ...
  55  * H'00_0001    2.38 x 10^-7    -132
  56  * H'00_0000    0               Mute    H'FF_FFFF       2.38 x 10^-7    -132
  57  *
  58  *
  59  * Ex) Input ch -> Output ch
  60  *      1ch     ->  0ch
  61  *      0ch     ->  1ch
  62  *
  63  *      amixer set "CTU Reset" on
  64  *      amixer set "CTU Pass" 9,10
  65  *      amixer set "CTU SV0" 0,4194304
  66  *      amixer set "CTU SV1" 4194304,0
  67  * or
  68  *      amixer set "CTU Reset" on
  69  *      amixer set "CTU Pass" 2,1
  70  */
  71 
  72 struct rsnd_ctu {
  73         struct rsnd_mod mod;
  74         struct rsnd_kctrl_cfg_m pass;
  75         struct rsnd_kctrl_cfg_m sv[4];
  76         struct rsnd_kctrl_cfg_s reset;
  77         int channels;
  78         u32 flags;
  79 };
  80 
  81 #define KCTRL_INITIALIZED       (1 << 0)
  82 
  83 #define rsnd_ctu_nr(priv) ((priv)->ctu_nr)
  84 #define for_each_rsnd_ctu(pos, priv, i)                                 \
  85         for ((i) = 0;                                                   \
  86              ((i) < rsnd_ctu_nr(priv)) &&                               \
  87                      ((pos) = (struct rsnd_ctu *)(priv)->ctu + i);      \
  88              i++)
  89 
  90 #define rsnd_mod_to_ctu(_mod)   \
  91         container_of((_mod), struct rsnd_ctu, mod)
  92 
  93 #define rsnd_ctu_get(priv, id) ((struct rsnd_ctu *)(priv->ctu) + id)
  94 
  95 static void rsnd_ctu_activation(struct rsnd_mod *mod)
  96 {
  97         rsnd_mod_write(mod, CTU_SWRSR, 0);
  98         rsnd_mod_write(mod, CTU_SWRSR, 1);
  99 }
 100 
 101 static void rsnd_ctu_halt(struct rsnd_mod *mod)
 102 {
 103         rsnd_mod_write(mod, CTU_CTUIR, 1);
 104         rsnd_mod_write(mod, CTU_SWRSR, 0);
 105 }
 106 
 107 static int rsnd_ctu_probe_(struct rsnd_mod *mod,
 108                            struct rsnd_dai_stream *io,
 109                            struct rsnd_priv *priv)
 110 {
 111         return rsnd_cmd_attach(io, rsnd_mod_id(mod));
 112 }
 113 
 114 static void rsnd_ctu_value_init(struct rsnd_dai_stream *io,
 115                                struct rsnd_mod *mod)
 116 {
 117         struct rsnd_ctu *ctu = rsnd_mod_to_ctu(mod);
 118         u32 cpmdr = 0;
 119         u32 scmdr = 0;
 120         int i, j;
 121 
 122         for (i = 0; i < RSND_MAX_CHANNELS; i++) {
 123                 u32 val = rsnd_kctrl_valm(ctu->pass, i);
 124 
 125                 cpmdr |= val << (28 - (i * 4));
 126 
 127                 if ((val > 0x8) && (scmdr < (val - 0x8)))
 128                         scmdr = val - 0x8;
 129         }
 130 
 131         rsnd_mod_write(mod, CTU_CTUIR, 1);
 132 
 133         rsnd_mod_write(mod, CTU_ADINR, rsnd_runtime_channel_original(io));
 134 
 135         rsnd_mod_write(mod, CTU_CPMDR, cpmdr);
 136 
 137         rsnd_mod_write(mod, CTU_SCMDR, scmdr);
 138 
 139         for (i = 0; i < 4; i++) {
 140 
 141                 if (i >= scmdr)
 142                         break;
 143 
 144                 for (j = 0; j < RSND_MAX_CHANNELS; j++)
 145                         rsnd_mod_write(mod, CTU_SVxxR(i, j), rsnd_kctrl_valm(ctu->sv[i], j));
 146         }
 147 
 148         rsnd_mod_write(mod, CTU_CTUIR, 0);
 149 }
 150 
 151 static void rsnd_ctu_value_reset(struct rsnd_dai_stream *io,
 152                                  struct rsnd_mod *mod)
 153 {
 154         struct rsnd_ctu *ctu = rsnd_mod_to_ctu(mod);
 155         int i;
 156 
 157         if (!rsnd_kctrl_vals(ctu->reset))
 158                 return;
 159 
 160         for (i = 0; i < RSND_MAX_CHANNELS; i++) {
 161                 rsnd_kctrl_valm(ctu->pass, i) = 0;
 162                 rsnd_kctrl_valm(ctu->sv[0],  i) = 0;
 163                 rsnd_kctrl_valm(ctu->sv[1],  i) = 0;
 164                 rsnd_kctrl_valm(ctu->sv[2],  i) = 0;
 165                 rsnd_kctrl_valm(ctu->sv[3],  i) = 0;
 166         }
 167         rsnd_kctrl_vals(ctu->reset) = 0;
 168 }
 169 
 170 static int rsnd_ctu_init(struct rsnd_mod *mod,
 171                          struct rsnd_dai_stream *io,
 172                          struct rsnd_priv *priv)
 173 {
 174         rsnd_mod_power_on(mod);
 175 
 176         rsnd_ctu_activation(mod);
 177 
 178         rsnd_ctu_value_init(io, mod);
 179 
 180         return 0;
 181 }
 182 
 183 static int rsnd_ctu_quit(struct rsnd_mod *mod,
 184                          struct rsnd_dai_stream *io,
 185                          struct rsnd_priv *priv)
 186 {
 187         rsnd_ctu_halt(mod);
 188 
 189         rsnd_mod_power_off(mod);
 190 
 191         return 0;
 192 }
 193 
 194 static int rsnd_ctu_pcm_new(struct rsnd_mod *mod,
 195                             struct rsnd_dai_stream *io,
 196                             struct snd_soc_pcm_runtime *rtd)
 197 {
 198         struct rsnd_ctu *ctu = rsnd_mod_to_ctu(mod);
 199         int ret;
 200 
 201         if (rsnd_flags_has(ctu, KCTRL_INITIALIZED))
 202                 return 0;
 203 
 204         /* CTU Pass */
 205         ret = rsnd_kctrl_new_m(mod, io, rtd, "CTU Pass",
 206                                rsnd_kctrl_accept_anytime,
 207                                NULL,
 208                                &ctu->pass, RSND_MAX_CHANNELS,
 209                                0xC);
 210 
 211         /* ROW0 */
 212         ret = rsnd_kctrl_new_m(mod, io, rtd, "CTU SV0",
 213                                rsnd_kctrl_accept_anytime,
 214                                NULL,
 215                                &ctu->sv[0], RSND_MAX_CHANNELS,
 216                                0x00FFFFFF);
 217         if (ret < 0)
 218                 return ret;
 219 
 220         /* ROW1 */
 221         ret = rsnd_kctrl_new_m(mod, io, rtd, "CTU SV1",
 222                                rsnd_kctrl_accept_anytime,
 223                                NULL,
 224                                &ctu->sv[1], RSND_MAX_CHANNELS,
 225                                0x00FFFFFF);
 226         if (ret < 0)
 227                 return ret;
 228 
 229         /* ROW2 */
 230         ret = rsnd_kctrl_new_m(mod, io, rtd, "CTU SV2",
 231                                rsnd_kctrl_accept_anytime,
 232                                NULL,
 233                                &ctu->sv[2], RSND_MAX_CHANNELS,
 234                                0x00FFFFFF);
 235         if (ret < 0)
 236                 return ret;
 237 
 238         /* ROW3 */
 239         ret = rsnd_kctrl_new_m(mod, io, rtd, "CTU SV3",
 240                                rsnd_kctrl_accept_anytime,
 241                                NULL,
 242                                &ctu->sv[3], RSND_MAX_CHANNELS,
 243                                0x00FFFFFF);
 244         if (ret < 0)
 245                 return ret;
 246 
 247         /* Reset */
 248         ret = rsnd_kctrl_new_s(mod, io, rtd, "CTU Reset",
 249                                rsnd_kctrl_accept_anytime,
 250                                rsnd_ctu_value_reset,
 251                                &ctu->reset, 1);
 252 
 253         rsnd_flags_set(ctu, KCTRL_INITIALIZED);
 254 
 255         return ret;
 256 }
 257 
 258 static int rsnd_ctu_id(struct rsnd_mod *mod)
 259 {
 260         /*
 261          * ctu00: -> 0, ctu01: -> 0, ctu02: -> 0, ctu03: -> 0
 262          * ctu10: -> 1, ctu11: -> 1, ctu12: -> 1, ctu13: -> 1
 263          */
 264         return mod->id / 4;
 265 }
 266 
 267 static int rsnd_ctu_id_sub(struct rsnd_mod *mod)
 268 {
 269         /*
 270          * ctu00: -> 0, ctu01: -> 1, ctu02: -> 2, ctu03: -> 3
 271          * ctu10: -> 0, ctu11: -> 1, ctu12: -> 2, ctu13: -> 3
 272          */
 273         return mod->id % 4;
 274 }
 275 
 276 static struct rsnd_mod_ops rsnd_ctu_ops = {
 277         .name           = CTU_NAME,
 278         .probe          = rsnd_ctu_probe_,
 279         .init           = rsnd_ctu_init,
 280         .quit           = rsnd_ctu_quit,
 281         .pcm_new        = rsnd_ctu_pcm_new,
 282         .get_status     = rsnd_mod_get_status,
 283         .id             = rsnd_ctu_id,
 284         .id_sub         = rsnd_ctu_id_sub,
 285         .id_cmd         = rsnd_mod_id_raw,
 286 };
 287 
 288 struct rsnd_mod *rsnd_ctu_mod_get(struct rsnd_priv *priv, int id)
 289 {
 290         if (WARN_ON(id < 0 || id >= rsnd_ctu_nr(priv)))
 291                 id = 0;
 292 
 293         return rsnd_mod_get(rsnd_ctu_get(priv, id));
 294 }
 295 
 296 int rsnd_ctu_probe(struct rsnd_priv *priv)
 297 {
 298         struct device_node *node;
 299         struct device_node *np;
 300         struct device *dev = rsnd_priv_to_dev(priv);
 301         struct rsnd_ctu *ctu;
 302         struct clk *clk;
 303         char name[CTU_NAME_SIZE];
 304         int i, nr, ret;
 305 
 306         /* This driver doesn't support Gen1 at this point */
 307         if (rsnd_is_gen1(priv))
 308                 return 0;
 309 
 310         node = rsnd_ctu_of_node(priv);
 311         if (!node)
 312                 return 0; /* not used is not error */
 313 
 314         nr = of_get_child_count(node);
 315         if (!nr) {
 316                 ret = -EINVAL;
 317                 goto rsnd_ctu_probe_done;
 318         }
 319 
 320         ctu = devm_kcalloc(dev, nr, sizeof(*ctu), GFP_KERNEL);
 321         if (!ctu) {
 322                 ret = -ENOMEM;
 323                 goto rsnd_ctu_probe_done;
 324         }
 325 
 326         priv->ctu_nr    = nr;
 327         priv->ctu       = ctu;
 328 
 329         i = 0;
 330         ret = 0;
 331         for_each_child_of_node(node, np) {
 332                 ctu = rsnd_ctu_get(priv, i);
 333 
 334                 /*
 335                  * CTU00, CTU01, CTU02, CTU03 => CTU0
 336                  * CTU10, CTU11, CTU12, CTU13 => CTU1
 337                  */
 338                 snprintf(name, CTU_NAME_SIZE, "%s.%d",
 339                          CTU_NAME, i / 4);
 340 
 341                 clk = devm_clk_get(dev, name);
 342                 if (IS_ERR(clk)) {
 343                         ret = PTR_ERR(clk);
 344                         of_node_put(np);
 345                         goto rsnd_ctu_probe_done;
 346                 }
 347 
 348                 ret = rsnd_mod_init(priv, rsnd_mod_get(ctu), &rsnd_ctu_ops,
 349                                     clk, RSND_MOD_CTU, i);
 350                 if (ret) {
 351                         of_node_put(np);
 352                         goto rsnd_ctu_probe_done;
 353                 }
 354 
 355                 i++;
 356         }
 357 
 358 
 359 rsnd_ctu_probe_done:
 360         of_node_put(node);
 361 
 362         return ret;
 363 }
 364 
 365 void rsnd_ctu_remove(struct rsnd_priv *priv)
 366 {
 367         struct rsnd_ctu *ctu;
 368         int i;
 369 
 370         for_each_rsnd_ctu(ctu, priv, i) {
 371                 rsnd_mod_quit(rsnd_mod_get(ctu));
 372         }
 373 }

/* [<][>][^][v][top][bottom][index][help] */