kernel_samsung_a53x/sound/soc/codecs/rt5691.c
2024-06-15 16:02:09 -03:00

4548 lines
124 KiB
C
Executable file

// SPDX-License-Identifier: GPL-2.0-only
//
// rt5691.c -- RT5691 ALSA SoC audio component driver
//
// Copyright 2022 Realtek Semiconductor Corp.
// Author: Oder Chiou <oder_chiou@realtek.com>
//
#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/spi/spi.h>
#include <linux/acpi.h>
#include <linux/gpio.h>
#include <linux/of_gpio.h>
#include <linux/mutex.h>
#include <linux/regulator/consumer.h>
#include <linux/slab.h>
#include <linux/cdev.h>
#include <linux/miscdevice.h>
#include <linux/iio/consumer.h>
#ifdef CONFIG_SWITCH
#include <linux/switch.h>
#endif
#include <sound/core.h>
#include <sound/pcm.h>
#include <sound/pcm_params.h>
#include <sound/jack.h>
#include <sound/soc.h>
#include <sound/soc-dapm.h>
#include <sound/initval.h>
#include <sound/tlv.h>
#include <sound/rt5691.h>
#ifdef CONFIG_DEBUG_FS
#include <linux/debugfs.h>
#endif
#include "rt5691.h"
#ifdef CONFIG_SWITCH
static struct switch_dev rt5691_headset_switch = {
.name = "h2w",
};
#endif
#ifdef CONFIG_DEBUG_FS
static struct dentry *rt5691_debugfs_root;
#endif
static struct {
int imp;
int gain;
} rt5691_hp_gain_table[] = {
{0x000d, 0},
{0x0019, 0},
{0x0035, 0},
{0x0067, 0},
{0xffff, 0},
};
static const struct reg_default rt5691_reg[] = {
{0x0000, 0x0000},
{0x0003, 0xc000},
{0x0004, 0x0000},
{0x0005, 0x0000},
{0x0006, 0x0000},
{0x000c, 0x1010},
{0x000d, 0x1000},
{0x000f, 0x0002},
{0x0011, 0x0000},
{0x0024, 0x0000},
{0x0026, 0xc0c0},
{0x0027, 0xc0c0},
{0x0029, 0x8080},
{0x002a, 0xa0a8},
{0x002b, 0x80ff},
{0x0030, 0x0000},
{0x0031, 0x0000},
{0x004b, 0x00c0},
{0x004c, 0x0000},
{0x004d, 0x0000},
{0x0050, 0x0080},
{0x0051, 0x0000},
{0x0060, 0x0003},
{0x0061, 0x0000},
{0x0062, 0x2408},
{0x0063, 0x0000},
{0x0064, 0x0000},
{0x0065, 0x0009},
{0x0066, 0x0000},
{0x0067, 0x2f00},
{0x006b, 0x0000},
{0x006c, 0x0000},
{0x0080, 0x0150},
{0x0081, 0x0000},
{0x0082, 0x0000},
{0x0083, 0x0122},
{0x0084, 0x0300},
{0x0085, 0x0000},
{0x0086, 0x0000},
{0x0087, 0x0122},
{0x0088, 0x0300},
{0x008e, 0x4000},
{0x008f, 0xaa81},
{0x0090, 0x7680},
{0x0091, 0x5c18},
{0x0092, 0x0425},
{0x0094, 0x008f},
{0x0095, 0x4000},
{0x009f, 0x0000},
{0x00b6, 0x0000},
{0x00b7, 0x0000},
{0x00b8, 0x0000},
{0x00b9, 0x0000},
{0x00ba, 0x0002},
{0x00bb, 0x0000},
{0x00be, 0x0000},
{0x00d0, 0x0000},
{0x00d1, 0x6666},
{0x00d2, 0xa6aa},
{0x00d3, 0x6666},
{0x00d4, 0xa6aa},
{0x00d5, 0x6666},
{0x00d6, 0xa6aa},
{0x00f6, 0x0000},
{0x00fa, 0x0000},
{0x00fb, 0x0000},
{0x00fc, 0x0000},
{0x00fd, 0x0000},
{0x00fe, 0x10ec},
{0x00ff, 0x1091},
{0x0100, 0x2510},
{0x0101, 0x2510},
{0x0102, 0x2510},
{0x0105, 0x6666},
{0x0106, 0x6646},
{0x0107, 0x666a},
{0x0108, 0x6600},
{0x0109, 0xaaa0},
{0x010b, 0x6600},
{0x010c, 0x6666},
{0x010d, 0x6666},
{0x010e, 0x6666},
{0x010f, 0x6666},
{0x0110, 0x0800},
{0x0111, 0x5800},
{0x0112, 0x5800},
{0x0117, 0x0001},
{0x0118, 0x0040},
{0x0119, 0x0040},
{0x011a, 0x0041},
{0x0125, 0x8120},
{0x013a, 0x3080},
{0x013b, 0x3080},
{0x013c, 0x3080},
{0x013d, 0xa490},
{0x013e, 0xa490},
{0x013f, 0xa490},
{0x0145, 0x0000},
{0x0146, 0x0000},
{0x0147, 0x0000},
{0x0148, 0x0000},
{0x0149, 0x0000},
{0x0194, 0x0000},
{0x0198, 0x0000},
{0x01a0, 0x00e4},
{0x01a1, 0x00de},
{0x01cb, 0x0000},
{0x01cc, 0x5757},
{0x01cd, 0x5757},
{0x01ce, 0x5757},
{0x01cf, 0x5757},
{0x01d0, 0x5757},
{0x01d1, 0x5757},
{0x01d2, 0x5757},
{0x01d3, 0x5757},
{0x01d4, 0x5757},
{0x01d5, 0x5757},
{0x01db, 0x0000},
{0x01dd, 0x1e00},
{0x01f0, 0x8007},
{0x01f1, 0x0000},
{0x0200, 0x0101},
{0x0201, 0x0101},
{0x0202, 0x0001},
{0x0203, 0x1101},
{0x0205, 0x0000},
{0x0206, 0x0101},
{0x0207, 0x0004},
{0x0208, 0x0000},
{0x0209, 0x2000},
{0x020a, 0x0000},
{0x020b, 0x0000},
{0x020c, 0x0000},
{0x020d, 0x0000},
{0x020e, 0x0001},
{0x020f, 0x0000},
{0x0210, 0x0001},
{0x0211, 0x0001},
{0x0212, 0x0003},
{0x0213, 0x0000},
{0x0214, 0x0000},
{0x0215, 0x0000},
{0x0216, 0x0000},
{0x0217, 0x0002},
{0x0218, 0x0001},
{0x0219, 0x0000},
{0x02fc, 0x0000},
{0x02fd, 0x0000},
{0x02fe, 0x0000},
{0x02ff, 0x0000},
{0x0300, 0x5757},
{0x0301, 0x0039},
{0x0400, 0x0000},
{0x0401, 0x01fe},
{0x0402, 0x0000},
{0x0403, 0x0000},
{0x0404, 0x0000},
{0x0405, 0x0000},
{0x0406, 0x0000},
{0x0407, 0x8000},
{0x0500, 0x0000},
{0x0600, 0x0000},
{0x0700, 0x0000},
{0x0701, 0x0000},
{0x0702, 0x0000},
{0x0703, 0x0000},
{0x0704, 0x00c0},
{0x0705, 0x00a8},
{0x0706, 0x0031},
{0x0707, 0x0031},
{0x0708, 0x0031},
{0x0709, 0x0031},
{0x070a, 0x0031},
{0x070b, 0x0031},
{0x070c, 0x0000},
{0x070d, 0x0000},
{0x070e, 0x0040},
{0x070f, 0x00aa},
{0x0710, 0x0000},
{0x0711, 0x0031},
{0x0712, 0x0031},
{0x0713, 0x0031},
{0x0714, 0x0031},
{0x0715, 0x0031},
{0x0716, 0x0031},
{0x0717, 0x0031},
{0x0718, 0x0031},
{0x0719, 0x0000},
{0x071a, 0x00ff},
{0x071b, 0x00ff},
{0x0b00, 0x0000},
{0x0c00, 0x001c},
{0x0d00, 0x0001},
{0x0d01, 0x000a},
{0x0d02, 0x0000},
{0x0d03, 0x002f},
{0x0d04, 0x002f},
{0x0d05, 0x00f3},
{0x0d06, 0x0000},
{0x0d07, 0x0023},
{0x0d08, 0x0000},
{0x0e00, 0x0001},
{0x0e01, 0x000a},
{0x0e02, 0x0000},
{0x0e03, 0x002f},
{0x0e04, 0x002f},
{0x0e05, 0x00f3},
{0x0e06, 0x0000},
{0x0e07, 0x0023},
{0x0e08, 0x0000},
{0x0f00, 0x0000},
{0x0f01, 0x0000},
{0x0f02, 0x0000},
{0x0f03, 0x0000},
{0x0f04, 0x0000},
{0x0f05, 0x0000},
{0x0f06, 0x0000},
{0x0f07, 0x0000},
{0x0f08, 0x0000},
{0x0f09, 0x0000},
{0x0f0a, 0x0000},
{0x0f0b, 0x0000},
{0x0f0c, 0x0000},
{0x0f11, 0x0000},
{0x0f12, 0x0000},
{0x0f13, 0x0000},
{0x0f14, 0x0000},
{0x0f15, 0x0000},
{0x0f16, 0x0000},
{0x0f17, 0x0000},
{0x0f18, 0x0000},
{0x0f19, 0x0000},
{0x0f1a, 0x0000},
{0x0f1b, 0x0000},
{0x0f1c, 0x0000},
{0x1000, 0x0000},
{0x1010, 0x8000},
{0x1011, 0x8000},
{0x1020, 0x0200},
{0x1021, 0x0000},
{0x1022, 0x0000},
{0x1023, 0x0000},
{0x1024, 0x0000},
{0x1025, 0x0000},
{0x1026, 0x0000},
{0x1027, 0x0000},
{0x1028, 0x0000},
{0x1029, 0x0000},
{0x1030, 0x0200},
{0x1031, 0x0000},
{0x1032, 0x0000},
{0x1033, 0x0000},
{0x1034, 0x0000},
{0x1035, 0x0000},
{0x1036, 0x0000},
{0x1037, 0x0000},
{0x1038, 0x0000},
{0x1039, 0x0000},
{0x1100, 0x00a6},
{0x1101, 0x04c3},
{0x1102, 0x27c8},
{0x1103, 0xbf50},
{0x1104, 0x0045},
{0x1105, 0x0007},
{0x1106, 0x7418},
{0x1107, 0x0401},
{0x1108, 0x0000},
{0x1109, 0x0010},
{0x110a, 0x1010},
{0x1200, 0x0000},
{0x1201, 0x0000},
{0x1202, 0x0000},
{0x1210, 0x8000},
{0x1211, 0x8000},
{0x1212, 0x8000},
{0x1213, 0x8000},
{0x1214, 0x8000},
{0x1215, 0x8000},
{0x1216, 0x8000},
{0x1217, 0x8000},
{0x1218, 0x8000},
{0x1219, 0x8000},
{0x1220, 0x0000},
{0x1221, 0x0000},
{0x1222, 0x0000},
{0x1223, 0x0000},
{0x1224, 0x0000},
{0x1225, 0x0000},
{0x1226, 0x0000},
{0x1227, 0x0000},
{0x1230, 0x0000},
{0x1231, 0x0000},
{0x1232, 0x0000},
{0x1233, 0x0000},
{0x1234, 0x0000},
{0x1235, 0x0000},
{0x1240, 0x0000},
{0x1241, 0x0000},
{0x1242, 0x0000},
{0x1243, 0x0000},
{0x1244, 0x0000},
{0x1245, 0x0000},
{0x1250, 0x0000},
{0x1251, 0x0000},
{0x1252, 0x0000},
{0x1253, 0x0000},
{0x1254, 0x0000},
{0x1255, 0x0000},
{0x1260, 0x0800},
{0x1261, 0x0800},
{0x1262, 0x0800},
{0x1263, 0x0800},
{0x1300, 0x3001},
{0x1302, 0x5981},
{0x1304, 0x0fff},
{0x1306, 0x0000},
{0x1308, 0x0fff},
{0x130a, 0x0fff},
{0x130c, 0x0040},
{0x130e, 0x0006},
{0x1320, 0x0b68},
{0x1322, 0x366b},
{0x1324, 0x1415},
{0x1326, 0x00a9},
{0x1328, 0x0fff},
{0x132a, 0x0fff},
{0x132c, 0x0000},
{0x132e, 0x0000},
{0x1400, 0x0002},
{0x1700, 0x4000},
{0x1701, 0x0000},
{0x1702, 0x000f},
{0x1703, 0x5000},
{0x1800, 0x0025},
{0x1801, 0x4000},
{0x1802, 0x0000},
{0x1803, 0x00ff},
{0x1900, 0x3018},
{0x1a00, 0x3018},
{0x1b00, 0x6000},
{0x1b01, 0x007f},
{0x1b02, 0x007f},
{0x1b03, 0x0000},
{0x1b04, 0x0200},
{0x1b05, 0x007f},
{0x1b06, 0xffff},
{0x1b07, 0x0000},
{0x2000, 0x0200},
{0x2001, 0x0000},
{0x2002, 0x0000},
{0x2400, 0x0038},
{0x2b00, 0x0000},
{0x2b01, 0x0000},
{0x2b02, 0x1ad0},
{0x2b03, 0x0004},
{0x2b04, 0x4000},
{0x2b05, 0x0000},
{0x2b06, 0x07ff},
{0x2b07, 0x0000},
{0x2b08, 0x0000},
{0x2b09, 0x000a},
{0x2b0a, 0x0004},
{0x2b0b, 0x0004},
{0x2b0c, 0x0004},
{0x2b0d, 0x0004},
{0x2b0e, 0x0004},
{0x2b10, 0x0000},
{0x2b11, 0x000a},
{0x2b12, 0x000a},
{0x2b13, 0x000a},
{0x2b14, 0x0000},
{0x2b15, 0x0000},
{0x2b16, 0x0000},
{0x2b17, 0x0000},
{0x2c00, 0x2000},
{0x2c01, 0x0000},
{0x2c02, 0x0000},
{0x2c03, 0x0000},
{0x2c04, 0x0017},
{0x2c05, 0x004b},
{0x2c06, 0x03e8},
{0x2c07, 0x0000},
{0x2c08, 0x0000},
{0x2c09, 0x0400},
{0x2c0a, 0xb5b6},
{0x2c0b, 0x9124},
{0x2c0c, 0x4924},
{0x2c0d, 0x0009},
{0x2c0e, 0x0018},
{0x2c0f, 0x002a},
{0x2c10, 0x004c},
{0x2c11, 0x0097},
{0x2c12, 0x01c3},
{0x2c13, 0x03e9},
{0x2c14, 0x1389},
{0x2c15, 0xc351},
{0x2c16, 0x02a0},
{0x2c17, 0x0b0f},
{0x2c18, 0x0000},
{0x2c19, 0x0000},
{0x2c1a, 0x0000},
{0x2c1b, 0x0000},
{0x2c1c, 0x0000},
{0x2c1d, 0x0000},
{0x2c1e, 0x0000},
{0x2d00, 0x40af},
{0x2d01, 0x0702},
{0x2d02, 0x0000},
{0x2f00, 0x000b},
{0x3000, 0x4650},
{0x3001, 0x0080},
{0x3002, 0x0080},
{0x3003, 0x0800},
{0x3004, 0x0000},
{0x3005, 0x0000},
{0x3006, 0x1111},
{0x3007, 0x0001},
{0x3008, 0x0000},
{0x300a, 0x0300},
{0x3100, 0x4ec0},
{0x3101, 0x0080},
{0x3102, 0x0080},
{0x3103, 0x0800},
{0x3104, 0x0000},
{0x3105, 0x0000},
{0x3106, 0x0000},
{0x3107, 0x000f},
{0x3108, 0x000f},
{0x3109, 0x0001},
{0x3200, 0x0200},
{0x3201, 0x2995},
{0x3202, 0x0000},
{0x3203, 0x07ff},
{0x3204, 0x0004},
{0x3205, 0x0004},
{0x3206, 0xca0a},
{0x3207, 0x0004},
{0x3208, 0x000a},
{0x3209, 0x8000},
{0x320a, 0x0007},
{0x320b, 0x0002},
{0x320c, 0x0000},
{0x3300, 0x0084},
{0x3301, 0x00a2},
{0x3302, 0x0073},
{0x3303, 0x00a0},
{0x3304, 0x0002},
{0x3308, 0x0004},
{0x3309, 0x0000},
{0x330a, 0x0002},
{0x330b, 0x004c},
{0x330c, 0x0001},
{0x330d, 0x0002},
{0x330e, 0x0000},
{0x330f, 0x00a3},
{0x3310, 0x0000},
{0x3311, 0x0048},
{0x3312, 0x00f0},
{0x3313, 0x0000},
{0x3314, 0x00c0},
{0x3315, 0x000a},
{0x3316, 0x07ff},
{0x3317, 0x0000},
{0x3400, 0x0200},
{0x3404, 0x0000},
{0x3405, 0x0000},
{0x3406, 0x0000},
{0x3407, 0x0000},
{0x3408, 0x0000},
{0x3409, 0x0000},
{0x340a, 0x0000},
{0x340b, 0x0000},
{0x340c, 0x0000},
{0x340d, 0x0000},
{0x340e, 0x0000},
{0x340f, 0x0000},
{0x3410, 0x0000},
{0x3411, 0x0000},
{0x3412, 0x0000},
{0x3413, 0x0000},
{0x3414, 0x0000},
{0x3415, 0x0000},
{0x3424, 0x0000},
{0x3425, 0x0000},
{0x3426, 0x0000},
{0x3427, 0x0000},
{0x3428, 0x0000},
{0x3429, 0x0000},
{0x342a, 0x0000},
{0x342b, 0x0000},
{0x342c, 0x0000},
{0x342d, 0x0000},
{0x342e, 0x0000},
{0x342f, 0x0000},
{0x3430, 0x0000},
{0x3431, 0x0000},
{0x3432, 0x0000},
{0x3433, 0x0000},
{0x3434, 0x0000},
{0x3435, 0x0000},
{0x3440, 0x6319},
{0x3441, 0x3771},
{0x3800, 0x3d00},
{0x3801, 0x0804},
{0x3802, 0xc100},
{0x3803, 0x0000},
{0x3804, 0x0000},
{0x3805, 0x0000},
{0x3806, 0x0000},
{0x3807, 0x0000},
{0x3808, 0x0000},
{0x3809, 0x0000},
{0x380a, 0x0000},
{0x380b, 0x0000},
{0x380c, 0x0000},
{0x380d, 0x0000},
{0x380e, 0x0000},
{0x3810, 0x0000},
{0x3811, 0x0000},
{0x3812, 0x0000},
{0x3813, 0x0000},
{0x3814, 0x0000},
{0x3815, 0x0000},
{0x3816, 0x0000},
{0x3817, 0x0000},
{0x3818, 0x0000},
{0x3820, 0x7406},
{0x3821, 0x4103},
{0x3822, 0x8000},
{0x3824, 0x0000},
{0x3825, 0x0000},
{0x3827, 0x0000},
{0x3828, 0x0000},
{0x382b, 0x0000},
{0x382c, 0x0000},
{0x3b00, 0x3020},
{0x3b01, 0x3300},
{0x3b02, 0x2200},
{0x3b03, 0x0100},
{0x3c00, 0x0000},
{0x3c01, 0x3300},
{0x3c02, 0x2200},
};
static struct reg_sequence rt5691_init_list[] = {
{RT5691_DEPOP_CTRL_1, 0xf000},
{RT5691_ANLG_BIAS_CTRL_2, 0x3480},
{RT5691_DACL_CTRL_1, 0x1080},
{RT5691_DACR_CTRL_2, 0x1080},
{RT5691_DACM_CTRL_3, 0x1080},
{RT5691_PWR_DIG_2, 0x2008},
{RT5691_STO1_DAC_MIXER_CTRL, 0xa8a8},
{RT5691_AD_DA_MIXER_CTRL, 0x8083},
{RT5691_HP_BEHAVIOR_LOGIC_CTRL_2, 0x0002},
{RT5691_MONO_OUTPUT_CTRL, 0x0010},
{RT5691_STO1_ADC_MIXER_CTRL, 0xf0f0},
{RT5691_STO2_ADC_MIXER_CTRL, 0xf0f0},
{RT5691_COMBO_JACK_CTRL_4, 0x0104},
{RT5691_COMBO_WATER_CTRL_3, 0x0f5f},
{RT5691_COMBO_WATER_CTRL_4, 0x004a},
{RT5691_COMBO_WATER_CTRL_5, 0x07c0},
{RT5691_COMBO_JACK_CTRL_2, 0x0010},
{RT5691_COMBO_JACK_CTRL_3, 0x18e2},
{RT5691_STO_DRE_CTRL_2, 0x0041},
{RT5691_STO_DRE_CTRL_3, 0x040c},
{RT5691_ADC_FILTER_CTRL_3, 0x0090},
{RT5691_ADC_FILTER2_CTRL_3, 0x0090},
{RT5691_HPOUT_CP_CTRL_1, 0x5018},
{RT5691_GPIO_CLK, 0x8000},
{RT5691_ADC_FILTER_CTRL_7, 0x0001},
{RT5691_ADC_FILTER_CTRL_9, 0x0001},
};
static bool rt5691_volatile_register(struct device *dev, unsigned int reg)
{
switch (reg) {
case RT5691_RESET:
case RT5691_INT_ST_1:
case RT5691_VENDOR_ID_2:
case RT5691_VENDOR_ID_1:
case RT5691_DEVICE_ID:
case RT5691_ANLG_READ_STA_324:
case RT5691_GPIO_ST_1:
case RT5691_CLK_SRC_SW_TEST:
case RT5691_MIC_BTN_CTRL_1:
case RT5691_MIC_BTN_CTRL_2:
case RT5691_MIC_BTN_CTRL_13:
case RT5691_MIC_BTN_CTRL_14:
case RT5691_MIC_BTN_CTRL_27:
case RT5691_MIC_BTN_CTRL_28:
case RT5691_DMIC_FLOATING_DET_CTRL_1:
case RT5691_HARM_COMP_OP_1:
case RT5691_DAC_BI_FILTER_CTRL_1:
case RT5691_ALC_PGA_TOP_9:
case RT5691_ALC_PGA_TOP_10:
case RT5691_ALC_PGA_TOP_11:
case RT5691_DAC_EQ_CTRL_3:
case RT5691_ALC_CTRL_13:
case RT5691_ALC_CTRL_14:
case RT5691_ALC_CTRL_15:
case RT5691_ALC_CTRL_16:
case RT5691_SIL_DET_TOP_8:
case RT5691_COMBO_JACK_CTRL_4:
case RT5691_COMBO_JACK_CTRL_7:
case RT5691_COMBO_JACK_CTRL_8:
case RT5691_COMBO_JACK_CTRL_9:
case RT5691_IMP_SENS_CTRL_1:
case RT5691_IMP_SENS_CTRL_8:
case RT5691_IMP_SENS_CTRL_9:
case RT5691_IMP_SENS_CTRL_25:
case RT5691_IMP_SENS_CTRL_26:
case RT5691_IMP_SENS_CTRL_27:
case RT5691_IMP_SENS_CTRL_28:
case RT5691_IMP_SENS_CTRL_29:
case RT5691_IMP_SENS_CTRL_30:
case RT5691_IMP_SENS_CTRL_31:
case RT5691_MONO_DRE_CTRL_5:
case RT5691_MONO_DRE_CTRL_6:
case RT5691_STO_DRE_CTRL_5:
case RT5691_STO_DRE_CTRL_6:
case RT5691_STO_DRE_CTRL_7:
case RT5691_WATER_DET_CTRL_3:
case RT5691_WATER_DET_CTRL_4:
case RT5691_SAR_ADC_DET_CTRL_2:
case RT5691_SAR_ADC_DET_CTRL_3:
case RT5691_SAR_ADC_DET_CTRL_9:
case RT5691_SAR_ADC_DET_CTRL_10:
case RT5691_SAR_ADC_DET_CTRL_19:
case RT5691_SAR_ADC_DET_CTRL_23:
case RT5691_SAR_ADC_DET_CTRL_24:
case RT5691_EFUSE_WRITE_1:
case RT5691_EFUSE_READ_1:
case RT5691_EFUSE_READ_2:
case RT5691_EFUSE_READ_3:
case RT5691_EFUSE_READ_4:
case RT5691_EFUSE_READ_5:
case RT5691_EFUSE_READ_6:
case RT5691_EFUSE_READ_7:
case RT5691_EFUSE_READ_8:
case RT5691_EFUSE_READ_9:
case RT5691_EFUSE_READ_10:
case RT5691_EFUSE_READ_11:
case RT5691_EFUSE_READ_12:
case RT5691_EFUSE_READ_13:
case RT5691_EFUSE_READ_14:
case RT5691_EFUSE_READ_15:
case RT5691_EFUSE_READ_16:
case RT5691_EFUSE_READ_17:
case RT5691_EFUSE_READ_18:
case RT5691_HP_AMP_DET_CTRL_9:
case RT5691_HP_AMP_DET_CTRL_12:
case RT5691_HP_AMP_DET_CTRL_13:
case RT5691_OFFSET_CAL_TOP_9:
case RT5691_OFFSET_CAL_TOP_10:
case RT5691_OFFSET_CAL_TOP_11:
case RT5691_OFFSET_CAL_TOP_12:
case RT5691_OFFSET_CAL_TOP_13:
case RT5691_OFFSET_CAL_TOP_14:
case RT5691_OFFSET_CAL_TOP_15:
case RT5691_OFFSET_CAL_21:
case RT5691_OFFSET_CAL_22:
case RT5691_OFFSET_CAL_30:
case RT5691_OFFSET_CAL_31:
case RT5691_OFFSET_CAL_32:
case RT5691_OFFSET_CAL_33:
return true;
default:
return false;
}
}
static bool rt5691_readable_register(struct device *dev, unsigned int reg)
{
switch (reg) {
case RT5691_RESET:
case RT5691_HP_AMP_CTRL_2:
case RT5691_MONO_OUTPUT_CTRL:
case RT5691_HP_AMP_L_GAIN_CTRL:
case RT5691_HP_AMP_R_GAIN_CTRL:
case RT5691_IN1_IN2_CTRL:
case RT5691_IN3_CTRL:
case RT5691_ZCD_CTRL:
case RT5691_JACK_TYPE_DET_CTRL_2:
case RT5691_ST_MUX_CTRL:
case RT5691_STO1_ADC_MIXER_CTRL:
case RT5691_STO2_ADC_MIXER_CTRL:
case RT5691_AD_DA_MIXER_CTRL:
case RT5691_STO1_DAC_MIXER_CTRL:
case RT5691_MONO_DAC_VOL_CTRL:
case RT5691_FIFO_CTRL:
case RT5691_PDM_OUTPUT_CTRL:
case RT5691_HP_ANLG_OFFSET_CTRL_1:
case RT5691_HP_ANLG_OFFSET_CTRL_2:
case RT5691_HP_ANLG_OFFSET_CTRL_3:
case RT5691_MONO_ANLG_OFFSET_CTRL_1:
case RT5691_MONO_ANLG_OFFSET_CTRL_2:
case RT5691_DMIC_CTRL:
case RT5691_PWR_DIG_1:
case RT5691_PWR_DIG_2:
case RT5691_PWR_ANLG_1:
case RT5691_PWR_ANLG_2:
case RT5691_JD2_CTRL_1:
case RT5691_BGLDO33_CTRL_1:
case RT5691_BGLDO33_CTRL_2:
case RT5691_MCLK_DET_CTRL_1:
case RT5691_MCLK_DET_CTRL_2:
case RT5691_ANLG_LDO_CTRL_1:
case RT5691_PLLA_CTRL_1:
case RT5691_PLLA_CTRL_2:
case RT5691_PLLA_CTRL_3:
case RT5691_PLLA_CTRL_4:
case RT5691_PLLB_CTRL_1:
case RT5691_PLLB_CTRL_2:
case RT5691_PLLB_CTRL_3:
case RT5691_PLLB_CTRL_4:
case RT5691_DEPOP_CTRL_1:
case RT5691_ANLG_BIAS_CTRL_1:
case RT5691_ANLG_BIAS_CTRL_2:
case RT5691_HPOUT_CP_CTRL_1:
case RT5691_HPOUT_CP_CTRL_2:
case RT5691_OSC_CTRL_1:
case RT5691_HP_CAL_CTRL_2:
case RT5691_RC_CLK_CTRL:
case RT5691_IRQ_CTRL_1:
case RT5691_IRQ_CTRL_2:
case RT5691_IRQ_CTRL_3:
case RT5691_IRQ_CTRL_4:
case RT5691_IRQ_CTRL_5:
case RT5691_IRQ_CTRL_6:
case RT5691_INT_ST_1:
case RT5691_HP_AMP_DET_CTRL_1:
case RT5691_HP_AMP_DET_CTRL_2:
case RT5691_HP_AMP_DET_CTRL_3:
case RT5691_HP_AMP_DET_CTRL_4:
case RT5691_HP_AMP_DET_CTRL_5:
case RT5691_HP_AMP_DET_CTRL_6:
case RT5691_HP_AMP_DET_CTRL_7:
case RT5691_JACK_DETECT_CTRL_1:
case RT5691_DIG_MISC_CTRL:
case RT5691_DUMMY_REGISTER_2:
case RT5691_DUMMY_REGISTER_3:
case RT5691_VENDOR_ID_2:
case RT5691_VENDOR_ID_1:
case RT5691_DEVICE_ID:
case RT5691_ANLG_BST1_CTRL_1:
case RT5691_ANLG_BST2_CTRL_2:
case RT5691_ANLG_BST3_CTRL_3:
case RT5691_ANLG_BIAS_CTRL_3:
case RT5691_ANLG_BIAS_CTRL_4:
case RT5691_ANLG_BIAS_CTRL_5:
case RT5691_ANLG_BIAS_CTRL_6:
case RT5691_ANLG_BIAS_CTRL_7:
case RT5691_ANLG_BIAS_CTRL_8:
case RT5691_ANLG_BIAS_CTRL_9:
case RT5691_ANLG_BIAS_CTRL_10:
case RT5691_ANLG_BIAS_CTRL_11:
case RT5691_ANLG_BIAS_CTRL_12:
case RT5691_DACREF_CTRL_1:
case RT5691_CALL_BUF_MIX_CTRL_1:
case RT5691_CALR_BUF_MIX_CTRL_2:
case RT5691_MONO_ANLG_DRE_CTRL_1:
case RT5691_MONO_ANLG_DRE_CTRL_2:
case RT5691_MONO_ANLG_DRE_CTRL_3:
case RT5691_MONO_ANLG_DRE_CTRL_4:
case RT5691_ANLG_BIAS_CTRL_13:
case RT5691_DACL_CTRL_1:
case RT5691_DACR_CTRL_2:
case RT5691_DACM_CTRL_3:
case RT5691_ADC12_CTRL:
case RT5691_ADC34_CTRL:
case RT5691_ADC56_CTRL:
case RT5691_TEST_MODE_CTRL:
case RT5691_GPIO_TEST_MODE3:
case RT5691_GPIO_TEST_MODE4:
case RT5691_GPIO_TEST_MODE5:
case RT5691_GPIO_TEST_MODE6:
case RT5691_SIL_DET_CTRL8:
case RT5691_SIL_DET_CTRL9:
case RT5691_LPF_AD10:
case RT5691_LPF_DMIC11:
case RT5691_HP_IMP_SEN_DIG_CTRL:
case RT5691_HP_IMP_SEN_DIG_CTRL_1:
case RT5691_HP_IMP_SEN_DIG_CTRL_2:
case RT5691_HP_IMP_SEN_DIG_CTRL_3:
case RT5691_HP_IMP_SEN_DIG_CTRL_4:
case RT5691_HP_IMP_SEN_DIG_CTRL_5:
case RT5691_HP_IMP_SEN_DIG_CTRL_6:
case RT5691_HP_IMP_SEN_DIG_CTRL_7:
case RT5691_HP_IMP_SEN_DIG_CTRL_8:
case RT5691_HP_IMP_SEN_DIG_CTRL_9:
case RT5691_HP_IMP_SEN_DIG_CTRL_10:
case RT5691_HP_BEHAVIOR_LOGIC_CTRL_2:
case RT5691_ANLG_READ_STA_324:
case RT5691_I2C_SLAVE_CTRL25:
case RT5691_I2C_SLAVE_CTRL26:
case RT5691_DA_STO1_FILTER_CLK_DIV:
case RT5691_AD_STO1_FILTER_CLK_DIV:
case RT5691_CLK_SEL_RX_FIFO:
case RT5691_CLK_SEL_STO_DAC_PDM_FIFO:
case RT5691_SYS_CLK_SRC:
case RT5691_ADC_AND_DAC_OSR:
case RT5691_I2S_MASTER_CLK:
case RT5691_MCLK_DET_CTRL_3:
case RT5691_PWR_DA_PATH_1:
case RT5691_PWR_DA_PATH_2:
case RT5691_PWR_AD_PATH:
case RT5691_AD_DA_ASRC:
case RT5691_PLL_CTRL_2:
case RT5691_I2S:
case RT5691_TRACKING_CTRL:
case RT5691_CLK_DIV_PDM:
case RT5691_CLK_DIV_DMIC:
case RT5691_EFUSE_CTRL:
case RT5691_EN_SW_CTRL:
case RT5691_GLITCH_FREE_MUX_CTRL:
case RT5691_GPIO_CLK:
case RT5691_RC_CLK:
case RT5691_FRAC_I2S1_MASTER_CTRL_1:
case RT5691_FRAC_I2S1_MASTER_CTRL_2:
case RT5691_FRAC_I2S1_MASTER_CTRL_3:
case RT5691_AD_CLK_GATING_FUNC_1:
case RT5691_AD_CLK_GATING_FUNC_2:
case RT5691_DA_CLK_GATING_FUNC_1:
case RT5691_DA_CLK_GATING_FUNC_2:
case RT5691_HP_IMP_FSOV_GAIN_CTRL_1:
case RT5691_HP_IMP_FSOV_GAIN_CTRL_2:
case RT5691_MULTI_FUNC_PIN_CTRL_1:
case RT5691_GPIO_CTRL_1:
case RT5691_GPIO_CTRL_3:
case RT5691_GPIO_ST_1:
case RT5691_GPIO_PULL_CTRL_1:
case RT5691_PAD_DRIVING_CTRL_1:
case RT5691_PAD_DRIVING_CTRL_5:
case RT5691_PAD_DRIVING_CTRL_6:
case RT5691_SCAN_CTRL_1:
case RT5691_CLK_SRC_SW_TEST:
case RT5691_MIC_BTN_CTRL_1:
case RT5691_MIC_BTN_CTRL_2:
case RT5691_MIC_BTN_CTRL_3:
case RT5691_MIC_BTN_CTRL_4:
case RT5691_MIC_BTN_CTRL_5:
case RT5691_MIC_BTN_CTRL_6:
case RT5691_MIC_BTN_CTRL_7:
case RT5691_MIC_BTN_CTRL_8:
case RT5691_MIC_BTN_CTRL_9:
case RT5691_MIC_BTN_CTRL_10:
case RT5691_MIC_BTN_CTRL_11:
case RT5691_MIC_BTN_CTRL_12:
case RT5691_MIC_BTN_CTRL_13:
case RT5691_MIC_BTN_CTRL_14:
case RT5691_MIC_BTN_CTRL_15:
case RT5691_MIC_BTN_CTRL_16:
case RT5691_MIC_BTN_CTRL_17:
case RT5691_MIC_BTN_CTRL_18:
case RT5691_MIC_BTN_CTRL_19:
case RT5691_MIC_BTN_CTRL_20:
case RT5691_MIC_BTN_CTRL_21:
case RT5691_MIC_BTN_CTRL_22:
case RT5691_MIC_BTN_CTRL_23:
case RT5691_MIC_BTN_CTRL_24:
case RT5691_MIC_BTN_CTRL_25:
case RT5691_MIC_BTN_CTRL_26:
case RT5691_MIC_BTN_CTRL_27:
case RT5691_MIC_BTN_CTRL_28:
case RT5691_DMIC_FLOATING_DET_CTRL_1:
case RT5691_PDM_CTRL_1:
case RT5691_ADC_FILTER_CTRL_1:
case RT5691_ADC_FILTER_CTRL_2:
case RT5691_ADC_FILTER_CTRL_3:
case RT5691_ADC_FILTER_CTRL_4:
case RT5691_ADC_FILTER_CTRL_5:
case RT5691_ADC_FILTER_CTRL_6:
case RT5691_ADC_FILTER_CTRL_7:
case RT5691_ADC_FILTER_CTRL_8:
case RT5691_ADC_FILTER_CTRL_9:
case RT5691_ADC_FILTER2_CTRL_1:
case RT5691_ADC_FILTER2_CTRL_2:
case RT5691_ADC_FILTER2_CTRL_3:
case RT5691_ADC_FILTER2_CTRL_4:
case RT5691_ADC_FILTER2_CTRL_5:
case RT5691_ADC_FILTER2_CTRL_6:
case RT5691_ADC_FILTER2_CTRL_7:
case RT5691_ADC_FILTER2_CTRL_8:
case RT5691_ADC_FILTER2_CTRL_9:
case RT5691_HARM_COMP_OP_1:
case RT5691_HARM_COMP_OP_2:
case RT5691_HARM_COMP_OP_3:
case RT5691_HARM_COMP_OP_4:
case RT5691_HARM_COMP_OP_5:
case RT5691_HARM_COMP_OP_6:
case RT5691_HARM_COMP_OP_7:
case RT5691_HARM_COMP_OP_8:
case RT5691_HARM_COMP_OP_9:
case RT5691_HARM_COMP_OP_10:
case RT5691_HARM_COMP_OP_11:
case RT5691_HARM_COMP_OP_12:
case RT5691_HARM_COMP_OP_13:
case RT5691_HARM_COMP_OP_14:
case RT5691_HARM_COMP_OP_15:
case RT5691_HARM_COMP_OP_16:
case RT5691_HARM_COMP_OP_17:
case RT5691_HARM_COMP_OP_18:
case RT5691_HARM_COMP_OP_19:
case RT5691_HARM_COMP_OP_20:
case RT5691_HARM_COMP_OP_21:
case RT5691_HARM_COMP_OP_22:
case RT5691_HARM_COMP_OP_23:
case RT5691_HARM_COMP_OP_24:
case RT5691_HARM_COMP_OP_25:
case RT5691_DAC_BI_FILTER_CTRL_1:
case RT5691_DAC_BI_FILTER_CTRL_2:
case RT5691_DAC_BI_FILTER_CTRL_3:
case RT5691_DAC_BI_FILTER_CTRL_4:
case RT5691_DAC_BI_FILTER_CTRL_5:
case RT5691_DAC_BI_FILTER_CTRL_6:
case RT5691_DAC_BI_FILTER_CTRL_7:
case RT5691_DAC_BI_FILTER_CTRL_8:
case RT5691_DAC_BI_FILTER_CTRL_9:
case RT5691_DAC_BI_FILTER_CTRL_10:
case RT5691_DAC_BI_FILTER_CTRL_11:
case RT5691_DAC_BI_FILTER_CTRL_12:
case RT5691_DAC_BI_FILTER_CTRL_13:
case RT5691_DAC_BI_FILTER_CTRL_14:
case RT5691_DAC_BI_FILTER_CTRL_15:
case RT5691_DAC_BI_FILTER_CTRL_16:
case RT5691_DAC_BI_FILTER_CTRL_17:
case RT5691_DAC_BI_FILTER_CTRL_18:
case RT5691_DAC_BI_FILTER_CTRL_19:
case RT5691_DAC_BI_FILTER_CTRL_20:
case RT5691_DAC_BI_FILTER_CTRL_21:
case RT5691_DAC_BI_FILTER_CTRL_22:
case RT5691_DAC_BI_FILTER_CTRL_23:
case RT5691_ALC_PGA_TOP_1:
case RT5691_ALC_PGA_TOP_2:
case RT5691_ALC_PGA_TOP_3:
case RT5691_ALC_PGA_TOP_4:
case RT5691_ALC_PGA_TOP_5:
case RT5691_ALC_PGA_TOP_6:
case RT5691_ALC_PGA_TOP_7:
case RT5691_ALC_PGA_TOP_8:
case RT5691_ALC_PGA_TOP_9:
case RT5691_ALC_PGA_TOP_10:
case RT5691_ALC_PGA_TOP_11:
case RT5691_DAC_EQ_CTRL_1:
case RT5691_DAC_EQ_CTRL_2:
case RT5691_DAC_EQ_CTRL_3:
case RT5691_DAC_EQ_CTRL_4:
case RT5691_DAC_EQ_CTRL_5:
case RT5691_DAC_EQ_CTRL_6:
case RT5691_DAC_EQ_CTRL_7:
case RT5691_DAC_EQ_CTRL_8:
case RT5691_DAC_EQ_CTRL_9:
case RT5691_DAC_EQ_CTRL_10:
case RT5691_DAC_EQ_CTRL_11:
case RT5691_DAC_EQ_CTRL_12:
case RT5691_DAC_EQ_CTRL_13:
case RT5691_DAC_EQ_CTRL_14:
case RT5691_DAC_EQ_CTRL_15:
case RT5691_DAC_EQ_CTRL_16:
case RT5691_DAC_EQ_CTRL_17:
case RT5691_DAC_EQ_CTRL_18:
case RT5691_DAC_EQ_CTRL_19:
case RT5691_DAC_EQ_CTRL_20:
case RT5691_DAC_EQ_CTRL_21:
case RT5691_DAC_EQ_CTRL_22:
case RT5691_DAC_EQ_CTRL_23:
case RT5691_DAC_EQ_CTRL_24:
case RT5691_DAC_EQ_CTRL_25:
case RT5691_DAC_EQ_CTRL_26:
case RT5691_DAC_EQ_CTRL_27:
case RT5691_DAC_EQ_CTRL_28:
case RT5691_DAC_EQ_CTRL_29:
case RT5691_DAC_EQ_CTRL_30:
case RT5691_DAC_EQ_CTRL_31:
case RT5691_DAC_EQ_CTRL_32:
case RT5691_DAC_EQ_CTRL_33:
case RT5691_DAC_EQ_CTRL_34:
case RT5691_DAC_EQ_CTRL_35:
case RT5691_DAC_EQ_CTRL_36:
case RT5691_DAC_EQ_CTRL_37:
case RT5691_DAC_EQ_CTRL_38:
case RT5691_DAC_EQ_CTRL_39:
case RT5691_DAC_EQ_CTRL_40:
case RT5691_DAC_EQ_CTRL_41:
case RT5691_DAC_EQ_CTRL_42:
case RT5691_DAC_EQ_CTRL_43:
case RT5691_ALC_CTRL_1:
case RT5691_ALC_CTRL_2:
case RT5691_ALC_CTRL_3:
case RT5691_ALC_CTRL_4:
case RT5691_ALC_CTRL_5:
case RT5691_ALC_CTRL_6:
case RT5691_ALC_CTRL_7:
case RT5691_ALC_CTRL_8:
case RT5691_ALC_CTRL_9:
case RT5691_ALC_CTRL_10:
case RT5691_ALC_CTRL_11:
case RT5691_ALC_CTRL_12:
case RT5691_ALC_CTRL_13:
case RT5691_ALC_CTRL_14:
case RT5691_ALC_CTRL_15:
case RT5691_ALC_CTRL_16:
case RT5691_EQ_ALC_SRC_CTRL:
case RT5691_DA_DVOL_MONO_1:
case RT5691_DA_DVOL_MONO_2:
case RT5691_DA_DVOL_MONO_3:
case RT5691_DA_DVOL_MONO_4:
case RT5691_DA_DVOL_STO_1:
case RT5691_DA_DVOL_STO_2:
case RT5691_DA_DVOL_STO_3:
case RT5691_DA_DVOL_STO_4:
case RT5691_SIL_DET_MONO_TOP:
case RT5691_SIL_DET_TOP:
case RT5691_SIL_DET_TOP_1:
case RT5691_SIL_DET_TOP_2:
case RT5691_SIL_DET_TOP_3:
case RT5691_SIL_DET_TOP_4:
case RT5691_SIL_DET_TOP_5:
case RT5691_SIL_DET_TOP_6:
case RT5691_SIL_DET_TOP_7:
case RT5691_SIL_DET_TOP_8:
case RT5691_ASRCIN_TCON_1:
case RT5691_ASRCIN_TCON_2:
case RT5691_ASRCIN_TCON_3:
case RT5691_I2S_CTRL_1:
case RT5691_COMBO_JACK_CTRL_1:
case RT5691_COMBO_JACK_CTRL_2:
case RT5691_COMBO_JACK_CTRL_3:
case RT5691_COMBO_JACK_CTRL_4:
case RT5691_COMBO_JACK_CTRL_5:
case RT5691_COMBO_JACK_CTRL_6:
case RT5691_COMBO_JACK_CTRL_7:
case RT5691_COMBO_JACK_CTRL_8:
case RT5691_COMBO_JACK_CTRL_9:
case RT5691_COMBO_JACK_CTRL_10:
case RT5691_COMBO_JACK_CTRL_11:
case RT5691_COMBO_JACK_CTRL_12:
case RT5691_COMBO_JACK_CTRL_13:
case RT5691_COMBO_JACK_CTRL_14:
case RT5691_COMBO_JACK_CTRL_15:
case RT5691_COMBO_JACK_CTRL_16:
case RT5691_COMBO_JACK_CTRL_17:
case RT5691_COMBO_JACK_CTRL_18:
case RT5691_COMBO_JACK_CTRL_19:
case RT5691_COMBO_JACK_CTRL_20:
case RT5691_COMBO_JACK_CTRL_21:
case RT5691_COMBO_JACK_CTRL_22:
case RT5691_COMBO_JACK_CTRL_23:
case RT5691_IMP_SENS_CTRL_1:
case RT5691_IMP_SENS_CTRL_2:
case RT5691_IMP_SENS_CTRL_3:
case RT5691_IMP_SENS_CTRL_4:
case RT5691_IMP_SENS_CTRL_5:
case RT5691_IMP_SENS_CTRL_6:
case RT5691_IMP_SENS_CTRL_7:
case RT5691_IMP_SENS_CTRL_8:
case RT5691_IMP_SENS_CTRL_9:
case RT5691_IMP_SENS_CTRL_10:
case RT5691_IMP_SENS_CTRL_11:
case RT5691_IMP_SENS_CTRL_12:
case RT5691_IMP_SENS_CTRL_13:
case RT5691_IMP_SENS_CTRL_14:
case RT5691_IMP_SENS_CTRL_15:
case RT5691_IMP_SENS_CTRL_16:
case RT5691_IMP_SENS_CTRL_17:
case RT5691_IMP_SENS_CTRL_18:
case RT5691_IMP_SENS_CTRL_19:
case RT5691_IMP_SENS_CTRL_20:
case RT5691_IMP_SENS_CTRL_21:
case RT5691_IMP_SENS_CTRL_22:
case RT5691_IMP_SENS_CTRL_23:
case RT5691_IMP_SENS_CTRL_24:
case RT5691_IMP_SENS_CTRL_25:
case RT5691_IMP_SENS_CTRL_26:
case RT5691_IMP_SENS_CTRL_27:
case RT5691_IMP_SENS_CTRL_28:
case RT5691_IMP_SENS_CTRL_29:
case RT5691_IMP_SENS_CTRL_30:
case RT5691_IMP_SENS_CTRL_31:
case RT5691_HP_IMP_SEN_DIG_CTRL_11:
case RT5691_HP_IMP_SEN_DIG_CTRL_12:
case RT5691_HP_IMP_SEN_DIG_CTRL_13:
case RT5691_COMBO_JACK_CTRL:
case RT5691_MONO_DRE_CTRL_1:
case RT5691_MONO_DRE_CTRL_2:
case RT5691_MONO_DRE_CTRL_3:
case RT5691_MONO_DRE_CTRL_4:
case RT5691_MONO_DRE_CTRL_5:
case RT5691_MONO_DRE_CTRL_6:
case RT5691_MONO_DRE_CTRL_7:
case RT5691_MONO_DRE_CTRL_8:
case RT5691_MONO_DRE_CTRL_9:
case RT5691_MONO_DRE_CTRL_10:
case RT5691_STO_DRE_CTRL_1:
case RT5691_STO_DRE_CTRL_2:
case RT5691_STO_DRE_CTRL_3:
case RT5691_STO_DRE_CTRL_4:
case RT5691_STO_DRE_CTRL_5:
case RT5691_STO_DRE_CTRL_6:
case RT5691_STO_DRE_CTRL_7:
case RT5691_STO_DRE_CTRL_8:
case RT5691_STO_DRE_CTRL_9:
case RT5691_STO_DEBOUNCE_CTRL_9:
case RT5691_WATER_DET_CTRL_1:
case RT5691_WATER_DET_CTRL_2:
case RT5691_WATER_DET_CTRL_3:
case RT5691_WATER_DET_CTRL_4:
case RT5691_COMBO_WATER_CTRL_1:
case RT5691_COMBO_WATER_CTRL_2:
case RT5691_COMBO_WATER_CTRL_3:
case RT5691_COMBO_WATER_CTRL_4:
case RT5691_COMBO_WATER_CTRL_5:
case RT5691_COMBO_WATER_CTRL_6:
case RT5691_COMBO_WATER_CTRL_7:
case RT5691_SAR_ADC_DET_CTRL_6:
case RT5691_SAR_ADC_DET_CTRL_7:
case RT5691_SAR_ADC_DET_CTRL_1:
case RT5691_SAR_ADC_DET_CTRL_2:
case RT5691_SAR_ADC_DET_CTRL_3:
case RT5691_SAR_ADC_DET_CTRL_4:
case RT5691_SAR_ADC_DET_CTRL_5:
case RT5691_SAR_ADC_DET_CTRL_9:
case RT5691_SAR_ADC_DET_CTRL_10:
case RT5691_SAR_ADC_DET_CTRL_11:
case RT5691_SAR_ADC_DET_CTRL_12:
case RT5691_SAR_ADC_DET_CTRL_13:
case RT5691_SAR_ADC_DET_CTRL_14:
case RT5691_SAR_ADC_DET_CTRL_15:
case RT5691_SAR_ADC_DET_CTRL_16:
case RT5691_SAR_ADC_DET_CTRL_17:
case RT5691_SAR_ADC_DET_CTRL_18:
case RT5691_SAR_ADC_DET_CTRL_19:
case RT5691_SAR_ADC_DET_CTRL_20:
case RT5691_SAR_ADC_DET_CTRL_21:
case RT5691_SAR_ADC_DET_CTRL_22:
case RT5691_SAR_ADC_DET_CTRL_23:
case RT5691_SAR_ADC_DET_CTRL_24:
case RT5691_EFUSE_WRITE_1:
case RT5691_EFUSE_WRITE_2:
case RT5691_EFUSE_WRITE_3:
case RT5691_EFUSE_WRITE_4:
case RT5691_EFUSE_WRITE_5:
case RT5691_EFUSE_WRITE_6:
case RT5691_EFUSE_WRITE_7:
case RT5691_EFUSE_WRITE_8:
case RT5691_EFUSE_WRITE_9:
case RT5691_EFUSE_WRITE_10:
case RT5691_EFUSE_WRITE_11:
case RT5691_EFUSE_WRITE_12:
case RT5691_EFUSE_WRITE_13:
case RT5691_EFUSE_WRITE_14:
case RT5691_EFUSE_WRITE_15:
case RT5691_EFUSE_WRITE_16:
case RT5691_EFUSE_WRITE_17:
case RT5691_EFUSE_WRITE_18:
case RT5691_EFUSE_WRITE_19:
case RT5691_EFUSE_READ_1:
case RT5691_EFUSE_READ_2:
case RT5691_EFUSE_READ_3:
case RT5691_EFUSE_READ_4:
case RT5691_EFUSE_READ_5:
case RT5691_EFUSE_READ_6:
case RT5691_EFUSE_READ_7:
case RT5691_EFUSE_READ_8:
case RT5691_EFUSE_READ_9:
case RT5691_EFUSE_READ_10:
case RT5691_EFUSE_READ_11:
case RT5691_EFUSE_READ_12:
case RT5691_EFUSE_READ_13:
case RT5691_EFUSE_READ_14:
case RT5691_EFUSE_READ_15:
case RT5691_EFUSE_READ_16:
case RT5691_EFUSE_READ_17:
case RT5691_EFUSE_READ_18:
case RT5691_EFUSE_READ_19:
case RT5691_EFUSE_READ_20:
case RT5691_OFFSET_CAL_1:
case RT5691_OFFSET_CAL_2:
case RT5691_HP_AMP_DET_CTRL_8:
case RT5691_HP_AMP_DET_CTRL_9:
case RT5691_HP_AMP_DET_CTRL_10:
case RT5691_HP_AMP_DET_CTRL_11:
case RT5691_HP_AMP_DET_CTRL_12:
case RT5691_HP_AMP_DET_CTRL_13:
case RT5691_OFFSET_CAL_TOP_9:
case RT5691_OFFSET_CAL_TOP_10:
case RT5691_OFFSET_CAL_TOP_11:
case RT5691_OFFSET_CAL_TOP_12:
case RT5691_OFFSET_CAL_TOP_13:
case RT5691_OFFSET_CAL_TOP_14:
case RT5691_OFFSET_CAL_TOP_15:
case RT5691_OFFSET_CAL_TOP_16:
case RT5691_OFFSET_CAL_TOP_17:
case RT5691_OFFSET_CAL_18:
case RT5691_OFFSET_CAL_19:
case RT5691_OFFSET_CAL_20:
case RT5691_OFFSET_CAL_21:
case RT5691_OFFSET_CAL_22:
case RT5691_OFFSET_CAL_23:
case RT5691_OFFSET_CAL_24:
case RT5691_OFFSET_CAL_25:
case RT5691_OFFSET_CAL_26:
case RT5691_OFFSET_CAL_27:
case RT5691_OFFSET_CAL_28:
case RT5691_OFFSET_CAL_29:
case RT5691_OFFSET_CAL_30:
case RT5691_OFFSET_CAL_31:
case RT5691_OFFSET_CAL_32:
case RT5691_OFFSET_CAL_33:
case RT5691_HP_AMP_DET_CTRL_14:
case RT5691_HP_AMP_DET_CTRL_15:
case RT5691_HP_AMP_DET_CTRL_16:
case RT5691_HP_AMP_DET_CTRL_17:
case RT5691_HP_AMP_DET_CTRL_18:
case RT5691_HP_AMP_DET_CTRL_19:
case RT5691_HP_AMP_DET_CTRL_20:
return true;
default:
return false;
}
}
static const DECLARE_TLV_DB_SCALE(hp_vol_tlv, -2250, 150, 0);
static const DECLARE_TLV_DB_SCALE(mono_vol_tlv, -2325, 150, 0);
static const DECLARE_TLV_DB_SCALE(dac_vol_tlv, -95625, 375, 0);
static const DECLARE_TLV_DB_SCALE(adc_vol_tlv, -17625, 375, 0);
static const DECLARE_TLV_DB_SCALE(in_bst_tlv, -1200, 75, 0);
static int rt5691_hp_vol_put(struct snd_kcontrol *kcontrol,
struct snd_ctl_elem_value *ucontrol)
{
struct snd_soc_component *component = snd_kcontrol_chip(kcontrol);
struct rt5691_priv *rt5691 = snd_soc_component_get_drvdata(component);
struct snd_soc_dapm_context *dapm = &component->dapm;
int ret;
snd_soc_dapm_mutex_lock(dapm);
dev_dbg(component->dev, "%s %d Impedance value\n", __func__,
rt5691->imp_value);
ucontrol->value.integer.value[0] =
(ucontrol->value.integer.value[0] > rt5691->imp_gain) ?
(ucontrol->value.integer.value[0] - rt5691->imp_gain) : 0;
ucontrol->value.integer.value[1] =
(ucontrol->value.integer.value[1] > rt5691->imp_gain) ?
(ucontrol->value.integer.value[1] - rt5691->imp_gain) : 0;
ret = snd_soc_put_volsw(kcontrol, ucontrol);
snd_soc_dapm_mutex_unlock(dapm);
return ret;
}
static int rt5691_disable_ng2_get(struct snd_kcontrol *kcontrol,
struct snd_ctl_elem_value *ucontrol)
{
struct snd_soc_component *component = snd_kcontrol_chip(kcontrol);
struct rt5691_priv *rt5691 = snd_soc_component_get_drvdata(component);
ucontrol->value.integer.value[0] = rt5691->disable_ng2;
return 0;
}
static void rt5691_noise_gate(struct snd_soc_component *component, bool enable)
{
if (enable) {
snd_soc_component_update_bits(component, RT5691_PWR_DA_PATH_1,
0x0080, 0x0080);
snd_soc_component_update_bits(component, RT5691_SIL_DET_TOP,
0xf078, 0xa040);
snd_soc_component_update_bits(component, RT5691_SIL_DET_CTRL8,
0xc000, 0xc000);
snd_soc_component_update_bits(component, RT5691_SIL_DET_CTRL9,
0xf000, 0xf000);
} else {
snd_soc_component_update_bits(component, RT5691_SIL_DET_CTRL9,
0xf000, 0);
snd_soc_component_update_bits(component, RT5691_SIL_DET_CTRL8,
0xc000, 0);
snd_soc_component_update_bits(component, RT5691_SIL_DET_TOP,
0x8000, 0);
snd_soc_component_update_bits(component, RT5691_PWR_DA_PATH_1,
0x0080, 0);
}
}
static int rt5691_disable_ng2_put(struct snd_kcontrol *kcontrol,
struct snd_ctl_elem_value *ucontrol)
{
struct snd_soc_component *component = snd_kcontrol_chip(kcontrol);
struct rt5691_priv *rt5691 = snd_soc_component_get_drvdata(component);
rt5691->disable_ng2 = !!ucontrol->value.integer.value[0];
if (rt5691->disable_ng2) {
snd_soc_component_update_bits(component, RT5691_PWR_DA_PATH_1,
0x0004, 0);
rt5691_noise_gate(component, false);
}
return 0;
}
static const struct snd_kcontrol_new rt5691_snd_controls[] = {
/* Headphone Output Volume */
SOC_DOUBLE_R_EXT_TLV("Headphone Playback Volume",
RT5691_HP_AMP_L_GAIN_CTRL, RT5691_HP_AMP_R_GAIN_CTRL,
RT5691_G_HP_SFT, 15, 1, snd_soc_get_volsw, rt5691_hp_vol_put,
hp_vol_tlv),
/* Mono Output Volume */
SOC_SINGLE_TLV("Mono Playback Volume", RT5691_MONO_DRE_CTRL_9,
RT5691_L_VOL_SFT, 17, 1, mono_vol_tlv),
/* DAC Digital Volume */
SOC_DOUBLE_R_TLV("DAC1 Playback Volume", RT5691_MIC_BTN_CTRL_27,
RT5691_MIC_BTN_CTRL_28, RT5691_R_VOL_SFT, 255, 0, dac_vol_tlv),
SOC_SINGLE_TLV("DAC2 Playback Volume", RT5691_MONO_DAC_VOL_CTRL,
RT5691_V_DAC2_L_SFT, 255, 0, dac_vol_tlv),
/* IN1/IN2/IN3 Volume */
SOC_SINGLE_TLV("IN1 Boost Volume", RT5691_IN1_IN2_CTRL,
RT5691_BST1_SFT, 69, 0, in_bst_tlv),
SOC_SINGLE_TLV("IN2 Boost Volume", RT5691_IN1_IN2_CTRL,
RT5691_BST2_SFT, 69, 0, in_bst_tlv),
SOC_SINGLE_TLV("IN3 Boost Volume", RT5691_IN3_CTRL,
RT5691_BST3_SFT, 69, 0, in_bst_tlv),
/* ADC Digital Volume Control */
SOC_DOUBLE_R_TLV("STO1 ADC Capture Volume", RT5691_ADC_FILTER_CTRL_4,
RT5691_ADC_FILTER_CTRL_5, RT5691_R_VOL_SFT, 127, 0,
adc_vol_tlv),
SOC_DOUBLE_R_TLV("STO2 ADC Capture Volume", RT5691_ADC_FILTER2_CTRL_4,
RT5691_ADC_FILTER2_CTRL_5, RT5691_R_VOL_SFT, 127, 0,
adc_vol_tlv),
SOC_SINGLE_EXT("Disable NG2", SND_SOC_NOPM, 0, 1, 0,
rt5691_disable_ng2_get, rt5691_disable_ng2_put),
};
/***** Muxes *****/
/* STO1 ADC Source */
/* MX-0026 [11:10] [3:2] */
static const char * const rt5691_sto1_adc_src[] = {
"ADC1", "ADC2", "ADC3"
};
static SOC_ENUM_SINGLE_DECL(
rt5691_sto1_adcl_enum, RT5691_STO1_ADC_MIXER_CTRL, 10,
rt5691_sto1_adc_src);
static const struct snd_kcontrol_new rt5691_sto1_adcl_mux =
SOC_DAPM_ENUM("Stereo1 ADCL Source", rt5691_sto1_adcl_enum);
static SOC_ENUM_SINGLE_DECL(
rt5691_sto1_adcr_enum, RT5691_STO1_ADC_MIXER_CTRL, 2,
rt5691_sto1_adc_src);
static const struct snd_kcontrol_new rt5691_sto1_adcr_mux =
SOC_DAPM_ENUM("Stereo1 ADCR Source", rt5691_sto1_adcr_enum);
/* STO1 ADC1 Source */
/* MX-0026 [13] [5] */
static const char * const rt5691_sto1_adc1_src[] = {
"DACL2", "STO1 ADC"
};
static SOC_ENUM_SINGLE_DECL(
rt5691_sto1_adc1l_enum, RT5691_STO1_ADC_MIXER_CTRL, 13,
rt5691_sto1_adc1_src);
static const struct snd_kcontrol_new rt5691_sto1_adc1l_mux =
SOC_DAPM_ENUM("Stereo1 ADC1L Source", rt5691_sto1_adc1l_enum);
static SOC_ENUM_SINGLE_DECL(
rt5691_sto1_adc1r_enum, RT5691_STO1_ADC_MIXER_CTRL, 5,
rt5691_sto1_adc1_src);
static const struct snd_kcontrol_new rt5691_sto1_adc1r_mux =
SOC_DAPM_ENUM("Stereo1 ADC1R Source", rt5691_sto1_adc1r_enum);
/* STO1 ADC2 Source */
/* MX-0026 [12] [4] */
static const char * const rt5691_sto1_adc2_src[] = {
"DAC MIX", "DMIC"
};
static SOC_ENUM_SINGLE_DECL(
rt5691_sto1_adc2l_enum, RT5691_STO1_ADC_MIXER_CTRL, 12,
rt5691_sto1_adc2_src);
static const struct snd_kcontrol_new rt5691_sto1_adc2l_mux =
SOC_DAPM_ENUM("Stereo1 ADC2L Source", rt5691_sto1_adc2l_enum);
static SOC_ENUM_SINGLE_DECL(
rt5691_sto1_adc2r_enum, RT5691_STO1_ADC_MIXER_CTRL, 4,
rt5691_sto1_adc2_src);
static const struct snd_kcontrol_new rt5691_sto1_adc2r_mux =
SOC_DAPM_ENUM("Stereo1 ADC2R Source", rt5691_sto1_adc2r_enum);
/* STO2 ADC Source */
/* MX-0027 [11:10] [3:2] */
static const char * const rt5691_sto2_adc_src[] = {
"ADC1", "ADC2", "ADC3"
};
static SOC_ENUM_SINGLE_DECL(
rt5691_sto2_adcl_enum, RT5691_STO2_ADC_MIXER_CTRL, 10,
rt5691_sto2_adc_src);
static const struct snd_kcontrol_new rt5691_sto2_adcl_mux =
SOC_DAPM_ENUM("Stereo2 ADCL Source", rt5691_sto2_adcl_enum);
static SOC_ENUM_SINGLE_DECL(
rt5691_sto2_adcr_enum, RT5691_STO2_ADC_MIXER_CTRL, 2,
rt5691_sto2_adc_src);
static const struct snd_kcontrol_new rt5691_sto2_adcr_mux =
SOC_DAPM_ENUM("Stereo2 ADCR Source", rt5691_sto2_adcr_enum);
/* STO2 ADC1 Source */
/* MX-0027 [13] [5] */
static const char * const rt5691_sto2_adc1_src[] = {
"DACL2", "STO2 ADC"
};
static SOC_ENUM_SINGLE_DECL(
rt5691_sto2_adc1l_enum, RT5691_STO2_ADC_MIXER_CTRL, 13,
rt5691_sto2_adc1_src);
static const struct snd_kcontrol_new rt5691_sto2_adc1l_mux =
SOC_DAPM_ENUM("Stereo2 ADC1L Source", rt5691_sto2_adc1l_enum);
static SOC_ENUM_SINGLE_DECL(
rt5691_sto2_adc1r_enum, RT5691_STO2_ADC_MIXER_CTRL, 5,
rt5691_sto2_adc1_src);
static const struct snd_kcontrol_new rt5691_sto2_adc1r_mux =
SOC_DAPM_ENUM("Stereo2 ADC1R Source", rt5691_sto2_adc1r_enum);
/* STO2 ADC2 Source */
/* MX-0027 [12] [4] */
static const char * const rt5691_sto2_adc2_src[] = {
"DAC MIX", "DMIC"
};
static SOC_ENUM_SINGLE_DECL(
rt5691_sto2_adc2l_enum, RT5691_STO2_ADC_MIXER_CTRL, 12,
rt5691_sto2_adc2_src);
static const struct snd_kcontrol_new rt5691_sto2_adc2l_mux =
SOC_DAPM_ENUM("Stereo2 ADC2L Source", rt5691_sto2_adc2l_enum);
static SOC_ENUM_SINGLE_DECL(
rt5691_sto2_adc2r_enum, RT5691_STO2_ADC_MIXER_CTRL, 4,
rt5691_sto2_adc2_src);
static const struct snd_kcontrol_new rt5691_sto2_adc2r_mux =
SOC_DAPM_ENUM("Stereo2 ADC2R Source", rt5691_sto2_adc2r_enum);
/* I2S ADCDAT Source */
/* MX-0030 [1:0] */
static const char * const rt5691_if_adc_data_src[] = {
"STO1 ADC", "STO2 ADC", "DAC"
};
static SOC_ENUM_SINGLE_DECL(
rt5691_if_adc_data_enum, RT5691_FIFO_CTRL, 0, rt5691_if_adc_data_src);
static const struct snd_kcontrol_new rt5691_if_adc_mux =
SOC_DAPM_ENUM("IF ADC Source", rt5691_if_adc_data_enum);
/* Interface Data Select */
/* MX-2400 [11:10] [9:8] */
static const char * const rt5691_data_select[] = {
"L/R", "R/L", "L/L", "R/R"
};
static SOC_ENUM_SINGLE_DECL(rt5691_if_data_adc_enum,
RT5691_I2S_CTRL_1, 8, rt5691_data_select);
static const struct snd_kcontrol_new rt5691_if_data_adc_mux =
SOC_DAPM_ENUM("IF Data ADC Source", rt5691_if_data_adc_enum);
static SOC_ENUM_SINGLE_DECL(rt5691_if_data_dac_enum,
RT5691_I2S_CTRL_1, 10, rt5691_data_select);
static const struct snd_kcontrol_new rt5691_if_data_dac_mux =
SOC_DAPM_ENUM("IF Data DAC Source", rt5691_if_data_dac_enum);
/* DAC2 Source */
/* MX-0031 [4] */
static const char * const rt5691_dac2_src[] = {
"STO1 DAC Mixer", "DAC2"
};
static SOC_ENUM_SINGLE_DECL(
rt5691_dac2_enum, RT5691_PDM_OUTPUT_CTRL, 4, rt5691_dac2_src);
static const struct snd_kcontrol_new rt5691_dac2_mux =
SOC_DAPM_ENUM("DAC2 Source", rt5691_dac2_enum);
/* PDM */
/* MX-0031 [11:10] [9:8] */
static const char * const rt5691_pdm_src[] = {
"Stereo1 DAC", "DAC2", "Sidetone"
};
static SOC_ENUM_SINGLE_DECL(
rt5691_pdm_l_enum, RT5691_PDM_OUTPUT_CTRL, 10, rt5691_pdm_src);
static const struct snd_kcontrol_new rt5691_pdm_l_mux =
SOC_DAPM_ENUM("PDM L Source", rt5691_pdm_l_enum);
static SOC_ENUM_SINGLE_DECL(
rt5691_pdm_r_enum, RT5691_PDM_OUTPUT_CTRL, 8, rt5691_pdm_src);
static const struct snd_kcontrol_new rt5691_pdm_r_mux =
SOC_DAPM_ENUM("PDM R Source", rt5691_pdm_r_enum);
/* Sidetone Source */
/* MX-0024 [9] */
static const char * const rt5691_st_src[] = {
"ADC1", "ADC2", "DMICL", "DMICR"
};
static SOC_ENUM_SINGLE_DECL(
rt5691_st_enum, RT5691_ST_MUX_CTRL, 9, rt5691_st_src);
static const struct snd_kcontrol_new rt5691_st_mux =
SOC_DAPM_ENUM("Sidetone Source", rt5691_st_enum);
/***** Mixers *****/
static const struct snd_kcontrol_new rt5691_sto1_adc_l_mix[] = {
SOC_DAPM_SINGLE("ADC1 Switch", RT5691_STO1_ADC_MIXER_CTRL,
15, 1, 1),
SOC_DAPM_SINGLE("ADC2 Switch", RT5691_STO1_ADC_MIXER_CTRL,
14, 1, 1),
};
static const struct snd_kcontrol_new rt5691_sto1_adc_r_mix[] = {
SOC_DAPM_SINGLE("ADC1 Switch", RT5691_STO1_ADC_MIXER_CTRL,
7, 1, 1),
SOC_DAPM_SINGLE("ADC2 Switch", RT5691_STO1_ADC_MIXER_CTRL,
6, 1, 1),
};
static const struct snd_kcontrol_new rt5691_sto2_adc_l_mix[] = {
SOC_DAPM_SINGLE("ADC1 Switch", RT5691_STO2_ADC_MIXER_CTRL,
15, 1, 1),
SOC_DAPM_SINGLE("ADC2 Switch", RT5691_STO2_ADC_MIXER_CTRL,
14, 1, 1),
};
static const struct snd_kcontrol_new rt5691_sto2_adc_r_mix[] = {
SOC_DAPM_SINGLE("ADC1 Switch", RT5691_STO2_ADC_MIXER_CTRL,
7, 1, 1),
SOC_DAPM_SINGLE("ADC2 Switch", RT5691_STO2_ADC_MIXER_CTRL,
6, 1, 1),
};
static const struct snd_kcontrol_new rt5691_dac_l_mix[] = {
SOC_DAPM_SINGLE("Stereo ADC Switch", RT5691_AD_DA_MIXER_CTRL,
RT5691_M_ADCMIX_L_SFT, 1, 1),
SOC_DAPM_SINGLE("DAC1 Switch", RT5691_MIC_BTN_CTRL_26, 7, 1, 1),
};
static const struct snd_kcontrol_new rt5691_dac_r_mix[] = {
SOC_DAPM_SINGLE("Stereo ADC Switch", RT5691_AD_DA_MIXER_CTRL,
RT5691_M_ADCMIX_R_SFT, 1, 1),
SOC_DAPM_SINGLE("DAC1 Switch", RT5691_MIC_BTN_CTRL_26, 3, 1, 1),
};
static const struct snd_kcontrol_new rt5691_sto_dac_l_mix[] = {
SOC_DAPM_SINGLE("DAC L1 Switch", RT5691_STO1_DAC_MIXER_CTRL,
15, 1, 1),
SOC_DAPM_SINGLE("DAC R1 Switch", RT5691_STO1_DAC_MIXER_CTRL,
13, 1, 1),
SOC_DAPM_SINGLE("Sidetone Switch", RT5691_STO1_DAC_MIXER_CTRL,
11, 1, 1),
};
static const struct snd_kcontrol_new rt5691_sto_dac_r_mix[] = {
SOC_DAPM_SINGLE("DAC L1 Switch", RT5691_STO1_DAC_MIXER_CTRL,
7, 1, 1),
SOC_DAPM_SINGLE("DAC R1 Switch", RT5691_STO1_DAC_MIXER_CTRL,
5, 1, 1),
SOC_DAPM_SINGLE("Sidetone Switch", RT5691_STO1_DAC_MIXER_CTRL,
3, 1, 1),
};
static const struct snd_kcontrol_new rt5691_mono_switch =
SOC_DAPM_SINGLE("Switch", RT5691_MONO_DAC_VOL_CTRL,
RT5691_M_DAC2_L_SFT, 1, 1);
static const struct snd_kcontrol_new rt5691_pdm_l_switch =
SOC_DAPM_SINGLE("Switch", RT5691_PDM_CTRL_1, 3, 1, 1);
static const struct snd_kcontrol_new rt5691_pdm_r_switch =
SOC_DAPM_SINGLE("Switch", RT5691_PDM_CTRL_1, 2, 1, 1);
static int rt5691_set_verf(struct snd_soc_dapm_widget *w,
struct snd_kcontrol *kcontrol, int event)
{
struct snd_soc_component *component =
snd_soc_dapm_to_component(w->dapm);
switch (event) {
case SND_SOC_DAPM_PRE_PMU:
switch (w->shift) {
case RT5691_PWR_VREF1_BIT:
snd_soc_component_update_bits(component,
RT5691_PWR_ANLG_1, RT5691_PWR_FV1, 0);
break;
case RT5691_PWR_VREF2_BIT:
snd_soc_component_update_bits(component,
RT5691_PWR_ANLG_1, RT5691_PWR_FV2, 0);
break;
case RT5691_PWR_VREF3_BIT:
snd_soc_component_update_bits(component,
RT5691_PWR_ANLG_1, RT5691_PWR_FV3, 0);
break;
default:
break;
}
break;
case SND_SOC_DAPM_POST_PMU:
usleep_range(15000, 20000);
switch (w->shift) {
case RT5691_PWR_VREF1_BIT:
snd_soc_component_update_bits(component,
RT5691_PWR_ANLG_1, RT5691_PWR_FV1,
RT5691_PWR_FV1);
break;
case RT5691_PWR_VREF2_BIT:
snd_soc_component_update_bits(component,
RT5691_PWR_ANLG_1, RT5691_PWR_FV2,
RT5691_PWR_FV2);
break;
case RT5691_PWR_VREF3_BIT:
snd_soc_component_update_bits(component,
RT5691_PWR_ANLG_1, RT5691_PWR_FV3,
RT5691_PWR_FV3);
break;
default:
break;
}
break;
default:
return 0;
}
return 0;
}
static int rt5691_calc_clk_div(struct rt5691_priv *rt5691, int fs,
int clk)
{
struct snd_soc_component *component = rt5691->component;
int div[] = {1, 2, 4, 6, 8, 12, 16, 24, 32, 48, 64, 96, 128};
int i, target;
if (rt5691->sysclk < 1000000 * div[0]) {
dev_warn(component->dev, "Base clock rate %d is too low\n",
rt5691->sysclk);
return -EINVAL;
}
if (fs)
target = rt5691->lrck * fs;
else
target = clk;
for (i = 0; i < ARRAY_SIZE(div); i++) {
if (target * div[i] >= rt5691->sysclk)
return i;
}
dev_warn(component->dev, "Base clock rate %d is too high\n",
rt5691->sysclk);
return -EINVAL;
}
static int rt5691_set_dmic_clk(struct snd_soc_dapm_widget *w,
struct snd_kcontrol *kcontrol, int event)
{
struct snd_soc_component *component =
snd_soc_dapm_to_component(w->dapm);
struct rt5691_priv *rt5691 = snd_soc_component_get_drvdata(component);
int idx = -EINVAL;
idx = rt5691_calc_clk_div(rt5691, 64, 0);
if (idx < 0)
dev_err(component->dev, "Failed to set DMIC clock\n");
else {
snd_soc_component_update_bits(component, RT5691_CLK_DIV_DMIC,
0xf, idx);
}
return idx;
}
static int rt5691_set_pdm_clk(struct snd_soc_dapm_widget *w,
struct snd_kcontrol *kcontrol, int event)
{
struct snd_soc_component *component =
snd_soc_dapm_to_component(w->dapm);
struct rt5691_priv *rt5691 = snd_soc_component_get_drvdata(component);
int idx = -EINVAL;
idx = rt5691_calc_clk_div(rt5691, 128, 0);
if (idx < 0)
dev_err(component->dev, "Failed to set PDM clock\n");
else {
snd_soc_component_update_bits(component, RT5691_CLK_DIV_PDM,
0xf, idx);
}
return idx;
}
static void rt5691_recalibrate(struct snd_soc_component *component)
{
static struct reg_sequence rt5691_rek_list[] = {
{RT5691_MIC_BTN_CTRL_26, 0x0088},
{RT5691_ADC_FILTER_CTRL_3, 0x0090},
{RT5691_ADC_FILTER2_CTRL_3, 0x0090},
{RT5691_RC_CLK, 0x8800},
{RT5691_SYS_CLK_SRC, 0x007d},
{RT5691_PWR_DA_PATH_1, 0x6801},
{RT5691_PWR_DA_PATH_2, 0x0223},
{RT5691_PWR_AD_PATH, 0x0023},
{RT5691_DA_STO1_FILTER_CLK_DIV, 0x0202},
{RT5691_AD_STO1_FILTER_CLK_DIV, 0x0202},
{RT5691_ADC_AND_DAC_OSR, 0x0202},
{RT5691_STO1_DAC_MIXER_CTRL, 0x2888},
{RT5691_HP_BEHAVIOR_LOGIC_CTRL_2, 0x0000},
{RT5691_BGLDO33_CTRL_1, 0x8000},
{RT5691_ADC56_CTRL, 0xb490},
{RT5691_OFFSET_CAL_1, 0x2500},
};
unsigned int rt5691_rek_list_saved[ARRAY_SIZE(rt5691_rek_list)];
int i;
for (i = 0; i < ARRAY_SIZE(rt5691_rek_list); i++) {
rt5691_rek_list_saved[i] =
snd_soc_component_read(component, rt5691_rek_list[i].reg);
if (rt5691_rek_list[i].reg == RT5691_PWR_DA_PATH_2) {
snd_soc_component_update_bits(component,
rt5691_rek_list[i].reg, rt5691_rek_list[i].def,
rt5691_rek_list[i].def);
continue;
}
snd_soc_component_write(component, rt5691_rek_list[i].reg,
rt5691_rek_list[i].def);
}
snd_soc_component_update_bits(component, RT5691_OFFSET_CAL_2, 0x0300,
0x0300);
snd_soc_component_update_bits(component, RT5691_OFFSET_CAL_2, 0x0300,
0x0100);
i = 0;
while (true) {
if (snd_soc_component_read(component,
RT5691_HP_AMP_DET_CTRL_12) & 0x8000)
usleep_range(10000, 10005);
else
break;
if (i > 20) {
dev_err(component->dev, "HP Recalibration Failure\n");
break;
}
i++;
}
snd_soc_component_update_bits(component, RT5691_OFFSET_CAL_2, 0x0300,
0);
for (i = ARRAY_SIZE(rt5691_rek_list) - 1; i >= 0; i--)
snd_soc_component_write(component, rt5691_rek_list[i].reg,
rt5691_rek_list_saved[i]);
}
static int rt5691_hp_event(struct snd_soc_dapm_widget *w,
struct snd_kcontrol *kcontrol, int event)
{
struct snd_soc_component *component =
snd_soc_dapm_to_component(w->dapm);
struct rt5691_priv *rt5691 = snd_soc_component_get_drvdata(component);
switch (event) {
case SND_SOC_DAPM_PRE_PMU:
snd_soc_component_update_bits(component, RT5691_HPOUT_CP_CTRL_1,
0x0c00, 0x0c00);
snd_soc_component_update_bits(component, RT5691_HP_AMP_CTRL_2,
0x3000, 0x3000);
snd_soc_component_update_bits(component,
RT5691_HP_AMP_DET_CTRL_18, 0x000c, 0x0008);
usleep_range(10000, 10005);
snd_soc_component_update_bits(component,
RT5691_HP_AMP_DET_CTRL_14, 0x0070, 0x0040);
if (!rt5691->disable_ng2) {
snd_soc_component_update_bits(component,
RT5691_PWR_DA_PATH_1, 0x0004, 0x0004);
rt5691_noise_gate(component, true);
}
rt5691->rek_timeout = jiffies + (HZ * 60);
break;
case SND_SOC_DAPM_POST_PMD:
snd_soc_component_update_bits(component, RT5691_HP_AMP_CTRL_2,
0x3000, 0);
snd_soc_component_update_bits(component,
RT5691_HP_AMP_DET_CTRL_14, 0x0070, 0x0020);
snd_soc_component_update_bits(component,
RT5691_HP_AMP_DET_CTRL_18, 0x000c, 0);
snd_soc_component_update_bits(component, RT5691_HPOUT_CP_CTRL_1,
0x0c00, 0);
snd_soc_component_update_bits(component, RT5691_PWR_DA_PATH_1,
0x0004, 0);
rt5691_noise_gate(component, false);
if (time_after(jiffies, rt5691->rek_timeout) && rt5691->rek) {
rt5691_recalibrate(component);
rt5691->rek = false;
}
break;
default:
return 0;
}
return 0;
}
static int rt5691_mono_event(struct snd_soc_dapm_widget *w,
struct snd_kcontrol *kcontrol, int event)
{
struct snd_soc_component *component =
snd_soc_dapm_to_component(w->dapm);
switch (event) {
case SND_SOC_DAPM_PRE_PMU:
snd_soc_component_update_bits(component,
RT5691_MONO_OUTPUT_CTRL, 0x0020, 0x0020);
break;
case SND_SOC_DAPM_POST_PMD:
snd_soc_component_update_bits(component,
RT5691_MONO_OUTPUT_CTRL, 0x0020, 0);
break;
default:
return 0;
}
return 0;
}
static int rt5691_sto1_l_adc_depop_event(struct snd_soc_dapm_widget *w,
struct snd_kcontrol *kcontrol, int event)
{
struct snd_soc_component *component =
snd_soc_dapm_to_component(w->dapm);
struct rt5691_priv *rt5691 = snd_soc_component_get_drvdata(component);
switch (event) {
case SND_SOC_DAPM_POST_PMU:
schedule_delayed_work(&rt5691->sto1_l_adc_work,
msecs_to_jiffies(80));
break;
case SND_SOC_DAPM_PRE_PMD:
cancel_delayed_work_sync(&rt5691->sto1_l_adc_work);
snd_soc_component_update_bits(component,
RT5691_ADC_FILTER_CTRL_3, (0x1 << 7), (0x1 << 7));
break;
default:
return 0;
}
return 0;
}
static int rt5691_sto1_r_adc_depop_event(struct snd_soc_dapm_widget *w,
struct snd_kcontrol *kcontrol, int event)
{
struct snd_soc_component *component =
snd_soc_dapm_to_component(w->dapm);
struct rt5691_priv *rt5691 = snd_soc_component_get_drvdata(component);
switch (event) {
case SND_SOC_DAPM_POST_PMU:
schedule_delayed_work(&rt5691->sto1_r_adc_work,
msecs_to_jiffies(80));
break;
case SND_SOC_DAPM_PRE_PMD:
cancel_delayed_work_sync(&rt5691->sto1_r_adc_work);
snd_soc_component_update_bits(component,
RT5691_ADC_FILTER_CTRL_3, (0x1 << 4), (0x1 << 4));
break;
default:
return 0;
}
return 0;
}
static int rt5691_sto2_l_adc_depop_event(struct snd_soc_dapm_widget *w,
struct snd_kcontrol *kcontrol, int event)
{
struct snd_soc_component *component =
snd_soc_dapm_to_component(w->dapm);
struct rt5691_priv *rt5691 = snd_soc_component_get_drvdata(component);
switch (event) {
case SND_SOC_DAPM_POST_PMU:
schedule_delayed_work(&rt5691->sto2_l_adc_work,
msecs_to_jiffies(80));
break;
case SND_SOC_DAPM_PRE_PMD:
cancel_delayed_work_sync(&rt5691->sto2_l_adc_work);
snd_soc_component_update_bits(component,
RT5691_ADC_FILTER2_CTRL_3, (0x1 << 7), (0x1 << 7));
break;
default:
return 0;
}
return 0;
}
static int rt5691_sto2_r_adc_depop_event(struct snd_soc_dapm_widget *w,
struct snd_kcontrol *kcontrol, int event)
{
struct snd_soc_component *component =
snd_soc_dapm_to_component(w->dapm);
struct rt5691_priv *rt5691 = snd_soc_component_get_drvdata(component);
switch (event) {
case SND_SOC_DAPM_POST_PMU:
schedule_delayed_work(&rt5691->sto2_r_adc_work,
msecs_to_jiffies(80));
break;
case SND_SOC_DAPM_PRE_PMD:
cancel_delayed_work_sync(&rt5691->sto2_r_adc_work);
snd_soc_component_update_bits(component,
RT5691_ADC_FILTER2_CTRL_3, (0x1 << 4), (0x1 << 4));
break;
default:
return 0;
}
return 0;
}
static int rt5691_bst1_event(struct snd_soc_dapm_widget *w,
struct snd_kcontrol *kcontrol, int event)
{
struct snd_soc_component *component =
snd_soc_dapm_to_component(w->dapm);
struct rt5691_priv *rt5691 = snd_soc_component_get_drvdata(component);
switch (event) {
case SND_SOC_DAPM_PRE_PMU:
if (!rt5691->open_gender) {
snd_soc_component_update_bits(component,
RT5691_COMBO_JACK_CTRL_2, 0x8000, 0);
snd_soc_component_update_bits(component,
RT5691_MONO_ANLG_DRE_CTRL_2, 0x0600, 0);
snd_soc_component_update_bits(component,
RT5691_COMBO_JACK_CTRL_3, 0x00f3, 0x00e2);
snd_soc_component_update_bits(component,
RT5691_COMBO_JACK_CTRL_2, 0x8000, 0x8000);
}
break;
case SND_SOC_DAPM_POST_PMD:
if (!rt5691->open_gender) {
snd_soc_component_update_bits(component,
RT5691_COMBO_JACK_CTRL_2, 0x8000, 0);
snd_soc_component_update_bits(component,
RT5691_MONO_ANLG_DRE_CTRL_2, 0x0600, 0x0600);
snd_soc_component_update_bits(component,
RT5691_COMBO_JACK_CTRL_3, 0x00f3, 0x00e1);
snd_soc_component_update_bits(component,
RT5691_COMBO_JACK_CTRL_2, 0x8000, 0x8000);
}
break;
default:
return 0;
}
return 0;
}
static const struct snd_soc_dapm_widget rt5691_dapm_widgets[] = {
SND_SOC_DAPM_SUPPLY("RC 1M", RT5691_RC_CLK, 11, 0, NULL, 0),
SND_SOC_DAPM_SUPPLY("RC 25M", RT5691_RC_CLK, 15, 0, NULL, 0),
SND_SOC_DAPM_SUPPLY("PLAY CLK", RT5691_SYS_CLK_SRC, 5, 0, NULL, 0),
SND_SOC_DAPM_SUPPLY("RECORD CLK", RT5691_SYS_CLK_SRC, 4, 0, NULL,
0),
/* Clock Detect */
SND_SOC_DAPM_SUPPLY("CLKDET", RT5691_MCLK_DET_CTRL_2, 2, 0, NULL, 0),
SND_SOC_DAPM_SUPPLY("CLKDET HP", RT5691_MCLK_DET_CTRL_1, 15, 0, NULL,
0),
SND_SOC_DAPM_SUPPLY("CLKDET MONO", RT5691_MCLK_DET_CTRL_1, 13, 0, NULL,
0),
/* Vref */
SND_SOC_DAPM_SUPPLY("Vref1", RT5691_PWR_ANLG_1, RT5691_PWR_VREF1_BIT, 0,
rt5691_set_verf, SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMU),
SND_SOC_DAPM_SUPPLY("Vref2", RT5691_PWR_ANLG_1, RT5691_PWR_VREF2_BIT, 0,
rt5691_set_verf, SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMU),
SND_SOC_DAPM_SUPPLY("Vref3", RT5691_PWR_ANLG_1, RT5691_PWR_VREF3_BIT, 0,
rt5691_set_verf, SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMU),
/* Input Side */
SND_SOC_DAPM_SUPPLY("MICBIAS1", RT5691_PWR_ANLG_2, RT5691_PWR_MB1_BIT,
0, NULL, 0),
SND_SOC_DAPM_SUPPLY("MICBIAS2", RT5691_PWR_ANLG_2, RT5691_PWR_MB2_BIT,
0, NULL, 0),
SND_SOC_DAPM_SUPPLY("MICBIAS3", RT5691_PWR_ANLG_2, RT5691_PWR_MB3_BIT,
0, NULL, 0),
SND_SOC_DAPM_SUPPLY("LDO MICBIAS1", RT5691_MONO_ANLG_DRE_CTRL_2, 7, 0,
NULL, 0),
SND_SOC_DAPM_SUPPLY("LDO MICBIAS2", RT5691_MONO_ANLG_DRE_CTRL_3, 7, 0,
NULL, 0),
SND_SOC_DAPM_SUPPLY("LDO MICBIAS3", RT5691_MONO_ANLG_DRE_CTRL_4, 7, 0,
NULL, 0),
/* Input Lines */
SND_SOC_DAPM_INPUT("DMICL"),
SND_SOC_DAPM_INPUT("DMICR"),
SND_SOC_DAPM_INPUT("IN1P"),
SND_SOC_DAPM_INPUT("IN1N"),
SND_SOC_DAPM_INPUT("IN2P"),
SND_SOC_DAPM_INPUT("IN2N"),
SND_SOC_DAPM_INPUT("IN3P"),
SND_SOC_DAPM_INPUT("IN3N"),
SND_SOC_DAPM_SUPPLY("DMIC CLK", SND_SOC_NOPM, 0, 0,
rt5691_set_dmic_clk, SND_SOC_DAPM_PRE_PMU),
SND_SOC_DAPM_SUPPLY("DMIC Power", RT5691_DMIC_CTRL, 7, 0, NULL, 0),
/* Boost */
SND_SOC_DAPM_PGA_E("BST1", SND_SOC_NOPM,
0, 0, NULL, 0, rt5691_bst1_event,
SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD),
SND_SOC_DAPM_PGA("BST2", SND_SOC_NOPM,
0, 0, NULL, 0),
SND_SOC_DAPM_PGA("BST3", SND_SOC_NOPM,
0, 0, NULL, 0),
SND_SOC_DAPM_SUPPLY("BST1 Power", RT5691_PWR_ANLG_2,
RT5691_PWR_BST1_BIT, 0, NULL, 0),
SND_SOC_DAPM_SUPPLY("BST2 Power", RT5691_PWR_ANLG_2,
RT5691_PWR_BST2_BIT, 0, NULL, 0),
SND_SOC_DAPM_SUPPLY("BST3 Power", RT5691_PWR_ANLG_2,
RT5691_PWR_BST3_BIT, 0, NULL, 0),
/* ADCs */
SND_SOC_DAPM_ADC("ADC1", NULL, SND_SOC_NOPM, 0, 0),
SND_SOC_DAPM_ADC("ADC2", NULL, SND_SOC_NOPM, 0, 0),
SND_SOC_DAPM_ADC("ADC3", NULL, SND_SOC_NOPM, 0, 0),
SND_SOC_DAPM_SUPPLY("ADC1 Power", RT5691_PWR_DIG_1, 5, 0, NULL, 0),
SND_SOC_DAPM_SUPPLY("ADC2 Power", RT5691_PWR_DIG_1, 4, 0, NULL, 0),
SND_SOC_DAPM_SUPPLY("ADC3 Power", RT5691_PWR_DIG_1, 3, 0, NULL, 0),
SND_SOC_DAPM_SUPPLY("ADC12 clock", RT5691_ADC12_CTRL, 12, 0, NULL, 0),
SND_SOC_DAPM_SUPPLY("ADC34 clock", RT5691_ADC34_CTRL, 12, 0, NULL, 0),
/* Sidetone */
SND_SOC_DAPM_MUX("Sidetone Mux", SND_SOC_NOPM, 0, 0,
&rt5691_st_mux),
/* ADC Mux */
SND_SOC_DAPM_MUX("Stereo1 ADC L1 Mux", SND_SOC_NOPM, 0, 0,
&rt5691_sto1_adc1l_mux),
SND_SOC_DAPM_MUX("Stereo1 ADC R1 Mux", SND_SOC_NOPM, 0, 0,
&rt5691_sto1_adc1r_mux),
SND_SOC_DAPM_MUX("Stereo1 ADC L2 Mux", SND_SOC_NOPM, 0, 0,
&rt5691_sto1_adc2l_mux),
SND_SOC_DAPM_MUX("Stereo1 ADC R2 Mux", SND_SOC_NOPM, 0, 0,
&rt5691_sto1_adc2r_mux),
SND_SOC_DAPM_MUX("Stereo1 ADC L Mux", SND_SOC_NOPM, 0, 0,
&rt5691_sto1_adcl_mux),
SND_SOC_DAPM_MUX("Stereo1 ADC R Mux", SND_SOC_NOPM, 0, 0,
&rt5691_sto1_adcr_mux),
SND_SOC_DAPM_MUX("Stereo2 ADC L1 Mux", SND_SOC_NOPM, 0, 0,
&rt5691_sto2_adc1l_mux),
SND_SOC_DAPM_MUX("Stereo2 ADC R1 Mux", SND_SOC_NOPM, 0, 0,
&rt5691_sto2_adc1r_mux),
SND_SOC_DAPM_MUX("Stereo2 ADC L2 Mux", SND_SOC_NOPM, 0, 0,
&rt5691_sto2_adc2l_mux),
SND_SOC_DAPM_MUX("Stereo2 ADC R2 Mux", SND_SOC_NOPM, 0, 0,
&rt5691_sto2_adc2r_mux),
SND_SOC_DAPM_MUX("Stereo2 ADC L Mux", SND_SOC_NOPM, 0, 0,
&rt5691_sto2_adcl_mux),
SND_SOC_DAPM_MUX("Stereo2 ADC R Mux", SND_SOC_NOPM, 0, 0,
&rt5691_sto2_adcr_mux),
/* ADC Mixer */
SND_SOC_DAPM_SUPPLY("ADC Stereo1 Filter", RT5691_PWR_AD_PATH,
0, 0, NULL, 0),
SND_SOC_DAPM_MIXER_E("Stereo1 ADC MIXL", SND_SOC_NOPM,
0, 0, rt5691_sto1_adc_l_mix, ARRAY_SIZE(rt5691_sto1_adc_l_mix),
rt5691_sto1_l_adc_depop_event,
SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_PRE_PMD),
SND_SOC_DAPM_MIXER_E("Stereo1 ADC MIXR", SND_SOC_NOPM,
0, 0, rt5691_sto1_adc_r_mix, ARRAY_SIZE(rt5691_sto1_adc_r_mix),
rt5691_sto1_r_adc_depop_event,
SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_PRE_PMD),
SND_SOC_DAPM_SUPPLY("ADC Stereo2 Filter", RT5691_PWR_AD_PATH,
1, 0, NULL, 0),
SND_SOC_DAPM_MIXER_E("Stereo2 ADC MIXL", SND_SOC_NOPM,
0, 0, rt5691_sto2_adc_l_mix, ARRAY_SIZE(rt5691_sto2_adc_l_mix),
rt5691_sto2_l_adc_depop_event,
SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_PRE_PMD),
SND_SOC_DAPM_MIXER_E("Stereo2 ADC MIXR", SND_SOC_NOPM,
0, 0, rt5691_sto2_adc_r_mix, ARRAY_SIZE(rt5691_sto2_adc_r_mix),
rt5691_sto2_r_adc_depop_event,
SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_PRE_PMD),
SND_SOC_DAPM_SUPPLY("ADC Stereo FIFO", RT5691_PWR_AD_PATH,
5, 0, NULL, 0),
/* ADC PGA */
SND_SOC_DAPM_PGA("Stereo1 ADC MIX", SND_SOC_NOPM, 0, 0, NULL, 0),
SND_SOC_DAPM_PGA("Stereo2 ADC MIX", SND_SOC_NOPM, 0, 0, NULL, 0),
/* Digital Interface */
SND_SOC_DAPM_SUPPLY("I2S", RT5691_I2S, 0, 0, NULL, 0),
SND_SOC_DAPM_PGA("IF DAC", SND_SOC_NOPM, 0, 0, NULL, 0),
SND_SOC_DAPM_PGA("IF DAC L", SND_SOC_NOPM, 0, 0, NULL, 0),
SND_SOC_DAPM_PGA("IF DAC R", SND_SOC_NOPM, 0, 0, NULL, 0),
/* Digital Interface Select */
SND_SOC_DAPM_MUX("IF ADC Mux", SND_SOC_NOPM, 0, 0,
&rt5691_if_adc_mux),
SND_SOC_DAPM_MUX("IF ADC Swap Mux", SND_SOC_NOPM, 0, 0,
&rt5691_if_data_adc_mux),
SND_SOC_DAPM_MUX("IF DAC Swap Mux", SND_SOC_NOPM, 0, 0,
&rt5691_if_data_dac_mux),
/* Audio Interface */
SND_SOC_DAPM_AIF_IN("AIF RX", "AIF Playback", 0, SND_SOC_NOPM, 0, 0),
SND_SOC_DAPM_AIF_OUT("AIF TX", "AIF Capture", 0, SND_SOC_NOPM, 0, 0),
/* Output Side */
/* DAC mixer before sound effect */
SND_SOC_DAPM_MIXER("DAC MIXL", SND_SOC_NOPM, 0, 0,
rt5691_dac_l_mix, ARRAY_SIZE(rt5691_dac_l_mix)),
SND_SOC_DAPM_MIXER("DAC MIXR", SND_SOC_NOPM, 0, 0,
rt5691_dac_r_mix, ARRAY_SIZE(rt5691_dac_r_mix)),
/* DAC channel Mux */
SND_SOC_DAPM_MUX("DAC2 Mux", SND_SOC_NOPM, 0, 0, &rt5691_dac2_mux),
/* DAC Mixer */
SND_SOC_DAPM_SUPPLY("DAC FIFO Stereo", RT5691_PWR_DA_PATH_1, 11, 0,
NULL, 0),
SND_SOC_DAPM_SUPPLY("DAC FIFO Mono", RT5691_PWR_DA_PATH_1, 12, 0,
NULL, 0),
SND_SOC_DAPM_MIXER("Stereo DAC MIXL", SND_SOC_NOPM, 0, 0,
rt5691_sto_dac_l_mix, ARRAY_SIZE(rt5691_sto_dac_l_mix)),
SND_SOC_DAPM_MIXER("Stereo DAC MIXR", SND_SOC_NOPM, 0, 0,
rt5691_sto_dac_r_mix, ARRAY_SIZE(rt5691_sto_dac_r_mix)),
/* DACs */
SND_SOC_DAPM_SUPPLY("DAC Stereo", RT5691_PWR_DA_PATH_1, 0, 0, NULL, 0),
SND_SOC_DAPM_SUPPLY("DAC Mono", RT5691_PWR_DA_PATH_1, 1, 0, NULL, 0),
SND_SOC_DAPM_DAC("DACL", NULL, SND_SOC_NOPM, 0, 0),
SND_SOC_DAPM_DAC("DACR", NULL, SND_SOC_NOPM, 0, 0),
SND_SOC_DAPM_DAC("DACM", NULL, SND_SOC_NOPM, 0, 0),
SND_SOC_DAPM_PGA("DAC1 MIX", SND_SOC_NOPM, 0, 0, NULL, 0),
SND_SOC_DAPM_PGA("DACL2", SND_SOC_NOPM, 0, 0, NULL, 0),
SND_SOC_DAPM_SUPPLY("DACM Power", RT5691_PWR_DIG_1, 7, 0, NULL, 0),
SND_SOC_DAPM_SUPPLY_S("DACL Clock", 1, RT5691_PWR_DA_PATH_2,
0, 0, NULL, 0),
SND_SOC_DAPM_SUPPLY_S("DACR Clock", 1, RT5691_PWR_DA_PATH_2,
1, 0, NULL, 0),
SND_SOC_DAPM_SUPPLY_S("DACM Clock", 1, RT5691_PWR_DA_PATH_2,
2, 0, NULL, 0),
SND_SOC_DAPM_SUPPLY_S("HP Clock", 1, RT5691_PWR_DA_PATH_2,
5, 0, NULL, 0),
SND_SOC_DAPM_PGA_S("HP Amp", 1, SND_SOC_NOPM, 0, 0, rt5691_hp_event,
SND_SOC_DAPM_POST_PMD | SND_SOC_DAPM_PRE_PMU),
SND_SOC_DAPM_PGA_S("Mono Amp", 1, RT5691_PWR_ANLG_1, RT5691_PWR_MA_BIT,
0, rt5691_mono_event,
SND_SOC_DAPM_POST_PMD | SND_SOC_DAPM_PRE_PMU),
SND_SOC_DAPM_SWITCH("Mono Playback", SND_SOC_NOPM, 0, 0,
&rt5691_mono_switch),
SND_SOC_DAPM_SWITCH("PDM L Playback", SND_SOC_NOPM, 0, 0,
&rt5691_pdm_l_switch),
SND_SOC_DAPM_SWITCH("PDM R Playback", SND_SOC_NOPM, 0, 0,
&rt5691_pdm_r_switch),
/* PDM */
SND_SOC_DAPM_SUPPLY("PDM CLK", RT5691_PWR_DA_PATH_1, 15, 0,
rt5691_set_pdm_clk, SND_SOC_DAPM_PRE_PMU),
SND_SOC_DAPM_MUX("PDM L Mux", SND_SOC_NOPM, 0, 0, &rt5691_pdm_l_mux),
SND_SOC_DAPM_MUX("PDM R Mux", SND_SOC_NOPM, 0, 0, &rt5691_pdm_r_mux),
/* Output Lines */
SND_SOC_DAPM_OUTPUT("HPOL"),
SND_SOC_DAPM_OUTPUT("HPOR"),
SND_SOC_DAPM_OUTPUT("MONOOUT"),
SND_SOC_DAPM_OUTPUT("PDML"),
SND_SOC_DAPM_OUTPUT("PDMR"),
};
static const struct snd_soc_dapm_route rt5691_dapm_routes[] = {
{"MICBIAS1", NULL, "Vref1"},
{"MICBIAS1", NULL, "Vref2"},
{"MICBIAS1", NULL, "LDO MICBIAS1"},
{"MICBIAS2", NULL, "Vref1"},
{"MICBIAS2", NULL, "Vref2"},
{"MICBIAS2", NULL, "LDO MICBIAS2"},
{"MICBIAS3", NULL, "Vref1"},
{"MICBIAS3", NULL, "Vref2"},
{"MICBIAS3", NULL, "LDO MICBIAS3"},
{"CLKDET HP", NULL, "CLKDET"},
{"CLKDET MONO", NULL, "CLKDET"},
{"BST1", NULL, "IN1P"},
{"BST1", NULL, "IN1N"},
{"BST1", NULL, "BST1 Power"},
{"BST2", NULL, "IN2P"},
{"BST2", NULL, "IN2N"},
{"BST2", NULL, "BST2 Power"},
{"BST3", NULL, "IN3P"},
{"BST3", NULL, "IN3N"},
{"BST3", NULL, "BST3 Power"},
{"ADC1", NULL, "BST1"},
{"ADC1", NULL, "ADC1 Power"},
{"ADC1", NULL, "ADC12 clock"},
{"ADC1", NULL, "Vref1"},
{"ADC1", NULL, "Vref2"},
{"ADC2", NULL, "BST2"},
{"ADC2", NULL, "ADC2 Power"},
{"ADC2", NULL, "ADC12 clock"},
{"ADC2", NULL, "Vref1"},
{"ADC2", NULL, "Vref2"},
{"ADC3", NULL, "BST3"},
{"ADC3", NULL, "ADC3 Power"},
{"ADC3", NULL, "ADC34 clock"},
{"ADC3", NULL, "Vref1"},
{"ADC3", NULL, "Vref2"},
{"DMICL", NULL, "DMIC CLK"},
{"DMICL", NULL, "DMIC Power"},
{"DMICR", NULL, "DMIC CLK"},
{"DMICR", NULL, "DMIC Power"},
{"Sidetone Mux", "ADC1", "ADC1"},
{"Sidetone Mux", "ADC2", "ADC2"},
{"Sidetone Mux", "DMICL", "DMICL"},
{"Sidetone Mux", "DMICR", "DMICR"},
{"Stereo1 ADC L Mux", "ADC1", "ADC1"},
{"Stereo1 ADC L Mux", "ADC2", "ADC2"},
{"Stereo1 ADC L Mux", "ADC3", "ADC3"},
{"Stereo1 ADC R Mux", "ADC1", "ADC1"},
{"Stereo1 ADC R Mux", "ADC2", "ADC2"},
{"Stereo1 ADC R Mux", "ADC3", "ADC3"},
{"Stereo1 ADC L1 Mux", "DACL2", "DACL2"},
{"Stereo1 ADC L1 Mux", "STO1 ADC", "Stereo1 ADC L Mux"},
{"Stereo1 ADC R1 Mux", "DACL2", "DACL2"},
{"Stereo1 ADC R1 Mux", "STO1 ADC", "Stereo1 ADC R Mux"},
{"Stereo1 ADC L2 Mux", "DAC MIX", "DAC MIXL"},
{"Stereo1 ADC L2 Mux", "DMIC", "DMICL"},
{"Stereo1 ADC R2 Mux", "DAC MIX", "DAC MIXR"},
{"Stereo1 ADC R2 Mux", "DMIC", "DMICR"},
{"Stereo1 ADC MIXL", "ADC1 Switch", "Stereo1 ADC L1 Mux"},
{"Stereo1 ADC MIXL", "ADC2 Switch", "Stereo1 ADC L2 Mux"},
{"Stereo1 ADC MIXL", NULL, "ADC Stereo1 Filter"},
{"Stereo1 ADC MIXL", NULL, "ADC Stereo FIFO"},
{"Stereo1 ADC MIXR", "ADC1 Switch", "Stereo1 ADC R1 Mux"},
{"Stereo1 ADC MIXR", "ADC2 Switch", "Stereo1 ADC R2 Mux"},
{"Stereo1 ADC MIXR", NULL, "ADC Stereo1 Filter"},
{"Stereo1 ADC MIXR", NULL, "ADC Stereo FIFO"},
{"Stereo2 ADC L Mux", "ADC1", "ADC1"},
{"Stereo2 ADC L Mux", "ADC2", "ADC2"},
{"Stereo2 ADC L Mux", "ADC3", "ADC3"},
{"Stereo2 ADC R Mux", "ADC1", "ADC1"},
{"Stereo2 ADC R Mux", "ADC2", "ADC2"},
{"Stereo2 ADC R Mux", "ADC3", "ADC3"},
{"Stereo2 ADC L1 Mux", "DACL2", "DACL2"},
{"Stereo2 ADC L1 Mux", "STO2 ADC", "Stereo2 ADC L Mux"},
{"Stereo2 ADC R1 Mux", "DACL2", "DACL2"},
{"Stereo2 ADC R1 Mux", "STO2 ADC", "Stereo2 ADC R Mux"},
{"Stereo2 ADC L2 Mux", "DAC MIX", "DAC MIXL"},
{"Stereo2 ADC L2 Mux", "DMIC", "DMICL"},
{"Stereo2 ADC R2 Mux", "DAC MIX", "DAC MIXR"},
{"Stereo2 ADC R2 Mux", "DMIC", "DMICR"},
{"Stereo2 ADC MIXL", "ADC1 Switch", "Stereo2 ADC L1 Mux"},
{"Stereo2 ADC MIXL", "ADC2 Switch", "Stereo2 ADC L2 Mux"},
{"Stereo2 ADC MIXL", NULL, "ADC Stereo2 Filter"},
{"Stereo2 ADC MIXL", NULL, "ADC Stereo FIFO"},
{"Stereo2 ADC MIXR", "ADC1 Switch", "Stereo2 ADC R1 Mux"},
{"Stereo2 ADC MIXR", "ADC2 Switch", "Stereo2 ADC R2 Mux"},
{"Stereo2 ADC MIXR", NULL, "ADC Stereo2 Filter"},
{"Stereo2 ADC MIXR", NULL, "ADC Stereo FIFO"},
{"Stereo1 ADC MIX", NULL, "Stereo1 ADC MIXL"},
{"Stereo1 ADC MIX", NULL, "Stereo1 ADC MIXR"},
{"Stereo2 ADC MIX", NULL, "Stereo2 ADC MIXL"},
{"Stereo2 ADC MIX", NULL, "Stereo2 ADC MIXR"},
{"IF ADC Mux", "STO1 ADC", "Stereo1 ADC MIX"},
{"IF ADC Mux", "STO2 ADC", "Stereo2 ADC MIX"},
{"IF ADC Mux", "DAC", "DAC1 MIX"},
{"IF ADC Swap Mux", "L/R", "IF ADC Mux"},
{"IF ADC Swap Mux", "R/L", "IF ADC Mux"},
{"IF ADC Swap Mux", "L/L", "IF ADC Mux"},
{"IF ADC Swap Mux", "R/R", "IF ADC Mux"},
{"AIF TX", NULL, "IF ADC Swap Mux"},
{"AIF TX", NULL, "I2S"},
{"AIF TX", NULL, "RECORD CLK"},
{"AIF RX", NULL, "I2S"},
{"AIF RX", NULL, "PLAY CLK"},
{"IF DAC Swap Mux", "L/R", "AIF RX"},
{"IF DAC Swap Mux", "R/L", "AIF RX"},
{"IF DAC Swap Mux", "L/L", "AIF RX"},
{"IF DAC Swap Mux", "R/R", "AIF RX"},
{"IF DAC", NULL, "IF DAC Swap Mux"},
{"IF DAC L", NULL, "IF DAC"},
{"IF DAC R", NULL, "IF DAC"},
{"DAC MIXL", "Stereo ADC Switch", "Stereo1 ADC MIXL"},
{"DAC MIXL", "DAC1 Switch", "IF DAC L"},
{"DAC MIXR", "Stereo ADC Switch", "Stereo1 ADC MIXR"},
{"DAC MIXR", "DAC1 Switch", "IF DAC R"},
{"DAC1 MIX", NULL, "DAC MIXL"},
{"DAC1 MIX", NULL, "DAC MIXR"},
{"Stereo DAC MIXL", "DAC L1 Switch", "DAC MIXL"},
{"Stereo DAC MIXL", "DAC R1 Switch", "DAC MIXR"},
{"Stereo DAC MIXL", "Sidetone Switch", "Sidetone Mux"},
{"Stereo DAC MIXL", NULL, "DAC Stereo"},
{"Stereo DAC MIXL", NULL, "DAC FIFO Stereo"},
{"Stereo DAC MIXR", "DAC L1 Switch", "DAC MIXL"},
{"Stereo DAC MIXR", "DAC R1 Switch", "DAC MIXR"},
{"Stereo DAC MIXR", "Sidetone Switch", "Sidetone Mux"},
{"Stereo DAC MIXR", NULL, "DAC Stereo"},
{"Stereo DAC MIXR", NULL, "DAC FIFO Stereo"},
{"DACL", NULL, "Stereo DAC MIXL"},
{"DACL", NULL, "DACL Clock"},
{"DACR", NULL, "Stereo DAC MIXR"},
{"DACR", NULL, "DACR Clock"},
{"DACL2", NULL, "IF DAC L"},
{"DACL2", NULL, "DAC Mono"},
{"DACL2", NULL, "DAC FIFO Mono"},
{"DAC2 Mux", "STO1 DAC Mixer", "Stereo DAC MIXL"},
{"DAC2 Mux", "DAC2", "DACL2"},
{"DACM", NULL, "DAC2 Mux"},
{"DACM", NULL, "DACM Clock"},
{"DACM", NULL, "DACM Power"},
{"PDM L Mux", "Stereo1 DAC", "Stereo DAC MIXL"},
{"PDM L Mux", "DAC2", "DACL2"},
{"PDM L Mux", "Sidetone", "Sidetone Mux"},
{"PDM L Mux", NULL, "PDM CLK"},
{"PDM R Mux", "Stereo1 DAC", "Stereo DAC MIXR"},
{"PDM R Mux", "DAC2", "DACL2"},
{"PDM R Mux", "Sidetone", "Sidetone Mux"},
{"PDM R Mux", NULL, "PDM CLK"},
{"HP Amp", NULL, "DACL"},
{"HP Amp", NULL, "DACR"},
{"HP Amp", NULL, "Vref1"},
{"HP Amp", NULL, "Vref2"},
{"HP Amp", NULL, "RC 1M"},
{"HP Amp", NULL, "HP Clock"},
{"HP Amp", NULL, "CLKDET HP"},
{"HPOL", NULL, "HP Amp"},
{"HPOR", NULL, "HP Amp"},
{"Mono Amp", NULL, "DACM"},
{"Mono Amp", NULL, "Vref1"},
{"Mono Amp", NULL, "Vref2"},
{"Mono Amp", NULL, "Vref3"},
{"Mono Amp", NULL, "RC 1M"},
{"Mono Amp", NULL, "CLKDET MONO"},
{"Mono Playback", "Switch", "Mono Amp"},
{"MONOOUT", NULL, "Mono Playback"},
{"PDM L Playback", "Switch", "PDM L Mux"},
{"PDM R Playback", "Switch", "PDM R Mux"},
{"PDML", NULL, "PDM L Playback"},
{"PDMR", NULL, "PDM R Playback"},
};
static int rt5691_hw_params(struct snd_pcm_substream *substream,
struct snd_pcm_hw_params *params, struct snd_soc_dai *dai)
{
struct snd_soc_component *component = dai->component;
struct rt5691_priv *rt5691 = snd_soc_component_get_drvdata(component);
int sys_div, osr_div, val = 0;
rt5691->lrck = params_rate(params);
sys_div = rt5691_calc_clk_div(rt5691, 256, 0);
if (sys_div < 0) {
dev_err(component->dev, "Unsupported clock setting %d for DAI %d\n",
rt5691->lrck, dai->id);
return -EINVAL;
}
dev_dbg(dai->dev, "lrck is %dHz and sys_div is %d for iis %d\n",
rt5691->lrck, sys_div, dai->id);
snd_soc_component_update_bits(component, RT5691_DA_STO1_FILTER_CLK_DIV,
0x0f0f, ((sys_div + 1) << 8) | (sys_div + 1));
snd_soc_component_update_bits(component, RT5691_AD_STO1_FILTER_CLK_DIV,
0x0f0f, ((sys_div + 1) << 8) | (sys_div + 1));
osr_div = rt5691_calc_clk_div(rt5691, 0, 12288000);
snd_soc_component_update_bits(component, RT5691_ADC_AND_DAC_OSR,
0x0f0f, ((osr_div + 1) << 8) | (osr_div + 1));
switch (params_width(params)) {
case 16:
val = 1;
break;
case 20:
val = 2;
break;
case 24:
val = 3;
break;
case 32:
val = 4;
break;
default:
return -EINVAL;
}
snd_soc_component_update_bits(component, RT5691_I2S_CTRL_1,
0x70, val << 4);
return 0;
}
static int rt5691_set_dai_fmt(struct snd_soc_dai *dai, unsigned int fmt)
{
struct snd_soc_component *component = dai->component;
struct rt5691_priv *rt5691 = snd_soc_component_get_drvdata(component);
unsigned int reg_val = 0;
switch (fmt & SND_SOC_DAIFMT_MASTER_MASK) {
case SND_SOC_DAIFMT_CBM_CFM:
rt5691->master = 1;
break;
case SND_SOC_DAIFMT_CBS_CFS:
reg_val |= (0x1 << 3);
rt5691->master = 0;
break;
default:
return -EINVAL;
}
switch (fmt & SND_SOC_DAIFMT_INV_MASK) {
case SND_SOC_DAIFMT_NB_NF:
break;
case SND_SOC_DAIFMT_IB_NF:
reg_val |= (0x1 << 13);
break;
default:
return -EINVAL;
}
switch (fmt & SND_SOC_DAIFMT_FORMAT_MASK) {
case SND_SOC_DAIFMT_I2S:
break;
case SND_SOC_DAIFMT_LEFT_J:
reg_val |= 0x1;
break;
case SND_SOC_DAIFMT_DSP_A:
reg_val |= 0x2;
break;
case SND_SOC_DAIFMT_DSP_B:
reg_val |= 0x3;
break;
default:
return -EINVAL;
}
snd_soc_component_update_bits(component, RT5691_I2S_CTRL_1,
0x200f, reg_val);
return 0;
}
static int rt5691_set_component_sysclk(struct snd_soc_component *component,
int clk_id, int source, unsigned int freq, int dir)
{
struct rt5691_priv *rt5691 = snd_soc_component_get_drvdata(component);
unsigned int reg_val = 0;
switch (clk_id) {
case RT5691_SCLK_S_MCLK:
break;
case RT5691_SCLK_S_PLL1:
reg_val |= (0x1 << 2);
snd_soc_component_update_bits(component, RT5691_PLLA_CTRL_2,
0xc400, 0xc400);
snd_soc_component_update_bits(component, RT5691_PLLA_CTRL_3,
0x4000, 0x4000);
snd_soc_component_update_bits(component, RT5691_PLL_CTRL_2,
0x1, 0x1);
break;
case RT5691_SCLK_S_PLL2:
reg_val |= (0x2 << 2);
break;
case RT5691_SCLK_S_RCCLK:
reg_val |= (0x3 << 2);
break;
default:
dev_err(component->dev, "Invalid clock id (%d)\n", clk_id);
return -EINVAL;
}
snd_soc_component_update_bits(component, RT5691_SYS_CLK_SRC,
0xc, reg_val);
rt5691->sysclk = freq;
rt5691->sysclk_src = clk_id;
dev_dbg(component->dev, "Sysclk is %dHz and clock id is %d\n", freq, clk_id);
return 0;
}
static const struct rt5691_pll_calc_map rt5691_pll_preset_table[] = {
{false, 19200000, 24576000, 3, 30, 3, false, false},
};
int rt5691_plla_calc(struct rt5691_priv *rt5691, const unsigned int freq_in,
const unsigned int freq_out, struct rt5691_pll_code *pll_code)
{
struct snd_soc_component *component = rt5691->component;
int max_n = RT5691_PLL_N_MAX, max_m = RT5691_PLL_M_MAX;
int k, red, n_t, pll_out, in_t, out_t;
int n = 0, m = 0, m_t = 0;
int red_t = abs(freq_out - freq_in);
bool m_bypass = false, k_bypass = false;
if (RT5691_PLL_INP_MAX < freq_in || RT5691_PLL_INP_MIN > freq_in)
return -EINVAL;
k = 100000000 / freq_out - 2;
if (k > RT5691_PLL_K_MAX)
k = RT5691_PLL_K_MAX;
if (k < 0) {
k = 0;
k_bypass = true;
}
for (n_t = 0; n_t <= max_n; n_t++) {
in_t = freq_in / (k_bypass ? 1 : (k + 2));
pll_out = freq_out / (n_t + 2);
if (in_t < 0)
continue;
if (in_t == pll_out) {
m_bypass = true;
n = n_t;
goto code_find;
}
red = abs(in_t - pll_out);
if (red < red_t) {
m_bypass = true;
n = n_t;
m = m_t;
if (red == 0)
goto code_find;
red_t = red;
}
for (m_t = 0; m_t <= max_m; m_t++) {
out_t = in_t / (m_t + 2);
red = abs(out_t - pll_out);
if (red < red_t) {
m_bypass = false;
n = n_t;
m = m_t;
if (red == 0)
goto code_find;
red_t = red;
}
}
}
dev_dbg(component->dev, "Only get approximation about PLL\n");
code_find:
pll_code->plla_m_bp = m_bypass;
pll_code->plla_k_bp = k_bypass;
pll_code->plla_m_code = m;
pll_code->plla_n_code = n;
pll_code->plla_k_code = k;
return 0;
}
static int rt5691_set_component_pll(struct snd_soc_component *component,
int pll_id, int source, unsigned int freq_in,
unsigned int freq_out)
{
struct rt5691_priv *rt5691 = snd_soc_component_get_drvdata(component);
struct rt5691_pll_code pll_code = {0};
int ret, i;
if (source == rt5691->pll_src && freq_in == rt5691->pll_in &&
freq_out == rt5691->pll_out)
return 0;
if (!freq_in || !freq_out) {
dev_dbg(component->dev, "PLL disabled\n");
rt5691->pll_in = 0;
rt5691->pll_out = 0;
snd_soc_component_update_bits(component, RT5691_PLL_CTRL_2,
0x30, 0x0);
return 0;
}
switch (source) {
case RT5691_PLL1_S_MCLK:
snd_soc_component_update_bits(component, RT5691_PLL_CTRL_2,
0x30, 0x0);
break;
case RT5691_PLL1_S_BCLK:
snd_soc_component_update_bits(component, RT5691_PLL_CTRL_2,
0x30, 0x10);
break;
default:
dev_err(component->dev, "Unknown PLL Source %d\n", source);
return -EINVAL;
}
for (i = 0; i < ARRAY_SIZE(rt5691_pll_preset_table); i++) {
if (freq_in == rt5691_pll_preset_table[i].pll_in &&
freq_out == rt5691_pll_preset_table[i].pll_out) {
pll_code.plla_k_code = rt5691_pll_preset_table[i].plla_k;
pll_code.plla_m_code = rt5691_pll_preset_table[i].plla_m;
pll_code.plla_n_code = rt5691_pll_preset_table[i].plla_n;
pll_code.plla_m_bp = rt5691_pll_preset_table[i].plla_m_bp;
pll_code.plla_k_bp = rt5691_pll_preset_table[i].plla_k_bp;
if (rt5691_pll_preset_table[i].use_pllb) {
pll_code.use_pllb = rt5691_pll_preset_table[i].use_pllb;
pll_code.pllb_k_code = rt5691_pll_preset_table[i].pllb_k;
pll_code.pllb_m_code = rt5691_pll_preset_table[i].pllb_m;
pll_code.pllb_n_code = rt5691_pll_preset_table[i].pllb_n;
pll_code.pllb_m_bp = rt5691_pll_preset_table[i].pllb_m_bp;
pll_code.pllb_k_bp = rt5691_pll_preset_table[i].pllb_k_bp;
pll_code.pllb_pulse = rt5691_pll_preset_table[i].pllb_pulse;
}
dev_dbg(component->dev, "Use preset PLL parameter table\n");
goto set_pll;
}
}
ret = rt5691_plla_calc(rt5691, freq_in, freq_out, &pll_code);
if (ret < 0) {
dev_err(component->dev, "Unsupport input clock %d\n", freq_in);
return ret;
}
set_pll:
dev_dbg(component->dev, "PLLA m_bypass=%d m=%d n=%d k_bypass=%d k=%d\n",
pll_code.plla_m_bp,
(pll_code.plla_m_bp ? 0 : pll_code.plla_m_code),
pll_code.plla_n_code, pll_code.plla_k_bp,
(pll_code.plla_k_bp ? 0 : pll_code.plla_k_code));
snd_soc_component_write(component, RT5691_PLLA_CTRL_1,
(pll_code.plla_k_bp ? 0 : pll_code.plla_k_code) << 8 |
(pll_code.plla_m_bp ? 0 : pll_code.plla_m_code) |
pll_code.plla_m_bp << 14 | pll_code.plla_k_bp << 15);
snd_soc_component_update_bits(component, RT5691_PLLA_CTRL_2,
RT5691_PLL_N_MAX, pll_code.plla_n_code);
if (pll_code.use_pllb) {
dev_dbg(component->dev, "PLLB m_bypass=%d m=%d n=%d k_bypass=%d k=%d pulse=%d\n",
pll_code.pllb_m_bp,
(pll_code.pllb_m_bp ? 0 : pll_code.pllb_m_code),
pll_code.pllb_n_code, pll_code.pllb_k_bp,
(pll_code.pllb_k_bp ? 0 : pll_code.pllb_k_code),
pll_code.pllb_pulse);
snd_soc_component_write(component, RT5691_PLLB_CTRL_1,
(pll_code.pllb_k_bp ? 0 : pll_code.pllb_k_code) << 8 |
(pll_code.pllb_m_bp ? 0 : pll_code.pllb_m_code) |
pll_code.pllb_m_bp << 14 | pll_code.pllb_k_bp << 15);
snd_soc_component_update_bits(component, RT5691_PLLB_CTRL_2,
RT5691_PLL_N_MAX, pll_code.pllb_n_code);
snd_soc_component_update_bits(component, RT5691_PLLB_CTRL_4,
1 << 15, pll_code.pllb_pulse << 15);
}
rt5691->pll_in = freq_in;
rt5691->pll_out = freq_out;
rt5691->pll_src = source;
return 0;
}
static int rt5691_set_bias_level(struct snd_soc_component *component,
enum snd_soc_bias_level level)
{
struct rt5691_priv *rt5691 = snd_soc_component_get_drvdata(component);
switch (level) {
case SND_SOC_BIAS_ON:
break;
case SND_SOC_BIAS_PREPARE:
regmap_update_bits(rt5691->regmap, RT5691_SYS_CLK_SRC,
0x41, 0x41);
break;
case SND_SOC_BIAS_STANDBY:
regmap_update_bits(rt5691->regmap, RT5691_PWR_DIG_1,
0x1 << 8, 0x1 << 8);
regmap_update_bits(rt5691->regmap, RT5691_PWR_ANLG_1,
RT5691_PWR_MB | RT5691_PWR_BG,
RT5691_PWR_MB | RT5691_PWR_BG);
regmap_update_bits(rt5691->regmap, RT5691_SYS_CLK_SRC, 0x41, 0);
if (snd_soc_component_get_bias_level(component) == SND_SOC_BIAS_PREPARE) {
regmap_update_bits(rt5691->regmap, RT5691_PLL_CTRL_2, 0x1, 0);
snd_soc_component_update_bits(component, RT5691_PLLA_CTRL_2,
0xc400, 0);
snd_soc_component_update_bits(component, RT5691_PLLA_CTRL_3,
0x4000, 0);
}
break;
case SND_SOC_BIAS_OFF:
regmap_update_bits(rt5691->regmap, RT5691_PWR_DIG_1,
0x1 << 8, 0);
regmap_update_bits(rt5691->regmap, RT5691_PWR_ANLG_1,
RT5691_PWR_MB | RT5691_PWR_BG, 0);
break;
default:
break;
}
return 0;
}
static int rt5691_probe(struct snd_soc_component *component)
{
struct rt5691_priv *rt5691 = snd_soc_component_get_drvdata(component);
int ret = 0;
rt5691->component = component;
schedule_delayed_work(&rt5691->calibrate_work, msecs_to_jiffies(100));
return ret;
}
static void rt5691_remove(struct snd_soc_component *component)
{
struct rt5691_priv *rt5691 = snd_soc_component_get_drvdata(component);
rt5691->cal_done = true;
cancel_delayed_work_sync(&rt5691->calibrate_work);
regmap_write(rt5691->regmap, RT5691_RESET, 0);
}
#ifdef CONFIG_PM
static int rt5691_suspend(struct snd_soc_component *component)
{
dev_info(component->dev, "%s\n", __func__);
return 0;
}
static int rt5691_resume(struct snd_soc_component *component)
{
dev_info(component->dev, "%s\n", __func__);
return 0;
}
#else
#define rt5691_suspend NULL
#define rt5691_resume NULL
#endif
#define RT5691_STEREO_RATES SNDRV_PCM_RATE_8000_192000
#define RT5691_FORMATS (SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S20_3LE | \
SNDRV_PCM_FMTBIT_S24_LE | SNDRV_PCM_FMTBIT_S8 | \
SNDRV_PCM_FMTBIT_S32_LE)
static const struct snd_soc_dai_ops rt5691_aif_dai_ops = {
.hw_params = rt5691_hw_params,
.set_fmt = rt5691_set_dai_fmt,
};
static struct snd_soc_dai_driver rt5691_dai[] = {
{
.name = "rt5691-aif",
.playback = {
.stream_name = "AIF Playback",
.channels_min = 1,
.channels_max = 8,
.rates = RT5691_STEREO_RATES,
.formats = RT5691_FORMATS,
},
.capture = {
.stream_name = "AIF Capture",
.channels_min = 1,
.channels_max = 8,
.rates = RT5691_STEREO_RATES,
.formats = RT5691_FORMATS,
},
.ops = &rt5691_aif_dai_ops,
},
};
static int rt5691_set_jack_detect(struct snd_soc_component *component,
struct snd_soc_jack *hs_jack, void *data)
{
struct rt5691_priv *rt5691 = snd_soc_component_get_drvdata(component);
if (!rt5691->pdata.jd_src)
return 0;
regmap_update_bits(rt5691->regmap, RT5691_BGLDO33_CTRL_1,
0x1 << 15, 0x1 << 15);
regmap_update_bits(rt5691->regmap, RT5691_MULTI_FUNC_PIN_CTRL_1,
0x1 << 15, 0x1 << 15);
regmap_update_bits(rt5691->regmap, RT5691_RC_CLK_CTRL,
0xf << 12, 0xf << 12);
regmap_write(rt5691->regmap, RT5691_IRQ_CTRL_6, 0x6102);
switch (rt5691->pdata.jd_src) {
case RT5691_JD1:
regmap_update_bits(rt5691->regmap, RT5691_WATER_DET_CTRL_1,
0x1 << 8, 0x1 << 8);
regmap_update_bits(rt5691->regmap, RT5691_IRQ_CTRL_1,
0x1 << 3, 0x1 << 3);
break;
default:
dev_warn(component->dev, "Wrong JD source\n");
break;
}
rt5691->hs_jack = hs_jack;
return 0;
}
static int rt5691_i2c_read(void *context, unsigned int reg, unsigned int *val)
{
struct i2c_client *i2c = context;
struct rt5691_priv *rt5691 = i2c_get_clientdata(i2c);
struct rt5691_i2c_err *i2c_err = rt5691->i2c_err;
int ret, i;
for (i = 0; i < rt5691->pdata.i2c_op_count; i++) {
ret = regmap_read(rt5691->i2c_regmap, reg, val);
if (ret) {
dev_err(&i2c->dev, "%s err: %d\n", __func__, ret);
if (i2c_err && i2c_err->i2c_err_cb)
i2c_err->i2c_err_cb(i2c_err->i2c_err_priv);
continue;
} else {
break;
}
}
return ret;
}
static int rt5691_i2c_write(void *context, unsigned int reg, unsigned int val)
{
struct i2c_client *i2c = context;
struct rt5691_priv *rt5691 = i2c_get_clientdata(i2c);
struct rt5691_i2c_err *i2c_err = rt5691->i2c_err;
int ret, i;
for (i = 0; i < rt5691->pdata.i2c_op_count; i++) {
ret = regmap_write(rt5691->i2c_regmap, reg, val);
if (ret) {
dev_err(&i2c->dev, "%s err: %d\n", __func__, ret);
if (i2c_err && i2c_err->i2c_err_cb)
i2c_err->i2c_err_cb(i2c_err->i2c_err_priv);
continue;
} else {
break;
}
}
return ret;
}
const struct snd_soc_component_driver rt5691_soc_component_dev = {
.probe = rt5691_probe,
.remove = rt5691_remove,
.suspend = rt5691_suspend,
.resume = rt5691_resume,
.set_bias_level = rt5691_set_bias_level,
.controls = rt5691_snd_controls,
.num_controls = ARRAY_SIZE(rt5691_snd_controls),
.dapm_widgets = rt5691_dapm_widgets,
.num_dapm_widgets = ARRAY_SIZE(rt5691_dapm_widgets),
.dapm_routes = rt5691_dapm_routes,
.num_dapm_routes = ARRAY_SIZE(rt5691_dapm_routes),
.set_sysclk = rt5691_set_component_sysclk,
.set_pll = rt5691_set_component_pll,
.set_jack = rt5691_set_jack_detect,
.use_pmdown_time = 1,
.endianness = 1,
.non_legacy_dai_naming = 1,
};
static const struct regmap_config rt5691_i2c_regmap = {
.name = "i2c",
.reg_bits = 16,
.val_bits = 16,
.cache_type = REGCACHE_NONE,
};
static const struct regmap_config rt5691_debug_regmap = {
.reg_bits = 16,
.val_bits = 16,
.max_register = RT5691_HP_AMP_DET_CTRL_20,
.volatile_reg = rt5691_volatile_register,
.readable_reg = rt5691_readable_register,
.cache_type = REGCACHE_RBTREE,
.reg_defaults = rt5691_reg,
.num_reg_defaults = ARRAY_SIZE(rt5691_reg),
.use_single_read = true,
.use_single_write = true,
.reg_read = rt5691_i2c_read,
.reg_write = rt5691_i2c_write,
};
static const struct regmap_config rt5691_regmap = {
.reg_bits = 16,
.val_bits = 16,
.max_register = RT5691_HP_AMP_DET_CTRL_20,
.volatile_reg = rt5691_volatile_register,
.readable_reg = rt5691_readable_register,
.cache_type = REGCACHE_RBTREE,
.reg_defaults = rt5691_reg,
.num_reg_defaults = ARRAY_SIZE(rt5691_reg),
.use_single_read = true,
.use_single_write = true,
};
static const struct i2c_device_id rt5691_i2c_id[] = {
{"rt5691", 0},
{}
};
MODULE_DEVICE_TABLE(i2c, rt5691_i2c_id);
static int rt5691_parse_dt(struct rt5691_priv *rt5691, struct device *dev)
{
int i, i2c_retry = 0;
u32 imp_data[ARRAY_SIZE(rt5691_hp_gain_table) * 2];
rt5691->pdata.in1_diff = of_property_read_bool(dev->of_node,
"realtek,in1-differential");
rt5691->pdata.in2_diff = of_property_read_bool(dev->of_node,
"realtek,in2-differential");
rt5691->pdata.in3_diff = of_property_read_bool(dev->of_node,
"realtek,in3-differential");
rt5691->pdata.ldo1_en = of_get_named_gpio(dev->of_node,
"realtek,ldo1_en", 0);
rt5691->pdata.gpio_1v8 = of_get_named_gpio(dev->of_node,
"realtek,gpio_1v8", 0);
rt5691->pdata.gpio_3v3 = of_get_named_gpio(dev->of_node,
"realtek,gpio_3v3", 0);
of_property_read_u32(dev->of_node, "realtek,gpio2-func",
&rt5691->pdata.gpio2_func);
of_property_read_u32(dev->of_node, "realtek,gpio3-func",
&rt5691->pdata.gpio3_func);
of_property_read_u32(dev->of_node, "realtek,jd-src",
&rt5691->pdata.jd_src);
of_property_read_u32(dev->of_node, "realtek,jd-resistor",
&rt5691->pdata.jd_resistor);
of_property_read_u32(dev->of_node, "realtek,delay-plug-in",
&rt5691->pdata.delay_plug_in);
of_property_read_u32(dev->of_node, "realtek,delay-plug-out-pb",
&rt5691->pdata.delay_plug_out_pb);
of_property_read_u32(dev->of_node, "realtek,sar-hs-type",
&rt5691->pdata.sar_hs_type);
of_property_read_u32(dev->of_node, "realtek,sar-hs-open-gender",
&rt5691->pdata.sar_hs_open_gender);
of_property_read_u32(dev->of_node, "realtek,sar-pb-vth0",
&rt5691->pdata.sar_pb_vth0);
of_property_read_u32(dev->of_node, "realtek,sar-pb-vth1",
&rt5691->pdata.sar_pb_vth1);
of_property_read_u32(dev->of_node, "realtek,sar-pb-vth2",
&rt5691->pdata.sar_pb_vth2);
of_property_read_u32(dev->of_node, "realtek,sar-pb-vth3",
&rt5691->pdata.sar_pb_vth3);
if (!of_property_read_u32_array(dev->of_node, "realtek,imp_table",
imp_data, (ARRAY_SIZE(rt5691_hp_gain_table) * 2))) {
for (i = 0; i < ARRAY_SIZE(rt5691_hp_gain_table); i++) {
rt5691_hp_gain_table[i].imp = imp_data[i * 2];
rt5691_hp_gain_table[i].gain = imp_data[(i * 2) + 1];
}
}
if (of_property_read_bool(dev->of_node, "realtek,i2c-dbg-cb"))
rt5691->pdata.i2c_op_count = 1;
of_property_read_u32(dev->of_node, "realtek,i2c-dbg-retry",
&i2c_retry);
if (i2c_retry)
rt5691->pdata.i2c_op_count = i2c_retry + 1;
of_property_read_u32(dev->of_node, "realtek,button-clk",
&rt5691->pdata.button_clk);
of_property_read_u32(dev->of_node, "realtek,hpa-capless-bias",
&rt5691->pdata.hpa_capless_bias);
return 0;
}
static void rt5691_enable_push_button_irq(struct snd_soc_component *component,
bool enable)
{
struct rt5691_priv *rt5691 = snd_soc_component_get_drvdata(component);
if (enable) {
snd_soc_component_write(component, RT5691_MIC_BTN_CTRL_16,
rt5691->pdata.button_clk);
snd_soc_component_write(component, RT5691_MIC_BTN_CTRL_17, 0x3);
snd_soc_component_update_bits(component,
RT5691_SAR_ADC_DET_CTRL_4, 0x8, 0x8);
snd_soc_component_update_bits(component, RT5691_PWR_DA_PATH_2, 0x40, 0x40);
if (rt5691->open_gender)
msleep(20);
snd_soc_component_update_bits(component, RT5691_MIC_BTN_CTRL_15, 0x80, 0x80);
snd_soc_component_update_bits(component, RT5691_IRQ_CTRL_3, 0x40, 0x40);
} else {
snd_soc_component_update_bits(component, RT5691_IRQ_CTRL_3, 0x40, 0);
snd_soc_component_update_bits(component, RT5691_MIC_BTN_CTRL_15, 0x80, 0);
snd_soc_component_update_bits(component, RT5691_PWR_DA_PATH_2, 0x40, 0);
}
}
static int rt5691_water_detect(struct snd_soc_component *component,
bool enable)
{
struct snd_soc_dapm_context *dapm = &component->dapm;
struct rt5691_priv *rt5691 = snd_soc_component_get_drvdata(component);
static struct reg_sequence rt5691_wt_list[] = {
{RT5691_MIC_BTN_CTRL_26, 0x0088},
{RT5691_ADC_FILTER_CTRL_3, 0x0090},
{RT5691_ADC_FILTER2_CTRL_3, 0x0090},
{RT5691_HP_AMP_L_GAIN_CTRL, 0x0000},
{RT5691_HP_AMP_R_GAIN_CTRL, 0x0000},
{RT5691_SYS_CLK_SRC, 0x006d},
{RT5691_DA_STO1_FILTER_CLK_DIV, 0x0202},
{RT5691_ADC_AND_DAC_OSR, 0x0202},
{RT5691_PWR_DA_PATH_1, 0x2001},
{RT5691_PWR_DA_PATH_2, 0x0020},
{RT5691_STO1_DAC_MIXER_CTRL, 0xa8a8},
{RT5691_HP_AMP_CTRL_2, 0xe000},
{RT5691_HP_AMP_DET_CTRL_18, 0x0008},
{RT5691_HP_AMP_DET_CTRL_14, 0x3040},
};
unsigned int rt5691_wt_list_saved[ARRAY_SIZE(rt5691_wt_list)];
int i;
if (enable) {
snd_soc_dapm_force_enable_pin(dapm, "Vref1");
snd_soc_dapm_force_enable_pin(dapm, "Vref2");
snd_soc_dapm_force_enable_pin(dapm, "RC 1M");
snd_soc_dapm_force_enable_pin(dapm, "RC 25M");
snd_soc_dapm_sync(dapm);
snd_soc_dapm_mutex_lock(dapm);
for (i = 0; i < ARRAY_SIZE(rt5691_wt_list); i++) {
rt5691_wt_list_saved[i] =
snd_soc_component_read(component, rt5691_wt_list[i].reg);
snd_soc_component_write(component, rt5691_wt_list[i].reg,
rt5691_wt_list[i].def);
if (rt5691_wt_list[i].reg == RT5691_HP_AMP_DET_CTRL_18)
usleep_range(10000, 10005);
}
regmap_update_bits(rt5691->regmap, RT5691_PWR_DA_PATH_2, 0x1100,
0x1100);
regmap_update_bits(rt5691->regmap, RT5691_WATER_DET_CTRL_3, 0x8000,
0x8000);
for (i = 0; i < 25; i++) {
if (!(snd_soc_component_read(component,
RT5691_WATER_DET_CTRL_3) & 0x4))
msleep(20);
else
break;
}
if ((snd_soc_component_read(component,
RT5691_WATER_DET_CTRL_3) & 0x3) == 0x2) {
regmap_update_bits(rt5691->regmap, RT5691_WATER_DET_CTRL_3, 0x8000,
0);
snd_soc_component_update_bits(component, RT5691_HP_AMP_CTRL_2,
0x3000, rt5691_wt_list_saved[ARRAY_SIZE(rt5691_wt_list) - 3]);
snd_soc_component_update_bits(component,
RT5691_HP_AMP_DET_CTRL_14, 0x0070,
rt5691_wt_list_saved[ARRAY_SIZE(rt5691_wt_list) - 1]);
snd_soc_component_update_bits(component,
RT5691_HP_AMP_DET_CTRL_18, 0x000c,
rt5691_wt_list_saved[ARRAY_SIZE(rt5691_wt_list) - 2]);
for (i = ARRAY_SIZE(rt5691_wt_list) - 4; i >= 0; i--)
snd_soc_component_write(component, rt5691_wt_list[i].reg,
rt5691_wt_list_saved[i]);
snd_soc_dapm_mutex_unlock(dapm);
snd_soc_dapm_disable_pin(dapm, "Vref1");
snd_soc_dapm_disable_pin(dapm, "Vref2");
snd_soc_dapm_disable_pin(dapm, "RC 1M");
snd_soc_dapm_disable_pin(dapm, "RC 25M");
snd_soc_dapm_sync(dapm);
} else {
dev_info(component->dev, "water detected\n");
regmap_update_bits(rt5691->regmap, RT5691_IRQ_CTRL_4,
0x0008, 0x0008);
rt5691->wt_en = true;
snd_soc_component_update_bits(component, RT5691_HP_AMP_CTRL_2,
0x3000, rt5691_wt_list_saved[ARRAY_SIZE(rt5691_wt_list) - 3]);
snd_soc_component_update_bits(component,
RT5691_HP_AMP_DET_CTRL_14, 0x0070,
rt5691_wt_list_saved[ARRAY_SIZE(rt5691_wt_list) - 1]);
snd_soc_component_update_bits(component,
RT5691_HP_AMP_DET_CTRL_18, 0x000c,
rt5691_wt_list_saved[ARRAY_SIZE(rt5691_wt_list) - 2]);
for (i = ARRAY_SIZE(rt5691_wt_list) - 4; i >= 0; i--) {
if (rt5691_wt_list[i].reg == RT5691_PWR_DA_PATH_2)
rt5691_wt_list_saved[i] |= 0x1100;
snd_soc_component_write(component, rt5691_wt_list[i].reg,
rt5691_wt_list_saved[i]);
}
snd_soc_dapm_mutex_unlock(dapm);
snd_soc_dapm_disable_pin(dapm, "Vref1");
snd_soc_dapm_disable_pin(dapm, "Vref2");
snd_soc_dapm_disable_pin(dapm, "RC 25M");
snd_soc_dapm_sync(dapm);
}
} else {
regmap_update_bits(rt5691->regmap, RT5691_IRQ_CTRL_4, 0x0008, 0);
regmap_update_bits(rt5691->regmap, RT5691_WATER_DET_CTRL_3,
0x8000, 0);
regmap_update_bits(rt5691->regmap, RT5691_PWR_DA_PATH_2, 0x1100,
0);
snd_soc_dapm_disable_pin(dapm, "RC 1M");
snd_soc_dapm_sync(dapm);
rt5691->wt_en = false;
}
return 0;
}
static int rt5691_headset_detect(struct snd_soc_component *component, int jack_insert)
{
struct rt5691_priv *rt5691 = snd_soc_component_get_drvdata(component);
struct snd_soc_dapm_context *dapm = &component->dapm;
unsigned int sar_hs_type;
if (jack_insert) {
regmap_update_bits(rt5691->regmap, RT5691_WATER_DET_CTRL_2, 0xf0, 0);
regmap_update_bits(rt5691->regmap, RT5691_IRQ_CTRL_1, 0x8, 0);
regmap_update_bits(rt5691->regmap, RT5691_COMBO_JACK_CTRL_5, 0xc007, 0xc005);
regmap_update_bits(rt5691->regmap, RT5691_COMBO_JACK_CTRL_4, 0x600, 0x600);
regmap_update_bits(rt5691->regmap, RT5691_PWR_DA_PATH_2, 0x480, 0x480);
snd_soc_dapm_force_enable_pin(dapm, "MICBIAS1");
snd_soc_dapm_sync(dapm);
regmap_write(rt5691->regmap, RT5691_SAR_ADC_DET_CTRL_2, 0x2c);
regmap_write(rt5691->regmap, RT5691_JACK_TYPE_DET_CTRL_2, 0xfc00);
regmap_write(rt5691->regmap, RT5691_SAR_ADC_DET_CTRL_1, 0);
msleep(20);
rt5691->adc_val = snd_soc_component_read(component,
RT5691_SAR_ADC_DET_CTRL_23);
sar_hs_type = rt5691->pdata.sar_hs_type ?
rt5691->pdata.sar_hs_type : 729;
dev_info(component->dev, "sar_adc_value = %d\n", rt5691->adc_val);
if (rt5691->pdata.sar_hs_open_gender) {
if (rt5691->adc_val > rt5691->pdata.sar_hs_open_gender) {
rt5691->jack_type = 0;
rt5691->open_gender = true;
regmap_update_bits(rt5691->regmap,
RT5691_COMBO_JACK_CTRL_2, 0x8000,
0x8000);
regmap_update_bits(rt5691->regmap,
RT5691_COMBO_JACK_CTRL_3, 0x00f3, 0x00e2);
regmap_update_bits(rt5691->regmap,
RT5691_IRQ_CTRL_1, 0x0004, 0);
regmap_update_bits(rt5691->regmap,
RT5691_IRQ_CTRL_2, 0x30, 0x20);
regmap_write(rt5691->regmap,
RT5691_SAR_ADC_DET_CTRL_2, 0x20);
rt5691_water_detect(component, false);
regmap_update_bits(rt5691->regmap,
RT5691_WATER_DET_CTRL_2, 0xf0, 0x90);
regmap_update_bits(rt5691->regmap,
RT5691_IRQ_CTRL_1, 0x8, 0x8);
dev_info(component->dev, "jack_type = open gender\n");
return rt5691->jack_type;
}
}
if (rt5691->adc_val > sar_hs_type) {
rt5691->jack_type = SND_JACK_HEADSET;
if (!rt5691->open_gender) {
regmap_update_bits(rt5691->regmap,
RT5691_IRQ_CTRL_1, 0x0004, 0x0004);
regmap_update_bits(rt5691->regmap,
RT5691_IRQ_CTRL_2, 0x0018, 0x0018);
regmap_write(rt5691->regmap, RT5691_INT_ST_1, 0);
regmap_update_bits(rt5691->regmap,
RT5691_COMBO_JACK_CTRL_3, 0x00f3, 0x00e1);
regmap_update_bits(rt5691->regmap,
RT5691_MONO_ANLG_DRE_CTRL_2, 0x0600, 0x0600);
if (rt5691->adc_val > 2000) {
regmap_update_bits(rt5691->regmap,
RT5691_COMBO_JACK_CTRL_5, 0xc007, 0xc005);
} else {
regmap_update_bits(rt5691->regmap,
RT5691_COMBO_JACK_CTRL_2, 0x8000, 0x8000);
regmap_update_bits(rt5691->regmap,
RT5691_COMBO_JACK_CTRL_5, 0xc007, 0xc004);
}
regmap_update_bits(rt5691->regmap,
RT5691_COMBO_JACK_CTRL_4, 0x600, 0x600);
regmap_update_bits(rt5691->regmap,
RT5691_PWR_DA_PATH_2, 0x400, 0x400);
}
rt5691_enable_push_button_irq(component, true);
} else {
rt5691->jack_type = SND_JACK_HEADPHONE;
if (!rt5691->open_gender) {
regmap_write(rt5691->regmap, RT5691_SAR_ADC_DET_CTRL_2, 0x20);
regmap_update_bits(rt5691->regmap, RT5691_COMBO_JACK_CTRL_4, 0x400, 0);
regmap_update_bits(rt5691->regmap, RT5691_MONO_ANLG_DRE_CTRL_2, 0x0600, 0);
regmap_update_bits(rt5691->regmap, RT5691_PWR_DA_PATH_2, 0x480, 0);
snd_soc_dapm_disable_pin(dapm, "MICBIAS1");
snd_soc_dapm_sync(dapm);
}
}
regmap_update_bits(rt5691->regmap, RT5691_WATER_DET_CTRL_2, 0xf0, 0x90);
regmap_update_bits(rt5691->regmap, RT5691_IRQ_CTRL_1, 0x8, 0x8);
} else {
if (!rt5691->open_gender) {
snd_soc_dapm_disable_pin(dapm, "MICBIAS1");
snd_soc_dapm_sync(dapm);
regmap_write(rt5691->regmap, RT5691_SAR_ADC_DET_CTRL_2, 0x20);
regmap_update_bits(rt5691->regmap, RT5691_COMBO_JACK_CTRL_4, 0x400, 0);
regmap_update_bits(rt5691->regmap, RT5691_MONO_ANLG_DRE_CTRL_2, 0x0600, 0);
regmap_update_bits(rt5691->regmap, RT5691_PWR_DA_PATH_2, 0x480, 0);
}
if (rt5691->jack_type == SND_JACK_HEADSET)
rt5691_enable_push_button_irq(component, false);
rt5691->jack_type = 0;
}
dev_info(component->dev, "jack_type = %d\n", rt5691->jack_type);
return rt5691->jack_type;
}
static int rt5691_button_detect(struct snd_soc_component *component)
{
int reg1, reg2;
reg1 = snd_soc_component_read(component, RT5691_MIC_BTN_CTRL_13);
snd_soc_component_write(component, RT5691_MIC_BTN_CTRL_13, reg1);
reg2 = snd_soc_component_read(component, RT5691_MIC_BTN_CTRL_14);
snd_soc_component_write(component, RT5691_MIC_BTN_CTRL_14, reg2);
return (reg1 << 8) | reg2;
}
static unsigned int rt5691_imp_detect(struct snd_soc_component *component)
{
struct snd_soc_dapm_context *dapm = &component->dapm;
struct rt5691_priv *rt5691 = snd_soc_component_get_drvdata(component);
static struct reg_sequence rt5691_imp_list[] = {
{RT5691_MIC_BTN_CTRL_26, 0x0088},
{RT5691_ADC_FILTER_CTRL_3, 0x0090},
{RT5691_ADC_FILTER2_CTRL_3, 0x0090},
{RT5691_HP_AMP_L_GAIN_CTRL, 0x0000},
{RT5691_HP_AMP_R_GAIN_CTRL, 0x0000},
{RT5691_RC_CLK, 0x8800},
{RT5691_SYS_CLK_SRC, 0x007d},
{RT5691_DA_STO1_FILTER_CLK_DIV, 0x0202},
{RT5691_AD_STO1_FILTER_CLK_DIV, 0x0202},
{RT5691_ADC_AND_DAC_OSR, 0x0202},
{RT5691_PWR_DA_PATH_1, 0x2001},
{RT5691_PWR_DA_PATH_2, 0x0013},
{RT5691_PWR_AD_PATH, 0x0002},
{RT5691_ADC56_CTRL, 0xb490},
{RT5691_STO1_DAC_MIXER_CTRL, 0x2888},
{RT5691_STO2_ADC_MIXER_CTRL, 0x6c6c},
{RT5691_HP_BEHAVIOR_LOGIC_CTRL_2, 0x0001},
{RT5691_ADC_FILTER2_CTRL_6, 0x0003},
{RT5691_IMP_SENS_CTRL_8, 0x2000},
{RT5691_IMP_SENS_CTRL_24, 0x1907},
{RT5691_IMP_SENS_CTRL_1, 0xa000},
};
unsigned int rt5691_imp_list_saved[ARRAY_SIZE(rt5691_imp_list)];
int i;
snd_soc_dapm_force_enable_pin(dapm, "Vref1");
snd_soc_dapm_force_enable_pin(dapm, "Vref2");
snd_soc_dapm_sync(dapm);
snd_soc_dapm_mutex_lock(dapm);
for (i = 0; i < ARRAY_SIZE(rt5691_imp_list); i++) {
rt5691_imp_list_saved[i] =
snd_soc_component_read(component, rt5691_imp_list[i].reg);
snd_soc_component_write(component, rt5691_imp_list[i].reg,
rt5691_imp_list[i].def);
}
for (i = 0; i < 50; i++) {
msleep(20);
if (!(snd_soc_component_read(component, RT5691_IMP_SENS_CTRL_1) & 0x8000))
break;
}
rt5691->imp_value = snd_soc_component_read(component, RT5691_IMP_SENS_CTRL_25);
for (i = ARRAY_SIZE(rt5691_imp_list) - 1; i >= 0; i--)
snd_soc_component_write(component, rt5691_imp_list[i].reg,
rt5691_imp_list_saved[i]);
snd_soc_dapm_mutex_unlock(dapm);
snd_soc_dapm_disable_pin(dapm, "Vref1");
snd_soc_dapm_disable_pin(dapm, "Vref2");
snd_soc_dapm_sync(dapm);
for (i = 0; i < ARRAY_SIZE(rt5691_hp_gain_table); i++) {
if (rt5691->imp_value <= rt5691_hp_gain_table[i].imp) {
rt5691->imp_gain = rt5691_hp_gain_table[i].gain;
break;
}
}
dev_dbg(component->dev, "[%d] SET GAIN %d for 0x%x Impedance value\n",
i, rt5691->imp_gain, rt5691->imp_value);
return 0;
}
static void rt5691_jack_detect_handler(struct work_struct *work)
{
struct rt5691_priv *rt5691 =
container_of(work, struct rt5691_priv, jack_detect_work.work);
struct snd_soc_component *component = rt5691->component;
int val, btn_type, mask, i;
pm_stay_awake(component->dev);
dev_info(component->dev, "%s\n", __func__);
if (rt5691->is_suspend) {
dev_info(component->dev, "%s wait resume\n", __func__);
i = 0;
while (i < 10 && rt5691->is_suspend) {
msleep(50);
i++;
}
}
rt5691->mic_check_break = true;
cancel_delayed_work_sync(&rt5691->mic_check_work);
mask = 0x8000;
i = 0;
while (regmap_read(rt5691->regmap, RT5691_ANLG_READ_STA_324, &val) && i < 5) {
msleep(100);
i++;
}
dev_info(component->dev, "JD state = 0x%04x\n", val);
if (!(val & mask)) {
if (rt5691->open_gender) {
if (val & 0x2000) {
rt5691->irq_work_delay =
rt5691->pdata.delay_plug_out_pb ?
rt5691->pdata.delay_plug_out_pb + 500 :
500;
if (rt5691->jack_type) {
/* jack out */
rt5691->jack_type = rt5691_headset_detect(rt5691->component, 0);
#ifdef CONFIG_SWITCH
switch_set_state(&rt5691_headset_switch, 0);
#endif
snd_soc_jack_report(rt5691->hs_jack, rt5691->jack_type,
SND_JACK_HEADSET |
SND_JACK_BTN_0 | SND_JACK_BTN_1 |
SND_JACK_BTN_2 | SND_JACK_BTN_3);
dev_info(component->dev, "open gender jack out\n");
}
pm_wakeup_event(component->dev, 1000);
return;
}
} else if (!rt5691->wt_en && !rt5691->jack_type) {
rt5691_water_detect(component, true);
}
if (rt5691->wt_en) {
regmap_read(rt5691->regmap, RT5691_WATER_DET_CTRL_3, &val);
if (val & 0x2) {
rt5691_water_detect(component, false);
} else {
dev_info(component->dev, "water detected 0x%04x\n",
val);
pm_wakeup_event(component->dev, 1000);
return;
}
}
/* jack in */
if (rt5691->jack_type == 0) {
/* jack was out, report jack type */
rt5691_imp_detect(rt5691->component);
rt5691->jack_type = rt5691_headset_detect(
rt5691->component, 1);
regmap_read(rt5691->regmap, RT5691_ANLG_READ_STA_324, &val);
if (val & mask) {
queue_delayed_work(system_wq, &rt5691->jack_detect_work,
msecs_to_jiffies(50));
pm_wakeup_event(component->dev, 1000);
return;
}
rt5691->irq_work_delay =
rt5691->pdata.delay_plug_out_pb ?
rt5691->pdata.delay_plug_out_pb : 0;
if (rt5691->jack_type == SND_JACK_HEADSET) {
#ifdef CONFIG_SWITCH
switch_set_state(&rt5691_headset_switch, 1);
#endif
rt5691->button_timeout = jiffies + (HZ * 1);
} else if (rt5691->jack_type == SND_JACK_HEADPHONE) {
#ifdef CONFIG_SWITCH
switch_set_state(&rt5691_headset_switch, 2);
#endif
if (!rt5691->open_gender) {
schedule_delayed_work(&rt5691->mic_check_work,
msecs_to_jiffies(40));
}
} else {
#ifdef CONFIG_SWITCH
switch_set_state(&rt5691_headset_switch, 0);
#endif
rt5691->irq_work_delay += 500;
}
} else {
if ((rt5691->jack_type & SND_JACK_HEADSET) ==
SND_JACK_HEADSET) {
/* jack is already in, report button event */
rt5691->jack_type = SND_JACK_HEADSET;
btn_type = rt5691_button_detect(rt5691->component);
if (!rt5691->open_gender) {
regmap_read(rt5691->regmap, RT5691_INT_ST_1, &val);
if (val & 0x2000) {
regmap_write(rt5691->regmap, RT5691_INT_ST_1, 0);
btn_type = 0;
dev_info(component->dev, "JD1 trigger\n");
msleep(200);
for (i = 0; i < 16; i++) {
if (!rt5691_button_detect(rt5691->component))
break;
msleep(50);
}
} else if (val & 0x0001) {
regmap_write(rt5691->regmap, RT5691_INT_ST_1, 0);
btn_type = 0;
dev_info(component->dev, "JD3 trigger\n");
}
}
if (time_before(jiffies, rt5691->button_timeout)) {
btn_type = 0;
dev_warn(rt5691->component->dev,
"%s: invalid button event\n",
__func__);
}
rt5691->adc_val = snd_soc_component_read(component,
RT5691_SAR_ADC_DET_CTRL_23);
switch (btn_type) {
case 0x4000:
case 0x2000:
case 0x1000:
rt5691->jack_type |= SND_JACK_BTN_0;
break;
case 0x0400:
case 0x0200:
case 0x0100:
rt5691->jack_type |= SND_JACK_BTN_1;
break;
case 0x0040:
case 0x0020:
case 0x0010:
rt5691->jack_type |= SND_JACK_BTN_2;
break;
case 0x0004:
case 0x0002:
case 0x0001:
rt5691->jack_type |= SND_JACK_BTN_3;
break;
case 0x0000: /* unpressed */
if (snd_soc_component_read(component,
RT5691_SAR_ADC_DET_CTRL_23) > 2000) {
regmap_update_bits(rt5691->regmap,
RT5691_COMBO_JACK_CTRL_5,
0xc007, 0xc005);
regmap_update_bits(rt5691->regmap,
RT5691_COMBO_JACK_CTRL_2,
0x8000, 0);
regmap_write(rt5691->regmap,
RT5691_INT_ST_1, 0);
}
break;
default:
btn_type = 0;
dev_err(rt5691->component->dev,
"Unexpected button code 0x%04x\n",
btn_type);
break;
}
dev_info(component->dev, "jack_type = 0x%04x\n",
rt5691->jack_type);
rt5691->btn_det =
(rt5691->jack_type & SND_JACK_BTN_0)
== SND_JACK_BTN_0 ? 1 : 0;
} else {
dev_err(component->dev, "%s invalid event\n",
__func__);
}
}
} else {
/* jack out */
rt5691->open_gender = false;
rt5691->jack_type = rt5691_headset_detect(rt5691->component, 0);
#ifdef CONFIG_SWITCH
switch_set_state(&rt5691_headset_switch, 0);
#endif
rt5691_water_detect(component, false);
regmap_update_bits(rt5691->regmap, RT5691_COMBO_JACK_CTRL_2, 0x8000, 0);
regmap_update_bits(rt5691->regmap, RT5691_IRQ_CTRL_2, 0x20, 0);
regmap_update_bits(rt5691->regmap, RT5691_IRQ_CTRL_1, 0x0004, 0);
if (rt5691->pdata.delay_plug_in)
rt5691->irq_work_delay =
rt5691->pdata.delay_plug_in;
else
rt5691->irq_work_delay = 50;
rt5691->adc_val = 0;
}
snd_soc_jack_report(rt5691->hs_jack, rt5691->jack_type,
SND_JACK_HEADSET |
SND_JACK_BTN_0 | SND_JACK_BTN_1 |
SND_JACK_BTN_2 | SND_JACK_BTN_3);
pm_wakeup_event(component->dev, 1000);
}
static irqreturn_t rt5691_irq(int irq, void *data)
{
struct rt5691_priv *rt5691 = data;
struct snd_soc_component *component = rt5691->component;
dev_info(component->dev, "%s\n", __func__);
pm_wakeup_event(component->dev, 3000);
cancel_delayed_work_sync(&rt5691->jack_detect_work);
queue_delayed_work(system_wq, &rt5691->jack_detect_work,
msecs_to_jiffies(rt5691->irq_work_delay));
return IRQ_HANDLED;
}
static void rt5691_calibrate(struct rt5691_priv *rt5691)
{
struct snd_soc_component *component = rt5691->component;
struct snd_soc_dapm_context *dapm = &component->dapm;
static struct reg_sequence rt5691_cal_list[] = {
{0x008e, 0xf000},
{0x0090, 0x3480},
{0x00d0, 0x0001},
{0x0213, 0x0001},
{0x3b00, 0x302b},
{0x3c00, 0x0003},
{0x013a, 0x1080},
{0x013b, 0x1080},
{0x013c, 0x1080},
{0x0062, 0x2008},
{0x2b03, 0x1004},
{0x0061, 0x3dbf},
{0x0063, 0xaa80},
{0x0216, 0x8800},
{0x0205, 0x007d},
{0x0209, 0xfff3},
{0x020a, 0xffff},
{0x020b, 0xffff},
{0x0200, 0x0202},
{0x0201, 0x0202},
{0x0206, 0x0202},
{0x01db, 0x0000},
{0x0066, 0x8000},
{0x013f, 0xb490},
{0x0194, 0x0000},
};
unsigned int rt5691_cal_list_saved[ARRAY_SIZE(rt5691_cal_list)];
int i, ret;
snd_soc_dapm_mutex_lock(dapm);
regcache_cache_bypass(rt5691->regmap, true);
regmap_write(rt5691->regmap, RT5691_RESET, 0);
if (rt5691->pdata.hpa_capless_bias)
regmap_write(rt5691->regmap, RT5691_ANLG_BIAS_CTRL_4,
rt5691->pdata.hpa_capless_bias);
for (i = 0; i < ARRAY_SIZE(rt5691_cal_list); i++)
rt5691_cal_list_saved[i] =
snd_soc_component_read(component, rt5691_cal_list[i].reg);
regmap_multi_reg_write(rt5691->regmap,
rt5691_cal_list, ARRAY_SIZE(rt5691_cal_list));
msleep(20);
regmap_write(rt5691->regmap, RT5691_PWR_ANLG_1, 0xfec0);
regmap_write(rt5691->regmap, RT5691_OFFSET_CAL_1, 0xbd00);
i = 0;
while (true) {
if (snd_soc_component_read(component, RT5691_HP_AMP_DET_CTRL_12) & 0x8000)
usleep_range(10000, 10005);
else
break;
if (i > 20) {
dev_err(component->dev, "HP Calibration Failure\n");
regmap_write(rt5691->regmap, RT5691_RESET, 0);
regcache_cache_bypass(rt5691->regmap, false);
return;
}
i++;
}
regmap_write(rt5691->regmap, RT5691_OFFSET_CAL_25, 0xf406);
usleep_range(400000, 400005);
for (i = ARRAY_SIZE(rt5691_cal_list) - 1; i >= 0; i--) {
if (rt5691_cal_list[i].reg == 0x0209)
rt5691_cal_list_saved[i] |= 0x2000;
snd_soc_component_write(component, rt5691_cal_list[i].reg,
rt5691_cal_list_saved[i]);
}
regcache_cache_bypass(rt5691->regmap, false);
regcache_mark_dirty(rt5691->regmap);
regcache_sync(rt5691->regmap);
/* volatile settings */
regmap_write(rt5691->regmap, RT5691_COMBO_JACK_CTRL_4, 0x0104);
snd_soc_dapm_mutex_unlock(dapm);
if (rt5691->irq) {
rt5691_irq(0, rt5691);
ret = request_threaded_irq(rt5691->irq, NULL, rt5691_irq,
IRQF_TRIGGER_RISING | IRQF_ONESHOT, "rt5691", rt5691);
if (ret)
dev_err(component->dev, "Failed to reguest IRQ: %d\n", ret);
ret = irq_set_irq_wake(rt5691->irq, 1);
if (ret)
dev_err(component->dev, "Failed to reguest IRQ wake: %d\n",
ret);
}
}
static void rt5691_calibrate_handler(struct work_struct *work)
{
struct rt5691_priv *rt5691 = container_of(work, struct rt5691_priv,
calibrate_work.work);
int i = 0;
while (!rt5691->component->card->instantiated) {
msleep(20);
if (rt5691->cal_done || i > 250)
return;
i++;
}
rt5691_calibrate(rt5691);
}
static void rt5691_mic_check_handler(struct work_struct *work)
{
struct rt5691_priv *rt5691 = container_of(work, struct rt5691_priv,
mic_check_work.work);
struct snd_soc_component *component = rt5691->component;
struct snd_soc_dapm_context *dapm = &component->dapm;
int sar_hs_type, i;
pm_wakeup_event(component->dev, 3000);
rt5691->mic_check_break = false;
if (rt5691->is_suspend) {
/* Because some SOCs need wake up time of I2C controller */
dev_info(component->dev, "%s wait resume\n", __func__);
i = 0;
while (i < 10 && rt5691->is_suspend) {
msleep(50);
i++;
}
}
regmap_update_bits(rt5691->regmap, RT5691_PWR_DA_PATH_2, 0x80, 0x80);
snd_soc_dapm_force_enable_pin(dapm, "MICBIAS1");
snd_soc_dapm_sync(dapm);
regmap_write(rt5691->regmap, RT5691_SAR_ADC_DET_CTRL_2, 0x2c);
regmap_write(rt5691->regmap, RT5691_JACK_TYPE_DET_CTRL_2, 0xfc00);
regmap_write(rt5691->regmap, RT5691_SAR_ADC_DET_CTRL_1, 0);
sar_hs_type = rt5691->pdata.sar_hs_type ?
rt5691->pdata.sar_hs_type : 729;
for (i = 0; i < 100; i++) {
msleep(20);
if (i % 10 == 0) {
rt5691->adc_val = snd_soc_component_read(component,
RT5691_SAR_ADC_DET_CTRL_23);
}
if (rt5691->mic_check_break)
break;
}
if (!rt5691->mic_check_break && rt5691->adc_val > sar_hs_type) {
regmap_update_bits(rt5691->regmap,
RT5691_IRQ_CTRL_1, 0x0004, 0x0004);
regmap_update_bits(rt5691->regmap,
RT5691_IRQ_CTRL_2, 0x0018, 0x0018);
regmap_write(rt5691->regmap, RT5691_INT_ST_1, 0);
regmap_update_bits(rt5691->regmap,
RT5691_COMBO_JACK_CTRL_3, 0x00f3, 0x00e1);
regmap_update_bits(rt5691->regmap,
RT5691_MONO_ANLG_DRE_CTRL_2, 0x0600, 0x0600);
if (rt5691->adc_val > 2000) {
regmap_update_bits(rt5691->regmap,
RT5691_COMBO_JACK_CTRL_5, 0xc007, 0xc005);
} else {
regmap_update_bits(rt5691->regmap,
RT5691_COMBO_JACK_CTRL_2, 0x8000, 0x8000);
regmap_update_bits(rt5691->regmap,
RT5691_COMBO_JACK_CTRL_5, 0xc007, 0xc004);
}
regmap_update_bits(rt5691->regmap,
RT5691_COMBO_JACK_CTRL_4, 0x600, 0x600);
regmap_update_bits(rt5691->regmap,
RT5691_PWR_DA_PATH_2, 0x400, 0x400);
rt5691->jack_type = SND_JACK_HEADSET;
rt5691_enable_push_button_irq(component, true);
#ifdef CONFIG_SWITCH
switch_set_state(&rt5691_headset_switch, 1);
#endif
rt5691->button_timeout = jiffies + (HZ * 1);
snd_soc_jack_report(rt5691->hs_jack, rt5691->jack_type,
SND_JACK_HEADSET);
dev_info(component->dev, "%s: jack_type = 0x%04x\n", __func__,
rt5691->jack_type);
return;
}
regmap_write(rt5691->regmap, RT5691_SAR_ADC_DET_CTRL_2, 0x20);
regmap_update_bits(rt5691->regmap, RT5691_COMBO_JACK_CTRL_4, 0x400, 0);
regmap_update_bits(rt5691->regmap, RT5691_MONO_ANLG_DRE_CTRL_2, 0x0600, 0);
regmap_update_bits(rt5691->regmap, RT5691_PWR_DA_PATH_2, 0x80, 0);
snd_soc_dapm_disable_pin(dapm, "MICBIAS1");
snd_soc_dapm_sync(dapm);
}
static void rt5691_sto1_l_adc_handler(struct work_struct *work)
{
struct rt5691_priv *rt5691 =
container_of(work, struct rt5691_priv, sto1_l_adc_work.work);
struct snd_soc_component *component = rt5691->component;
snd_soc_component_update_bits(component, RT5691_ADC_FILTER_CTRL_3,
(0x1 << 7), 0);
}
static void rt5691_sto1_r_adc_handler(struct work_struct *work)
{
struct rt5691_priv *rt5691 =
container_of(work, struct rt5691_priv, sto1_r_adc_work.work);
struct snd_soc_component *component = rt5691->component;
snd_soc_component_update_bits(component, RT5691_ADC_FILTER_CTRL_3,
(0x1 << 4), 0);
}
static void rt5691_sto2_l_adc_handler(struct work_struct *work)
{
struct rt5691_priv *rt5691 =
container_of(work, struct rt5691_priv, sto2_l_adc_work.work);
struct snd_soc_component *component = rt5691->component;
snd_soc_component_update_bits(component, RT5691_ADC_FILTER2_CTRL_3,
(0x1 << 7), 0);
}
static void rt5691_sto2_r_adc_handler(struct work_struct *work)
{
struct rt5691_priv *rt5691 =
container_of(work, struct rt5691_priv, sto2_r_adc_work.work);
struct snd_soc_component *component = rt5691->component;
snd_soc_component_update_bits(component, RT5691_ADC_FILTER2_CTRL_3,
(0x1 << 4), 0);
}
#ifdef CONFIG_DEBUG_FS
static ssize_t rt5691_codec_reg_read_file(struct file *file,
char __user *user_buf, size_t count, loff_t *ppos)
{
struct rt5691_priv *rt5691 = file->private_data;
char *buf;
unsigned int val, i;
size_t ret = 0, size = 0;
if (rt5691->dump_reg > RT5691_HP_AMP_DET_CTRL_20) {
rt5691->dump_reg = RT5691_RESET;
return 0;
}
buf = kzalloc(count, GFP_KERNEL);
if (!buf)
return -ENOMEM;
for (i = rt5691->dump_reg; i <= RT5691_HP_AMP_DET_CTRL_20; i++) {
if (rt5691_readable_register(NULL, i)) {
if (size + ret >= count)
break;
regmap_read(rt5691->regmap, i, &val);
ret = sprintf(buf + size, "%04x: %04x\n", i, val);
size += ret;
}
}
if (copy_to_user(user_buf, buf, size)) {
kfree(buf);
return -EFAULT;
}
rt5691->dump_reg = i;
kfree(buf);
return size;
}
static ssize_t rt5691_codec_reg_write_file(struct file *file,
const char __user *user_buf, size_t count, loff_t *ppos)
{
struct rt5691_priv *rt5691 = file->private_data;
char buf[32];
size_t buf_size;
char *start = buf;
unsigned long reg, value;
int ret;
buf_size = min(count, (sizeof(buf)-1));
if (copy_from_user(buf, user_buf, buf_size))
return -EFAULT;
buf[buf_size] = 0;
while (*start == ' ')
start++;
reg = simple_strtoul(start, &start, 16);
while (*start == ' ')
start++;
if (kstrtoul(start, 16, &value))
return -EINVAL;
ret = regmap_write(rt5691->regmap, reg, value);
if (ret < 0)
return ret;
return buf_size;
}
static const struct file_operations rt5691_codec_reg_fops = {
.open = simple_open,
.read = rt5691_codec_reg_read_file,
.write = rt5691_codec_reg_write_file,
.llseek = default_llseek,
};
static ssize_t rt5691_codec_reg_adb_read_file(struct file *file,
char __user *user_buf, size_t count, loff_t *ppos)
{
struct rt5691_priv *rt5691 = file->private_data;
char *buf;
unsigned int val, i;
size_t ret = 0, size = 0;
if (!rt5691->adb_reg_num)
return 0;
buf = kzalloc(count, GFP_KERNEL);
if (!buf)
return -ENOMEM;
for (i = 0; i < rt5691->adb_reg_num; i++) {
if (rt5691_readable_register(NULL, rt5691->adb_reg_addr[i])) {
if (size + ret >= count)
break;
regmap_read(rt5691->regmap, rt5691->adb_reg_addr[i],
&val);
ret = sprintf(buf + size, "%04x: %04x\n",
rt5691->adb_reg_addr[i], val);
size += ret;
}
}
if (copy_to_user(user_buf, buf, size)) {
kfree(buf);
return -EFAULT;
}
rt5691->adb_reg_num = 0;
kfree(buf);
return size;
}
static ssize_t rt5691_codec_reg_adb_write_file(struct file *file,
const char __user *user_buf, size_t count, loff_t *ppos)
{
struct rt5691_priv *rt5691 = file->private_data;
char buf[768];
size_t buf_size;
unsigned int value;
int i = 2, j = 0;
buf_size = min(count, (sizeof(buf)-1));
if (copy_from_user(buf, user_buf, buf_size))
return -EFAULT;
if (buf[0] == 'R' || buf[0] == 'r') {
while (j <= 0x3f && i < count) {
rt5691->adb_reg_addr[j] = 0;
value = 0;
for ( ; i < count; i++) {
if (*(buf + i) <= '9' && *(buf + i) >= '0')
value = (value << 4) | (*(buf + i) - '0');
else if (*(buf + i) <= 'f' && *(buf + i) >= 'a')
value = (value << 4) | ((*(buf + i) - 'a') + 0xa);
else if (*(buf + i) <= 'F' && *(buf + i) >= 'A')
value = (value << 4) | ((*(buf + i) - 'A') + 0xa);
else
break;
}
i++;
rt5691->adb_reg_addr[j] = value;
j++;
}
rt5691->adb_reg_num = j;
} else if (buf[0] == 'W' || buf[0] == 'w') {
while (j <= 0x3f && i < count) {
/* Get address */
rt5691->adb_reg_addr[j] = 0;
value = 0;
for ( ; i < count; i++) {
if (*(buf + i) <= '9' && *(buf + i) >= '0')
value = (value << 4) | (*(buf + i) - '0');
else if (*(buf + i) <= 'f' && *(buf + i) >= 'a')
value = (value << 4) | ((*(buf + i) - 'a') + 0xa);
else if (*(buf + i) <= 'F' && *(buf + i) >= 'A')
value = (value << 4) | ((*(buf + i) - 'A') + 0xa);
else
break;
}
i++;
rt5691->adb_reg_addr[j] = value;
/* Get value */
rt5691->adb_reg_value[j] = 0;
value = 0;
for ( ; i < count; i++) {
if (*(buf + i) <= '9' && *(buf + i) >= '0')
value = (value << 4) | (*(buf + i) - '0');
else if (*(buf + i) <= 'f' && *(buf + i) >= 'a')
value = (value << 4) | ((*(buf + i) - 'a') + 0xa);
else if (*(buf + i) <= 'F' && *(buf + i) >= 'A')
value = (value << 4) | ((*(buf + i) - 'A') + 0xa);
else
break;
}
i++;
rt5691->adb_reg_value[j] = value;
j++;
}
rt5691->adb_reg_num = j;
for (i = 0; i < rt5691->adb_reg_num; i++) {
regmap_write(rt5691->regmap,
rt5691->adb_reg_addr[i],
rt5691->adb_reg_value[i]);
}
}
return count;
}
static const struct file_operations rt5691_codec_reg_adb_fops = {
.open = simple_open,
.read = rt5691_codec_reg_adb_read_file,
.write = rt5691_codec_reg_adb_write_file,
.llseek = default_llseek,
};
#endif
static int rt5691_i2c_probe(struct i2c_client *i2c,
const struct i2c_device_id *id)
{
struct rt5691_platform_data *pdata = dev_get_platdata(&i2c->dev);
struct rt5691_priv *rt5691;
struct regulator *regulator_1v8, *regulator_3v3;
int ret;
unsigned int val;
rt5691 = devm_kzalloc(&i2c->dev, sizeof(struct rt5691_priv),
GFP_KERNEL);
if (rt5691 == NULL)
return -ENOMEM;
i2c_set_clientdata(i2c, rt5691);
if (pdata)
rt5691->pdata = *pdata;
else
rt5691_parse_dt(rt5691, &i2c->dev);
regulator_1v8 = devm_regulator_get(&i2c->dev, "regulator_1v8");
if (IS_ERR(regulator_1v8))
dev_err(&i2c->dev, "Fail to get regulator_1v8\n");
else if (regulator_enable(regulator_1v8))
dev_err(&i2c->dev, "Fail to enable regulator_1v8\n");
regulator_3v3 = devm_regulator_get(&i2c->dev, "regulator_3v3");
if (IS_ERR(regulator_3v3))
dev_err(&i2c->dev, "Fail to get regulator_3v3\n");
else if (regulator_enable(regulator_3v3))
dev_err(&i2c->dev, "Fail to enable regulator_3v3\n");
if (gpio_is_valid(rt5691->pdata.gpio_1v8)) {
if (devm_gpio_request(&i2c->dev, rt5691->pdata.gpio_1v8,
"rt5691"))
dev_err(&i2c->dev, "Fail gpio_request gpio_1v8\n");
else if (gpio_direction_output(rt5691->pdata.gpio_1v8, 1))
dev_err(&i2c->dev, "Fail gpio_direction gpio_1v8\n");
}
if (gpio_is_valid(rt5691->pdata.gpio_3v3)) {
if (devm_gpio_request(&i2c->dev, rt5691->pdata.gpio_3v3,
"rt5691"))
dev_err(&i2c->dev, "Fail gpio_request gpio_3v3\n");
else if (gpio_direction_output(rt5691->pdata.gpio_3v3, 1))
dev_err(&i2c->dev, "Fail gpio_direction gpio_ldo\n");
}
if (gpio_is_valid(rt5691->pdata.ldo1_en)) {
if (devm_gpio_request(&i2c->dev, rt5691->pdata.ldo1_en,
"rt5691"))
dev_err(&i2c->dev, "Fail gpio_request gpio_ldo\n");
else if (gpio_direction_output(rt5691->pdata.ldo1_en, 1))
dev_err(&i2c->dev, "Fail gpio_direction gpio_ldo\n");
}
/* Sleep for 100 ms minimum */
usleep_range(100000, 150000);
if (rt5691->pdata.i2c_op_count) {
rt5691->i2c_regmap = devm_regmap_init_i2c(i2c, &rt5691_i2c_regmap);
if (IS_ERR(rt5691->i2c_regmap)) {
ret = PTR_ERR(rt5691->i2c_regmap);
dev_err(&i2c->dev, "Failed to allocate i2c_regmap: %d\n",
ret);
return ret;
}
rt5691->regmap = devm_regmap_init(&i2c->dev, NULL, i2c,
&rt5691_debug_regmap);
if (IS_ERR(rt5691->regmap)) {
ret = PTR_ERR(rt5691->regmap);
dev_err(&i2c->dev, "Failed to allocate debug_regmap: %d\n",
ret);
return ret;
}
} else {
rt5691->regmap = devm_regmap_init_i2c(i2c, &rt5691_regmap);
if (IS_ERR(rt5691->regmap)) {
ret = PTR_ERR(rt5691->regmap);
dev_err(&i2c->dev, "Failed to allocate regmap: %d\n",
ret);
return ret;
}
}
regmap_read(rt5691->regmap, RT5691_DEVICE_ID, &val);
if (val != 0x1091 && val != 0x6827) {
dev_err(&i2c->dev,
"Device with ID register %x is not rt5691\n", val);
if (IS_ERR(regulator_1v8))
dev_err(&i2c->dev, "Fail to get regulator_1v8\n");
else if (regulator_disable(regulator_1v8))
dev_err(&i2c->dev, "Fail to disable regulator_1v8\n");
if (IS_ERR(regulator_3v3))
dev_err(&i2c->dev, "Fail to get regulator_3v3\n");
else if (regulator_disable(regulator_3v3))
dev_err(&i2c->dev, "Fail to disable regulator_3v3\n");
return -ENODEV;
} else {
dev_info(&i2c->dev, "Device ID = 0x%04x\n", val);
}
regmap_write(rt5691->regmap, RT5691_RESET, 0);
regmap_multi_reg_write(rt5691->regmap,
rt5691_init_list, ARRAY_SIZE(rt5691_init_list));
if (rt5691->pdata.in1_diff)
regmap_update_bits(rt5691->regmap, RT5691_IN1_IN2_CTRL,
0x1 << 15, 0x1 << 15);
if (rt5691->pdata.in2_diff)
regmap_update_bits(rt5691->regmap, RT5691_IN1_IN2_CTRL,
0x1 << 7, 0x1 << 7);
if (rt5691->pdata.in3_diff)
regmap_update_bits(rt5691->regmap, RT5691_IN3_CTRL,
0x1 << 15, 0x1 << 15);
if (rt5691->pdata.gpio2_func)
regmap_update_bits(rt5691->regmap, RT5691_MULTI_FUNC_PIN_CTRL_1,
0x3 << 13, rt5691->pdata.gpio2_func << 13);
if (rt5691->pdata.gpio3_func)
regmap_update_bits(rt5691->regmap, RT5691_MULTI_FUNC_PIN_CTRL_1,
0x3 << 11, rt5691->pdata.gpio3_func << 11);
if (rt5691->pdata.sar_pb_vth0) {
regmap_write(rt5691->regmap, RT5691_SAR_ADC_DET_CTRL_17,
(rt5691->pdata.sar_pb_vth0 & 0x700) >> 8);
regmap_write(rt5691->regmap, RT5691_SAR_ADC_DET_CTRL_18,
rt5691->pdata.sar_pb_vth0 & 0xff);
}
if (rt5691->pdata.sar_pb_vth1) {
regmap_write(rt5691->regmap, RT5691_SAR_ADC_DET_CTRL_15,
(rt5691->pdata.sar_pb_vth1 & 0x700) >> 8);
regmap_write(rt5691->regmap, RT5691_SAR_ADC_DET_CTRL_16,
rt5691->pdata.sar_pb_vth1 & 0xff);
}
if (rt5691->pdata.sar_pb_vth2) {
regmap_write(rt5691->regmap, RT5691_SAR_ADC_DET_CTRL_13,
(rt5691->pdata.sar_pb_vth2 & 0x700) >> 8);
regmap_write(rt5691->regmap, RT5691_SAR_ADC_DET_CTRL_14,
rt5691->pdata.sar_pb_vth2 & 0xff);
}
if (rt5691->pdata.sar_pb_vth3) {
regmap_write(rt5691->regmap, RT5691_SAR_ADC_DET_CTRL_11,
(rt5691->pdata.sar_pb_vth3 & 0x700) >> 8);
regmap_write(rt5691->regmap, RT5691_SAR_ADC_DET_CTRL_12,
rt5691->pdata.sar_pb_vth3 & 0xff);
}
if (rt5691->pdata.jd_resistor)
regmap_write(rt5691->regmap, RT5691_COMBO_WATER_CTRL_4,
rt5691->pdata.jd_resistor);
if (rt5691->pdata.hpa_capless_bias)
regmap_write(rt5691->regmap, RT5691_ANLG_BIAS_CTRL_4,
rt5691->pdata.hpa_capless_bias);
#ifdef CONFIG_SWITCH
switch_dev_register(&rt5691_headset_switch);
#endif
#ifdef CONFIG_DEBUG_FS
rt5691_debugfs_root = debugfs_create_dir("rt5691", NULL);
if (!rt5691_debugfs_root) {
dev_err(&i2c->dev, "Failed to create debugfs root\n");
} else {
debugfs_create_file("codec_reg", 0664,
rt5691_debugfs_root, rt5691,
&rt5691_codec_reg_fops);
debugfs_create_file("codec_reg_adb", 0664,
rt5691_debugfs_root, rt5691,
&rt5691_codec_reg_adb_fops);
}
#endif
INIT_DELAYED_WORK(&rt5691->jack_detect_work,
rt5691_jack_detect_handler);
INIT_DELAYED_WORK(&rt5691->calibrate_work, rt5691_calibrate_handler);
INIT_DELAYED_WORK(&rt5691->sto1_l_adc_work, rt5691_sto1_l_adc_handler);
INIT_DELAYED_WORK(&rt5691->sto1_r_adc_work, rt5691_sto1_r_adc_handler);
INIT_DELAYED_WORK(&rt5691->sto2_l_adc_work, rt5691_sto2_l_adc_handler);
INIT_DELAYED_WORK(&rt5691->sto2_r_adc_work, rt5691_sto2_r_adc_handler);
INIT_DELAYED_WORK(&rt5691->mic_check_work, rt5691_mic_check_handler);
if (i2c->irq)
rt5691->irq = i2c->irq;
device_init_wakeup(&i2c->dev, true);
return devm_snd_soc_register_component(&i2c->dev, &rt5691_soc_component_dev,
rt5691_dai, ARRAY_SIZE(rt5691_dai));
}
static int rt5691_i2c_remove(struct i2c_client *i2c)
{
#ifdef CONFIG_SWITCH
switch_dev_unregister(&rt5691_headset_switch);
#endif
device_init_wakeup(&i2c->dev, false);
return 0;
}
static void rt5691_i2c_shutdown(struct i2c_client *client)
{
struct rt5691_priv *rt5691 = i2c_get_clientdata(client);
regmap_write(rt5691->regmap, RT5691_RESET, 0);
}
#ifdef CONFIG_OF
static const struct of_device_id rt5691_of_match[] = {
{.compatible = "realtek,rt5691"},
{},
};
MODULE_DEVICE_TABLE(of, rt5691_of_match);
#endif
#ifdef CONFIG_ACPI
static struct acpi_device_id rt5691_acpi_match[] = {
{"10EC5691", 0,},
{},
};
MODULE_DEVICE_TABLE(acpi, rt5691_acpi_match);
#endif
#ifdef CONFIG_PM_SLEEP
static int rt5691_pm_suspend(struct device *dev)
{
struct rt5691_priv *rt5691 = dev_get_drvdata(dev);
struct snd_soc_component *component = rt5691->component;
dev_info(component->dev, "%s\n", __func__);
rt5691->is_suspend = true;
return 0;
}
static int rt5691_pm_resume(struct device *dev)
{
struct rt5691_priv *rt5691 = dev_get_drvdata(dev);
struct snd_soc_component *component = rt5691->component;
dev_info(component->dev, "%s\n", __func__);
rt5691->is_suspend = false;
rt5691->rek = true;
return 0;
}
#endif
static const struct dev_pm_ops rt5691_pm_ops = {
SET_SYSTEM_SLEEP_PM_OPS(rt5691_pm_suspend, rt5691_pm_resume)
};
struct i2c_driver rt5691_i2c_driver = {
.driver = {
.name = "rt5691",
.owner = THIS_MODULE,
.of_match_table = of_match_ptr(rt5691_of_match),
.acpi_match_table = ACPI_PTR(rt5691_acpi_match),
.pm = &rt5691_pm_ops,
},
.probe = rt5691_i2c_probe,
.remove = rt5691_i2c_remove,
.shutdown = rt5691_i2c_shutdown,
.id_table = rt5691_i2c_id,
};
module_i2c_driver(rt5691_i2c_driver);
MODULE_DESCRIPTION("ASoC RT5691 driver");
MODULE_AUTHOR("Oder Chiou<oder_chiou@realtek.com>");
MODULE_LICENSE("GPL v2");