mirror of
https://github.com/Rockbox/rockbox.git
synced 2025-12-10 21:55:10 -05:00
Audio samplerate control for Gigabeat S: 8, 11.025, 12, 16, 22.050, 24, 32, 44.1 and 48 kHz.
git-svn-id: svn://svn.rockbox.org/rockbox/trunk@19178 a1c6a512-1295-4272-9138-f99709370657
This commit is contained in:
parent
0394ebe44d
commit
7c007f5d87
5 changed files with 214 additions and 17 deletions
|
|
@ -227,8 +227,9 @@ void audiohw_postinit(void)
|
||||||
wmc_write(WMC_DAC_CONTROL, WMC_DACOSR_128 | WMC_AMUTE);
|
wmc_write(WMC_DAC_CONTROL, WMC_DACOSR_128 | WMC_AMUTE);
|
||||||
|
|
||||||
/* Specific to HW clocking */
|
/* Specific to HW clocking */
|
||||||
wmc_write(WMC_CLOCK_GEN_CTRL, WMC_MCLKDIV_1_5 | WMC_BCLKDIV_8 | WMC_MS);
|
wmc_write_masked(WMC_CLOCK_GEN_CTRL, WMC_BCLKDIV_4 | WMC_MS,
|
||||||
wmc_write(WMC_ADDITIONAL_CTRL, WMC_SR_48KHZ); /* 44.1 */
|
WMC_BCLKDIV | WMC_MS | WMC_CLKSEL);
|
||||||
|
audiohw_set_frequency(HW_SAMPR_DEFAULT);
|
||||||
|
|
||||||
/* ADC silenced */
|
/* ADC silenced */
|
||||||
wmc_write_masked(WMC_LEFT_ADC_DIGITAL_VOL, 0x00, WMC_DVOL);
|
wmc_write_masked(WMC_LEFT_ADC_DIGITAL_VOL, 0x00, WMC_DVOL);
|
||||||
|
|
@ -354,6 +355,131 @@ void audiohw_mute(bool mute)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void audiohw_set_frequency(int sampling_control)
|
||||||
|
{
|
||||||
|
/* For 16.9344MHz MCLK */
|
||||||
|
static const struct
|
||||||
|
{
|
||||||
|
uint32_t plln : 8;
|
||||||
|
uint32_t pllk0 : 6;
|
||||||
|
uint32_t pllk1 : 9;
|
||||||
|
uint32_t pllk2 : 9;
|
||||||
|
unsigned char mclkdiv;
|
||||||
|
unsigned char filter;
|
||||||
|
} sctrl_table[HW_NUM_FREQ] =
|
||||||
|
{
|
||||||
|
[HW_FREQ_8] = /* PLL = 65.536MHz */
|
||||||
|
{
|
||||||
|
.plln = WMC_PLLNw(7) | WMC_PLL_PRESCALE,
|
||||||
|
.pllk0 = WMC_PLLK_23_18w(12414886 >> 18),
|
||||||
|
.pllk1 = WMC_PLLK_17_9w(12414886 >> 9),
|
||||||
|
.pllk2 = WMC_PLLK_8_0w(12414886 >> 0),
|
||||||
|
.mclkdiv = WMC_MCLKDIV_8, /* 2.0480 MHz */
|
||||||
|
.filter = WMC_SR_8KHZ,
|
||||||
|
},
|
||||||
|
[HW_FREQ_11] = /* PLL = off */
|
||||||
|
{
|
||||||
|
.mclkdiv = WMC_MCLKDIV_6, /* 2.8224 MHz */
|
||||||
|
.filter = WMC_SR_12KHZ,
|
||||||
|
},
|
||||||
|
[HW_FREQ_12] = /* PLL = 73.728 MHz */
|
||||||
|
{
|
||||||
|
.plln = WMC_PLLNw(8) | WMC_PLL_PRESCALE,
|
||||||
|
.pllk0 = WMC_PLLK_23_18w(11869595 >> 18),
|
||||||
|
.pllk1 = WMC_PLLK_17_9w(11869595 >> 9),
|
||||||
|
.pllk2 = WMC_PLLK_8_0w(11869595 >> 0),
|
||||||
|
.mclkdiv = WMC_MCLKDIV_6, /* 3.0720 MHz */
|
||||||
|
.filter = WMC_SR_12KHZ,
|
||||||
|
},
|
||||||
|
[HW_FREQ_16] = /* PLL = 65.536MHz */
|
||||||
|
{
|
||||||
|
.plln = WMC_PLLNw(7) | WMC_PLL_PRESCALE,
|
||||||
|
.pllk0 = WMC_PLLK_23_18w(12414886 >> 18),
|
||||||
|
.pllk1 = WMC_PLLK_17_9w(12414886 >> 9),
|
||||||
|
.pllk2 = WMC_PLLK_8_0w(12414886 >> 0),
|
||||||
|
.mclkdiv = WMC_MCLKDIV_4, /* 4.0960 MHz */
|
||||||
|
.filter = WMC_SR_16KHZ,
|
||||||
|
},
|
||||||
|
[HW_FREQ_22] = /* PLL = off */
|
||||||
|
{
|
||||||
|
.mclkdiv = WMC_MCLKDIV_3, /* 5.6448 MHz */
|
||||||
|
.filter = WMC_SR_24KHZ,
|
||||||
|
},
|
||||||
|
[HW_FREQ_24] = /* PLL = 73.728 MHz */
|
||||||
|
{
|
||||||
|
.plln = WMC_PLLNw(8) | WMC_PLL_PRESCALE,
|
||||||
|
.pllk0 = WMC_PLLK_23_18w(11869595 >> 18),
|
||||||
|
.pllk1 = WMC_PLLK_17_9w(11869595 >> 9),
|
||||||
|
.pllk2 = WMC_PLLK_8_0w(11869595 >> 0),
|
||||||
|
.mclkdiv = WMC_MCLKDIV_3, /* 6.1440 MHz */
|
||||||
|
.filter = WMC_SR_24KHZ,
|
||||||
|
},
|
||||||
|
[HW_FREQ_32] = /* PLL = 65.536MHz */
|
||||||
|
{
|
||||||
|
.plln = WMC_PLLNw(7) | WMC_PLL_PRESCALE,
|
||||||
|
.pllk0 = WMC_PLLK_23_18w(12414886 >> 18),
|
||||||
|
.pllk1 = WMC_PLLK_17_9w(12414886 >> 9),
|
||||||
|
.pllk2 = WMC_PLLK_8_0w(12414886 >> 0),
|
||||||
|
.mclkdiv = WMC_MCLKDIV_2, /* 8.1920 MHz */
|
||||||
|
.filter = WMC_SR_32KHZ,
|
||||||
|
},
|
||||||
|
[HW_FREQ_44] = /* PLL = off */
|
||||||
|
{
|
||||||
|
.mclkdiv = WMC_MCLKDIV_1_5, /* 11.2896 MHz */
|
||||||
|
.filter = WMC_SR_48KHZ,
|
||||||
|
},
|
||||||
|
[HW_FREQ_48] = /* PLL = 73.728 MHz */
|
||||||
|
{
|
||||||
|
.plln = WMC_PLLNw(8) | WMC_PLL_PRESCALE,
|
||||||
|
.pllk0 = WMC_PLLK_23_18w(11869595 >> 18),
|
||||||
|
.pllk1 = WMC_PLLK_17_9w(11869595 >> 9),
|
||||||
|
.pllk2 = WMC_PLLK_8_0w(11869595 >> 0),
|
||||||
|
.mclkdiv = WMC_MCLKDIV_1_5, /* 12.2880 MHz */
|
||||||
|
.filter = WMC_SR_48KHZ,
|
||||||
|
},
|
||||||
|
};
|
||||||
|
|
||||||
|
unsigned int plln;
|
||||||
|
unsigned int mclkdiv;
|
||||||
|
|
||||||
|
if ((unsigned)sampling_control >= ARRAYLEN(sctrl_table))
|
||||||
|
sampling_control = HW_FREQ_DEFAULT;
|
||||||
|
|
||||||
|
|
||||||
|
/* Setup filters. */
|
||||||
|
wmc_write(WMC_ADDITIONAL_CTRL,
|
||||||
|
sctrl_table[sampling_control].filter);
|
||||||
|
|
||||||
|
plln = sctrl_table[sampling_control].plln;
|
||||||
|
mclkdiv = sctrl_table[sampling_control].mclkdiv;
|
||||||
|
|
||||||
|
if (plln != 0)
|
||||||
|
{
|
||||||
|
/* Using PLL to generate SYSCLK */
|
||||||
|
|
||||||
|
/* Program PLL. */
|
||||||
|
wmc_write(WMC_PLL_N, plln);
|
||||||
|
wmc_write(WMC_PLLK_23_18, sctrl_table[sampling_control].pllk0);
|
||||||
|
wmc_write(WMC_PLLK_17_9, sctrl_table[sampling_control].pllk1);
|
||||||
|
wmc_write(WMC_PLLK_8_0, sctrl_table[sampling_control].pllk2);
|
||||||
|
|
||||||
|
/* Turn on PLL. */
|
||||||
|
wmc_set(WMC_POWER_MANAGEMENT1, WMC_PLLEN);
|
||||||
|
|
||||||
|
/* Switch to PLL and set divider. */
|
||||||
|
wmc_write_masked(WMC_CLOCK_GEN_CTRL, mclkdiv | WMC_CLKSEL,
|
||||||
|
WMC_MCLKDIV | WMC_CLKSEL);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
/* Switch away from PLL and set MCLKDIV. */
|
||||||
|
wmc_write_masked(WMC_CLOCK_GEN_CTRL, mclkdiv,
|
||||||
|
WMC_MCLKDIV | WMC_CLKSEL);
|
||||||
|
|
||||||
|
/* Turn off PLL. */
|
||||||
|
wmc_clear(WMC_POWER_MANAGEMENT1, WMC_PLLEN);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
#ifdef HAVE_RECORDING
|
#ifdef HAVE_RECORDING
|
||||||
/* TODO */
|
/* TODO */
|
||||||
|
|
|
||||||
|
|
@ -72,8 +72,10 @@
|
||||||
/* Define this if you have the WM8978 audio codec */
|
/* Define this if you have the WM8978 audio codec */
|
||||||
#define HAVE_WM8978
|
#define HAVE_WM8978
|
||||||
|
|
||||||
#define HW_SAMPR_CAPS (SAMPR_CAP_88 | SAMPR_CAP_44 | SAMPR_CAP_22 | \
|
#define HW_SAMPR_CAPS (SAMPR_CAP_48 | SAMPR_CAP_44 | SAMPR_CAP_32 | \
|
||||||
SAMPR_CAP_11)
|
SAMPR_CAP_24 | SAMPR_CAP_22 | SAMPR_CAP_16 | \
|
||||||
|
SAMPR_CAP_16 | SAMPR_CAP_12 | SAMPR_CAP_11 | \
|
||||||
|
SAMPR_CAP_8)
|
||||||
|
|
||||||
#ifndef BOOTLOADER
|
#ifndef BOOTLOADER
|
||||||
/* Not for bootloader */
|
/* Not for bootloader */
|
||||||
|
|
|
||||||
|
|
@ -28,6 +28,7 @@
|
||||||
|
|
||||||
int tenthdb2master(int db);
|
int tenthdb2master(int db);
|
||||||
void audiohw_set_headphone_vol(int vol_l, int vol_r);
|
void audiohw_set_headphone_vol(int vol_l, int vol_r);
|
||||||
|
void audiohw_set_frequency(int sampling_control);
|
||||||
|
|
||||||
#define WMC_I2C_ADDR 0x34
|
#define WMC_I2C_ADDR 0x34
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -37,7 +37,8 @@ struct dma_data
|
||||||
int state;
|
int state;
|
||||||
};
|
};
|
||||||
|
|
||||||
static unsigned long pcm_freq = HW_SAMPR_DEFAULT; /* 44.1 is default */
|
static unsigned long pcm_freq; /* 44.1 is default */
|
||||||
|
static int sr_ctrl;
|
||||||
|
|
||||||
static struct dma_data dma_play_data =
|
static struct dma_data dma_play_data =
|
||||||
{
|
{
|
||||||
|
|
@ -71,7 +72,7 @@ static void _pcm_apply_settings(void)
|
||||||
if (pcm_freq != pcm_curr_sampr)
|
if (pcm_freq != pcm_curr_sampr)
|
||||||
{
|
{
|
||||||
pcm_curr_sampr = pcm_freq;
|
pcm_curr_sampr = pcm_freq;
|
||||||
// TODO: audiohw_set_frequency(sr_ctrl);
|
audiohw_set_frequency(sr_ctrl);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -110,11 +111,17 @@ static void __attribute__((interrupt("IRQ"))) SSI1_HANDLER(void)
|
||||||
|
|
||||||
void pcm_apply_settings(void)
|
void pcm_apply_settings(void)
|
||||||
{
|
{
|
||||||
int oldstatus = disable_fiq_save();
|
pcm_play_lock();
|
||||||
|
#ifdef HAVE_RECORDING
|
||||||
|
pcm_rec_lock();
|
||||||
|
#endif
|
||||||
|
|
||||||
_pcm_apply_settings();
|
_pcm_apply_settings();
|
||||||
|
|
||||||
restore_fiq(oldstatus);
|
#ifdef HAVE_RECORDING
|
||||||
|
pcm_rec_unlock();
|
||||||
|
#endif
|
||||||
|
pcm_play_unlock();
|
||||||
}
|
}
|
||||||
|
|
||||||
void pcm_play_dma_init(void)
|
void pcm_play_dma_init(void)
|
||||||
|
|
@ -189,11 +196,25 @@ void pcm_play_dma_init(void)
|
||||||
SSI_SCR2 = 0;
|
SSI_SCR2 = 0;
|
||||||
SSI_SRCR2 = 0;
|
SSI_SRCR2 = 0;
|
||||||
SSI_STCR2 = SSI_STCR_TXDIR;
|
SSI_STCR2 = SSI_STCR_TXDIR;
|
||||||
SSI_STCCR2 = SSI_STRCCR_PMw(0);
|
|
||||||
|
|
||||||
/* Enable SSIs */
|
/* f(INT_BIT_CLK) =
|
||||||
|
* f(SYS_CLK) / [(DIV2 + 1)*(7*PSR + 1)*(PM + 1)*2] =
|
||||||
|
* 677737600 / [(1 + 1)*(7*0 + 1)*(0 + 1)*2] =
|
||||||
|
* 677737600 / 4 = 169344000 Hz
|
||||||
|
*
|
||||||
|
* 45.4.2.2 DIV2, PSR, and PM Bit Description states:
|
||||||
|
* Bits DIV2, PSR, and PM should not be all set to zero at the same
|
||||||
|
* time.
|
||||||
|
*
|
||||||
|
* The hardware seems to force a divide by 4 even if all bits are
|
||||||
|
* zero but comply by setting DIV2 and the others to zero.
|
||||||
|
*/
|
||||||
|
SSI_STCCR2 = SSI_STRCCR_DIV2 | SSI_STRCCR_PMw(1-1);
|
||||||
|
|
||||||
|
/* Enable SSI2 (codec clock) */
|
||||||
SSI_SCR2 |= SSI_SCR_SSIEN;
|
SSI_SCR2 |= SSI_SCR_SSIEN;
|
||||||
|
|
||||||
|
pcm_set_frequency(HW_SAMPR_DEFAULT);
|
||||||
audiohw_init();
|
audiohw_init();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -280,8 +301,45 @@ void pcm_play_dma_pause(bool pause)
|
||||||
hardware here but simply cache it. */
|
hardware here but simply cache it. */
|
||||||
void pcm_set_frequency(unsigned int frequency)
|
void pcm_set_frequency(unsigned int frequency)
|
||||||
{
|
{
|
||||||
/* TODO */
|
int index;
|
||||||
(void)frequency;
|
|
||||||
|
switch (frequency)
|
||||||
|
{
|
||||||
|
case SAMPR_48:
|
||||||
|
index = HW_FREQ_48;
|
||||||
|
break;
|
||||||
|
case SAMPR_44:
|
||||||
|
index = HW_FREQ_44;
|
||||||
|
break;
|
||||||
|
case SAMPR_32:
|
||||||
|
index = HW_FREQ_32;
|
||||||
|
break;
|
||||||
|
case SAMPR_24:
|
||||||
|
index = HW_FREQ_24;
|
||||||
|
break;
|
||||||
|
case SAMPR_22:
|
||||||
|
index = HW_FREQ_22;
|
||||||
|
break;
|
||||||
|
case SAMPR_16:
|
||||||
|
index = HW_FREQ_16;
|
||||||
|
break;
|
||||||
|
case SAMPR_12:
|
||||||
|
index = HW_FREQ_12;
|
||||||
|
break;
|
||||||
|
case SAMPR_11:
|
||||||
|
index = HW_FREQ_11;
|
||||||
|
break;
|
||||||
|
case SAMPR_8:
|
||||||
|
index = HW_FREQ_8;
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
/* Invalid = default */
|
||||||
|
frequency = HW_SAMPR_DEFAULT;
|
||||||
|
index = HW_FREQ_DEFAULT;
|
||||||
|
}
|
||||||
|
|
||||||
|
pcm_freq = frequency;
|
||||||
|
sr_ctrl = index;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Return the number of bytes waiting - full L-R sample pairs only */
|
/* Return the number of bytes waiting - full L-R sample pairs only */
|
||||||
|
|
|
||||||
|
|
@ -41,13 +41,23 @@ static struct i2c_node wm8978_i2c_node =
|
||||||
|
|
||||||
void audiohw_init(void)
|
void audiohw_init(void)
|
||||||
{
|
{
|
||||||
/* USB PLL = 338.688MHz, /30 = 11.2896MHz = 256Fs */
|
/* How SYSCLK for codec is derived (USBPLL=338.688MHz).
|
||||||
|
*
|
||||||
|
* SSI post dividers (SSI2 PODF=4, SSI2 PRE PODF=0):
|
||||||
|
* 338688000Hz / 5 = 67737600Hz = ssi2_clk
|
||||||
|
*
|
||||||
|
* SSI bit clock dividers (DIV2=1, PSR=0, PM=0):
|
||||||
|
* ssi2_clk / 4 = 16934400Hz = INT_BIT_CLK (MCLK)
|
||||||
|
*
|
||||||
|
* WM Codec post divider (MCLKDIV=1.5):
|
||||||
|
* INT_BIT_CLK (MCLK) / 1.5 = 11289600Hz = 256*fs = SYSCLK
|
||||||
|
*/
|
||||||
imx31_regmod32(&CLKCTL_PDR1,
|
imx31_regmod32(&CLKCTL_PDR1,
|
||||||
PDR1_SSI1_PODFw(64-1) | PDR1_SSI2_PODFw(5-1),
|
PDR1_SSI1_PODFw(64-1) | PDR1_SSI2_PODFw(5-1) |
|
||||||
PDR1_SSI1_PODF | PDR1_SSI2_PODF);
|
PDR1_SSI1_PRE_PODFw(8-1) | PDR1_SSI2_PRE_PODFw(1-1),
|
||||||
imx31_regmod32(&CLKCTL_PDR1,
|
PDR1_SSI1_PODF | PDR1_SSI2_PODF |
|
||||||
PDR1_SSI1_PRE_PODFw(4-1) | PDR1_SSI2_PRE_PODFw(1-1),
|
|
||||||
PDR1_SSI1_PRE_PODF | PDR1_SSI2_PRE_PODF);
|
PDR1_SSI1_PRE_PODF | PDR1_SSI2_PRE_PODF);
|
||||||
|
|
||||||
i2c_enable_node(&wm8978_i2c_node, true);
|
i2c_enable_node(&wm8978_i2c_node, true);
|
||||||
|
|
||||||
audiohw_preinit();
|
audiohw_preinit();
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue