| 1 | // SPDX-License-Identifier: GPL-2.0-only |
| 2 | // |
| 3 | // tegra210_mbdrc.c - Tegra210 MBDRC driver |
| 4 | // |
| 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 | |
| 42 | static 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 */ |
| 53 | static 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 | |
| 215 | static 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(map: regmap, reg: reg_ctrl, val); |
| 228 | |
| 229 | for (i = 0; i < size; i++) |
| 230 | regmap_write(map: regmap, reg: reg_data, val: data[i]); |
| 231 | } |
| 232 | |
| 233 | static 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_kcontrol_chip(kcontrol); |
| 239 | struct tegra210_ope *ope = snd_soc_component_get_drvdata(c: cmpnt); |
| 240 | unsigned int val; |
| 241 | |
| 242 | regmap_read(map: ope->mbdrc_regmap, reg: mc->reg, val: &val); |
| 243 | |
| 244 | ucontrol->value.integer.value[0] = (val >> mc->shift) & mc->max; |
| 245 | |
| 246 | return 0; |
| 247 | } |
| 248 | |
| 249 | static 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_kcontrol_chip(kcontrol); |
| 255 | struct tegra210_ope *ope = snd_soc_component_get_drvdata(c: 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(map: ope->mbdrc_regmap, reg: mc->reg, |
| 262 | mask: (mc->max << mc->shift), val, change: &change); |
| 263 | |
| 264 | return change ? 1 : 0; |
| 265 | } |
| 266 | |
| 267 | static int tegra210_mbdrc_get_enum(struct snd_kcontrol *kcontrol, |
| 268 | struct snd_ctl_elem_value *ucontrol) |
| 269 | { |
| 270 | struct snd_soc_component *cmpnt = snd_kcontrol_chip(kcontrol); |
| 271 | struct tegra210_ope *ope = snd_soc_component_get_drvdata(c: cmpnt); |
| 272 | struct soc_enum *e = (struct soc_enum *)kcontrol->private_value; |
| 273 | unsigned int val; |
| 274 | |
| 275 | regmap_read(map: ope->mbdrc_regmap, reg: e->reg, val: &val); |
| 276 | |
| 277 | ucontrol->value.enumerated.item[0] = (val >> e->shift_l) & e->mask; |
| 278 | |
| 279 | return 0; |
| 280 | } |
| 281 | |
| 282 | static int tegra210_mbdrc_put_enum(struct snd_kcontrol *kcontrol, |
| 283 | struct snd_ctl_elem_value *ucontrol) |
| 284 | { |
| 285 | struct snd_soc_component *cmpnt = snd_kcontrol_chip(kcontrol); |
| 286 | struct tegra210_ope *ope = snd_soc_component_get_drvdata(c: 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(map: ope->mbdrc_regmap, reg: e->reg, mask, val, |
| 299 | change: &change); |
| 300 | |
| 301 | return change ? 1 : 0; |
| 302 | } |
| 303 | |
| 304 | static 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_kcontrol_chip(kcontrol); |
| 309 | struct tegra210_ope *ope = snd_soc_component_get_drvdata(c: 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(map: ope->mbdrc_regmap, reg: regs, val: &data[i]); |
| 318 | |
| 319 | data[i] = ((data[i] & mask) >> shift); |
| 320 | } |
| 321 | |
| 322 | return 0; |
| 323 | } |
| 324 | |
| 325 | static 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_kcontrol_chip(kcontrol); |
| 330 | struct tegra210_ope *ope = snd_soc_component_get_drvdata(c: 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(map: ope->mbdrc_regmap, reg: regs, mask, |
| 342 | val: data[i] << shift, change: &update); |
| 343 | |
| 344 | change |= update; |
| 345 | } |
| 346 | |
| 347 | return change ? 1 : 0; |
| 348 | } |
| 349 | |
| 350 | static 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_kcontrol_chip(kcontrol); |
| 355 | struct tegra210_ope *ope = snd_soc_component_get_drvdata(c: 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(map: ope->mbdrc_regmap, reg: regs, val: &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 | |
| 378 | static 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_kcontrol_chip(kcontrol); |
| 383 | struct tegra210_ope *ope = snd_soc_component_get_drvdata(c: 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(map: ope->mbdrc_regmap, reg: regs, mask: 0xffffffff, |
| 403 | val: data[i], change: &update); |
| 404 | |
| 405 | change |= update; |
| 406 | } |
| 407 | |
| 408 | return change ? 1 : 0; |
| 409 | } |
| 410 | |
| 411 | static 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_kcontrol_chip(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 | |
| 423 | static 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_kcontrol_chip(kcontrol); |
| 428 | struct tegra210_ope *ope = snd_soc_component_get_drvdata(c: 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(regmap: ope->mbdrc_regmap, reg_ctrl, reg_data, |
| 434 | ram_offset: params->shift, data, size: params->soc.num_regs); |
| 435 | |
| 436 | return 1; |
| 437 | } |
| 438 | |
| 439 | static 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 | |
| 450 | static 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_kcontrol_chip(kcontrol); |
| 456 | struct tegra210_ope *ope = snd_soc_component_get_drvdata(c: cmpnt); |
| 457 | int val; |
| 458 | |
| 459 | regmap_read(map: ope->mbdrc_regmap, reg: mc->reg, val: &val); |
| 460 | |
| 461 | ucontrol->value.integer.value[0] = |
| 462 | ((val >> mc->shift) - TEGRA210_MBDRC_MASTER_VOL_MIN); |
| 463 | |
| 464 | return 0; |
| 465 | } |
| 466 | |
| 467 | static 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_kcontrol_chip(kcontrol); |
| 473 | struct tegra210_ope *ope = snd_soc_component_get_drvdata(c: 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(map: ope->mbdrc_regmap, reg: mc->reg, |
| 480 | mask: mc->max << mc->shift, val: val << mc->shift, |
| 481 | change: &change); |
| 482 | |
| 483 | regmap_read(map: ope->mbdrc_regmap, reg: mc->reg, val: &val); |
| 484 | |
| 485 | return change ? 1 : 0; |
| 486 | } |
| 487 | |
| 488 | static const char * const tegra210_mbdrc_mode_text[] = { |
| 489 | "Bypass" , "Fullband" , "Dualband" , "Multiband" |
| 490 | }; |
| 491 | |
| 492 | static 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 | |
| 496 | static const char * const tegra210_mbdrc_peak_rms_text[] = { |
| 497 | "Peak" , "RMS" |
| 498 | }; |
| 499 | |
| 500 | static 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 | |
| 504 | static const char * const tegra210_mbdrc_filter_structure_text[] = { |
| 505 | "All-pass-tree" , "Flexible" |
| 506 | }; |
| 507 | |
| 508 | static 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 | |
| 513 | static const char * const tegra210_mbdrc_frame_size_text[] = { |
| 514 | "N1" , "N2" , "N4" , "N8" , "N16" , "N32" , "N64" |
| 515 | }; |
| 516 | |
| 517 | static 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 | |
| 531 | static const DECLARE_TLV_DB_MINMAX(mdbrc_vol_tlv, -25600, 25500); |
| 532 | |
| 533 | static 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 | |
| 686 | static 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 | |
| 703 | static 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 | |
| 721 | static 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 | |
| 739 | static 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 | |
| 754 | static 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 | |
| 769 | int tegra210_mbdrc_hw_params(struct snd_soc_component *cmpnt) |
| 770 | { |
| 771 | struct tegra210_ope *ope = snd_soc_component_get_drvdata(c: cmpnt); |
| 772 | const struct tegra210_mbdrc_config *conf = &mbdrc_init_config; |
| 773 | u32 val = 0; |
| 774 | unsigned int i; |
| 775 | |
| 776 | regmap_read(map: ope->mbdrc_regmap, TEGRA210_MBDRC_CFG, val: &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(regmap: ope->mbdrc_regmap, |
| 790 | reg_ctrl: reg_off + TEGRA210_MBDRC_CFG_RAM_CTRL, |
| 791 | reg_data: reg_off + TEGRA210_MBDRC_CFG_RAM_DATA, |
| 792 | ram_offset: 0, data: (u32 *)¶ms->biquad_params[0], |
| 793 | TEGRA210_MBDRC_MAX_BIQUAD_STAGES * 5); |
| 794 | } |
| 795 | return 0; |
| 796 | } |
| 797 | |
| 798 | int tegra210_mbdrc_component_init(struct snd_soc_component *cmpnt) |
| 799 | { |
| 800 | struct tegra210_ope *ope = snd_soc_component_get_drvdata(c: cmpnt); |
| 801 | const struct tegra210_mbdrc_config *conf = &mbdrc_init_config; |
| 802 | unsigned int i; |
| 803 | u32 val; |
| 804 | |
| 805 | pm_runtime_get_sync(dev: cmpnt->dev); |
| 806 | |
| 807 | /* Initialize MBDRC registers and AHUB RAM with default params */ |
| 808 | regmap_update_bits(map: ope->mbdrc_regmap, TEGRA210_MBDRC_CFG, |
| 809 | TEGRA210_MBDRC_CFG_MBDRC_MODE_MASK, |
| 810 | val: conf->mode << TEGRA210_MBDRC_CFG_MBDRC_MODE_SHIFT); |
| 811 | |
| 812 | regmap_update_bits(map: ope->mbdrc_regmap, TEGRA210_MBDRC_CFG, |
| 813 | TEGRA210_MBDRC_CFG_RMS_OFFSET_MASK, |
| 814 | val: conf->rms_off << TEGRA210_MBDRC_CFG_RMS_OFFSET_SHIFT); |
| 815 | |
| 816 | regmap_update_bits(map: ope->mbdrc_regmap, TEGRA210_MBDRC_CFG, |
| 817 | TEGRA210_MBDRC_CFG_PEAK_RMS_MASK, |
| 818 | val: conf->peak_rms_mode << TEGRA210_MBDRC_CFG_PEAK_RMS_SHIFT); |
| 819 | |
| 820 | regmap_update_bits(map: ope->mbdrc_regmap, TEGRA210_MBDRC_CFG, |
| 821 | TEGRA210_MBDRC_CFG_FILTER_STRUCTURE_MASK, |
| 822 | val: conf->filter_structure << |
| 823 | TEGRA210_MBDRC_CFG_FILTER_STRUCTURE_SHIFT); |
| 824 | |
| 825 | regmap_update_bits(map: ope->mbdrc_regmap, TEGRA210_MBDRC_CFG, |
| 826 | TEGRA210_MBDRC_CFG_SHIFT_CTRL_MASK, |
| 827 | val: conf->shift_ctrl << TEGRA210_MBDRC_CFG_SHIFT_CTRL_SHIFT); |
| 828 | |
| 829 | regmap_update_bits(map: 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(map: ope->mbdrc_regmap, TEGRA210_MBDRC_CHANNEL_MASK, |
| 835 | TEGRA210_MBDRC_CHANNEL_MASK_MASK, |
| 836 | val: conf->channel_mask << TEGRA210_MBDRC_CHANNEL_MASK_SHIFT); |
| 837 | |
| 838 | regmap_update_bits(map: ope->mbdrc_regmap, TEGRA210_MBDRC_FAST_FACTOR, |
| 839 | TEGRA210_MBDRC_FAST_FACTOR_ATTACK_MASK, |
| 840 | val: conf->fa_factor << TEGRA210_MBDRC_FAST_FACTOR_ATTACK_SHIFT); |
| 841 | |
| 842 | regmap_update_bits(map: ope->mbdrc_regmap, TEGRA210_MBDRC_FAST_FACTOR, |
| 843 | TEGRA210_MBDRC_FAST_FACTOR_ATTACK_MASK, |
| 844 | val: 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(map: ope->mbdrc_regmap, |
| 852 | reg: reg_off + TEGRA210_MBDRC_IIR_CFG, |
| 853 | TEGRA210_MBDRC_IIR_CFG_NUM_STAGES_MASK, |
| 854 | val: params->iir_stages << |
| 855 | TEGRA210_MBDRC_IIR_CFG_NUM_STAGES_SHIFT); |
| 856 | |
| 857 | regmap_update_bits(map: ope->mbdrc_regmap, |
| 858 | reg: reg_off + TEGRA210_MBDRC_IN_ATTACK, |
| 859 | TEGRA210_MBDRC_IN_ATTACK_TC_MASK, |
| 860 | val: params->in_attack_tc << |
| 861 | TEGRA210_MBDRC_IN_ATTACK_TC_SHIFT); |
| 862 | |
| 863 | regmap_update_bits(map: ope->mbdrc_regmap, |
| 864 | reg: reg_off + TEGRA210_MBDRC_IN_RELEASE, |
| 865 | TEGRA210_MBDRC_IN_RELEASE_TC_MASK, |
| 866 | val: params->in_release_tc << |
| 867 | TEGRA210_MBDRC_IN_RELEASE_TC_SHIFT); |
| 868 | |
| 869 | regmap_update_bits(map: ope->mbdrc_regmap, |
| 870 | reg: reg_off + TEGRA210_MBDRC_FAST_ATTACK, |
| 871 | TEGRA210_MBDRC_FAST_ATTACK_TC_MASK, |
| 872 | val: 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(map: ope->mbdrc_regmap, |
| 889 | reg: reg_off + TEGRA210_MBDRC_IN_THRESHOLD, |
| 890 | mask: 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(map: ope->mbdrc_regmap, |
| 906 | reg: reg_off + TEGRA210_MBDRC_OUT_THRESHOLD, |
| 907 | mask: 0xffffffff, val); |
| 908 | |
| 909 | regmap_update_bits(map: ope->mbdrc_regmap, |
| 910 | reg: reg_off + TEGRA210_MBDRC_RATIO_1ST, |
| 911 | TEGRA210_MBDRC_RATIO_1ST_MASK, |
| 912 | val: params->ratio[0] << TEGRA210_MBDRC_RATIO_1ST_SHIFT); |
| 913 | |
| 914 | regmap_update_bits(map: ope->mbdrc_regmap, |
| 915 | reg: reg_off + TEGRA210_MBDRC_RATIO_2ND, |
| 916 | TEGRA210_MBDRC_RATIO_2ND_MASK, |
| 917 | val: params->ratio[1] << TEGRA210_MBDRC_RATIO_2ND_SHIFT); |
| 918 | |
| 919 | regmap_update_bits(map: ope->mbdrc_regmap, |
| 920 | reg: reg_off + TEGRA210_MBDRC_RATIO_3RD, |
| 921 | TEGRA210_MBDRC_RATIO_3RD_MASK, |
| 922 | val: params->ratio[2] << TEGRA210_MBDRC_RATIO_3RD_SHIFT); |
| 923 | |
| 924 | regmap_update_bits(map: ope->mbdrc_regmap, |
| 925 | reg: reg_off + TEGRA210_MBDRC_RATIO_4TH, |
| 926 | TEGRA210_MBDRC_RATIO_4TH_MASK, |
| 927 | val: params->ratio[3] << TEGRA210_MBDRC_RATIO_4TH_SHIFT); |
| 928 | |
| 929 | regmap_update_bits(map: ope->mbdrc_regmap, |
| 930 | reg: reg_off + TEGRA210_MBDRC_RATIO_5TH, |
| 931 | TEGRA210_MBDRC_RATIO_5TH_MASK, |
| 932 | val: params->ratio[4] << TEGRA210_MBDRC_RATIO_5TH_SHIFT); |
| 933 | |
| 934 | regmap_update_bits(map: ope->mbdrc_regmap, |
| 935 | reg: reg_off + TEGRA210_MBDRC_MAKEUP_GAIN, |
| 936 | TEGRA210_MBDRC_MAKEUP_GAIN_MASK, |
| 937 | val: params->makeup_gain << |
| 938 | TEGRA210_MBDRC_MAKEUP_GAIN_SHIFT); |
| 939 | |
| 940 | regmap_update_bits(map: ope->mbdrc_regmap, |
| 941 | reg: reg_off + TEGRA210_MBDRC_INIT_GAIN, |
| 942 | TEGRA210_MBDRC_INIT_GAIN_MASK, |
| 943 | val: params->gain_init << |
| 944 | TEGRA210_MBDRC_INIT_GAIN_SHIFT); |
| 945 | |
| 946 | regmap_update_bits(map: ope->mbdrc_regmap, |
| 947 | reg: reg_off + TEGRA210_MBDRC_GAIN_ATTACK, |
| 948 | TEGRA210_MBDRC_GAIN_ATTACK_MASK, |
| 949 | val: params->gain_attack_tc << |
| 950 | TEGRA210_MBDRC_GAIN_ATTACK_SHIFT); |
| 951 | |
| 952 | regmap_update_bits(map: ope->mbdrc_regmap, |
| 953 | reg: reg_off + TEGRA210_MBDRC_GAIN_RELEASE, |
| 954 | TEGRA210_MBDRC_GAIN_RELEASE_MASK, |
| 955 | val: params->gain_release_tc << |
| 956 | TEGRA210_MBDRC_GAIN_RELEASE_SHIFT); |
| 957 | |
| 958 | regmap_update_bits(map: ope->mbdrc_regmap, |
| 959 | reg: reg_off + TEGRA210_MBDRC_FAST_RELEASE, |
| 960 | TEGRA210_MBDRC_FAST_RELEASE_MASK, |
| 961 | val: params->fast_release_tc << |
| 962 | TEGRA210_MBDRC_FAST_RELEASE_SHIFT); |
| 963 | |
| 964 | tegra210_mbdrc_write_ram(regmap: ope->mbdrc_regmap, |
| 965 | reg_ctrl: reg_off + TEGRA210_MBDRC_CFG_RAM_CTRL, |
| 966 | reg_data: reg_off + TEGRA210_MBDRC_CFG_RAM_DATA, ram_offset: 0, |
| 967 | data: (u32 *)¶ms->biquad_params[0], |
| 968 | TEGRA210_MBDRC_MAX_BIQUAD_STAGES * 5); |
| 969 | } |
| 970 | |
| 971 | pm_runtime_put_sync(dev: cmpnt->dev); |
| 972 | |
| 973 | snd_soc_add_component_controls(component: cmpnt, controls: tegra210_mbdrc_controls, |
| 974 | ARRAY_SIZE(tegra210_mbdrc_controls)); |
| 975 | |
| 976 | return 0; |
| 977 | } |
| 978 | |
| 979 | int 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(node: dev->of_node, name: "dynamic-range-compressor" ); |
| 989 | if (!child) |
| 990 | return -ENODEV; |
| 991 | |
| 992 | err = of_address_to_resource(dev: child, index: 0, r: &mem); |
| 993 | of_node_put(node: 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, res: &mem); |
| 1001 | if (IS_ERR(ptr: regs)) |
| 1002 | return PTR_ERR(ptr: regs); |
| 1003 | |
| 1004 | ope->mbdrc_regmap = devm_regmap_init_mmio(dev, regs, |
| 1005 | &tegra210_mbdrc_regmap_cfg); |
| 1006 | if (IS_ERR(ptr: ope->mbdrc_regmap)) { |
| 1007 | dev_err(dev, "regmap init failed\n" ); |
| 1008 | return PTR_ERR(ptr: ope->mbdrc_regmap); |
| 1009 | } |
| 1010 | |
| 1011 | regcache_cache_only(map: ope->mbdrc_regmap, enable: true); |
| 1012 | |
| 1013 | return 0; |
| 1014 | } |
| 1015 | |