WM8904: Add logic to analyze BCLK setup
This commit is contained in:
parent
b9384ced60
commit
72b739fbcb
@ -137,6 +137,12 @@ config WM8904_REGDUMP
|
||||
---help---
|
||||
Enable logic to dump the contents of all WM8904 registers.
|
||||
|
||||
config WM8904_CLKDEBUG
|
||||
bool "WM8904 clock analysis"
|
||||
default n
|
||||
---help---
|
||||
Enable logic to analyze WM8904 clock configuation.
|
||||
|
||||
endif # AUDIO_WM8904
|
||||
|
||||
config AUDIO_NULL
|
||||
|
@ -47,6 +47,10 @@ ifeq ($(CONFIG_AUDIO_WM8904),y)
|
||||
CSRCS += wm8904.c
|
||||
ifeq ($(CONFIG_WM8904_REGDUMP),y)
|
||||
CSRCS += wm8904_debug.c
|
||||
else
|
||||
ifeq ($(CONFIG_WM8904_CLKDEBUG),y)
|
||||
CSRCS += wm8904_debug.c
|
||||
endif
|
||||
endif
|
||||
endif
|
||||
|
||||
|
@ -75,99 +75,15 @@
|
||||
* Pre-processor Definitions
|
||||
****************************************************************************/
|
||||
|
||||
/* Dummy register address */
|
||||
|
||||
#define WM8904_DUMMY 0xff
|
||||
|
||||
/* Default FLL configuration */
|
||||
|
||||
#define WM8904_DEFAULT_SAMPRATE 11025
|
||||
#define WM8904_DEFAULT_NCHANNELS 1
|
||||
#define WM8904_DEFAULT_BPSAMP 16
|
||||
|
||||
#define WM8904_STARTBITS 2
|
||||
|
||||
#define WM8904_NFLLRATIO_DIV1 0
|
||||
#define WM8904_NFLLRATIO_DIV2 1
|
||||
#define WM8904_NFLLRATIO_DIV4 2
|
||||
#define WM8904_NFLLRATIO_DIV8 3
|
||||
#define WM8904_NFLLRATIO_DIV16 4
|
||||
#define WM8904_NFLLRATIO 5
|
||||
|
||||
#define WM8904_MINOUTDIV 4
|
||||
#define WM8904_MAXOUTDIV 64
|
||||
|
||||
#define WM8904_BCLK_MAXDIV 20
|
||||
|
||||
#define WM8904_FVCO_MIN 90000000
|
||||
#define WM8904_FVCO_MAX 100000000
|
||||
|
||||
/* Commonly defined and redefined macros */
|
||||
|
||||
#ifndef MIN
|
||||
# define MIN(a,b) (((a) < (b)) ? (a) : (b))
|
||||
#endif
|
||||
|
||||
#ifndef MAX
|
||||
# define MAX(a,b) (((a) > (b)) ? (a) : (b))
|
||||
#endif
|
||||
|
||||
/****************************************************************************
|
||||
* Private Types
|
||||
****************************************************************************/
|
||||
|
||||
struct wm8904_dev_s
|
||||
{
|
||||
/* We are an audio lower half driver (We are also the upper "half" of
|
||||
* the WM8904 driver with respect to the board lower half driver).
|
||||
*
|
||||
* Terminology: Our "lower" half audio instances will be called dev for the
|
||||
* publicly visible version and "priv" for the version that only this driver
|
||||
* knows. From the point of view of this driver, it is the board lower
|
||||
* "half" that is referred to as "lower".
|
||||
*/
|
||||
|
||||
struct audio_lowerhalf_s dev; /* WM8904 audio lower half (this device) */
|
||||
|
||||
/* Our specific driver data goes here */
|
||||
|
||||
const FAR struct wm8904_lower_s *lower; /* Pointer to the board lower functions */
|
||||
FAR struct i2c_dev_s *i2c; /* I2C driver to use */
|
||||
FAR struct i2s_dev_s *i2s; /* I2S driver to use */
|
||||
struct dq_queue_s pendq; /* Queue of pending buffers to be sent */
|
||||
struct dq_queue_s doneq; /* Queue of sent buffers to be returned */
|
||||
mqd_t mq; /* Message queue for receiving messages */
|
||||
char mqname[16]; /* Our message queue name */
|
||||
pthread_t threadid; /* ID of our thread */
|
||||
uint32_t bitrate; /* Actual programmed bit rate */
|
||||
sem_t pendsem; /* Protect pendq */
|
||||
uint16_t samprate; /* Configured samprate (samples/sec) */
|
||||
#ifndef CONFIG_AUDIO_EXCLUDE_VOLUME
|
||||
#ifndef CONFIG_AUDIO_EXCLUDE_BALANCE
|
||||
uint16_t balance; /* Current balance level (b16) */
|
||||
#endif /* CONFIG_AUDIO_EXCLUDE_BALANCE */
|
||||
uint8_t volume; /* Current volume level {0..63} */
|
||||
#endif /* CONFIG_AUDIO_EXCLUDE_VOLUME */
|
||||
uint8_t nchannels; /* Number of channels (1 or 2) */
|
||||
uint8_t bpsamp; /* Bits per sample (8 or 16) */
|
||||
volatile uint8_t inflight; /* Number of audio buffers in-flight */
|
||||
bool running; /* True: Worker thread is running */
|
||||
bool paused; /* True: Playing is paused */
|
||||
bool mute; /* True: Output is muted */
|
||||
#ifndef CONFIG_AUDIO_EXCLUDE_STOP
|
||||
bool terminating; /* True: Stop requested */
|
||||
#endif
|
||||
bool reserved; /* True: Device is reserved */
|
||||
volatile int result; /* The result of the last transfer */
|
||||
};
|
||||
|
||||
static const uint8_t g_fllratio[WM8904_NFLLRATIO] = {1, 2, 4, 8, 16};
|
||||
|
||||
/****************************************************************************
|
||||
* Private Function Prototypes
|
||||
****************************************************************************/
|
||||
|
||||
#ifndef CONFIG_WM8904_REGDUMP
|
||||
#if !defined(CONFIG_WM8904_REGDUMP) && !defined(CONFIG_WM8904_CLKDEBUG)
|
||||
static
|
||||
#endif
|
||||
uint16_t wm8904_readreg(FAR struct wm8904_dev_s *priv,
|
||||
@ -289,13 +205,21 @@ static const struct audio_ops_s g_audioops =
|
||||
wm8904_release /* release */
|
||||
};
|
||||
|
||||
static const uint8_t g_sysclk_scaleb1[WM8904_BCLK_MAXDIV+1] =
|
||||
#ifndef CONFIG_WM8904_CLKDEBUG
|
||||
static
|
||||
#endif
|
||||
const uint8_t g_sysclk_scaleb1[WM8904_BCLK_MAXDIV+1] =
|
||||
{
|
||||
2, 3, 4, 6, 8, 10, 11, /* 1, 1.5, 2, 3, 4, 5, 5.5 */
|
||||
12, 16, 20, 22, 24, 32, 40, /* 6, 8, 10, 11, 12, 16, 20 */
|
||||
44, 48, 50, 60, 64, 88, 96 /* 22, 24, 25, 30, 32, 44, 48 */
|
||||
};
|
||||
|
||||
#ifndef CONFIG_WM8904_CLKDEBUG
|
||||
static
|
||||
#endif
|
||||
const uint8_t g_fllratio[WM8904_NFLLRATIO] = {1, 2, 4, 8, 16};
|
||||
|
||||
/****************************************************************************
|
||||
* Private Functions
|
||||
****************************************************************************/
|
||||
@ -308,7 +232,7 @@ static const uint8_t g_sysclk_scaleb1[WM8904_BCLK_MAXDIV+1] =
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
#ifndef CONFIG_WM8904_REGDUMP
|
||||
#if !defined(CONFIG_WM8904_REGDUMP) && !defined(CONFIG_WM8904_CLKDEBUG)
|
||||
static
|
||||
#endif
|
||||
uint16_t wm8904_readreg(FAR struct wm8904_dev_s *priv, uint8_t regaddr)
|
||||
@ -900,7 +824,7 @@ static void wm8904_setbitrate(FAR struct wm8904_dev_s *priv)
|
||||
*
|
||||
* Already set above
|
||||
*/
|
||||
|
||||
|
||||
/* Allow time for FLL lock. Typical is 2 MSec. Lock status is available
|
||||
* in the WM8904 interrupt status register.
|
||||
*/
|
||||
@ -911,19 +835,6 @@ static void wm8904_setbitrate(FAR struct wm8904_dev_s *priv)
|
||||
|
||||
regval = WM8904_FLL_FRACN_ENA | WM8904_FLL_ENA;
|
||||
wm8904_writereg(priv, WM8904_FLL_CTRL1, regval);
|
||||
|
||||
/* Dump all FLL registers */
|
||||
|
||||
audvdbg("FLL control 1[%02x]: %04x\n",
|
||||
WM8904_FLL_CTRL1, wm8904_readreg(priv, WM8904_FLL_CTRL1));
|
||||
audvdbg("FLL control 2[%02x]: %04x\n",
|
||||
WM8904_FLL_CTRL2, wm8904_readreg(priv, WM8904_FLL_CTRL2));
|
||||
audvdbg("FLL control 3[%02x]: %04x\n",
|
||||
WM8904_FLL_CTRL3, wm8904_readreg(priv, WM8904_FLL_CTRL3));
|
||||
audvdbg("FLL control 4[%02x]: %04x\n",
|
||||
WM8904_FLL_CTRL4, wm8904_readreg(priv, WM8904_FLL_CTRL4));
|
||||
audvdbg("FLL control 5[%02x]: %04x\n",
|
||||
WM8904_FLL_CTRL5, wm8904_readreg(priv, WM8904_FLL_CTRL5));
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
@ -1260,6 +1171,8 @@ static int wm8904_configure(FAR struct audio_lowerhalf_s *dev,
|
||||
wm8904_setbitrate(priv);
|
||||
wm8904_setlrclock(priv);
|
||||
wm8904_writereg(priv, WM8904_DUMMY, 0x55aa);
|
||||
|
||||
wm8904_clock_analysis(&priv->dev, "AUDIO_TYPE_OUTPUT");
|
||||
ret = OK;
|
||||
}
|
||||
break;
|
||||
@ -2375,6 +2288,7 @@ FAR struct audio_lowerhalf_s *
|
||||
|
||||
wm8904_audio_output(priv);
|
||||
wm8904_dump_registers(&priv->dev, "After configuration");
|
||||
wm8904_clock_analysis(&priv->dev, "After configuration");
|
||||
|
||||
/* Attach our ISR to this device */
|
||||
|
||||
|
@ -47,6 +47,9 @@
|
||||
#include <nuttx/config.h>
|
||||
#include <nuttx/compiler.h>
|
||||
|
||||
#include <pthread.h>
|
||||
#include <mqueue.h>
|
||||
|
||||
#include <nuttx/fs/ioctl.h>
|
||||
|
||||
#ifdef CONFIG_AUDIO
|
||||
@ -157,6 +160,8 @@
|
||||
#define WM8904_FLL_NCO_TEST0 0xf7 /* FLL NCO Test 0 */
|
||||
#define WM8904_FLL_NCO_TEST1 0xf8 /* FLL NCO Test 1 */
|
||||
|
||||
#define WM8904_DUMMY 0xff /* Dummy register address */
|
||||
|
||||
/* Register Default Values **************************************************/
|
||||
/* Registers have some undocumented bits set on power up. These probably
|
||||
* should be retained on writes (?).
|
||||
@ -853,7 +858,7 @@
|
||||
# define WM8904_FLL_CLK_REF_DIV4 (2 << WM8904_FLL_CLK_REF_DIV_SHIFT) /* MCLK / 4 */
|
||||
# define WM8904_FLL_CLK_REF_DIV8 (3 << WM8904_FLL_CLK_REF_DIV_SHIFT) /* MCLK / 8 */
|
||||
#define WM8904_FLL_CLK_REF_SRC_SHIFT (0) /* Bits 0-2: FLL clock source */
|
||||
#define WM8904_FLL_CLK_REF_SRC_MASK (3) << WM8904_FLL_CLK_REF_SRC_SHIFT)
|
||||
#define WM8904_FLL_CLK_REF_SRC_MASK (3 << WM8904_FLL_CLK_REF_SRC_SHIFT)
|
||||
# define WM8904_FLL_CLK_REF_SRC_MCLK (0 << WM8904_FLL_CLK_REF_SRC_SHIFT)
|
||||
# define WM8904_FLL_CLK_REF_SRC_BCLK (1 << WM8904_FLL_CLK_REF_SRC_SHIFT)
|
||||
# define WM8904_FLL_CLK_REF_SRC_LRCLK (2 << WM8904_FLL_CLK_REF_SRC_SHIFT)
|
||||
@ -977,14 +982,98 @@
|
||||
|
||||
/* 0xf8 FLL NCO Test 1 (16-bit FLL forced oscillator value */
|
||||
|
||||
/* FLL Configuration *********************************************************/
|
||||
/* Default FLL configuration */
|
||||
|
||||
#define WM8904_DEFAULT_SAMPRATE 11025
|
||||
#define WM8904_DEFAULT_NCHANNELS 1
|
||||
#define WM8904_DEFAULT_BPSAMP 16
|
||||
|
||||
#define WM8904_STARTBITS 2
|
||||
|
||||
#define WM8904_NFLLRATIO_DIV1 0
|
||||
#define WM8904_NFLLRATIO_DIV2 1
|
||||
#define WM8904_NFLLRATIO_DIV4 2
|
||||
#define WM8904_NFLLRATIO_DIV8 3
|
||||
#define WM8904_NFLLRATIO_DIV16 4
|
||||
#define WM8904_NFLLRATIO 5
|
||||
|
||||
#define WM8904_MINOUTDIV 4
|
||||
#define WM8904_MAXOUTDIV 64
|
||||
|
||||
#define WM8904_BCLK_MAXDIV 20
|
||||
|
||||
#define WM8904_FVCO_MIN 90000000
|
||||
#define WM8904_FVCO_MAX 100000000
|
||||
|
||||
/* Commonly defined and redefined macros */
|
||||
|
||||
#ifndef MIN
|
||||
# define MIN(a,b) (((a) < (b)) ? (a) : (b))
|
||||
#endif
|
||||
|
||||
#ifndef MAX
|
||||
# define MAX(a,b) (((a) > (b)) ? (a) : (b))
|
||||
#endif
|
||||
|
||||
/****************************************************************************
|
||||
* Public Types
|
||||
****************************************************************************/
|
||||
|
||||
struct wm8904_dev_s
|
||||
{
|
||||
/* We are an audio lower half driver (We are also the upper "half" of
|
||||
* the WM8904 driver with respect to the board lower half driver).
|
||||
*
|
||||
* Terminology: Our "lower" half audio instances will be called dev for the
|
||||
* publicly visible version and "priv" for the version that only this driver
|
||||
* knows. From the point of view of this driver, it is the board lower
|
||||
* "half" that is referred to as "lower".
|
||||
*/
|
||||
|
||||
struct audio_lowerhalf_s dev; /* WM8904 audio lower half (this device) */
|
||||
|
||||
/* Our specific driver data goes here */
|
||||
|
||||
const FAR struct wm8904_lower_s *lower; /* Pointer to the board lower functions */
|
||||
FAR struct i2c_dev_s *i2c; /* I2C driver to use */
|
||||
FAR struct i2s_dev_s *i2s; /* I2S driver to use */
|
||||
struct dq_queue_s pendq; /* Queue of pending buffers to be sent */
|
||||
struct dq_queue_s doneq; /* Queue of sent buffers to be returned */
|
||||
mqd_t mq; /* Message queue for receiving messages */
|
||||
char mqname[16]; /* Our message queue name */
|
||||
pthread_t threadid; /* ID of our thread */
|
||||
uint32_t bitrate; /* Actual programmed bit rate */
|
||||
sem_t pendsem; /* Protect pendq */
|
||||
uint16_t samprate; /* Configured samprate (samples/sec) */
|
||||
#ifndef CONFIG_AUDIO_EXCLUDE_VOLUME
|
||||
#ifndef CONFIG_AUDIO_EXCLUDE_BALANCE
|
||||
uint16_t balance; /* Current balance level (b16) */
|
||||
#endif /* CONFIG_AUDIO_EXCLUDE_BALANCE */
|
||||
uint8_t volume; /* Current volume level {0..63} */
|
||||
#endif /* CONFIG_AUDIO_EXCLUDE_VOLUME */
|
||||
uint8_t nchannels; /* Number of channels (1 or 2) */
|
||||
uint8_t bpsamp; /* Bits per sample (8 or 16) */
|
||||
volatile uint8_t inflight; /* Number of audio buffers in-flight */
|
||||
bool running; /* True: Worker thread is running */
|
||||
bool paused; /* True: Playing is paused */
|
||||
bool mute; /* True: Output is muted */
|
||||
#ifndef CONFIG_AUDIO_EXCLUDE_STOP
|
||||
bool terminating; /* True: Stop requested */
|
||||
#endif
|
||||
bool reserved; /* True: Device is reserved */
|
||||
volatile int result; /* The result of the last transfer */
|
||||
};
|
||||
|
||||
/****************************************************************************
|
||||
* Public Data
|
||||
****************************************************************************/
|
||||
|
||||
#ifdef CONFIG_WM8904_CLKDEBUG
|
||||
extern const uint8_t g_sysclk_scaleb1[WM8904_BCLK_MAXDIV+1];
|
||||
extern const uint8_t g_fllratio[WM8904_NFLLRATIO];
|
||||
#endif
|
||||
|
||||
/****************************************************************************
|
||||
* Public Function Prototypes
|
||||
****************************************************************************/
|
||||
@ -997,7 +1086,7 @@
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
#ifdef CONFIG_WM8904_REGDUMP
|
||||
#if defined(CONFIG_WM8904_REGDUMP) || defined(CONFIG_WM8904_CLKDEBUG)
|
||||
struct wm8904_dev_s;
|
||||
uint16_t wm8904_readreg(FAR struct wm8904_dev_s *priv, uint8_t regaddr);
|
||||
#endif
|
||||
|
@ -48,14 +48,15 @@
|
||||
#include <nuttx/config.h>
|
||||
|
||||
#include <stdint.h>
|
||||
#include <assert.h>
|
||||
#include <fixedmath.h>
|
||||
#include <syslog.h>
|
||||
|
||||
#include <nuttx/audio/audio.h>
|
||||
#include <nuttx/audio/wm8904.h>
|
||||
|
||||
#include "wm8904.h"
|
||||
|
||||
#ifdef CONFIG_WM8904_REGDUMP
|
||||
|
||||
/****************************************************************************
|
||||
* Pre-processor Definitions
|
||||
****************************************************************************/
|
||||
@ -64,11 +65,13 @@
|
||||
* Private Types
|
||||
****************************************************************************/
|
||||
|
||||
struct wm8904_debug_s
|
||||
#ifdef CONFIG_WM8904_REGDUMP
|
||||
struct wb8904_regdump_s
|
||||
{
|
||||
FAR const char *regname;
|
||||
uint8_t regaddr;
|
||||
};
|
||||
#endif
|
||||
|
||||
/****************************************************************************
|
||||
* Private Function Prototypes
|
||||
@ -78,7 +81,8 @@ struct wm8904_debug_s
|
||||
* Private Data
|
||||
****************************************************************************/
|
||||
|
||||
static const struct wm8904_debug_s g_wm8904_debug[] =
|
||||
#ifdef CONFIG_WM8904_REGDUMP
|
||||
static const struct wb8904_regdump_s g_wm8904_debug[] =
|
||||
{
|
||||
{"ID", WM8904_ID },
|
||||
{"BIAS_CTRL", WM8904_BIAS_CTRL },
|
||||
@ -180,7 +184,8 @@ static const struct wm8904_debug_s g_wm8904_debug[] =
|
||||
{"FLL_NCO_TEST1", WM8904_FLL_NCO_TEST1 }
|
||||
};
|
||||
|
||||
#define WM8904_NREGISTERS (sizeof(g_wm8904_debug)/sizeof(struct wm8904_debug_s))
|
||||
# define WM8904_NREGISTERS (sizeof(g_wm8904_debug)/sizeof(struct wb8904_regdump_s))
|
||||
#endif /* CONFIG_WM8904_REGDUMP */
|
||||
|
||||
/****************************************************************************
|
||||
* Private Functions
|
||||
@ -204,6 +209,7 @@ static const struct wm8904_debug_s g_wm8904_debug[] =
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
#ifdef CONFIG_WM8904_REGDUMP
|
||||
void wm8904_dump_registers(FAR struct audio_lowerhalf_s *dev,
|
||||
FAR const char *msg)
|
||||
{
|
||||
@ -218,5 +224,210 @@ void wm8904_dump_registers(FAR struct audio_lowerhalf_s *dev,
|
||||
g_wm8904_debug[i].regaddr));
|
||||
}
|
||||
}
|
||||
|
||||
#endif /* CONFIG_WM8904_REGDUMP */
|
||||
|
||||
/****************************************************************************
|
||||
* Name: wm8904_clock_analysis
|
||||
*
|
||||
* Description:
|
||||
* Analyze the settings in the clock chain and dump to syslog.
|
||||
*
|
||||
* Input Parameters:
|
||||
* dev - The device instance returned by wm8904_initialize
|
||||
*
|
||||
* Returned Value:
|
||||
* None.
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
#ifdef CONFIG_WM8904_CLKDEBUG
|
||||
void wm8904_clock_analysis(FAR struct audio_lowerhalf_s *dev,
|
||||
FAR const char *msg)
|
||||
{
|
||||
FAR struct wm8904_dev_s *priv = (FAR struct wm8904_dev_s *)dev;
|
||||
uint32_t sysclk;
|
||||
uint32_t bclk;
|
||||
uint32_t lrclk;
|
||||
uint16_t regval;
|
||||
unsigned int tmp;
|
||||
double ftmp;
|
||||
|
||||
syslog("WM8904 Clock Analysis: %s\n", msg);
|
||||
DEBUGASSERT(priv && priv->lower);
|
||||
syslog(" MCLK: %lu Hz\n", (unsigned long)priv->lower->mclk);
|
||||
|
||||
/* Is the SYSCLK source the FLL? Or MCK? */
|
||||
|
||||
regval = wm8904_readreg(priv, WM8904_CLKRATE2);
|
||||
if ((regval & WM8904_SYSCLK_SRC) == WM8904_SYSCLK_SRCMCLK)
|
||||
{
|
||||
/* The SYSCLK divider bypasses the FLL and takes its input
|
||||
* directly from MCLK.
|
||||
*/
|
||||
|
||||
sysclk = priv->lower->mclk;
|
||||
syslog(" SYSCLK Source: MCLK (%s)\n",
|
||||
(regval & WM8904_MCLK_INV) != 0 ? "inverted" : "not inverted");
|
||||
}
|
||||
else
|
||||
{
|
||||
uint32_t fref;
|
||||
uint32_t fvco;
|
||||
uint32_t fout;
|
||||
unsigned int outdiv;
|
||||
unsigned int frndx;
|
||||
unsigned int flln;
|
||||
unsigned int fllk;
|
||||
unsigned int fratio;
|
||||
double nk;
|
||||
|
||||
/* Assume that the Fref input to the FLL is MCLK */
|
||||
|
||||
fref = priv->lower->mclk;
|
||||
|
||||
/* Now get the real FLL input source */
|
||||
|
||||
regval = wm8904_readreg(priv, WM8904_FLL_CTRL5);
|
||||
switch (regval & WM8904_FLL_CLK_REF_SRC_MASK)
|
||||
{
|
||||
case WM8904_FLL_CLK_REF_SRC_MCLK:
|
||||
syslog(" FLL Source: MCLK\n");
|
||||
break;
|
||||
|
||||
case WM8904_FLL_CLK_REF_SRC_BCLK:
|
||||
syslog(" ERROR: FLL source is BCLK: %04x\n", regval);
|
||||
break;
|
||||
|
||||
case WM8904_FLL_CLK_REF_SRC_LRCLK:
|
||||
syslog(" ERROR: FLL source is LRCLK: %04x\n", regval);
|
||||
break;
|
||||
|
||||
default:
|
||||
syslog(" ERROR: Unrecognized FLL source: %04x\n", regval);
|
||||
}
|
||||
|
||||
syslog(" Fref: %lu Hz (before divider)\n", fref);
|
||||
switch (regval & WM8904_FLL_CLK_REF_DIV_MASK)
|
||||
{
|
||||
case WM8904_FLL_CLK_REF_DIV1:
|
||||
syslog(" FLL_CLK_REF_DIV: 1\n");
|
||||
break;
|
||||
|
||||
case WM8904_FLL_CLK_REF_DIV2:
|
||||
syslog(" FLL_CLK_REF_DIV: 2\n");
|
||||
fref >>= 1;
|
||||
break;
|
||||
|
||||
case WM8904_FLL_CLK_REF_DIV4:
|
||||
syslog(" FLL_CLK_REF_DIV: 4\n");
|
||||
fref >>= 2;
|
||||
break;
|
||||
|
||||
case WM8904_FLL_CLK_REF_DIV8:
|
||||
syslog(" FLL_CLK_REF_DIV: 8\n");
|
||||
fref >>= 3;
|
||||
break;
|
||||
}
|
||||
|
||||
syslog(" Fref: %lu Hz (after divider)\n", fref);
|
||||
|
||||
regval = wm8904_readreg(priv, WM8904_FLL_CTRL2);
|
||||
frndx = (regval & WM8904_FLL_FRATIO_MASK) >> WM8904_FLL_FRATIO_SHIFT;
|
||||
tmp = (regval & WM8904_FLL_CTRL_RATE_MASK) >> WM8904_FLL_CTRL_RATE_SHIFT;
|
||||
outdiv = ((regval & WM8904_FLL_OUTDIV_MASK) >> WM8904_FLL_OUTDIV_SHIFT) + 1;
|
||||
|
||||
syslog(" FLL_CTRL_RATE: Fvco / %u\n", tmp + 1);
|
||||
|
||||
regval = wm8904_readreg(priv, WM8904_FLL_CTRL4);
|
||||
flln = (regval & WM8904_FLL_N_MASK) >> WM8904_FLL_N_SHIFT;
|
||||
tmp = (regval & WM8904_FLL_GAIN_MASK) >> WM8904_FLL_GAIN_SHIFT;
|
||||
|
||||
syslog(" FLL_GAIN: %u\n", (1 << tmp));
|
||||
|
||||
fllk = wm8904_readreg(priv, WM8904_FLL_CTRL3);
|
||||
nk = (double)flln + ((double)fllk / 65536.0);
|
||||
fratio = g_fllratio[frndx];
|
||||
|
||||
syslog(" FLL_FRATIO: %u\n", fratio);
|
||||
syslog(" FLL_OUTDIV: %u\n", outdiv);
|
||||
syslog(" FLL_N.K: %u.%05u\n", flln, fllk);
|
||||
|
||||
ftmp = nk * (double)fref * (double)fratio;
|
||||
fvco = (uint32_t)ftmp;
|
||||
|
||||
syslog(" Fvco: %lu Hz\n", (unsigned long)fvco);
|
||||
|
||||
fout = fvco / outdiv;
|
||||
syslog(" Fout: %lu Hz\n", (unsigned long)fout);
|
||||
|
||||
regval = wm8904_readreg(priv, WM8904_FLL_CTRL1);
|
||||
|
||||
syslog(" FLL_FRACN_ENA: %s\n",
|
||||
(regval & WM8904_FLL_FRACN_ENA) != 0 ? "Enabled" : "Disabled");
|
||||
syslog(" FLL_OSC_ENA: %s\n",
|
||||
(regval & WM8904_FLL_OSC_ENA) != 0 ? "Enabled" : "Disabled");
|
||||
syslog(" FLL_ENA: %s\n",
|
||||
(regval & WM8904_FLL_ENA) != 0 ? "Enabled" : "Disabled");
|
||||
|
||||
if ((regval & WM8904_FLL_ENA) == 0)
|
||||
{
|
||||
syslog(" No SYSCLK\n");
|
||||
return;
|
||||
}
|
||||
|
||||
sysclk = fout;
|
||||
}
|
||||
|
||||
syslog(" SYSCLK: %lu Hz (before divider)\n", (unsigned long)sysclk);
|
||||
|
||||
regval = wm8904_readreg(priv, WM8904_CLKRATE0);
|
||||
if ((regval & WM8904_MCLK_DIV) == WM8904_MCLK_DIV1)
|
||||
{
|
||||
syslog(" MCLK_DIV: 1\n");
|
||||
}
|
||||
else
|
||||
{
|
||||
syslog(" MCLK_DIV: 2\n");
|
||||
sysclk >>=1;
|
||||
}
|
||||
|
||||
syslog(" SYSCLK: %lu (after divider)\n", (unsigned long)sysclk);
|
||||
|
||||
regval = wm8904_readreg(priv, WM8904_CLKRATE2);
|
||||
|
||||
syslog(" CLK_SYS_ENA: %s\n",
|
||||
(regval & WM8904_CLK_SYS_ENA) != 0 ? "Enabled" : "Disabled");
|
||||
|
||||
if ((regval & WM8904_CLK_SYS_ENA) == 0)
|
||||
{
|
||||
syslog(" No SYSCLK\n");
|
||||
return;
|
||||
}
|
||||
|
||||
regval = wm8904_readreg(priv, WM8904_AIF2);
|
||||
tmp = (regval & WM8904_BCLK_DIV_MASK) >> WM8904_BCLK_DIV_SHIFT;
|
||||
tmp = g_sysclk_scaleb1[tmp];
|
||||
ftmp = (double)tmp / 2.0;
|
||||
|
||||
syslog(" BCLK_DIV: SYSCLK / %u.%01u\n",
|
||||
(unsigned int)(tmp >> 1), (unsigned int)(5 * (tmp & 1)));
|
||||
|
||||
bclk = (uint32_t)(sysclk / ftmp);
|
||||
|
||||
syslog(" BCLK: %lu Hz\n", (unsigned long)bclk);
|
||||
|
||||
regval = wm8904_readreg(priv, WM8904_AIF1);
|
||||
syslog(" BCLK_DIR: %s\n",
|
||||
(regval & WM8904_BCLK_DIR) != 0 ? "Output" : "Input");
|
||||
|
||||
regval = wm8904_readreg(priv, WM8904_AIF3);
|
||||
tmp = (regval & WM8904_LRCLK_RATE_MASK) >> WM8904_LRCLK_RATE_SHIFT;
|
||||
|
||||
lrclk = bclk / tmp;
|
||||
|
||||
syslog(" LRCLK_RATE: BCLK / %lu\n", (unsigned long)tmp);
|
||||
syslog(" LRCLK: %lu\n", (unsigned long)lrclk);
|
||||
syslog(" LRCLK_DIR: %s\n",
|
||||
(regval & WM8904_LRCLK_DIR) != 0 ? "Output" : "Input");
|
||||
}
|
||||
#endif /* CONFIG_WM8904_CLKDEBUG */
|
||||
|
@ -245,6 +245,31 @@ void wm8904_dump_registers(FAR struct audio_lowerhalf_s *dev,
|
||||
# define wm8904_dump_registers(d,m)
|
||||
#endif
|
||||
|
||||
/****************************************************************************
|
||||
* Name: wm8904_clock_analysis
|
||||
*
|
||||
* Description:
|
||||
* Analyze the settings in the clock chain and dump to syslog.
|
||||
*
|
||||
* Input Parameters:
|
||||
* dev - The device instance returned by wm8904_initialize
|
||||
*
|
||||
* Returned Value:
|
||||
* None.
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
#ifdef CONFIG_WM8904_CLKDEBUG
|
||||
void wm8904_clock_analysis(FAR struct audio_lowerhalf_s *dev,
|
||||
FAR const char *msg);
|
||||
#else
|
||||
/* This eliminates the need for any conditional compilation in the
|
||||
* including file.
|
||||
*/
|
||||
|
||||
# define wm8904_clock_analysis(d,m)
|
||||
#endif
|
||||
|
||||
#undef EXTERN
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user