/*
* wm8971.c -- WM8971 ALSA SoC Audio driver
*
* Copyright 2005 Lab126, Inc.
*
* Author: Kenneth Kiraly <kiraly@lab126.com>
*
* Based on wm8753.c by Liam Girdwood
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the
* Free Software Foundation; either version 2 of the License, or (at your
* option) any later version.
*/
#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 <linux/slab.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 "wm8971.h"
#define WM8971_VERSION "0.9"
#define WM8971_REG_COUNT 43
static struct workqueue_struct *wm8971_workq = NULL;
/* codec private data */
struct wm8971_priv {
unsigned int sysclk;
};
/*
* wm8971 register cache
* We can't read the WM8971 register space when we
* are using 2 wire for device control, so we cache them instead.
*/
static const u16 wm8971_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 wm8971_reset(c) snd_soc_write(c, WM8971_RESET, 0)
/* WM8971 Controls */
static const char *wm8971_bass[] = { "Linear Control", "Adaptive Boost" };
static const char *wm8971_bass_filter[] = { "130Hz @ 48kHz",
"200Hz @ 48kHz" };
static const char *wm8971_treble[] = { "8kHz", "4kHz" };
static const char *wm8971_alc_func[] = { "Off", "Right", "Left", "Stereo" };
static const char *wm8971_ng_type[] = { "Constant PGA Gain",
"Mute ADC Output" };
static const char *wm8971_deemp[] = { "None", "32kHz", "44.1kHz", "48kHz" };
static const char *wm8971_mono_mux[] = {"Stereo", "Mono (Left)",
"Mono (Right)", "Digital Mono"};
static const char *wm8971_dac_phase[] = { "Non Inverted", "Inverted" };
static const char *wm8971_lline_mux[] = {"Line", "NC", "NC", "PGA",
"Differential"};
static const char *wm8971_rline_mux[] = {"Line", "Mic", "NC", "PGA",
"Differential"};
static const char *wm8971_lpga_sel[] = {"Line", "NC", "NC", "Differential"};
static const char *wm8971_rpga_sel[] = {"Line", "Mic", "NC", "Differential"};
static const char *wm8971_adcpol[] = {"Normal", "L Invert", "R Invert",
"L + R Invert"};
static const struct soc_enum wm8971_enum[] = {
SOC_ENUM_SINGLE(WM8971_BASS, 7, 2, wm8971_bass), /* 0 */
SOC_ENUM_SINGLE(WM8971_BASS, 6, 2, wm8971_bass_filter),
SOC_ENUM_SINGLE(WM8971_TREBLE, 6, 2, wm8971_treble),
SOC_ENUM_SINGLE(WM8971_ALC1, 7, 4, wm8971_alc_func),
SOC_ENUM_SINGLE(WM8971_NGATE, 1, 2, wm8971_ng_type), /* 4 */
SOC_ENUM_SINGLE(WM8971_ADCDAC, 1, 4, wm8971_deemp),
SOC_ENUM_SINGLE(WM8971_ADCTL1, 4, 4, wm8971_mono_mux),
SOC_ENUM_SINGLE(WM8971_ADCTL1, 1, 2, wm8971_dac_phase),
SOC_ENUM_SINGLE(WM8971_LOUTM1, 0, 5, wm8971_lline_mux), /* 8 */
SOC_ENUM_SINGLE(WM8971_ROUTM1, 0, 5, wm8971_rline_mux),
SOC_ENUM_SINGLE(WM8971_LADCIN, 6, 4, wm8971_lpga_sel),
SOC_ENUM_SINGLE(WM8971_RADCIN, 6, 4, wm8971_rpga_sel),
SOC_ENUM_SINGLE(WM8971_ADCDAC, 5, 4, wm8971_adcpol), /* 12 */
SOC_ENUM_SINGLE(WM8971_ADCIN, 6, 4, wm8971_mono_mux),
};
static const struct snd_kcontrol_new wm8971_snd_controls[] = {
SOC_DOUBLE_R("Capture Volume", WM8971_LINVOL, WM8971_RINVOL, 0, 63, 0),
SOC_DOUBLE_R("Capture ZC Switch", WM8971_LINVOL, WM8971_RINVOL,
6, 1, 0),
SOC_DOUBLE_R("Capture Switch", WM8971_LINVOL, WM8971_RINVOL, 7, 1, 1),
SOC_DOUBLE_R("Headphone Playback ZC Switch", WM8971_LOUT1V,
WM8971_ROUT1V, 7, 1, 0),
SOC_DOUBLE_R("Speaker Playback ZC Switch", WM8971_LOUT2V,
WM8971_ROUT2V, 7, 1, 0),
SOC_SINGLE("Mono Playback ZC Switch", WM8971_MOUTV, 7, 1, 0),
SOC_DOUBLE_R("PCM Volume", WM8971_LDAC, WM8971_RDAC, 0, 255, 0),