From 465596b1639393ef320decced442537133ab09e8 Mon Sep 17 00:00:00 2001 From: Dave Chapman Date: Sun, 5 Feb 2006 17:16:34 +0000 Subject: More iPod 3G code from Seven Le Mesle git-svn-id: svn://svn.rockbox.org/rockbox/trunk@8582 a1c6a512-1295-4272-9138-f99709370657 --- firmware/drivers/ata.c | 33 ++++-- firmware/drivers/button.c | 139 +++++++++++++++++++++- firmware/drivers/i2c-pp5002.c | 168 ++++++++++++++++++++++++++ firmware/drivers/pcf50605.c | 4 + firmware/drivers/power.c | 8 +- firmware/drivers/serial.c | 6 +- firmware/drivers/wm8731l.c | 268 ++++++++++++++++++++++++++++++++++++++++++ 7 files changed, 610 insertions(+), 16 deletions(-) create mode 100644 firmware/drivers/i2c-pp5002.c create mode 100644 firmware/drivers/wm8731l.c diff --git a/firmware/drivers/ata.c b/firmware/drivers/ata.c index 3c79c1be8f..a5fb78d6bd 100644 --- a/firmware/drivers/ata.c +++ b/firmware/drivers/ata.c @@ -71,13 +71,20 @@ #define SET_REG(reg,val) reg = ((val) << 8) #define SET_16BITREG(reg,val) reg = (val) -#elif CONFIG_CPU == PP5020 +#elif (CONFIG_CPU == PP5002) || (CONFIG_CPU == PP5020) /* don't use sh7034 assembler routines */ #define PREFER_C_READING #define PREFER_C_WRITING +#if (CONFIG_CPU == PP5002) +#define ATA_IOBASE 0xc00031e0 +#define ATA_CONTROL (*((volatile unsigned char*)(0xc00033f8))) +#elif (CONFIG_CPU == PP5020) #define ATA_IOBASE 0xc30001e0 +#define ATA_CONTROL (*((volatile unsigned char*)(0xc30003f8))) +#endif + #define ATA_DATA (*((volatile unsigned short*)(ATA_IOBASE))) #define ATA_ERROR (*((volatile unsigned char*)(ATA_IOBASE + 0x04))) #define ATA_NSECTOR (*((volatile unsigned char*)(ATA_IOBASE + 0x08))) @@ -86,7 +93,6 @@ #define ATA_HCYL (*((volatile unsigned char*)(ATA_IOBASE + 0x14))) #define ATA_SELECT (*((volatile unsigned char*)(ATA_IOBASE + 0x18))) #define ATA_COMMAND (*((volatile unsigned char*)(ATA_IOBASE + 0x1c))) -#define ATA_CONTROL (*((volatile unsigned char*)(0xc30003f8))) #define STATUS_BSY 0x80 #define STATUS_RDY 0x40 @@ -928,6 +934,11 @@ extern void ata_flush(void) static int check_registers(void) { +#if (CONFIG_CPU == PP5002) + /* This fails on the PP5002, but the ATA driver still works. This + needs more investigation. */ + return 0; +#else int i; if ( ATA_STATUS & STATUS_BSY ) return -1; @@ -939,13 +950,14 @@ static int check_registers(void) SET_REG(ATA_HCYL, WRITE_PATTERN4); if ((ATA_NSECTOR == READ_PATTERN1) && - (ATA_SECTOR == READ_PATTERN2) && - (ATA_LCYL == READ_PATTERN3) && - (ATA_HCYL == READ_PATTERN4)) + (ATA_SECTOR == READ_PATTERN2) && + (ATA_LCYL == READ_PATTERN3) && + (ATA_HCYL == READ_PATTERN4)) return 0; } return -2; +#endif } static int freeze_lock(void) @@ -1254,7 +1266,7 @@ void ata_enable(bool on) (void)on; #elif CONFIG_CPU == TCC730 -#elif CONFIG_CPU == PP5020 +#elif (CONFIG_CPU == PP5002) || (CONFIG_CPU == PP5020) /* TODO: Implement ata_enable() */ (void)on; #endif @@ -1410,7 +1422,7 @@ int ata_init(void) #elif defined(IAUDIO_X5) /* X5 TODO */ bool coldstart = true; -#elif CONFIG_CPU == PP5020 +#elif (CONFIG_CPU == PP5002) || (CONFIG_CPU == PP5020) bool coldstart = false; /* TODO: Implement coldstart variable */ #else @@ -1440,6 +1452,13 @@ int ata_init(void) or_l(0x00080000, &GPIO_FUNCTION); /* FYI: The IDECONFIGx registers are set by set_cpu_frequency() */ +#elif CONFIG_CPU == PP5002 + /* From ipod-ide.c:ipod_ide_register() */ + outl(inl(0xc0003024) | (1 << 7), 0xc0003024); + outl(inl(0xc0003024) & ~(1<<2), 0xc0003024); + + outl(0x10, 0xc0003000); + outl(0x80002150, 0xc0003004); #elif CONFIG_CPU == PP5020 /* From ipod-ide.c:ipod_ide_register() */ outl(inl(0xc3000028) | (1 << 5), 0xc3000028); diff --git a/firmware/drivers/button.c b/firmware/drivers/button.c index 654852c516..5098cbe556 100644 --- a/firmware/drivers/button.c +++ b/firmware/drivers/button.c @@ -61,7 +61,8 @@ static bool flipped; /* buttons can be flipped to match the LCD flip */ #define REPEAT_INTERVAL_FINISH 5 /* the power-off button and number of repeated keys before shutting off */ -#if (CONFIG_KEYPAD == IPOD_4G_PAD) || (CONFIG_KEYPAD == IRIVER_IFP7XX_PAD) +#if (CONFIG_KEYPAD == IPOD_3G_PAD) || (CONFIG_KEYPAD == IPOD_4G_PAD) ||\ + (CONFIG_KEYPAD == IRIVER_IFP7XX_PAD) #define POWEROFF_BUTTON BUTTON_PLAY #define POWEROFF_COUNT 40 #else @@ -220,7 +221,132 @@ void ipod_4g_button_int(void) CPU_HI_INT_EN = I2C_MASK; } #endif +#if CONFIG_KEYPAD == IPOD_3G_PAD +/* Variable to use for setting button status in interrupt handler */ +int int_btn = BUTTON_NONE; +/** + * + * + */ +void handle_scroll_wheel(int new_scroll, int was_hold, int reverse) +{ + int wheel_keycode = BUTTON_NONE; + static int prev_scroll = -1; + static int scroll_state[4][4] = { + {0, 1, -1, 0}, + {-1, 0, 0, 1}, + {1, 0, 0, -1}, + {0, -1, 1, 0} + }; + + if ( prev_scroll == -1 ) { + prev_scroll = new_scroll; + } + else if (!was_hold) { + switch (scroll_state[prev_scroll][new_scroll]) { + case 1: + if (reverse) { + /* 'r' keypress */ + wheel_keycode = BUTTON_SCROLL_FWD; + } + else { + /* 'l' keypress */ + wheel_keycode = BUTTON_SCROLL_BACK; + } + break; + case -1: + if (reverse) { + /* 'l' keypress */ + wheel_keycode = BUTTON_SCROLL_BACK; + } + else { + /* 'r' keypress */ + wheel_keycode = BUTTON_SCROLL_FWD; + break; + default: + /* only happens if we get out of sync */ + break; + } + } + } + if (wheel_keycode != BUTTON_NONE) + queue_post(&button_queue, wheel_keycode, NULL); + prev_scroll = new_scroll; +} + +static int ipod_3g_button_read(void) +{ + unsigned char source, state; + static int was_hold = 0; +int btn = BUTTON_NONE; + /* + * we need some delay for g3, cause hold generates several interrupts, + * some of them delayed + */ + udelay(250); + + /* get source of interupts */ + source = inb(0xcf000040); + if (source) { + + /* get current keypad status */ + state = inb(0xcf000030); + outb(~state, 0xcf000060); + + if (was_hold && source == 0x40 && state == 0xbf) { + /* ack any active interrupts */ + outb(source, 0xcf000070); + return BUTTON_NONE; + } + was_hold = 0; + + + if ( source & 0x20 ) { + /* 3g hold switch is active low */ + btn |= BUTTON_HOLD; + was_hold = 1; + /* hold switch on 3g causes all outputs to go low */ + /* we shouldn't interpret these as key presses */ + goto done; + } + if (source & 0x1) { + btn |= BUTTON_RIGHT; + } + if (source & 0x2) { + btn |= BUTTON_SELECT; + } + if (source & 0x4) { + btn |= BUTTON_PLAY; + } + if (source & 0x8) { + btn |= BUTTON_LEFT; + } + if (source & 0x10) { + btn |= BUTTON_MENU; + } + + if (source & 0xc0) { + handle_scroll_wheel((state & 0xc0) >> 6, was_hold, 0); + } + done: + + /* ack any active interrupts */ + outb(source, 0xcf000070); + } + return btn; +} + +void ipod_3g_button_int(void) +{ + /** + * Theire is other things to do but for now ... + * TODO: implement this function in a better way + **/ + int_btn = ipod_3g_button_read(); + +} +#endif static void button_tick(void) { static int tick = 0; @@ -404,8 +530,13 @@ void button_init(void) GPIOA_INT_EN = 0x20; CPU_INT_EN = 0x40000000; CPU_HI_INT_EN = I2C_MASK; -#endif /* CONFIG_KEYPAD */ +#elif CONFIG_KEYPAD == IPOD_3G_PAD + outb(~inb(GPIOA_INPUT_VAL), GPIOA_INT_LEV); + outb(inb(GPIOA_INT_STAT), GPIOA_INT_CLR); + outb(0xff, GPIOA_INT_EN); + +#endif /* CONFIG_KEYPAD */ queue_init(&button_queue); button_read(); lastbtn = button_read(); @@ -418,7 +549,7 @@ void button_init(void) } #ifdef HAVE_LCD_BITMAP /* only bitmap displays can be flipped */ -#if (CONFIG_KEYPAD != IPOD_4G_PAD) +#if (CONFIG_KEYPAD != IPOD_3G_PAD) && (CONFIG_KEYPAD != IPOD_4G_PAD) /* * helper function to swap UP/DOWN, LEFT/RIGHT (and F1/F3 for Recorder) */ @@ -883,7 +1014,7 @@ static int button_read(void) if (data & 0x01) btn |= BUTTON_ON; -#elif CONFIG_KEYPAD == IPOD_4G_PAD +#elif (CONFIG_KEYPAD == IPOD_3G_PAD) || (CONFIG_KEYPAD == IPOD_4G_PAD) (void)data; /* The int_btn variable is set in the button interrupt handler */ btn = int_btn; diff --git a/firmware/drivers/i2c-pp5002.c b/firmware/drivers/i2c-pp5002.c new file mode 100644 index 0000000000..dc26d8a5d9 --- /dev/null +++ b/firmware/drivers/i2c-pp5002.c @@ -0,0 +1,168 @@ +/*************************************************************************** + * __________ __ ___. + * Open \______ \ ____ ____ | | _\_ |__ _______ ___ + * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ / + * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < < + * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \ + * \/ \/ \/ \/ \/ + * $Id$ + * + * PP5002 I2C driver + * + * Based on code from the ipodlinux project - http://ipodlinux.org/ + * Adapted for Rockbox in January 2006 + * + * Original file: linux/arch/armnommu/mach-ipod/hardware.c + * + * Copyright (c) 2003-2005 Bernard Leach (leachbj@bouncycastle.org) + * + * 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 "cpu.h" +#include "kernel.h" +#include "logf.h" +#include "system.h" +#include "i2c-pp5002.h" + +/* Local functions definitions */ + +#define IPOD_I2C_BASE 0xc0008000 +#define IPOD_I2C_CTRL (IPOD_I2C_BASE+0x00) +#define IPOD_I2C_ADDR (IPOD_I2C_BASE+0x04) +#define IPOD_I2C_DATA0 (IPOD_I2C_BASE+0x0c) +#define IPOD_I2C_DATA1 (IPOD_I2C_BASE+0x10) +#define IPOD_I2C_DATA2 (IPOD_I2C_BASE+0x14) +#define IPOD_I2C_DATA3 (IPOD_I2C_BASE+0x18) +#define IPOD_I2C_STATUS (IPOD_I2C_BASE+0x1c) + +/* IPOD_I2C_CTRL bit definitions */ +#define IPOD_I2C_SEND 0x80 + +/* IPOD_I2C_STATUS bit definitions */ +#define IPOD_I2C_BUSY (1<<6) + +#define POLL_TIMEOUT (HZ) + +static int ipod_i2c_wait_not_busy(void) +{ + unsigned long timeout; + timeout = current_tick + POLL_TIMEOUT; + while (TIME_BEFORE(current_tick, timeout)) { + if (!(inb(IPOD_I2C_STATUS) & IPOD_I2C_BUSY)) { + return 0; + } + yield(); + } + + return -1; +} + + +/* Public functions */ + +int ipod_i2c_read_byte(unsigned int addr, unsigned int *data) +{ + if (ipod_i2c_wait_not_busy() < 0) + { + return -1; + } + + /* clear top 15 bits, left shift 1, or in 0x1 for a read */ + outb(((addr << 17) >> 16) | 0x1, IPOD_I2C_ADDR); + + outb(inb(IPOD_I2C_CTRL) | 0x20, IPOD_I2C_CTRL); + + outb(inb(IPOD_I2C_CTRL) | IPOD_I2C_SEND, IPOD_I2C_CTRL); + + if (ipod_i2c_wait_not_busy() < 0) + { + return -1; + } + + if (data) + { + *data = inb(IPOD_I2C_DATA0); + } + + return 0; +} + +int ipod_i2c_send_bytes(unsigned int addr, unsigned int len, unsigned char *data) +{ + int data_addr; + unsigned int i; + + if (len < 1 || len > 4) + { + return -1; + } + + if (ipod_i2c_wait_not_busy() < 0) + { + return -2; + } + + /* clear top 15 bits, left shift 1 */ + outb((addr << 17) >> 16, IPOD_I2C_ADDR); + + outb(inb(IPOD_I2C_CTRL) & ~0x20, IPOD_I2C_CTRL); + + data_addr = IPOD_I2C_DATA0; + for ( i = 0; i < len; i++ ) + { + outb(*data++, data_addr); + data_addr += 4; + } + + outb((inb(IPOD_I2C_CTRL) & ~0x26) | ((len-1) << 1), IPOD_I2C_CTRL); + + outb(inb(IPOD_I2C_CTRL) | IPOD_I2C_SEND, IPOD_I2C_CTRL); + + return 0x0; +} + +int ipod_i2c_send_byte(unsigned int addr, int data0) +{ + unsigned char data[1]; + + data[0] = data0; + + return ipod_i2c_send_bytes(addr, 1, data); +} + + +int i2c_readbyte(unsigned int dev_addr, int addr) +{ + int data; + + ipod_i2c_send_byte(dev_addr, addr); + ipod_i2c_read_byte(dev_addr, &data); + + return data; +} + +int ipod_i2c_send(unsigned int addr, int data0, int data1) +{ + unsigned char data[2]; + + data[0] = data0; + data[1] = data1; + + return ipod_i2c_send_bytes(addr, 2, data); +} + +void i2c_init(void) +{ + /* From ipodlinux */ + + outl(inl(0xcf005000) | 0x2, 0xcf005000); + + outl(inl(0xcf005030) | (1<<8), 0xcf005030); + outl(inl(0xcf005030) & ~(1<<8), 0xcf005030); +} diff --git a/firmware/drivers/pcf50605.c b/firmware/drivers/pcf50605.c index d205f89882..122ba6ee38 100644 --- a/firmware/drivers/pcf50605.c +++ b/firmware/drivers/pcf50605.c @@ -24,7 +24,11 @@ * ****************************************************************************/ #include "config.h" +#if CONFIG_I2C == I2C_PP5020 #include "i2c-pp5020.h" +#elif CONFIG_I2C == I2C_PP5002 +#include "i2c-pp5002.h" +#endif #include "rtc.h" #define OOCS 0x01 diff --git a/firmware/drivers/power.c b/firmware/drivers/power.c index e91d8a25cc..2150040dd6 100644 --- a/firmware/drivers/power.c +++ b/firmware/drivers/power.c @@ -84,7 +84,7 @@ void power_init(void) pcf50606_init(); #endif #endif -#elif CONFIG_CPU == PP5020 +#elif CONFIG_CPU == PP5020 || CONFIG_CPU == PP5002 /* TODO: Implement power_init() */ #else #ifdef HAVE_POWEROFF_ON_PB5 @@ -181,7 +181,7 @@ void ide_power_enable(bool on) or_l(0x80000000, &GPIO_OUT); #elif defined(IAUDIO_X5) /* X5 TODO */ -#elif CONFIG_CPU == PP5020 +#elif (CONFIG_CPU == PP5002) || (CONFIG_CPU == PP5020) /* We do nothing on the iPod */ #elif defined(GMINI_ARCH) if(on) @@ -237,7 +237,7 @@ bool ide_powered(void) return (GPIO_OUT & 0x80000000)?false:true; #elif defined(IAUDIO_X5) return false; /* X5 TODO */ -#elif CONFIG_CPU == PP5020 +#elif (CONFIG_CPU == PP5002) || (CONFIG_CPU == PP5020) /* pretend we are always powered - we don't turn it off on the ipod */ return true; #elif defined(GMINI_ARCH) @@ -273,7 +273,7 @@ void power_off(void) and_l(~0x00080000, &GPIO1_OUT); #elif defined(IAUDIO_X5) and_l(~0x00000008, &GPIO_OUT); -#elif CONFIG_CPU == PP5020 +#elif (CONFIG_CPU == PP5002) || (CONFIG_CPU == PP5002) #ifndef BOOTLOADER /* We don't turn off the ipod, we put it in a deep sleep */ pcf50605_standby_mode(); diff --git a/firmware/drivers/serial.c b/firmware/drivers/serial.c index b491b13abb..8479da52f8 100644 --- a/firmware/drivers/serial.c +++ b/firmware/drivers/serial.c @@ -27,7 +27,11 @@ #include "lcd.h" #include "serial.h" -#if (CONFIG_CPU != MCF5249) && (CONFIG_CPU != TCC730) && (CONFIG_CPU != PP5020) && (CONFIG_CPU != PNX0101) && (CONFIG_CPU != MCF5250) + +#if (CONFIG_CPU != MCF5249) && (CONFIG_CPU != TCC730) && \ + (CONFIG_CPU != PP5020) && (CONFIG_CPU != PNX0101) && \ + (CONFIG_CPU != PP5002) && (CONFIG_CPU != MCF5250) + /* FIX: this doesn't work on iRiver or Gmini or iPod yet */ /* iFP7xx has no remote */ diff --git a/firmware/drivers/wm8731l.c b/firmware/drivers/wm8731l.c new file mode 100644 index 0000000000..d49e8f4476 --- /dev/null +++ b/firmware/drivers/wm8731l.c @@ -0,0 +1,268 @@ +/*************************************************************************** + * __________ __ ___. + * Open \______ \ ____ ____ | | _\_ |__ _______ ___ + * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ / + * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < < + * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \ + * \/ \/ \/ \/ \/ + * $Id$ + * + * Driver for WM8731L audio codec + * + * Based on code from the ipodlinux project - http://ipodlinux.org/ + * Adapted for Rockbox in January 2006 + * + * Original file: linux/arch/armnommu/mach-ipod/audio.c + * + * Copyright (c) 2003-2005 Bernard Leach (leachbj@bouncycastle.org) + * + * 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 "i2c-pp5002.h" +#include "wm8731l.h" +#include "pcf50605.h" + +void wm8731l_reset(void); + +#define IPOD_PCM_LEVEL 0x65 /* -6dB */ + +#define RESET (0x0f<<1) +#define PWRMGMT1 (0x19<<1) +#define PWRMGMT2 (0x1a<<1) +#define AINTFCE (0x07<<1) +#define LOUT1VOL (0x02<<1) +#define ROUT1VOL (0x03<<1) +#define LOUT2VOL (0x28<<1) +#define ROUT2VOL (0x29<<1) + +int wm8731l_mute(int mute) +{ + if (mute) + { + /* Set DACMU = 1 to soft-mute the audio DACs. */ + ipod_i2c_send(0x1a, 0xa, 0x8); + } else { + /* Set DACMU = 0 to soft-un-mute the audio DACs. */ + ipod_i2c_send(0x1a, 0xa, 0x0); + } + + return 0; +} +/** From ipodLinux **/ +static void codec_set_active(int active) +{ + /* set active to 0x0 or 0x1 */ + if (active) { + ipod_i2c_send(0x1a, 0x12, 0x01); + } else { + ipod_i2c_send(0x1a, 0x12, 0x00); + } +} + +/* + * Reset the I2S BIT.FORMAT I2S, 16bit, FIFO.FORMAT 32bit + */ +static void i2s_reset(void) +{ + /* I2S device reset */ + outl(inl(0xcf005030) | 0x80, 0xcf005030); + outl(inl(0xcf005030) & ~0x80, 0xcf005030); + + /* I2S controller enable */ + outl(inl(0xc0002500) | 0x1, 0xc0002500); + + /* BIT.FORMAT [11:10] = I2S (default) */ + /* BIT.SIZE [9:8] = 24bit */ + /* FIFO.FORMAT = 24 bit LSB */ + + /* reset DAC and ADC fifo */ + outl(inl(0xc000251c) | 0x30000, 0xc000251c); +} + +/* + * Initialise the WM8975 for playback via headphone and line out. + * Note, I'm using the WM8750 datasheet as its apparently close. + */ +int wm8731l_init(void) { + /* reset I2C */ + i2c_init(); + + /* device reset */ + outl(inl(0xcf005030) | 0x80, 0xcf005030); + outl(inl(0xcf005030) & ~0x80, 0xcf005030); + + /* device enable */ + outl(inl(0xcf005000) | 0x80, 0xcf005000); + + /* GPIO D06 enable for output */ + outl(inl(0xcf00000c) | 0x40, 0xcf00000c); + outl(inl(0xcf00001c) & ~0x40, 0xcf00001c); + /* bits 11,10 == 01 */ + outl(inl(0xcf004040) | 0x400, 0xcf004040); + outl(inl(0xcf004040) & ~0x800, 0xcf004040); + + outl(inl(0xcf004048) & ~0x1, 0xcf004048); + + outl(inl(0xcf000004) & ~0xf, 0xcf000004); + outl(inl(0xcf004044) & ~0xf, 0xcf004044); + + /* C03 = 0 */ + outl(inl(0xcf000008) | 0x8, 0xcf000008); + outl(inl(0xcf000018) | 0x8, 0xcf000018); + outl(inl(0xcf000028) & ~0x8, 0xcf000028); + + return 0; +} + +/* Silently enable / disable audio output */ +void wm8731l_enable_output(bool enable) +{ + if (enable) + { + /* reset the I2S controller into known state */ + i2s_reset(); + + ipod_i2c_send(0x1a, 0x1e, 0x0); /*Reset*/ + + codec_set_active(0x0); + + /* DACSEL=1 */ + /* BYPASS=1 */ + ipod_i2c_send(0x1a, 0x8, 0x18); + + /* set power register to POWEROFF=0 on OUTPD=0, DACPD=0 */ + ipod_i2c_send(0x1a, 0xc, 0x67); + + /* BCLKINV=0(Dont invert BCLK) MS=1(Enable Master) LRSWAP=0 LRP=0 */ + /* IWL=00(16 bit) FORMAT=10(I2S format) */ + ipod_i2c_send(0x1a, 0xe, 0x42); + + wm8731l_set_sample_rate(WM8731L_44100HZ); + + /* set the volume to -6dB */ + ipod_i2c_send(0x1a, 0x4, IPOD_PCM_LEVEL); + ipod_i2c_send(0x1a, 0x6 | 0x1, IPOD_PCM_LEVEL); + + /* ACTIVE=1 */ + codec_set_active(1); + + /* 5. Set DACMU = 0 to soft-un-mute the audio DACs. */ + ipod_i2c_send(0x1a, 0xa, 0x0); + + wm8731l_mute(0); + } else { + wm8731l_mute(1); + } +} + +int wm8731l_set_master_vol(int vol_l, int vol_r) +{ + /* +6 to -73dB 1dB steps (plus mute == 80levels) 7bits */ + /* 1111111 == +6dB */ + /* 1111001 == 0dB */ + /* 0110000 == -73dB */ + /* 0101111 == mute (0x2f) */ + if (vol_l == vol_r) { + ipod_i2c_send(0x1a, 0x4 | 0x1, vol_l); + } else { + ipod_i2c_send(0x1a, 0x4, vol_l); + ipod_i2c_send(0x1a, 0x6, vol_r); + } + + return 0; +} + +int wm8975_set_mixer_vol(int channel1, int channel2) +{ + (void)channel1; + (void)channel2; + + return 0; +} + +void wm8731l_set_bass(int value) +{ + (void)value; +} + +void wm8731l_set_treble(int value) +{ + (void)value; +} + +/* Nice shutdown of WM8975 codec */ +void wm8731l_close(void) +{ + /* set DACMU=1 DEEMPH=0 */ + ipod_i2c_send(0x1a, 0xa, 0x8); + + /* ACTIVE=0 */ + codec_set_active(0x0); + + /* line in mute left & right*/ + ipod_i2c_send(0x1a, 0x0 | 0x1, 0x80); + + /* set DACSEL=0, MUTEMIC=1 */ + ipod_i2c_send(0x1a, 0x8, 0x2); + + /* set POWEROFF=0 OUTPD=0 DACPD=1 */ + ipod_i2c_send(0x1a, 0xc, 0x6f); + + /* set POWEROFF=1 OUTPD=1 DACPD=1 */ + ipod_i2c_send(0x1a, 0xc, 0xff); +} + +/* Change the order of the noise shaper, 5th order is recommended above 32kHz */ +void wm8731l_set_nsorder(int order) +{ + (void)order; +} + +/* */ +void wm8731l_set_sample_rate(int sampling_control) +{ + codec_set_active(0x0); + ipod_i2c_send(0x1a, 0x10, sampling_control); + codec_set_active(0x1); +} + +void wm8731l_enable_recording(bool source_mic) +{ + (void)source_mic; +} + +void wm8731l_disable_recording(void) +{ + +} + +void wm8731l_set_recvol(int left, int right, int type) +{ + (void)left; + (void)right; + (void)type; +} + +void wm8731l_set_monitor(int enable) +{ + (void)enable; +} -- cgit v1.2.3