0001
0002
0003
0004
0005
0006
0007 #include <linux/clk.h>
0008 #include <linux/device.h>
0009 #include <linux/io.h>
0010 #include <linux/module.h>
0011 #include <linux/of.h>
0012 #include <linux/of_address.h>
0013 #include <linux/of_device.h>
0014 #include <linux/platform_device.h>
0015 #include <linux/pm_runtime.h>
0016 #include <linux/regmap.h>
0017 #include <sound/core.h>
0018 #include <sound/pcm.h>
0019 #include <sound/pcm_params.h>
0020 #include <sound/soc.h>
0021
0022 #include "tegra210_ope.h"
0023 #include "tegra210_peq.h"
0024
0025 static const struct reg_default tegra210_peq_reg_defaults[] = {
0026 { TEGRA210_PEQ_CFG, 0x00000013},
0027 { TEGRA210_PEQ_CFG_RAM_CTRL, 0x00004000},
0028 { TEGRA210_PEQ_CFG_RAM_SHIFT_CTRL, 0x00004000},
0029 };
0030
0031 static const u32 biquad_init_gains[TEGRA210_PEQ_GAIN_PARAM_SIZE_PER_CH] = {
0032 1495012349,
0033
0034
0035 536870912, -1073741824, 536870912, 2143508246, -1069773768,
0036 134217728, -265414508, 131766272, 2140402222, -1071252997,
0037 268435456, -233515765, -33935948, 1839817267, -773826124,
0038 536870912, -672537913, 139851540, 1886437554, -824433167,
0039 268435456, -114439279, 173723964, 205743566, 278809729,
0040 1, 0, 0, 0, 0,
0041 1, 0, 0, 0, 0,
0042 1, 0, 0, 0, 0,
0043 1, 0, 0, 0, 0,
0044 1, 0, 0, 0, 0,
0045 1, 0, 0, 0, 0,
0046 1, 0, 0, 0, 0,
0047
0048 963423114,
0049 };
0050
0051 static const u32 biquad_init_shifts[TEGRA210_PEQ_SHIFT_PARAM_SIZE_PER_CH] = {
0052 23,
0053 30, 30, 30, 30, 30, 0, 0, 0, 0, 0, 0, 0,
0054 28,
0055 };
0056
0057 static s32 biquad_coeff_buffer[TEGRA210_PEQ_GAIN_PARAM_SIZE_PER_CH];
0058
0059 static void tegra210_peq_read_ram(struct regmap *regmap, unsigned int reg_ctrl,
0060 unsigned int reg_data, unsigned int ram_offset,
0061 unsigned int *data, size_t size)
0062 {
0063 unsigned int val;
0064 unsigned int i;
0065
0066 val = ram_offset & TEGRA210_PEQ_RAM_CTRL_RAM_ADDR_MASK;
0067 val |= TEGRA210_PEQ_RAM_CTRL_ADDR_INIT_EN;
0068 val |= TEGRA210_PEQ_RAM_CTRL_SEQ_ACCESS_EN;
0069 val |= TEGRA210_PEQ_RAM_CTRL_RW_READ;
0070
0071 regmap_write(regmap, reg_ctrl, val);
0072
0073
0074
0075
0076
0077 for (i = 0; i < size; i++)
0078 regmap_read(regmap, reg_data, &data[i]);
0079 }
0080
0081 static void tegra210_peq_write_ram(struct regmap *regmap, unsigned int reg_ctrl,
0082 unsigned int reg_data, unsigned int ram_offset,
0083 unsigned int *data, size_t size)
0084 {
0085 unsigned int val;
0086 unsigned int i;
0087
0088 val = ram_offset & TEGRA210_PEQ_RAM_CTRL_RAM_ADDR_MASK;
0089 val |= TEGRA210_PEQ_RAM_CTRL_ADDR_INIT_EN;
0090 val |= TEGRA210_PEQ_RAM_CTRL_SEQ_ACCESS_EN;
0091 val |= TEGRA210_PEQ_RAM_CTRL_RW_WRITE;
0092
0093 regmap_write(regmap, reg_ctrl, val);
0094
0095 for (i = 0; i < size; i++)
0096 regmap_write(regmap, reg_data, data[i]);
0097 }
0098
0099 static int tegra210_peq_get(struct snd_kcontrol *kcontrol,
0100 struct snd_ctl_elem_value *ucontrol)
0101 {
0102 struct soc_mixer_control *mc =
0103 (struct soc_mixer_control *)kcontrol->private_value;
0104 struct snd_soc_component *cmpnt = snd_soc_kcontrol_component(kcontrol);
0105 struct tegra210_ope *ope = snd_soc_component_get_drvdata(cmpnt);
0106 unsigned int mask = (1 << fls(mc->max)) - 1;
0107 unsigned int val;
0108
0109 regmap_read(ope->peq_regmap, mc->reg, &val);
0110
0111 ucontrol->value.integer.value[0] = (val >> mc->shift) & mask;
0112
0113 if (!mc->invert)
0114 return 0;
0115
0116 ucontrol->value.integer.value[0] =
0117 mc->max - ucontrol->value.integer.value[0];
0118
0119 return 0;
0120 }
0121
0122 static int tegra210_peq_put(struct snd_kcontrol *kcontrol,
0123 struct snd_ctl_elem_value *ucontrol)
0124 {
0125 struct soc_mixer_control *mc =
0126 (struct soc_mixer_control *)kcontrol->private_value;
0127 struct snd_soc_component *cmpnt = snd_soc_kcontrol_component(kcontrol);
0128 struct tegra210_ope *ope = snd_soc_component_get_drvdata(cmpnt);
0129 unsigned int mask = (1 << fls(mc->max)) - 1;
0130 bool change = false;
0131 unsigned int val;
0132
0133 val = (ucontrol->value.integer.value[0] & mask);
0134
0135 if (mc->invert)
0136 val = mc->max - val;
0137
0138 val = val << mc->shift;
0139
0140 regmap_update_bits_check(ope->peq_regmap, mc->reg, (mask << mc->shift),
0141 val, &change);
0142
0143 return change ? 1 : 0;
0144 }
0145
0146 static int tegra210_peq_ram_get(struct snd_kcontrol *kcontrol,
0147 struct snd_ctl_elem_value *ucontrol)
0148 {
0149 struct tegra_soc_bytes *params = (void *)kcontrol->private_value;
0150 struct snd_soc_component *cmpnt = snd_soc_kcontrol_component(kcontrol);
0151 struct tegra210_ope *ope = snd_soc_component_get_drvdata(cmpnt);
0152 u32 i, reg_ctrl = params->soc.base;
0153 u32 reg_data = reg_ctrl + cmpnt->val_bytes;
0154 s32 *data = (s32 *)biquad_coeff_buffer;
0155
0156 pm_runtime_get_sync(cmpnt->dev);
0157
0158 tegra210_peq_read_ram(ope->peq_regmap, reg_ctrl, reg_data,
0159 params->shift, data, params->soc.num_regs);
0160
0161 pm_runtime_put_sync(cmpnt->dev);
0162
0163 for (i = 0; i < params->soc.num_regs; i++)
0164 ucontrol->value.integer.value[i] = (long)data[i];
0165
0166 return 0;
0167 }
0168
0169 static int tegra210_peq_ram_put(struct snd_kcontrol *kcontrol,
0170 struct snd_ctl_elem_value *ucontrol)
0171 {
0172 struct tegra_soc_bytes *params = (void *)kcontrol->private_value;
0173 struct snd_soc_component *cmpnt = snd_soc_kcontrol_component(kcontrol);
0174 struct tegra210_ope *ope = snd_soc_component_get_drvdata(cmpnt);
0175 u32 i, reg_ctrl = params->soc.base;
0176 u32 reg_data = reg_ctrl + cmpnt->val_bytes;
0177 s32 *data = (s32 *)biquad_coeff_buffer;
0178
0179 for (i = 0; i < params->soc.num_regs; i++)
0180 data[i] = (s32)ucontrol->value.integer.value[i];
0181
0182 pm_runtime_get_sync(cmpnt->dev);
0183
0184 tegra210_peq_write_ram(ope->peq_regmap, reg_ctrl, reg_data,
0185 params->shift, data, params->soc.num_regs);
0186
0187 pm_runtime_put_sync(cmpnt->dev);
0188
0189 return 1;
0190 }
0191
0192 static int tegra210_peq_param_info(struct snd_kcontrol *kcontrol,
0193 struct snd_ctl_elem_info *uinfo)
0194 {
0195 struct soc_bytes *params = (void *)kcontrol->private_value;
0196
0197 uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER;
0198 uinfo->value.integer.min = INT_MIN;
0199 uinfo->value.integer.max = INT_MAX;
0200 uinfo->count = params->num_regs;
0201
0202 return 0;
0203 }
0204
0205 #define TEGRA210_PEQ_GAIN_PARAMS_CTRL(chan) \
0206 TEGRA_SOC_BYTES_EXT("PEQ Channel-" #chan " Biquad Gain Params", \
0207 TEGRA210_PEQ_CFG_RAM_CTRL, \
0208 TEGRA210_PEQ_GAIN_PARAM_SIZE_PER_CH, \
0209 (TEGRA210_PEQ_GAIN_PARAM_SIZE_PER_CH * chan), 0xffffffff, \
0210 tegra210_peq_ram_get, tegra210_peq_ram_put, \
0211 tegra210_peq_param_info)
0212
0213 #define TEGRA210_PEQ_SHIFT_PARAMS_CTRL(chan) \
0214 TEGRA_SOC_BYTES_EXT("PEQ Channel-" #chan " Biquad Shift Params", \
0215 TEGRA210_PEQ_CFG_RAM_SHIFT_CTRL, \
0216 TEGRA210_PEQ_SHIFT_PARAM_SIZE_PER_CH, \
0217 (TEGRA210_PEQ_SHIFT_PARAM_SIZE_PER_CH * chan), 0x1f, \
0218 tegra210_peq_ram_get, tegra210_peq_ram_put, \
0219 tegra210_peq_param_info)
0220
0221 static const struct snd_kcontrol_new tegra210_peq_controls[] = {
0222 SOC_SINGLE_EXT("PEQ Active", TEGRA210_PEQ_CFG,
0223 TEGRA210_PEQ_CFG_MODE_SHIFT, 1, 0,
0224 tegra210_peq_get, tegra210_peq_put),
0225
0226 SOC_SINGLE_EXT("PEQ Biquad Stages", TEGRA210_PEQ_CFG,
0227 TEGRA210_PEQ_CFG_BIQUAD_STAGES_SHIFT,
0228 TEGRA210_PEQ_MAX_BIQUAD_STAGES - 1, 0,
0229 tegra210_peq_get, tegra210_peq_put),
0230
0231 TEGRA210_PEQ_GAIN_PARAMS_CTRL(0),
0232 TEGRA210_PEQ_GAIN_PARAMS_CTRL(1),
0233 TEGRA210_PEQ_GAIN_PARAMS_CTRL(2),
0234 TEGRA210_PEQ_GAIN_PARAMS_CTRL(3),
0235 TEGRA210_PEQ_GAIN_PARAMS_CTRL(4),
0236 TEGRA210_PEQ_GAIN_PARAMS_CTRL(5),
0237 TEGRA210_PEQ_GAIN_PARAMS_CTRL(6),
0238 TEGRA210_PEQ_GAIN_PARAMS_CTRL(7),
0239
0240 TEGRA210_PEQ_SHIFT_PARAMS_CTRL(0),
0241 TEGRA210_PEQ_SHIFT_PARAMS_CTRL(1),
0242 TEGRA210_PEQ_SHIFT_PARAMS_CTRL(2),
0243 TEGRA210_PEQ_SHIFT_PARAMS_CTRL(3),
0244 TEGRA210_PEQ_SHIFT_PARAMS_CTRL(4),
0245 TEGRA210_PEQ_SHIFT_PARAMS_CTRL(5),
0246 TEGRA210_PEQ_SHIFT_PARAMS_CTRL(6),
0247 TEGRA210_PEQ_SHIFT_PARAMS_CTRL(7),
0248 };
0249
0250 static bool tegra210_peq_wr_reg(struct device *dev, unsigned int reg)
0251 {
0252 switch (reg) {
0253 case TEGRA210_PEQ_SOFT_RESET:
0254 case TEGRA210_PEQ_CG:
0255 case TEGRA210_PEQ_CFG ... TEGRA210_PEQ_CFG_RAM_SHIFT_DATA:
0256 return true;
0257 default:
0258 return false;
0259 }
0260 }
0261
0262 static bool tegra210_peq_rd_reg(struct device *dev, unsigned int reg)
0263 {
0264 if (tegra210_peq_wr_reg(dev, reg))
0265 return true;
0266
0267 switch (reg) {
0268 case TEGRA210_PEQ_STATUS:
0269 return true;
0270 default:
0271 return false;
0272 }
0273 }
0274
0275 static bool tegra210_peq_volatile_reg(struct device *dev, unsigned int reg)
0276 {
0277 switch (reg) {
0278 case TEGRA210_PEQ_SOFT_RESET:
0279 case TEGRA210_PEQ_STATUS:
0280 case TEGRA210_PEQ_CFG_RAM_CTRL ... TEGRA210_PEQ_CFG_RAM_SHIFT_DATA:
0281 return true;
0282 default:
0283 return false;
0284 }
0285 }
0286
0287 static bool tegra210_peq_precious_reg(struct device *dev, unsigned int reg)
0288 {
0289 switch (reg) {
0290 case TEGRA210_PEQ_CFG_RAM_DATA:
0291 case TEGRA210_PEQ_CFG_RAM_SHIFT_DATA:
0292 return true;
0293 default:
0294 return false;
0295 }
0296 }
0297
0298 static const struct regmap_config tegra210_peq_regmap_config = {
0299 .name = "peq",
0300 .reg_bits = 32,
0301 .reg_stride = 4,
0302 .val_bits = 32,
0303 .max_register = TEGRA210_PEQ_CFG_RAM_SHIFT_DATA,
0304 .writeable_reg = tegra210_peq_wr_reg,
0305 .readable_reg = tegra210_peq_rd_reg,
0306 .volatile_reg = tegra210_peq_volatile_reg,
0307 .precious_reg = tegra210_peq_precious_reg,
0308 .reg_defaults = tegra210_peq_reg_defaults,
0309 .num_reg_defaults = ARRAY_SIZE(tegra210_peq_reg_defaults),
0310 .cache_type = REGCACHE_FLAT,
0311 };
0312
0313 void tegra210_peq_restore(struct regmap *regmap, u32 *biquad_gains,
0314 u32 *biquad_shifts)
0315 {
0316 unsigned int i;
0317
0318 for (i = 0; i < TEGRA210_PEQ_MAX_CHANNELS; i++) {
0319 tegra210_peq_write_ram(regmap, TEGRA210_PEQ_CFG_RAM_CTRL,
0320 TEGRA210_PEQ_CFG_RAM_DATA,
0321 (i * TEGRA210_PEQ_GAIN_PARAM_SIZE_PER_CH),
0322 biquad_gains,
0323 TEGRA210_PEQ_GAIN_PARAM_SIZE_PER_CH);
0324
0325 tegra210_peq_write_ram(regmap,
0326 TEGRA210_PEQ_CFG_RAM_SHIFT_CTRL,
0327 TEGRA210_PEQ_CFG_RAM_SHIFT_DATA,
0328 (i * TEGRA210_PEQ_SHIFT_PARAM_SIZE_PER_CH),
0329 biquad_shifts,
0330 TEGRA210_PEQ_SHIFT_PARAM_SIZE_PER_CH);
0331
0332 }
0333 }
0334
0335 void tegra210_peq_save(struct regmap *regmap, u32 *biquad_gains,
0336 u32 *biquad_shifts)
0337 {
0338 unsigned int i;
0339
0340 for (i = 0; i < TEGRA210_PEQ_MAX_CHANNELS; i++) {
0341 tegra210_peq_read_ram(regmap,
0342 TEGRA210_PEQ_CFG_RAM_CTRL,
0343 TEGRA210_PEQ_CFG_RAM_DATA,
0344 (i * TEGRA210_PEQ_GAIN_PARAM_SIZE_PER_CH),
0345 biquad_gains,
0346 TEGRA210_PEQ_GAIN_PARAM_SIZE_PER_CH);
0347
0348 tegra210_peq_read_ram(regmap,
0349 TEGRA210_PEQ_CFG_RAM_SHIFT_CTRL,
0350 TEGRA210_PEQ_CFG_RAM_SHIFT_DATA,
0351 (i * TEGRA210_PEQ_SHIFT_PARAM_SIZE_PER_CH),
0352 biquad_shifts,
0353 TEGRA210_PEQ_SHIFT_PARAM_SIZE_PER_CH);
0354 }
0355 }
0356
0357 int tegra210_peq_component_init(struct snd_soc_component *cmpnt)
0358 {
0359 struct tegra210_ope *ope = snd_soc_component_get_drvdata(cmpnt);
0360 unsigned int i;
0361
0362 pm_runtime_get_sync(cmpnt->dev);
0363 regmap_update_bits(ope->peq_regmap, TEGRA210_PEQ_CFG,
0364 TEGRA210_PEQ_CFG_MODE_MASK,
0365 0 << TEGRA210_PEQ_CFG_MODE_SHIFT);
0366 regmap_update_bits(ope->peq_regmap, TEGRA210_PEQ_CFG,
0367 TEGRA210_PEQ_CFG_BIQUAD_STAGES_MASK,
0368 (TEGRA210_PEQ_BIQUAD_INIT_STAGE - 1) <<
0369 TEGRA210_PEQ_CFG_BIQUAD_STAGES_SHIFT);
0370
0371
0372 for (i = 0; i < TEGRA210_PEQ_MAX_CHANNELS; i++) {
0373
0374
0375 tegra210_peq_write_ram(ope->peq_regmap,
0376 TEGRA210_PEQ_CFG_RAM_CTRL,
0377 TEGRA210_PEQ_CFG_RAM_DATA,
0378 (i * TEGRA210_PEQ_GAIN_PARAM_SIZE_PER_CH),
0379 (u32 *)&biquad_init_gains,
0380 TEGRA210_PEQ_GAIN_PARAM_SIZE_PER_CH);
0381
0382
0383 tegra210_peq_write_ram(ope->peq_regmap,
0384 TEGRA210_PEQ_CFG_RAM_SHIFT_CTRL,
0385 TEGRA210_PEQ_CFG_RAM_SHIFT_DATA,
0386 (i * TEGRA210_PEQ_SHIFT_PARAM_SIZE_PER_CH),
0387 (u32 *)&biquad_init_shifts,
0388 TEGRA210_PEQ_SHIFT_PARAM_SIZE_PER_CH);
0389
0390 }
0391
0392 pm_runtime_put_sync(cmpnt->dev);
0393
0394 snd_soc_add_component_controls(cmpnt, tegra210_peq_controls,
0395 ARRAY_SIZE(tegra210_peq_controls));
0396
0397 return 0;
0398 }
0399
0400 int tegra210_peq_regmap_init(struct platform_device *pdev)
0401 {
0402 struct device *dev = &pdev->dev;
0403 struct tegra210_ope *ope = dev_get_drvdata(dev);
0404 struct device_node *child;
0405 struct resource mem;
0406 void __iomem *regs;
0407 int err;
0408
0409 child = of_get_child_by_name(dev->of_node, "equalizer");
0410 if (!child)
0411 return -ENODEV;
0412
0413 err = of_address_to_resource(child, 0, &mem);
0414 of_node_put(child);
0415 if (err < 0) {
0416 dev_err(dev, "fail to get PEQ resource\n");
0417 return err;
0418 }
0419
0420 mem.flags = IORESOURCE_MEM;
0421 regs = devm_ioremap_resource(dev, &mem);
0422 if (IS_ERR(regs))
0423 return PTR_ERR(regs);
0424 ope->peq_regmap = devm_regmap_init_mmio(dev, regs,
0425 &tegra210_peq_regmap_config);
0426 if (IS_ERR(ope->peq_regmap)) {
0427 dev_err(dev, "regmap init failed\n");
0428 return PTR_ERR(ope->peq_regmap);
0429 }
0430
0431 regcache_cache_only(ope->peq_regmap, true);
0432
0433 return 0;
0434 }