Gigabeat S: Implement i2c driver - transmit works but no testing of receiving which will get a chance later. Add some seeds for codec driver. Correct a few #defines.

git-svn-id: svn://svn.rockbox.org/rockbox/trunk@17254 a1c6a512-1295-4272-9138-f99709370657
This commit is contained in:
Michael Sevakis 2008-04-27 10:30:54 +00:00
parent fec6af659f
commit 27fac88548
10 changed files with 572 additions and 34 deletions

View file

@ -210,7 +210,9 @@ drivers/mas.c
drivers/audio/uda1380.c
#elif defined(HAVE_WM8751)
drivers/audio/wm8751.c
#elif defined(HAVE_WM8975) || defined(HAVE_WM8978)
#elif defined(HAVE_WM8978)
drivers/audio/wm8978.c
#elif defined(HAVE_WM8975)
drivers/audio/wm8975.c
#elif defined(HAVE_WM8985)
drivers/audio/wm8985.c

View file

@ -0,0 +1,60 @@
/***************************************************************************
* __________ __ ___.
* Open \______ \ ____ ____ | | _\_ |__ _______ ___
* Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
* Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
* Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
* \/ \/ \/ \/ \/
* $Id$
*
* Copyright (C) 2008 by Michael Sevakis
*
* Driver for WM8978 audio codec
*
* 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 "config.h"
#include "system.h"
#include "audiohw.h"
#include "wmcodec.h"
#include "audio.h"
const struct sound_settings_info audiohw_settings[] = {
[SOUND_VOLUME] = {"dB", 0, 1, -58, 6, -25},
[SOUND_BASS] = {"dB", 0, 1, -12, 12, 0},
[SOUND_TREBLE] = {"dB", 0, 1, -12, 12, 0},
[SOUND_BALANCE] = {"%", 0, 1,-100, 100, 0},
[SOUND_CHANNELS] = {"", 0, 1, 0, 5, 0},
[SOUND_STEREO_WIDTH] = {"%", 0, 5, 0, 250, 100},
[SOUND_LEFT_GAIN] = {"dB", 1, 1,-128, 96, 0},
[SOUND_RIGHT_GAIN] = {"dB", 1, 1,-128, 96, 0},
[SOUND_MIC_GAIN] = {"dB", 1, 1,-128, 108, 16},
#if 0
[SOUND_BASS_CUTOFF] = {"", 0, 1, 1, 4, 1},
[SOUND_TREBLE_CUTOFF] = {"", 0, 1, 1, 4, 1},
#endif
};
void audiohw_preinit(void)
{
wmcodec_write(WM8978_SOFTWARE_RESET, 0);
}
void audiohw_postinit(void)
{
sleep(HZ);
}
void audiohw_close(void)
{
}
void audiohw_mute(bool mute)
{
(void)mute;
}

View file

@ -27,7 +27,9 @@
#include "uda1380.h"
#elif defined(HAVE_WM8751)
#include "wm8751.h"
#elif defined(HAVE_WM8975) || defined(HAVE_WM8978)
#elif defined(HAVE_WM8978)
#include "wm8978.h"
#elif defined(HAVE_WM8975)
#include "wm8975.h"
#elif defined(HAVE_WM8985)
#include "wm8985.h"
@ -109,7 +111,14 @@ extern const struct sound_settings_info audiohw_settings[];
void audiohw_init(void);
/**
* Do some stuff (codec related) after audiohw_init.
* Do initial audio codec setup.
*/
void audiohw_preinit(void);
/**
* Do some stuff (codec related) after audiohw_init that needs to be
* delayed such as enabling outputs to prevent popping. This lets
* other inits in the system complete in the meantime.
*/
void audiohw_postinit(void);

View file

@ -66,10 +66,9 @@
/* The number of bytes reserved for loadable plugins */
#define PLUGIN_BUFFER_SIZE 0x80000
/* Define this if you have the WM8975 audio codec */
/* Define this if you have the WM8978 audio codec */
#define HAVE_WM8978
#define HW_SAMPR_CAPS (SAMPR_CAP_88 | SAMPR_CAP_44 | SAMPR_CAP_22 | \
SAMPR_CAP_11)
@ -85,8 +84,9 @@
/* Define this if you want to use coldfire's i2c interface */
#define CONFIG_I2C I2C_IMX31L
/* Define the bitmask of serial interface modules (CSPI) used */
/* Define the bitmask of modules used */
#define SPI_MODULE_MASK (USE_CSPI2_MODULE)
#define I2C_MODULE_MASK (USE_I2C1_MODULE)
/* Define this if target has an additional number of threads specific to it */
#define TARGET_EXTRA_THREADS 1

View file

@ -49,7 +49,7 @@
#define ETB_SLOT4_BASE_ADDR 0x43F10000
#define ETB_SLOT5_BASE_ADDR 0x43F14000
#define ECT_CTIO_BASE_ADDR 0x43F18000
#define I2C_BASE_ADDR 0x43F80000
#define I2C1_BASE_ADDR 0x43F80000
#define I2C3_BASE_ADDR 0x43F84000
#define OTG_BASE_ADDR 0x43F88000
#define ATA_BASE_ADDR 0x43F8C000
@ -628,6 +628,112 @@
#define CSPI_TESTREG_SWAP (1 << 15)
#define CSPI_TESTREG_LBC (1 << 14)
/* I2C */
#define I2C_IADR1 (*(REG16_PTR_T)(I2C1_BASE_ADDR+0x0))
#define I2C_IFDR1 (*(REG16_PTR_T)(I2C1_BASE_ADDR+0x4))
#define I2C_I2CR1 (*(REG16_PTR_T)(I2C1_BASE_ADDR+0x8))
#define I2C_I2SR1 (*(REG16_PTR_T)(I2C1_BASE_ADDR+0xC))
#define I2C_I2DR1 (*(REG16_PTR_T)(I2C1_BASE_ADDR+0x10))
#define I2C_IADR2 (*(REG16_PTR_T)(I2C2_BASE_ADDR+0x0))
#define I2C_IFDR2 (*(REG16_PTR_T)(I2C2_BASE_ADDR+0x4))
#define I2C_I2CR2 (*(REG16_PTR_T)(I2C2_BASE_ADDR+0x8))
#define I2C_I2SR2 (*(REG16_PTR_T)(I2C2_BASE_ADDR+0xC))
#define I2C_I2DR2 (*(REG16_PTR_T)(I2C2_BASE_ADDR+0x10))
#define I2C_IADR3 (*(REG16_PTR_T)(I2C3_BASE_ADDR+0x0))
#define I2C_IFDR3 (*(REG16_PTR_T)(I2C3_BASE_ADDR+0x4))
#define I2C_I2CR3 (*(REG16_PTR_T)(I2C3_BASE_ADDR+0x8))
#define I2C_I2SR3 (*(REG16_PTR_T)(I2C3_BASE_ADDR+0xC))
#define I2C_I2DR3 (*(REG16_PTR_T)(I2C3_BASE_ADDR+0x10))
/* IADR - [7:1] Address */
/* IFDR */
#define I2C_IFDR_DIV30 0x00
#define I2C_IFDR_DIV32 0x01
#define I2C_IFDR_DIV36 0x02
#define I2C_IFDR_DIV42 0x03
#define I2C_IFDR_DIV48 0x04
#define I2C_IFDR_DIV52 0x05
#define I2C_IFDR_DIV60 0x06
#define I2C_IFDR_DIV72 0x07
#define I2C_IFDR_DIV80 0x08
#define I2C_IFDR_DIV88 0x09
#define I2C_IFDR_DIV104 0x0a
#define I2C_IFDR_DIV128 0x0b
#define I2C_IFDR_DIV144 0x0c
#define I2C_IFDR_DIV160 0x0d
#define I2C_IFDR_DIV192 0x0e
#define I2C_IFDR_DIV240 0x0f
#define I2C_IFDR_DIV288 0x10
#define I2C_IFDR_DIV320 0x11
#define I2C_IFDR_DIV384 0x12
#define I2C_IFDR_DIV480 0x13
#define I2C_IFDR_DIV576 0x14
#define I2C_IFDR_DIV640 0x15
#define I2C_IFDR_DIV768 0x16
#define I2C_IFDR_DIV960 0x17
#define I2C_IFDR_DIV1152 0x18
#define I2C_IFDR_DIV1280 0x19
#define I2C_IFDR_DIV1536 0x1a
#define I2C_IFDR_DIV1920 0x1b
#define I2C_IFDR_DIV2304 0x1c
#define I2C_IFDR_DIV2560 0x1d
#define I2C_IFDR_DIV3072 0x1e
#define I2C_IFDR_DIV3840 0x1f
#define I2C_IFDR_DIV22 0x20
#define I2C_IFDR_DIV24 0x21
#define I2C_IFDR_DIV26 0x22
#define I2C_IFDR_DIV28 0x23
#define I2C_IFDR_DIV32_2 0x24
#define I2C_IFDR_DIV36_2 0x25
#define I2C_IFDR_DIV40 0x26
#define I2C_IFDR_DIV44 0x27
#define I2C_IFDR_DIV48_2 0x28
#define I2C_IFDR_DIV56 0x29
#define I2C_IFDR_DIV64 0x2a
#define I2C_IFDR_DIV72_2 0x2b
#define I2C_IFDR_DIV80_2 0x2c
#define I2C_IFDR_DIV96 0x2d
#define I2C_IFDR_DIV112 0x2e
#define I2C_IFDR_DIV128_2 0x2f
#define I2C_IFDR_DIV160_2 0x30
#define I2C_IFDR_DIV192_2 0x31
#define I2C_IFDR_DIV224 0x32
#define I2C_IFDR_DIV256 0x33
#define I2C_IFDR_DIV320_2 0x34
#define I2C_IFDR_DIV384_2 0x35
#define I2C_IFDR_DIV448 0x36
#define I2C_IFDR_DIV512 0x37
#define I2C_IFDR_DIV640_2 0x38
#define I2C_IFDR_DIV768_2 0x39
#define I2C_IFDR_DIV896 0x3a
#define I2C_IFDR_DIV1024 0x3b
#define I2C_IFDR_DIV1280_2 0x3c
#define I2C_IFDR_DIV1536_2 0x3d
#define I2C_IFDR_DIV1792 0x3e
#define I2C_IFDR_DIV2048 0x3f
/* I2CR */
#define I2C_I2CR_IEN (1 << 7)
#define I2C_I2CR_IIEN (1 << 6)
#define I2C_I2CR_MSTA (1 << 5)
#define I2C_I2CR_MTX (1 << 4)
#define I2C_I2CR_TXAK (1 << 3)
#define I2C_I2CR_RSATA (1 << 2)
/* I2SR */
#define I2C_I2SR_ICF (1 << 7)
#define I2C_I2SR_IAAS (1 << 6)
#define I2C_I2SR_IBB (1 << 5)
#define I2C_I2SR_IAL (1 << 4)
#define I2C_I2SR_SRW (1 << 2)
#define I2C_I2SR_IIF (1 << 1)
#define I2C_I2SR_RXAK (1 << 0)
/* I2DR - [7:0] Data */
/* RTC */
#define RTC_HOURMIN (*(REG32_PTR_T)(RTC_BASE_ADDR+0x00))
#define RTC_SECONDS (*(REG32_PTR_T)(RTC_BASE_ADDR+0x04))

