// SPDX-License-Identifier: GPL-2.0-or-later
/*
* Analog Devices ADAU1373 Audio Codec drive
*
* Copyright 2011 Analog Devices Inc.
* Author: Lars-Peter Clausen <lars@metafoo.de>
*/
#include <linux/module.h>
#include <linux/init.h>
#include <linux/delay.h>
#include <linux/pm.h>
#include <linux/i2c.h>
#include <linux/slab.h>
#include <linux/gcd.h>
#include <sound/core.h>
#include <sound/pcm.h>
#include <sound/pcm_params.h>
#include <sound/tlv.h>
#include <sound/soc.h>
#include <sound/adau1373.h>
#include "adau1373.h"
#include "adau-utils.h"
struct adau1373_dai {
unsigned int clk_src;
unsigned int sysclk;
bool enable_src;
bool master;
};
struct adau1373 {
struct regmap *regmap;
struct adau1373_dai dais[3];
};
#define ADAU1373_INPUT_MODE 0x00
#define ADAU1373_AINL_CTRL(x) (0x01 + (x) * 2)
#define ADAU1373_AINR_CTRL(x) (0x02 + (x) * 2)
#define ADAU1373_LLINE_OUT(x) (0x9 + (x) * 2)
#define ADAU1373_RLINE_OUT(x) (0xa + (x) * 2)
#define ADAU1373_LSPK_OUT 0x0d
#define ADAU1373_RSPK_OUT 0x0e
#define ADAU1373_LHP_OUT 0x0f
#define ADAU1373_RHP_OUT 0x10
#define ADAU1373_ADC_GAIN 0x11
#define ADAU1373_LADC_MIXER 0x12
#define ADAU1373_RADC_MIXER 0x13
#define ADAU1373_LLINE1_MIX 0x14
#define ADAU1373_RLINE1_MIX 0x15
#define ADAU1373_LLINE2_MIX 0x16
#define ADAU1373_RLINE2_MIX 0x17
#define ADAU1373_LSPK_MIX 0x18
#define ADAU1373_RSPK_MIX 0x19
#define ADAU1373_LHP_MIX 0x1a
#define ADAU1373_RHP_MIX 0x1b
#define ADAU1373_EP_MIX 0x1c
#define ADAU1373_HP_CTRL 0x1d
#define ADAU1373_HP_CTRL2 0x1e
#define ADAU1373_LS_CTRL 0x1f
#define ADAU1373_EP_CTRL 0x21
#define ADAU1373_MICBIAS_CTRL1 0x22
#define ADAU1373_MICBIAS_CTRL2 0x23
#define ADAU1373_OUTPUT_CTRL 0x24
#define ADAU1373_PWDN_CTRL1 0x25
#define ADAU1373_PWDN_CTRL2 0x26
#define ADAU1373_PWDN_CTRL3 0x27
#define ADAU1373_DPLL_CTRL(x) (0x28 + (x) * 7)
#define ADAU1373_PLL_CTRL1(x) (0x29 + (x) * 7)
#define ADAU1373_PLL_CTRL2(x) (0x2a + (x) * 7)
#define ADAU1373_PLL_CTRL3(x) (0x2b + (x) * 7)
#define ADAU1373_PLL_CTRL4(x) (0x2c + (x) * 7)
#define ADAU1373_PLL_CTRL5(x) (0x2d + (x) * 7)
#define ADAU1373_PLL_CTRL6(x) (0x2e + (x) * 7)
#define ADAU1373_HEADDECT 0x36
#define ADAU1373_ADC_DAC_STATUS 0x37
#define ADAU1373_ADC_CTRL 0x3c
#define ADAU1373_DAI(x) (0x44 + (x))
#define ADAU1373_CLK_SRC_DIV(x) (0x40 + (x) * 2)
#define ADAU1373_BCLKDIV(x) (0x47 + (x))
#define ADAU1373_SRC_RATIOA(x) (0x4a + (x) * 2)
#define ADAU1373_SRC_RATIOB(x) (0x4b + (x) * 2)
#define ADAU1373_DEEMP_CTRL 0x50
#define ADAU1373_SRC_DAI_CTRL(x) (0x51 + (x))
#define ADAU1373_DIN_MIX_CTRL(x) (0x56 + (x))
#define ADAU1373_DOUT_MIX_CTRL(x) (0x5b + (x))
#define ADAU1373_DAI_PBL_VOL(x) (0x62 + (x) * 2)
#define ADAU1373_DAI_PBR_VOL(x) (0x63 + (x) * 2)
#define ADAU1373_DAI_RECL_VOL(x) (0x68 + (x) * 2)
#define ADAU1373_DAI_RECR_VOL(x) (0x69 + (x) * 2)
#define ADAU1373_DAC1_PBL_VOL 0x6e
#define ADAU1373_DAC1_PBR_VOL 0x6f
#define ADAU1373_DAC2_PBL_VOL 0x70
#define ADAU1373_DAC2_PBR_VOL 0x71
#define ADAU1373_ADC_RECL_VOL 0x72
#define ADAU1373_ADC_RECR_VOL 0x73
#define ADAU1373_DMIC_RECL_VOL 0x74
#define ADAU1373_DMIC_RECR_VOL 0x75
#define ADAU1373_VOL_GAIN1 0x76
#define ADAU1373_VOL_GAIN2 0x77
#define ADAU1373_VOL_GAIN3 0x78
#define ADAU1373_HPF_CTRL 0x7d
#define ADAU1373_BASS1 0x7e
#define ADAU1373_BASS2 0x7f
#define ADAU1373_DRC(x) (0x80 + (x) * 0x10)
#define ADAU1373_3D_CTRL1 0xc0
#define ADAU1373_3D_CTRL2 0xc1
#define ADAU1373_FDSP_SEL1 0xdc
#define ADAU1373_FDSP_SEL2 0xdd
#define ADAU1373_FDSP_SEL3 0xde
#define ADAU1373_FDSP_SEL4 0xdf
#define ADAU1373_DIGMICCTRL 0xe2
#define ADAU1373_DIGEN 0xeb
#define ADAU1373_SOFT_RESET 0xff
#define ADAU1373_PLL_CTRL6_DPLL_BYPASS BIT(1)
#define ADAU1373_PLL_CTRL6_PLL_EN BIT(0)
#define ADAU1373_DAI_INVERT_BCLK BIT(7)
#define ADAU1373_DAI_MASTER BIT(6)
#define ADAU1373_DAI_INVERT_LRCLK BIT(4)
#define ADAU1373_DAI_WLEN_16 0x0
#define ADAU1373_DAI_WLEN_20 0x4
#define ADAU1373_DAI_WLEN_24 0x8
#define ADAU1373_DAI_WLEN_32 0xc
#define ADAU1373_DAI_WLEN_MASK 0xc
#define ADAU1373_DAI_FORMAT_RIGHT_J 0x0
#define ADAU1373_DAI_FORMAT_LEFT_J 0x1
#define ADAU1373_DAI_FORMAT_I2S 0x2
#define ADAU1373_DAI_FORMAT_DSP 0x3
#define ADAU1373_BCLKDIV_SOURCE BIT(5)
#define ADAU1373_BCLKDIV_SR_MASK (0x07 << 2)
#define ADAU1373_BCLKDIV_BCLK_MASK 0x03
#define ADAU1373_BCLKDIV_32 0x03
#define ADAU1373_BCLKDIV_64 0x02
#define ADAU1373_BCLKDIV_128 0x01
#define ADAU1373_BCLKDIV_256 0x00
#define ADAU1373_ADC_CTRL_PEAK_DETECT BIT(0)
#define ADAU1373_ADC_CTRL_RESET BIT(1)
#define ADAU1373_ADC_CTRL_RESET_FORCE BIT(2)
#define ADAU1373_OUTPUT_CTRL_LDIFF BIT(3)
#define ADAU1373_OUTPUT_CTRL_LNFBEN BIT(2)
#define ADAU1373_PWDN_CTRL3_PWR_EN BIT(0)
#define ADAU1373_EP_CTRL_MICBIAS1_OFFSET 4
#define ADAU1373_EP_CTRL_MICBIAS2_OFFSET 2
static const struct reg_default adau1373_reg_defaults[] = {
{ ADAU1373_INPUT_MODE, 0x00 },
{ ADAU1373_AINL_CTRL(0), 0x00 },
{ ADAU1373_AINR_CTRL(0), 0x00 },
{ ADAU1373_AINL_CTRL(1), 0x00 },
{ ADAU1373_AINR_CTRL(1), 0x00 },
{ ADAU1373_AINL_CTRL(2), 0x00 },
{ ADAU1373_AINR_CTRL(2), 0x00 },
{ ADAU1373_AINL_CTRL(3), 0x00 },
{ ADAU1373_AINR_CTRL(3), 0x00 },
{ ADAU1373_LLINE_OUT(0), 0x00 },
{ ADAU1373_RLINE_OUT(0), 0x00 },
{ ADAU1373_LLINE_OUT(1), 0x00 },
{ ADAU1373_RLINE_OUT(1), 0x00 },
{ ADAU1373_LSPK_OUT, 0x00 },
{ ADAU1373_RSPK_OUT, 0x00 },
{ ADAU1373_LHP_OUT, 0x00 },
{ ADAU1373_RHP_OUT, 0x00 },
{ ADAU1373_ADC_GAIN, 0x00 },
{ ADAU1373_LADC_MIXER, 0x00 },
{ ADAU1373_RADC_MIXER, 0x00 },
{ ADAU1373_LLINE1_MIX, 0x00 },
{ ADAU1373_RLINE1_MIX, 0x00 },
{ ADAU1373_LLINE2_MIX, 0x00 },
{ ADAU1373_RLINE2_MIX, 0x00 },
{ ADAU1373_LSPK_MIX, 0x00 },
{ ADAU1373_RSPK_MIX, 0x00 },
{ ADAU1373_LHP_MIX, 0x00 },
{ ADAU1373_RHP_MIX, 0x00 },
{ ADAU1373_EP_MIX, 0x00 },
{ ADAU1373_HP_CTRL, 0x00 },
{ ADAU1373_HP_CTRL2, 0x00 },
{ ADAU1373_LS_CTRL, 0x00 },
{ ADAU1373_EP_CTRL, 0x00 },
{ ADAU1373_MICBIAS_CTRL1, 0x00 },
{ ADAU1373_MICBIAS_CTRL2, 0x00 },
{ ADAU1373_OUTPUT_CTRL, 0x00 },
{ ADAU1373_PWDN_CTRL1, 0x00 },
{ ADAU1373_PWDN_CTRL2, 0x00 },
{ ADAU1373_PWDN_CTRL3, 0x00 },
{ ADAU1373_DPLL_CTRL(0), 0x00 },
{ ADAU1373_PLL_CTRL1(0), 0x00 },
{ ADAU1373_PLL_CTRL2(0), 0x00 },
{ ADAU1373_PLL_CTRL3(0), 0x00 },
{ ADAU1373_PLL_CTRL4(0), 0x00 },
{ ADAU1373_PLL_CTRL5(0), 0x00 },
{ ADAU1373_PLL_CTRL6(0), 0x02 },
{ ADAU1373_DPLL_CTRL(1), 0x00 },
{ ADAU1373_PLL_CTRL1(1), 0x00 },
{ ADAU1373_PLL_CTRL2(1), 0x00 },
{ ADAU1373_PLL_CTRL3(1), 0x00 },
{ ADAU1373_PLL_CTRL4(1), 0x00 },
{ ADAU1373_PLL_CTRL5(1), 0x00 },
{ ADAU1373_PLL_CTRL6(1), 0x02 },
{ ADAU1373_HEADDECT, 0x00 },
{ ADAU1373_ADC_CTRL, 0x00 },
{ ADAU1373_CLK_SRC_DIV(0), 0x00 },
{ ADAU1373_CLK_SRC_DIV(1), 0x00 },
{ ADAU1373_DAI(0), 0x0a },
{ ADAU1373_DAI(1), 0x0a },
{ ADAU1373_DAI(2), 0x0a },
{ ADAU1373_BCLKDIV(0), 0x00 },
{ ADAU1373_BCLKDIV(1), 0x00 },
{ ADAU1373_BCLKDIV(2), 0x00 },
{ ADAU1373_SRC_RATIOA(0), 0x00 },
{ ADAU1373_SRC_RATIOB(0), 0x00 },
{ ADAU1373_SRC_RATIOA(1), 0x00 },
{ ADAU1373_SRC_RATIOB(1), 0x00 },
{ ADAU1373_SRC_RATIOA(2), 0x00 },
{ ADAU1373_SRC_RATIOB(2), 0x00 },
{ ADAU1373_DEEMP_CTRL, 0x00 },
{ ADAU1373_SRC_DAI_CTRL(0), 0x08 },
{ ADAU1373_SRC_DAI_CTRL(1), 0x08 },
{ ADAU1373_SRC_DAI_CTRL(2), 0x08 },
{ ADAU1373_DIN_MIX_CTRL(0), 0x00 },
{ ADAU1373_DIN_MIX_CTRL(1), 0x00 },
{ ADAU1373_DIN_MIX_CTRL(2), 0x00 },
{ ADAU1373_DIN_MIX_CTRL(3), 0x00 },
{ ADAU1373_DIN_MIX_CTRL(4), 0x00 },
{ ADAU1373_DOUT_MIX_CTRL(0), 0x00 },
{ ADAU1373_DOUT_MIX_CTRL(1), 0x00 },
{ ADAU1373_DOUT_MIX_CTRL(2), 0x00 },
{ ADAU1373_DOUT_MIX_CTRL(3), 0x00 },
{ ADAU1373_DOUT_MIX_CTRL(4), 0x00 },
{ ADAU1373_DAI_PBL_VOL(0), 0x00 },
{ ADAU1373_DAI_PBR_VOL(0), 0x00 },
{ ADAU1373_DAI_PBL_VOL(1), 0x00 },
{ ADAU1373_DAI_PBR_VOL(1), 0x00 },
{ ADAU1373_DAI_PBL_VOL(2), 0x00 },
{ ADAU1373_DAI_PBR_VOL(2), 0x00 },
|