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