/*
* Codec driver for ST STA32x 2.1-channel high-efficiency digital audio system
*
* Copyright: 2011 Raumfeld GmbH
* Author: Johannes Stezenbach <js@sig21.net>
*
* based on code from:
* Wolfson Microelectronics PLC.
* Mark Brown <broonie@opensource.wolfsonmicro.com>
* Freescale Semiconductor, Inc.
* Timur Tabi <timur@freescale.com>
*
* 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.
*/
#define pr_fmt(fmt) KBUILD_MODNAME ":%s:%d: " fmt, __func__, __LINE__
#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/regmap.h>
#include <linux/regulator/consumer.h>
#include <linux/slab.h>
#include <linux/workqueue.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 <sound/tlv.h>
#include <sound/sta32x.h>
#include "sta32x.h"
#define STA32X_RATES (SNDRV_PCM_RATE_32000 | \
SNDRV_PCM_RATE_44100 | \
SNDRV_PCM_RATE_48000 | \
SNDRV_PCM_RATE_88200 | \
SNDRV_PCM_RATE_96000 | \
SNDRV_PCM_RATE_176400 | \
SNDRV_PCM_RATE_192000)
#define STA32X_FORMATS \
(SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S16_BE | \
SNDRV_PCM_FMTBIT_S18_3LE | SNDRV_PCM_FMTBIT_S18_3BE | \
SNDRV_PCM_FMTBIT_S20_3LE | SNDRV_PCM_FMTBIT_S20_3BE | \
SNDRV_PCM_FMTBIT_S24_3LE | SNDRV_PCM_FMTBIT_S24_3BE | \
SNDRV_PCM_FMTBIT_S24_LE | SNDRV_PCM_FMTBIT_S24_BE | \
SNDRV_PCM_FMTBIT_S32_LE | SNDRV_PCM_FMTBIT_S32_BE)
/* Power-up register defaults */
static const struct reg_default sta32x_regs[] = {
{ 0x0, 0x63 },
{ 0x1, 0x80 },
{ 0x2, 0xc2 },
{ 0x3, 0x40 },
{ 0x4, 0xc2 },
{ 0x5, 0x5c },
{ 0x6, 0x10 },
{ 0x7, 0xff },
{ 0x8, 0x60 },
{ 0x9, 0x60 },
{ 0xa, 0x60 },
{ 0xb, 0x80 },
{ 0xc, 0x00 },
{ 0xd, 0x00 },
{ 0xe, 0x00 },
{ 0xf, 0x40 },
{ 0x10, 0x80 },
{ 0x11, 0x77 },
{ 0x12, 0x6a },
{ 0x13, 0x69 },
{ 0x14, 0x6a },
{ 0x15, 0x69 },
{ 0x16, 0x00 },
{ 0x17, 0x00 },
{ 0x18, 0x00 },
{ 0x19, 0x00 },
{ 0x1a, 0x00 },
{ 0x1b, 0x00 },
{ 0x1c, 0x00 },
{ 0x1d, 0x00 },
{ 0x1e, 0x00 },
{ 0x1f, 0x00 },
{ 0x20, 0x00 },
{ 0x21, 0x00 },
{ 0x22, 0x00 },
{ 0x23, 0x00 },
{ 0x24, 0x00 },
{ 0x25, 0x00 },
{ 0x26, 0x00 },
{ 0x27, 0x2d },
{ 0x28, 0xc0 },
{ 0x2b, 0x00 },
{ 0x2c, 0x0c },
};
/* regulator power supply names */
static const char *sta32x_supply_names[] = {
"Vdda", /* analog supply, 3.3VV */
"Vdd3", /* digital supply, 3.3V */
"Vcc" /* power amp spply, 10V - 36V */
};
/* codec private data */
struct sta32x_priv {
struct regmap *regmap;
struct regulator_bulk_data supplies[ARRAY_SIZE(sta32x_supply_names)];
struct snd_soc_codec *codec;
struct sta32x_platform_data *pdata;
unsigned int mclk;
unsigned int format;
u32 coef_shadow[STA32X_COEF_COUNT];
struct delayed_work watchdog_work;
int shutdown;
};
static const DECLARE_TLV_DB_SCALE(mvol_tlv, -12700, 50, 1);
static const DECLARE_TLV_DB_SCALE(chvol_tlv, -7950, 50, 1);
static const DECLARE_TLV_DB_SCALE(tone_tlv, -120, 200, 0);
static const char *sta32x_drc_ac[] = {
"Anti-Clipping", "Dynamic Range Compression" };
static const char *sta32x_auto_eq_mode[] = {
"User", "Preset", "Loudness" };
static const char *sta32x_auto_gc_mode[] = {
"User", "AC no clipping", "AC limited clipping (10%)",
"DRC nighttime listening mode" };
static const char *sta32x_auto