mirror of
git://nv-tegra.nvidia.com/linux-nv-oot.git
synced 2025-12-22 09:11:26 +03:00
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>
132 lines
2.7 KiB
C
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_ */
|