Index: bootloader/ipodnano2g.c =================================================================== --- bootloader/ipodnano2g.c (revision 22007) +++ bootloader/ipodnano2g.c (working copy) @@ -44,6 +44,9 @@ #include "power.h" #include "file.h" #include "common.h" +#include "pcm.h" +#include "audiohw.h" +#include "wmcodec.h" char version[] = APPSVERSION; @@ -51,10 +54,13 @@ extern int show_logo(void); extern int line; + unsigned char* data = (unsigned char*)0x08800000; +#define CHUNK_SIZE (1024*1024) + void main(void) { - int i; + int i,j,k; system_init(); i2c_init(); @@ -66,26 +72,44 @@ _backlight_init(); + button_init_device(); + + audiohw_init(); /* Nothing! */ + + dma_init(); /* - enables IRQs... */ + + INTMSK = ~((1<<1) | (1<<3) | (1<<4) | (1<<5) | (1<<10) | (1<<13)); + + // for (i=0;i<100000;i++) { data[i] = i; } + + audiohw_init(); + pcm_play_dma_init(); + pcm_dma_apply_settings(); + pcm_postinit(); + + my_pcm_play_data(data, 1*1024*1024); + data += CHUNK_SIZE; + + // audio_test(); + lcd_puts_scroll(0,0,"+++ this is a very very long line to test scrolling. ---"); verbose = 0; i = 0; + j = 1; + + while (!button_hold()) { + if (DMACTCNT0 == 0) { + my_pcm_play_data(data, CHUNK_SIZE); + data += CHUNK_SIZE; + } line = 1; - printf("i=%d",i++); - printf("TBCNT: %08x",TBCNT); - printf("GPIO 0: %08x",PDAT0); - printf("GPIO 1: %08x",PDAT1); - printf("GPIO 2: %08x",PDAT2); - printf("GPIO 3: %08x",PDAT3); - printf("GPIO 4: %08x",PDAT4); - printf("GPIO 5: %08x",PDAT5); - printf("GPIO 6: %08x",PDAT6); - printf("GPIO 7: %08x",PDAT7); - printf("GPIO 10: %08x",PDAT10); - printf("GPIO 11: %08x",PDAT11); - printf("GPIO 13: %08x",PDAT13); - printf("GPIO 14: %08x",PDAT14); + printf("j=%d",j++); + printf("buttons=%08x",button_read_device()); + printf("DMACTCNT0=%10d",DMACTCNT0); + printf("SRCPND=%08x",SRCPND); + printf("I2SSTATUS=%08x",I2SSTATUS); lcd_update(); } Index: bootloader/meizu_m3.c =================================================================== --- bootloader/meizu_m3.c (revision 22007) +++ bootloader/meizu_m3.c (working copy) @@ -53,6 +53,8 @@ #include "pcm.h" #include "audiohw.h" #include "rtc.h" +#include "tea5760.h" +#include "fmradio_i2c.h" char version[] = APPSVERSION; #define LONG_DELAY 200000 @@ -106,13 +108,33 @@ delay(SHORT_DELAY*6); } +static struct tea5760_dbg_info fm_info; +static int count = 0; + +static void timer_callback(void) +{ + count++; +} + +extern int usb_int_count; + void main(void) { char mystring[64]; int i; unsigned short data = 0; char write_data[2], read_data[16]; + int line = 1; + static int pos, prev = 0; + static const int clicks[] = {1, 2, 1, 2}; + static int click = 0; + bool already = false; + + PCON0 = 0; + PCON1 = 0; + PCON3 = 0; + //Set backlight pin to output and enable int oldval = PCON0; PCON0 = ((oldval & ~(3 << 4)) | (1 << 4)); @@ -136,9 +158,9 @@ PCON1 = (oldval & ~(0xf)) | 2; // enable external interrupts - EINTPOL = 0x11; - INTMSK = 0x11; - EINTMSK = 0x11; +// EINTPOL = 0x11; +// INTMSK = 0x11; +// EINTMSK = 0x11; asm volatile("msr cpsr_c, #0x13\n\t"); // enable interrupts system_init(); @@ -147,10 +169,30 @@ backlight_init(); lcd_init(); lcd_update(); + + adc_init(); i2c_init(); + fmradio_i2c_init(); + tea5760_set(RADIO_SLEEP, 0); + tea5760_set(RADIO_MUTE, 0); + tea5760_set(RADIO_FREQUENCY, 97600000); + button_init_device(); + audiohw_init(); + dma_init(); + pcm_play_dma_init(); + pcm_dma_apply_settings(); + pcm_postinit(); + + my_pcm_play_data(0, 10000); + + timer_register(1, NULL, 3 * TIMER_FREQ, timer_callback); + + power_init(); + init_qt1106(); + usb_init(); /* Calibrate the lot */ qt1106_io(QT1106_MODE_FREE | QT1106_MOD_INF | QT1106_DI \ @@ -165,13 +207,15 @@ while(true) { -#if 1 /* enable this to see info about the slider touchpad */ + line = 3; + +#if 0 /* enable this to see info about the slider touchpad */ qt1106_wait(); int slider = qt1106_io(QT1106_MODE_FREE | QT1106_MOD_INF \ | QT1106_DI | QT1106_SLD_SLIDER | QT1106_RES_256); snprintf(mystring, 64, "%x %2.2x",(slider & 0x008000)>>15, slider&0xff); - lcd_puts(0,1,mystring); + lcd_puts(0,line++,mystring); _backlight_set_brightness((slider & 0xFF) >> 4); /* @@ -180,12 +224,22 @@ */ #endif -#if 1 /* enable this to see info about the RTC */ +#if 0 + pos = (slider >> 4) & 0xF; + if (pos != prev) { + PDAT5 = (PDAT5 & ~0x6) | (clicks[click] << 1); + click = (click + 1) % 4; + prev = pos; + } +#endif + + +#if 0 /* enable this to see info about the RTC */ rtc_read_datetime(read_data); for (i = 0; i < 7; i++) { snprintf(mystring + 2 * i, 64, "%02X", read_data[i]); } - lcd_puts(0, 10, mystring); + lcd_puts(0, line++, mystring); #endif #if 1 /* enable this so see info about the UDA1380 codec */ @@ -196,18 +250,84 @@ data = read_data[0] << 8 | read_data[1]; snprintf(mystring + 4 * i, 64, "%04X", data); } - lcd_puts(0, 11, mystring); + lcd_puts(0, line++, mystring); #endif #if 1 /* enable this to see info about IODMA channel 0 (PCM) */ snprintf(mystring, 64, "DMA: %08X %08X", DMACADDR0, DMACTCNT0); - lcd_puts(0, 12, mystring); + lcd_puts(0, line++, mystring); #endif -#if 1 /* enable this to see info about IIS */ - snprintf(mystring, 64, "IIS: %08X", I2SSTATUS); - lcd_puts(0, 13, mystring); -#endif +#if 0 /* enable this to see info about fmradio */ + tea5760_dbg_info(&fm_info); + for (i = 0; i < 8; i++) { + snprintf(mystring + 3 * i, 64, "%02X ", fm_info.read_regs[i]); + } + lcd_puts(0, line++, mystring); + for (i = 0; i < 8; i++) { + snprintf(mystring + 3 * i, 64, "%02X ", fm_info.read_regs[i+8]); + } + lcd_puts(0, line++, mystring); +#endif + +#if 0 /* enable this to see ADC */ + snprintf(mystring, 64, "ADC: %04X %04X %04X %04X", + adc_read(0), adc_read(1), adc_read(2), adc_read(3)); + lcd_puts(0, line++, mystring); +#endif + +#if 1 /* enable this to see info about GPIO */ + snprintf(mystring, 64, "GPIO: %02X %02X %02X %02X %02X %02X", + PDAT0, PDAT1, PDAT2, PDAT3, PDAT4, PDAT5); + lcd_puts(0, line++, mystring); +#endif + +#if 1 /* enable this to see info about GPIO */ + snprintf(mystring, 64, "BUTTONS: %08X", button_read_device()); + lcd_puts(0, line++, mystring); +#endif + +#if 0 /* enable to see timer/counter */ + snprintf(mystring, 64, "TIMER: %08X", count); + lcd_puts(0, line++, mystring); + snprintf(mystring, 64, "TIMER %04X %04X %04X", TDCON, TDPRE, TDDATA0); + lcd_puts(0, line++, mystring); +#endif + +#if 1 /* enable to see clocking info */ + snprintf(mystring, 64, "CLK %08X PLL0 %08X", CLKCON, PLL0PMS); + lcd_puts(0, line++, mystring); +#endif + +#if 1 /* enable to see power/charge info */ + snprintf(mystring, 64, "PWR %02X CHG %02X INS %02X BAT %04d", + power_input_status(), charging_state(), charger_inserted(), battery_adc_voltage()); + lcd_puts(0, line++, mystring); +#endif + +#if 0 /* USB info */ + snprintf(mystring, 64, "cnt %4d", usb_int_count); + lcd_puts(0, line++, mystring); + + snprintf(mystring, 64, "%08X %08X %08X", REG_ONE, REG_TWO); + lcd_puts(0, line++, mystring); + + snprintf(mystring, 64, "%08X %08X %08X", PHYCTRL, UCLKCON, URSTCON); + lcd_puts(0, line++, mystring); + + snprintf(mystring, 64, "SSR %04X SCR %04X EP0 %04X", SSR, SCR, EP0SR); + lcd_puts(0, line++, mystring); + + if (button_read_device() != 0) { + if (!already) { + usb_start_monitoring(); + usb_attach(); +// usb_acknowledge(SYS_USB_CONNECTED_ACK); + already = true; + } + } +#endif + lcd_update(); } Index: firmware/export/s5l8700.h =================================================================== --- firmware/export/s5l8700.h (revision 22007) +++ firmware/export/s5l8700.h (working copy) @@ -108,8 +108,10 @@ #define CLKCON (*(REG32_PTR_T)(0x3C500000)) /* Clock control Register */ #define PLL0PMS (*(REG32_PTR_T)(0x3C500004)) /* PLL PMS value Register */ #define PLL1PMS (*(REG32_PTR_T)(0x3C500008)) /* PLL PMS value Register */ +#define PLL2PMS (*(REG32_PTR_T)(0x3C50000C)) /* PLL PMS value Register */ #define PLL0LCNT (*(REG32_PTR_T)(0x3C500014)) /* PLL0 lock count register */ #define PLL1LCNT (*(REG32_PTR_T)(0x3C500018)) /* PLL1 lock count register */ +#define PLL2LCNT (*(REG32_PTR_T)(0x3C50001C)) /* PLL2 lock count register */ #define PLLLOCK (*(REG32_PTR_T)(0x3C500020)) /* PLL lock status register */ #define PLLCON (*(REG32_PTR_T)(0x3C500024)) /* PLL control register */ #define PWRCON (*(REG32_PTR_T)(0x3C500028)) /* Clock power control register */ Index: firmware/export/config-ipodnano2g.h =================================================================== --- firmware/export/config-ipodnano2g.h (revision 22007) +++ firmware/export/config-ipodnano2g.h (working copy) @@ -86,7 +86,7 @@ #define CONFIG_LCD LCD_NANO2G /* Define the type of audio codec */ -#define HAVE_UDA1380 +#define HAVE_WM8975 /* Define this for LCD backlight available */ #define HAVE_BACKLIGHT @@ -101,10 +101,6 @@ /* The number of bytes reserved for loadable plugins */ #define PLUGIN_BUFFER_SIZE 0x80000 -/* FM Tuner */ -#define CONFIG_TUNER TEA5760 -#define CONFIG_TUNER_XTAL 32768 - //#define HAVE_TLV320 /* TLV320 has no tone controls, so we use the software ones */ Index: firmware/SOURCES =================================================================== --- firmware/SOURCES (revision 22007) +++ firmware/SOURCES (working copy) @@ -1302,7 +1302,12 @@ #endif /* MEIZU_M3 */ #ifdef IPOD_NANO2G +target/arm/s5l8700/stubs.c target/arm/s5l8700/kernel-s5l8700.c +target/arm/s5l8700/wmcodec-s5l8700.c +target/arm/s5l8700/pcm-s5l8700.c +target/arm/s5l8700/dma-s5l8700.c +drivers/audio/wm8975.c target/arm/s5l8700/ipodnano2g/backlight-nano2g.c target/arm/s5l8700/ipodnano2g/button-nano2g.c target/arm/s5l8700/ipodnano2g/lcd-nano2g.c Index: firmware/target/arm/s5l8700/pcm-s5l8700.c =================================================================== --- firmware/target/arm/s5l8700/pcm-s5l8700.c (revision 22007) +++ firmware/target/arm/s5l8700/pcm-s5l8700.c (working copy) @@ -48,7 +48,11 @@ int pdiv, mdiv, sdiv, cdiv; } div_table[HW_NUM_FREQ] = { [HW_FREQ_11] = { 26, 189, 3, 8}, +#ifdef IPOD_NANO2G + [HW_FREQ_22] = { 5, 6, 3, 4}, +#else [HW_FREQ_22] = { 50, 98, 2, 8}, +#endif [HW_FREQ_44] = { 37, 151, 1, 9}, [HW_FREQ_88] = { 50, 98, 1, 4}, #if 0 /* disabled because the codec driver does not support it (yet) */ @@ -116,6 +120,18 @@ DMA_IISOUT_DSIZE, DMA_IISOUT_BLEN, (void *)addr, size / 2, dma_callback); +#ifdef IPOD_NANO2G +// I2STXCON = (0x10 << 16) | /* burst length */ + I2STXCON = (DMA_IISOUT_BLEN << 16) | /* burst length */ + (0 << 15) | /* 0 = falling edge */ + (0 << 13) | /* 0 = basic I2S format */ + (0 << 12) | /* 0 = MSB first */ + (0 << 11) | /* 0 = left channel for low polarity */ + (5 << 8) | /* MCLK divider */ + (0 << 5) | /* 0 = 16-bit */ + (2 << 3) | /* bit clock per frame */ + (1 << 0); /* channel index */ +#else /* S2: IIS Tx mode set */ I2STXCON = (DMA_IISOUT_BLEN << 16) | /* burst length */ (0 << 15) | /* 0 = falling edge */ @@ -126,6 +142,7 @@ (0 << 5) | /* 0 = 16-bit */ (0 << 3) | /* bit clock per frame */ (1 << 0); /* channel index */ +#endif /* S3: DMA channel 0 on */ dma_enable_channel(DMA_IISOUT_CHANNEL); @@ -169,7 +186,12 @@ void pcm_play_dma_init(void) { /* configure IIS pins */ +#ifdef IPOD_NANO2G + PCON5 = (PCON5 & ~(0xFFFFF000)) | 0x22220000; + PCON6 = (PCON6 & ~(0x0F000000)) | 0x02000000; +#else PCON7 = (PCON7 & ~(0x0FFFFF00)) | 0x02222200; +#endif /* enable clock to the IIS module */ PWRCON &= ~(1 << 6); @@ -185,26 +207,45 @@ /* set the configured PCM frequency */ void pcm_dma_apply_settings(void) { - audiohw_set_frequency(pcm_sampr); + // audiohw_set_frequency(pcm_sampr); struct div_entry div = div_table[pcm_fsel]; - + + PLLCON &= ~4; + PLLCON &= ~0x10; + PLLCON &= 0x3f; + PLLCON |= 4; + /* configure PLL1 and MCLK for the desired sample rate */ +#ifdef IPOD_NANO2G + PLL2PMS = 0x20c02; + PLL2LCNT = 0x4d2; + + /* enable PLL2 and wait for lock */ + PLLCON |= (1 << 2); + while ((PLLLOCK & (1 << 2)) == 0); +#else PLL1PMS = (div.pdiv << 16) | (div.mdiv << 8) | (div.sdiv << 0); PLL1LCNT = 7500; /* no idea what to put here */ - + /* enable PLL1 and wait for lock */ PLLCON |= (1 << 1); while ((PLLLOCK & (1 << 1)) == 0); +#endif + /* configure MCLK */ +#ifdef IPOD_NANO2G + CLKCON = (CLKCON & ~(0xFF)) | 0x72; +#else CLKCON = (CLKCON & ~(0xFF)) | (0 << 7) | /* MCLK_MASK */ (2 << 5) | /* MCLK_SEL = PLL1 */ (1 << 4) | /* MCLK_DIV_ON */ (div.cdiv - 1); /* MCLK_DIV_VAL */ +#endif } size_t pcm_get_bytes_waiting(void) Index: firmware/target/arm/s5l8700/wmcodec-s5l8700.c =================================================================== --- firmware/target/arm/s5l8700/wmcodec-s5l8700.c (revision 0) +++ firmware/target/arm/s5l8700/wmcodec-s5l8700.c (revision 0) @@ -0,0 +1,46 @@ +/*************************************************************************** + * __________ __ ___. + * Open \______ \ ____ ____ | | _\_ |__ _______ ___ + * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ / + * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < < + * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \ + * \/ \/ \/ \/ \/ + * $Id: wmcodec-telechips.c 21798 2009-07-12 09:43:44Z kugel $ + * + * TCC specific code for Wolfson audio codecs + * + * Based on code from the ipodlinux project - http://ipodlinux.org/ + * Adapted for Rockbox in December 2005 + * + * Original file: linux/arch/armnommu/mach-ipod/audio.c + * + * Copyright (c) 2003-2005 Bernard Leach (leachbj@bouncycastle.org) + * + * 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 "system.h" +#include "audiohw.h" +#include "i2c-s5l8700.h" +#include "wmcodec.h" + +void audiohw_init(void) +{ +#if defined(HAVE_WM8731) || defined(HAVE_WM8751) || defined(HAVE_WM8985) + audiohw_preinit(); +#endif +} + +void wmcodec_write(int reg, int data) +{ + unsigned char d = data & 0xff; + + i2c_write(0x34, (reg << 1) | ((data & 0x100) >> 8), 1, &d); +} Index: firmware/target/arm/s5l8700/boot.lds =================================================================== --- firmware/target/arm/s5l8700/boot.lds (revision 22007) +++ firmware/target/arm/s5l8700/boot.lds (working copy) @@ -14,7 +14,7 @@ #define DRAMSIZE 16M #define IRAMORIG 0x22000000 -#define IRAMSIZE 256K +#define IRAMSIZE 176K #ifdef MEIZU_M6SL #define DFULOADADDR IRAMORIG Index: firmware/target/arm/s5l8700/system-s5l8700.c =================================================================== --- firmware/target/arm/s5l8700/system-s5l8700.c (revision 22007) +++ firmware/target/arm/s5l8700/system-s5l8700.c (working copy) @@ -96,6 +96,8 @@ "sub sp, sp, #8 \n"); /* Reserve stack */ int irq_no = INTOFFSET; + + if (irq_no==10) { INTMSK &= ~(1<<10); } irqvector[irq_no](); Index: firmware/target/arm/s5l8700/ipodnano2g/button-nano2g.c =================================================================== --- firmware/target/arm/s5l8700/ipodnano2g/button-nano2g.c (revision 22007) +++ firmware/target/arm/s5l8700/ipodnano2g/button-nano2g.c (working copy) @@ -25,16 +25,58 @@ #include "s5l8700.h" #include "button-target.h" +#define CLICKWHEEL00 (*(volatile unsigned long*)(0x3c200000)) +#define CLICKWHEEL10 (*(volatile unsigned long*)(0x3c200010)) +#define CLICKWHEELINT (*(volatile unsigned long*)(0x3c200014)) +#define CLICKWHEEL_DATA (*(volatile unsigned long*)(0x3c200018)) + +static int buttons = 0; + +void INT_SPI(void) +{ + int clickwheel_events; + int btn =0; + int status; + + clickwheel_events = CLICKWHEELINT; + + if (clickwheel_events & 4) CLICKWHEELINT = 4; + if (clickwheel_events & 2) CLICKWHEELINT = 2; + if (clickwheel_events & 1) CLICKWHEELINT = 1; + + status = CLICKWHEEL_DATA; + if ((status & 0x800000ff) == 0x8000001a) + { + if (status & 0x00000100) + btn |= BUTTON_SELECT; + if (status & 0x00000200) + btn |= BUTTON_RIGHT; + if (status & 0x00000400) + btn |= BUTTON_LEFT; + if (status & 0x00000800) + btn |= BUTTON_PLAY; + if (status & 0x00001000) + btn |= BUTTON_MENU; + } + + buttons = btn; +} + void button_init_device(void) { + CLICKWHEEL00 = 0x280000; + CLICKWHEEL10 = 3; + INTMOD = 0; + INTMSK |= (1<<26); + PCON10 &= ~0xF00; } int button_read_device(void) { + return buttons; } bool button_hold(void) { return ((PDAT14 & (1 << 6)) == 0); } - Index: firmware/target/arm/s5l8700/meizu-m3/button-target.h =================================================================== --- firmware/target/arm/s5l8700/meizu-m3/button-target.h (revision 22007) +++ firmware/target/arm/s5l8700/meizu-m3/button-target.h (working copy) @@ -33,6 +33,12 @@ #define BUTTON_PREVNEXT 0x00000001 #define BUTTON_MENU 0x00000002 #define BUTTON_PLAY 0x00000004 +#define BUTTON_UP 0x00000008 +#define BUTTON_DOWN 0x00000010 +#define BUTTON_SELECT 0x00000020 +#define BUTTON_POWER 0x00000040 +#define BUTTON_VOL_UP 0x00000040 +#define BUTTON_VOL_DOWN 0x00000040 /* there are no LEFT/RIGHT buttons, but other parts of the code expect them */ #define BUTTON_LEFT 0 Index: firmware/target/arm/s5l8700/crt0.S =================================================================== --- firmware/target/arm/s5l8700/crt0.S (revision 22007) +++ firmware/target/arm/s5l8700/crt0.S (working copy) @@ -82,6 +82,7 @@ // orr r0, r0, r2 // str r0, [r1] // switch backlight on +#if 0 ldr r1, =0x3c500000 // CLKCON ldr r0, =0x00800080 str r0, [r1] @@ -90,7 +91,7 @@ str r0, [r1] ldr r1, =0x3c500004 // PLL0PMS #ifdef IPOD_NANO2G - ldr r0, =0x21200 + ldr r0, =0x21200 // pdiv=2, mdiv=?? sdiv=0 #else ldr r0, =0x1ad200 #endif @@ -123,7 +124,8 @@ nop nop nop - +#endif + // ldr r0, =0x10100000 // ldr r1, =0x38200034 // str r0, [r1] // SRAM0/1 data width 16 bit @@ -143,7 +145,7 @@ str r0, [r1, #40] // enable clock for all peripherals mov r0, #0 // 0x0 str r0, [r1, #44] // do not enter any power saving mode - + mov r1, #0x1 mrc 15, 0, r0, c1, c0, 0 bic r0, r0, r1 @@ -186,7 +188,7 @@ mcr 15, 0, r0, c6, c0, 1 mov r0, #0x2f mcr 15, 0, r0, c6, c1, 1 - ldr r0, =0x0800002f + ldr r0, =0x08000031 mcr 15, 0, r0, c6, c2, 1 ldr r0, =0x22000023 mcr 15, 0, r0, c6, c3, 1 @@ -196,7 +198,7 @@ mcr 15, 0, r0, c6, c0, 0 mov r0, #0x2f mcr 15, 0, r0, c6, c1, 0 - ldr r0, =0x0800002f + ldr r0, =0x08000031 mcr 15, 0, r0, c6, c2, 0 ldr r0, =0x22000023 mcr 15, 0, r0, c6, c3, 0 Index: firmware/drivers/audio/wm8975.c =================================================================== --- firmware/drivers/audio/wm8975.c (revision 22020) +++ firmware/drivers/audio/wm8975.c (working copy) @@ -133,7 +133,10 @@ /* 2. Enable Vmid and VREF, quick startup. */ wm8975_write(PWRMGMT1, wm8975_regs[PWRMGMT1]); - sleep(HZ/50); + + // sleep(HZ/50); + lcd_update(); + wm8975_regs[PWRMGMT1] &= ~PWRMGMT1_VMIDSEL_MASK; wm8975_write(PWRMGMT1, wm8975_regs[PWRMGMT1] | PWRMGMT1_VMIDSEL_50K); @@ -145,7 +148,8 @@ wm8975_write(DAPCTRL, wm8975_regs[DAPCTRL] ); - wmcodec_write(SAMPCTRL, WM8975_44100HZ); +// wmcodec_write(SAMPCTRL, WM8975_44100HZ); + wmcodec_write(SAMPCTRL, 0); /* set the volume to -6dB */ wmcodec_write(LOUT1VOL, LOUT1VOL_LO1ZC | IPOD_PCM_LEVEL);