View file

@ -21,6 +21,9 @@
#ifndef _WM8978_H
#define _WM8978_H
#define VOLUME_MIN -570
#define VOLUME_MAX 60
#define WM8978_I2C_ADDR 0x34
/* Registers */
@ -142,7 +145,7 @@
#define WM8978_DAC_COMP_U_LAW (2 << 3)
#define WM8978_DAC_COMP_A_LAW (3 << 3)
#define WM8978_ADC_COMP (3 << 1)
#define WM8978_DAC_COMP_OFF (0 << 1)
#define WM8978_ADC_COMP_OFF (0 << 1)
#define WM8978_ADC_COMP_U_LAW (2 << 1)
#define WM8978_ADC_COMP_A_LAW (3 << 1)
#define WM8978_LOOPBACK (1 << 0)
@ -159,12 +162,12 @@
#define WM8978_MCLKDIV_8 (6 << 5)
#define WM8978_MCLKDIV_12 (7 << 5)
#define WM8978_BCLKDIV (7 << 2)
#define WM8978_MCLKDIV_1 (0 << 2)
#define WM8978_MCLKDIV_2 (1 << 2)
#define WM8978_MCLKDIV_4 (2 << 2)
#define WM8978_MCLKDIV_8 (3 << 2)
#define WM8978_MCLKDIV_16 (4 << 2)
#define WM8978_MCLKDIV_32 (5 << 2)
#define WM8978_BCLKDIV_1 (0 << 2)
#define WM8978_BCLKDIV_2 (1 << 2)
#define WM8978_BCLKDIV_4 (2 << 2)
#define WM8978_BCLKDIV_8 (3 << 2)
#define WM8978_BCLKDIV_16 (4 << 2)
#define WM8978_BCLKDIV_32 (5 << 2)
#define WM8978_MS (1 << 0)
/* WM8978_ADDITIONAL_CTRL (0x07) */

