blob: c3d9863e04578b05bec717844689880687871049 [file] [log] [blame]
/*
* sound/soc/amlogic/auge/tdm_hw.c
*
* Copyright (C) 2017 Amlogic, Inc. All rights reserved.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
* more details.
*
*/
#include <sound/soc.h>
#include "tdm_hw.h"
#include "iomap.h"
#define MST_CLK_INVERT_PH0_PAD_BCLK (1 << 0)
#define MST_CLK_INVERT_PH0_PAD_FCLK (1 << 1)
#define MST_CLK_INVERT_PH1_TDMIN_BCLK (1 << 2)
#define MST_CLK_INVERT_PH1_TDMIN_FCLK (1 << 3)
#define MST_CLK_INVERT_PH2_TDMOUT_BCLK (1 << 4)
#define MST_CLK_INVERT_PH2_TDMOUT_FCLK (1 << 5)
/*#define G12A_PTM_LB_INTERNAL*/
/*#define TL1_PTM_LB_INTERNAL*/
/* without audio handler, it should be improved */
void aml_tdm_enable(
struct aml_audio_controller *actrl,
int stream, int index,
bool is_enable)
{
unsigned int offset, reg;
if (stream == SNDRV_PCM_STREAM_PLAYBACK) {
pr_debug("tdm playback enable\n");
offset = EE_AUDIO_TDMOUT_B_CTRL0
- EE_AUDIO_TDMOUT_A_CTRL0;
reg = EE_AUDIO_TDMOUT_A_CTRL0 + offset * index;
aml_audiobus_update_bits(actrl, reg, 1<<31, is_enable<<31);
} else {
pr_debug("tdm capture enable\n");
offset = EE_AUDIO_TDMIN_B_CTRL
- EE_AUDIO_TDMIN_A_CTRL;
reg = EE_AUDIO_TDMIN_A_CTRL + offset * index;
aml_audiobus_update_bits(actrl, reg, 1<<31, is_enable<<31);
}
}
void aml_tdm_arb_config(struct aml_audio_controller *actrl)
{
/* config ddr arb */
aml_audiobus_write(actrl, EE_AUDIO_ARB_CTRL, 1<<31|0xff<<0);
}
void aml_tdm_fifo_reset(
struct aml_audio_controller *actrl,
int stream, int index)
{
unsigned int reg, offset;
if (stream == SNDRV_PCM_STREAM_PLAYBACK) {
offset = EE_AUDIO_TDMOUT_B_CTRL0
- EE_AUDIO_TDMOUT_A_CTRL0;
reg = EE_AUDIO_TDMOUT_A_CTRL0 + offset * index;
/* reset afifo */
aml_audiobus_update_bits(actrl, reg, 3<<28, 0);
aml_audiobus_update_bits(actrl, reg, 1<<29, 1<<29);
aml_audiobus_update_bits(actrl, reg, 1<<28, 1<<28);
} else {
offset = EE_AUDIO_TDMIN_B_CTRL
- EE_AUDIO_TDMIN_A_CTRL;
reg = EE_AUDIO_TDMIN_A_CTRL + offset * index;
/* reset afifo */
aml_audiobus_update_bits(actrl, reg, 3<<28, 0);
aml_audiobus_update_bits(actrl, reg, 1<<29, 1<<29);
aml_audiobus_update_bits(actrl, reg, 1<<28, 1<<28);
}
}
void tdm_enable(int tdm_index, int is_enable)
{
unsigned int offset, reg;
if (tdm_index < 3) {
pr_info("tdmout is_enable:%d\n", is_enable);
offset = EE_AUDIO_TDMOUT_B_CTRL0
- EE_AUDIO_TDMOUT_A_CTRL0;
reg = EE_AUDIO_TDMOUT_A_CTRL0 + offset * tdm_index;
audiobus_update_bits(reg, 1<<31, is_enable<<31);
} else if (tdm_index < 6) {
pr_info("tdmin is_enable:%d\n", is_enable);
tdm_index -= 3;
offset = EE_AUDIO_TDMIN_B_CTRL
- EE_AUDIO_TDMIN_A_CTRL;
reg = EE_AUDIO_TDMIN_A_CTRL + offset * tdm_index;
audiobus_update_bits(reg, 1<<31, is_enable<<31);
}
}
void tdm_fifo_enable(int tdm_index, int is_enable)
{
unsigned int reg, offset;
if (tdm_index < 3) {
offset = EE_AUDIO_TDMOUT_B_CTRL0
- EE_AUDIO_TDMOUT_A_CTRL0;
reg = EE_AUDIO_TDMOUT_A_CTRL0 + offset * tdm_index;
if (is_enable) {
audiobus_update_bits(reg, 1<<29, 1<<29);
audiobus_update_bits(reg, 1<<28, 1<<28);
} else
audiobus_update_bits(reg, 3<<28, 0);
} else if (tdm_index < 6) {
tdm_index -= 3;
offset = EE_AUDIO_TDMIN_B_CTRL
- EE_AUDIO_TDMIN_A_CTRL;
reg = EE_AUDIO_TDMIN_A_CTRL + offset * tdm_index;
if (is_enable) {
audiobus_update_bits(reg, 1<<29, 1<<29);
audiobus_update_bits(reg, 1<<28, 1<<28);
} else
audiobus_update_bits(reg, 3<<28, 0);
}
}
int tdmout_get_frddr_type(int bitwidth)
{
unsigned int frddr_type = 0;
switch (bitwidth) {
case 8:
frddr_type = 0;
break;
case 16:
frddr_type = 2;
break;
case 24:
case 32:
frddr_type = 4;
break;
default:
pr_err("invalid bit_depth: %d\n",
bitwidth);
break;
}
return frddr_type;
}
void aml_tdm_fifo_ctrl(
struct aml_audio_controller *actrl,
int bitwidth, int stream,
int index, unsigned int fifo_id)
{
unsigned int frddr_type = tdmout_get_frddr_type(bitwidth);
unsigned int reg, offset;
if (stream == SNDRV_PCM_STREAM_PLAYBACK) {
pr_debug("tdm prepare----playback\n");
// from ddr, 63bit split into 2 samples
offset = EE_AUDIO_TDMOUT_B_CTRL1
- EE_AUDIO_TDMOUT_A_CTRL1;
reg = EE_AUDIO_TDMOUT_A_CTRL1 + offset * index;
aml_audiobus_update_bits(actrl, reg,
0x3<<24|0x1f<<8|0x7<<4,
fifo_id<<24|(bitwidth-1)<<8|frddr_type<<4);
} else {
pr_debug("tdm prepare----capture\n");
}
}
static void aml_clk_set_tdmout_by_id(
struct aml_audio_controller *actrl,
unsigned int tdm_index,
unsigned int sclk_sel,
unsigned int lrclk_sel,
bool sclk_ws_inv,
bool is_master,
bool binv)
{
unsigned int val_sclk_ws_inv = 0;
unsigned int reg = EE_AUDIO_CLK_TDMOUT_A_CTRL + tdm_index;
/* This is just a copy from previous setting. WHY??? */
val_sclk_ws_inv = sclk_ws_inv && is_master;
if (val_sclk_ws_inv)
aml_audiobus_update_bits(actrl, reg,
0x3<<30|1<<28|0xf<<24|0xf<<20,
0x3<<30|val_sclk_ws_inv<<28|
sclk_sel<<24|lrclk_sel<<20);
else
aml_audiobus_update_bits(actrl, reg,
0x3<<30|1<<29|0xf<<24|0xf<<20,
0x3<<30|binv<<29|
sclk_sel<<24|lrclk_sel<<20);
}
static void aml_clk_set_tdmin_by_id(
struct aml_audio_controller *actrl,
unsigned int tdm_index,
unsigned int sclk_sel,
unsigned int lrclk_sel)
{
unsigned int reg =
EE_AUDIO_CLK_TDMIN_A_CTRL + tdm_index;
aml_audiobus_update_bits(actrl,
reg,
0xff<<20,
sclk_sel<<24|lrclk_sel<<20);
}
static void aml_tdmout_invert_lrclk(
struct aml_audio_controller *actrl,
unsigned int tdm_index,
bool finv)
{
unsigned int off_set =
EE_AUDIO_TDMOUT_B_CTRL1 - EE_AUDIO_TDMOUT_A_CTRL1;
unsigned int reg_out =
EE_AUDIO_TDMOUT_A_CTRL1 + off_set * tdm_index;
aml_audiobus_update_bits(actrl,
reg_out, 0x1<<28, finv<<28);
}
static void aml_tdmout_bclk_skew(
struct aml_audio_controller *actrl,
unsigned int tdm_index,
unsigned int bclkout_skew)
{
unsigned int off_set =
EE_AUDIO_TDMOUT_B_CTRL0 - EE_AUDIO_TDMOUT_A_CTRL0;
unsigned int reg_out =
EE_AUDIO_TDMOUT_A_CTRL0 + off_set * tdm_index;
aml_audiobus_update_bits(actrl,
reg_out, 0x1f<<15, bclkout_skew<<15);
}
void aml_tdm_set_format(
struct aml_audio_controller *actrl,
struct pcm_setting *p_config,
unsigned int clk_sel,
unsigned int index,
unsigned int fmt,
unsigned int capture_active,
unsigned int playback_active)
{
unsigned int binv, finv, id;
unsigned int valb, valf;
unsigned int reg_in, reg_out, off_set;
int bclkin_skew, bclkout_skew;
int master_mode;
unsigned int clkctl = 0;
id = index;
binv = 0;
finv = 0;
switch (fmt & SND_SOC_DAIFMT_MASTER_MASK) {
case SND_SOC_DAIFMT_CBM_CFM:
valb = SLAVE_A + id;
valf = SLAVE_A + id;
master_mode = 0;
break;
case SND_SOC_DAIFMT_CBS_CFS:
valb = MASTER_A + clk_sel;
valf = MASTER_A + clk_sel;
master_mode = 1;
break;
default:
return;
}
aml_clk_set_tdmin_by_id(actrl, id, valb, valf);
switch (fmt & SND_SOC_DAIFMT_FORMAT_MASK) {
case SND_SOC_DAIFMT_I2S:
if (p_config->sclk_ws_inv) {
if (master_mode)
bclkout_skew = 2;
else
bclkout_skew = 3;
} else
bclkout_skew = 1;
bclkin_skew = 3;
clkctl |= MST_CLK_INVERT_PH0_PAD_FCLK
| MST_CLK_INVERT_PH2_TDMOUT_FCLK;
finv = 1;
if (master_mode) {
clkctl |= MST_CLK_INVERT_PH0_PAD_BCLK;
if (capture_active)
binv |= 1;
} else {
if (playback_active)
binv |= 1;
}
break;
case SND_SOC_DAIFMT_DSP_A:
/*
* Frame high, 1clk before data, one bit for frame sync,
* frame sync starts one serial clock cycle earlier,
* that is, together with the last bit of the previous
* data word.
*/
if (p_config->sclk_ws_inv) {
if (master_mode)
bclkout_skew = 2;
else
bclkout_skew = 3;
} else
bclkout_skew = 1;
bclkin_skew = 3;
if (capture_active)
binv |= 1;
break;
case SND_SOC_DAIFMT_LEFT_J:
case SND_SOC_DAIFMT_DSP_B:
/*
* Frame high, one bit for frame sync,
* frame sync asserts with the first bit of the frame.
*/
if (p_config->sclk_ws_inv) {
if (master_mode)
bclkout_skew = 3;
else
bclkout_skew = 4;
} else
bclkout_skew = 2;
bclkin_skew = 2;
if (capture_active)
binv |= 1;
break;
default:
return;
}
p_config->pcm_mode = fmt & SND_SOC_DAIFMT_FORMAT_MASK;
pr_debug("pad clk ctl value:%x\n", clkctl);
/* set lrclk/bclk invertion */
switch (fmt & SND_SOC_DAIFMT_INV_MASK) {
case SND_SOC_DAIFMT_IB_IF:
/* Invert both clocks */
if (!master_mode)
binv ^= 1;
finv |= 1;
clkctl ^= MST_CLK_INVERT_PH0_PAD_BCLK;
clkctl ^= MST_CLK_INVERT_PH0_PAD_FCLK;
break;
case SND_SOC_DAIFMT_IB_NF:
/* Invert bit clock */
if (!master_mode)
binv ^= 1;
clkctl ^= MST_CLK_INVERT_PH0_PAD_BCLK;
break;
case SND_SOC_DAIFMT_NB_IF:
/* Invert frame clock */
finv ^= 1;
clkctl ^= MST_CLK_INVERT_PH0_PAD_FCLK;
break;
case SND_SOC_DAIFMT_NB_NF:
/* normal cases */
break;
default:
return;
}
pr_debug("sclk_ph0 (pad) clk ctl set:%x\n", clkctl);
/* clk ctrl: delay line and invert clk */
/*clkctl |= 0x88880000;*/
if (master_mode) {
off_set = EE_AUDIO_MST_B_SCLK_CTRL1 - EE_AUDIO_MST_A_SCLK_CTRL1;
reg_out = EE_AUDIO_MST_A_SCLK_CTRL1 + off_set * id;
aml_audiobus_update_bits(actrl, reg_out, 0x3f, clkctl);
}
pr_info("master_mode(%d), binv(%d), finv(%d) out_skew(%d), in_skew(%d)\n",
master_mode, binv, finv, bclkout_skew, bclkin_skew);
/* TDM out */
if (playback_active) {
aml_clk_set_tdmout_by_id(actrl,
id, valb, valf,
p_config->sclk_ws_inv, master_mode, binv);
aml_tdmout_invert_lrclk(actrl, id, finv);
aml_tdmout_bclk_skew(actrl, id, bclkout_skew);
}
/* TDM in */
if (capture_active) {
reg_in = EE_AUDIO_CLK_TDMIN_A_CTRL + id;
aml_audiobus_update_bits(actrl, reg_in,
0x3<<30, 0x3<<30);
if (master_mode)
aml_audiobus_update_bits(actrl, reg_in,
0x1<<29, binv<<29);
off_set = EE_AUDIO_TDMIN_B_CTRL - EE_AUDIO_TDMIN_A_CTRL;
reg_in = EE_AUDIO_TDMIN_A_CTRL + off_set * id;
aml_audiobus_update_bits(actrl, reg_in,
3<<26|0x7<<16, 3<<26|bclkin_skew<<16);
aml_audiobus_update_bits(actrl, reg_in,
0x1<<25, finv<<25);
if (p_config->pcm_mode == SND_SOC_DAIFMT_I2S)
aml_audiobus_update_bits(actrl, reg_in,
1<<30,
1<<30);
}
}
void aml_update_tdmin_skew(struct aml_audio_controller *actrl,
int idx, int skew)
{
unsigned int reg_in, off_set;
off_set = EE_AUDIO_TDMIN_B_CTRL - EE_AUDIO_TDMIN_A_CTRL;
reg_in = EE_AUDIO_TDMIN_A_CTRL + off_set * idx;
aml_audiobus_update_bits(actrl, reg_in,
0x7 << 16, skew << 16);
}
void aml_update_tdmin_rev_ws(struct aml_audio_controller *actrl,
int idx, int is_rev)
{
unsigned int reg_in, off_set;
off_set = EE_AUDIO_TDMIN_B_CTRL - EE_AUDIO_TDMIN_A_CTRL;
reg_in = EE_AUDIO_TDMIN_A_CTRL + off_set * idx;
aml_audiobus_update_bits(actrl, reg_in,
0x1 << 25, is_rev << 25);
}
void aml_tdm_set_slot_out(
struct aml_audio_controller *actrl,
int index, int slots, int slot_width,
int force_oe, int oe_val)
{
unsigned int reg, offset;
offset = EE_AUDIO_TDMOUT_B_CTRL0 - EE_AUDIO_TDMOUT_A_CTRL0;
reg = EE_AUDIO_TDMOUT_A_CTRL0 + offset * index;
aml_audiobus_update_bits(actrl, reg,
0x3ff, ((slots - 1) << 5) | (slot_width - 1));
if (force_oe) {
aml_audiobus_update_bits(actrl, reg, 0xf << 24, force_oe << 24);
/* force oe val, in or out */
if (oe_val) {
reg = EE_AUDIO_TDMOUT_A_CTRL1 + offset * index;
aml_audiobus_update_bits(actrl, reg,
0xf << 0, oe_val << 0);
}
}
}
void aml_tdm_set_slot_in(
struct aml_audio_controller *actrl,
int index, int in_src, int slot_width)
{
unsigned int reg, offset;
offset = EE_AUDIO_TDMIN_B_CTRL - EE_AUDIO_TDMIN_A_CTRL;
reg = EE_AUDIO_TDMIN_A_CTRL + offset * index;
#if defined(G12A_PTM_LB_INTERNAL)
if (index == 0) /*TODO: ptm, tdma dsp_a lb*/
aml_audiobus_update_bits(actrl, reg,
0xf<<20|0x1f, 6<<20|(slot_width-1));
if (index == 1) /*TODO: ptm, tdmb i2s lb*/
aml_audiobus_update_bits(actrl, reg,
0xf<<20|0x1f, 7<<20|(slot_width-1));
else
#elif defined(TL1_PTM_LB_INTERNAL)
if (index == 0) /*TODO: ptm, tdma dsp_a lb*/
aml_audiobus_update_bits(actrl, reg,
0xf<<20|0x1f, 13<<20|(slot_width-1));
else if (index == 1) /*TODO: ptm, tdmb i2s lb*/
aml_audiobus_update_bits(actrl, reg,
0xf<<20|0x1f, 14<<20|(slot_width-1));
else
#endif
aml_audiobus_update_bits(actrl, reg,
0xf << 20 | 0x1f, in_src << 20 | (slot_width-1));
}
void aml_update_tdmin_src(
struct aml_audio_controller *actrl,
int index, int in_src)
{
unsigned int reg, offset;
offset = EE_AUDIO_TDMIN_B_CTRL - EE_AUDIO_TDMIN_A_CTRL;
reg = EE_AUDIO_TDMIN_A_CTRL + offset * index;
aml_audiobus_update_bits(actrl, reg,
0xf << 20, in_src << 20);
}
void tdmin_set_chnum_en(
struct aml_audio_controller *actrl,
int index, bool enable)
{
unsigned int reg, offset;
offset = EE_AUDIO_TDMIN_B_CTRL - EE_AUDIO_TDMIN_A_CTRL;
reg = EE_AUDIO_TDMIN_A_CTRL + offset * index;
aml_audiobus_update_bits(actrl, reg,
0x1 << 6, enable << 6);
}
void aml_tdm_set_channel_mask(
struct aml_audio_controller *actrl,
int stream, int index, int lane, int mask)
{
unsigned int offset, reg;
if (stream == SNDRV_PCM_STREAM_PLAYBACK) {
if (lane >= LANE_MAX1)
offset = EE_AUDIO_TDMOUT_B_MASK4
- EE_AUDIO_TDMOUT_A_MASK4;
else
offset = EE_AUDIO_TDMOUT_B_MASK0
- EE_AUDIO_TDMOUT_A_MASK0;
reg = EE_AUDIO_TDMOUT_A_MASK0 + offset * index;
} else {
if (lane >= LANE_MAX1)
offset = EE_AUDIO_TDMIN_B_MASK4
- EE_AUDIO_TDMIN_A_MASK4;
else
offset = EE_AUDIO_TDMIN_B_MASK0
- EE_AUDIO_TDMIN_A_MASK0;
reg = EE_AUDIO_TDMIN_A_MASK0 + offset * index;
}
aml_audiobus_write(actrl, reg + lane, mask);
}
void aml_tdm_set_lane_channel_swap(
struct aml_audio_controller *actrl,
int stream, int index, int swap0, int swap1)
{
unsigned int offset, reg;
pr_debug("\t %s swap0 = %#x, swap1 = %#x\n",
(stream == SNDRV_PCM_STREAM_PLAYBACK) ? "tdmout" : "tdmin",
swap0,
swap1);
if (stream == SNDRV_PCM_STREAM_PLAYBACK) {
offset = EE_AUDIO_TDMOUT_B_SWAP0
- EE_AUDIO_TDMOUT_A_SWAP0;
reg = EE_AUDIO_TDMOUT_A_SWAP0 + offset * index;
aml_audiobus_write(actrl, reg, swap0);
if (swap1) {
offset = EE_AUDIO_TDMOUT_B_SWAP1
- EE_AUDIO_TDMOUT_A_SWAP1;
reg = EE_AUDIO_TDMOUT_A_SWAP1 + offset * index;
aml_audiobus_write(actrl, reg, swap1);
}
} else {
offset = EE_AUDIO_TDMIN_B_SWAP0
- EE_AUDIO_TDMIN_A_SWAP0;
reg = EE_AUDIO_TDMIN_A_SWAP0 + offset * index;
aml_audiobus_write(actrl, reg, swap0);
if (swap1) {
offset = EE_AUDIO_TDMIN_B_SWAP1
- EE_AUDIO_TDMIN_A_SWAP1;
reg = EE_AUDIO_TDMIN_A_SWAP1 + offset * index;
aml_audiobus_write(actrl, reg, swap1);
}
}
}
void aml_tdm_set_bclk_ratio(
struct aml_audio_controller *actrl,
int clk_sel, int lrclk_hi, int bclk_ratio)
{
unsigned int reg, reg_step = 2;
reg = EE_AUDIO_MST_A_SCLK_CTRL0 + reg_step * clk_sel;
aml_audiobus_update_bits(actrl, reg,
(3 << 30)|0x3ff<<10|0x3ff,
(3 << 30)|lrclk_hi<<10|bclk_ratio);
}
void aml_tdm_set_lrclkdiv(
struct aml_audio_controller *actrl,
int clk_sel, int ratio)
{
unsigned int reg, reg_step = 2;
pr_debug("aml_dai_set_clkdiv, clksel(%d), ratio(%d)\n",
clk_sel, ratio);
reg = EE_AUDIO_MST_A_SCLK_CTRL0 + reg_step * clk_sel;
aml_audiobus_update_bits(actrl, reg,
(3 << 30)|(0x3ff << 20),
(3 << 30)|(ratio << 20));
}
void aml_tdmout_select_aed(bool enable, int tdmout_id)
{
unsigned int reg, offset;
/* select eq_drc output */
offset = EE_AUDIO_TDMOUT_B_CTRL1
- EE_AUDIO_TDMOUT_A_CTRL1;
reg = EE_AUDIO_TDMOUT_A_CTRL1 + offset * tdmout_id;
audiobus_update_bits(reg, 0x1 << 31, enable << 31);
}
void aml_tdmout_get_aed_info(int tdmout_id,
int *bitwidth, int *frddrtype)
{
unsigned int reg, offset, val;
offset = EE_AUDIO_TDMOUT_B_CTRL1
- EE_AUDIO_TDMOUT_A_CTRL1;
reg = EE_AUDIO_TDMOUT_A_CTRL1 + offset * tdmout_id;
val = audiobus_read(reg);
if (bitwidth)
*bitwidth = (val >> 8) & 0x1f;
if (frddrtype)
*frddrtype = (val >> 4) & 0x7;
}
void aml_tdmout_enable_gain(int tdmout_id, int en)
{
unsigned int reg, offset;
offset = EE_AUDIO_TDMOUT_B_CTRL1
- EE_AUDIO_TDMOUT_A_CTRL1;
reg = EE_AUDIO_TDMOUT_A_CTRL1 + offset * tdmout_id;
audiobus_update_bits(reg, 0x1 << 26, !!en << 26);
}
void aml_tdm_clk_pad_select(
struct aml_audio_controller *actrl,
int mpad, int mpad_offset, int mclk_sel,
int tdm_index, int clk_sel)
{
unsigned int reg, mask_offset, val_offset;
if (mpad >= 0) {
switch (mpad) {
case 0:
mask_offset = 0x7 << 0;
val_offset = mclk_sel << 0;
break;
case 1:
mask_offset = 0x7 << 4;
val_offset = mclk_sel << 4;
break;
default:
mask_offset = 0;
val_offset = 0;
pr_info("unknown tdm mpad:%d\n", mpad);
break;
}
reg = EE_AUDIO_MST_PAD_CTRL0(mpad_offset);
if (actrl)
aml_audiobus_update_bits(actrl, reg,
mask_offset, val_offset);
else
audiobus_update_bits(reg,
mask_offset, val_offset);
} else
pr_warn("mclk is not configured\n");
reg = EE_AUDIO_MST_PAD_CTRL1(mpad_offset);
switch (tdm_index) {
case 0:
mask_offset = 0x7 << 16 | 0x7 << 0;
val_offset = clk_sel << 16 | clk_sel << 0;
break;
case 1:
mask_offset = 0x7 << 20 | 0x7 << 4;
val_offset = clk_sel << 20 | clk_sel << 4;
break;
case 2:
mask_offset = 0x7 << 24 | 0x7 << 8;
val_offset = clk_sel << 24 | clk_sel << 8;
break;
default:
pr_err("unknown mclk pad, tdm index:%d\n", tdm_index);
return;
}
if (actrl)
aml_audiobus_update_bits(actrl, reg,
mask_offset, val_offset);
else
audiobus_update_bits(reg,
mask_offset, val_offset);
}
void i2s_to_hdmitx_ctrl(int tdm_index)
{
audiobus_write(EE_AUDIO_TOHDMITX_CTRL0,
1 << 31
| tdm_index << 12 /* dat_sel */
| tdm_index << 8 /* lrclk_sel */
| 1 << 7 /* Bclk_cap_inv */
| 0 << 6 /* Bclk_o_inv */
| tdm_index << 4 /* Bclk_sel */
);
}
void aml_tdm_mute_playback(
struct aml_audio_controller *actrl,
int tdm_index,
bool mute)
{
unsigned int offset, reg;
unsigned int mute_mask = 0xffffffff;
unsigned int mute_val = 0;
int i = 0, lanes = 4;
if (mute)
mute_val = 0xffffffff;
offset = EE_AUDIO_TDMOUT_B_MUTE0
- EE_AUDIO_TDMOUT_A_MUTE0;
reg = EE_AUDIO_TDMOUT_A_MUTE0 + offset * tdm_index;
for (i = 0; i < lanes; i++)
aml_audiobus_update_bits(actrl, reg + i, mute_mask, mute_val);
}
void aml_tdm_mute_capture(
struct aml_audio_controller *actrl,
int tdm_index,
bool mute)
{
unsigned int offset, reg;
unsigned int mute_mask = 0xffffffff;
unsigned int mute_val = 0;
int i = 0, lanes = 4;
if (mute)
mute_val = 0xffffffff;
offset = EE_AUDIO_TDMIN_B_MUTE0
- EE_AUDIO_TDMIN_A_MUTE0;
reg = EE_AUDIO_TDMIN_A_MUTE0 + offset * tdm_index;
for (i = 0; i < lanes; i++)
aml_audiobus_update_bits(actrl, reg + i, mute_mask, mute_val);
}