1*7358a803SSameer Pujar // SPDX-License-Identifier: GPL-2.0-only 2*7358a803SSameer Pujar // 3*7358a803SSameer Pujar // tegra210_peq.c - Tegra210 PEQ driver 4*7358a803SSameer Pujar // 5*7358a803SSameer Pujar // Copyright (c) 2022, NVIDIA CORPORATION. All rights reserved. 6*7358a803SSameer Pujar 7*7358a803SSameer Pujar #include <linux/clk.h> 8*7358a803SSameer Pujar #include <linux/device.h> 9*7358a803SSameer Pujar #include <linux/io.h> 10*7358a803SSameer Pujar #include <linux/module.h> 11*7358a803SSameer Pujar #include <linux/of.h> 12*7358a803SSameer Pujar #include <linux/of_address.h> 13*7358a803SSameer Pujar #include <linux/of_device.h> 14*7358a803SSameer Pujar #include <linux/platform_device.h> 15*7358a803SSameer Pujar #include <linux/pm_runtime.h> 16*7358a803SSameer Pujar #include <linux/regmap.h> 17*7358a803SSameer Pujar #include <sound/core.h> 18*7358a803SSameer Pujar #include <sound/pcm.h> 19*7358a803SSameer Pujar #include <sound/pcm_params.h> 20*7358a803SSameer Pujar #include <sound/soc.h> 21*7358a803SSameer Pujar 22*7358a803SSameer Pujar #include "tegra210_ope.h" 23*7358a803SSameer Pujar #include "tegra210_peq.h" 24*7358a803SSameer Pujar 25*7358a803SSameer Pujar static const struct reg_default tegra210_peq_reg_defaults[] = { 26*7358a803SSameer Pujar { TEGRA210_PEQ_CFG, 0x00000013}, 27*7358a803SSameer Pujar { TEGRA210_PEQ_CFG_RAM_CTRL, 0x00004000}, 28*7358a803SSameer Pujar { TEGRA210_PEQ_CFG_RAM_SHIFT_CTRL, 0x00004000}, 29*7358a803SSameer Pujar }; 30*7358a803SSameer Pujar 31*7358a803SSameer Pujar static const u32 biquad_init_gains[TEGRA210_PEQ_GAIN_PARAM_SIZE_PER_CH] = { 32*7358a803SSameer Pujar 1495012349, /* Pre-gain */ 33*7358a803SSameer Pujar 34*7358a803SSameer Pujar /* Gains : b0, b1, a0, a1, a2 */ 35*7358a803SSameer Pujar 536870912, -1073741824, 536870912, 2143508246, -1069773768, /* Band-0 */ 36*7358a803SSameer Pujar 134217728, -265414508, 131766272, 2140402222, -1071252997, /* Band-1 */ 37*7358a803SSameer Pujar 268435456, -233515765, -33935948, 1839817267, -773826124, /* Band-2 */ 38*7358a803SSameer Pujar 536870912, -672537913, 139851540, 1886437554, -824433167, /* Band-3 */ 39*7358a803SSameer Pujar 268435456, -114439279, 173723964, 205743566, 278809729, /* Band-4 */ 40*7358a803SSameer Pujar 1, 0, 0, 0, 0, /* Band-5 */ 41*7358a803SSameer Pujar 1, 0, 0, 0, 0, /* Band-6 */ 42*7358a803SSameer Pujar 1, 0, 0, 0, 0, /* Band-7 */ 43*7358a803SSameer Pujar 1, 0, 0, 0, 0, /* Band-8 */ 44*7358a803SSameer Pujar 1, 0, 0, 0, 0, /* Band-9 */ 45*7358a803SSameer Pujar 1, 0, 0, 0, 0, /* Band-10 */ 46*7358a803SSameer Pujar 1, 0, 0, 0, 0, /* Band-11 */ 47*7358a803SSameer Pujar 48*7358a803SSameer Pujar 963423114, /* Post-gain */ 49*7358a803SSameer Pujar }; 50*7358a803SSameer Pujar 51*7358a803SSameer Pujar static const u32 biquad_init_shifts[TEGRA210_PEQ_SHIFT_PARAM_SIZE_PER_CH] = { 52*7358a803SSameer Pujar 23, /* Pre-shift */ 53*7358a803SSameer Pujar 30, 30, 30, 30, 30, 0, 0, 0, 0, 0, 0, 0, /* Shift for bands */ 54*7358a803SSameer Pujar 28, /* Post-shift */ 55*7358a803SSameer Pujar }; 56*7358a803SSameer Pujar 57*7358a803SSameer Pujar static s32 biquad_coeff_buffer[TEGRA210_PEQ_GAIN_PARAM_SIZE_PER_CH]; 58*7358a803SSameer Pujar 59*7358a803SSameer Pujar static void tegra210_peq_read_ram(struct regmap *regmap, unsigned int reg_ctrl, 60*7358a803SSameer Pujar unsigned int reg_data, unsigned int ram_offset, 61*7358a803SSameer Pujar unsigned int *data, size_t size) 62*7358a803SSameer Pujar { 63*7358a803SSameer Pujar unsigned int val; 64*7358a803SSameer Pujar unsigned int i; 65*7358a803SSameer Pujar 66*7358a803SSameer Pujar val = ram_offset & TEGRA210_PEQ_RAM_CTRL_RAM_ADDR_MASK; 67*7358a803SSameer Pujar val |= TEGRA210_PEQ_RAM_CTRL_ADDR_INIT_EN; 68*7358a803SSameer Pujar val |= TEGRA210_PEQ_RAM_CTRL_SEQ_ACCESS_EN; 69*7358a803SSameer Pujar val |= TEGRA210_PEQ_RAM_CTRL_RW_READ; 70*7358a803SSameer Pujar 71*7358a803SSameer Pujar regmap_write(regmap, reg_ctrl, val); 72*7358a803SSameer Pujar 73*7358a803SSameer Pujar /* 74*7358a803SSameer Pujar * Since all ahub non-io modules work under same ahub clock it is not 75*7358a803SSameer Pujar * necessary to check ahub read busy bit after every read. 76*7358a803SSameer Pujar */ 77*7358a803SSameer Pujar for (i = 0; i < size; i++) 78*7358a803SSameer Pujar regmap_read(regmap, reg_data, &data[i]); 79*7358a803SSameer Pujar } 80*7358a803SSameer Pujar 81*7358a803SSameer Pujar static void tegra210_peq_write_ram(struct regmap *regmap, unsigned int reg_ctrl, 82*7358a803SSameer Pujar unsigned int reg_data, unsigned int ram_offset, 83*7358a803SSameer Pujar unsigned int *data, size_t size) 84*7358a803SSameer Pujar { 85*7358a803SSameer Pujar unsigned int val; 86*7358a803SSameer Pujar unsigned int i; 87*7358a803SSameer Pujar 88*7358a803SSameer Pujar val = ram_offset & TEGRA210_PEQ_RAM_CTRL_RAM_ADDR_MASK; 89*7358a803SSameer Pujar val |= TEGRA210_PEQ_RAM_CTRL_ADDR_INIT_EN; 90*7358a803SSameer Pujar val |= TEGRA210_PEQ_RAM_CTRL_SEQ_ACCESS_EN; 91*7358a803SSameer Pujar val |= TEGRA210_PEQ_RAM_CTRL_RW_WRITE; 92*7358a803SSameer Pujar 93*7358a803SSameer Pujar regmap_write(regmap, reg_ctrl, val); 94*7358a803SSameer Pujar 95*7358a803SSameer Pujar for (i = 0; i < size; i++) 96*7358a803SSameer Pujar regmap_write(regmap, reg_data, data[i]); 97*7358a803SSameer Pujar } 98*7358a803SSameer Pujar 99*7358a803SSameer Pujar static int tegra210_peq_get(struct snd_kcontrol *kcontrol, 100*7358a803SSameer Pujar struct snd_ctl_elem_value *ucontrol) 101*7358a803SSameer Pujar { 102*7358a803SSameer Pujar struct soc_mixer_control *mc = 103*7358a803SSameer Pujar (struct soc_mixer_control *)kcontrol->private_value; 104*7358a803SSameer Pujar struct snd_soc_component *cmpnt = snd_soc_kcontrol_component(kcontrol); 105*7358a803SSameer Pujar struct tegra210_ope *ope = snd_soc_component_get_drvdata(cmpnt); 106*7358a803SSameer Pujar unsigned int mask = (1 << fls(mc->max)) - 1; 107*7358a803SSameer Pujar unsigned int val; 108*7358a803SSameer Pujar 109*7358a803SSameer Pujar regmap_read(ope->peq_regmap, mc->reg, &val); 110*7358a803SSameer Pujar 111*7358a803SSameer Pujar ucontrol->value.integer.value[0] = (val >> mc->shift) & mask; 112*7358a803SSameer Pujar 113*7358a803SSameer Pujar if (!mc->invert) 114*7358a803SSameer Pujar return 0; 115*7358a803SSameer Pujar 116*7358a803SSameer Pujar ucontrol->value.integer.value[0] = 117*7358a803SSameer Pujar mc->max - ucontrol->value.integer.value[0]; 118*7358a803SSameer Pujar 119*7358a803SSameer Pujar return 0; 120*7358a803SSameer Pujar } 121*7358a803SSameer Pujar 122*7358a803SSameer Pujar static int tegra210_peq_put(struct snd_kcontrol *kcontrol, 123*7358a803SSameer Pujar struct snd_ctl_elem_value *ucontrol) 124*7358a803SSameer Pujar { 125*7358a803SSameer Pujar struct soc_mixer_control *mc = 126*7358a803SSameer Pujar (struct soc_mixer_control *)kcontrol->private_value; 127*7358a803SSameer Pujar struct snd_soc_component *cmpnt = snd_soc_kcontrol_component(kcontrol); 128*7358a803SSameer Pujar struct tegra210_ope *ope = snd_soc_component_get_drvdata(cmpnt); 129*7358a803SSameer Pujar unsigned int mask = (1 << fls(mc->max)) - 1; 130*7358a803SSameer Pujar bool change = false; 131*7358a803SSameer Pujar unsigned int val; 132*7358a803SSameer Pujar 133*7358a803SSameer Pujar val = (ucontrol->value.integer.value[0] & mask); 134*7358a803SSameer Pujar 135*7358a803SSameer Pujar if (mc->invert) 136*7358a803SSameer Pujar val = mc->max - val; 137*7358a803SSameer Pujar 138*7358a803SSameer Pujar val = val << mc->shift; 139*7358a803SSameer Pujar 140*7358a803SSameer Pujar regmap_update_bits_check(ope->peq_regmap, mc->reg, (mask << mc->shift), 141*7358a803SSameer Pujar val, &change); 142*7358a803SSameer Pujar 143*7358a803SSameer Pujar return change ? 1 : 0; 144*7358a803SSameer Pujar } 145*7358a803SSameer Pujar 146*7358a803SSameer Pujar static int tegra210_peq_ram_get(struct snd_kcontrol *kcontrol, 147*7358a803SSameer Pujar struct snd_ctl_elem_value *ucontrol) 148*7358a803SSameer Pujar { 149*7358a803SSameer Pujar struct tegra_soc_bytes *params = (void *)kcontrol->private_value; 150*7358a803SSameer Pujar struct snd_soc_component *cmpnt = snd_soc_kcontrol_component(kcontrol); 151*7358a803SSameer Pujar struct tegra210_ope *ope = snd_soc_component_get_drvdata(cmpnt); 152*7358a803SSameer Pujar u32 i, reg_ctrl = params->soc.base; 153*7358a803SSameer Pujar u32 reg_data = reg_ctrl + cmpnt->val_bytes; 154*7358a803SSameer Pujar s32 *data = (s32 *)biquad_coeff_buffer; 155*7358a803SSameer Pujar 156*7358a803SSameer Pujar pm_runtime_get_sync(cmpnt->dev); 157*7358a803SSameer Pujar 158*7358a803SSameer Pujar tegra210_peq_read_ram(ope->peq_regmap, reg_ctrl, reg_data, 159*7358a803SSameer Pujar params->shift, data, params->soc.num_regs); 160*7358a803SSameer Pujar 161*7358a803SSameer Pujar pm_runtime_put_sync(cmpnt->dev); 162*7358a803SSameer Pujar 163*7358a803SSameer Pujar for (i = 0; i < params->soc.num_regs; i++) 164*7358a803SSameer Pujar ucontrol->value.integer.value[i] = (long)data[i]; 165*7358a803SSameer Pujar 166*7358a803SSameer Pujar return 0; 167*7358a803SSameer Pujar } 168*7358a803SSameer Pujar 169*7358a803SSameer Pujar static int tegra210_peq_ram_put(struct snd_kcontrol *kcontrol, 170*7358a803SSameer Pujar struct snd_ctl_elem_value *ucontrol) 171*7358a803SSameer Pujar { 172*7358a803SSameer Pujar struct tegra_soc_bytes *params = (void *)kcontrol->private_value; 173*7358a803SSameer Pujar struct snd_soc_component *cmpnt = snd_soc_kcontrol_component(kcontrol); 174*7358a803SSameer Pujar struct tegra210_ope *ope = snd_soc_component_get_drvdata(cmpnt); 175*7358a803SSameer Pujar u32 i, reg_ctrl = params->soc.base; 176*7358a803SSameer Pujar u32 reg_data = reg_ctrl + cmpnt->val_bytes; 177*7358a803SSameer Pujar s32 *data = (s32 *)biquad_coeff_buffer; 178*7358a803SSameer Pujar 179*7358a803SSameer Pujar for (i = 0; i < params->soc.num_regs; i++) 180*7358a803SSameer Pujar data[i] = (s32)ucontrol->value.integer.value[i]; 181*7358a803SSameer Pujar 182*7358a803SSameer Pujar pm_runtime_get_sync(cmpnt->dev); 183*7358a803SSameer Pujar 184*7358a803SSameer Pujar tegra210_peq_write_ram(ope->peq_regmap, reg_ctrl, reg_data, 185*7358a803SSameer Pujar params->shift, data, params->soc.num_regs); 186*7358a803SSameer Pujar 187*7358a803SSameer Pujar pm_runtime_put_sync(cmpnt->dev); 188*7358a803SSameer Pujar 189*7358a803SSameer Pujar return 1; 190*7358a803SSameer Pujar } 191*7358a803SSameer Pujar 192*7358a803SSameer Pujar static int tegra210_peq_param_info(struct snd_kcontrol *kcontrol, 193*7358a803SSameer Pujar struct snd_ctl_elem_info *uinfo) 194*7358a803SSameer Pujar { 195*7358a803SSameer Pujar struct soc_bytes *params = (void *)kcontrol->private_value; 196*7358a803SSameer Pujar 197*7358a803SSameer Pujar uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER; 198*7358a803SSameer Pujar uinfo->value.integer.min = INT_MIN; 199*7358a803SSameer Pujar uinfo->value.integer.max = INT_MAX; 200*7358a803SSameer Pujar uinfo->count = params->num_regs; 201*7358a803SSameer Pujar 202*7358a803SSameer Pujar return 0; 203*7358a803SSameer Pujar } 204*7358a803SSameer Pujar 205*7358a803SSameer Pujar #define TEGRA210_PEQ_GAIN_PARAMS_CTRL(chan) \ 206*7358a803SSameer Pujar TEGRA_SOC_BYTES_EXT("PEQ Channel-" #chan " Biquad Gain Params", \ 207*7358a803SSameer Pujar TEGRA210_PEQ_CFG_RAM_CTRL, \ 208*7358a803SSameer Pujar TEGRA210_PEQ_GAIN_PARAM_SIZE_PER_CH, \ 209*7358a803SSameer Pujar (TEGRA210_PEQ_GAIN_PARAM_SIZE_PER_CH * chan), 0xffffffff, \ 210*7358a803SSameer Pujar tegra210_peq_ram_get, tegra210_peq_ram_put, \ 211*7358a803SSameer Pujar tegra210_peq_param_info) 212*7358a803SSameer Pujar 213*7358a803SSameer Pujar #define TEGRA210_PEQ_SHIFT_PARAMS_CTRL(chan) \ 214*7358a803SSameer Pujar TEGRA_SOC_BYTES_EXT("PEQ Channel-" #chan " Biquad Shift Params", \ 215*7358a803SSameer Pujar TEGRA210_PEQ_CFG_RAM_SHIFT_CTRL, \ 216*7358a803SSameer Pujar TEGRA210_PEQ_SHIFT_PARAM_SIZE_PER_CH, \ 217*7358a803SSameer Pujar (TEGRA210_PEQ_SHIFT_PARAM_SIZE_PER_CH * chan), 0x1f, \ 218*7358a803SSameer Pujar tegra210_peq_ram_get, tegra210_peq_ram_put, \ 219*7358a803SSameer Pujar tegra210_peq_param_info) 220*7358a803SSameer Pujar 221*7358a803SSameer Pujar static const struct snd_kcontrol_new tegra210_peq_controls[] = { 222*7358a803SSameer Pujar SOC_SINGLE_EXT("PEQ Active", TEGRA210_PEQ_CFG, 223*7358a803SSameer Pujar TEGRA210_PEQ_CFG_MODE_SHIFT, 1, 0, 224*7358a803SSameer Pujar tegra210_peq_get, tegra210_peq_put), 225*7358a803SSameer Pujar 226*7358a803SSameer Pujar SOC_SINGLE_EXT("PEQ Biquad Stages", TEGRA210_PEQ_CFG, 227*7358a803SSameer Pujar TEGRA210_PEQ_CFG_BIQUAD_STAGES_SHIFT, 228*7358a803SSameer Pujar TEGRA210_PEQ_MAX_BIQUAD_STAGES - 1, 0, 229*7358a803SSameer Pujar tegra210_peq_get, tegra210_peq_put), 230*7358a803SSameer Pujar 231*7358a803SSameer Pujar TEGRA210_PEQ_GAIN_PARAMS_CTRL(0), 232*7358a803SSameer Pujar TEGRA210_PEQ_GAIN_PARAMS_CTRL(1), 233*7358a803SSameer Pujar TEGRA210_PEQ_GAIN_PARAMS_CTRL(2), 234*7358a803SSameer Pujar TEGRA210_PEQ_GAIN_PARAMS_CTRL(3), 235*7358a803SSameer Pujar TEGRA210_PEQ_GAIN_PARAMS_CTRL(4), 236*7358a803SSameer Pujar TEGRA210_PEQ_GAIN_PARAMS_CTRL(5), 237*7358a803SSameer Pujar TEGRA210_PEQ_GAIN_PARAMS_CTRL(6), 238*7358a803SSameer Pujar TEGRA210_PEQ_GAIN_PARAMS_CTRL(7), 239*7358a803SSameer Pujar 240*7358a803SSameer Pujar TEGRA210_PEQ_SHIFT_PARAMS_CTRL(0), 241*7358a803SSameer Pujar TEGRA210_PEQ_SHIFT_PARAMS_CTRL(1), 242*7358a803SSameer Pujar TEGRA210_PEQ_SHIFT_PARAMS_CTRL(2), 243*7358a803SSameer Pujar TEGRA210_PEQ_SHIFT_PARAMS_CTRL(3), 244*7358a803SSameer Pujar TEGRA210_PEQ_SHIFT_PARAMS_CTRL(4), 245*7358a803SSameer Pujar TEGRA210_PEQ_SHIFT_PARAMS_CTRL(5), 246*7358a803SSameer Pujar TEGRA210_PEQ_SHIFT_PARAMS_CTRL(6), 247*7358a803SSameer Pujar TEGRA210_PEQ_SHIFT_PARAMS_CTRL(7), 248*7358a803SSameer Pujar }; 249*7358a803SSameer Pujar 250*7358a803SSameer Pujar static bool tegra210_peq_wr_reg(struct device *dev, unsigned int reg) 251*7358a803SSameer Pujar { 252*7358a803SSameer Pujar switch (reg) { 253*7358a803SSameer Pujar case TEGRA210_PEQ_SOFT_RESET: 254*7358a803SSameer Pujar case TEGRA210_PEQ_CG: 255*7358a803SSameer Pujar case TEGRA210_PEQ_CFG ... TEGRA210_PEQ_CFG_RAM_SHIFT_DATA: 256*7358a803SSameer Pujar return true; 257*7358a803SSameer Pujar default: 258*7358a803SSameer Pujar return false; 259*7358a803SSameer Pujar } 260*7358a803SSameer Pujar } 261*7358a803SSameer Pujar 262*7358a803SSameer Pujar static bool tegra210_peq_rd_reg(struct device *dev, unsigned int reg) 263*7358a803SSameer Pujar { 264*7358a803SSameer Pujar if (tegra210_peq_wr_reg(dev, reg)) 265*7358a803SSameer Pujar return true; 266*7358a803SSameer Pujar 267*7358a803SSameer Pujar switch (reg) { 268*7358a803SSameer Pujar case TEGRA210_PEQ_STATUS: 269*7358a803SSameer Pujar return true; 270*7358a803SSameer Pujar default: 271*7358a803SSameer Pujar return false; 272*7358a803SSameer Pujar } 273*7358a803SSameer Pujar } 274*7358a803SSameer Pujar 275*7358a803SSameer Pujar static bool tegra210_peq_volatile_reg(struct device *dev, unsigned int reg) 276*7358a803SSameer Pujar { 277*7358a803SSameer Pujar switch (reg) { 278*7358a803SSameer Pujar case TEGRA210_PEQ_SOFT_RESET: 279*7358a803SSameer Pujar case TEGRA210_PEQ_STATUS: 280*7358a803SSameer Pujar case TEGRA210_PEQ_CFG_RAM_CTRL ... TEGRA210_PEQ_CFG_RAM_SHIFT_DATA: 281*7358a803SSameer Pujar return true; 282*7358a803SSameer Pujar default: 283*7358a803SSameer Pujar return false; 284*7358a803SSameer Pujar } 285*7358a803SSameer Pujar } 286*7358a803SSameer Pujar 287*7358a803SSameer Pujar static bool tegra210_peq_precious_reg(struct device *dev, unsigned int reg) 288*7358a803SSameer Pujar { 289*7358a803SSameer Pujar switch (reg) { 290*7358a803SSameer Pujar case TEGRA210_PEQ_CFG_RAM_DATA: 291*7358a803SSameer Pujar case TEGRA210_PEQ_CFG_RAM_SHIFT_DATA: 292*7358a803SSameer Pujar return true; 293*7358a803SSameer Pujar default: 294*7358a803SSameer Pujar return false; 295*7358a803SSameer Pujar } 296*7358a803SSameer Pujar } 297*7358a803SSameer Pujar 298*7358a803SSameer Pujar static const struct regmap_config tegra210_peq_regmap_config = { 299*7358a803SSameer Pujar .name = "peq", 300*7358a803SSameer Pujar .reg_bits = 32, 301*7358a803SSameer Pujar .reg_stride = 4, 302*7358a803SSameer Pujar .val_bits = 32, 303*7358a803SSameer Pujar .max_register = TEGRA210_PEQ_CFG_RAM_SHIFT_DATA, 304*7358a803SSameer Pujar .writeable_reg = tegra210_peq_wr_reg, 305*7358a803SSameer Pujar .readable_reg = tegra210_peq_rd_reg, 306*7358a803SSameer Pujar .volatile_reg = tegra210_peq_volatile_reg, 307*7358a803SSameer Pujar .precious_reg = tegra210_peq_precious_reg, 308*7358a803SSameer Pujar .reg_defaults = tegra210_peq_reg_defaults, 309*7358a803SSameer Pujar .num_reg_defaults = ARRAY_SIZE(tegra210_peq_reg_defaults), 310*7358a803SSameer Pujar .cache_type = REGCACHE_FLAT, 311*7358a803SSameer Pujar }; 312*7358a803SSameer Pujar 313*7358a803SSameer Pujar void tegra210_peq_restore(struct regmap *regmap, u32 *biquad_gains, 314*7358a803SSameer Pujar u32 *biquad_shifts) 315*7358a803SSameer Pujar { 316*7358a803SSameer Pujar unsigned int i; 317*7358a803SSameer Pujar 318*7358a803SSameer Pujar for (i = 0; i < TEGRA210_PEQ_MAX_CHANNELS; i++) { 319*7358a803SSameer Pujar tegra210_peq_write_ram(regmap, TEGRA210_PEQ_CFG_RAM_CTRL, 320*7358a803SSameer Pujar TEGRA210_PEQ_CFG_RAM_DATA, 321*7358a803SSameer Pujar (i * TEGRA210_PEQ_GAIN_PARAM_SIZE_PER_CH), 322*7358a803SSameer Pujar biquad_gains, 323*7358a803SSameer Pujar TEGRA210_PEQ_GAIN_PARAM_SIZE_PER_CH); 324*7358a803SSameer Pujar 325*7358a803SSameer Pujar tegra210_peq_write_ram(regmap, 326*7358a803SSameer Pujar TEGRA210_PEQ_CFG_RAM_SHIFT_CTRL, 327*7358a803SSameer Pujar TEGRA210_PEQ_CFG_RAM_SHIFT_DATA, 328*7358a803SSameer Pujar (i * TEGRA210_PEQ_SHIFT_PARAM_SIZE_PER_CH), 329*7358a803SSameer Pujar biquad_shifts, 330*7358a803SSameer Pujar TEGRA210_PEQ_SHIFT_PARAM_SIZE_PER_CH); 331*7358a803SSameer Pujar 332*7358a803SSameer Pujar } 333*7358a803SSameer Pujar } 334*7358a803SSameer Pujar 335*7358a803SSameer Pujar void tegra210_peq_save(struct regmap *regmap, u32 *biquad_gains, 336*7358a803SSameer Pujar u32 *biquad_shifts) 337*7358a803SSameer Pujar { 338*7358a803SSameer Pujar unsigned int i; 339*7358a803SSameer Pujar 340*7358a803SSameer Pujar for (i = 0; i < TEGRA210_PEQ_MAX_CHANNELS; i++) { 341*7358a803SSameer Pujar tegra210_peq_read_ram(regmap, 342*7358a803SSameer Pujar TEGRA210_PEQ_CFG_RAM_CTRL, 343*7358a803SSameer Pujar TEGRA210_PEQ_CFG_RAM_DATA, 344*7358a803SSameer Pujar (i * TEGRA210_PEQ_GAIN_PARAM_SIZE_PER_CH), 345*7358a803SSameer Pujar biquad_gains, 346*7358a803SSameer Pujar TEGRA210_PEQ_GAIN_PARAM_SIZE_PER_CH); 347*7358a803SSameer Pujar 348*7358a803SSameer Pujar tegra210_peq_read_ram(regmap, 349*7358a803SSameer Pujar TEGRA210_PEQ_CFG_RAM_SHIFT_CTRL, 350*7358a803SSameer Pujar TEGRA210_PEQ_CFG_RAM_SHIFT_DATA, 351*7358a803SSameer Pujar (i * TEGRA210_PEQ_SHIFT_PARAM_SIZE_PER_CH), 352*7358a803SSameer Pujar biquad_shifts, 353*7358a803SSameer Pujar TEGRA210_PEQ_SHIFT_PARAM_SIZE_PER_CH); 354*7358a803SSameer Pujar } 355*7358a803SSameer Pujar } 356*7358a803SSameer Pujar 357*7358a803SSameer Pujar int tegra210_peq_component_init(struct snd_soc_component *cmpnt) 358*7358a803SSameer Pujar { 359*7358a803SSameer Pujar struct tegra210_ope *ope = snd_soc_component_get_drvdata(cmpnt); 360*7358a803SSameer Pujar unsigned int i; 361*7358a803SSameer Pujar 362*7358a803SSameer Pujar pm_runtime_get_sync(cmpnt->dev); 363*7358a803SSameer Pujar regmap_update_bits(ope->peq_regmap, TEGRA210_PEQ_CFG, 364*7358a803SSameer Pujar TEGRA210_PEQ_CFG_MODE_MASK, 365*7358a803SSameer Pujar 0 << TEGRA210_PEQ_CFG_MODE_SHIFT); 366*7358a803SSameer Pujar regmap_update_bits(ope->peq_regmap, TEGRA210_PEQ_CFG, 367*7358a803SSameer Pujar TEGRA210_PEQ_CFG_BIQUAD_STAGES_MASK, 368*7358a803SSameer Pujar (TEGRA210_PEQ_BIQUAD_INIT_STAGE - 1) << 369*7358a803SSameer Pujar TEGRA210_PEQ_CFG_BIQUAD_STAGES_SHIFT); 370*7358a803SSameer Pujar 371*7358a803SSameer Pujar /* Initialize PEQ AHUB RAM with default params */ 372*7358a803SSameer Pujar for (i = 0; i < TEGRA210_PEQ_MAX_CHANNELS; i++) { 373*7358a803SSameer Pujar 374*7358a803SSameer Pujar /* Set default gain params */ 375*7358a803SSameer Pujar tegra210_peq_write_ram(ope->peq_regmap, 376*7358a803SSameer Pujar TEGRA210_PEQ_CFG_RAM_CTRL, 377*7358a803SSameer Pujar TEGRA210_PEQ_CFG_RAM_DATA, 378*7358a803SSameer Pujar (i * TEGRA210_PEQ_GAIN_PARAM_SIZE_PER_CH), 379*7358a803SSameer Pujar (u32 *)&biquad_init_gains, 380*7358a803SSameer Pujar TEGRA210_PEQ_GAIN_PARAM_SIZE_PER_CH); 381*7358a803SSameer Pujar 382*7358a803SSameer Pujar /* Set default shift params */ 383*7358a803SSameer Pujar tegra210_peq_write_ram(ope->peq_regmap, 384*7358a803SSameer Pujar TEGRA210_PEQ_CFG_RAM_SHIFT_CTRL, 385*7358a803SSameer Pujar TEGRA210_PEQ_CFG_RAM_SHIFT_DATA, 386*7358a803SSameer Pujar (i * TEGRA210_PEQ_SHIFT_PARAM_SIZE_PER_CH), 387*7358a803SSameer Pujar (u32 *)&biquad_init_shifts, 388*7358a803SSameer Pujar TEGRA210_PEQ_SHIFT_PARAM_SIZE_PER_CH); 389*7358a803SSameer Pujar 390*7358a803SSameer Pujar } 391*7358a803SSameer Pujar 392*7358a803SSameer Pujar pm_runtime_put_sync(cmpnt->dev); 393*7358a803SSameer Pujar 394*7358a803SSameer Pujar snd_soc_add_component_controls(cmpnt, tegra210_peq_controls, 395*7358a803SSameer Pujar ARRAY_SIZE(tegra210_peq_controls)); 396*7358a803SSameer Pujar 397*7358a803SSameer Pujar return 0; 398*7358a803SSameer Pujar } 399*7358a803SSameer Pujar 400*7358a803SSameer Pujar int tegra210_peq_regmap_init(struct platform_device *pdev) 401*7358a803SSameer Pujar { 402*7358a803SSameer Pujar struct device *dev = &pdev->dev; 403*7358a803SSameer Pujar struct tegra210_ope *ope = dev_get_drvdata(dev); 404*7358a803SSameer Pujar struct device_node *child; 405*7358a803SSameer Pujar struct resource mem; 406*7358a803SSameer Pujar void __iomem *regs; 407*7358a803SSameer Pujar int err; 408*7358a803SSameer Pujar 409*7358a803SSameer Pujar child = of_get_child_by_name(dev->of_node, "equalizer"); 410*7358a803SSameer Pujar if (!child) 411*7358a803SSameer Pujar return -ENODEV; 412*7358a803SSameer Pujar 413*7358a803SSameer Pujar err = of_address_to_resource(child, 0, &mem); 414*7358a803SSameer Pujar of_node_put(child); 415*7358a803SSameer Pujar if (err < 0) { 416*7358a803SSameer Pujar dev_err(dev, "fail to get PEQ resource\n"); 417*7358a803SSameer Pujar return err; 418*7358a803SSameer Pujar } 419*7358a803SSameer Pujar 420*7358a803SSameer Pujar mem.flags = IORESOURCE_MEM; 421*7358a803SSameer Pujar regs = devm_ioremap_resource(dev, &mem); 422*7358a803SSameer Pujar if (IS_ERR(regs)) 423*7358a803SSameer Pujar return PTR_ERR(regs); 424*7358a803SSameer Pujar ope->peq_regmap = devm_regmap_init_mmio(dev, regs, 425*7358a803SSameer Pujar &tegra210_peq_regmap_config); 426*7358a803SSameer Pujar if (IS_ERR(ope->peq_regmap)) { 427*7358a803SSameer Pujar dev_err(dev, "regmap init failed\n"); 428*7358a803SSameer Pujar return PTR_ERR(ope->peq_regmap); 429*7358a803SSameer Pujar } 430*7358a803SSameer Pujar 431*7358a803SSameer Pujar regcache_cache_only(ope->peq_regmap, true); 432*7358a803SSameer Pujar 433*7358a803SSameer Pujar return 0; 434*7358a803SSameer Pujar } 435