static void tegra30_dam_write_coeff_ram(struct tegra30_dam_context *dam, int fsin, int fsout) { u32 val; int i, *coefRam = NULL; tegra30_dam_writel(dam, 0x00002000, TEGRA30_DAM_AUDIORAMCTL_DAM_CTRL_0); switch(fsin) { case TEGRA30_AUDIO_SAMPLERATE_8000: if (fsout == TEGRA30_AUDIO_SAMPLERATE_48000) coefRam = coefRam8To48; else if (fsout == TEGRA30_AUDIO_SAMPLERATE_44100) coefRam = coefRam8To44; else if (fsout == TEGRA30_AUDIO_SAMPLERATE_16000) coefRam = coefRam8To16; break; case TEGRA30_AUDIO_SAMPLERATE_16000: if (fsout == TEGRA30_AUDIO_SAMPLERATE_48000) coefRam = coefRam16To48; else if (fsout == TEGRA30_AUDIO_SAMPLERATE_44100) coefRam = coefRam16To44; else if (fsout == TEGRA30_AUDIO_SAMPLERATE_8000) coefRam = coefRam16To8; break; case TEGRA30_AUDIO_SAMPLERATE_44100: if (fsout == TEGRA30_AUDIO_SAMPLERATE_8000) coefRam = coefRam44To8; else if (fsout == TEGRA30_AUDIO_SAMPLERATE_16000) coefRam = coefRam44To16; break; case TEGRA30_AUDIO_SAMPLERATE_48000: if (fsout == TEGRA30_AUDIO_SAMPLERATE_8000) coefRam = coefRam48To8; else if (fsout == TEGRA30_AUDIO_SAMPLERATE_16000) coefRam = coefRam48To16; break; default: break; } tegra30_dam_writel(dam, 0x00005000, TEGRA30_DAM_AUDIORAMCTL_DAM_CTRL_0); if (coefRam) { for (i = 0; i < 64; i++) { val = coefRam[i]; tegra30_dam_writel(dam, val, TEGRA30_DAM_AUDIORAMCTL_DAM_DATA_0); } } }
static void tegra30_dam_set_biquad_fixed_coef(struct tegra30_dam_context *dam) { u32 val = TEGRA30_DAM_CH0_BIQUAD_FIXED_COEF_0_VAL; tegra30_dam_writel(dam, val, TEGRA30_DAM_CH0_BIQUAD_FIXED_COEF_0); }
static void tegra30_dam_set_input_samplerate(struct tegra30_dam_context *dam, int fsin) { u32 val; val = tegra30_dam_readl(dam, TEGRA30_DAM_CH0_CTRL); val &= ~TEGRA30_DAM_CH0_CTRL_FSIN_MASK; switch (fsin) { case TEGRA30_AUDIO_SAMPLERATE_8000: val |= TEGRA30_DAM_CH0_CTRL_FSIN_FS8; break; case TEGRA30_AUDIO_SAMPLERATE_16000: val |= TEGRA30_DAM_CH0_CTRL_FSIN_FS16; break; case TEGRA30_AUDIO_SAMPLERATE_44100: val |= TEGRA30_DAM_CH0_CTRL_FSIN_FS44; break; case TEGRA30_AUDIO_SAMPLERATE_48000: val |= TEGRA30_DAM_CH0_CTRL_FSIN_FS48; break; default: break; } tegra30_dam_writel(dam, val, TEGRA30_DAM_CH0_CTRL); }
int tegra30_dam_set_acif_stereo_conv(int ifc, int chtype, int conv) { unsigned int reg; unsigned int val = 0; if (ifc >= TEGRA30_NR_DAM_IFC) return -EINVAL; if ((conv != TEGRA30_CIF_STEREOCONV_CH0) && (conv != TEGRA30_CIF_STEREOCONV_CH1) && (conv != TEGRA30_CIF_STEREOCONV_AVG)) return -EINVAL; switch (chtype) { case dam_ch_out: reg = TEGRA30_DAM_AUDIOCIF_OUT_CTRL; break; case dam_ch_in0: reg = TEGRA30_DAM_AUDIOCIF_CH0_CTRL; break; case dam_ch_in1: reg = TEGRA30_DAM_AUDIOCIF_CH1_CTRL; break; default: return -EINVAL; } val = tegra30_dam_readl(dams_cont_info[ifc], reg); val &= ~TEGRA30_CIF_STEREOCONV_MASK; val |= conv; tegra30_dam_writel(dams_cont_info[ifc], val, reg); return 0; }
int tegra30_dam_set_acif(int ifc, int chid, unsigned int audio_channels, unsigned int audio_bits, unsigned int client_channels, unsigned int client_bits) { unsigned int reg; unsigned int value = 0; if (ifc >= TEGRA30_NR_DAM_IFC) return -EINVAL; #ifndef CONFIG_ARCH_TEGRA_3x_SOC /*ch0 takes input as mono always*/ if ((chid == dam_ch_in0) && ((client_channels != 1))) return -EINVAL; /*as per dam spec file chout is fixed to 32 bits*/ /*so accept ch0, ch1 and chout as 32bit always*/ if (client_bits != 32) return -EINVAL; #else /*ch0 takes input as mono/16bit always*/ if ((chid == dam_ch_in0) && ((client_channels != 1) || (client_bits != 16))) return -EINVAL; #endif value |= TEGRA30_AUDIOCIF_CTRL_MONO_CONV_COPY; value |= TEGRA30_AUDIOCIF_CTRL_STEREO_CONV_AVG; value |= (audio_channels-1) << TEGRA30_AUDIOCIF_CTRL_AUDIO_CHANNELS_SHIFT; value |= (((audio_bits>>2)-1) << TEGRA30_AUDIOCIF_CTRL_AUDIO_BITS_SHIFT); value |= (client_channels-1) << TEGRA30_AUDIOCIF_CTRL_CLIENT_CHANNELS_SHIFT; value |= (((client_bits>>2)-1) << TEGRA30_AUDIOCIF_CTRL_CLIENT_BITS_SHIFT); switch (chid) { case dam_ch_out: value |= TEGRA30_CIF_DIRECTION_TX; reg = TEGRA30_DAM_AUDIOCIF_OUT_CTRL; break; case dam_ch_in0: value |= TEGRA30_CIF_DIRECTION_RX; reg = TEGRA30_DAM_AUDIOCIF_CH0_CTRL; break; case dam_ch_in1: value |= TEGRA30_CIF_DIRECTION_RX; reg = TEGRA30_DAM_AUDIOCIF_CH1_CTRL; break; default: return -EINVAL; } tegra30_dam_writel(dams_cont_info[ifc], value, reg); return 0; }
static void tegra30_dam_enable_coeff_ram(struct tegra30_dam_context *dam) { u32 val; val = tegra30_dam_readl(dam, TEGRA30_DAM_CH0_CTRL); val |= TEGRA30_DAM_CH0_CTRL_COEFF_RAM_ENABLE; tegra30_dam_writel(dam, val, TEGRA30_DAM_CH0_CTRL); }
static void tegra30_dam_ch0_set_step(struct tegra30_dam_context *dam, int step) { u32 val; val = tegra30_dam_readl(dam, TEGRA30_DAM_CH0_CTRL); val &= ~TEGRA30_DAM_CH0_CTRL_STEP_MASK; val |= step << TEGRA30_DAM_CH0_CTRL_STEP_SHIFT; tegra30_dam_writel(dam, val, TEGRA30_DAM_CH0_CTRL); }
void tegra30_dam_enable_clip_counter(struct tegra30_dam_context *dam, int on) { u32 val; val = tegra30_dam_readl(dam, TEGRA30_DAM_CLIP); val &= ~TEGRA30_DAM_CLIP_COUNTER_ENABLE; val |= on ? TEGRA30_DAM_CLIP_COUNTER_ENABLE : 0; tegra30_dam_writel(dam, val, TEGRA30_DAM_CLIP); }
int tegra30_dam_set_gain(int ifc, int chid, int gain) { if (ifc >= TEGRA30_NR_DAM_IFC) return -EINVAL; switch (chid) { case dam_ch_in0: tegra30_dam_writel(dams_cont_info[ifc], gain, TEGRA30_DAM_CH0_CONV); break; case dam_ch_in1: tegra30_dam_writel(dams_cont_info[ifc], gain, TEGRA30_DAM_CH1_CONV); break; default: break; } return 0; }
void tegra30_dam_ch1_set_datasync(int ifc, int datasync) { u32 val; struct tegra30_dam_context *dam = NULL; dam = dams_cont_info[ifc]; val = tegra30_dam_readl(dam, TEGRA30_DAM_CH1_CTRL); val &= ~TEGRA30_DAM_CH1_CTRL_DATA_SYNC_MASK; val |= datasync << TEGRA30_DAM_DATA_SYNC_SHIFT; tegra30_dam_writel(dam, val, TEGRA30_DAM_CH1_CTRL); }
int tegra30_dam_soft_reset(int ifc) { int dcnt = 10; u32 val; struct tegra30_dam_context *dam = NULL; dam = dams_cont_info[ifc]; val = tegra30_dam_readl(dam, TEGRA30_DAM_CTRL); val |= TEGRA30_DAM_CTRL_SOFT_RESET_ENABLE; tegra30_dam_writel(dam, val, TEGRA30_DAM_CTRL); while ((tegra30_dam_readl(dam, TEGRA30_DAM_CTRL) & TEGRA30_DAM_CTRL_SOFT_RESET_ENABLE) && dcnt--) udelay(100); /* Restore reg_ctrl to ensure if a concurrent playback/capture session was active it continues after SOFT_RESET */ val &= ~TEGRA30_DAM_CTRL_SOFT_RESET_ENABLE; tegra30_dam_writel(dam, val, TEGRA30_DAM_CTRL); return (dcnt < 0) ? -ETIMEDOUT : 0; }
void tegra30_dam_enable_stereo_mixing(int ifc, int on) { u32 val; if ((ifc < 0) || (ifc >= TEGRA30_NR_DAM_IFC)) return; val = tegra30_dam_readl(dams_cont_info[ifc], TEGRA30_DAM_CTRL); if (on) val |= TEGRA30_DAM_CTRL_STEREO_MIXING_ENABLE; else val &= ~TEGRA30_DAM_CTRL_STEREO_MIXING_ENABLE; tegra30_dam_writel(dams_cont_info[ifc], val, TEGRA30_DAM_CTRL); }
static void tegra30_dam_set_filter_stages(struct tegra30_dam_context *dam, int fsin, int fsout) { u32 val; int filt_stages = 0; val = tegra30_dam_readl(dam, TEGRA30_DAM_CH0_CTRL); switch(fsin) { case TEGRA30_AUDIO_SAMPLERATE_8000: if (fsout == TEGRA30_AUDIO_SAMPLERATE_48000) filt_stages = 1; else if (fsout == TEGRA30_AUDIO_SAMPLERATE_44100) filt_stages = 2; else if (fsout == TEGRA30_AUDIO_SAMPLERATE_16000) filt_stages = 0; break; case TEGRA30_AUDIO_SAMPLERATE_16000: if (fsout == TEGRA30_AUDIO_SAMPLERATE_48000) filt_stages = 0; else if (fsout == TEGRA30_AUDIO_SAMPLERATE_44100) filt_stages = 3; else if (fsout == TEGRA30_AUDIO_SAMPLERATE_8000) filt_stages = 0; break; case TEGRA30_AUDIO_SAMPLERATE_44100: if (fsout == TEGRA30_AUDIO_SAMPLERATE_8000) filt_stages = 2; else if (fsout == TEGRA30_AUDIO_SAMPLERATE_16000) filt_stages = 2; break; case TEGRA30_AUDIO_SAMPLERATE_48000: if (fsout == TEGRA30_AUDIO_SAMPLERATE_8000) filt_stages = 1; else if (fsout == TEGRA30_AUDIO_SAMPLERATE_16000) filt_stages = 0; break; default: break; } val |= filt_stages << TEGRA30_DAM_CH0_CTRL_FILT_STAGES_SHIFT; tegra30_dam_writel(dam, val, TEGRA30_DAM_CH0_CTRL); }
static void tegra30_dam_set_farrow_param(struct tegra30_dam_context *dam, int fsin, int fsout) { u32 val = TEGRA30_FARROW_PARAM_RESET; switch(fsin) { case TEGRA30_AUDIO_SAMPLERATE_8000: if (fsout == TEGRA30_AUDIO_SAMPLERATE_48000) val = TEGRA30_FARROW_PARAM_1; else if (fsout == TEGRA30_AUDIO_SAMPLERATE_44100) val = TEGRA30_FARROW_PARAM_2; else if (fsout == TEGRA30_AUDIO_SAMPLERATE_16000) val = TEGRA30_FARROW_PARAM_1; break; case TEGRA30_AUDIO_SAMPLERATE_16000: if (fsout == TEGRA30_AUDIO_SAMPLERATE_48000) val = TEGRA30_FARROW_PARAM_1; else if (fsout == TEGRA30_AUDIO_SAMPLERATE_44100) val = TEGRA30_FARROW_PARAM_2; else if (fsout == TEGRA30_AUDIO_SAMPLERATE_8000) val = TEGRA30_FARROW_PARAM_1; break; case TEGRA30_AUDIO_SAMPLERATE_44100: if (fsout == TEGRA30_AUDIO_SAMPLERATE_8000) val = TEGRA30_FARROW_PARAM_3; else if (fsout == TEGRA30_AUDIO_SAMPLERATE_16000) val = TEGRA30_FARROW_PARAM_3; break; case TEGRA30_AUDIO_SAMPLERATE_48000: if (fsout == TEGRA30_AUDIO_SAMPLERATE_8000) val = TEGRA30_FARROW_PARAM_1; else if (fsout == TEGRA30_AUDIO_SAMPLERATE_16000) val = TEGRA30_FARROW_PARAM_1; break; default: break; } tegra30_dam_writel(dam, val, TEGRA30_DAM_FARROW_PARAM_0); }
void tegra30_dam_enable(int ifc, int on, int chid) { u32 old_val, val, enreg; u32 old_val_dam, val_dam; int dcnt = 10; struct tegra30_dam_context *dam; if ((ifc < 0) || (ifc >= TEGRA30_NR_DAM_IFC) || (chid < dam_ch_in0) || (chid > dam_ch_in1)) return; dam = dams_cont_info[ifc]; if (chid == dam_ch_in0) enreg = TEGRA30_DAM_CH0_CTRL; else enreg = TEGRA30_DAM_CH1_CTRL; old_val = val = tegra30_dam_readl(dam, enreg); if (on) { if (!dam->ch_enable_refcnt[chid]++) val |= TEGRA30_DAM_CH0_CTRL_EN; } else if (dam->ch_enable_refcnt[chid]) { dam->ch_enable_refcnt[chid]--; if (!dam->ch_enable_refcnt[chid]) val &= ~TEGRA30_DAM_CH0_CTRL_EN; } old_val_dam = val_dam = tegra30_dam_readl(dam, TEGRA30_DAM_CTRL); if (dam->ch_enable_refcnt[dam_ch_in0] || dam->ch_enable_refcnt[dam_ch_in1]) val_dam |= TEGRA30_DAM_CTRL_DAM_EN; else val_dam &= ~TEGRA30_DAM_CTRL_DAM_EN; if (val != old_val) { tegra30_dam_writel(dam, val, enreg); if (!on) { if (chid == dam_ch_in0) { while (!tegra30_ahub_dam_ch0_is_empty(ifc) && dcnt--) udelay(100); dcnt = 10; } else { while (!tegra30_ahub_dam_ch1_is_empty(ifc) && dcnt--) udelay(100); dcnt = 10; } } } if (old_val_dam != val_dam) { tegra30_dam_writel(dam, val_dam, TEGRA30_DAM_CTRL); if (!on) { while (!tegra30_ahub_dam_tx_is_empty(ifc) && dcnt--) udelay(100); dcnt = 10; } } }