/*
* wm8750.c -- WM8750 ALSA SoC audio driver
*
* Copyright 2005 Openedhand Ltd.
*
* Author: Richard Purdie <richard@openedhand.com>
*
* Based on WM8753.c
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as
* published by the Free Software Foundation.
*/
#include <linux/module.h>
#include <linux/moduleparam.h>
#include <linux/init.h>
#include <linux/delay.h>
#include <linux/pm.h>
#include <linux/i2c.h>
#include <linux/platform_device.h>
#include <sound/driver.h>
#include <sound/core.h>
#include <sound/pcm.h>
#include <sound/pcm_params.h>
#include <sound/soc.h>
#include <sound/soc-dapm.h>
#include <sound/initval.h>
#include "wm8750.h"
#define AUDIO_NAME "WM8750"
#define WM8750_VERSION "0.11"
/*
* Debug
*/
#define WM8750_DEBUG 0
#ifdef WM8750_DEBUG
#define dbg(format, arg...) \
printk(KERN_DEBUG AUDIO_NAME ": " format "\n" , ## arg)
#else
#define dbg(format, arg...) do {} while (0)
#endif
#define err(format, arg...) \
printk(KERN_ERR AUDIO_NAME ": " format "\n" , ## arg)
#define info(format, arg...) \
printk(KERN_INFO AUDIO_NAME ": " format "\n" , ## arg)
#define warn(format, arg...) \
printk(KERN_WARNING AUDIO_NAME ": " format "\n" , ## arg)
static struct workqueue_struct *wm8750_workq = NULL;
static struct work_struct wm8750_dapm_work;
/*
* wm8750 register cache
* We can't read the WM8750 register space when we
* are using 2 wire for device control, so we cache them instead.
*/
static const u16 wm8750_reg[] = {
0x0097, 0x0097, 0x0079, 0x0079, /* 0 */
0x0000, 0x0008, 0x0000, 0x000a, /* 4 */
0x0000, 0x0000, 0x00ff, 0x00ff, /* 8 */
0x000f, 0x000f, 0x0000, 0x0000, /* 12 */
0x0000, 0x007b, 0x0000, 0x0032, /* 16 */
0x0000, 0x00c3, 0x00c3, 0x00c0, /* 20 */
0x0000, 0x0000, 0x0000, 0x0000, /* 24 */
0x0000, 0x0000, 0x0000, 0x0000, /* 28 */
0x0000, 0x0000, 0x0050, 0x0050, /* 32 */
0x0050, 0x0050, 0x0050, 0x0050, /* 36 */
0x0079, 0x0079, 0x0079, /* 40 */
};
#define WM8750_HIFI_DAIFMT \
(SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_LEFT_J | SND_SOC_DAIFMT_RIGHT_J | \
SND_SOC_DAIFMT_NB_NF | SND_SOC_DAIFMT_NB_IF | SND_SOC_DAIFMT_IB_NF | \
SND_SOC_DAIFMT_IB_IF)
#define WM8750_DIR \
(SND_SOC_DAIDIR_PLAYBACK | SND_SOC_DAIDIR_CAPTURE)
#define WM8750_HIFI_FSB \
(SND_SOC_FSBD(1) | SND_SOC_FSBD(2) | SND_SOC_FSBD(4) | \
SND_SOC_FSBD(8) | SND_SOC_FSBD(16))
#define WM8750_HIFI_RATES \
(SNDRV_PCM_RATE_8000 | SNDRV_PCM_RATE_11025 | SNDRV_PCM_RATE_16000 | \
SNDRV_PCM_RATE_22050 | SNDRV_PCM_RATE_32000 | SNDRV_PCM_RATE_44100 | \
SNDRV_PCM_RATE_48000 | SNDRV_PCM_RATE_88200 | SNDRV_PCM_RATE_96000)
#define WM8750_HIFI_BITS \
(SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S20_3LE | \
SNDRV_PCM_FMTBIT_S24_LE | SNDRV_PCM_FMTBIT_S32_LE)
static struct snd_soc_dai_mode wm8750_modes[] = {
/* common codec frame and clock master modes */
/* 8k */
{
.fmt = WM8750_HIFI_DAIFMT | SND_SOC_DAIFMT_CBM_CFM,
.pcmfmt = WM8750_HIFI_BITS,
.pcmrate = SNDRV_PCM_RATE_8000,
.pcmdir = WM8750_DIR,
.flags = SND_SOC_DAI_BFS_DIV,
.fs = 1536,
.bfs = WM8750_HIFI_FSB,
},
{
.fmt = WM8750_HIFI_DAIFMT | SND_SOC_DAIFMT_CBM_CFM,
.pcmfmt = WM8750_HIFI_BITS,
.pcmrate = SNDRV_PCM_RATE_8000,
.<