Files
Niranjan Dighe aaa19719df sound: safety-i2s: Add support for always-on rx/tx
Add support for keeping RX/TX always ON by using amixer commands
and to not disable clocks after playback/capture usecases finish.
This is to prevent A2B master from losing internal state.

Bug 3742979

Change-Id: I01dacaa3f54c98a7a14be101d8f0a315b006d7d8
Signed-off-by: Niranjan Dighe <ndighe@nvidia.com>
Reviewed-on: https://git-master.nvidia.com/r/c/linux-nv-oot/+/2966000
Reviewed-by: Uday Gupta <udayg@nvidia.com>
Reviewed-by: Laxman Dewangan <ldewangan@nvidia.com>
GVS: Gerrit_Virtual_Submit <buildbot_gerritrpt@nvidia.com>
Tested-by: Purvi Medawala <pmedawala@nvidia.com>
2023-10-17 18:44:37 -07:00

132 lines
2.7 KiB
C

/* SPDX-License-Identifier: GPL-2.0-only */
/*
* Copyright (c) 2021-2023 NVIDIA CORPORATION & AFFILIATES. All rights reserved.
*/
#ifndef _TEGRA_I2S_H_
#define _TEGRA_I2S_H_
#define PCM_STREAM_PLAYBACK 0
#define PCM_STREAM_CAPTURE 1
#define NUM_SAFETY_I2S_INST 2
#define I2S_DT_NODE "i2s%u"
#define I2S_NODE_START_INDEX 7
enum clock_mode {
I2S_SLAVE = 0,
I2S_MASTER
};
enum edge_ctrl {
I2S_CLK_POS_EDGE = 0,
I2S_CLK_NEG_EDGE
};
enum clock_polarity {
LRCK_LOW = 0,
LRCK_HIGH
};
enum i2s_mode {
I2S_FRAME_FORMAT_I2S = 0,
I2S_FRAME_FORMAT_TDM
};
enum i2s_clocks {
CLK_PLLA_OUT0,
CLK_I2S,
CLK_I2S_SOURCE,
CLK_I2S_SYNC,
CLK_AUDIO_SYNC,
CLK_AUDIO_INPUT_SYNC,
CLK_NUM_ENTRIES = CLK_AUDIO_INPUT_SYNC
};
struct i2s_config {
unsigned int mode;
unsigned int clock_mode;
unsigned int clock_polarity;
unsigned int edge_ctrl;
unsigned int total_slots;
unsigned int bclk;
unsigned int bit_size;
unsigned int channels;
unsigned int offset;
unsigned int tx_mask;
unsigned int rx_mask;
unsigned int srate;
unsigned int bclk_ratio;
unsigned int fsync_width;
unsigned int pcm_mask_bits;
unsigned int highz_ctrl;
unsigned int clock_trim;
unsigned int tx_always_on;
unsigned int rx_always_on;
};
struct dma_data {
const char *dma_chan_name;
unsigned long addr;
unsigned int size;
unsigned int width;
unsigned int req_sel;
unsigned int triggered;
};
struct i2s_dev {
volatile void __iomem *base;
struct dma_data capture_data;
struct dma_data playback_data;
struct clk *clk_i2s;
struct clk *clk_i2s_src;
struct clk *audio_sync;
struct clk *i2s_sync;
struct clk *audio_sync_input;
struct reset_control *reset;
struct i2s_config config;
};
struct i2s_dev *safety_i2s_get_priv(void);
#ifdef SAFETY_I2S_DEBUG
void i2s_dump_all_regs(unsigned int id);
#endif
int i2s_configure(unsigned int id, struct i2s_config *config);
/* Enable I2S controller */
unsigned int i2s_enable(unsigned int id);
/* Disable I2S controller */
unsigned int i2s_disable(unsigned int id);
/* Enable the Tx engine on I2S controller IO */
unsigned int i2s_enable_tx(unsigned int id);
/* Disable the Tx engine on I2S controller IO */
unsigned int i2s_disable_tx(unsigned int id);
/* Enable the Rx engine on I2S controller IO */
unsigned int i2s_enable_rx(unsigned int id);
/* Disable the Rx engine on I2S controller IO */
unsigned int i2s_disable_rx(unsigned int id);
static inline void
updatel(volatile void __iomem *addr, unsigned int mask, unsigned int val)
{
unsigned int prev_val, new_val;
prev_val = readl(addr);
new_val = (prev_val & (~mask)) | (val & mask);
writel(new_val, addr);
}
/* Enable/Disable digital loopback with I2S controller */
unsigned int i2s_set_loopback(unsigned int id, unsigned int enable);
#endif /* _TEGRA_I2S_H_ */