diff options
author | Gregory Nutt <gnutt@nuttx.org> | 2014-08-03 17:11:38 -0600 |
---|---|---|
committer | Gregory Nutt <gnutt@nuttx.org> | 2014-08-03 17:11:38 -0600 |
commit | 4caf93f84ea980263dad17e17cd6b3de28fc96c4 (patch) | |
tree | 61b8717d6a9765550d33479d44e0bc850756d4d7 | |
parent | 0d33cb3f799c21104d826812d4c412bce8a97a5b (diff) | |
download | px4-nuttx-4caf93f84ea980263dad17e17cd6b3de28fc96c4.tar.gz px4-nuttx-4caf93f84ea980263dad17e17cd6b3de28fc96c4.tar.bz2 px4-nuttx-4caf93f84ea980263dad17e17cd6b3de28fc96c4.zip |
WM8904: Add logic to analyze BCLK setup
-rw-r--r-- | nuttx/drivers/audio/Kconfig | 6 | ||||
-rw-r--r-- | nuttx/drivers/audio/Make.defs | 4 | ||||
-rw-r--r-- | nuttx/drivers/audio/wm8904.c | 116 | ||||
-rw-r--r-- | nuttx/drivers/audio/wm8904.h | 93 | ||||
-rw-r--r-- | nuttx/drivers/audio/wm8904_debug.c | 223 | ||||
-rw-r--r-- | nuttx/include/nuttx/audio/wm8904.h | 25 |
6 files changed, 358 insertions, 109 deletions
diff --git a/nuttx/drivers/audio/Kconfig b/nuttx/drivers/audio/Kconfig index b226e2f04..e0fdf4e2b 100644 --- a/nuttx/drivers/audio/Kconfig +++ b/nuttx/drivers/audio/Kconfig @@ -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 diff --git a/nuttx/drivers/audio/Make.defs b/nuttx/drivers/audio/Make.defs index 049882967..f645deade 100644 --- a/nuttx/drivers/audio/Make.defs +++ b/nuttx/drivers/audio/Make.defs @@ -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 diff --git a/nuttx/drivers/audio/wm8904.c b/nuttx/drivers/audio/wm8904.c index 3cb3f0c97..90fe08952 100644 --- a/nuttx/drivers/audio/wm8904.c +++ b/nuttx/drivers/audio/wm8904.c @@ -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 */ diff --git a/nuttx/drivers/audio/wm8904.h b/nuttx/drivers/audio/wm8904.h index 41f2e3699..9b2059c6c 100644 --- a/nuttx/drivers/audio/wm8904.h +++ b/nuttx/drivers/audio/wm8904.h @@ -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 diff --git a/nuttx/drivers/audio/wm8904_debug.c b/nuttx/drivers/audio/wm8904_debug.c index df6e9abb2..753712827 100644 --- a/nuttx/drivers/audio/wm8904_debug.c +++ b/nuttx/drivers/audio/wm8904_debug.c @@ -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 */ diff --git a/nuttx/include/nuttx/audio/wm8904.h b/nuttx/include/nuttx/audio/wm8904.h index 9c25fd4ad..c2f0a78ed 100644 --- a/nuttx/include/nuttx/audio/wm8904.h +++ b/nuttx/include/nuttx/audio/wm8904.h @@ -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 } |