WM8904: Add initialization logic
This commit is contained in:
parent
a0607ff2a7
commit
89ed7ab558
@ -320,10 +320,12 @@ menuconfig AUDIO_DEVICES
|
|||||||
bool "Audio Device Support"
|
bool "Audio Device Support"
|
||||||
default n
|
default n
|
||||||
---help---
|
---help---
|
||||||
Enable support for audio device drivers.
|
Enable support for audio device drivers. This includes drivers for
|
||||||
This includes drivers for MP3, WMA and Ogg Vorbis encoding,
|
MP3, WMA and Ogg Vorbis encoding, decoding, as well as drivers for
|
||||||
decoding, as well as drivers for interfacing with external
|
interfacing with external DSP chips to perform custom audio functions.
|
||||||
DSP chips to perform custom audio functions.
|
|
||||||
|
NOTE: All of these drivers depend on support from the audio subsystem
|
||||||
|
enabled with the AUDIO selection.
|
||||||
|
|
||||||
if AUDIO_DEVICES
|
if AUDIO_DEVICES
|
||||||
source drivers/audio/Kconfig
|
source drivers/audio/Kconfig
|
||||||
|
@ -6,7 +6,7 @@
|
|||||||
config AUDIO_I2SCHAR
|
config AUDIO_I2SCHAR
|
||||||
bool "I2S character driver (for testing only)"
|
bool "I2S character driver (for testing only)"
|
||||||
default n
|
default n
|
||||||
depends on I2S
|
depends on I2S && AUDIO
|
||||||
---help---
|
---help---
|
||||||
This selection enables a simple character driver that supports I2S
|
This selection enables a simple character driver that supports I2S
|
||||||
transfers via a read() and write(). The intent of this driver is to
|
transfers via a read() and write(). The intent of this driver is to
|
||||||
@ -38,6 +38,7 @@ endif #AUDIO_I2SCHAR
|
|||||||
config VS1053
|
config VS1053
|
||||||
bool "VS1053 codec chip"
|
bool "VS1053 codec chip"
|
||||||
default n
|
default n
|
||||||
|
depends on AUDIO
|
||||||
---help---
|
---help---
|
||||||
Select to enable support for the VS1053 Audio codec by VLSI Solutions.
|
Select to enable support for the VS1053 Audio codec by VLSI Solutions.
|
||||||
This chip provides encoding and decoding of MP3, WMA, AAC and Ogg
|
This chip provides encoding and decoding of MP3, WMA, AAC and Ogg
|
||||||
@ -86,11 +87,11 @@ endif # VS1053
|
|||||||
config AUDIO_WM8904
|
config AUDIO_WM8904
|
||||||
bool "WM8904 audio chip"
|
bool "WM8904 audio chip"
|
||||||
default n
|
default n
|
||||||
depends on EXPERIMENTAL
|
depends on AUDIO && EXPERIMENTAL
|
||||||
---help---
|
---help---
|
||||||
Select to enable support for the WM8904 Audio codec by Wolfson
|
Select to enable support for the WM8904 Audio codec by Wolfson
|
||||||
Microelectonics. This chip is a lower level audio chip.. basically
|
Microelectonics. This chip is a lower level audio chip.. basically
|
||||||
an exotic D-to-A. It includes no builtin support for audion CODECS
|
an exotic D-to-A. It includes no built-in support for audio CODECS
|
||||||
The WM8904 provides:
|
The WM8904 provides:
|
||||||
|
|
||||||
- Low power consumption
|
- Low power consumption
|
||||||
@ -101,6 +102,9 @@ config AUDIO_WM8904
|
|||||||
- Ground-referenced headphone driver
|
- Ground-referenced headphone driver
|
||||||
- Ground-referenced line outputs
|
- Ground-referenced line outputs
|
||||||
|
|
||||||
|
NOTE: This driver also depends on both I2C and I2S support although
|
||||||
|
that dependency is not explicit here.
|
||||||
|
|
||||||
if AUDIO_WM8904
|
if AUDIO_WM8904
|
||||||
endif # AUDIO_WM8904
|
endif # AUDIO_WM8904
|
||||||
|
|
||||||
|
@ -6,11 +6,11 @@
|
|||||||
* Copyright (C) 2014 Gregory Nutt. All rights reserved.
|
* Copyright (C) 2014 Gregory Nutt. All rights reserved.
|
||||||
* Author: Gregory Nutt <gnutt@nuttx.org>
|
* Author: Gregory Nutt <gnutt@nuttx.org>
|
||||||
*
|
*
|
||||||
* Reference:
|
* References:
|
||||||
* "WM8904 Ultra Low Power CODEC for Portable Audio Applications, Pre-
|
* - "WM8904 Ultra Low Power CODEC for Portable Audio Applications, Pre-
|
||||||
* Production", September 2012, Rev 3.3, Wolfson Microelectronics
|
* Production", September 2012, Rev 3.3, Wolfson Microelectronics
|
||||||
*
|
*
|
||||||
* The framework for this driver is based on Ken Pettit's VS1053 driver.
|
* - The framework for this driver is based on Ken Pettit's VS1053 driver.
|
||||||
*
|
*
|
||||||
* Redistribution and use in source and binary forms, with or without
|
* Redistribution and use in source and binary forms, with or without
|
||||||
* modification, are permitted provided that the following conditions
|
* modification, are permitted provided that the following conditions
|
||||||
@ -96,7 +96,7 @@
|
|||||||
# define CONFIG_WM8904_WORKER_STACKSIZE 768
|
# define CONFIG_WM8904_WORKER_STACKSIZE 768
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#define WM8904_DUMMY 0xFF
|
#define WM8904_DUMMY 0xff
|
||||||
#define WM8904_DEFAULT_XTALI 12288000
|
#define WM8904_DEFAULT_XTALI 12288000
|
||||||
#define WM8904_DATA_FREQ 20000000
|
#define WM8904_DATA_FREQ 20000000
|
||||||
#define WM8904_RST_USECS 2000
|
#define WM8904_RST_USECS 2000
|
||||||
@ -199,6 +199,13 @@ static int wm8904_cancelbuffer(FAR struct audio_lowerhalf_s *dev,
|
|||||||
static int wm8904_ioctl(FAR struct audio_lowerhalf_s *dev, int cmd,
|
static int wm8904_ioctl(FAR struct audio_lowerhalf_s *dev, int cmd,
|
||||||
unsigned long arg);
|
unsigned long arg);
|
||||||
|
|
||||||
|
/* Initialization */
|
||||||
|
|
||||||
|
static void wm8904_audio_output(FAR struct wm8904_dev_s *priv);
|
||||||
|
#if 0 /* Not used */
|
||||||
|
static void wm8904_audio_input(FAR struct wm8904_dev_s *priv);
|
||||||
|
#endif
|
||||||
|
|
||||||
/****************************************************************************
|
/****************************************************************************
|
||||||
* Private Data
|
* Private Data
|
||||||
****************************************************************************/
|
****************************************************************************/
|
||||||
@ -241,11 +248,71 @@ static const struct audio_ops_s g_audioops =
|
|||||||
|
|
||||||
static uint16_t wm8904_readreg(FAR struct wm8904_dev_s *priv, uint8_t regaddr)
|
static uint16_t wm8904_readreg(FAR struct wm8904_dev_s *priv, uint8_t regaddr)
|
||||||
{
|
{
|
||||||
FAR struct i2c_dev_s *i2c = priv->i2c;
|
int retries;
|
||||||
uint16_t regval;
|
|
||||||
#warning Missing logic
|
/* Try up to three times to read the register */
|
||||||
audvdbg("Read: %02x -> %04x\n", regaddr, regval);
|
|
||||||
return regval;
|
for (retries = 1; retries <= 3; retries++)
|
||||||
|
{
|
||||||
|
struct i2c_msg_s msg[2];
|
||||||
|
uint8_t data[2];
|
||||||
|
int ret;
|
||||||
|
|
||||||
|
/* Set up to write the address */
|
||||||
|
|
||||||
|
msg[0].addr = priv->lower->address;
|
||||||
|
msg[0].flags = 0;
|
||||||
|
msg[0].buffer = ®addr;
|
||||||
|
msg[0].length = 1;
|
||||||
|
|
||||||
|
/* Followed by the read data */
|
||||||
|
|
||||||
|
msg[1].addr = priv->lower->address;
|
||||||
|
msg[1].flags = I2C_M_READ;
|
||||||
|
msg[1].buffer = data;
|
||||||
|
msg[1].length = 2;
|
||||||
|
|
||||||
|
/* Read the register data. The returned value is the number messages
|
||||||
|
* completed.
|
||||||
|
*/
|
||||||
|
|
||||||
|
ret = I2C_TRANSFER(priv->i2c, msg, 2);
|
||||||
|
if (ret < 0)
|
||||||
|
{
|
||||||
|
#ifdef CONFIG_I2C_RESET
|
||||||
|
/* Perhaps the I2C bus is locked up? Try to shake the bus free */
|
||||||
|
|
||||||
|
idbg("WARNING: I2C_TRANSFER failed: %d ... Resetting\n", ret);
|
||||||
|
|
||||||
|
ret = up_i2creset(priv->i2c);
|
||||||
|
if (ret < 0)
|
||||||
|
{
|
||||||
|
idbg("ERROR: up_i2creset failed: %d\n", ret);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
#else
|
||||||
|
idbg("ERROR: I2C_TRANSFER failed: %d\n", ret);
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
uint16_t regval;
|
||||||
|
|
||||||
|
/* The I2C transfer was successful... break out of the loop and
|
||||||
|
* return the value read.
|
||||||
|
*/
|
||||||
|
|
||||||
|
regval = ((uint16_t)data[0] << 8) | (uint16_t)data[1]
|
||||||
|
audvdbg("READ: %02x -> %04x\n", regaddr, regval);
|
||||||
|
return regval;
|
||||||
|
}
|
||||||
|
|
||||||
|
ivdbg("retries=%d regaddr=%04x\n", retries, regaddr);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* No error indication is returned on a failure... just return zero */
|
||||||
|
|
||||||
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
/************************************************************************************
|
/************************************************************************************
|
||||||
@ -256,18 +323,70 @@ static uint16_t wm8904_readreg(FAR struct wm8904_dev_s *priv, uint8_t regaddr)
|
|||||||
*
|
*
|
||||||
************************************************************************************/
|
************************************************************************************/
|
||||||
|
|
||||||
static void wm8904_writereg(FAR struct wm8904_dev_s *priv, uint8_t regaddr, uint16_t regval)
|
static void wm8904_writereg(FAR struct wm8904_dev_s *priv, uint8_t regaddr,
|
||||||
|
uint16_t regval)
|
||||||
{
|
{
|
||||||
FAR struct i2c_dev_s *i2c = priv->i2c;
|
int retries;
|
||||||
|
|
||||||
/* Select the AUDIO_CTRL device on the I2C bus */
|
/* Try up to three times to read the register */
|
||||||
|
|
||||||
audvdbg("Write: %02x <- %04x\n", regaddr, regval);
|
for (retries = 1; retries <= 3; retries++)
|
||||||
#warning "Missing logic"
|
{
|
||||||
|
struct i2c_msg_s msg[2];
|
||||||
|
uint8_t data[2];
|
||||||
|
int ret;
|
||||||
|
|
||||||
/* Short delay after a write for WM8904 processing time */
|
/* Set up to write the address */
|
||||||
/* REVISIT: Necessary for the WM8904? */
|
|
||||||
usleep(10);
|
msg[0].addr = priv->lower->address;
|
||||||
|
msg[0].flags = 0;
|
||||||
|
msg[0].buffer = ®addr;
|
||||||
|
msg[0].length = 1;
|
||||||
|
|
||||||
|
/* Followed by the read data */
|
||||||
|
|
||||||
|
data[0] = regval >> 8;
|
||||||
|
data[1] = regval & 0xff;
|
||||||
|
|
||||||
|
msg[1].addr = priv->lower->address;
|
||||||
|
msg[1].flags = I2C_M_NORESTART;
|
||||||
|
msg[1].buffer = data;
|
||||||
|
msg[1].length = 2;
|
||||||
|
|
||||||
|
/* Read the register data. The returned value is the number messages
|
||||||
|
* completed.
|
||||||
|
*/
|
||||||
|
|
||||||
|
ret = I2C_TRANSFER(priv->i2c, msg, 2);
|
||||||
|
if (ret < 0)
|
||||||
|
{
|
||||||
|
#ifdef CONFIG_I2C_RESET
|
||||||
|
/* Perhaps the I2C bus is locked up? Try to shake the bus free */
|
||||||
|
|
||||||
|
idbg("WARNING: I2C_TRANSFER failed: %d ... Resetting\n", ret);
|
||||||
|
|
||||||
|
ret = up_i2creset(priv->i2c);
|
||||||
|
if (ret < 0)
|
||||||
|
{
|
||||||
|
idbg("ERROR: up_i2creset failed: %d\n", ret);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
#else
|
||||||
|
idbg("ERROR: I2C_TRANSFER failed: %d\n", ret);
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
/* The I2C transfer was successful... break out of the loop and
|
||||||
|
* return the value read.
|
||||||
|
*/
|
||||||
|
|
||||||
|
audvdbg("Write: %02x <- %04x\n", regaddr, regval);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
ivdbg("retries=%d regaddr=%04x\n", retries, regaddr);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/************************************************************************************
|
/************************************************************************************
|
||||||
@ -1457,6 +1576,190 @@ static int wm8904_release(FAR struct audio_lowerhalf_s *dev)
|
|||||||
return OK;
|
return OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/****************************************************************************
|
||||||
|
* Name: wm8904_audio_output
|
||||||
|
*
|
||||||
|
* Description:
|
||||||
|
* Initialize and configure the WM8904 device as an audio output device.
|
||||||
|
*
|
||||||
|
* Input Parameters:
|
||||||
|
* prive - A reference to the driver state structure
|
||||||
|
*
|
||||||
|
* Returned Value:
|
||||||
|
* None. No failures are detected.
|
||||||
|
*
|
||||||
|
****************************************************************************/
|
||||||
|
|
||||||
|
static void wm8904_audio_output(FAR struct wm8904_dev_s *priv)
|
||||||
|
{
|
||||||
|
uint16_t regval;
|
||||||
|
|
||||||
|
/* Bias Control.
|
||||||
|
* Preserve undocumented default bit.WM8904_DUMMY
|
||||||
|
*/
|
||||||
|
|
||||||
|
regval = WM8904_ISEL_HIGH | WM8904_BIAS_ENA | 0x0010;
|
||||||
|
wm8904_writereg(priv, WM8904_BIAS_CTRL, regval);
|
||||||
|
|
||||||
|
/* VMID Control */
|
||||||
|
|
||||||
|
regval = WM8904_VMID_BUF_ENA | WM8904_VMID_RES_NORMAL | WM8904_VMID_ENA;
|
||||||
|
wm8904_writereg(priv, WM8904_VMID_CTRL, regval);
|
||||||
|
|
||||||
|
/* Mic Bias Control 0 */
|
||||||
|
/* MICDET_ENA=1, MICBIAS_ENA=1 */
|
||||||
|
|
||||||
|
regval = WM8904_MICDET_ENA | WM8904_MICBIAS_ENA;
|
||||||
|
wm8904_writereg(priv, WM8904_MIC_BIAS_CTRL0, regval);
|
||||||
|
|
||||||
|
/* Mic Bias Control 1. */
|
||||||
|
|
||||||
|
wm8904_writereg(priv, WM8904_MIC_BIAS_CTRL1, 0xc000);
|
||||||
|
|
||||||
|
/* Power Management 0 */
|
||||||
|
|
||||||
|
regval = WM8904_INL_ENA | WM8904_INR_ENA;
|
||||||
|
wm8904_writereg(priv, WM8904_PM0, regval);
|
||||||
|
|
||||||
|
/* Power Management 2 */
|
||||||
|
|
||||||
|
regval = WM8904_HPL_PGA_ENA | WM8904_HPR_PGA_ENA;
|
||||||
|
wm8904_writereg(priv, WM8904_PM2, regval);
|
||||||
|
|
||||||
|
/* Power Management 6 */
|
||||||
|
/* DACL_ENA=1, DACR_ENA=1, ADCL_ENA=1, ADCR_ENA=1 */
|
||||||
|
|
||||||
|
regval = WM8904_DACL_ENA | WM8904_DACR_ENA | WM8904_ADCL_ENA | WM8904_ADCR_ENA;
|
||||||
|
wm8904_writereg(priv, WM8904_PM6, regval);
|
||||||
|
|
||||||
|
/* Clock Rates 0.
|
||||||
|
*
|
||||||
|
* This value sets TOCLK_RATE_DIV16=0, TOCLK_RATE_X4=0, and MCLK_DIV=0 while
|
||||||
|
* preserving the state of some undocumented bits (see wm8904.h).
|
||||||
|
*/
|
||||||
|
|
||||||
|
wm8904_writereg(priv, WM8904_CLKRATE0, 0x845e);
|
||||||
|
|
||||||
|
/* Clock Rates 2 */
|
||||||
|
|
||||||
|
regval = WM8904_SYSCLK_SRC | WM8904_CLK_SYS_ENA | WM8904_CLK_DSP_ENA;
|
||||||
|
wm8904_writereg(priv, WM8904_CLKRATE2, regval);
|
||||||
|
|
||||||
|
/* Audio Interface 1.
|
||||||
|
*
|
||||||
|
* This value sets AIFADC_TDM=0, AIFADC_TDM_CHAN=0, BCLK_DIR=1 while preserving
|
||||||
|
* the state of some undocumented bits (see wm8904.h).
|
||||||
|
*/
|
||||||
|
|
||||||
|
wm8904_writereg(priv, WM8904_AIF1, 0x404A);
|
||||||
|
|
||||||
|
/* Audio Interface 3 */
|
||||||
|
|
||||||
|
regval = WM8904_LRCLK_DIR | WM8904_LRCLK_RATE(64);
|
||||||
|
wm8904_writereg(priv, WM8904_AIF3, regval);
|
||||||
|
|
||||||
|
/* DAC Digital 1 */
|
||||||
|
|
||||||
|
wm8904_writereg(priv, WM8904_DAC_DIGI1, 0);
|
||||||
|
|
||||||
|
/* Analogue Left Input 0 */
|
||||||
|
/* Analogue Right Input 0 */
|
||||||
|
|
||||||
|
regval = WM8904_IN_VOL(5);
|
||||||
|
wm8904_writereg(priv, WM8904_ANA_LEFT_IN0, regval);
|
||||||
|
wm8904_writereg(priv, WM8904_ANA_RIGHT_IN0, regval);
|
||||||
|
|
||||||
|
/* Analogue Left Input 1 */
|
||||||
|
|
||||||
|
wm8904_writereg(priv, WM8904_ANA_LEFT_IN1, 0);
|
||||||
|
wm8904_writereg(priv, WM8904_ANA_RIGHT_IN1, 0);
|
||||||
|
|
||||||
|
/* Analogue OUT1 Right */
|
||||||
|
|
||||||
|
regval = WM8904_HPOUT_MUTE | WM8904_HPOUTZC | WM8904_HPOUT_VOL(29);
|
||||||
|
wm8904_writereg(priv, WM8904_ANA_RIGHT_OUT1, regval);
|
||||||
|
|
||||||
|
/* DC Servo 0 */
|
||||||
|
/* DCS_ENA_CHAN_1=1, DCS_ENA_CHAN_0=1 */
|
||||||
|
|
||||||
|
regval = WM8904_DCS_ENA_CHAN_1 | WM8904_DCS_ENA_CHAN_0;
|
||||||
|
wm8904_writereg(priv, WM8904_DC_SERVO0, regval);
|
||||||
|
|
||||||
|
/* Analogue HP 0 */
|
||||||
|
|
||||||
|
regval = WM8904_HPL_RMV_SHORT | WM8904_HPL_ENA_OUTP | WM8904_HPL_ENA_DLY | WM8904_HPL_ENA |
|
||||||
|
WM8904_HPR_RMV_SHORT | WM8904_HPR_ENA_OUTP | WM8904_HPR_ENA_DLY | WM8904_HPR_ENA;
|
||||||
|
wm8904_writereg(priv, WM8904_ANA_HP0, regval);
|
||||||
|
|
||||||
|
/* Charge Pump 0 */
|
||||||
|
|
||||||
|
wm8904_writereg(priv, WM8904_CHG_PUMP0, WM8904_CP_ENA);
|
||||||
|
|
||||||
|
/* Class W 0 */
|
||||||
|
|
||||||
|
regval = WM8904_CP_DYN_PWR | 0x0004;
|
||||||
|
wm8904_writereg(priv, WM8904_CLASS_W0, regval);
|
||||||
|
|
||||||
|
/* FLL Control 1 */
|
||||||
|
|
||||||
|
wm8904_writereg(priv, WM8904_FLL_CTRL1, 0);
|
||||||
|
|
||||||
|
regval = WM8904_FLL_FRACN_ENA | WM8904_FLL_ENA;
|
||||||
|
wm8904_writereg(priv, WM8904_FLL_CTRL1, regval);
|
||||||
|
|
||||||
|
/* FLL Control 2 */
|
||||||
|
|
||||||
|
regval = WM8904_FLL_OUTDIV(8) | WM8904_FLL_FRATIO_DIV16;
|
||||||
|
wm8904_writereg(priv, WM8904_FLL_CTRL2, regval);
|
||||||
|
|
||||||
|
/* FLL Control 3 */
|
||||||
|
|
||||||
|
wm8904_writereg(priv, WM8904_FLL_CTRL3, 16384);
|
||||||
|
|
||||||
|
/* FLL Control 4 */
|
||||||
|
|
||||||
|
regval = WM8904_FLL_N(187) | WM8904_FLL_GAIN_X1;
|
||||||
|
wm8904_writereg(priv, WM8904_FLL_CTRL4, regval);
|
||||||
|
|
||||||
|
wm8904_writereg(priv, WM8904_DUMMY, 0x55AA);
|
||||||
|
}
|
||||||
|
|
||||||
|
/****************************************************************************
|
||||||
|
* Name: wm8904_audio_input
|
||||||
|
*
|
||||||
|
* Description:
|
||||||
|
* Initialize and configure the WM8904 device as an audio output device
|
||||||
|
* (Right input only).
|
||||||
|
*
|
||||||
|
* Input Parameters:
|
||||||
|
* prive - A reference to the driver state structure
|
||||||
|
*
|
||||||
|
* Returned Value:
|
||||||
|
* None. No failures are detected.
|
||||||
|
*
|
||||||
|
****************************************************************************/
|
||||||
|
|
||||||
|
#if 0 /* Not used */
|
||||||
|
static void wm8904_audio_input(FAR struct wm8904_dev_s *priv)
|
||||||
|
{
|
||||||
|
/* Analogue Left Input 0 */
|
||||||
|
|
||||||
|
wm8904_writereg(priv, WM8904_ANA_LEFT_IN0, WM8904_INMUTE);
|
||||||
|
|
||||||
|
/* Analogue Right Input 0 */
|
||||||
|
|
||||||
|
wm8904_writereg(priv, WM8904_ANA_RIGHT_IN0, WM8904_IN_VOL(5));
|
||||||
|
|
||||||
|
/* Analogue Left Input 1 */
|
||||||
|
|
||||||
|
wm8904_writereg(priv, WM8904_ANA_LEFT_IN1, 0);
|
||||||
|
|
||||||
|
/* Analogue Right Input 1 */
|
||||||
|
|
||||||
|
wm8904_writereg(priv, WM8904_ANA_RIGHT_IN1, WM8904_IP_SEL_N_IN2L);
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
/****************************************************************************
|
/****************************************************************************
|
||||||
* Public Functions
|
* Public Functions
|
||||||
****************************************************************************/
|
****************************************************************************/
|
||||||
@ -1485,6 +1788,7 @@ FAR struct audio_lowerhalf_s *
|
|||||||
FAR const struct wm8904_lower_s *lower, unsigned int devno)
|
FAR const struct wm8904_lower_s *lower, unsigned int devno)
|
||||||
{
|
{
|
||||||
FAR struct wm8904_dev_s *priv;
|
FAR struct wm8904_dev_s *priv;
|
||||||
|
uint16_t regval;
|
||||||
|
|
||||||
/* Sanity check */
|
/* Sanity check */
|
||||||
|
|
||||||
@ -1527,17 +1831,28 @@ FAR struct audio_lowerhalf_s *
|
|||||||
I2C_SETFREQUENCY(i2c, lower->frequency);
|
I2C_SETFREQUENCY(i2c, lower->frequency);
|
||||||
I2C_SETADDRESS(i2c, lower->address, 7);
|
I2C_SETADDRESS(i2c, lower->address, 7);
|
||||||
|
|
||||||
/* Verify the device ID read from the chip */
|
/* Software reset */
|
||||||
#warning Missing logic
|
|
||||||
|
|
||||||
/* Initialize the WM8904 hardware */
|
wm8904_writereg(priv, WM8904_SWRST, 0);
|
||||||
#warning Missing logic
|
|
||||||
|
/* Verify that WM8904 is present and available on this I2C */
|
||||||
|
|
||||||
|
regval = wm8904_readreg(priv, WM8904_ID);
|
||||||
|
if (regval != WM8904_SW_RST_DEV_ID1)
|
||||||
|
{
|
||||||
|
auddbg("ERROR: WM8904 not found: ID=%04x\n", regval);
|
||||||
|
return -ENODEV;
|
||||||
|
}
|
||||||
|
WM8904_DUMMY
|
||||||
|
/* Configure the WM8904 hardware as an audio input device */
|
||||||
|
|
||||||
|
wm8904_audio_output(priv);
|
||||||
|
|
||||||
/* Attach our ISR to this device */
|
/* Attach our ISR to this device */
|
||||||
|
|
||||||
WM8904_ATTACH(lower, wm8904_interrupt, priv);
|
WM8904_ATTACH(lower, wm8904_interrupt, priv);
|
||||||
|
|
||||||
/* Put the drive in the 'shutdown' status */
|
/* Put the driver in the 'shutdown' state */
|
||||||
|
|
||||||
wm8904_shutdown(&priv->dev);
|
wm8904_shutdown(&priv->dev);
|
||||||
}
|
}
|
||||||
|
@ -57,7 +57,8 @@
|
|||||||
|
|
||||||
/* Registers Addresses ******************************************************/
|
/* Registers Addresses ******************************************************/
|
||||||
|
|
||||||
#define WM8904_SWRST_ID 0x00 /* SW Reset and ID */
|
#define WM8904_SWRST 0x00 /* SW Reset and ID */
|
||||||
|
#define WM8904_ID 0x00 /* SW Reset and ID */
|
||||||
#define WM8904_BIAS_CTRL 0x04 /* Bias Control */
|
#define WM8904_BIAS_CTRL 0x04 /* Bias Control */
|
||||||
#define WM8904_VMID_CTRL 0x05 /* VMID Control */
|
#define WM8904_VMID_CTRL 0x05 /* VMID Control */
|
||||||
#define WM8904_MIC_BIAS_CTRL0 0x06 /* Mic Bias Control 0 */
|
#define WM8904_MIC_BIAS_CTRL0 0x06 /* Mic Bias Control 0 */
|
||||||
@ -77,7 +78,7 @@
|
|||||||
#define WM8904_DAC_VOL_LEFT 0x1e /* DAC Digital Volume Left */
|
#define WM8904_DAC_VOL_LEFT 0x1e /* DAC Digital Volume Left */
|
||||||
#define WM8904_DAC_VOL_RIGHT 0x1f /* DAC Digital Volume Right */
|
#define WM8904_DAC_VOL_RIGHT 0x1f /* DAC Digital Volume Right */
|
||||||
#define WM8904_DAC_DIGI0 0x20 /* DAC Digital 0 */
|
#define WM8904_DAC_DIGI0 0x20 /* DAC Digital 0 */
|
||||||
#define WM8904_DATA_DIGI1 0x21 /* DAC Digital 1 */
|
#define WM8904_DAC_DIGI1 0x21 /* DAC Digital 1 */
|
||||||
#define WM8904_ADC_VOL_LEFT 0x24 /* ADC Digital Volume Left */
|
#define WM8904_ADC_VOL_LEFT 0x24 /* ADC Digital Volume Left */
|
||||||
#define WM8904_ADC_VOL_RIGHT 0x25 /* ADC Digital Volume Right */
|
#define WM8904_ADC_VOL_RIGHT 0x25 /* ADC Digital Volume Right */
|
||||||
#define WM8904_ADC_DIGI 0x26 /* ADC Digital */
|
#define WM8904_ADC_DIGI 0x26 /* ADC Digital */
|
||||||
@ -156,6 +157,109 @@
|
|||||||
#define WM8904_FLL_NCO_TEST0 0xf7 /* FLL NCO Test 0 */
|
#define WM8904_FLL_NCO_TEST0 0xf7 /* FLL NCO Test 0 */
|
||||||
#define WM8904_FLL_NCO_TEST1 0xf8 /* FLL NCO Test 1 */
|
#define WM8904_FLL_NCO_TEST1 0xf8 /* FLL NCO Test 1 */
|
||||||
|
|
||||||
|
/* Register Default Values **************************************************/
|
||||||
|
/* Registers have some undocumented bits set on power up. These probably
|
||||||
|
* should be retained on writes (?).
|
||||||
|
*/
|
||||||
|
|
||||||
|
#define WM8904_SWRST_DEFAULT 0x8904
|
||||||
|
#define WM8904_ID_DEFAULT 0x0018
|
||||||
|
#define WM8904_BIAS_CTRL_DEFAULT 0x0000
|
||||||
|
#define WM8904_VMID_CTRL_DEFAULT 0x0000
|
||||||
|
#define WM8904_MIC_BIAS_CTRL0_DEFAULT 0x0000
|
||||||
|
#define WM8904_MIC_BIAS_CTRL1_DEFAULT 0x0000
|
||||||
|
#define WM8904_ANALOG_ADC_DEFAULT 0x0001
|
||||||
|
#define WM8904_PM0_DEFAULT 0x0000
|
||||||
|
#define WM8904_PM2_DEFAULT 0x0000
|
||||||
|
#define WM8904_PM3_DEFAULT 0x0000
|
||||||
|
#define WM8904_PM6_DEFAULT 0x0000
|
||||||
|
#define WM8904_CLKRATE0_DEFAULT 0x8c5e
|
||||||
|
#define WM8904_CLKRATE1_DEFAULT 0x0c05
|
||||||
|
#define WM8904_CLKRATE2_DEFAULT 0x0000
|
||||||
|
#define WM8904_AIF0_DEFAULT 0x0050
|
||||||
|
#define WM8904_AIF1_DEFAULT 0x000a
|
||||||
|
#define WM8904_AIF2_DEFAULT 0x00e4
|
||||||
|
#define WM8904_AIF3_DEFAULT 0x0040
|
||||||
|
#define WM8904_DAC_VOL_LEFT_DEFAULT 0x00c0
|
||||||
|
#define WM8904_DAC_VOL_RIGHT_DEFAULT 0x00c0
|
||||||
|
#define WM8904_DAC_DIGI0_DEFAULT 0x0000
|
||||||
|
#define WM8904_DAC_DIGI1_DEFAULT 0x0004
|
||||||
|
#define WM8904_ADC_VOL_LEFT_DEFAULT 0x00c0
|
||||||
|
#define WM8904_ADC_VOL_RIGHT_DEFAULT 0x00c0
|
||||||
|
#define WM8904_ADC_DIGI_DEFAULT 0x0010
|
||||||
|
#define WM8904_MIC_DIGI_DEFAULT 0x0000
|
||||||
|
#define WM8904_DRC0_DEFAULT 0x01af
|
||||||
|
#define WM8904_DRC1_DEFAULT 0x3248
|
||||||
|
#define WM8904_DRC2_DEFAULT 0x0000
|
||||||
|
#define WM8904_DRC3_DEFAULT 0x0000
|
||||||
|
#define WM8904_ANA_LEFT_IN0_DEFAULT 0x0085
|
||||||
|
#define WM8904_ANA_RIGHT_IN0_DEFAULT 0x0085
|
||||||
|
#define WM8904_ANA_LEFT_IN1_DEFAULT 0x0044
|
||||||
|
#define WM8904_ANA_RIGHT_IN1_DEFAULT 0x0044
|
||||||
|
#define WM8904_ANA_LEFT_OUT1_DEFAULT 0x002d
|
||||||
|
#define WM8904_ANA_RIGHT_OUT1_DEFAULT 0x002d
|
||||||
|
#define WM8904_ANA_LEFT_OUT2_DEFAULT 0x0039
|
||||||
|
#define WM8904_ANA_RIGHT_OUT2_DEFAULT 0x0039
|
||||||
|
#define WM8904_ANA_OUT12_ZC_DEFAULT 0x0000
|
||||||
|
#define WM8904_DC_SERVO0_DEFAULT 0x0000
|
||||||
|
#define WM8904_DC_SERVO2_DEFAULT 0xaaaa
|
||||||
|
#define WM8904_DC_SERVO4_DEFAULT 0xaaaa
|
||||||
|
#define WM8904_DC_SERVO5_DEFAULT 0xaaaa
|
||||||
|
#define WM8904_DC_SERVO6_DEFAULT 0x0000
|
||||||
|
#define WM8904_DC_SERVO7_DEFAULT 0x0000
|
||||||
|
#define WM8904_DC_SERVO8_DEFAULT 0x0000
|
||||||
|
#define WM8904_DC_SERVO9_DEFAULT 0x0000
|
||||||
|
#define WM8904_DC_SERVO_RDBACK_DEFAULT 0x0000
|
||||||
|
#define WM8904_ANA_HP0_DEFAULT 0x0000
|
||||||
|
#define WM8904_ANA_LINEOUT0_DEFAULT 0x0000
|
||||||
|
#define WM8904_CHG_PUMP0_DEFAULT 0x0000
|
||||||
|
#define WM8904_CLASS_W0_DEFAULT 0x0000
|
||||||
|
#define WM8904_WR_SEQ0_DEFAULT 0x0000
|
||||||
|
#define WM8904_WR_SEQ1_DEFAULT 0x0000
|
||||||
|
#define WM8904_WR_SEQ2_DEFAULT 0x0000
|
||||||
|
#define WM8904_WR_SEQ3_DEFAULT 0x0000
|
||||||
|
#define WM8904_WR_SEQ4_DEFAULT 0x0000
|
||||||
|
#define WM8904_FLL_CTRL1_DEFAULT 0x0000
|
||||||
|
#define WM8904_FLL_CTRL2_DEFAULT 0x0007
|
||||||
|
#define WM8904_FLL_CTRL3_DEFAULT 0x0000
|
||||||
|
#define WM8904_FLL_CTRL4_DEFAULT 0x2ee0
|
||||||
|
#define WM8904_FLL_CTRL5_DEFAULT 0x0004
|
||||||
|
#define WM8904_GPIO_CTRL1_DEFAULT 0x0014
|
||||||
|
#define WM8904_GPIO_CTRL2_DEFAULT 0x0010
|
||||||
|
#define WM8904_GPIO_CTRL3_DEFAULT 0x0010
|
||||||
|
#define WM8904_GPIO_CTRL4_DEFAULT 0x0000
|
||||||
|
#define WM8904_DIGI_PULLS_DEFAULT 0x0000
|
||||||
|
#define WM8904_INT_MASK_DEFAULT 0xffff
|
||||||
|
#define WM8904_INT_POL_DEFAULT 0x0000
|
||||||
|
#define WM8904_INT_DEBOUNCE_DEFAULT 0x0000
|
||||||
|
#define WM8904_EQ1_DEFAULT 0x0000
|
||||||
|
#define WM8904_EQ2_DEFAULT 0x000c
|
||||||
|
#define WM8904_EQ3_DEFAULT 0x000c
|
||||||
|
#define WM8904_EQ4_DEFAULT 0x000c
|
||||||
|
#define WM8904_EQ5_DEFAULT 0x000c
|
||||||
|
#define WM8904_EQ6_DEFAULT 0x000c
|
||||||
|
#define WM8904_EQ7_DEFAULT 0x0fca
|
||||||
|
#define WM8904_EQ8_DEFAULT 0x0400
|
||||||
|
#define WM8904_EQ9_DEFAULT 0x00d8
|
||||||
|
#define WM8904_EQ10_DEFAULT 0x1eb5
|
||||||
|
#define WM8904_EQ11_DEFAULT 0xf145
|
||||||
|
#define WM8904_EQ12_DEFAULT 0x0b75
|
||||||
|
#define WM8904_EQ13_DEFAULT 0x01c5
|
||||||
|
#define WM8904_EQ14_DEFAULT 0x1c54
|
||||||
|
#define WM8904_EQ15_DEFAULT 0xf373
|
||||||
|
#define WM8904_EQ16_DEFAULT 0x0a54
|
||||||
|
#define WM8904_EQ17_DEFAULT 0x0558
|
||||||
|
#define WM8904_EQ18_DEFAULT 0x168e
|
||||||
|
#define WM8904_EQ19_DEFAULT 0xf829
|
||||||
|
#define WM8904_EQ20_DEFAULT 0x07ad
|
||||||
|
#define WM8904_EQ21_DEFAULT 0x1103
|
||||||
|
#define WM8904_EQ22_DEFAULT 0x0564
|
||||||
|
#define WM8904_EQ23_DEFAULT 0x0559
|
||||||
|
#define WM8904_EQ24_DEFAULT 0x4000
|
||||||
|
#define WM8904_ADC_TEST_DEFAULT 0x0000
|
||||||
|
#define WM8904_FLL_NCO_TEST0_DEFAULT 0x0000
|
||||||
|
#define WM8904_FLL_NCO_TEST1_DEFAULT 0x0019
|
||||||
|
|
||||||
/* Register Bit Definitions *************************************************/
|
/* Register Bit Definitions *************************************************/
|
||||||
|
|
||||||
/* 0x00 SW Reset and ID */
|
/* 0x00 SW Reset and ID */
|
||||||
|
@ -83,6 +83,16 @@
|
|||||||
|
|
||||||
/* Default configuration values */
|
/* Default configuration values */
|
||||||
|
|
||||||
|
#ifndef CONFIG_WM8904_I2CFREQUENCY
|
||||||
|
# define CONFIG_WM8904_I2CFREQUENCY 400000
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#if CONFIG_WM8904_I2CFREQUENCY > 400000
|
||||||
|
# warning WM8904 I2C frequency cannot exceed 400KHz
|
||||||
|
# undef CONFIG_WM8904_I2CFREQUENCY
|
||||||
|
# define CONFIG_WM8904_I2CFREQUENCY 400000
|
||||||
|
#endif
|
||||||
|
|
||||||
/* Helper macros ************************************************************/
|
/* Helper macros ************************************************************/
|
||||||
|
|
||||||
#define WM8904_ATTACH(s,isr,arg) ((s)->attach(s,isr,arg))
|
#define WM8904_ATTACH(s,isr,arg) ((s)->attach(s,isr,arg))
|
||||||
|
Loading…
Reference in New Issue
Block a user