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; }
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); }
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); }
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 int tegra30_dam_show(struct seq_file *s, void *unused) { #define REG(r) { r, #r } static const struct { int offset; const char *name; } regs[] = { REG(TEGRA30_DAM_CTRL), REG(TEGRA30_DAM_CLIP), REG(TEGRA30_DAM_CLIP_THRESHOLD), REG(TEGRA30_DAM_AUDIOCIF_OUT_CTRL), REG(TEGRA30_DAM_CH0_CTRL), REG(TEGRA30_DAM_CH0_CONV), REG(TEGRA30_DAM_AUDIOCIF_CH0_CTRL), REG(TEGRA30_DAM_CH1_CTRL), REG(TEGRA30_DAM_CH1_CONV), REG(TEGRA30_DAM_AUDIOCIF_CH1_CTRL), }; #undef REG struct tegra30_dam_context *dam = s->private; int i; tegra30_ahub_enable_clocks(); clk_enable(dam->dam_clk); for (i = 0; i < ARRAY_SIZE(regs); i++) { u32 val = tegra30_dam_readl(dam, regs[i].offset); seq_printf(s, "%s = %08x\n", regs[i].name, val); } clk_disable(dam->dam_clk); tegra30_ahub_disable_clocks(); return 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; } } }