View file

@ -7,7 +7,7 @@
* \/ \/ \/ \/ \/
* $Id$
*
* Copyright (C) 2007 by Michael Sevakis
* Copyright (C) 2008 by Michael Sevakis
*
* 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.
@ -16,38 +16,321 @@
* KIND, either express or implied.
*
****************************************************************************/
#include <stdlib.h>
#include "config.h"
#include "system.h"
#include "kernel.h"
#include "avic-imx31.h"
#include "clkctl-imx31.h"
#include "i2c-imx31.h"
#if 0
static int i2c_getack(void)
/* Forward interrupt handler declarations */
#if (I2C_MODULE_MASK & USE_I2C1_MODULE)
static __attribute__((interrupt("IRQ"))) void I2C1_HANDLER(void);
#endif
#if (I2C_MODULE_MASK & USE_I2C2_MODULE)
static __attribute__((interrupt("IRQ"))) void I2C2_HANDLER(void);
#endif
#if (I2C_MODULE_MASK & USE_I2C3_MODULE)
static __attribute__((interrupt("IRQ"))) void I2C3_HANDLER(void);
#endif
static struct i2c_module_descriptor
{
return 0;
struct i2c_map *base; /* Module base address */
enum IMX31_CG_LIST cg; /* Clock gating index */
enum IMX31_INT_LIST ints; /* Module interrupt number */
int enable; /* Enable count */
void (*handler)(void); /* Module interrupt handler */
struct mutex m; /* Node mutual-exclusion */
struct wakeup w; /* I2C done signal */
unsigned char *addr_data; /* Additional addressing data */
int addr_count; /* Addressing byte count */
unsigned char *data; /* TX/RX buffer (actual data) */
int data_count; /* TX/RX byte count */
unsigned char addr; /* Address + r/w bit */
} i2c_descs[I2C_NUM_I2C] =
{
#if (I2C_MODULE_MASK & USE_I2C1_MODULE)
{
.base = (struct i2c_map *)I2C1_BASE_ADDR,
.cg = CG_I2C1,
.ints = I2C1,
.handler = I2C1_HANDLER,
},
#endif
#if (I2C_MODULE_MASK & USE_I2C2_MODULE)
{
.base = (struct i2c_map *)I2C2_BASE_ADDR,
.cg = CG_I2C2,
.ints = I2C2,
.handler = I2C2_HANDLER,
},
#endif
#if (I2C_MODULE_MASK & USE_I2C3_MODULE)
{
.base = (struct i2c_map *)I2C3_BASE_ADDR,
.cg = CG_I2C3,
.ints = I2C3,
.handler = I2C3_HANDLER,
},
#endif
};
static void i2c_interrupt(enum i2c_module_number i2c)
{
struct i2c_module_descriptor *const desc = &i2c_descs[i2c];
struct i2c_map * const base = desc->base;
uint16_t i2sr = base->i2sr;
base->i2sr = i2sr & ~I2C_I2SR_IIF; /* Clear IIF */
if (desc->addr_count >= 0)
{
/* ADDR cycle - either done or more to send */
if ((i2sr & I2C_I2SR_RXAK) != 0)
{
goto i2c_stop; /* problem */
}
if (--desc->addr_count < 0)
{
/* Switching to data cycle */
if (desc->addr & 0x1)
{
base->i2cr &= ~I2C_I2CR_MTX; /* Switch to RX mode */
base->i2dr; /* Dummy read */
return;
}
/* else remaining data is TX - handle below */
goto i2c_transmit;
}
else
{
base->i2dr = *desc->addr_data++; /* Send next addressing byte */
return;
}
}
if (base->i2cr & I2C_I2CR_MTX)
{
i2c_transmit:
/* Transmitting data */
if ((i2sr & I2C_I2SR_RXAK) == 0 && desc->data_count > 0)
{
/* More bytes to send, got ACK from previous byte */
base->i2dr = *desc->data++;
desc->data_count--;
return;
}
/* else done or no ACK received */
}
else
{
/* Receiving data */
if (--desc->data_count > 0)
{
if (desc->data_count == 1)
{
/* 2nd to Last byte - NACK */
base->i2cr |= I2C_I2CR_TXAK;
}
*desc->data++ = base->i2dr; /* Read data from I2DR and store */
return;
}
else
{
/* Generate STOP signal before reading data */
base->i2cr &= ~(I2C_I2CR_MSTA | I2C_I2CR_IIEN);
*desc->data++ = base->i2dr; /* Read data from I2DR and store */
goto i2c_done;
}
}
i2c_stop:
/* Generate STOP signal */
base->i2cr &= ~(I2C_I2CR_MSTA | I2C_I2CR_IIEN);
i2c_done:
/* Signal thread we're done */
wakeup_signal(&desc->w);
}
static int i2c_start(void)
#if (I2C_MODULE_MASK & USE_I2C1_MODULE)
static __attribute__((interrupt("IRQ"))) void I2C1_HANDLER(void)
{
return 0;
i2c_interrupt(I2C1_NUM);
}
static void i2c_stop(void)
#endif
#if (I2C_MODULE_MASK & USE_I2C2_MODULE)
static __attribute__((interrupt("IRQ"))) void I2C2_HANDLER(void)
{
i2c_interrupt(I2C2_NUM);
}
static int i2c_outb(unsigned char byte)
#endif
#if (I2C_MODULE_MASK & USE_I2C3_MODULE)
static __attribute__((interrupt("IRQ"))) void I2C3_HANDLER(void)
{
(void)byte;
return 0;
i2c_interrupt(I2C3_NUM);
}
#endif
void i2c_write(int addr, const unsigned char *buf, int count)
static int i2c_transfer(struct i2c_node * const node,
struct i2c_module_descriptor *const desc)
{
(void)addr;
(void)buf;
(void)count;
struct i2c_map * const base = desc->base;
int count = desc->data_count;
uint16_t i2cr;
/* Set speed */
base->ifdr = node->ifdr;
/* Enable module */
base->i2cr = I2C_I2CR_IEN;
/* Enable Interrupt, Master */
i2cr = I2C_I2CR_IEN | I2C_I2CR_IIEN | I2C_I2CR_MTX;
if ((desc->addr & 0x1) && desc->data_count < 2)
{
/* Receiving less than two bytes - disable ACK generation */
i2cr |= I2C_I2CR_TXAK;
}
/* Set config */
base->i2cr = i2cr;
/* Generate START */
base->i2cr |= I2C_I2CR_MSTA;
/* Address slave (first byte sent) and begin session. */
base->i2dr = desc->addr;
/* Wait for transfer to complete */
count = (wakeup_wait(&desc->w, HZ) != OBJ_WAIT_SUCCEEDED) ?
-1 : (count - desc->data_count);
/* Disable module - generate STOP if timeout */
base->i2cr = 0;
return count;
}
int i2c_read(struct i2c_node *node, int reg,
unsigned char *data, int data_count)
{
struct i2c_module_descriptor *const desc = &i2c_descs[node->num];
unsigned char ad[1];
mutex_lock(&desc->m);
desc->addr = (node->addr & 0xfe) | 0x1; /* Slave address/rd */
if (reg >= 0)
{
/* Sub-address */
desc->addr_count = 1;
desc->addr_data = ad;
ad[0] = reg;
}
/* else raw read from slave */
desc->data = data;
desc->data_count = data_count;
data_count = i2c_transfer(node, desc);
desc->addr_count = 0; /* To eliminate zeroing elsewhere */
mutex_unlock(&desc->m);
return data_count;
}
int i2c_write(struct i2c_node *node, const unsigned char *data, int data_count)
{
struct i2c_module_descriptor *const desc = &i2c_descs[node->num];
mutex_lock(&desc->m);
desc->addr = node->addr & 0xfe; /* Slave address/wr */
desc->data = (unsigned char *)data;
desc->data_count = data_count;
data_count = i2c_transfer(node, desc);
mutex_unlock(&desc->m);
return data_count;
}
void i2c_init(void)
{
int i;
/* Do one-time inits for each module that will be used - leave
* module disabled and unclocked until something wants it */
for (i = 0; i < I2C_NUM_I2C; i++)
{
struct i2c_module_descriptor *const desc = &i2c_descs[i];
imx31_clkctl_module_clock_gating(desc->cg, CGM_ON_ALL);
mutex_init(&desc->m);
wakeup_init(&desc->w);
desc->base->i2cr = 0;
imx31_clkctl_module_clock_gating(desc->cg, CGM_OFF);
}
#if 0
/* Pad config set up by OF bootloader doesn't agree with manual but
* TX works at the moment - probably would't do this here either */
uint32_t reg = SW_PAD_CTL_CSI_PIXCLK_I2C_CLK_I2C_DAT;
reg &= ~0xfffff;
reg |= (1 << 19) | (3 << 17) | (1 << 15) | (1 << 14) |
(1 << 13) | (0 << 11);
reg |= (1 << 9) | (3 << 7) | (1 << 5) | (1 << 4) |
(1 << 3) | (0 << 1);
SW_PAD_CTL_CSI_PIXCLK_I2C_CLK_I2C_DAT = reg;
#endif
}
void i2c_enable_node(struct i2c_node *node, bool enable)
{
struct i2c_module_descriptor *const desc = &i2c_descs[node->num];
mutex_lock(&desc->m);
if (enable)
{
if (++desc->enable == 1)
{
/* First enable */
imx31_clkctl_module_clock_gating(desc->cg, CGM_ON_ALL);
avic_enable_int(desc->ints, IRQ, 7, desc->handler);
}
}
else
{
if (desc->enable > 0 && --desc->enable == 0)
{
/* Last enable */
avic_disable_int(desc->ints);
imx31_clkctl_module_clock_gating(desc->cg, CGM_OFF);
}
}
mutex_unlock(&desc->m);
}
void i2c_lock_node(struct i2c_node *node)
{
struct i2c_module_descriptor *const desc = &i2c_descs[node->num];
mutex_lock(&desc->m);
}
void i2c_unlock_node(struct i2c_node *node)
{
struct i2c_module_descriptor *const desc = &i2c_descs[node->num];
mutex_unlock(&desc->m);
}

