uda1380: Added bass/treble and recording functions
git-svn-id: svn://svn.rockbox.org/rockbox/trunk@6729 a1c6a512-1295-4272-9138-f99709370657
diff --git a/firmware/drivers/uda1380.c b/firmware/drivers/uda1380.c
index 4b63ccd..4eb04d1 100644
--- a/firmware/drivers/uda1380.c
+++ b/firmware/drivers/uda1380.c
@@ -39,27 +39,28 @@
int uda1380_write_reg(unsigned char reg, unsigned short value);
unsigned short uda1380_regs[0x30];
-/* Definition of a good (?) configuration to start with */
-/* Not enabling ADC for now.. */
+/* Definition of a playback configuration to start with */
#define NUM_DEFAULT_REGS 13
-unsigned short uda1380_defaults[2*NUM_DEFAULT_REGS] =
+unsigned short uda1380_defaults[2*NUM_DEFAULT_REGS] =
{
- REG_0, EN_DAC | EN_INT | EN_DEC | SYSCLK_256FS | WSPLL_25_50,
- REG_I2S, I2S_IFMT_IIS,
- REG_PWR, PON_PLL | PON_DAC | PON_BIAS, /* PON_HP is enabled later */
- REG_AMIX, AMIX_RIGHT(0x10) | AMIX_LEFT(0x10), /* 00=max, 3f=mute */
- REG_MASTER_VOL, MASTER_VOL_LEFT(0x20) | MASTER_VOL_RIGHT(0x20), /* 00=max, ff=mute */
- REG_MIX_VOL, MIX_VOL_CHANNEL_1(0) | MIX_VOL_CHANNEL_2(0xff), /* 00=max, ff=mute */
- REG_EQ, 0,
- REG_MUTE, MUTE_MASTER, /* Mute everything to start with */
- REG_MIX_CTL, 0,
- REG_DEC_VOL, 0,
- REG_PGA, MUTE_ADC,
- REG_ADC, SKIP_DCFIL,
- REG_AGC, 0
+ REG_0, EN_DAC | EN_INT | EN_DEC | SYSCLK_256FS | WSPLL_25_50,
+ REG_I2S, I2S_IFMT_IIS,
+ REG_PWR, PON_PLL | PON_DAC | PON_BIAS, /* PON_HP is enabled later */
+ REG_AMIX, AMIX_RIGHT(0x3f) | AMIX_LEFT(0x3f), /* 00=max, 3f=mute */
+ REG_MASTER_VOL, MASTER_VOL_LEFT(0x20) | MASTER_VOL_RIGHT(0x20), /* 00=max, ff=mute */
+ REG_MIX_VOL, MIX_VOL_CH_1(0) | MIX_VOL_CH_2(0xff), /* 00=max, ff=mute */
+ REG_EQ, EQ_MODE_MAX, /* Bass and tremble = 0 dB */
+ REG_MUTE, MUTE_MASTER, /* Mute everything to start with */
+ REG_MIX_CTL, 0,
+ REG_DEC_VOL, 0,
+ REG_PGA, MUTE_ADC,
+ REG_ADC, SKIP_DCFIL,
+ REG_AGC, 0
};
+
+
/* Returns 0 if register was written or -1 if write failed */
int uda1380_write_reg(unsigned char reg, unsigned short value)
{
@@ -93,6 +94,22 @@
MASTER_VOL_LEFT(vol) | MASTER_VOL_RIGHT(vol));
}
+/**
+ * Sets the bass value (0-15)
+ */
+void uda1380_set_bass(int value)
+{
+ uda1380_write_reg(REG_EQ, (uda1380_regs[REG_EQ] & ~BASS_MASK) | BASSL(value) | BASSR(value));
+}
+
+/**
+ * Sets the treble value (0-3)
+ */
+void uda1380_set_treble(int value)
+{
+ uda1380_write_reg(REG_EQ, (uda1380_regs[REG_EQ] & ~TREBLE_MASK) | TREBLEL(value) | TREBLER(value));
+}
+
/**
* Mute (mute=1) or enable sound (mute=0)
*
@@ -163,3 +180,81 @@
uda1380_write_reg(REG_PWR, 0);
uda1380_write_reg(REG_0, 0); /* Disable codec */
}
+
+/**
+ * Calling this function enables the UDA1380 to send
+ * sound samples over the I2S bus, which is connected
+ * to the processor's IIS1 interface.
+ *
+ * source_mic: true=record from microphone, false=record from line-in
+ */
+void uda1380_enable_recording(bool source_mic)
+{
+ uda1380_write_reg(REG_0, uda1380_regs[REG_0] | EN_ADC);
+
+ if (source_mic)
+ {
+ uda1380_write_reg(REG_PWR, uda1380_regs[REG_PWR] | PON_LNA | PON_ADCL);
+ uda1380_write_reg(REG_ADC, (uda1380_regs[REG_ADC] & VGA_GAIN_MASK) | SEL_LNA | SEL_MIC | EN_DCFIL); /* VGA_GAIN: 0=0 dB, F=30dB */
+ uda1380_write_reg(REG_PGA, 0);
+ } else
+ {
+ uda1380_write_reg(REG_PWR, uda1380_regs[REG_PWR] | PON_PGAL | PON_ADCL | PON_PGAR | PON_ADCR);
+ uda1380_write_reg(REG_ADC, EN_DCFIL);
+ uda1380_write_reg(REG_PGA, (uda1380_regs[REG_PGA] & PGA_GAIN_MASK) | PGA_GAINL(0) | PGA_GAINR(0)); /* PGA_GAIN: 0=0 dB, F=24dB */
+ }
+
+ uda1380_write_reg(REG_I2S, uda1380_regs[REG_I2S] | I2S_MODE_MASTER);
+ uda1380_write_reg(REG_MIX_CTL, MIX_MODE(3)); /* Not sure which mode is the best one.. */
+
+}
+
+/**
+ * Stop sending samples on the I2S bus
+ */
+void uda1380_disable_recording(void)
+{
+ uda1380_write_reg(REG_PGA, MUTE_ADC);
+ sleep(HZ/8);
+
+ uda1380_write_reg(REG_I2S, I2S_IFMT_IIS);
+ uda1380_write_reg(REG_PWR, uda1380_regs[REG_PWR] & ~(PON_LNA | PON_ADCL | PON_ADCR | PON_PGAL | PON_PGAR));
+ uda1380_write_reg(REG_0, uda1380_regs[REG_0] & ~EN_ADC);
+ uda1380_write_reg(REG_ADC, SKIP_DCFIL);
+}
+
+/**
+ * Set recording gain and volume
+ *
+ * mic_gain : range 0 .. 15 -> 0 .. 30 dB gain
+ * linein_gain : range 0 .. 15 -> 0 .. 24 dB gain
+ *
+ * adc_volume : range -127 .. 48 -> -63 .. 24 dB gain
+ * note that 0 -> 0 dB gain..
+ */
+void uda1380_set_recvol(int mic_gain, int linein_gain, int adc_volume)
+{
+ uda1380_write_reg(REG_DEC_VOL, DEC_VOLL(adc_volume) | DEC_VOLR(adc_volume));
+ uda1380_write_reg(REG_PGA, (uda1380_regs[REG_PGA] & ~PGA_GAIN_MASK) | PGA_GAINL(linein_gain) | PGA_GAINR(linein_gain));
+ uda1380_write_reg(REG_ADC, (uda1380_regs[REG_ADC] & ~VGA_GAIN_MASK) | VGA_GAIN(mic_gain));
+}
+
+
+/**
+ * Enable or disable recording monitor (so one can listen to the recording)
+ *
+ */
+void uda1380_set_monitor(int enable)
+{
+ if (enable)
+ {
+ /* enable channel 2 */
+ uda1380_write_reg(REG_MIX_VOL, (uda1380_regs[REG_MIX_VOL] & 0x00FF) | MIX_VOL_CH_2(0));
+ uda1380_write_reg(REG_MUTE, 0);
+ } else
+ {
+ /* mute channel 2 */
+ uda1380_write_reg(REG_MUTE, MUTE_CH2);
+ uda1380_write_reg(REG_MIX_VOL, (uda1380_regs[REG_MIX_VOL] & 0x00FF) | MIX_VOL_CH_2(0xff));
+ }
+}
diff --git a/firmware/export/uda1380.h b/firmware/export/uda1380.h
index c6993ef..f7e97e1 100644
--- a/firmware/export/uda1380.h
+++ b/firmware/export/uda1380.h
@@ -17,32 +17,33 @@
*
****************************************************************************/
-/*
- * Driver for UDA1380 Audio-Codec
- * 2005-02-17 hubble@mochine.com
- *
- */
-
#ifndef _UDA1380_H
#define _UDA1380_H
extern int uda1380_init(void);
extern void uda1380_enable_output(bool enable);
extern int uda1380_setvol(int vol);
+extern void uda1380_set_bass(int value);
+extern void uda1380_set_treble(int value);
extern int uda1380_mute(int mute);
extern void uda1380_close(void);
-#define UDA1380_ADDR 0x30
+extern void uda1380_enable_recording(bool source_mic);
+extern void uda1380_disable_recording(void);
+extern void uda1380_set_recvol(int mic_gain, int linein_gain, int adc_volume);
+extern void uda1380_set_monitor(int enable);
+
+#define UDA1380_ADDR 0x30
/* REG_0: Misc settings */
-#define REG_0 0x00
+#define REG_0 0x00
-#define EN_ADC (1 << 11) /* Enable ADC */
-#define EN_DEC (1 << 10) /* Enable Decimator */
-#define EN_DAC (1 << 9) /* Enable DAC */
-#define EN_INT (1 << 8) /* Enable Interpolator */
-#define ADC_CLK (1 << 5) /* ADC_CLK: WSPLL (1) SYSCLK (0) */
-#define DAC_CLK (1 << 4) /* DAC_CLK: WSPLL (1) SYSCLK (0) */
+#define EN_ADC (1 << 11) /* Enable ADC */
+#define EN_DEC (1 << 10) /* Enable Decimator */
+#define EN_DAC (1 << 9) /* Enable DAC */
+#define EN_INT (1 << 8) /* Enable Interpolator */
+#define ADC_CLK (1 << 5) /* ADC_CLK: WSPLL (1) SYSCLK (0) */
+#define DAC_CLK (1 << 4) /* DAC_CLK: WSPLL (1) SYSCLK (0) */
/* SYSCLK freqency select */
#define SYSCLK_256FS (0 << 2)
@@ -51,14 +52,14 @@
#define SYSCLK_768FS (3 << 2)
/* WSPLL Input frequency range (kHz) */
-#define WSPLL_625_125 (0 << 0) /* 6.25 - 12.5 */
-#define WSPLL_125_25 (1 << 0) /* 12.5 - 25 */
-#define WSPLL_25_50 (2 << 0) /* 25 - 50 */
-#define WSPLL_50_100 (3 << 0) /* 50 - 100 */
+#define WSPLL_625_125 (0 << 0) /* 6.25 - 12.5 */
+#define WSPLL_125_25 (1 << 0) /* 12.5 - 25 */
+#define WSPLL_25_50 (2 << 0) /* 25 - 50 */
+#define WSPLL_50_100 (3 << 0) /* 50 - 100 */
/* REG_I2S: I2S settings */
-#define REG_I2S 0x01
+#define REG_I2S 0x01
#define I2S_IFMT_IIS (0 << 8)
#define I2S_IFMT_LSB16 (1 << 8)
#define I2S_IFMT_LSB18 (2 << 8)
@@ -70,71 +71,92 @@
#define I2S_OFMT_LSB20 (3 << 0)
#define I2S_OFMT_LSB24 (4 << 0)
#define I2S_OFMT_MSB (5 << 0)
-
+#define I2S_MODE_MASTER (1 << 4)
/* REG_PWR: Power control */
-#define REG_PWR 0x02
-#define PON_PLL (1 << 15) /* Power-on WSPLL */
-#define PON_HP (1 << 13) /* Power-on Headphone driver */
-#define PON_DAC (1 << 10) /* Power-on DAC */
-#define PON_BIAS (1 << 8) /* Power-on BIAS for ADC, AVC, FSDAC */
-#define EN_AVC (1 << 7) /* Enable analog mixer */
-#define PON_AVC (1 << 6) /* Power-on analog mixer */
-#define PON_LNA (1 << 4) /* Power-on LNA & SDC */
-#define PON_PGAL (1 << 3) /* Power-on PGA left */
-#define PON_ADCL (1 << 2) /* Power-on ADC left */
-#define PON_PGAR (1 << 1) /* Power-on PGA right */
-#define PON_ADCR (1 << 0) /* Power-on ADC right */
+#define REG_PWR 0x02
+#define PON_PLL (1 << 15) /* Power-on WSPLL */
+#define PON_HP (1 << 13) /* Power-on Headphone driver */
+#define PON_DAC (1 << 10) /* Power-on DAC */
+#define PON_BIAS (1 << 8) /* Power-on BIAS for ADC, AVC, FSDAC */
+#define EN_AVC (1 << 7) /* Enable analog mixer */
+#define PON_AVC (1 << 6) /* Power-on analog mixer */
+#define PON_LNA (1 << 4) /* Power-on LNA & SDC */
+#define PON_PGAL (1 << 3) /* Power-on PGA left */
+#define PON_ADCL (1 << 2) /* Power-on ADC left */
+#define PON_PGAR (1 << 1) /* Power-on PGA right */
+#define PON_ADCR (1 << 0) /* Power-on ADC right */
/* REG_AMIX: Analog mixer */
-#define REG_AMIX 0x03
-#define AMIX_LEFT(x) (((x) & 0x3f) << 8)
-#define AMIX_RIGHT(x) (((x) & 0x3f) << 0)
+#define REG_AMIX 0x03
+#define AMIX_LEFT(x) (((x) & 0x3f) << 8)
+#define AMIX_RIGHT(x) (((x) & 0x3f) << 0)
/* REG_HP: Headphone amp */
-#define REG_HP 0x04
+#define REG_HP 0x04
/* REG_MV: Master Volume control */
#define REG_MASTER_VOL 0x10
-#define MASTER_VOL_RIGHT(x) (((x) & 0xff) << 8)
-#define MASTER_VOL_LEFT(x) (((x) & 0xff) << 0)
+#define MASTER_VOL_RIGHT(x) (((x) & 0xff) << 8)
+#define MASTER_VOL_LEFT(x) (((x) & 0xff) << 0)
/* REG_MIX: Mixer volume control */
/* Channel 1 is from digital data from I2S */
/* Channel 2 is from decimation filter */
-#define REG_MIX_VOL 0x11
-#define MIX_VOL_CHANNEL_1(x) (((x) & 0xff) << 0)
-#define MIX_VOL_CHANNEL_2(x) (((x) & 0xff) << 8)
+#define REG_MIX_VOL 0x11
+#define MIX_VOL_CH_1(x) (((x) & 0xff) << 0)
+#define MIX_VOL_CH_2(x) (((x) & 0xff) << 8)
/* REG_EQ: Bass boost and tremble */
-#define REG_EQ 0x12
+#define REG_EQ 0x12
+#define EQ_MODE_FLAG (0 << 14)
+#define EQ_MODE_MIN (1 << 14)
+#define EQ_MODE_MAX (3 << 14)
+#define BASSL(x) (((x) & 0xF) << 8)
+#define BASSR(x) (((x) & 0xF) << 0)
+#define TREBLEL(x) (((x) & 0x3) << 12)
+#define TREBLER(x) (((x) & 0x3) << 4)
+#define BASS_MASK 0x0F0F
+#define TREBLE_MASK 0x3030
-/* REG_MUTE: Master Mute */
-#define REG_MUTE 0x13
-#define MUTE_MASTER (1 << 14) /* Master Mute (soft) */
-#define MUTE_CH2 (1 << 11) /* Channel 2 mute */
-#define MUTE_CH1 (1 << 3) /* Channel 1 mute */
+/* REG_MUTE: Master Mute, silence detector and oversampling */
+#define REG_MUTE 0x13
+#define MUTE_MASTER (1 << 14) /* Master Mute (soft) */
+#define MIX_MODE(x) ((x) << 12) /* Mixer mode: See table 48 */
+#define MUTE_CH2 (1 << 11) /* Channel 2 mute */
+#define MUTE_CH1 (1 << 3) /* Channel 1 mute */
+
/* REG_MIX_CTL: Mixer, silence detector and oversampling settings */
-#define REG_MIX_CTL 0x14
+#define REG_MIX_CTL 0x14
#define MIX_CTL_MIX_POS (1 << 13)
#define MIX_CTL_MIX (1 << 12)
-/* REG_DEC_VOL: Decimator Volume control */
-#define REG_DEC_VOL 0x20
+/* REG_DEC_VOL: Decimator (ADC) volume control */
+#define REG_DEC_VOL 0x20
+#define DEC_VOLL(x) (((x) & 0xff) << 8)
+#define DEC_VOLR(x) (((x) & 0xff) << 0)
/* REG_PGA: PGA settings and mute */
-#define REG_PGA 0x21
-#define MUTE_ADC (1 << 15) /* Mute ADC */
+#define REG_PGA 0x21
+#define MUTE_ADC (1 << 15) /* Mute ADC */
+#define PGA_GAINR(x) (((x) & 0xF) << 8)
+#define PGA_GAINL(x) (((x) & 0xF) << 0)
+#define PGA_GAIN_MASK 0x0F0F
/* REG_ADC: */
-#define REG_ADC 0x22
+#define REG_ADC 0x22
+#define SEL_LNA (1 << 3)
+#define SEL_MIC (1 << 2)
+#define SKIP_DCFIL (1 << 1)
+#define EN_DCFIL (1 << 0)
+#define VGA_GAIN(x) (((x) & 0xF) << 8)
+#define VGA_GAIN_MASK 0x0F00
/* REG_AGC: Attack / Gain */
-#define REG_AGC 0x23
-#define SKIP_DCFIL ( 1 << 1)
+#define REG_AGC 0x23
#endif /* _UDA_1380_H */
diff --git a/firmware/sound.c b/firmware/sound.c
index c8347f2..7558a33 100644
--- a/firmware/sound.c
+++ b/firmware/sound.c
@@ -498,6 +498,8 @@
#if (CONFIG_HWCODEC == MAS3587F) || (CONFIG_HWCODEC == MAS3539F)
tmp = ((value * 8) & 0xff) << 8;
mas_codec_writereg(0x14, tmp & 0xff00);
+#elif defined(HAVE_UDA1380)
+ uda1380_set_bass(value >> 1);
#elif CONFIG_HWCODEC == MAS3507D
mas_writereg(MAS_REG_KBASS, bass_table[value+15]);
current_bass = value * 10;
@@ -509,6 +511,8 @@
#if (CONFIG_HWCODEC == MAS3587F) || (CONFIG_HWCODEC == MAS3539F)
tmp = ((value * 8) & 0xff) << 8;
mas_codec_writereg(0x15, tmp & 0xff00);
+#elif defined(HAVE_UDA1380)
+ uda1380_set_treble(value >> 1);
#elif CONFIG_HWCODEC == MAS3507D
mas_writereg(MAS_REG_KTREBLE, treble_table[value+15]);
current_treble = value * 10;