// SPDX-License-Identifier: GPL-2.0-only
/*
* wm8961.c -- WM8961 ALSA SoC Audio driver
*
* Copyright 2009-10 Wolfson Microelectronics, plc
*
* Author: Mark Brown
*
* Currently unimplemented features:
* - ALC
*/
#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/slab.h>
#include <sound/core.h>
#include <sound/pcm.h>
#include <sound/pcm_params.h>
#include <sound/soc.h>
#include <sound/initval.h>
#include <sound/tlv.h>
#include "wm8961.h"
#define WM8961_MAX_REGISTER 0xFC
static const struct reg_default wm8961_reg_defaults[] = {
{ 0, 0x009F }, /* R0 - Left Input volume */
{ 1, 0x009F }, /* R1 - Right Input volume */
{ 2, 0x0000 }, /* R2 - LOUT1 volume */
{ 3, 0x0000 }, /* R3 - ROUT1 volume */
{ 4, 0x0020 }, /* R4 - Clocking1 */
{ 5, 0x0008 }, /* R5 - ADC & DAC Control 1 */
{ 6, 0x0000 }, /* R6 - ADC & DAC Control 2 */
{ 7, 0x000A }, /* R7 - Audio Interface 0 */
{ 8, 0x01F4 }, /* R8 - Clocking2 */
{ 9, 0x0000 }, /* R9 - Audio Interface 1 */
{ 10, 0x00FF }, /* R10 - Left DAC volume */
{ 11, 0x00FF }, /* R11 - Right DAC volume */
{ 14, 0x0040 }, /* R14 - Audio Interface 2 */
{ 17, 0x007B }, /* R17 - ALC1 */
{ 18, 0x0000 }, /* R18 - ALC2 */
{ 19, 0x0032 }, /* R19 - ALC3 */
{ 20, 0x0000 }, /* R20 - Noise Gate */
{ 21, 0x00C0 }, /* R21 - Left ADC volume */
{ 22, 0x00C0 }, /* R22 - Right ADC volume */
{ 23, 0x0120 }, /* R23 - Additional control(1) */
{ 24, 0x0000 }, /* R24 - Additional control(2) */
{ 25, 0x0000 }, /* R25 - Pwr Mgmt (1) */
{ 26, 0x0000 }, /* R26 - Pwr Mgmt (2) */
{ 27, 0x0000 }, /* R27 - Additional Control (3) */
{ 28, 0x0000 }, /* R28 - Anti-pop */
{ 30, 0x005F }, /* R30 - Clocking 3 */
{ 32, 0x0000 }, /* R32 - ADCL signal path */
{ 33, 0x0000 }, /* R33 - ADCR signal path */
{ 40, 0x0000 }, /* R40 - LOUT2 volume */
{ 41, 0x0000 }, /* R41 - ROUT2 volume */
{ 47, 0x0000 }, /* R47 - Pwr Mgmt (3) */
{ 48, 0x0023 }, /* R48 - Additional Control (4) */
{ 49, 0x0000 }, /* R49 - Class D Control 1 */
{ 51, 0x0003 }, /* R51 - Class D Control 2 */
{ 56, 0x0106 }, /* R56 - Clocking 4 */
{ 57, 0x0000 }, /* R57 - DSP Sidetone 0 */
{ 58, 0x0000 }, /* R58 - DSP Sidetone 1 */
{ 60, 0x0000 }, /* R60 - DC Servo 0 */
{ 61, 0x0000 }, /* R61 - DC Servo 1 */
{ 63, 0x015E }, /* R63 - DC Servo 3 */
{ 65, 0x0010 }, /* R65 - DC Servo 5 */
{ 68, 0x0003 }, /* R68 - Analogue PGA Bias */
{ 69, 0x0000 }, /* R69 - Analogue HP 0 */
{ 71, 0x01FB }, /* R71 - Analogue HP 2 */
{ 72, 0x0000 }, /* R72 - Charge Pump 1 */
{ 82, 0x0000 }, /* R82 - Charge Pump B */
{ 87, 0x0000 }, /* R87 - Write Sequencer 1 */
{ 88, 0x0000 }, /* R88 - Write Sequencer 2 */
{ 89, 0x0000 }, /* R89 - Write Sequencer 3 */
{ 90, 0x0000 }, /* R90 - Write Sequencer 4 */
{ 91, 0x0000 }, /* R91 - Write Sequencer 5 */
{ 92, 0x0000 }, /* R92 - Write Sequencer 6 */
{ 93, 0x0000 }, /* R93 - Write Sequencer 7 */
{ 252, 0x0001 }, /* R252 - General test 1 */
};
struct wm8961_priv {
struct regmap *regmap;
int sysclk;
};
static bool wm8961_volatile(struct device *dev, unsigned int reg)
{
switch (reg) {
case WM8961_SOFTWARE_RESET:
case WM8961_WRITE_SEQUENCER_7:
case WM8961_DC_SERVO_1:
return true;
default:
return false;
}
}
static bool wm8961_readable(struct device *dev, unsigned int reg)
{
switch (reg) {
case WM8961_LEFT_INPUT_VOLUME:
case WM8961_RIGHT_INPUT_VOLUME:
case WM8961_LOUT1_VOLUME:
case WM8961_ROUT1_VOLUME:
case WM8961_CLOCKING1:
case WM8961_ADC_DAC_CONTROL_1:
case WM8961_ADC_DAC_CONTROL_2:
case WM8961_AUDIO_INTERFACE_0:
case WM8961_CLOCKING2:
case WM8961_AUDIO_INTERFACE_1:
case WM8961_LEFT_DAC_VOLUME:
case WM8961_RIGHT_DAC_VOLUME:
case WM8961_AUDIO_INTERFACE_2:
case WM8961_SOFTWARE_RESET:
case