forked from len0rd/rockbox
More iPod 3G code from Seven Le Mesle
git-svn-id: svn://svn.rockbox.org/rockbox/trunk@8582 a1c6a512-1295-4272-9138-f99709370657
This commit is contained in:
parent
d16a8b8845
commit
465596b163
7 changed files with 610 additions and 16 deletions
|
|
@ -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;
|
||||
|
|
@ -946,6 +957,7 @@ static int check_registers(void)
|
|||
}
|
||||
|
||||
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);
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
|
|
|||
168
firmware/drivers/i2c-pp5002.c
Normal file
168
firmware/drivers/i2c-pp5002.c
Normal file
|
|
@ -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);
|
||||
}
|
||||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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();
|
||||
|
|
|
|||
|
|
@ -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 */
|
||||
|
||||
|
|
|
|||
268
firmware/drivers/wm8731l.c
Normal file
268
firmware/drivers/wm8731l.c
Normal file
|
|
@ -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;
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue