return 0;
}
+#include <plat/mcbsp.h>
+
+static struct omap_mcbsp_reg_cfg cfg = {
+ .spcr2 = XINTM(3) | FREE,
+ .spcr1 = RINTM(3),
+ .rcr2 = RPHASE | RWDLEN2(OMAP_MCBSP_WORD_16) | RDATDLY(1),
+ .rcr1 = RWDLEN1(OMAP_MCBSP_WORD_16),
+ .xcr2 = XPHASE | XWDLEN2(OMAP_MCBSP_WORD_16) | XDATDLY(1),
+ .xcr1 = XWDLEN1(OMAP_MCBSP_WORD_16),
+ .srgr2 = FSGM | FPER(32 - 1),
+ .srgr1 = FWID(32 / 2 - 1) | CLKGDV(8 - 1),
+ .pcr0 = FSXM | FSRM | CLKXM | CLKRM | FSXP | FSRP | CLKXP | CLKRP,
+ .xccr = DXENDLY(1) | XDISABLE,
+ .rccr = RFULL_CYCLE | RDISABLE,
+};
+
+/* to power down the DAC properly, it's not enough to just set the GPIO,
+ * the clocks must be running. What's worse, SCKI (256fs) is not enough,
+ * the other clocks must be running too, and for that McBSP must be started,
+ * so here are some horrible functions */
+static int mcbsp2_clocking_start(void)
+{
+ int ret;
+
+ ret = omap_mcbsp_request(1);
+ if (ret != 0) {
+ pr_err("%s: request mcbsp2: %d\n", __func__, ret);
+ return ret;
+ }
+ omap2_mcbsp_set_clks_src(1, MCBSP_CLKS_PAD_SRC);
+
+ cfg.xccr &= ~XDMAEN,
+ cfg.rccr &= ~RDMAEN,
+ omap_mcbsp_config(1, &cfg);
+
+ omap_mcbsp_start(1, 1, 0);
+
+ /* according to TRM "21.4.4.5 Underflow in the Transmitter",
+ * now it should output zeros on mcbspi_dx, so it's enough to sleep */
+ return 0;
+}
+
+static void mcbsp2_clocking_stop(void)
+{
+ omap_mcbsp_stop(1, 1, 0);
+
+ cfg.xccr |= XDMAEN,
+ cfg.rccr |= RDMAEN,
+ omap_mcbsp_config(1, &cfg);
+
+ omap2_mcbsp_set_clks_src(1, MCBSP_CLKS_PRCM_SRC);
+ omap_mcbsp_free(1);
+}
+
static int omap3pandora_dac_event(struct snd_soc_dapm_widget *w,
struct snd_kcontrol *k, int event)
{
- /*
- * The PCM1773 DAC datasheet requires 1ms delay between switching
- * VCC power on/off and /PD pin high/low
- */
if (SND_SOC_DAPM_EVENT_ON(event)) {
regulator_enable(omap3pandora_dac_reg);
- mdelay(1);
+ /* can only set /PD from low to high 1ms after
+ * power and clock stabilize */
+ msleep(1);
gpio_set_value(OMAP3_PANDORA_DAC_POWER_GPIO, 1);
} else {
+ int ret = mcbsp2_clocking_start();
+
+ /* let it sync to the clocks (just in case) */
+ msleep(1);
+
gpio_set_value(OMAP3_PANDORA_DAC_POWER_GPIO, 0);
- regulator_disable_deferred(omap3pandora_dac_reg, 1);
+
+ /* 9334 (!) samples before power and clocks can be cut */
+ msleep(9334 * 1000 / 8000 + 1);
+
+ if (ret == 0)
+ mcbsp2_clocking_stop();
+ regulator_disable(omap3pandora_dac_reg);
}
return 0;