rockbox/firmware/drivers/as3514.c
Daniel Ankers dfad406aa1 Sound for Sansa E200 - based on work by myself, Rene Peinthor, Barry Wardell and Christian Gmeiner from the AS3514 datasheet.
git-svn-id: svn://svn.rockbox.org/rockbox/trunk@12727 a1c6a512-1295-4272-9138-f99709370657
2007-03-11 17:38:08 +00:00

229 lines
5.1 KiB
C

/***************************************************************************
* __________ __ ___.
* Open \______ \ ____ ____ | | _\_ |__ _______ ___
* Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
* Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
* Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
* \/ \/ \/ \/ \/
* $Id$
*
* Driver for AS3514 audio codec
*
* Copyright (c) 2007 Daniel Ankers
*
* All files in this archive are subject to the GNU General Public License.
* See the file COPYING in the source tree root for full license agreement.
*
* This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
* KIND, either express or implied.
*
****************************************************************************/
#include "lcd.h"
#include "cpu.h"
#include "kernel.h"
#include "thread.h"
#include "power.h"
#include "debug.h"
#include "system.h"
#include "sprintf.h"
#include "button.h"
#include "string.h"
#include "file.h"
#include "buffer.h"
#include "audio.h"
#include "backlight.h"
#include "as3514.h"
#include "i2s.h"
#include "i2c-pp.h"
/* convert tenth of dB volume to master volume register value */
int tenthdb2master(int db)
{
/* +1..07 to -45.43dB in 1.5dB steps == 32 levels = 5 bits */
/* 11111 == +1.07dB (0x1f) = 31) */
/* 11110 == -0.43dB (0x1e) = 30) */
/* 00001 == -43.93dB (0x01) */
/* 00000 == -45.43dB (0x00) */
if (db < VOLUME_MIN) {
return 0x0;
} else if (db >= VOLUME_MAX) {
return 0x1f;
} else {
return((db-VOLUME_MIN)/15); /* VOLUME_MIN is negative */
}
}
/* convert tenth of dB volume (-405..60) to mixer volume register value */
int tenthdb2mixer(int db)
{
/* FIXME: Make this sensible */
if (db < -405) {
return 0x0;
} else if (db >= 60) {
return 0x1f;
} else {
return((db+405)/15);
}
}
void audiohw_reset(void);
/*
* Initialise the PP I2C and I2S.
*/
int audiohw_init(void) {
/* reset I2C */
i2c_init();
/* normal outputs for CDI and I2S pin groups */
DEV_INIT &= ~0x300;
/*mini2?*/
outl(inl(0x70000010) & ~0x3000000, 0x70000010);
/*mini2?*/
/* device reset */
DEV_RS |= 0x800;
DEV_RS &=~0x800;
/* device enable */
DEV_EN |= 0x807;
/* enable external dev clock clocks */
DEV_EN |= 0x2;
/* external dev clock to 24MHz */
outl(inl(0x70000018) & ~0xc, 0x70000018);
i2s_reset();
/* Set ADC off, mixer on, DAC on, line out off, line in off, mic off */
pp_i2c_send(AS3514_I2C_ADDR, AUDIOSET1, 0x60); /* Turn on DAC and mixer */
pp_i2c_send(AS3514_I2C_ADDR, PLLMODE, 0x04);
pp_i2c_send(AS3514_I2C_ADDR, DAC_L, 0x50); /* DAC mute off, -16.5dB gain */
pp_i2c_send(AS3514_I2C_ADDR, DAC_R, 0x10); /* DAC -16.5dB gain to prevent overloading
the headphone amp */
return 0;
}
void audiohw_postinit(void)
{
}
/* Silently enable / disable audio output */
void audiohw_enable_output(bool enable)
{
if (enable)
{
/* reset the I2S controller into known state */
i2s_reset();
pp_i2c_send(AS3514_I2C_ADDR, HPH_OUT_L, 0xc0); /* Mute on, power on */
audiohw_mute(0);
} else {
audiohw_mute(1);
pp_i2c_send(AS3514_I2C_ADDR, HPH_OUT_L, 0x80); /* Mute on, power off */
}
}
int audiohw_set_master_vol(int vol_l, int vol_r)
{
vol_l &= 0x1f;
vol_r &= 0x1f;
pp_i2c_send(AS3514_I2C_ADDR, HPH_OUT_R, 0x40 | vol_r);
pp_i2c_send(AS3514_I2C_ADDR, HPH_OUT_L, 0x40 | vol_l);
return 0;
}
int audiohw_set_lineout_vol(int vol_l, int vol_r)
{
pp_i2c_send(AS3514_I2C_ADDR, LINE_OUT_R, 0x40 | vol_r);
pp_i2c_send(AS3514_I2C_ADDR, LINE_OUT_L, 0x40 | vol_l);
return 0;
}
int audiohw_set_mixer_vol(int channel1, int channel2)
{
(void)channel1;
(void)channel2;
return 0;
}
/* We are using Linear bass control */
void audiohw_set_bass(int value)
{
(void)value;
}
void audiohw_set_treble(int value)
{
(void)value;
}
int audiohw_mute(int mute)
{
int curr;
curr = i2c_readbyte(AS3514_I2C_ADDR, HPH_OUT_L);
if (mute)
{
pp_i2c_send(AS3514_I2C_ADDR, HPH_OUT_L, curr | 0x80);
} else {
pp_i2c_send(AS3514_I2C_ADDR, HPH_OUT_L, curr & ~(0x80));
}
return 0;
}
/* Nice shutdown of WM8758 codec */
void audiohw_close(void)
{
audiohw_mute(1);
}
/* Change the order of the noise shaper, 5th order is recommended above 32kHz */
void audiohw_set_nsorder(int order)
{
(void)order;
}
void audiohw_set_sample_rate(int sampling_control)
{
(void)sampling_control;
/* TODO: Implement this by adjusting the I2S Master clock */
}
void audiohw_enable_recording(bool source_mic)
{
(void)source_mic;
/* TODO */
}
void audiohw_disable_recording(void) {
/* TODO */
}
void audiohw_set_recvol(int left, int right, int type) {
(void)left;
(void)right;
(void)type;
}
void audiohw_set_monitor(int enable) {
(void)enable;
}
void audiohw_set_equalizer_band(int band, int freq, int bw, int gain)
{
(void)band;
(void)freq;
(void)bw;
(void)gain;
}