From 7b70e5a8fae7ce8b0f9c74403c1efcc414297e35 Mon Sep 17 00:00:00 2001 From: Amaury Pouly Date: Tue, 18 Oct 2011 22:06:05 +0000 Subject: imx233/fuze+: implement audioout functions (init, volume, frequency); add stubs for audioin git-svn-id: svn://svn.rockbox.org/rockbox/trunk@30798 a1c6a512-1295-4272-9138-f99709370657 --- firmware/target/arm/imx233/audioin-imx233.c | 33 +++++ firmware/target/arm/imx233/audioin-imx233.h | 4 + firmware/target/arm/imx233/audioout-imx233.c | 179 +++++++++++++++++++++++++++ firmware/target/arm/imx233/audioout-imx233.h | 95 ++++++++++++++ 4 files changed, 311 insertions(+) create mode 100644 firmware/target/arm/imx233/audioin-imx233.c create mode 100644 firmware/target/arm/imx233/audioout-imx233.c (limited to 'firmware') diff --git a/firmware/target/arm/imx233/audioin-imx233.c b/firmware/target/arm/imx233/audioin-imx233.c new file mode 100644 index 0000000000..4c2ee657f9 --- /dev/null +++ b/firmware/target/arm/imx233/audioin-imx233.c @@ -0,0 +1,33 @@ +/*************************************************************************** + * __________ __ ___. + * Open \______ \ ____ ____ | | _\_ |__ _______ ___ + * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ / + * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < < + * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \ + * \/ \/ \/ \/ \/ + * $Id$ + * + * Copyright (C) 2011 by Amaury Pouly + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY + * KIND, either express or implied. + * + ****************************************************************************/ +#include "audioout-imx233.h" + +void imx233_audioin_preinit(void) +{ +} + +void imx233_audioin_postinit(void) +{ +} + +void imx233_audioin_close(void) +{ +} diff --git a/firmware/target/arm/imx233/audioin-imx233.h b/firmware/target/arm/imx233/audioin-imx233.h index d4468f8d4a..c13f7cef56 100644 --- a/firmware/target/arm/imx233/audioin-imx233.h +++ b/firmware/target/arm/imx233/audioin-imx233.h @@ -24,4 +24,8 @@ #include "config.h" #include "cpu.h" +void imx233_audioin_preinit(void); +void imx233_audioin_postinit(void); +void imx233_audioin_close(void); + #endif /* __audioin_imx233__ */ diff --git a/firmware/target/arm/imx233/audioout-imx233.c b/firmware/target/arm/imx233/audioout-imx233.c new file mode 100644 index 0000000000..0a48a909e8 --- /dev/null +++ b/firmware/target/arm/imx233/audioout-imx233.c @@ -0,0 +1,179 @@ +/*************************************************************************** + * __________ __ ___. + * Open \______ \ ____ ____ | | _\_ |__ _______ ___ + * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ / + * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < < + * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \ + * \/ \/ \/ \/ \/ + * $Id$ + * + * Copyright (C) 2011 by Amaury Pouly + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY + * KIND, either express or implied. + * + ****************************************************************************/ +#include "audioout-imx233.h" +#include "clkctrl-imx233.h" +#include "rtc-imx233.h" +#include "pcm_sampr.h" + +void imx233_audioout_preinit(void) +{ + /* Enable AUDIOOUT block */ + imx233_reset_block(&HW_AUDIOOUT_CTRL); + /* Enable digital filter clock */ + imx233_enable_xtal_clock(XTAL_FILT, true); + /* Enable DAC */ + __REG_CLR(HW_AUDIOOUT_ANACLKCTRL) = HW_AUDIOOUT_ANACLKCTRL__CLKGATE; + /* Set capless mode */ + __REG_CLR(HW_AUDIOOUT_PWRDN) = HW_AUDIOOUT_PWRDN__CAPLESS; + /* Set word-length to 16-bit */ + __REG_SET(HW_AUDIOOUT_CTRL) = HW_AUDIOOUT_CTRL__WORD_LENGTH; + /* Power up DAC */ + __REG_CLR(HW_AUDIOOUT_PWRDN) = HW_AUDIOOUT_PWRDN__DAC; + /* Hold HP to ground to avoid pop, then release and power up HP */ + __REG_SET(HW_AUDIOOUT_ANACTRL) = HW_AUDIOOUT_ANACTRL__HP_HOLD_GND; + __REG_SET(HW_RTC_PERSISTENT0) = HW_RTC_PERSISTENT0__SPARE__RELEASE_GND; + __REG_CLR(HW_AUDIOOUT_PWRDN) = HW_AUDIOOUT_PWRDN__HEADPHONE; + /* Set HP mode to AB */ + __REG_SET(HW_AUDIOOUT_ANACTRL) = HW_AUDIOOUT_ANACTRL__HP_CLASSAB; + /* Stop holding to ground */ + __REG_CLR(HW_AUDIOOUT_ANACTRL) = HW_AUDIOOUT_ANACTRL__HP_HOLD_GND; + /* Set dmawait count to 31 (see errata, workaround random stop) */ + __REG_CLR(HW_AUDIOOUT_CTRL) = HW_AUDIOOUT_CTRL__DMAWAIT_COUNT_BM; + __REG_SET(HW_AUDIOOUT_CTRL) = 31 << HW_AUDIOOUT_CTRL__DMAWAIT_COUNT_BP; +} + +void imx233_audioout_postinit(void) +{ + /* start converting audio */ + __REG_SET(HW_AUDIOOUT_CTRL) = HW_AUDIOOUT_CTRL__RUN; +} + +void imx233_audioout_close(void) +{ + /* Switch to class A */ + __REG_CLR(HW_AUDIOOUT_ANACTRL) = HW_AUDIOOUT_ANACTRL__HP_CLASSAB; + /* Hold HP to ground */ + __REG_SET(HW_AUDIOOUT_ANACTRL) = HW_AUDIOOUT_ANACTRL__HP_HOLD_GND; + /* Mute HP and power down */ + __REG_SET(HW_AUDIOOUT_HPVOL) = HW_AUDIOOUT_HPVOL__MUTE; + /* Power down HP */ + __REG_SET(HW_AUDIOOUT_PWRDN) = HW_AUDIOOUT_PWRDN__HEADPHONE; + /* Mute DAC */ + __REG_SET(HW_AUDIOOUT_DACVOLUME) = HW_AUDIOOUT_DACVOLUME__MUTE_LEFT + | HW_AUDIOOUT_DACVOLUME__MUTE_RIGHT; + /* Power down DAC */ + __REG_SET(HW_AUDIOOUT_PWRDN) = HW_AUDIOOUT_PWRDN__DAC; + /* Gate off DAC */ + __REG_SET(HW_AUDIOOUT_ANACLKCTRL) = HW_AUDIOOUT_ANACLKCTRL__CLKGATE; + /* Disable digital filter clock */ + imx233_enable_xtal_clock(XTAL_FILT, false); + /* will also gate off the module */ + __REG_CLR(HW_AUDIOOUT_CTRL) = HW_AUDIOOUT_CTRL__RUN; +} +/* volume in half dB */ +void imx233_audioout_set_dac_vol(int vol_l, int vol_r) +{ + /* minimum is -100dB and max is 0dB */ + vol_l = MAX(-200, MIN(vol_l, 0)); + vol_r = MAX(-200, MIN(vol_r, 0)); + /* unmute, enable zero cross and set volume. + * 0xff is 0dB */ + HW_AUDIOOUT_DACVOLUME = + (0xff + vol_l) << HW_AUDIOOUT_DACVOLUME__VOLUME_LEFT_BP | + (0xff + vol_r) << HW_AUDIOOUT_DACVOLUME__VOLUME_RIGHT_BP | + HW_AUDIOOUT_DACVOLUME__EN_ZCD; +} + +void imx233_audioout_set_hp_vol(int vol_l, int vol_r) +{ + uint32_t select = (HW_AUDIOOUT_HPVOL & HW_AUDIOOUT_HPVOL__SELECT); + /* minimum is -57.5dB and max is 6dB in DAC mode + * and -51.5dB / 12dB in Line1 mode */ + int min = select ? -103 : -115; + int max = select ? 24 : 12; + + vol_l = MAX(min, MIN(vol_l, max)); + vol_r = MAX(min, MIN(vol_r, max)); + /* unmute, enable zero cross and set volume. Keep select value. */ + HW_AUDIOOUT_HPVOL = + (max - vol_l) << HW_AUDIOOUT_HPVOL__VOL_LEFT_BP | + (max - vol_r) << HW_AUDIOOUT_HPVOL__VOL_RIGHT_BP | + select | + HW_AUDIOOUT_HPVOL__EN_MSTR_ZCD; +} + +void imx233_audioout_set_freq(int fsel) +{ + static struct + { + int base_mult; + int src_hold; + int src_int; + int src_frac; + }dacssr[HW_NUM_FREQ] = + { + HW_HAVE_8_([HW_FREQ_8] = { 0x1, 0x3, 0x17, 0xe00 } ,) + HW_HAVE_11_([HW_FREQ_11] = { 0x1, 0x3, 0x11, 0x37 } ,) + HW_HAVE_12_([HW_FREQ_12] = { 0x1, 0x3, 0xf, 0x13ff },) + HW_HAVE_16_([HW_FREQ_16] = { 0x1, 0x1, 0x17, 0xe00},) + HW_HAVE_22_([HW_FREQ_22] = { 0x1, 0x1, 0x11, 0x37 },) + HW_HAVE_24_([HW_FREQ_24] = { 0x1, 0x1, 0xf, 0x13ff },) + HW_HAVE_32_([HW_FREQ_32] = { 0x1, 0x0, 0x17, 0xe00},) + HW_HAVE_44_([HW_FREQ_44] = { 0x1, 0x0, 0x11, 0x37 },) + HW_HAVE_48_([HW_FREQ_48] = { 0x1, 0x0, 0xf, 0x13ff },) + HW_HAVE_64_([HW_FREQ_64] = { 0x2, 0x0, 0x17, 0xe00},) + HW_HAVE_88_([HW_FREQ_88] = { 0x2, 0x0, 0x11, 0x37 },) + HW_HAVE_96_([HW_FREQ_96] = { 0x2, 0x0, 0xf, 0x13ff },) + }; + + HW_AUDIOOUT_DACSRR = + dacssr[fsel].src_frac << HW_AUDIOOUT_DACSRR__SRC_FRAC_BP | + dacssr[fsel].src_int << HW_AUDIOOUT_DACSRR__SRC_INT_BP | + dacssr[fsel].src_hold << HW_AUDIOOUT_DACSRR__SRC_HOLD_BP | + dacssr[fsel].base_mult << HW_AUDIOOUT_DACSRR__BASEMULT_BP; + + #if 0 + /* Select base_mult and src_hold depending on the audio range: + * 0 < f <= 12000 --> base_mult = 1, src_hold = 3 (div by 4) + * 12000 < f <= 24000 --> base_mult = 1, src_hold = 1 (div by 2) + * 24000 < f <= 48000 --> base_mult = 1, src_hold = 0 (div by 1) + * 48000 < f <= 96000 --> base_mult = 2, src_hold = 0 (mul by 2) + * 96000 < f <= ..... --> base_mult = 4, src_hold = 0 (mul by 4) */ + int base_mult = 1; + int src_hold = 0; + if(f > 96000) + base_mult = 4; + else if(f > 48000) + base_mult = 2; + else if(f <= 12000) + src_hold = 3; + else if(f <= 24000) + src_hold = 1; + /* compute the divisor (a tricky to keep to do it with 32-bit words only) */ + int src_int = (750000 * base_mult) / (f * (src_hold + 1)); + int src_frac = ((750000 * base_mult - src_int * f * (src_hold + 1)) << 13) / (f * (src_hold + 1)); + + HW_AUDIOOUT_DACSRR = + src_frac << HW_AUDIOOUT_DACSRR__SRC_FRAC_BP | + src_int << HW_AUDIOOUT_DACSRR__SRC_INT_BP | + src_hold << HW_AUDIOOUT_DACSRR__SRC_HOLD_BP | + base_mult << HW_AUDIOOUT_DACSRR__BASEMULT_BP; + #endif +} + +/* select between DAC and Line1 */ +void imx233_audiout_select_hp_input(bool line1) +{ + if(line1) + __REG_SET(HW_AUDIOOUT_HPVOL) = HW_AUDIOOUT_HPVOL__SELECT; + else + __REG_CLR(HW_AUDIOOUT_HPVOL) = HW_AUDIOOUT_HPVOL__SELECT; +} diff --git a/firmware/target/arm/imx233/audioout-imx233.h b/firmware/target/arm/imx233/audioout-imx233.h index 913e633de0..cd997e7d31 100644 --- a/firmware/target/arm/imx233/audioout-imx233.h +++ b/firmware/target/arm/imx233/audioout-imx233.h @@ -23,5 +23,100 @@ #include "config.h" #include "cpu.h" +#include "system.h" + +#define HW_AUDIOOUT_BASE 0x80048000 + +#define HW_AUDIOOUT_CTRL (*(volatile uint32_t *)(HW_AUDIOOUT_BASE + 0x0)) +#define HW_AUDIOOUT_CTRL__RUN (1 << 0) +#define HW_AUDIOOUT_CTRL__FIFO_ERROR_IRQ_EN (1 << 1) +#define HW_AUDIOOUT_CTRL__FIFO_OVERFLOW_IRQ (1 << 2) +#define HW_AUDIOOUT_CTRL__FIFO_UNDERFLOW_IRQ (1 << 3) +#define HW_AUDIOOUT_CTRL__WORD_LENGTH (1 << 6) +#define HW_AUDIOOUT_CTRL__SS3D_EFFECT_BP 8 +#define HW_AUDIOOUT_CTRL__SS3D_EFFECT_BM (3 << 8) +#define HW_AUDIOOUT_CTRL__SS3D_EFFECT_OFF (0 << 8) +#define HW_AUDIOOUT_CTRL__SS3D_EFFECT_3 (1 << 8) +#define HW_AUDIOOUT_CTRL__SS3D_EFFECT_4P5 (2 << 8) +#define HW_AUDIOOUT_CTRL__SS3D_EFFECT_6 (3 << 8) +#define HW_AUDIOOUT_CTRL__DMAWAIT_COUNT_BP 16 +#define HW_AUDIOOUT_CTRL__DMAWAIT_COUNT_BM (0x1f << 16) + +#define HW_AUDIOOUT_DACSRR (*(volatile uint32_t *)(HW_AUDIOOUT_BASE + 0x20)) +#define HW_AUDIOOUT_DACSRR__SRC_FRAC_BP 0 +#define HW_AUDIOOUT_DACSRR__SRC_FRAC_BM (0x1ff << 0) +#define HW_AUDIOOUT_DACSRR__SRC_INT_BP 16 +#define HW_AUDIOOUT_DACSRR__SRC_INT_BM (0x1f << 16) +#define HW_AUDIOOUT_DACSRR__SRC_HOLD_BP 24 +#define HW_AUDIOOUT_DACSRR__SRC_HOLD_BM (0x7 << 24) +#define HW_AUDIOOUT_DACSRR__BASEMULT_BP 28 +#define HW_AUDIOOUT_DACSRR__BASEMULT_BM (0x7 << 28) +#define HW_AUDIOOUT_DACSRR__OSR (1 << 31) + +#define HW_AUDIOOUT_DACVOLUME (*(volatile uint32_t *)(HW_AUDIOOUT_BASE + 0x30)) +#define HW_AUDIOOUT_DACVOLUME__VOLUME_RIGHT_BP 0 +#define HW_AUDIOOUT_DACVOLUME__VOLUME_RIGHT_BM 0xff +#define HW_AUDIOOUT_DACVOLUME__MUTE_RIGHT (1 << 8) +#define HW_AUDIOOUT_DACVOLUME__VOLUME_UPDATE_RIGHT (1 << 12) +#define HW_AUDIOOUT_DACVOLUME__VOLUME_LEFT_BP 16 +#define HW_AUDIOOUT_DACVOLUME__VOLUME_LEFT_BM (0xff << 16) +#define HW_AUDIOOUT_DACVOLUME__MUTE_LEFT (1 << 24) +#define HW_AUDIOOUT_DACVOLUME__EN_ZCD (1 << 25) +#define HW_AUDIOOUT_DACVOLUME__VOLUME_UPDATE_LEFT (1 << 28) + +#define HW_AUDIOOUT_DACDEBUG (*(volatile uint32_t *)(HW_AUDIOOUT_BASE + 0x40)) +#define HW_AUDIOOUT_DACDEBUG__FIFO_STATUS 1 + + +#define HW_AUDIOOUT_HPVOL (*(volatile uint32_t *)(HW_AUDIOOUT_BASE + 0x50)) +#define HW_AUDIOOUT_HPVOL__VOL_RIGHT_BP 0 +#define HW_AUDIOOUT_HPVOL__VOL_RIGHT_BM (0x7f << 0) +#define HW_AUDIOOUT_HPVOL__VOL_LEFT_BP 8 +#define HW_AUDIOOUT_HPVOL__VOL_LEFT_BM (0x7f << 8) +#define HW_AUDIOOUT_HPVOL__SELECT (1 << 16) +#define HW_AUDIOOUT_HPVOL__MUTE (1 << 24) +#define HW_AUDIOOUT_HPVOL__EN_MSTR_ZCD (1 << 25) + +#define HW_AUDIOOUT_PWRDN (*(volatile uint32_t *)(HW_AUDIOOUT_BASE + 0x70)) +#define HW_AUDIOOUT_PWRDN__HEADPHONE (1 << 0) +#define HW_AUDIOOUT_PWRDN__CAPLESS (1 << 4) +#define HW_AUDIOOUT_PWRDN__ADC (1 << 8) +#define HW_AUDIOOUT_PWRDN__DAC (1 << 12) +#define HW_AUDIOOUT_PWRDN__RIGHT_ADC (1 << 16) +#define HW_AUDIOOUT_PWRDN__SPEAKER (1 << 24) + +#define HW_AUDIOOUT_REFCTRL (*(volatile uint32_t *)(HW_AUDIOOUT_BASE + 0x80)) +#define HW_AUDIOOUT_REFCTRL__LOW_PWR (1 << 19) + +#define HW_AUDIOOUT_ANACTRL (*(volatile uint32_t *)(HW_AUDIOOUT_BASE + 0x90)) +#define HW_AUDIOOUT_ANACTRL__HP_CLASSAB (1 << 4) +#define HW_AUDIOOUT_ANACTRL__HP_HOLD_GND (1 << 5) +#define HW_AUDIOOUT_ANACTRL__SHORTMODE_LR_BP 17 +#define HW_AUDIOOUT_ANACTRL__SHORTMODE_LR_BM (3 << 17) +#define HW_AUDIOOUT_ANACTRL__SHORTMODE_CM_BP 20 +#define HW_AUDIOOUT_ANACTRL__SHORTMODE_CM_BM (3 << 20) +#define HW_AUDIOOUT_ANACTRL__SHORT_LR_STS (1 << 24) +#define HW_AUDIOOUT_ANACTRL__SHORT_CM_STS (1 << 28) + +#define HW_AUDIOOUT_ANACLKCTRL (*(volatile uint32_t *)(HW_AUDIOOUT_BASE + 0xe0)) +#define HW_AUDIOOUT_ANACLKCTRL__DACDIV_BP 0 +#define HW_AUDIOOUT_ANACLKCTRL__DACDIV_BM (7 << 0) +#define HW_AUDIOOUT_ANACLKCTRL__CLKGATE (1 << 31) + +#define HW_AUDIOOUT_DATA (*(volatile uint32_t *)(HW_AUDIOOUT_BASE + 0xf0)) + +#define HW_AUDIOOUT_VERSION (*(volatile uint32_t *)(HW_AUDIOOUT_BASE + 0x200)) + + +void imx233_audioout_preinit(void); +void imx233_audioout_postinit(void); +void imx233_audioout_close(void); +/* volume in half dB */ +void imx233_audioout_set_dac_vol(int vol_l, int vol_r); +void imx233_audioout_set_hp_vol(int vol_l, int vol_r); +/* frequency index, NOT the frequency itself */ +void imx233_audioout_set_freq(int fsel); +/* select between DAC and Line1 */ +void imx233_audiout_select_hp_input(bool line1); #endif /* __audioout_imx233__ */ -- cgit v1.2.3