View file

@ -16,7 +16,61 @@
* KIND, either express or implied.
*
****************************************************************************/
#ifndef _I2C_IMX31_H_
#define _I2C_IMX31_H_
#include <stdbool.h>
/* I2C module usage masks */
#define USE_I2C1_MODULE (1 << 0)
#define USE_I2C2_MODULE (1 << 1)
#define USE_I2C3_MODULE (1 << 2)
enum i2c_module_number
{
__I2C_NUM_START = -1,
#if (I2C_MODULE_MASK & USE_I2C1_MODULE)
I2C1_NUM,
#endif
#if (I2C_MODULE_MASK & USE_I2C2_MODULE)
I2C2_NUM,
#endif
#if (I2C_MODULE_MASK & USE_I2C3_MODULE)
I2C3_NUM,
#endif
I2C_NUM_I2C,
};
/* Module interface map structure */
struct i2c_map
{
volatile uint16_t iadr; /* 0x00 */
volatile uint16_t unused1;
volatile uint16_t ifdr; /* 0x04 */
volatile uint16_t unused2;
volatile uint16_t i2cr; /* 0x08 */
volatile uint16_t unused3;
volatile uint16_t i2sr; /* 0x0C */
volatile uint16_t unused4;
volatile uint16_t i2dr; /* 0x10 */
};
struct i2c_node
{
enum i2c_module_number num; /* Module that this node uses */
unsigned int ifdr; /* Maximum frequency for node */
unsigned char addr; /* Slave address on module */
};
void i2c_init(void);
void i2c_write(int addr, const unsigned char *data, int count);
/* Enable or disable the node - modules will be switch on/off accordingly. */
void i2c_enable_node(struct i2c_node *node, bool enable);
/* If addr < 0, then raw read */
int i2c_read(struct i2c_node *node, int addr, unsigned char *data, int count);
int i2c_write(struct i2c_node *node, const unsigned char *data, int count);
/* Gain mutually-exclusive access to the node and module to perform multiple
* operations atomically */
void i2c_lock_node(struct i2c_node *node);
void i2c_unlock_node(struct i2c_node *node);
#endif /* _I2C_IMX31_H_ */

