/* deassert reset on ABB */
regmap_read(i2s->sysctrl, SC_PERIPH_RSTSTAT2, &val); if (val & BIT(4))
regmap_write(i2s->sysctrl, SC_PERIPH_RSTDIS2, BIT(4));
for (n = 0; n < i2s->clocks; n++) {
ret = clk_prepare_enable(i2s->clk[n]); if (ret) goto err_unprepare_clk;
}
ret = clk_set_rate(i2s->clk[CLK_I2S_BASE], 49152000); if (ret) {
dev_err(i2s->dev, "%s: setting 49.152MHz base rate failed %d\n",
__func__, ret); goto err_unprepare_clk;
}
/* enable clock before frequency division */
regmap_write(i2s->sysctrl, SC_PERIPH_CLKEN12, BIT(9));
/* enable codec working clock / == "codec bus clock" */
regmap_write(i2s->sysctrl, SC_PERIPH_CLKEN1, BIT(5));
/* deassert reset on codec / interface clock / working clock */
regmap_write(i2s->sysctrl, SC_PERIPH_RSTEN1, BIT(5));
regmap_write(i2s->sysctrl, SC_PERIPH_RSTDIS1, BIT(5));
/* not interested in i2s irqs */
val = hi6210_read_reg(i2s, HII2S_CODEC_IRQ_MASK);
val |= 0x3f;
hi6210_write_reg(i2s, HII2S_CODEC_IRQ_MASK, val);
/* reset the stereo downlink fifo */
val = hi6210_read_reg(i2s, HII2S_APB_AFIFO_CFG_1);
val |= (BIT(5) | BIT(4));
hi6210_write_reg(i2s, HII2S_APB_AFIFO_CFG_1, val);
val = hi6210_read_reg(i2s, HII2S_APB_AFIFO_CFG_1);
val &= ~(BIT(5) | BIT(4));
hi6210_write_reg(i2s, HII2S_APB_AFIFO_CFG_1, val);
val = hi6210_read_reg(i2s, HII2S_SW_RST_N);
val &= ~(HII2S_SW_RST_N__ST_DL_WORDLEN_MASK <<
HII2S_SW_RST_N__ST_DL_WORDLEN_SHIFT);
val |= (HII2S_BITS_16 << HII2S_SW_RST_N__ST_DL_WORDLEN_SHIFT);
hi6210_write_reg(i2s, HII2S_SW_RST_N, val);
val = hi6210_read_reg(i2s, HII2S_MISC_CFG); /* mux 11/12 = APB not i2s */
val &= ~HII2S_MISC_CFG__ST_DL_TEST_SEL; /* BT R ch 0 = mixer op of DACR ch */
val &= ~HII2S_MISC_CFG__S2_DOUT_RIGHT_SEL;
val &= ~HII2S_MISC_CFG__S2_DOUT_TEST_SEL;
val |= HII2S_MISC_CFG__S2_DOUT_RIGHT_SEL; /* BT L ch = 1 = mux 7 = "mixer output of DACL */
val |= HII2S_MISC_CFG__S2_DOUT_TEST_SEL;
hi6210_write_reg(i2s, HII2S_MISC_CFG, val);
val = hi6210_read_reg(i2s, HII2S_SW_RST_N);
val |= HII2S_SW_RST_N__SW_RST_N;
hi6210_write_reg(i2s, HII2S_SW_RST_N, val);
return 0;
err_unprepare_clk: while (n--)
clk_disable_unprepare(i2s->clk[n]); return ret;
}
/* * We don't actually set the hardware until the hw_params * call, but we need to validate the user input here.
*/ switch (fmt & SND_SOC_DAIFMT_CLOCK_PROVIDER_MASK) { case SND_SOC_DAIFMT_BC_FC: case SND_SOC_DAIFMT_BP_FP: break; default: return -EINVAL;
}
switch (fmt & SND_SOC_DAIFMT_FORMAT_MASK) { case SND_SOC_DAIFMT_I2S: case SND_SOC_DAIFMT_LEFT_J: case SND_SOC_DAIFMT_RIGHT_J: break; default: return -EINVAL;
}
switch (i2s->channels) { case 1:
val = hi6210_read_reg(i2s, HII2S_I2S_CFG);
val |= HII2S_I2S_CFG__S2_FRAME_MODE;
hi6210_write_reg(i2s, HII2S_I2S_CFG, val); break; default:
val = hi6210_read_reg(i2s, HII2S_I2S_CFG);
val &= ~HII2S_I2S_CFG__S2_FRAME_MODE;
hi6210_write_reg(i2s, HII2S_I2S_CFG, val); break;
}
/* clear loopback, set signed type and word length */
val = hi6210_read_reg(i2s, HII2S_I2S_CFG);
val &= ~HII2S_I2S_CFG__S2_CODEC_DATA_FORMAT;
val &= ~(HII2S_I2S_CFG__S2_CODEC_IO_WORDLENGTH_MASK <<
HII2S_I2S_CFG__S2_CODEC_IO_WORDLENGTH_SHIFT);
val &= ~(HII2S_I2S_CFG__S2_DIRECT_LOOP_MASK <<
HII2S_I2S_CFG__S2_DIRECT_LOOP_SHIFT);
val |= signed_data;
val |= (bits << HII2S_I2S_CFG__S2_CODEC_IO_WORDLENGTH_SHIFT);
hi6210_write_reg(i2s, HII2S_I2S_CFG, val);
if (!i2s->master) return 0;
/* set DAC and related units to correct rate */
val = hi6210_read_reg(i2s, HII2S_FS_CFG);
val &= ~(HII2S_FS_CFG__FS_S2_MASK << HII2S_FS_CFG__FS_S2_SHIFT);
val &= ~(HII2S_FS_CFG__FS_DACLR_MASK << HII2S_FS_CFG__FS_DACLR_SHIFT);
val &= ~(HII2S_FS_CFG__FS_ST_DL_R_MASK <<
HII2S_FS_CFG__FS_ST_DL_R_SHIFT);
val &= ~(HII2S_FS_CFG__FS_ST_DL_L_MASK <<
HII2S_FS_CFG__FS_ST_DL_L_SHIFT);
val |= (rate << HII2S_FS_CFG__FS_S2_SHIFT);
val |= (rate << HII2S_FS_CFG__FS_DACLR_SHIFT);
val |= (rate << HII2S_FS_CFG__FS_ST_DL_R_SHIFT);
val |= (rate << HII2S_FS_CFG__FS_ST_DL_L_SHIFT);
hi6210_write_reg(i2s, HII2S_FS_CFG, val);
return 0;
}
staticint hi6210_i2s_trigger(struct snd_pcm_substream *substream, int cmd, struct snd_soc_dai *cpu_dai)
{
pr_debug("%s\n", __func__); switch (cmd) { case SNDRV_PCM_TRIGGER_START: case SNDRV_PCM_TRIGGER_PAUSE_RELEASE: if (substream->stream == SNDRV_PCM_STREAM_CAPTURE)
hi6210_i2s_rxctrl(cpu_dai, 1); else
hi6210_i2s_txctrl(cpu_dai, 1); break; case SNDRV_PCM_TRIGGER_STOP: case SNDRV_PCM_TRIGGER_PAUSE_PUSH: if (substream->stream == SNDRV_PCM_STREAM_CAPTURE)
hi6210_i2s_rxctrl(cpu_dai, 0); else
hi6210_i2s_txctrl(cpu_dai, 0); break; default:
dev_err(cpu_dai->dev, "unknown cmd\n"); return -EINVAL;
} return 0;
}
Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.
Bemerkung:
Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.