blob: f5bad613b9f2fa9c4324909789efddd77a16773e [file] [log] [blame]
// SPDX-License-Identifier: GPL-2.0
/*
* Copyright (C) 2019 Amlogic, Inc. All rights reserved.
*
*/
#include <linux/kernel.h>
#include "effects_hw_v2.h"
#include "regs.h"
#include "iomap.h"
#include "tdm_hw.h"
#include "spdif_hw.h"
void aed_init_ram_coeff(int version, int add, int len, unsigned int *params)
{
int i, ctrl_v;
unsigned int *p = params;
for (i = 0; i < len; i++, p++) {
ctrl_v = ((add + i) << 2) | (0x1 << 1) | (0x1 << 0);
eqdrc_write(AED_COEF_RAM_DATA, *p);
eqdrc_write(AED_COEF_RAM_CNTL, ctrl_v);
}
/* init RAMB */
if (version > VERSION3) {
p = params;
for (i = 0; i < len; i++, p++) {
ctrl_v = ((add + i) << 2) | (0x1 << 1) | (0x1 << 0);
eqdrc_write(AED_COEF_RAM_DATA_B, *p);
eqdrc_write(AED_COEF_RAM_CNTL_B, ctrl_v);
}
}
}
void aed_set_ram_coeff(int version, int add, int len, unsigned int *params)
{
int i, ctrl_v;
unsigned int *p = params, value = 0;
if (version > VERSION3) {
/*
* dynamic control
* step 1. write params to unselected ram
* step 2. switch to unselected ram
* step 3. write params to the other ram
*/
/*
* EE_AED_EQDRC_DYNAMIC_CNTL bit 0
* coef ram sel: 0 select rama coef; 1 select ramb coef
*/
value = eqdrc_read(AED_EQDRC_DYNAMIC_CNTL);
value &= 0x1;
if (value) {
for (i = 0; i < len; i++, p++) {
ctrl_v = ((add + i) << 2)
| (0x1 << 1)
| (0x1 << 0);
eqdrc_write(AED_COEF_RAM_DATA, *p);
eqdrc_write(AED_COEF_RAM_CNTL, ctrl_v);
}
} else {
for (i = 0; i < len; i++, p++) {
ctrl_v = ((add + i) << 2)
| (0x1 << 1)
| (0x1 << 0);
eqdrc_write(AED_COEF_RAM_DATA_B, *p);
eqdrc_write(AED_COEF_RAM_CNTL_B, ctrl_v);
}
}
eqdrc_update_bits(AED_EQDRC_DYNAMIC_CNTL,
0x1 << 0,
!value << 0);
p = params;
if (value) {
for (i = 0; i < len; i++, p++) {
ctrl_v = ((add + i) << 2)
| (0x1 << 1)
| (0x1 << 0);
eqdrc_write(AED_COEF_RAM_DATA_B, *p);
eqdrc_write(AED_COEF_RAM_CNTL_B, ctrl_v);
}
} else {
for (i = 0; i < len; i++, p++) {
ctrl_v = ((add + i) << 2)
| (0x1 << 1)
| (0x1 << 0);
eqdrc_write(AED_COEF_RAM_DATA, *p);
eqdrc_write(AED_COEF_RAM_CNTL, ctrl_v);
}
}
} else {
for (i = 0; i < len; i++, p++) {
ctrl_v = ((add + i) << 2) | (0x1 << 1) | (0x1 << 0);
eqdrc_write(AED_COEF_RAM_DATA, *p);
eqdrc_write(AED_COEF_RAM_CNTL, ctrl_v);
}
}
}
void aed_get_ram_coeff(int add, int len, unsigned int *params)
{
int i, ctrl_v;
unsigned int *p = params;
for (i = 0; i < len; i++, p++) {
ctrl_v = ((add + i) << 2) | (0x0 << 1) | (0x1 << 0);
eqdrc_write(AED_COEF_RAM_CNTL, ctrl_v);
*p = eqdrc_read(AED_COEF_RAM_DATA);
//pr_info("%s, params[%d] = %8.8x\n", __func__, i, *p);
}
}
void aed_set_multiband_drc_coeff(int band, unsigned int *params)
{
int i;
int offset = AED_MDRC_RMS_COEF10 - AED_MDRC_RMS_COEF00;
int reg = AED_MDRC_RMS_COEF00;
for (i = 0; i < offset; i++) {
eqdrc_write(reg + band * offset + i,
params[band * offset + i]);
}
}
void aed_get_multiband_drc_coeff(int band, unsigned int *params)
{
int i;
int offset = AED_MDRC_RMS_COEF10 - AED_MDRC_RMS_COEF00;
int reg = AED_MDRC_RMS_COEF00;
for (i = 0; i < offset; i++) {
*(params + band * offset + i) =
eqdrc_read(reg + band * offset + i);
}
}
void aed_set_fullband_drc_coeff(int group, unsigned int *params)
{
unsigned int *p = params;
if (group == 0) {
eqdrc_write(AED_DRC_RELEASE_COEF00, *p++);
eqdrc_write(AED_DRC_RELEASE_COEF01, *p++);
eqdrc_write(AED_DRC_ATTACK_COEF00, *p++);
eqdrc_write(AED_DRC_ATTACK_COEF01, *p++);
eqdrc_write(AED_DRC_THD0, *p++);
eqdrc_write(AED_DRC_K0, *p++);
} else if (group == 1) {
eqdrc_write(AED_DRC_RELEASE_COEF10, *p++);
eqdrc_write(AED_DRC_RELEASE_COEF11, *p++);
eqdrc_write(AED_DRC_ATTACK_COEF10, *p++);
eqdrc_write(AED_DRC_ATTACK_COEF11, *p++);
eqdrc_write(AED_DRC_THD1, *p++);
eqdrc_write(AED_DRC_K2, *p++);
eqdrc_write(AED_DRC_THD_OUT0, eqdrc_read(AED_DRC_THD1));
} else if (group == 2) {
eqdrc_write(AED_DRC_RMS_COEF0, *p++);
eqdrc_write(AED_DRC_RMS_COEF1, *p++);
eqdrc_write(AED_DRC_LOOPBACK_CNTL, *p++);
/*THD_OUT0 = THD1; K1 = 1.0*/
eqdrc_write(AED_DRC_THD_OUT0, eqdrc_read(AED_DRC_THD1));
eqdrc_write(AED_DRC_K1, 0x40000);
}
}
void aed_get_fullband_drc_coeff(int len, unsigned int *params)
{
unsigned int *p = params;
*p++ = eqdrc_read(AED_DRC_RELEASE_COEF00);
*p++ = eqdrc_read(AED_DRC_RELEASE_COEF01);
*p++ = eqdrc_read(AED_DRC_ATTACK_COEF00);
*p++ = eqdrc_read(AED_DRC_ATTACK_COEF01);
*p++ = eqdrc_read(AED_DRC_THD0);
*p++ = eqdrc_read(AED_DRC_K0);
*p++ = eqdrc_read(AED_DRC_RELEASE_COEF10);
*p++ = eqdrc_read(AED_DRC_RELEASE_COEF11);
*p++ = eqdrc_read(AED_DRC_ATTACK_COEF10);
*p++ = eqdrc_read(AED_DRC_ATTACK_COEF11);
*p++ = eqdrc_read(AED_DRC_THD1);
*p++ = eqdrc_read(AED_DRC_K2);
*p++ = eqdrc_read(AED_DRC_RMS_COEF0);
*p++ = eqdrc_read(AED_DRC_RMS_COEF1);
*p++ = eqdrc_read(AED_DRC_LOOPBACK_CNTL);
*p++ = eqdrc_read(AED_DRC_THD_OUT0);
*p++ = eqdrc_read(AED_DRC_K1);
}
void aed_set_mixer_params(void)
{
eqdrc_write(AED_MIX0_LL, 0x40000);
eqdrc_write(AED_MIX0_RL, 0x0);
eqdrc_write(AED_MIX0_LR, 0x0);
eqdrc_write(AED_MIX0_RR, 0x40000);
eqdrc_write(AED_CLIP_THD, 0x7fffff);
}
void aed_dc_enable(bool enable)
{
eqdrc_write(AED_DC_EN, enable << 0);
}
void aed_nd_enable(bool enable)
{
if (enable) {
eqdrc_write(AED_ND_LOW_THD, 0x100);
eqdrc_write(AED_ND_HIGH_THD, 0x200);
eqdrc_write(AED_ND_CNT_THD, 0x100);
eqdrc_write(AED_ND_SUM_NUM, 0x200);
eqdrc_write(AED_ND_CZ_NUM, 0x800);
eqdrc_write(AED_ND_SUM_THD0, 0x20000);
eqdrc_write(AED_ND_SUM_THD1, 0x30000);
eqdrc_write(AED_ND_CZ_THD0, 0x200);
eqdrc_write(AED_ND_CZ_THD1, 0x100);
eqdrc_write(AED_ND_COND_CNTL, 0x3f);
eqdrc_write(AED_ND_RELEASE_COEF0, 0x3263a);
eqdrc_write(AED_ND_RELEASE_COEF1, 0x7cd9c6);
eqdrc_write(AED_ND_ATTACK_COEF0, 0x5188);
eqdrc_write(AED_ND_ATTACK_COEF1, 0x7fae78);
}
eqdrc_write(AED_ND_CNTL, (enable << 0) | (3 << 1));
}
void aed_eq_enable(int idx, bool enable)
{
eqdrc_update_bits(AED_EQ_EN, 0x1 << idx, enable << idx);
}
void aed_eq_taps(unsigned int eq1_taps)
{
if (eq1_taps > 20) {
pr_err("Error EQ1_Tap = %d\n", eq1_taps);
return;
}
eqdrc_update_bits(AED_EQ_TAP_CNTL, 0x1f, eq1_taps);
eqdrc_update_bits(AED_EQ_TAP_CNTL, 0x1f << 5, (20 - eq1_taps) << 5);
}
void aed_set_multiband_drc_param(void)
{
eqdrc_update_bits(AED_MDRC_CNTL,
(0x1 << 16) | (0x7 << 3) | (0x7 << 0),
(0x0 << 16) | (0x7 << 3) | (0x7 << 0));
}
void aed_set_fullband_drc_param(int tap)
{
eqdrc_update_bits(AED_DRC_CNTL, (0x7 << 3), (tap << 3));
}
void aed_set_multiband_drc_enable(bool enable)
{
eqdrc_update_bits(AED_MDRC_CNTL, (0x1 << 8), (enable << 8));
}
void aed_set_fullband_drc_enable(bool enable)
{
eqdrc_update_bits(AED_DRC_CNTL, (0x1 << 0), (enable << 0));
}
void aed_set_volume(unsigned int master_vol,
unsigned int lch_vol, unsigned int rch_vol)
{
eqdrc_write(AED_EQ_VOLUME,
(0 << 30) | /* volume step: 0.125dB */
(master_vol << 16) | /* master volume: 0dB */
(lch_vol << 8) | /* channel 2 volume: 0dB */
(rch_vol << 0) /* channel 1 volume: 0dB */
);
eqdrc_write(AED_EQ_VOLUME_SLEW_CNT, 0x2); /*40ms from -120dB~0dB*/
eqdrc_write(AED_MUTE, 0);
}
void aed_set_lane_and_channels(int lane_mask, int ch_mask)
{
int ch_num = 0, i = 0;
int val = ch_mask & 0xff;
eqdrc_update_bits(AED_TOP_CTL,
0xff << 18 | 0xf << 14,
ch_mask << 18 | lane_mask << 14);
for (i = 0; i < 8; i++) {
if ((val & 0x1) == 0x1)
ch_num++;
val >>= 1;
}
eqdrc_update_bits(AED_TOP_REQ_CTL,
0xff << 12, (ch_num - 1) << 12);
}
/* max 16ch, 8 lane*/
void aed_set_lane_and_channels_v3(int lane_mask, int ch_mask)
{
int ch_num = 0, lane_num = 0, i = 0;
int val_ch = ch_mask & 0xffff;
int val_lane = lane_mask & 0xff;
for (i = 0; i < 16; i++) {
if ((val_ch & 0x1) == 0x1)
ch_num++;
if ((val_lane & 0x1) == 0x1)
lane_num = i;
val_ch >>= 1;
val_lane >>= 1;
}
eqdrc_update_bits(AED_TOP_CTL1,
0xf << 20 | 0xf << 16 | 0x1 << 5 | 0x1 << 4 | 0xf,
(lane_num * 2 + 1) << 20 | (lane_num * 2) << 16 |
0x1 << 5 | 0x1 << 4 | (ch_num - 1));
eqdrc_update_bits(AED_TOP_CTL2, 0xff << 12, (ch_num - 1) << 12);
}
void aed_set_ctrl(bool enable, int sel, enum frddr_dest module, int offset)
{
int mask = 0, val = 0;
switch (sel) {
case 0: /* REQ_SEL0 */
mask = 0xf << 0;
val = 0x1 << 3 | module << 0;
break;
case 1: /* REQ_SEL1 */
mask = 0xf << 4;
val = 0x1 << 7 | module << 4;
break;
case 2: /* REQ_SEL2 */
mask = 0xf << 8;
val = 0x1 << 11 | module << 8;
break;
default:
pr_err("unknown AED req_sel:%d, module:%d\n",
sel, module);
return;
}
/*AED_TOP_REQ_CTL or AED_TOP_CTL2*/
eqdrc_update_bits((AED_TOP_REQ_CTL + offset), mask, val);
/* Effect Module */
if (module <= TDMOUT_C && module >= TDMOUT_A) {
/* TDMOUT A/B/C */
aml_tdmout_select_aed(enable, module);
} else if (module == TDMOUT_D) {
aml_tdmout_select_aed(enable, 3);
} else {
/* SPDIFOUT A/B */
aml_spdifout_select_aed(enable, module - SPDIFOUT_A);
}
}
void aed_set_format(int msb, enum ddr_types frddr_type,
enum ddr_num source, int offset)
{
eqdrc_update_bits(AED_TOP_CTL,
0x7 << 11 | 0x1f << 6 | 0x3 << (4 - offset),
frddr_type << 11 | msb << 6 |
source << (4 - offset));
}
void aed_reload_config(void)
{
eqdrc_update_bits(AED_TOP_CTL, 0x1 << 29, 0x1 << 29);
eqdrc_update_bits(AED_TOP_CTL, 0x1 << 29, 0x0 << 29);
}
void aed_enable(bool enable)
{
/*don't change this flow*/
if (enable) {
eqdrc_write(AED_ED_CNTL, 0x1);
eqdrc_write(AED_ED_CNTL, 0x1);
eqdrc_update_bits(AED_TOP_CTL, 0x3 << 1, 0x3 << 1);
eqdrc_update_bits(AED_TOP_CTL, 0x1 << 0, 0x1 << 0);
eqdrc_update_bits(AED_TOP_CTL, 0x1 << 31, 0x1 << 31);
} else {
eqdrc_update_bits(AED_TOP_CTL, 0x1 << 0, 0x0 << 0);
eqdrc_write(AED_ED_CNTL, 0x1);
eqdrc_write(AED_ED_CNTL, 0x1);
eqdrc_update_bits(AED_TOP_CTL, 0x3 << 1, 0x0 << 1);
}
}
void aed_module_reset(int offset)
{
audiobus_update_bits(EE_AUDIO_SW_RESET0(offset),
REG_BIT_RESET_EQDRC, REG_BIT_RESET_EQDRC);
audiobus_update_bits(EE_AUDIO_SW_RESET0(offset),
REG_BIT_RESET_EQDRC, 0);
}