1015 lines · c
1// SPDX-License-Identifier: GPL-2.0-only2//3// tegra210_mbdrc.c - Tegra210 MBDRC driver4//5// Copyright (c) 2022, NVIDIA CORPORATION. All rights reserved.6 7#include <linux/device.h>8#include <linux/io.h>9#include <linux/module.h>10#include <linux/of_address.h>11#include <linux/pm_runtime.h>12#include <linux/regmap.h>13#include <sound/core.h>14#include <sound/soc.h>15#include <sound/tlv.h>16 17#include "tegra210_mbdrc.h"18#include "tegra210_ope.h"19 20#define MBDRC_FILTER_REG(reg, id) \21 ((reg) + ((id) * TEGRA210_MBDRC_FILTER_PARAM_STRIDE))22 23#define MBDRC_FILTER_REG_DEFAULTS(id) \24 { MBDRC_FILTER_REG(TEGRA210_MBDRC_IIR_CFG, id), 0x00000005}, \25 { MBDRC_FILTER_REG(TEGRA210_MBDRC_IN_ATTACK, id), 0x3e48590c}, \26 { MBDRC_FILTER_REG(TEGRA210_MBDRC_IN_RELEASE, id), 0x08414e9f}, \27 { MBDRC_FILTER_REG(TEGRA210_MBDRC_FAST_ATTACK, id), 0x7fffffff}, \28 { MBDRC_FILTER_REG(TEGRA210_MBDRC_IN_THRESHOLD, id), 0x06145082}, \29 { MBDRC_FILTER_REG(TEGRA210_MBDRC_OUT_THRESHOLD, id), 0x060d379b}, \30 { MBDRC_FILTER_REG(TEGRA210_MBDRC_RATIO_1ST, id), 0x0000a000}, \31 { MBDRC_FILTER_REG(TEGRA210_MBDRC_RATIO_2ND, id), 0x00002000}, \32 { MBDRC_FILTER_REG(TEGRA210_MBDRC_RATIO_3RD, id), 0x00000b33}, \33 { MBDRC_FILTER_REG(TEGRA210_MBDRC_RATIO_4TH, id), 0x00000800}, \34 { MBDRC_FILTER_REG(TEGRA210_MBDRC_RATIO_5TH, id), 0x0000019a}, \35 { MBDRC_FILTER_REG(TEGRA210_MBDRC_MAKEUP_GAIN, id), 0x00000002}, \36 { MBDRC_FILTER_REG(TEGRA210_MBDRC_INIT_GAIN, id), 0x00066666}, \37 { MBDRC_FILTER_REG(TEGRA210_MBDRC_GAIN_ATTACK, id), 0x00d9ba0e}, \38 { MBDRC_FILTER_REG(TEGRA210_MBDRC_GAIN_RELEASE, id), 0x3e48590c}, \39 { MBDRC_FILTER_REG(TEGRA210_MBDRC_FAST_RELEASE, id), 0x7ffff26a}, \40 { MBDRC_FILTER_REG(TEGRA210_MBDRC_CFG_RAM_CTRL, id), 0x4000}41 42static const struct reg_default tegra210_mbdrc_reg_defaults[] = {43 { TEGRA210_MBDRC_CFG, 0x0030de51},44 { TEGRA210_MBDRC_CHANNEL_MASK, 0x00000003},45 { TEGRA210_MBDRC_FAST_FACTOR, 0x30000800},46 47 MBDRC_FILTER_REG_DEFAULTS(0),48 MBDRC_FILTER_REG_DEFAULTS(1),49 MBDRC_FILTER_REG_DEFAULTS(2),50};51 52/* Default MBDRC parameters */53static const struct tegra210_mbdrc_config mbdrc_init_config = {54 .mode = 0, /* Bypass */55 .rms_off = 48,56 .peak_rms_mode = 1, /* PEAK */57 .filter_structure = 0, /* All-pass tree */58 .shift_ctrl = 30,59 .frame_size = 32,60 .channel_mask = 0x3,61 .fa_factor = 2048,62 .fr_factor = 14747,63 64 .band_params[MBDRC_LOW_BAND] = {65 .band = MBDRC_LOW_BAND,66 .iir_stages = 5,67 .in_attack_tc = 1044928780,68 .in_release_tc = 138497695,69 .fast_attack_tc = 2147483647,70 .in_threshold = {130, 80, 20, 6},71 .out_threshold = {155, 55, 13, 6},72 .ratio = {40960, 8192, 2867, 2048, 410},73 .makeup_gain = 4,74 .gain_init = 419430,75 .gain_attack_tc = 14268942,76 .gain_release_tc = 1440547090,77 .fast_release_tc = 2147480170,78 79 .biquad_params = {80 /*81 * Gains:82 *83 * b0, b1, a0,84 * a1, a2,85 */86 87 /* Band-0 */88 961046798, -2030431983, 1073741824,89 2030431983, -961046798,90 /* Band-1 */91 1030244425, -2099481453, 1073741824,92 2099481453, -1030244425,93 /* Band-2 */94 1067169294, -2136327263, 1073741824,95 2136327263, -1067169294,96 /* Band-3 */97 434951949, -1306567134, 1073741824,98 1306567134, -434951949,99 /* Band-4 */100 780656019, -1605955641, 1073741824,101 1605955641, -780656019,102 /* Band-5 */103 1024497031, -1817128152, 1073741824,104 1817128152, -1024497031,105 /* Band-6 */106 1073741824, 0, 0,107 0, 0,108 /* Band-7 */109 1073741824, 0, 0,110 0, 0,111 }112 },113 114 .band_params[MBDRC_MID_BAND] = {115 .band = MBDRC_MID_BAND,116 .iir_stages = 5,117 .in_attack_tc = 1581413104,118 .in_release_tc = 35494783,119 .fast_attack_tc = 2147483647,120 .in_threshold = {130, 50, 30, 6},121 .out_threshold = {106, 50, 30, 13},122 .ratio = {40960, 2867, 4096, 2867, 410},123 .makeup_gain = 6,124 .gain_init = 419430,125 .gain_attack_tc = 4766887,126 .gain_release_tc = 1044928780,127 .fast_release_tc = 2147480170,128 129 .biquad_params = {130 /*131 * Gains:132 *133 * b0, b1, a0,134 * a1, a2,135 */136 137 /* Band-0 */138 -1005668963, 1073741824, 0,139 1005668963, 0,140 /* Band-1 */141 998437058, -2067742187, 1073741824,142 2067742187, -998437058,143 /* Band-2 */144 1051963422, -2121153948, 1073741824,145 2121153948, -1051963422,146 /* Band-3 */147 434951949, -1306567134, 1073741824,148 1306567134, -434951949,149 /* Band-4 */150 780656019, -1605955641, 1073741824,151 1605955641, -780656019,152 /* Band-5 */153 1024497031, -1817128152, 1073741824,154 1817128152, -1024497031,155 /* Band-6 */156 1073741824, 0, 0,157 0, 0,158 /* Band-7 */159 1073741824, 0, 0,160 0, 0,161 }162 },163 164 .band_params[MBDRC_HIGH_BAND] = {165 .band = MBDRC_HIGH_BAND,166 .iir_stages = 5,167 .in_attack_tc = 2144750688,168 .in_release_tc = 70402888,169 .fast_attack_tc = 2147483647,170 .in_threshold = {130, 50, 30, 6},171 .out_threshold = {106, 50, 30, 13},172 .ratio = {40960, 2867, 4096, 2867, 410},173 .makeup_gain = 6,174 .gain_init = 419430,175 .gain_attack_tc = 4766887,176 .gain_release_tc = 1044928780,177 .fast_release_tc = 2147480170,178 179 .biquad_params = {180 /*181 * Gains:182 *183 * b0, b1, a0,184 * a1, a2,185 */186 187 /* Band-0 */188 1073741824, 0, 0,189 0, 0,190 /* Band-1 */191 1073741824, 0, 0,192 0, 0,193 /* Band-2 */194 1073741824, 0, 0,195 0, 0,196 /* Band-3 */197 -619925131, 1073741824, 0,198 619925131, 0,199 /* Band-4 */200 606839335, -1455425976, 1073741824,201 1455425976, -606839335,202 /* Band-5 */203 917759617, -1724690840, 1073741824,204 1724690840, -917759617,205 /* Band-6 */206 1073741824, 0, 0,207 0, 0,208 /* Band-7 */209 1073741824, 0, 0,210 0, 0,211 }212 }213};214 215static void tegra210_mbdrc_write_ram(struct regmap *regmap, unsigned int reg_ctrl,216 unsigned int reg_data, unsigned int ram_offset,217 unsigned int *data, size_t size)218{219 unsigned int val;220 unsigned int i;221 222 val = ram_offset & TEGRA210_MBDRC_RAM_CTRL_RAM_ADDR_MASK;223 val |= TEGRA210_MBDRC_RAM_CTRL_ADDR_INIT_EN;224 val |= TEGRA210_MBDRC_RAM_CTRL_SEQ_ACCESS_EN;225 val |= TEGRA210_MBDRC_RAM_CTRL_RW_WRITE;226 227 regmap_write(regmap, reg_ctrl, val);228 229 for (i = 0; i < size; i++)230 regmap_write(regmap, reg_data, data[i]);231}232 233static int tegra210_mbdrc_get(struct snd_kcontrol *kcontrol,234 struct snd_ctl_elem_value *ucontrol)235{236 struct soc_mixer_control *mc =237 (struct soc_mixer_control *)kcontrol->private_value;238 struct snd_soc_component *cmpnt = snd_soc_kcontrol_component(kcontrol);239 struct tegra210_ope *ope = snd_soc_component_get_drvdata(cmpnt);240 unsigned int val;241 242 regmap_read(ope->mbdrc_regmap, mc->reg, &val);243 244 ucontrol->value.integer.value[0] = (val >> mc->shift) & mc->max;245 246 return 0;247}248 249static int tegra210_mbdrc_put(struct snd_kcontrol *kcontrol,250 struct snd_ctl_elem_value *ucontrol)251{252 struct soc_mixer_control *mc =253 (struct soc_mixer_control *)kcontrol->private_value;254 struct snd_soc_component *cmpnt = snd_soc_kcontrol_component(kcontrol);255 struct tegra210_ope *ope = snd_soc_component_get_drvdata(cmpnt);256 unsigned int val = ucontrol->value.integer.value[0];257 bool change = false;258 259 val = val << mc->shift;260 261 regmap_update_bits_check(ope->mbdrc_regmap, mc->reg,262 (mc->max << mc->shift), val, &change);263 264 return change ? 1 : 0;265}266 267static int tegra210_mbdrc_get_enum(struct snd_kcontrol *kcontrol,268 struct snd_ctl_elem_value *ucontrol)269{270 struct snd_soc_component *cmpnt = snd_soc_kcontrol_component(kcontrol);271 struct tegra210_ope *ope = snd_soc_component_get_drvdata(cmpnt);272 struct soc_enum *e = (struct soc_enum *)kcontrol->private_value;273 unsigned int val;274 275 regmap_read(ope->mbdrc_regmap, e->reg, &val);276 277 ucontrol->value.enumerated.item[0] = (val >> e->shift_l) & e->mask;278 279 return 0;280}281 282static int tegra210_mbdrc_put_enum(struct snd_kcontrol *kcontrol,283 struct snd_ctl_elem_value *ucontrol)284{285 struct snd_soc_component *cmpnt = snd_soc_kcontrol_component(kcontrol);286 struct tegra210_ope *ope = snd_soc_component_get_drvdata(cmpnt);287 struct soc_enum *e = (struct soc_enum *)kcontrol->private_value;288 bool change = false;289 unsigned int val;290 unsigned int mask;291 292 if (ucontrol->value.enumerated.item[0] > e->items - 1)293 return -EINVAL;294 295 val = ucontrol->value.enumerated.item[0] << e->shift_l;296 mask = e->mask << e->shift_l;297 298 regmap_update_bits_check(ope->mbdrc_regmap, e->reg, mask, val,299 &change);300 301 return change ? 1 : 0;302}303 304static int tegra210_mbdrc_band_params_get(struct snd_kcontrol *kcontrol,305 struct snd_ctl_elem_value *ucontrol)306{307 struct tegra_soc_bytes *params = (void *)kcontrol->private_value;308 struct snd_soc_component *cmpnt = snd_soc_kcontrol_component(kcontrol);309 struct tegra210_ope *ope = snd_soc_component_get_drvdata(cmpnt);310 u32 *data = (u32 *)ucontrol->value.bytes.data;311 u32 regs = params->soc.base;312 u32 mask = params->soc.mask;313 u32 shift = params->shift;314 unsigned int i;315 316 for (i = 0; i < params->soc.num_regs; i++, regs += cmpnt->val_bytes) {317 regmap_read(ope->mbdrc_regmap, regs, &data[i]);318 319 data[i] = ((data[i] & mask) >> shift);320 }321 322 return 0;323}324 325static int tegra210_mbdrc_band_params_put(struct snd_kcontrol *kcontrol,326 struct snd_ctl_elem_value *ucontrol)327{328 struct tegra_soc_bytes *params = (void *)kcontrol->private_value;329 struct snd_soc_component *cmpnt = snd_soc_kcontrol_component(kcontrol);330 struct tegra210_ope *ope = snd_soc_component_get_drvdata(cmpnt);331 u32 *data = (u32 *)ucontrol->value.bytes.data;332 u32 regs = params->soc.base;333 u32 mask = params->soc.mask;334 u32 shift = params->shift;335 bool change = false;336 unsigned int i;337 338 for (i = 0; i < params->soc.num_regs; i++, regs += cmpnt->val_bytes) {339 bool update = false;340 341 regmap_update_bits_check(ope->mbdrc_regmap, regs, mask,342 data[i] << shift, &update);343 344 change |= update;345 }346 347 return change ? 1 : 0;348}349 350static int tegra210_mbdrc_threshold_get(struct snd_kcontrol *kcontrol,351 struct snd_ctl_elem_value *ucontrol)352{353 struct tegra_soc_bytes *params = (void *)kcontrol->private_value;354 struct snd_soc_component *cmpnt = snd_soc_kcontrol_component(kcontrol);355 struct tegra210_ope *ope = snd_soc_component_get_drvdata(cmpnt);356 u32 *data = (u32 *)ucontrol->value.bytes.data;357 u32 regs = params->soc.base;358 u32 num_regs = params->soc.num_regs;359 u32 val;360 unsigned int i;361 362 for (i = 0; i < num_regs; i += 4, regs += cmpnt->val_bytes) {363 regmap_read(ope->mbdrc_regmap, regs, &val);364 365 data[i] = (val & TEGRA210_MBDRC_THRESH_1ST_MASK) >>366 TEGRA210_MBDRC_THRESH_1ST_SHIFT;367 data[i + 1] = (val & TEGRA210_MBDRC_THRESH_2ND_MASK) >>368 TEGRA210_MBDRC_THRESH_2ND_SHIFT;369 data[i + 2] = (val & TEGRA210_MBDRC_THRESH_3RD_MASK) >>370 TEGRA210_MBDRC_THRESH_3RD_SHIFT;371 data[i + 3] = (val & TEGRA210_MBDRC_THRESH_4TH_MASK) >>372 TEGRA210_MBDRC_THRESH_4TH_SHIFT;373 }374 375 return 0;376}377 378static int tegra210_mbdrc_threshold_put(struct snd_kcontrol *kcontrol,379 struct snd_ctl_elem_value *ucontrol)380{381 struct tegra_soc_bytes *params = (void *)kcontrol->private_value;382 struct snd_soc_component *cmpnt = snd_soc_kcontrol_component(kcontrol);383 struct tegra210_ope *ope = snd_soc_component_get_drvdata(cmpnt);384 u32 *data = (u32 *)ucontrol->value.bytes.data;385 u32 regs = params->soc.base;386 u32 num_regs = params->soc.num_regs;387 bool change = false;388 unsigned int i;389 390 for (i = 0; i < num_regs; i += 4, regs += cmpnt->val_bytes) {391 bool update = false;392 393 data[i] = (((data[i] >> TEGRA210_MBDRC_THRESH_1ST_SHIFT) &394 TEGRA210_MBDRC_THRESH_1ST_MASK) |395 ((data[i + 1] >> TEGRA210_MBDRC_THRESH_2ND_SHIFT) &396 TEGRA210_MBDRC_THRESH_2ND_MASK) |397 ((data[i + 2] >> TEGRA210_MBDRC_THRESH_3RD_SHIFT) &398 TEGRA210_MBDRC_THRESH_3RD_MASK) |399 ((data[i + 3] >> TEGRA210_MBDRC_THRESH_4TH_SHIFT) &400 TEGRA210_MBDRC_THRESH_4TH_MASK));401 402 regmap_update_bits_check(ope->mbdrc_regmap, regs, 0xffffffff,403 data[i], &update);404 405 change |= update;406 }407 408 return change ? 1 : 0;409}410 411static int tegra210_mbdrc_biquad_coeffs_get(struct snd_kcontrol *kcontrol,412 struct snd_ctl_elem_value *ucontrol)413{414 struct tegra_soc_bytes *params = (void *)kcontrol->private_value;415 struct snd_soc_component *cmpnt = snd_soc_kcontrol_component(kcontrol);416 u32 *data = (u32 *)ucontrol->value.bytes.data;417 418 memset(data, 0, params->soc.num_regs * cmpnt->val_bytes);419 420 return 0;421}422 423static int tegra210_mbdrc_biquad_coeffs_put(struct snd_kcontrol *kcontrol,424 struct snd_ctl_elem_value *ucontrol)425{426 struct tegra_soc_bytes *params = (void *)kcontrol->private_value;427 struct snd_soc_component *cmpnt = snd_soc_kcontrol_component(kcontrol);428 struct tegra210_ope *ope = snd_soc_component_get_drvdata(cmpnt);429 u32 reg_ctrl = params->soc.base;430 u32 reg_data = reg_ctrl + cmpnt->val_bytes;431 u32 *data = (u32 *)ucontrol->value.bytes.data;432 433 tegra210_mbdrc_write_ram(ope->mbdrc_regmap, reg_ctrl, reg_data,434 params->shift, data, params->soc.num_regs);435 436 return 1;437}438 439static int tegra210_mbdrc_param_info(struct snd_kcontrol *kcontrol,440 struct snd_ctl_elem_info *uinfo)441{442 struct soc_bytes *params = (void *)kcontrol->private_value;443 444 uinfo->type = SNDRV_CTL_ELEM_TYPE_BYTES;445 uinfo->count = params->num_regs * sizeof(u32);446 447 return 0;448}449 450static int tegra210_mbdrc_vol_get(struct snd_kcontrol *kcontrol,451 struct snd_ctl_elem_value *ucontrol)452{453 struct soc_mixer_control *mc =454 (struct soc_mixer_control *)kcontrol->private_value;455 struct snd_soc_component *cmpnt = snd_soc_kcontrol_component(kcontrol);456 struct tegra210_ope *ope = snd_soc_component_get_drvdata(cmpnt);457 int val;458 459 regmap_read(ope->mbdrc_regmap, mc->reg, &val);460 461 ucontrol->value.integer.value[0] =462 ((val >> mc->shift) - TEGRA210_MBDRC_MASTER_VOL_MIN);463 464 return 0;465}466 467static int tegra210_mbdrc_vol_put(struct snd_kcontrol *kcontrol,468 struct snd_ctl_elem_value *ucontrol)469{470 struct soc_mixer_control *mc =471 (struct soc_mixer_control *)kcontrol->private_value;472 struct snd_soc_component *cmpnt = snd_soc_kcontrol_component(kcontrol);473 struct tegra210_ope *ope = snd_soc_component_get_drvdata(cmpnt);474 int val = ucontrol->value.integer.value[0];475 bool change = false;476 477 val += TEGRA210_MBDRC_MASTER_VOL_MIN;478 479 regmap_update_bits_check(ope->mbdrc_regmap, mc->reg,480 mc->max << mc->shift, val << mc->shift,481 &change);482 483 regmap_read(ope->mbdrc_regmap, mc->reg, &val);484 485 return change ? 1 : 0;486}487 488static const char * const tegra210_mbdrc_mode_text[] = {489 "Bypass", "Fullband", "Dualband", "Multiband"490};491 492static const struct soc_enum tegra210_mbdrc_mode_enum =493 SOC_ENUM_SINGLE(TEGRA210_MBDRC_CFG, TEGRA210_MBDRC_CFG_MBDRC_MODE_SHIFT,494 4, tegra210_mbdrc_mode_text);495 496static const char * const tegra210_mbdrc_peak_rms_text[] = {497 "Peak", "RMS"498};499 500static const struct soc_enum tegra210_mbdrc_peak_rms_enum =501 SOC_ENUM_SINGLE(TEGRA210_MBDRC_CFG, TEGRA210_MBDRC_CFG_PEAK_RMS_SHIFT,502 2, tegra210_mbdrc_peak_rms_text);503 504static const char * const tegra210_mbdrc_filter_structure_text[] = {505 "All-pass-tree", "Flexible"506};507 508static const struct soc_enum tegra210_mbdrc_filter_structure_enum =509 SOC_ENUM_SINGLE(TEGRA210_MBDRC_CFG,510 TEGRA210_MBDRC_CFG_FILTER_STRUCTURE_SHIFT, 2,511 tegra210_mbdrc_filter_structure_text);512 513static const char * const tegra210_mbdrc_frame_size_text[] = {514 "N1", "N2", "N4", "N8", "N16", "N32", "N64"515};516 517static const struct soc_enum tegra210_mbdrc_frame_size_enum =518 SOC_ENUM_SINGLE(TEGRA210_MBDRC_CFG, TEGRA210_MBDRC_CFG_FRAME_SIZE_SHIFT,519 7, tegra210_mbdrc_frame_size_text);520 521#define TEGRA_MBDRC_BYTES_EXT(xname, xbase, xregs, xshift, xmask, xinfo) \522 TEGRA_SOC_BYTES_EXT(xname, xbase, xregs, xshift, xmask, \523 tegra210_mbdrc_band_params_get, \524 tegra210_mbdrc_band_params_put, \525 tegra210_mbdrc_param_info)526 527#define TEGRA_MBDRC_BAND_BYTES_EXT(xname, xbase, xshift, xmask, xinfo) \528 TEGRA_MBDRC_BYTES_EXT(xname, xbase, TEGRA210_MBDRC_FILTER_COUNT, \529 xshift, xmask, xinfo)530 531static const DECLARE_TLV_DB_MINMAX(mdbrc_vol_tlv, -25600, 25500);532 533static const struct snd_kcontrol_new tegra210_mbdrc_controls[] = {534 SOC_ENUM_EXT("MBDRC Peak RMS Mode", tegra210_mbdrc_peak_rms_enum,535 tegra210_mbdrc_get_enum, tegra210_mbdrc_put_enum),536 537 SOC_ENUM_EXT("MBDRC Filter Structure",538 tegra210_mbdrc_filter_structure_enum,539 tegra210_mbdrc_get_enum, tegra210_mbdrc_put_enum),540 541 SOC_ENUM_EXT("MBDRC Frame Size", tegra210_mbdrc_frame_size_enum,542 tegra210_mbdrc_get_enum, tegra210_mbdrc_put_enum),543 544 SOC_ENUM_EXT("MBDRC Mode", tegra210_mbdrc_mode_enum,545 tegra210_mbdrc_get_enum, tegra210_mbdrc_put_enum),546 547 SOC_SINGLE_EXT("MBDRC RMS Offset", TEGRA210_MBDRC_CFG,548 TEGRA210_MBDRC_CFG_RMS_OFFSET_SHIFT, 0x1ff, 0,549 tegra210_mbdrc_get, tegra210_mbdrc_put),550 551 SOC_SINGLE_EXT("MBDRC Shift Control", TEGRA210_MBDRC_CFG,552 TEGRA210_MBDRC_CFG_SHIFT_CTRL_SHIFT, 0x1f, 0,553 tegra210_mbdrc_get, tegra210_mbdrc_put),554 555 SOC_SINGLE_EXT("MBDRC Fast Attack Factor", TEGRA210_MBDRC_FAST_FACTOR,556 TEGRA210_MBDRC_FAST_FACTOR_ATTACK_SHIFT, 0xffff, 0,557 tegra210_mbdrc_get, tegra210_mbdrc_put),558 559 SOC_SINGLE_EXT("MBDRC Fast Release Factor", TEGRA210_MBDRC_FAST_FACTOR,560 TEGRA210_MBDRC_FAST_FACTOR_RELEASE_SHIFT, 0xffff, 0,561 tegra210_mbdrc_get, tegra210_mbdrc_put),562 563 SOC_SINGLE_RANGE_EXT_TLV("MBDRC Master Volume",564 TEGRA210_MBDRC_MASTER_VOL,565 TEGRA210_MBDRC_MASTER_VOL_SHIFT,566 0, 0x1ff, 0,567 tegra210_mbdrc_vol_get, tegra210_mbdrc_vol_put,568 mdbrc_vol_tlv),569 570 TEGRA_SOC_BYTES_EXT("MBDRC IIR Stages", TEGRA210_MBDRC_IIR_CFG,571 TEGRA210_MBDRC_FILTER_COUNT,572 TEGRA210_MBDRC_IIR_CFG_NUM_STAGES_SHIFT,573 TEGRA210_MBDRC_IIR_CFG_NUM_STAGES_MASK,574 tegra210_mbdrc_band_params_get,575 tegra210_mbdrc_band_params_put,576 tegra210_mbdrc_param_info),577 578 TEGRA_SOC_BYTES_EXT("MBDRC In Attack Time Const", TEGRA210_MBDRC_IN_ATTACK,579 TEGRA210_MBDRC_FILTER_COUNT,580 TEGRA210_MBDRC_IN_ATTACK_TC_SHIFT,581 TEGRA210_MBDRC_IN_ATTACK_TC_MASK,582 tegra210_mbdrc_band_params_get,583 tegra210_mbdrc_band_params_put,584 tegra210_mbdrc_param_info),585 586 TEGRA_SOC_BYTES_EXT("MBDRC In Release Time Const", TEGRA210_MBDRC_IN_RELEASE,587 TEGRA210_MBDRC_FILTER_COUNT,588 TEGRA210_MBDRC_IN_RELEASE_TC_SHIFT,589 TEGRA210_MBDRC_IN_RELEASE_TC_MASK,590 tegra210_mbdrc_band_params_get,591 tegra210_mbdrc_band_params_put,592 tegra210_mbdrc_param_info),593 594 TEGRA_SOC_BYTES_EXT("MBDRC Fast Attack Time Const", TEGRA210_MBDRC_FAST_ATTACK,595 TEGRA210_MBDRC_FILTER_COUNT,596 TEGRA210_MBDRC_FAST_ATTACK_TC_SHIFT,597 TEGRA210_MBDRC_FAST_ATTACK_TC_MASK,598 tegra210_mbdrc_band_params_get,599 tegra210_mbdrc_band_params_put,600 tegra210_mbdrc_param_info),601 602 TEGRA_SOC_BYTES_EXT("MBDRC In Threshold", TEGRA210_MBDRC_IN_THRESHOLD,603 TEGRA210_MBDRC_FILTER_COUNT * 4, 0, 0xffffffff,604 tegra210_mbdrc_threshold_get,605 tegra210_mbdrc_threshold_put,606 tegra210_mbdrc_param_info),607 608 TEGRA_SOC_BYTES_EXT("MBDRC Out Threshold", TEGRA210_MBDRC_OUT_THRESHOLD,609 TEGRA210_MBDRC_FILTER_COUNT * 4, 0, 0xffffffff,610 tegra210_mbdrc_threshold_get,611 tegra210_mbdrc_threshold_put,612 tegra210_mbdrc_param_info),613 614 TEGRA_SOC_BYTES_EXT("MBDRC Ratio", TEGRA210_MBDRC_RATIO_1ST,615 TEGRA210_MBDRC_FILTER_COUNT * 5,616 TEGRA210_MBDRC_RATIO_1ST_SHIFT, TEGRA210_MBDRC_RATIO_1ST_MASK,617 tegra210_mbdrc_band_params_get,618 tegra210_mbdrc_band_params_put,619 tegra210_mbdrc_param_info),620 621 TEGRA_SOC_BYTES_EXT("MBDRC Makeup Gain", TEGRA210_MBDRC_MAKEUP_GAIN,622 TEGRA210_MBDRC_FILTER_COUNT,623 TEGRA210_MBDRC_MAKEUP_GAIN_SHIFT,624 TEGRA210_MBDRC_MAKEUP_GAIN_MASK,625 tegra210_mbdrc_band_params_get,626 tegra210_mbdrc_band_params_put,627 tegra210_mbdrc_param_info),628 629 TEGRA_SOC_BYTES_EXT("MBDRC Init Gain", TEGRA210_MBDRC_INIT_GAIN,630 TEGRA210_MBDRC_FILTER_COUNT,631 TEGRA210_MBDRC_INIT_GAIN_SHIFT,632 TEGRA210_MBDRC_INIT_GAIN_MASK,633 tegra210_mbdrc_band_params_get,634 tegra210_mbdrc_band_params_put,635 tegra210_mbdrc_param_info),636 637 TEGRA_SOC_BYTES_EXT("MBDRC Attack Gain", TEGRA210_MBDRC_GAIN_ATTACK,638 TEGRA210_MBDRC_FILTER_COUNT,639 TEGRA210_MBDRC_GAIN_ATTACK_SHIFT,640 TEGRA210_MBDRC_GAIN_ATTACK_MASK,641 tegra210_mbdrc_band_params_get,642 tegra210_mbdrc_band_params_put,643 tegra210_mbdrc_param_info),644 645 TEGRA_SOC_BYTES_EXT("MBDRC Release Gain", TEGRA210_MBDRC_GAIN_RELEASE,646 TEGRA210_MBDRC_FILTER_COUNT,647 TEGRA210_MBDRC_GAIN_RELEASE_SHIFT,648 TEGRA210_MBDRC_GAIN_RELEASE_MASK,649 tegra210_mbdrc_band_params_get,650 tegra210_mbdrc_band_params_put,651 tegra210_mbdrc_param_info),652 653 TEGRA_SOC_BYTES_EXT("MBDRC Fast Release Gain",654 TEGRA210_MBDRC_FAST_RELEASE,655 TEGRA210_MBDRC_FILTER_COUNT,656 TEGRA210_MBDRC_FAST_RELEASE_SHIFT,657 TEGRA210_MBDRC_FAST_RELEASE_MASK,658 tegra210_mbdrc_band_params_get,659 tegra210_mbdrc_band_params_put,660 tegra210_mbdrc_param_info),661 662 TEGRA_SOC_BYTES_EXT("MBDRC Low Band Biquad Coeffs",663 TEGRA210_MBDRC_CFG_RAM_CTRL,664 TEGRA210_MBDRC_MAX_BIQUAD_STAGES * 5, 0, 0xffffffff,665 tegra210_mbdrc_biquad_coeffs_get,666 tegra210_mbdrc_biquad_coeffs_put,667 tegra210_mbdrc_param_info),668 669 TEGRA_SOC_BYTES_EXT("MBDRC Mid Band Biquad Coeffs",670 TEGRA210_MBDRC_CFG_RAM_CTRL +671 TEGRA210_MBDRC_FILTER_PARAM_STRIDE,672 TEGRA210_MBDRC_MAX_BIQUAD_STAGES * 5, 0, 0xffffffff,673 tegra210_mbdrc_biquad_coeffs_get,674 tegra210_mbdrc_biquad_coeffs_put,675 tegra210_mbdrc_param_info),676 677 TEGRA_SOC_BYTES_EXT("MBDRC High Band Biquad Coeffs",678 TEGRA210_MBDRC_CFG_RAM_CTRL +679 (TEGRA210_MBDRC_FILTER_PARAM_STRIDE * 2),680 TEGRA210_MBDRC_MAX_BIQUAD_STAGES * 5, 0, 0xffffffff,681 tegra210_mbdrc_biquad_coeffs_get,682 tegra210_mbdrc_biquad_coeffs_put,683 tegra210_mbdrc_param_info),684};685 686static bool tegra210_mbdrc_wr_reg(struct device *dev, unsigned int reg)687{688 if (reg >= TEGRA210_MBDRC_IIR_CFG)689 reg -= ((reg - TEGRA210_MBDRC_IIR_CFG) %690 (TEGRA210_MBDRC_FILTER_PARAM_STRIDE *691 TEGRA210_MBDRC_FILTER_COUNT));692 693 switch (reg) {694 case TEGRA210_MBDRC_SOFT_RESET:695 case TEGRA210_MBDRC_CG:696 case TEGRA210_MBDRC_CFG ... TEGRA210_MBDRC_CFG_RAM_DATA:697 return true;698 default:699 return false;700 }701}702 703static bool tegra210_mbdrc_rd_reg(struct device *dev, unsigned int reg)704{705 if (tegra210_mbdrc_wr_reg(dev, reg))706 return true;707 708 if (reg >= TEGRA210_MBDRC_IIR_CFG)709 reg -= ((reg - TEGRA210_MBDRC_IIR_CFG) %710 (TEGRA210_MBDRC_FILTER_PARAM_STRIDE *711 TEGRA210_MBDRC_FILTER_COUNT));712 713 switch (reg) {714 case TEGRA210_MBDRC_STATUS:715 return true;716 default:717 return false;718 }719}720 721static bool tegra210_mbdrc_volatile_reg(struct device *dev, unsigned int reg)722{723 if (reg >= TEGRA210_MBDRC_IIR_CFG)724 reg -= ((reg - TEGRA210_MBDRC_IIR_CFG) %725 (TEGRA210_MBDRC_FILTER_PARAM_STRIDE *726 TEGRA210_MBDRC_FILTER_COUNT));727 728 switch (reg) {729 case TEGRA210_MBDRC_SOFT_RESET:730 case TEGRA210_MBDRC_STATUS:731 case TEGRA210_MBDRC_CFG_RAM_CTRL:732 case TEGRA210_MBDRC_CFG_RAM_DATA:733 return true;734 default:735 return false;736 }737}738 739static bool tegra210_mbdrc_precious_reg(struct device *dev, unsigned int reg)740{741 if (reg >= TEGRA210_MBDRC_IIR_CFG)742 reg -= ((reg - TEGRA210_MBDRC_IIR_CFG) %743 (TEGRA210_MBDRC_FILTER_PARAM_STRIDE *744 TEGRA210_MBDRC_FILTER_COUNT));745 746 switch (reg) {747 case TEGRA210_MBDRC_CFG_RAM_DATA:748 return true;749 default:750 return false;751 }752}753 754static const struct regmap_config tegra210_mbdrc_regmap_cfg = {755 .name = "mbdrc",756 .reg_bits = 32,757 .reg_stride = 4,758 .val_bits = 32,759 .max_register = TEGRA210_MBDRC_MAX_REG,760 .writeable_reg = tegra210_mbdrc_wr_reg,761 .readable_reg = tegra210_mbdrc_rd_reg,762 .volatile_reg = tegra210_mbdrc_volatile_reg,763 .precious_reg = tegra210_mbdrc_precious_reg,764 .reg_defaults = tegra210_mbdrc_reg_defaults,765 .num_reg_defaults = ARRAY_SIZE(tegra210_mbdrc_reg_defaults),766 .cache_type = REGCACHE_FLAT,767};768 769int tegra210_mbdrc_hw_params(struct snd_soc_component *cmpnt)770{771 struct tegra210_ope *ope = snd_soc_component_get_drvdata(cmpnt);772 const struct tegra210_mbdrc_config *conf = &mbdrc_init_config;773 u32 val = 0;774 unsigned int i;775 776 regmap_read(ope->mbdrc_regmap, TEGRA210_MBDRC_CFG, &val);777 778 val &= TEGRA210_MBDRC_CFG_MBDRC_MODE_MASK;779 780 if (val == TEGRA210_MBDRC_CFG_MBDRC_MODE_BYPASS)781 return 0;782 783 for (i = 0; i < MBDRC_NUM_BAND; i++) {784 const struct tegra210_mbdrc_band_params *params =785 &conf->band_params[i];786 787 u32 reg_off = i * TEGRA210_MBDRC_FILTER_PARAM_STRIDE;788 789 tegra210_mbdrc_write_ram(ope->mbdrc_regmap,790 reg_off + TEGRA210_MBDRC_CFG_RAM_CTRL,791 reg_off + TEGRA210_MBDRC_CFG_RAM_DATA,792 0, (u32 *)¶ms->biquad_params[0],793 TEGRA210_MBDRC_MAX_BIQUAD_STAGES * 5);794 }795 return 0;796}797 798int tegra210_mbdrc_component_init(struct snd_soc_component *cmpnt)799{800 struct tegra210_ope *ope = snd_soc_component_get_drvdata(cmpnt);801 const struct tegra210_mbdrc_config *conf = &mbdrc_init_config;802 unsigned int i;803 u32 val;804 805 pm_runtime_get_sync(cmpnt->dev);806 807 /* Initialize MBDRC registers and AHUB RAM with default params */808 regmap_update_bits(ope->mbdrc_regmap, TEGRA210_MBDRC_CFG,809 TEGRA210_MBDRC_CFG_MBDRC_MODE_MASK,810 conf->mode << TEGRA210_MBDRC_CFG_MBDRC_MODE_SHIFT);811 812 regmap_update_bits(ope->mbdrc_regmap, TEGRA210_MBDRC_CFG,813 TEGRA210_MBDRC_CFG_RMS_OFFSET_MASK,814 conf->rms_off << TEGRA210_MBDRC_CFG_RMS_OFFSET_SHIFT);815 816 regmap_update_bits(ope->mbdrc_regmap, TEGRA210_MBDRC_CFG,817 TEGRA210_MBDRC_CFG_PEAK_RMS_MASK,818 conf->peak_rms_mode << TEGRA210_MBDRC_CFG_PEAK_RMS_SHIFT);819 820 regmap_update_bits(ope->mbdrc_regmap, TEGRA210_MBDRC_CFG,821 TEGRA210_MBDRC_CFG_FILTER_STRUCTURE_MASK,822 conf->filter_structure <<823 TEGRA210_MBDRC_CFG_FILTER_STRUCTURE_SHIFT);824 825 regmap_update_bits(ope->mbdrc_regmap, TEGRA210_MBDRC_CFG,826 TEGRA210_MBDRC_CFG_SHIFT_CTRL_MASK,827 conf->shift_ctrl << TEGRA210_MBDRC_CFG_SHIFT_CTRL_SHIFT);828 829 regmap_update_bits(ope->mbdrc_regmap, TEGRA210_MBDRC_CFG,830 TEGRA210_MBDRC_CFG_FRAME_SIZE_MASK,831 __ffs(conf->frame_size) <<832 TEGRA210_MBDRC_CFG_FRAME_SIZE_SHIFT);833 834 regmap_update_bits(ope->mbdrc_regmap, TEGRA210_MBDRC_CHANNEL_MASK,835 TEGRA210_MBDRC_CHANNEL_MASK_MASK,836 conf->channel_mask << TEGRA210_MBDRC_CHANNEL_MASK_SHIFT);837 838 regmap_update_bits(ope->mbdrc_regmap, TEGRA210_MBDRC_FAST_FACTOR,839 TEGRA210_MBDRC_FAST_FACTOR_ATTACK_MASK,840 conf->fa_factor << TEGRA210_MBDRC_FAST_FACTOR_ATTACK_SHIFT);841 842 regmap_update_bits(ope->mbdrc_regmap, TEGRA210_MBDRC_FAST_FACTOR,843 TEGRA210_MBDRC_FAST_FACTOR_ATTACK_MASK,844 conf->fr_factor << TEGRA210_MBDRC_FAST_FACTOR_ATTACK_SHIFT);845 846 for (i = 0; i < MBDRC_NUM_BAND; i++) {847 const struct tegra210_mbdrc_band_params *params =848 &conf->band_params[i];849 u32 reg_off = i * TEGRA210_MBDRC_FILTER_PARAM_STRIDE;850 851 regmap_update_bits(ope->mbdrc_regmap,852 reg_off + TEGRA210_MBDRC_IIR_CFG,853 TEGRA210_MBDRC_IIR_CFG_NUM_STAGES_MASK,854 params->iir_stages <<855 TEGRA210_MBDRC_IIR_CFG_NUM_STAGES_SHIFT);856 857 regmap_update_bits(ope->mbdrc_regmap,858 reg_off + TEGRA210_MBDRC_IN_ATTACK,859 TEGRA210_MBDRC_IN_ATTACK_TC_MASK,860 params->in_attack_tc <<861 TEGRA210_MBDRC_IN_ATTACK_TC_SHIFT);862 863 regmap_update_bits(ope->mbdrc_regmap,864 reg_off + TEGRA210_MBDRC_IN_RELEASE,865 TEGRA210_MBDRC_IN_RELEASE_TC_MASK,866 params->in_release_tc <<867 TEGRA210_MBDRC_IN_RELEASE_TC_SHIFT);868 869 regmap_update_bits(ope->mbdrc_regmap,870 reg_off + TEGRA210_MBDRC_FAST_ATTACK,871 TEGRA210_MBDRC_FAST_ATTACK_TC_MASK,872 params->fast_attack_tc <<873 TEGRA210_MBDRC_FAST_ATTACK_TC_SHIFT);874 875 val = (((params->in_threshold[0] >>876 TEGRA210_MBDRC_THRESH_1ST_SHIFT) &877 TEGRA210_MBDRC_THRESH_1ST_MASK) |878 ((params->in_threshold[1] >>879 TEGRA210_MBDRC_THRESH_2ND_SHIFT) &880 TEGRA210_MBDRC_THRESH_2ND_MASK) |881 ((params->in_threshold[2] >>882 TEGRA210_MBDRC_THRESH_3RD_SHIFT) &883 TEGRA210_MBDRC_THRESH_3RD_MASK) |884 ((params->in_threshold[3] >>885 TEGRA210_MBDRC_THRESH_4TH_SHIFT) &886 TEGRA210_MBDRC_THRESH_4TH_MASK));887 888 regmap_update_bits(ope->mbdrc_regmap,889 reg_off + TEGRA210_MBDRC_IN_THRESHOLD,890 0xffffffff, val);891 892 val = (((params->out_threshold[0] >>893 TEGRA210_MBDRC_THRESH_1ST_SHIFT) &894 TEGRA210_MBDRC_THRESH_1ST_MASK) |895 ((params->out_threshold[1] >>896 TEGRA210_MBDRC_THRESH_2ND_SHIFT) &897 TEGRA210_MBDRC_THRESH_2ND_MASK) |898 ((params->out_threshold[2] >>899 TEGRA210_MBDRC_THRESH_3RD_SHIFT) &900 TEGRA210_MBDRC_THRESH_3RD_MASK) |901 ((params->out_threshold[3] >>902 TEGRA210_MBDRC_THRESH_4TH_SHIFT) &903 TEGRA210_MBDRC_THRESH_4TH_MASK));904 905 regmap_update_bits(ope->mbdrc_regmap,906 reg_off + TEGRA210_MBDRC_OUT_THRESHOLD,907 0xffffffff, val);908 909 regmap_update_bits(ope->mbdrc_regmap,910 reg_off + TEGRA210_MBDRC_RATIO_1ST,911 TEGRA210_MBDRC_RATIO_1ST_MASK,912 params->ratio[0] << TEGRA210_MBDRC_RATIO_1ST_SHIFT);913 914 regmap_update_bits(ope->mbdrc_regmap,915 reg_off + TEGRA210_MBDRC_RATIO_2ND,916 TEGRA210_MBDRC_RATIO_2ND_MASK,917 params->ratio[1] << TEGRA210_MBDRC_RATIO_2ND_SHIFT);918 919 regmap_update_bits(ope->mbdrc_regmap,920 reg_off + TEGRA210_MBDRC_RATIO_3RD,921 TEGRA210_MBDRC_RATIO_3RD_MASK,922 params->ratio[2] << TEGRA210_MBDRC_RATIO_3RD_SHIFT);923 924 regmap_update_bits(ope->mbdrc_regmap,925 reg_off + TEGRA210_MBDRC_RATIO_4TH,926 TEGRA210_MBDRC_RATIO_4TH_MASK,927 params->ratio[3] << TEGRA210_MBDRC_RATIO_4TH_SHIFT);928 929 regmap_update_bits(ope->mbdrc_regmap,930 reg_off + TEGRA210_MBDRC_RATIO_5TH,931 TEGRA210_MBDRC_RATIO_5TH_MASK,932 params->ratio[4] << TEGRA210_MBDRC_RATIO_5TH_SHIFT);933 934 regmap_update_bits(ope->mbdrc_regmap,935 reg_off + TEGRA210_MBDRC_MAKEUP_GAIN,936 TEGRA210_MBDRC_MAKEUP_GAIN_MASK,937 params->makeup_gain <<938 TEGRA210_MBDRC_MAKEUP_GAIN_SHIFT);939 940 regmap_update_bits(ope->mbdrc_regmap,941 reg_off + TEGRA210_MBDRC_INIT_GAIN,942 TEGRA210_MBDRC_INIT_GAIN_MASK,943 params->gain_init <<944 TEGRA210_MBDRC_INIT_GAIN_SHIFT);945 946 regmap_update_bits(ope->mbdrc_regmap,947 reg_off + TEGRA210_MBDRC_GAIN_ATTACK,948 TEGRA210_MBDRC_GAIN_ATTACK_MASK,949 params->gain_attack_tc <<950 TEGRA210_MBDRC_GAIN_ATTACK_SHIFT);951 952 regmap_update_bits(ope->mbdrc_regmap,953 reg_off + TEGRA210_MBDRC_GAIN_RELEASE,954 TEGRA210_MBDRC_GAIN_RELEASE_MASK,955 params->gain_release_tc <<956 TEGRA210_MBDRC_GAIN_RELEASE_SHIFT);957 958 regmap_update_bits(ope->mbdrc_regmap,959 reg_off + TEGRA210_MBDRC_FAST_RELEASE,960 TEGRA210_MBDRC_FAST_RELEASE_MASK,961 params->fast_release_tc <<962 TEGRA210_MBDRC_FAST_RELEASE_SHIFT);963 964 tegra210_mbdrc_write_ram(ope->mbdrc_regmap,965 reg_off + TEGRA210_MBDRC_CFG_RAM_CTRL,966 reg_off + TEGRA210_MBDRC_CFG_RAM_DATA, 0,967 (u32 *)¶ms->biquad_params[0],968 TEGRA210_MBDRC_MAX_BIQUAD_STAGES * 5);969 }970 971 pm_runtime_put_sync(cmpnt->dev);972 973 snd_soc_add_component_controls(cmpnt, tegra210_mbdrc_controls,974 ARRAY_SIZE(tegra210_mbdrc_controls));975 976 return 0;977}978 979int tegra210_mbdrc_regmap_init(struct platform_device *pdev)980{981 struct device *dev = &pdev->dev;982 struct tegra210_ope *ope = dev_get_drvdata(dev);983 struct device_node *child;984 struct resource mem;985 void __iomem *regs;986 int err;987 988 child = of_get_child_by_name(dev->of_node, "dynamic-range-compressor");989 if (!child)990 return -ENODEV;991 992 err = of_address_to_resource(child, 0, &mem);993 of_node_put(child);994 if (err < 0) {995 dev_err(dev, "fail to get MBDRC resource\n");996 return err;997 }998 999 mem.flags = IORESOURCE_MEM;1000 regs = devm_ioremap_resource(dev, &mem);1001 if (IS_ERR(regs))1002 return PTR_ERR(regs);1003 1004 ope->mbdrc_regmap = devm_regmap_init_mmio(dev, regs,1005 &tegra210_mbdrc_regmap_cfg);1006 if (IS_ERR(ope->mbdrc_regmap)) {1007 dev_err(dev, "regmap init failed\n");1008 return PTR_ERR(ope->mbdrc_regmap);1009 }1010 1011 regcache_cache_only(ope->mbdrc_regmap, true);1012 1013 return 0;1014}1015