e61e9c61d0
* SOUND_x enum can be generated by audiohw_settings.h along with settings entries and sound_val2phys. * VOLUME_MIN and VOLUME_MAX are no longer necessary within sound.c. If you need them, they are for target-defined purposes. * Fix up SDL volume implementation in sdl.c. Move sim volume calculation code to pcm-sdl.c. * Min trigger tresholds were based upon VOLUME_MIN for some reason. These setting have nothing to do with playback volume. Since it is no longer present, set these at -89dB which is the minimum peak meter sensitivity setting. * Fix an oversight in wm8758.c. I forgot to add the dB->register conversion to audiohw_set_volume. Change-Id: Ie1df33f1793eee75e6793f16bc7bddd16edb7f75
234 lines
6 KiB
C
234 lines
6 KiB
C
/***************************************************************************
|
|
* __________ __ ___.
|
|
* Open \______ \ ____ ____ | | _\_ |__ _______ ___
|
|
* Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
|
|
* Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
|
|
* Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
|
|
* \/ \/ \/ \/ \/
|
|
* $Id: uda1380.c 21975 2009-07-19 22:45:32Z bertrik $
|
|
*
|
|
* Copyright (C) 2009 by Bob Cousins
|
|
*
|
|
* 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 <string.h>
|
|
|
|
#include "config.h"
|
|
#include "logf.h"
|
|
#include "system.h"
|
|
#include "audio.h"
|
|
#include "debug.h"
|
|
|
|
#include "audiohw.h"
|
|
|
|
/* convert tenth of dB volume (-600..0) to volume register value */
|
|
static int vol_tenthdb2hw(int db)
|
|
{
|
|
if (db <= -610)
|
|
return 63;
|
|
else /* 1 dB steps */
|
|
return -(db / 10) + 1;
|
|
}
|
|
|
|
static unsigned short uda_regs[NUM_REG_ID];
|
|
|
|
/****************************************************************************/
|
|
|
|
/* ------------------------------------------------- */
|
|
/* Local functions and variables */
|
|
/* ------------------------------------------------- */
|
|
|
|
/* Generic L3 functions */
|
|
|
|
#define L3PORT GPBDAT
|
|
#define L3MODE (1 << 2)
|
|
#define L3DATA (1 << 3)
|
|
#define L3CLOCK (1 << 4)
|
|
|
|
static void l3_init (void)
|
|
{
|
|
L3PORT |= L3MODE | L3CLOCK;
|
|
L3PORT &= ~L3DATA;
|
|
|
|
S3C2440_GPIO_CONFIG (GPBCON, 2, GPIO_OUTPUT); /* L3 MODE */
|
|
S3C2440_GPIO_CONFIG (GPBCON, 3, GPIO_OUTPUT); /* L3 DATA */
|
|
S3C2440_GPIO_CONFIG (GPBCON, 4, GPIO_OUTPUT); /* L3 CLOCK */
|
|
|
|
S3C2440_GPIO_PULLUP (GPBUP, 2, GPIO_PULLUP_DISABLE);
|
|
S3C2440_GPIO_PULLUP (GPBUP, 3, GPIO_PULLUP_DISABLE);
|
|
S3C2440_GPIO_PULLUP (GPBUP, 4, GPIO_PULLUP_DISABLE);
|
|
}
|
|
|
|
static void bit_delay (void)
|
|
{
|
|
volatile int j;
|
|
for (j=0; j<5; j++)
|
|
;
|
|
}
|
|
|
|
static void l3_write_byte (unsigned char data, bool address_mode)
|
|
{
|
|
int bit;
|
|
|
|
L3PORT |= L3CLOCK;
|
|
if (address_mode)
|
|
L3PORT &= ~L3MODE;
|
|
else
|
|
L3PORT |= L3MODE;
|
|
bit_delay();
|
|
|
|
for (bit=0; bit < 8; bit++)
|
|
{
|
|
if (data & 1)
|
|
{
|
|
L3PORT |= L3DATA;
|
|
}
|
|
else
|
|
{
|
|
L3PORT &= ~L3DATA;
|
|
}
|
|
L3PORT &= ~L3CLOCK;
|
|
bit_delay();
|
|
L3PORT |= L3CLOCK;
|
|
bit_delay();
|
|
|
|
data >>= 1;
|
|
}
|
|
|
|
if (address_mode)
|
|
L3PORT |= L3MODE;
|
|
else
|
|
L3PORT &= ~L3MODE;
|
|
bit_delay();
|
|
}
|
|
|
|
static void l3_write_addr (unsigned char addr)
|
|
{
|
|
/* write address byte */
|
|
l3_write_byte (addr, true);
|
|
}
|
|
|
|
static void l3_write_data (unsigned char data)
|
|
{
|
|
/* write data byte */
|
|
l3_write_byte (data, false);
|
|
}
|
|
|
|
/****************************************************************************/
|
|
|
|
/* UDA1341 access functions */
|
|
|
|
static int udacodec_write(unsigned char reg, unsigned short value)
|
|
{
|
|
l3_write_addr (UDA1341_ADDR | reg);
|
|
l3_write_data (value & 0xff);
|
|
return 0;
|
|
}
|
|
|
|
static void udacodec_reset(void)
|
|
{
|
|
/* uda reset */
|
|
l3_init();
|
|
|
|
udacodec_write (UDA_REG_STATUS, UDA_STATUS_0 | UDA_RESET | UDA_SYSCLK_256FS |
|
|
I2S_IFMT_IIS);
|
|
udacodec_write (UDA_REG_STATUS, UDA_STATUS_0 | UDA_SYSCLK_256FS | I2S_IFMT_IIS);
|
|
udacodec_write (UDA_REG_STATUS, UDA_STATUS_1 | UDA_POWER_DAC_ON);
|
|
|
|
uda_regs[UDA_REG_ID_CTRL2] = UDA_PEAK_DETECT_POS_AFTER |
|
|
UDA_DE_EMPHASIS_NONE | UDA_MUTE_OFF | UDA_MODE_SWITCH_FLAT;
|
|
|
|
}
|
|
|
|
/****************************************************************************/
|
|
|
|
/* Audio API functions */
|
|
|
|
/* This table must match the table in pcm-xxxx.c if using Master mode */
|
|
/* [reserved, master clock rate] */
|
|
static const unsigned char uda_freq_parms[HW_NUM_FREQ][2] =
|
|
{
|
|
[HW_FREQ_44] = { 0, UDA_SYSCLK_384FS },
|
|
[HW_FREQ_22] = { 0, UDA_SYSCLK_256FS },
|
|
[HW_FREQ_11] = { 0, UDA_SYSCLK_256FS },
|
|
};
|
|
|
|
void audiohw_init(void)
|
|
{
|
|
udacodec_reset();
|
|
|
|
audiohw_set_bass (0);
|
|
audiohw_set_treble (0);
|
|
audiohw_set_volume (-250); /* -25 dB */
|
|
}
|
|
|
|
void audiohw_postinit(void)
|
|
{
|
|
}
|
|
|
|
void audiohw_close(void)
|
|
{
|
|
/* DAC, ADC off */
|
|
udacodec_write (UDA_REG_STATUS, UDA_STATUS_1 | 0);
|
|
}
|
|
|
|
void audiohw_set_bass(int value)
|
|
{
|
|
uda_regs [UDA_REG_ID_CTRL1] &= UDA_BASS_BOOST (UDA_BASS_BOOST_MASK);
|
|
uda_regs [UDA_REG_ID_CTRL1] |= UDA_BASS_BOOST (value & UDA_BASS_BOOST_MASK);
|
|
|
|
udacodec_write (UDA_REG_DATA0, UDA_DATA_CTRL1 | uda_regs [UDA_REG_ID_CTRL1] );
|
|
}
|
|
|
|
void audiohw_set_treble(int value)
|
|
{
|
|
uda_regs [UDA_REG_ID_CTRL1] &= UDA_TREBLE (UDA_TREBLE_MASK);
|
|
uda_regs [UDA_REG_ID_CTRL1] |= UDA_TREBLE (value & UDA_TREBLE_MASK);
|
|
|
|
udacodec_write (UDA_REG_DATA0, UDA_DATA_CTRL1 | uda_regs [UDA_REG_ID_CTRL1] );
|
|
}
|
|
|
|
/*static void audiohw_mute(bool mute)
|
|
{
|
|
if (mute)
|
|
uda_regs [UDA_REG_ID_CTRL2] |= UDA_MUTE_ON;
|
|
else
|
|
uda_regs [UDA_REG_ID_CTRL2] &= ~UDA_MUTE_ON;
|
|
|
|
udacodec_write (UDA_REG_DATA0, UDA_DATA_CTRL2 | uda_regs [UDA_REG_ID_CTRL2] );
|
|
}
|
|
*/
|
|
|
|
#ifdef AUDIOHW_HAVE_PRESCALER
|
|
void audiohw_set_prescaler(int val)
|
|
{
|
|
(void)val;
|
|
}
|
|
#endif /* AUDIOHW_HAVE_PRESCALER */
|
|
|
|
/**
|
|
* Set master volume (1(max) to 62(muted))
|
|
*/
|
|
void audiohw_set_volume(int volume)
|
|
{
|
|
volume = vol_tenthdb2hw(volume) / 2;
|
|
uda_regs[UDA_REG_ID_CTRL0] = volume;
|
|
udacodec_write (UDA_REG_DATA0, UDA_DATA_CTRL0 | uda_regs[UDA_REG_ID_CTRL0]);
|
|
}
|
|
|
|
void audiohw_set_frequency(int fsel)
|
|
{
|
|
if ((unsigned)fsel >= HW_NUM_FREQ)
|
|
fsel = HW_FREQ_DEFAULT;
|
|
|
|
uda_regs[UDA_REG_ID_STATUS_0] = I2S_IFMT_IIS | uda_freq_parms[fsel][1];
|
|
|
|
udacodec_write (UDA_REG_STATUS, UDA_STATUS_0 | uda_regs[UDA_REG_ID_STATUS_0]);
|
|
}
|