From: Grazvydas Ignotas Date: Mon, 4 Jul 2016 23:57:40 +0000 (+0300) Subject: ASoC: pandora: try to power down the DAC properly X-Git-Tag: sz_175~2 X-Git-Url: https://git.openpandora.org/cgi-bin/gitweb.cgi?p=pandora-kernel.git;a=commitdiff_plain;h=4af149ce9cd9620dff3ba17fc7c5660db990c7f0 ASoC: pandora: try to power down the DAC properly some nasty stuff, but without this, there is like 5-10mW loss --- diff --git a/sound/soc/omap/omap3pandora.c b/sound/soc/omap/omap3pandora.c index 40992277bb11..0d308f9e1e1e 100644 --- a/sound/soc/omap/omap3pandora.c +++ b/sound/soc/omap/omap3pandora.c @@ -101,20 +101,83 @@ static int omap3pandora_hw_free(struct snd_pcm_substream *substream) return 0; } +#include + +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;