/*
* wm8988.c -- WM8988 ALSA SoC audio driver
*
* Copyright 2009 Wolfson Microelectronics plc
* Copyright 2005 Openedhand Ltd.
*
* Author: Mark Brown <broonie@opensource.wolfsonmicro.com>
*
* 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/spi/spi.h>
#include <linux/slab.h>
#include <sound/core.h>
#include <sound/pcm.h>
#include <sound/pcm_params.h>
#include <sound/tlv.h>
#include <sound/soc.h>
#include <sound/initval.h>
#include "wm8988.h"
/*
* wm8988 register cache
* We can't read the WM8988 register space when we
* are using 2 wire for device control, so we cache them instead.
*/
static const struct reg_default wm8988_reg_defaults[] = {
{ 0, 0x0097 },
{ 1, 0x0097 },
{ 2, 0x0079 },
{ 3, 0x0079 },
{ 5, 0x0008 },
{ 7, 0x000a },
{ 8, 0x0000 },
{ 10, 0x00ff },
{ 11, 0x00ff },
{ 12, 0x000f },
{ 13, 0x000f },
{ 16, 0x0000 },
{ 17, 0x007b },
{ 18, 0x0000 },
{ 19, 0x0032 },
{ 20, 0x0000 },
{ 21, 0x00c3 },
{ 22, 0x00c3 },
{ 23, 0x00c0 },
{ 24, 0x0000 },
{ 25, 0x0000 },
{ 26, 0x0000 },
{ 27, 0x0000 },
{ 31, 0x0000 },
{ 32, 0x0000 },
{ 33, 0x0000 },
{ 34, 0x0050 },
{ 35, 0x0050 },
{ 36, 0x0050 },
{ 37, 0x0050 },
{ 40, 0x0079 },
{ 41, 0x0079 },
{ 42, 0x0079 },
};
static bool wm8988_writeable(struct device *dev, unsigned int reg)
{
switch (reg) {
case WM8988_LINVOL:
case WM8988_RINVOL:
case WM8988_LOUT1V:
case WM8988_ROUT1V:
case WM8988_ADCDAC:
case WM8988_IFACE:
case WM8988_SRATE:
case WM8988_LDAC:
case WM8988_RDAC:
case WM8988_BASS:
case WM8988_TREBLE:
case WM8988_RESET:
case WM8988_3D:
case WM8988_ALC1:
case WM8988_ALC2:
case WM8988_ALC3:
case WM8988_NGATE:
case WM8988_LADC:
case WM8988_RADC:
case WM8988_ADCTL1:
case WM8988_ADCTL2:
case WM8988_PWR1:
case WM8988_PWR2:
case WM8988_ADCTL3:
case WM8988_ADCIN:
case WM8988_LADCIN:
case WM8988_RADCIN:
case WM8988_LOUTM1:
case WM8988_LOUTM2:
case WM8988_ROUTM1:
case WM8988_ROUTM2:
case WM8988_LOUT2V:
case WM8988_ROUT2V:
case WM8988_LPPB:
return true;
default:
return false;
}
}
/* codec private data */
struct wm8988_priv {
struct regmap *regmap;
unsigned int sysclk;
struct snd_pcm_hw_constraint_list *sysclk_constraints;
};
#define wm8988_reset(c) snd_soc_write(c, WM8988_RESET, 0)
/*
* WM8988 Controls
*/
static const char *bass_boost_txt[] = {"Linear Control", "Adaptive Boost"};
static const struct soc_enum bass_boost =
SOC_ENUM_SINGLE(WM8988_BASS, 7, 2, bass_boost_txt);
static const char *bass_filter_txt[] = { "130Hz @ 48kHz", "200Hz @ 48kHz" };
static const struct soc_enum bass_filter =
SOC_ENUM_SINGLE(WM8988_BASS, 6, 2, bass_filter_txt);
static const char *treble_txt[] = {"8kHz", "4kHz"};
static const struct soc_enum treble =
SOC_ENUM_SINGLE(WM8988_TREBLE, 6, 2, treble_txt);
static const char *stereo_3d_lc_txt[] = {"200Hz", "500Hz"};
static const struct soc_enum stereo_3d_lc =
SOC_ENUM_SINGLE(WM8988_3D, 5, 2, stereo_3d_lc_txt);
static const char *stereo_3d_uc_txt[] = {"2.2kHz", "1.5kHz"};
static const struct soc_enum stereo_3d_uc