View file

@ -49,10 +49,12 @@ void pcm_apply_settings(void)
void pcm_play_dma_init(void)
{
audiohw_init();
}
void pcm_postinit(void)
{
audiohw_postinit();
}
#if 0

View file

@ -7,7 +7,7 @@
* \/ \/ \/ \/ \/
* $Id$
*
* Gigabeat specific code for the Wolfson codec
* Gigabeat S specific code for the WM8978 codec
*
* Based on code from the ipodlinux project - http://ipodlinux.org/
* Adapted for Rockbox in December 2005
@ -28,12 +28,31 @@
#include "sound.h"
#include "i2c-imx31.h"
/* NOTE: Some port-specific bits will have to be moved away (node and GPIO
* writes) for cleanest implementation. */
static struct i2c_node wm8978_i2c_node =
{
.num = I2C1_NUM,
.ifdr = I2C_IFDR_DIV192, /* 66MHz/.4MHz = 165, closest = 192 = 343750Hz */
/* Just hard-code for now - scaling may require
* updating */
.addr = WM8978_I2C_ADDR,
};
void audiohw_init(void)
{
i2c_enable_node(&wm8978_i2c_node, true);
GPIO3_DR |= (1 << 21); /* Turn on analogue LDO */
sleep(HZ/10); /* Wait for things to stabilize */
audiohw_preinit();
}
void wmcodec_write(int reg, int data)
{
(void)reg;
(void)data;
unsigned char d[2];
/* |aaaaaaad|dddddddd| */
d[0] = (reg << 1) | ((data & 0x100) >> 8);
d[1] = data;
i2c_write(&wm8978_i2c_node, d, 2);
}