// SPDX-License-Identifier: GPL-2.0
/*
* rt1011.c -- rt1011 ALSA SoC amplifier component driver
*
* Copyright(c) 2019 Realtek Semiconductor Corp.
*
* Author: Shuming Fan <shumingf@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/acpi.h>
#include <linux/regmap.h>
#include <linux/platform_device.h>
#include <linux/firmware.h>
#include <sound/core.h>
#include <sound/pcm.h>
#include <sound/pcm_params.h>
#include <sound/soc.h>
#include <sound/soc-dapm.h>
#include <sound/initval.h>
#include <sound/tlv.h>
#include "rl6231.h"
#include "rt1011.h"
static int rt1011_calibrate(struct rt1011_priv *rt1011,
unsigned char cali_flag);
static const struct reg_sequence init_list[] = {
{ RT1011_POWER_9, 0 xa840 },
{ RT1011_ADC_SET_5, 0 x0a20 },
{ RT1011_DAC_SET_2, 0 xa032 },
{ RT1011_SPK_PRO_DC_DET_1, 0 xb00c },
{ RT1011_SPK_PRO_DC_DET_2, 0 xcccc },
{ RT1011_A_TIMING_1, 0 x6054 },
{ RT1011_POWER_7, 0 x3e55 },
{ RT1011_POWER_8, 0 x0520 },
{ RT1011_BOOST_CON_1, 0 xe188 },
{ RT1011_POWER_4, 0 x16f2 },
{ RT1011_CROSS_BQ_SET_1, 0 x0004 },
{ RT1011_SIL_DET, 0 xc313 },
{ RT1011_SINE_GEN_REG_1, 0 x0707 },
{ RT1011_DC_CALIB_CLASSD_3, 0 xcb00 },
{ RT1011_DAC_SET_1, 0 xe702 },
{ RT1011_DAC_SET_3, 0 x2004 },
};
static const struct reg_default rt1011_reg[] = {
{0 x0000, 0 x0000},
{0 x0002, 0 x0000},
{0 x0004, 0 xa000},
{0 x0006, 0 x0000},
{0 x0008, 0 x0003},
{0 x000a, 0 x087e},
{0 x000c, 0 x0020},
{0 x000e, 0 x9002},
{0 x0010, 0 x0000},
{0 x0012, 0 x0000},
{0 x0020, 0 x0c40},
{0 x0022, 0 x4313},
{0 x0076, 0 x0000},
{0 x0078, 0 x0000},
{0 x007a, 0 x0000},
{0 x007c, 0 x10ec},
{0 x007d, 0 x1011},
{0 x00f0, 0 x5000},
{0 x00f2, 0 x0374},
{0 x00f3, 0 x0000},
{0 x00f4, 0 x0000},
{0 x0100, 0 x0038},
{0 x0102, 0 xff02},
{0 x0104, 0 x0232},
{0 x0106, 0 x200c},
{0 x0107, 0 x0000},
{0 x0108, 0 x2f2f},
{0 x010a, 0 x2f2f},
{0 x010c, 0 x002f},
{0 x010e, 0 xe000},
{0 x0110, 0 x0820},
{0 x0111, 0 x4010},
{0 x0112, 0 x0000},
{0 x0114, 0 x0000},
{0 x0116, 0 x0000},
{0 x0118, 0 x0000},
{0 x011a, 0 x0101},
{0 x011c, 0 x4567},
{0 x011e, 0 x0000},
{0 x0120, 0 x0000},
{0 x0122, 0 x0000},
{0 x0124, 0 x0123},
{0 x0126, 0 x4567},
{0 x0200, 0 x0000},
{0 x0300, 0 xffdd},
{0 x0302, 0 x001e},
{0 x0311, 0 x0000},
{0 x0313, 0 x5254},
{0 x0314, 0 x0062},
{0 x0316, 0 x7f40},
{0 x0319, 0 x000f},
{0 x031a, 0 xffff},
{0 x031b, 0 x0000},
{0 x031c, 0 x009f},
{0 x031d, 0 xffff},
{0 x031e, 0 x0000},
{0 x031f, 0 x0000},
{0 x0320, 0 xe31c},
{0 x0321, 0 x0000},
{0 x0322, 0 x0000},
{0 x0324, 0 x0000},
{0 x0326, 0 x0002},
{0 x0328, 0 x20b2},
{0 x0329, 0 x0175},
{0 x032a, 0 x32ad},
{0 x032b, 0 x3455},
{0 x032c, 0 x0528},
{0 x032d, 0 xa800},
{0 x032e, 0 x030e},
{0 x0330, 0 x2080},
{0 x0332, 0 x0034},
{0 x0334, 0 x0000},
{0 x0508, 0 x0010},
{0 x050a, 0 x0018},
{0 x050c, 0 x0000},
{0 x050d, 0 xffff},
{0 x050e, 0 x1f1f},
{0 x050f, 0 x04ff},
{0 x0510, 0 x4020},
{0 x0511, 0 x01f0},
{0 x0512, 0 x0702},
{0 x0516, 0 xbb80},
{0 x0517, 0 xffff},
{0 x0518, 0 xffff},
{0 x0519, 0 x307f},
{0 x051a, 0 xffff},
{0 x051b, 0 x0000},
{0 x051c, 0 x0000},
{0 x051d, 0 x2000},
{0 x051e, 0 x0000},
{0 x051f, 0 x0000},
{0 x0520, 0 x0000},
{0 x0521, 0 x1001},
{0 x0522, 0 x7fff},
{0 x0524, 0 x7fff},
{0 x0526, 0 x0000},
{0 x0528, 0 x0000},
{0 x052a, 0 x0000},
{0 x0530, 0 x0401},
{0 x0532, 0 x3000},
{0 x0534, 0 x0000},
{0 x0535, 0 xffff},
{0 x0536, 0 x101c},
{0 x0538, 0 x1814},
{0 x053a, 0 x100c},
{0 x053c, 0 x0804},
{0 x053d, 0 x0000},
{0 x053e, 0 x0000},
{0 x053f, 0 x0000},
{0 x0540, 0 x0000},
{0 x0541, 0 x0000},
{0 x0542, 0 x0000},
{0 x0543, 0 x0000},
{0 x0544, 0 x001c},
{0 x0545, 0 x1814},
{0 x0546, 0 x100c},
{0 x0547, 0 x0804},
{0 x0548, 0 x0000},
{0 x0549, 0 x0000},
{0 x054a, 0 x0000},
{0 x054b, 0 x0000},
{0 x054c, 0 x0000},
{0 x054d, 0 x0000},
{0 x054e, 0 x0000},
{0 x054f, 0 x0000},
{0 x0566, 0 x0000},
{0 x0568, 0 x20f1},
{0 x056a, 0 x0007},
{0 x0600, 0 x9d00},
{0 x0611, 0 x2000},
{0 x0612, 0 x505f},
{0 x0613, 0 x0444},
{0 x0614, 0 x4000},
{0 x0615, 0 x4004},
{0 x0616, 0 x0606},
{0 x0617, 0 x8904},
{0 x0618, 0 xe021},
{0 x0621, 0 x2000},
{0 x0622, 0 x505f},
{0 x0623, 0 x0444},
{0 x0624, 0 x4000},
{0 x0625, 0 x4004},
{0 x0626, 0 x0606},
{0 x0627, 0 x8704},
{0 x0628, 0 xe021},
{0 x0631, 0 x2000},
{0 x0632, 0 x517f},
{0 x0633, 0 x0440},
{0 x0634, 0 x4000},
{0 x0635, 0 x4104},
{0 x0636, 0 x0306},
{0 x0637, 0 x8904},
{0 x0638, 0 xe021},
{0 x0702, 0 x0014},
{0 x0704, 0 x0000},
{0 x0706, 0 x0014},
{0 x0708, 0 x0000},
{0 x070a, 0 x0000},
{0 x0710, 0 x0200},
{0 x0711, 0 x0000},
{0 x0712, 0 x0200},
{0 x0713, 0 x0000},
{0 x0720, 0 x0200},
{0 x0721, 0 x0000},
{0 x0722, 0 x0000},
{0 x0723, 0 x0000},
{0 x0724, 0 x0000},
{0 x0725, 0 x0000},
{0 x0726, 0 x0000},
{0 x0727, 0 x0000},
{0 x0728, 0 x0000},
{0 x0729, 0 x0000},
{0 x0730, 0 x0200},
{0 x0731, 0 x0000},
{0 x0732, 0 x0000},
{0 x0733, 0 x0000},
{0 x0734, 0 x0000},
{0 x0735, 0 x0000},
{0 x0736, 0 x0000},
{0 x0737, 0 x0000},
{0 x0738, 0 x0000},
{0 x0739, 0 x0000},
{0 x0740, 0 x0200},
{0 x0741, 0 x0000},
{0 x0742, 0 x0000},
{0 x0743, 0 x0000},
{0 x0744, 0 x0000},
{0 x0745, 0 x0000},
{0 x0746, 0 x0000},
{0 x0747, 0 x0000},
{0 x0748, 0 x0000},
{0 x0749, 0 x0000},
{0 x0750, 0 x0200},
{0 x0751, 0 x0000},
{0 x0752, 0 x0000},
{0 x0753, 0 x0000},
{0 x0754, 0 x0000},
{0 x0755, 0 x0000},
{0 x0756, 0 x0000},
{0 x0757, 0 x0000},
{0 x0758, 0 x0000},
{0 x0759, 0 x0000},
{0 x0760, 0 x0200},
{0 x0761, 0 x0000},
{0 x0762, 0 x0000},
{0 x0763, 0 x0000},
{0 x0764, 0 x0000},
{0 x0765, 0 x0000},
{0 x0766, 0 x0000},
{0 x0767, 0 x0000},
{0 x0768, 0 x0000},
{0 x0769, 0 x0000},
{0 x0770, 0 x0200},
{0 x0771, 0 x0000},
{0 x0772, 0 x0000},
{0 x0773, 0 x0000},
{0 x0774, 0 x0000},
{0 x0775, 0 x0000},
{0 x0776, 0 x0000},
{0 x0777, 0 x0000},
{0 x0778, 0 x0000},
{0 x0779, 0 x0000},
{0 x0780, 0 x0200},
{0 x0781, 0 x0000},
{0 x0782, 0 x0000},
{0 x0783, 0 x0000},
{0 x0784, 0 x0000},
{0 x0785, 0 x0000},
{0 x0786, 0 x0000},
{0 x0787, 0 x0000},
{0 x0788, 0 x0000},
{0 x0789, 0 x0000},
{0 x0790, 0 x0200},
{0 x0791, 0 x0000},
{0 x0792, 0 x0000},
{0 x0793, 0 x0000},
{0 x0794, 0 x0000},
{0 x0795, 0 x0000},
{0 x0796, 0 x0000},
{0 x0797, 0 x0000},
{0 x0798, 0 x0000},
{0 x0799, 0 x0000},
{0 x07a0, 0 x0200},
{0 x07a1, 0 x0000},
{0 x07a2, 0 x0000},
{0 x07a3, 0 x0000},
{0 x07a4, 0 x0000},
{0 x07a5, 0 x0000},
{0 x07a6, 0 x0000},
{0 x07a7, 0 x0000},
{0 x07a8, 0 x0000},
{0 x07a9, 0 x0000},
{0 x07b0, 0 x0200},
{0 x07b1, 0 x0000},
{0 x07b2, 0 x0000},
{0 x07b3, 0 x0000},
{0 x07b4, 0 x0000},
{0 x07b5, 0 x0000},
{0 x07b6, 0 x0000},
{0 x07b7, 0 x0000},
{0 x07b8, 0 x0000},
{0 x07b9, 0 x0000},
{0 x07c0, 0 x0200},
{0 x07c1, 0 x0000},
{0 x07c2, 0 x0000},
{0 x07c3, 0 x0000},
{0 x07c4, 0 x0000},
{0 x07c5, 0 x0000},
{0 x07c6, 0 x0000},
{0 x07c7, 0 x0000},
{0 x07c8, 0 x0000},
{0 x07c9, 0 x0000},
{0 x1000, 0 x4040},
{0 x1002, 0 x6505},
{0 x1004, 0 x5405},
{0 x1006, 0 x5555},
{0 x1007, 0 x003f},
{0 x1008, 0 x7fd7},
{0 x1009, 0 x770f},
{0 x100a, 0 xfffe},
{0 x100b, 0 xe000},
{0 x100c, 0 x0000},
{0 x100d, 0 x0007},
{0 x1010, 0 xa433},
{0 x1020, 0 x0000},
{0 x1022, 0 x0000},
{0 x1024, 0 x0000},
{0 x1200, 0 x5a01},
{0 x1202, 0 x6324},
{0 x1204, 0 x0b00},
{0 x1206, 0 x0000},
{0 x1208, 0 x0000},
{0 x120a, 0 x0024},
{0 x120c, 0 x0000},
{0 x120e, 0 x000e},
{0 x1210, 0 x0000},
{0 x1212, 0 x0000},
{0 x1300, 0 x0701},
{0 x1302, 0 x12f9},
{0 x1304, 0 x3405},
{0 x1305, 0 x0844},
{0 x1306, 0 x5611},
{0 x1308, 0 x555e},
{0 x130a, 0 xa605},
{0 x130c, 0 x2000},
{0 x130e, 0 x0000},
{0 x130f, 0 x0001},
{0 x1310, 0 xaa48},
{0 x1312, 0 x0285},
{0 x1314, 0 xaaaa},
{0 x1316, 0 xaaa0},
{0 x1318, 0 x2aaa},
{0 x131a, 0 xaa07},
{0 x1322, 0 x0029},
{0 x1323, 0 x4a52},
{0 x1324, 0 x002c},
{0 x1325, 0 x0b02},
{0 x1326, 0 x002d},
{0 x1327, 0 x6b5a},
{0 x1328, 0 x002e},
{0 x1329, 0 xcbb2},
{0 x132a, 0 x0030},
{0 x132b, 0 x2c0b},
{0 x1330, 0 x0031},
{0 x1331, 0 x8c63},
{0 x1332, 0 x0032},
{0 x1333, 0 xecbb},
{0 x1334, 0 x0034},
{0 x1335, 0 x4d13},
{0 x1336, 0 x0037},
{0 x1337, 0 x0dc3},
{0 x1338, 0 x003d},
{0 x1339, 0 xef7b},
{0 x133a, 0 x0044},
{0 x133b, 0 xd134},
{0 x133c, 0 x0047},
{0 x133d, 0 x91e4},
{0 x133e, 0 x004d},
{0 x133f, 0 xc370},
{0 x1340, 0 x0053},
{0 x1341, 0 xf4fd},
{0 x1342, 0 x0060},
{0 x1343, 0 x5816},
{0 x1344, 0 x006c},
{0 x1345, 0 xbb2e},
{0 x1346, 0 x0072},
{0 x1347, 0 xecbb},
{0 x1348, 0 x0076},
{0 x1349, 0 x5d97},
{0 x1500, 0 x0702},
{0 x1502, 0 x002f},
{0 x1504, 0 x0000},
{0 x1510, 0 x0064},
{0 x1512, 0 x0000},
{0 x1514, 0 xdf47},
{0 x1516, 0 x079c},
{0 x1518, 0 xfbf5},
{0 x151a, 0 x00bc},
{0 x151c, 0 x3b85},
{0 x151e, 0 x02b3},
{0 x1520, 0 x3333},
{0 x1522, 0 x0000},
{0 x1524, 0 x4000},
{0 x1528, 0 x0064},
{0 x152a, 0 x0000},
{0 x152c, 0 x0000},
{0 x152e, 0 x0000},
{0 x1530, 0 x0000},
{0 x1532, 0 x0000},
{0 x1534, 0 x0000},
{0 x1536, 0 x0000},
{0 x1538, 0 x0040},
{0 x1539, 0 x0000},
{0 x153a, 0 x0040},
{0 x153b, 0 x0000},
{0 x153c, 0 x0064},
{0 x153e, 0 x0bf9},
{0 x1540, 0 xb2a9},
{0 x1544, 0 x0200},
{0 x1546, 0 x0000},
{0 x1548, 0 x00ca},
{0 x1552, 0 x03ff},
{0 x1554, 0 x017f},
{0 x1556, 0 x017f},
{0 x155a, 0 x0000},
{0 x155c, 0 x0000},
{0 x1560, 0 x0040},
{0 x1562, 0 x0000},
{0 x1570, 0 x03ff},
{0 x1571, 0 xdcff},
{0 x1572, 0 x1e00},
{0 x1573, 0 x224f},
{0 x1574, 0 x0000},
{0 x1575, 0 x0000},
{0 x1576, 0 x1e00},
{0 x1577, 0 x0000},
{0 x1578, 0 x0000},
{0 x1579, 0 x1128},
{0 x157a, 0 x03ff},
{0 x157b, 0 xdcff},
{0 x157c, 0 x1e00},
{0 x157d, 0 x224f},
{0 x157e, 0 x0000},
{0 x157f, 0 x0000},
{0 x1580, 0 x1e00},
{0 x1581, 0 x0000},
{0 x1582, 0 x0000},
{0 x1583, 0 x1128},
{0 x1590, 0 x03ff},
{0 x1591, 0 xdcff},
{0 x1592, 0 x1e00},
{0 x1593, 0 x224f},
{0 x1594, 0 x0000},
{0 x1595, 0 x0000},
{0 x1596, 0 x1e00},
{0 x1597, 0 x0000},
{0 x1598, 0 x0000},
{0 x1599, 0 x1128},
{0 x159a, 0 x03ff},
{0 x159b, 0 xdcff},
{0 x159c, 0 x1e00},
{0 x159d, 0 x224f},
{0 x159e, 0 x0000},
{0 x159f, 0 x0000},
{0 x15a0, 0 x1e00},
{0 x15a1, 0 x0000},
{0 x15a2, 0 x0000},
{0 x15a3, 0 x1128},
{0 x15b0, 0 x007f},
{0 x15b1, 0 xffff},
{0 x15b2, 0 x007f},
{0 x15b3, 0 xffff},
{0 x15b4, 0 x007f},
{0 x15b5, 0 xffff},
{0 x15b8, 0 x007f},
{0 x15b9, 0 xffff},
{0 x15bc, 0 x0000},
{0 x15bd, 0 x0000},
{0 x15be, 0 xff00},
{0 x15bf, 0 x0000},
{0 x15c0, 0 xff00},
{0 x15c1, 0 x0000},
{0 x15c3, 0 xfc00},
{0 x15c4, 0 xbb80},
{0 x15d0, 0 x0000},
{0 x15d1, 0 x0000},
{0 x15d2, 0 x0000},
{0 x15d3, 0 x0000},
{0 x15d4, 0 x0000},
{0 x15d5, 0 x0000},
{0 x15d6, 0 x0000},
{0 x15d7, 0 x0000},
{0 x15d8, 0 x0200},
{0 x15d9, 0 x0000},
{0 x15da, 0 x0000},
{0 x15db, 0 x0000},
{0 x15dc, 0 x0000},
{0 x15dd, 0 x0000},
{0 x15de, 0 x0000},
{0 x15df, 0 x0000},
{0 x15e0, 0 x0000},
{0 x15e1, 0 x0000},
{0 x15e2, 0 x0200},
{0 x15e3, 0 x0000},
{0 x15e4, 0 x0000},
{0 x15e5, 0 x0000},
{0 x15e6, 0 x0000},
{0 x15e7, 0 x0000},
{0 x15e8, 0 x0000},
{0 x15e9, 0 x0000},
{0 x15ea, 0 x0000},
{0 x15eb, 0 x0000},
{0 x15ec, 0 x0200},
{0 x15ed, 0 x0000},
{0 x15ee, 0 x0000},
{0 x15ef, 0 x0000},
{0 x15f0, 0 x0000},
{0 x15f1, 0 x0000},
{0 x15f2, 0 x0000},
{0 x15f3, 0 x0000},
{0 x15f4, 0 x0000},
{0 x15f5, 0 x0000},
{0 x15f6, 0 x0200},
{0 x15f7, 0 x0200},
{0 x15f8, 0 x8200},
{0 x15f9, 0 x0000},
{0 x1600, 0 x007d},
{0 x1601, 0 xa178},
{0 x1602, 0 x00c2},
{0 x1603, 0 x5383},
{0 x1604, 0 x0000},
{0 x1605, 0 x02c1},
{0 x1606, 0 x007d},
{0 x1607, 0 xa178},
{0 x1608, 0 x00c2},
{0 x1609, 0 x5383},
{0 x160a, 0 x003e},
{0 x160b, 0 xd37d},
{0 x1611, 0 x3210},
{0 x1612, 0 x7418},
{0 x1613, 0 xc0ff},
{0 x1614, 0 x0000},
{0 x1615, 0 x00ff},
{0 x1616, 0 x0000},
{0 x1617, 0 x0000},
{0 x1621, 0 x6210},
{0 x1622, 0 x7418},
{0 x1623, 0 xc0ff},
{0 x1624, 0 x0000},
{0 x1625, 0 x00ff},
{0 x1626, 0 x0000},
{0 x1627, 0 x0000},
{0 x1631, 0 x3a14},
{0 x1632, 0 x7418},
{0 x1633, 0 xc3ff},
{0 x1634, 0 x0000},
{0 x1635, 0 x00ff},
{0 x1636, 0 x0000},
{0 x1637, 0 x0000},
{0 x1638, 0 x0000},
{0 x163a, 0 x0000},
{0 x163c, 0 x0000},
{0 x163e, 0 x0000},
{0 x1640, 0 x0000},
{0 x1642, 0 x0000},
{0 x1644, 0 x0000},
{0 x1646, 0 x0000},
{0 x1648, 0 x0000},
{0 x1650, 0 x0000},
{0 x1652, 0 x0000},
{0 x1654, 0 x0000},
{0 x1656, 0 x0000},
{0 x1658, 0 x0000},
{0 x1660, 0 x0000},
{0 x1662, 0 x0000},
{0 x1664, 0 x0000},
{0 x1666, 0 x0000},
{0 x1668, 0 x0000},
{0 x1670, 0 x0000},
{0 x1672, 0 x0000},
{0 x1674, 0 x0000},
{0 x1676, 0 x0000},
{0 x1678, 0 x0000},
{0 x1680, 0 x0000},
{0 x1682, 0 x0000},
{0 x1684, 0 x0000},
{0 x1686, 0 x0000},
{0 x1688, 0 x0000},
{0 x1690, 0 x0000},
{0 x1692, 0 x0000},
{0 x1694, 0 x0000},
{0 x1696, 0 x0000},
{0 x1698, 0 x0000},
{0 x1700, 0 x0000},
{0 x1702, 0 x0000},
{0 x1704, 0 x0000},
{0 x1706, 0 x0000},
{0 x1708, 0 x0000},
{0 x1710, 0 x0000},
{0 x1712, 0 x0000},
{0 x1714, 0 x0000},
{0 x1716, 0 x0000},
{0 x1718, 0 x0000},
{0 x1720, 0 x0000},
{0 x1722, 0 x0000},
{0 x1724, 0 x0000},
{0 x1726, 0 x0000},
{0 x1728, 0 x0000},
{0 x1730, 0 x0000},
{0 x1732, 0 x0000},
{0 x1734, 0 x0000},
{0 x1736, 0 x0000},
{0 x1738, 0 x0000},
{0 x173a, 0 x0000},
{0 x173c, 0 x0000},
{0 x173e, 0 x0000},
{0 x17bb, 0 x0500},
{0 x17bd, 0 x0004},
{0 x17bf, 0 x0004},
{0 x17c1, 0 x0004},
{0 x17c2, 0 x7fff},
{0 x17c3, 0 x0000},
{0 x17c5, 0 x0000},
{0 x17c7, 0 x0000},
{0 x17c9, 0 x0000},
{0 x17cb, 0 x2010},
{0 x17cd, 0 x0000},
{0 x17cf, 0 x0000},
{0 x17d1, 0 x0000},
{0 x17d3, 0 x0000},
{0 x17d5, 0 x0000},
{0 x17d7, 0 x0000},
{0 x17d9, 0 x0000},
{0 x17db, 0 x0000},
{0 x17dd, 0 x0000},
{0 x17df, 0 x0000},
{0 x17e1, 0 x0000},
{0 x17e3, 0 x0000},
{0 x17e5, 0 x0000},
{0 x17e7, 0 x0000},
{0 x17e9, 0 x0000},
{0 x17eb, 0 x0000},
{0 x17ed, 0 x0000},
{0 x17ef, 0 x0000},
{0 x17f1, 0 x0000},
{0 x17f3, 0 x0000},
{0 x17f5, 0 x0000},
{0 x17f7, 0 x0000},
{0 x17f9, 0 x0000},
{0 x17fb, 0 x0000},
{0 x17fd, 0 x0000},
{0 x17ff, 0 x0000},
{0 x1801, 0 x0000},
{0 x1803, 0 x0000},
};
static int rt1011_reg_init(struct snd_soc_component *component)
{
struct rt1011_priv *rt1011 = snd_soc_component_get_drvdata(component);
regmap_multi_reg_write(rt1011->regmap,
init_list, ARRAY_SIZE(init_list));
return 0 ;
}
static bool rt1011_volatile_register(struct device *dev, unsigned int reg)
{
switch (reg) {
case RT1011_RESET:
case RT1011_SRC_2:
case RT1011_CLK_DET:
case RT1011_SIL_DET:
case RT1011_VERSION_ID:
case RT1011_VENDOR_ID:
case RT1011_DEVICE_ID:
case RT1011_DUM_RO:
case RT1011_DAC_SET_3:
case RT1011_PWM_CAL:
case RT1011_SPK_VOL_TEST_OUT:
case RT1011_VBAT_VOL_DET_1:
case RT1011_VBAT_TEST_OUT_1:
case RT1011_VBAT_TEST_OUT_2:
case RT1011_VBAT_PROTECTION:
case RT1011_VBAT_DET:
case RT1011_BOOST_CON_1:
case RT1011_SHORT_CIRCUIT_DET_1:
case RT1011_SPK_TEMP_PROTECT_3:
case RT1011_SPK_TEMP_PROTECT_6:
case RT1011_SPK_PRO_DC_DET_3:
case RT1011_SPK_PRO_DC_DET_7:
case RT1011_SPK_PRO_DC_DET_8:
case RT1011_SPL_1:
case RT1011_SPL_4:
case RT1011_EXCUR_PROTECT_1:
case RT1011_CROSS_BQ_SET_1:
case RT1011_CROSS_BQ_SET_2:
case RT1011_BQ_SET_0:
case RT1011_BQ_SET_1:
case RT1011_BQ_SET_2:
case RT1011_TEST_PAD_STATUS:
case RT1011_DC_CALIB_CLASSD_1:
case RT1011_DC_CALIB_CLASSD_5:
case RT1011_DC_CALIB_CLASSD_6:
case RT1011_DC_CALIB_CLASSD_7:
case RT1011_DC_CALIB_CLASSD_8:
case RT1011_SINE_GEN_REG_2:
case RT1011_STP_CALIB_RS_TEMP:
case RT1011_SPK_RESISTANCE_1:
case RT1011_SPK_RESISTANCE_2:
case RT1011_SPK_THERMAL:
case RT1011_ALC_BK_GAIN_O:
case RT1011_ALC_BK_GAIN_O_PRE:
case RT1011_SPK_DC_O_23_16:
case RT1011_SPK_DC_O_15_0:
case RT1011_INIT_RECIPROCAL_SYN_24_16:
case RT1011_INIT_RECIPROCAL_SYN_15_0:
case RT1011_SPK_EXCURSION_23_16:
case RT1011_SPK_EXCURSION_15_0:
case RT1011_SEP_MAIN_OUT_23_16:
case RT1011_SEP_MAIN_OUT_15_0:
case RT1011_ALC_DRC_HB_INTERNAL_5:
case RT1011_ALC_DRC_HB_INTERNAL_6:
case RT1011_ALC_DRC_HB_INTERNAL_7:
case RT1011_ALC_DRC_BB_INTERNAL_5:
case RT1011_ALC_DRC_BB_INTERNAL_6:
case RT1011_ALC_DRC_BB_INTERNAL_7:
case RT1011_ALC_DRC_POS_INTERNAL_5:
case RT1011_ALC_DRC_POS_INTERNAL_6:
case RT1011_ALC_DRC_POS_INTERNAL_7:
case RT1011_ALC_DRC_POS_INTERNAL_8:
case RT1011_ALC_DRC_POS_INTERNAL_9:
case RT1011_ALC_DRC_POS_INTERNAL_10:
case RT1011_ALC_DRC_POS_INTERNAL_11:
case RT1011_IRQ_1:
case RT1011_EFUSE_CONTROL_1:
case RT1011_EFUSE_CONTROL_2:
case RT1011_EFUSE_MATCH_DONE ... RT1011_EFUSE_READ_R0_3_15_0:
return true ;
default :
return false ;
}
}
static bool rt1011_readable_register(struct device *dev, unsigned int reg)
{
switch (reg) {
case RT1011_RESET:
case RT1011_CLK_1:
case RT1011_CLK_2:
case RT1011_CLK_3:
case RT1011_CLK_4:
case RT1011_PLL_1:
case RT1011_PLL_2:
case RT1011_SRC_1:
case RT1011_SRC_2:
case RT1011_SRC_3:
case RT1011_CLK_DET:
case RT1011_SIL_DET:
case RT1011_PRIV_INDEX:
case RT1011_PRIV_DATA:
case RT1011_CUSTOMER_ID:
case RT1011_FM_VER:
case RT1011_VERSION_ID:
case RT1011_VENDOR_ID:
case RT1011_DEVICE_ID:
case RT1011_DUM_RW_0:
case RT1011_DUM_YUN:
case RT1011_DUM_RW_1:
case RT1011_DUM_RO:
case RT1011_MAN_I2C_DEV:
case RT1011_DAC_SET_1:
case RT1011_DAC_SET_2:
case RT1011_DAC_SET_3:
case RT1011_ADC_SET:
case RT1011_ADC_SET_1:
case RT1011_ADC_SET_2:
case RT1011_ADC_SET_3:
case RT1011_ADC_SET_4:
case RT1011_ADC_SET_5:
case RT1011_TDM_TOTAL_SET:
case RT1011_TDM1_SET_TCON:
case RT1011_TDM1_SET_1:
case RT1011_TDM1_SET_2:
case RT1011_TDM1_SET_3:
case RT1011_TDM1_SET_4:
case RT1011_TDM1_SET_5:
case RT1011_TDM2_SET_1:
case RT1011_TDM2_SET_2:
case RT1011_TDM2_SET_3:
case RT1011_TDM2_SET_4:
case RT1011_TDM2_SET_5:
case RT1011_PWM_CAL:
case RT1011_MIXER_1:
case RT1011_MIXER_2:
case RT1011_ADRC_LIMIT:
case RT1011_A_PRO:
case RT1011_A_TIMING_1:
case RT1011_A_TIMING_2:
case RT1011_A_TEMP_SEN:
case RT1011_SPK_VOL_DET_1:
case RT1011_SPK_VOL_DET_2:
case RT1011_SPK_VOL_TEST_OUT:
case RT1011_VBAT_VOL_DET_1:
case RT1011_VBAT_VOL_DET_2:
case RT1011_VBAT_TEST_OUT_1:
case RT1011_VBAT_TEST_OUT_2:
case RT1011_VBAT_PROTECTION:
case RT1011_VBAT_DET:
case RT1011_POWER_1:
case RT1011_POWER_2:
case RT1011_POWER_3:
case RT1011_POWER_4:
case RT1011_POWER_5:
case RT1011_POWER_6:
case RT1011_POWER_7:
case RT1011_POWER_8:
case RT1011_POWER_9:
case RT1011_CLASS_D_POS:
case RT1011_BOOST_CON_1:
case RT1011_BOOST_CON_2:
case RT1011_ANALOG_CTRL:
case RT1011_POWER_SEQ:
case RT1011_SHORT_CIRCUIT_DET_1:
case RT1011_SHORT_CIRCUIT_DET_2:
case RT1011_SPK_TEMP_PROTECT_0:
case RT1011_SPK_TEMP_PROTECT_1:
case RT1011_SPK_TEMP_PROTECT_2:
case RT1011_SPK_TEMP_PROTECT_3:
case RT1011_SPK_TEMP_PROTECT_4:
case RT1011_SPK_TEMP_PROTECT_5:
case RT1011_SPK_TEMP_PROTECT_6:
case RT1011_SPK_TEMP_PROTECT_7:
case RT1011_SPK_TEMP_PROTECT_8:
case RT1011_SPK_TEMP_PROTECT_9:
case RT1011_SPK_PRO_DC_DET_1:
case RT1011_SPK_PRO_DC_DET_2:
case RT1011_SPK_PRO_DC_DET_3:
case RT1011_SPK_PRO_DC_DET_4:
case RT1011_SPK_PRO_DC_DET_5:
case RT1011_SPK_PRO_DC_DET_6:
case RT1011_SPK_PRO_DC_DET_7:
case RT1011_SPK_PRO_DC_DET_8:
case RT1011_SPL_1:
case RT1011_SPL_2:
case RT1011_SPL_3:
case RT1011_SPL_4:
case RT1011_THER_FOLD_BACK_1:
case RT1011_THER_FOLD_BACK_2:
case RT1011_EXCUR_PROTECT_1:
case RT1011_EXCUR_PROTECT_2:
case RT1011_EXCUR_PROTECT_3:
case RT1011_EXCUR_PROTECT_4:
case RT1011_BAT_GAIN_1:
case RT1011_BAT_GAIN_2:
case RT1011_BAT_GAIN_3:
case RT1011_BAT_GAIN_4:
case RT1011_BAT_GAIN_5:
case RT1011_BAT_GAIN_6:
case RT1011_BAT_GAIN_7:
case RT1011_BAT_GAIN_8:
case RT1011_BAT_GAIN_9:
case RT1011_BAT_GAIN_10:
case RT1011_BAT_GAIN_11:
case RT1011_BAT_RT_THMAX_1:
case RT1011_BAT_RT_THMAX_2:
case RT1011_BAT_RT_THMAX_3:
case RT1011_BAT_RT_THMAX_4:
case RT1011_BAT_RT_THMAX_5:
case RT1011_BAT_RT_THMAX_6:
case RT1011_BAT_RT_THMAX_7:
case RT1011_BAT_RT_THMAX_8:
case RT1011_BAT_RT_THMAX_9:
case RT1011_BAT_RT_THMAX_10:
case RT1011_BAT_RT_THMAX_11:
case RT1011_BAT_RT_THMAX_12:
case RT1011_SPREAD_SPECTURM:
case RT1011_PRO_GAIN_MODE:
case RT1011_RT_DRC_CROSS:
case RT1011_RT_DRC_HB_1:
case RT1011_RT_DRC_HB_2:
case RT1011_RT_DRC_HB_3:
case RT1011_RT_DRC_HB_4:
case RT1011_RT_DRC_HB_5:
case RT1011_RT_DRC_HB_6:
case RT1011_RT_DRC_HB_7:
case RT1011_RT_DRC_HB_8:
case RT1011_RT_DRC_BB_1:
case RT1011_RT_DRC_BB_2:
case RT1011_RT_DRC_BB_3:
case RT1011_RT_DRC_BB_4:
case RT1011_RT_DRC_BB_5:
case RT1011_RT_DRC_BB_6:
case RT1011_RT_DRC_BB_7:
case RT1011_RT_DRC_BB_8:
case RT1011_RT_DRC_POS_1:
case RT1011_RT_DRC_POS_2:
case RT1011_RT_DRC_POS_3:
case RT1011_RT_DRC_POS_4:
case RT1011_RT_DRC_POS_5:
case RT1011_RT_DRC_POS_6:
case RT1011_RT_DRC_POS_7:
case RT1011_RT_DRC_POS_8:
case RT1011_CROSS_BQ_SET_1:
case RT1011_CROSS_BQ_SET_2:
case RT1011_BQ_SET_0:
case RT1011_BQ_SET_1:
case RT1011_BQ_SET_2:
case RT1011_BQ_PRE_GAIN_28_16:
case RT1011_BQ_PRE_GAIN_15_0:
case RT1011_BQ_POST_GAIN_28_16:
case RT1011_BQ_POST_GAIN_15_0:
case RT1011_BQ_H0_28_16 ... RT1011_BQ_A2_15_0:
case RT1011_BQ_1_H0_28_16 ... RT1011_BQ_1_A2_15_0:
case RT1011_BQ_2_H0_28_16 ... RT1011_BQ_2_A2_15_0:
case RT1011_BQ_3_H0_28_16 ... RT1011_BQ_3_A2_15_0:
case RT1011_BQ_4_H0_28_16 ... RT1011_BQ_4_A2_15_0:
case RT1011_BQ_5_H0_28_16 ... RT1011_BQ_5_A2_15_0:
case RT1011_BQ_6_H0_28_16 ... RT1011_BQ_6_A2_15_0:
case RT1011_BQ_7_H0_28_16 ... RT1011_BQ_7_A2_15_0:
case RT1011_BQ_8_H0_28_16 ... RT1011_BQ_8_A2_15_0:
case RT1011_BQ_9_H0_28_16 ... RT1011_BQ_9_A2_15_0:
case RT1011_BQ_10_H0_28_16 ... RT1011_BQ_10_A2_15_0:
case RT1011_TEST_PAD_STATUS ... RT1011_PLL_INTERNAL_SET:
case RT1011_TEST_OUT_1 ... RT1011_TEST_OUT_3:
case RT1011_DC_CALIB_CLASSD_1 ... RT1011_DC_CALIB_CLASSD_10:
case RT1011_CLASSD_INTERNAL_SET_1 ... RT1011_VREF_LV_1:
case RT1011_SMART_BOOST_TIMING_1 ... RT1011_SMART_BOOST_TIMING_36:
case RT1011_SINE_GEN_REG_1 ... RT1011_SINE_GEN_REG_3:
case RT1011_STP_INITIAL_RS_TEMP ... RT1011_SPK_THERMAL:
case RT1011_STP_OTP_TH ... RT1011_INIT_RECIPROCAL_SYN_15_0:
case RT1011_STP_BQ_1_A1_L_28_16 ... RT1011_STP_BQ_1_H0_R_15_0:
case RT1011_STP_BQ_2_A1_L_28_16 ... RT1011_SEP_RE_REG_15_0:
case RT1011_DRC_CF_PARAMS_1 ... RT1011_DRC_CF_PARAMS_12:
case RT1011_ALC_DRC_HB_INTERNAL_1 ... RT1011_ALC_DRC_HB_INTERNAL_7:
case RT1011_ALC_DRC_BB_INTERNAL_1 ... RT1011_ALC_DRC_BB_INTERNAL_7:
case RT1011_ALC_DRC_POS_INTERNAL_1 ... RT1011_ALC_DRC_POS_INTERNAL_8:
case RT1011_ALC_DRC_POS_INTERNAL_9 ... RT1011_BQ_1_PARAMS_CHECK_5:
case RT1011_BQ_2_PARAMS_CHECK_1 ... RT1011_BQ_2_PARAMS_CHECK_5:
case RT1011_BQ_3_PARAMS_CHECK_1 ... RT1011_BQ_3_PARAMS_CHECK_5:
case RT1011_BQ_4_PARAMS_CHECK_1 ... RT1011_BQ_4_PARAMS_CHECK_5:
case RT1011_BQ_5_PARAMS_CHECK_1 ... RT1011_BQ_5_PARAMS_CHECK_5:
case RT1011_BQ_6_PARAMS_CHECK_1 ... RT1011_BQ_6_PARAMS_CHECK_5:
case RT1011_BQ_7_PARAMS_CHECK_1 ... RT1011_BQ_7_PARAMS_CHECK_5:
case RT1011_BQ_8_PARAMS_CHECK_1 ... RT1011_BQ_8_PARAMS_CHECK_5:
case RT1011_BQ_9_PARAMS_CHECK_1 ... RT1011_BQ_9_PARAMS_CHECK_5:
case RT1011_BQ_10_PARAMS_CHECK_1 ... RT1011_BQ_10_PARAMS_CHECK_5:
case RT1011_IRQ_1 ... RT1011_PART_NUMBER_EFUSE:
case RT1011_EFUSE_CONTROL_1 ... RT1011_EFUSE_READ_R0_3_15_0:
return true ;
default :
return false ;
}
}
static const char * const rt1011_din_source_select[] = {
"Left" ,
"Right" ,
"Left + Right average" ,
};
static SOC_ENUM_SINGLE_DECL(rt1011_din_source_enum, RT1011_CROSS_BQ_SET_1, 5 ,
rt1011_din_source_select);
static const char * const rt1011_tdm_data_out_select[] = {
"TDM_O_LR" , "BQ1" , "DVOL" , "BQ10" , "ALC" , "DMIX" , "ADC_SRC_LR" ,
"ADC_O_LR" , "ADC_MONO" , "RSPK_BPF_LR" , "DMIX_ADD" , "ENVELOPE_FS" ,
"SEP_O_GAIN" , "ALC_BK_GAIN" , "STP_V_C" , "DMIX_ABST"
};
static const char * const rt1011_tdm_l_ch_data_select[] = {
"Slot0" , "Slot1" , "Slot2" , "Slot3" , "Slot4" , "Slot5" , "Slot6" , "Slot7"
};
static SOC_ENUM_SINGLE_DECL(rt1011_tdm1_l_dac1_enum, RT1011_TDM1_SET_4, 12 ,
rt1011_tdm_l_ch_data_select);
static SOC_ENUM_SINGLE_DECL(rt1011_tdm2_l_dac1_enum, RT1011_TDM2_SET_4, 12 ,
rt1011_tdm_l_ch_data_select);
static SOC_ENUM_SINGLE_DECL(rt1011_tdm1_adc1_dat_enum,
RT1011_ADCDAT_OUT_SOURCE, 0 , rt1011_tdm_data_out_select);
static SOC_ENUM_SINGLE_DECL(rt1011_tdm1_adc1_loc_enum, RT1011_TDM1_SET_2, 0 ,
rt1011_tdm_l_ch_data_select);
static const char * const rt1011_adc_data_mode_select[] = {
"Stereo" , "Mono"
};
static SOC_ENUM_SINGLE_DECL(rt1011_adc_dout_mode_enum, RT1011_TDM1_SET_1, 12 ,
rt1011_adc_data_mode_select);
static const char * const rt1011_tdm_adc_data_len_control[] = {
"1CH" , "2CH" , "3CH" , "4CH" , "5CH" , "6CH" , "7CH" , "8CH"
};
static SOC_ENUM_SINGLE_DECL(rt1011_tdm1_dout_len_enum, RT1011_TDM1_SET_2, 13 ,
rt1011_tdm_adc_data_len_control);
static SOC_ENUM_SINGLE_DECL(rt1011_tdm2_dout_len_enum, RT1011_TDM2_SET_2, 13 ,
rt1011_tdm_adc_data_len_control);
static const char * const rt1011_tdm_adc_swap_select[] = {
"L/R" , "R/L" , "L/L" , "R/R"
};
static SOC_ENUM_SINGLE_DECL(rt1011_tdm_adc1_1_enum, RT1011_TDM1_SET_3, 6 ,
rt1011_tdm_adc_swap_select);
static SOC_ENUM_SINGLE_DECL(rt1011_tdm_adc2_1_enum, RT1011_TDM1_SET_3, 4 ,
rt1011_tdm_adc_swap_select);
static void rt1011_reset(struct regmap *regmap)
{
regmap_write(regmap, RT1011_RESET, 0 );
}
static int rt1011_recv_spk_mode_get(struct snd_kcontrol *kcontrol,
struct snd_ctl_elem_value *ucontrol)
{
struct snd_soc_component *component =
snd_soc_kcontrol_component(kcontrol);
struct rt1011_priv *rt1011 =
snd_soc_component_get_drvdata(component);
ucontrol->value.integer.value[0 ] = rt1011->recv_spk_mode;
return 0 ;
}
static int rt1011_recv_spk_mode_put(struct snd_kcontrol *kcontrol,
struct snd_ctl_elem_value *ucontrol)
{
struct snd_soc_component *component =
snd_soc_kcontrol_component(kcontrol);
struct rt1011_priv *rt1011 =
snd_soc_component_get_drvdata(component);
if (ucontrol->value.integer.value[0 ] == rt1011->recv_spk_mode)
return 0 ;
if (snd_soc_component_get_bias_level(component) == SND_SOC_BIAS_OFF) {
rt1011->recv_spk_mode = ucontrol->value.integer.value[0 ];
if (rt1011->recv_spk_mode) {
/* 1: recevier mode on */
snd_soc_component_update_bits(component,
RT1011_CLASSD_INTERNAL_SET_3,
RT1011_REG_GAIN_CLASSD_RI_SPK_MASK,
RT1011_REG_GAIN_CLASSD_RI_410K);
snd_soc_component_update_bits(component,
RT1011_CLASSD_INTERNAL_SET_1,
RT1011_RECV_MODE_SPK_MASK,
RT1011_RECV_MODE);
} else {
/* 0: speaker mode on */
snd_soc_component_update_bits(component,
RT1011_CLASSD_INTERNAL_SET_3,
RT1011_REG_GAIN_CLASSD_RI_SPK_MASK,
RT1011_REG_GAIN_CLASSD_RI_72P5K);
snd_soc_component_update_bits(component,
RT1011_CLASSD_INTERNAL_SET_1,
RT1011_RECV_MODE_SPK_MASK,
RT1011_SPK_MODE);
}
}
return 0 ;
}
static bool rt1011_validate_bq_drc_coeff(unsigned short reg)
{
if ((reg == RT1011_DAC_SET_1) ||
(reg >= RT1011_ADC_SET && reg <= RT1011_ADC_SET_1) ||
(reg == RT1011_ADC_SET_4) || (reg == RT1011_ADC_SET_5) ||
(reg == RT1011_MIXER_1) ||
(reg == RT1011_A_TIMING_1) ||
(reg >= RT1011_POWER_7 && reg <= RT1011_POWER_8) ||
(reg == RT1011_CLASS_D_POS) || (reg == RT1011_ANALOG_CTRL) ||
(reg >= RT1011_SPK_TEMP_PROTECT_0 && reg <= RT1011_SPK_TEMP_PROTECT_6) ||
(reg >= RT1011_SPK_PRO_DC_DET_5 && reg <= RT1011_BAT_GAIN_1) ||
(reg >= RT1011_RT_DRC_CROSS && reg <= RT1011_RT_DRC_POS_8) ||
(reg >= RT1011_CROSS_BQ_SET_1 && reg <= RT1011_BQ_10_A2_15_0) ||
(reg >= RT1011_SMART_BOOST_TIMING_1 && reg <= RT1011_SMART_BOOST_TIMING_36) ||
(reg == RT1011_SINE_GEN_REG_1) ||
(reg >= RT1011_STP_ALPHA_RECIPROCAL_MSB && reg <= RT1011_BQ_6_PARAMS_CHECK_5) ||
(reg >= RT1011_BQ_7_PARAMS_CHECK_1 && reg <= RT1011_BQ_10_PARAMS_CHECK_5))
return true ;
return false ;
}
static int rt1011_bq_drc_coeff_get(struct snd_kcontrol *kcontrol,
struct snd_ctl_elem_value *ucontrol)
{
struct snd_soc_component *component =
snd_soc_kcontrol_component(kcontrol);
struct rt1011_priv *rt1011 =
snd_soc_component_get_drvdata(component);
struct rt1011_bq_drc_params *bq_drc_info;
struct rt1011_bq_drc_params *params =
(struct rt1011_bq_drc_params *)ucontrol->value.integer.value;
unsigned int i, mode_idx = 0 ;
if (strstr(ucontrol->id.name, "AdvanceMode Initial Set" ))
mode_idx = RT1011_ADVMODE_INITIAL_SET;
else if (strstr(ucontrol->id.name, "AdvanceMode SEP BQ Coeff" ))
mode_idx = RT1011_ADVMODE_SEP_BQ_COEFF;
else if (strstr(ucontrol->id.name, "AdvanceMode EQ BQ Coeff" ))
mode_idx = RT1011_ADVMODE_EQ_BQ_COEFF;
else if (strstr(ucontrol->id.name, "AdvanceMode BQ UI Coeff" ))
mode_idx = RT1011_ADVMODE_BQ_UI_COEFF;
else if (strstr(ucontrol->id.name, "AdvanceMode SmartBoost Coeff" ))
mode_idx = RT1011_ADVMODE_SMARTBOOST_COEFF;
else
return -EINVAL;
pr_info("%s, id.name=%s, mode_idx=%d\n" , __func__,
ucontrol->id.name, mode_idx);
bq_drc_info = rt1011->bq_drc_params[mode_idx];
for (i = 0 ; i < RT1011_BQ_DRC_NUM; i++) {
params[i].reg = bq_drc_info[i].reg;
params[i].val = bq_drc_info[i].val;
}
return 0 ;
}
static int rt1011_bq_drc_coeff_put(struct snd_kcontrol *kcontrol,
struct snd_ctl_elem_value *ucontrol)
{
struct snd_soc_component *component =
snd_soc_kcontrol_component(kcontrol);
struct rt1011_priv *rt1011 =
snd_soc_component_get_drvdata(component);
struct rt1011_bq_drc_params *bq_drc_info;
struct rt1011_bq_drc_params *params =
(struct rt1011_bq_drc_params *)ucontrol->value.integer.value;
unsigned int i, mode_idx = 0 ;
if (strstr(ucontrol->id.name, "AdvanceMode Initial Set" ))
mode_idx = RT1011_ADVMODE_INITIAL_SET;
else if (strstr(ucontrol->id.name, "AdvanceMode SEP BQ Coeff" ))
mode_idx = RT1011_ADVMODE_SEP_BQ_COEFF;
else if (strstr(ucontrol->id.name, "AdvanceMode EQ BQ Coeff" ))
mode_idx = RT1011_ADVMODE_EQ_BQ_COEFF;
else if (strstr(ucontrol->id.name, "AdvanceMode BQ UI Coeff" ))
mode_idx = RT1011_ADVMODE_BQ_UI_COEFF;
else if (strstr(ucontrol->id.name, "AdvanceMode SmartBoost Coeff" ))
mode_idx = RT1011_ADVMODE_SMARTBOOST_COEFF;
else
return -EINVAL;
bq_drc_info = rt1011->bq_drc_params[mode_idx];
memset(bq_drc_info, 0 ,
sizeof (struct rt1011_bq_drc_params) * RT1011_BQ_DRC_NUM);
pr_info("%s, id.name=%s, mode_idx=%d\n" , __func__,
ucontrol->id.name, mode_idx);
for (i = 0 ; i < RT1011_BQ_DRC_NUM; i++) {
bq_drc_info[i].reg = params[i].reg;
bq_drc_info[i].val = params[i].val;
}
for (i = 0 ; i < RT1011_BQ_DRC_NUM; i++) {
if (bq_drc_info[i].reg == 0 )
break ;
else if (rt1011_validate_bq_drc_coeff(bq_drc_info[i].reg)) {
snd_soc_component_write(component, bq_drc_info[i].reg,
bq_drc_info[i].val);
}
}
return 0 ;
}
static int rt1011_bq_drc_info(struct snd_kcontrol *kcontrol,
struct snd_ctl_elem_info *uinfo)
{
uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER;
uinfo->count = 128 ;
uinfo->value.integer.max = 0 x17ffffff;
return 0 ;
}
#define RT1011_BQ_DRC(xname) \
{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = xname, \
.info = rt1011_bq_drc_info, \
.get = rt1011_bq_drc_coeff_get, \
.put = rt1011_bq_drc_coeff_put \
}
static int rt1011_r0_cali_get(struct snd_kcontrol *kcontrol,
struct snd_ctl_elem_value *ucontrol)
{
struct snd_soc_component *component = snd_kcontrol_chip(kcontrol);
struct rt1011_priv *rt1011 = snd_soc_component_get_drvdata(component);
ucontrol->value.integer.value[0 ] = rt1011->cali_done;
return 0 ;
}
static int rt1011_r0_cali_put(struct snd_kcontrol *kcontrol,
struct snd_ctl_elem_value *ucontrol)
{
struct snd_soc_component *component = snd_kcontrol_chip(kcontrol);
struct rt1011_priv *rt1011 = snd_soc_component_get_drvdata(component);
rt1011->cali_done = 0 ;
if (snd_soc_component_get_bias_level(component) == SND_SOC_BIAS_OFF &&
ucontrol->value.integer.value[0 ])
rt1011_calibrate(rt1011, 1 );
return 0 ;
}
static int rt1011_r0_load(struct rt1011_priv *rt1011)
{
if (!rt1011->r0_reg)
return -EINVAL;
/* write R0 to register */
regmap_write(rt1011->regmap, RT1011_INIT_RECIPROCAL_REG_24_16,
((rt1011->r0_reg>>16 ) & 0 x1ff));
regmap_write(rt1011->regmap, RT1011_INIT_RECIPROCAL_REG_15_0,
(rt1011->r0_reg & 0 xffff));
regmap_write(rt1011->regmap, RT1011_SPK_TEMP_PROTECT_4, 0 x4080);
return 0 ;
}
static int rt1011_r0_load_mode_get(struct snd_kcontrol *kcontrol,
struct snd_ctl_elem_value *ucontrol)
{
struct snd_soc_component *component = snd_kcontrol_chip(kcontrol);
struct rt1011_priv *rt1011 = snd_soc_component_get_drvdata(component);
ucontrol->value.integer.value[0 ] = rt1011->r0_reg;
return 0 ;
}
static int rt1011_r0_load_mode_put(struct snd_kcontrol *kcontrol,
struct snd_ctl_elem_value *ucontrol)
{
struct snd_soc_component *component = snd_kcontrol_chip(kcontrol);
struct rt1011_priv *rt1011 = snd_soc_component_get_drvdata(component);
struct device *dev;
unsigned int r0_integer, r0_factor, format;
if (ucontrol->value.integer.value[0 ] == rt1011->r0_reg)
return 0 ;
if (ucontrol->value.integer.value[0 ] == 0 )
return -EINVAL;
dev = regmap_get_device(rt1011->regmap);
if (snd_soc_component_get_bias_level(component) == SND_SOC_BIAS_OFF) {
rt1011->r0_reg = ucontrol->value.integer.value[0 ];
format = 2147483648 U; /* 2^24 * 128 */
r0_integer = format / rt1011->r0_reg / 128 ;
r0_factor = ((format / rt1011->r0_reg * 100 ) / 128 )
- (r0_integer * 100 );
dev_info(dev, "New r0 resistance about %d.%02d ohm, reg=0x%X\n" ,
r0_integer, r0_factor, rt1011->r0_reg);
if (rt1011->r0_reg)
rt1011_r0_load(rt1011);
}
return 0 ;
}
static int rt1011_r0_load_info(struct snd_kcontrol *kcontrol,
struct snd_ctl_elem_info *uinfo)
{
uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER;
uinfo->count = 1 ;
uinfo->value.integer.max = 0 x1ffffff;
return 0 ;
}
#define RT1011_R0_LOAD(xname) \
{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = xname, \
.info = rt1011_r0_load_info, \
.get = rt1011_r0_load_mode_get, \
.put = rt1011_r0_load_mode_put \
}
static const char * const rt1011_i2s_ref[] = {
"None" , "Left Channel" , "Right Channel"
};
static SOC_ENUM_SINGLE_DECL(rt1011_i2s_ref_enum, 0 , 0 ,
rt1011_i2s_ref);
static int rt1011_i2s_ref_put(struct snd_kcontrol *kcontrol,
struct snd_ctl_elem_value *ucontrol)
{
struct snd_soc_component *component =
snd_soc_kcontrol_component(kcontrol);
struct rt1011_priv *rt1011 =
snd_soc_component_get_drvdata(component);
rt1011->i2s_ref = ucontrol->value.enumerated.item[0 ];
switch (rt1011->i2s_ref) {
case RT1011_I2S_REF_LEFT_CH:
regmap_write(rt1011->regmap, RT1011_TDM_TOTAL_SET, 0 x0240);
regmap_write(rt1011->regmap, RT1011_TDM1_SET_2, 0 x8);
regmap_write(rt1011->regmap, RT1011_TDM1_SET_1, 0 x1022);
regmap_write(rt1011->regmap, RT1011_ADCDAT_OUT_SOURCE, 0 x4);
break ;
case RT1011_I2S_REF_RIGHT_CH:
regmap_write(rt1011->regmap, RT1011_TDM_TOTAL_SET, 0 x0240);
regmap_write(rt1011->regmap, RT1011_TDM1_SET_2, 0 x8);
regmap_write(rt1011->regmap, RT1011_TDM1_SET_1, 0 x10a2);
regmap_write(rt1011->regmap, RT1011_ADCDAT_OUT_SOURCE, 0 x4);
break ;
default :
dev_info(component->dev, "I2S Reference: Do nothing\n" );
}
return 0 ;
}
static int rt1011_i2s_ref_get(struct snd_kcontrol *kcontrol,
struct snd_ctl_elem_value *ucontrol)
{
struct snd_soc_component *component =
snd_soc_kcontrol_component(kcontrol);
struct rt1011_priv *rt1011 =
snd_soc_component_get_drvdata(component);
ucontrol->value.enumerated.item[0 ] = rt1011->i2s_ref;
return 0 ;
}
static const struct snd_kcontrol_new rt1011_snd_controls[] = {
/* I2S Data In Selection */
SOC_ENUM("DIN Source" , rt1011_din_source_enum),
/* TDM Data In Selection */
SOC_ENUM("TDM1 DIN Source" , rt1011_tdm1_l_dac1_enum),
SOC_ENUM("TDM2 DIN Source" , rt1011_tdm2_l_dac1_enum),
/* TDM1 Data Out Selection */
SOC_ENUM("TDM1 DOUT Source" , rt1011_tdm1_adc1_dat_enum),
SOC_ENUM("TDM1 DOUT Location" , rt1011_tdm1_adc1_loc_enum),
SOC_ENUM("TDM1 ADC1DAT Swap Select" , rt1011_tdm_adc1_1_enum),
SOC_ENUM("TDM1 ADC2DAT Swap Select" , rt1011_tdm_adc2_1_enum),
/* Data Out Mode */
SOC_ENUM("I2S ADC DOUT Mode" , rt1011_adc_dout_mode_enum),
SOC_ENUM("TDM1 DOUT Length" , rt1011_tdm1_dout_len_enum),
SOC_ENUM("TDM2 DOUT Length" , rt1011_tdm2_dout_len_enum),
/* Speaker/Receiver Mode */
SOC_SINGLE_EXT("RECV SPK Mode" , SND_SOC_NOPM, 0 , 1 , 0 ,
rt1011_recv_spk_mode_get, rt1011_recv_spk_mode_put),
/* BiQuad/DRC/SmartBoost Settings */
RT1011_BQ_DRC("AdvanceMode Initial Set" ),
RT1011_BQ_DRC("AdvanceMode SEP BQ Coeff" ),
RT1011_BQ_DRC("AdvanceMode EQ BQ Coeff" ),
RT1011_BQ_DRC("AdvanceMode BQ UI Coeff" ),
RT1011_BQ_DRC("AdvanceMode SmartBoost Coeff" ),
/* R0 */
SOC_SINGLE_EXT("R0 Calibration" , SND_SOC_NOPM, 0 , 1 , 0 ,
rt1011_r0_cali_get, rt1011_r0_cali_put),
RT1011_R0_LOAD("R0 Load Mode" ),
/* R0 temperature */
SOC_SINGLE("R0 Temperature" , RT1011_STP_INITIAL_RESISTANCE_TEMP,
2 , 255 , 0 ),
/* I2S Reference */
SOC_ENUM_EXT("I2S Reference" , rt1011_i2s_ref_enum,
rt1011_i2s_ref_get, rt1011_i2s_ref_put),
};
static int rt1011_is_sys_clk_from_pll(struct snd_soc_dapm_widget *source,
struct snd_soc_dapm_widget *sink)
{
struct snd_soc_component *component =
snd_soc_dapm_to_component(source->dapm);
struct rt1011_priv *rt1011 = snd_soc_component_get_drvdata(component);
if (rt1011->sysclk_src == RT1011_FS_SYS_PRE_S_PLL1)
return 1 ;
else
return 0 ;
}
static int rt1011_dac_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_POST_PMU:
snd_soc_component_update_bits(component,
RT1011_SPK_TEMP_PROTECT_0,
RT1011_STP_EN_MASK | RT1011_STP_RS_CLB_EN_MASK,
RT1011_STP_EN | RT1011_STP_RS_CLB_EN);
snd_soc_component_update_bits(component, RT1011_POWER_9,
RT1011_POW_MNL_SDB_MASK, RT1011_POW_MNL_SDB);
msleep(50 );
snd_soc_component_update_bits(component,
RT1011_CLASSD_INTERNAL_SET_1,
RT1011_DRIVER_READY_SPK, RT1011_DRIVER_READY_SPK);
break ;
case SND_SOC_DAPM_PRE_PMD:
snd_soc_component_update_bits(component, RT1011_POWER_9,
RT1011_POW_MNL_SDB_MASK, 0 );
snd_soc_component_update_bits(component,
RT1011_SPK_TEMP_PROTECT_0,
RT1011_STP_EN_MASK | RT1011_STP_RS_CLB_EN_MASK, 0 );
msleep(200 );
snd_soc_component_update_bits(component,
RT1011_CLASSD_INTERNAL_SET_1,
RT1011_DRIVER_READY_SPK, 0 );
break ;
default :
return 0 ;
}
return 0 ;
}
static const struct snd_soc_dapm_widget rt1011_dapm_widgets[] = {
SND_SOC_DAPM_SUPPLY("LDO2" , RT1011_POWER_1,
RT1011_POW_LDO2_BIT, 0 , NULL, 0 ),
SND_SOC_DAPM_SUPPLY("ISENSE SPK" , RT1011_POWER_1,
RT1011_POW_ISENSE_SPK_BIT, 0 , NULL, 0 ),
SND_SOC_DAPM_SUPPLY("VSENSE SPK" , RT1011_POWER_1,
RT1011_POW_VSENSE_SPK_BIT, 0 , NULL, 0 ),
SND_SOC_DAPM_SUPPLY("PLL" , RT1011_POWER_2,
RT1011_PLLEN_BIT, 0 , NULL, 0 ),
SND_SOC_DAPM_SUPPLY("BG" , RT1011_POWER_2,
RT1011_POW_BG_BIT, 0 , NULL, 0 ),
SND_SOC_DAPM_SUPPLY("BG MBIAS" , RT1011_POWER_2,
RT1011_POW_BG_MBIAS_LV_BIT, 0 , NULL, 0 ),
SND_SOC_DAPM_SUPPLY("DET VBAT" , RT1011_POWER_3,
RT1011_POW_DET_VBAT_BIT, 0 , NULL, 0 ),
SND_SOC_DAPM_SUPPLY("MBIAS" , RT1011_POWER_3,
RT1011_POW_MBIAS_LV_BIT, 0 , NULL, 0 ),
SND_SOC_DAPM_SUPPLY("ADC I" , RT1011_POWER_3,
RT1011_POW_ADC_I_BIT, 0 , NULL, 0 ),
SND_SOC_DAPM_SUPPLY("ADC V" , RT1011_POWER_3,
RT1011_POW_ADC_V_BIT, 0 , NULL, 0 ),
SND_SOC_DAPM_SUPPLY("ADC T" , RT1011_POWER_3,
RT1011_POW_ADC_T_BIT, 0 , NULL, 0 ),
SND_SOC_DAPM_SUPPLY("DITHER ADC T" , RT1011_POWER_3,
RT1011_POWD_ADC_T_BIT, 0 , NULL, 0 ),
SND_SOC_DAPM_SUPPLY("MIX I" , RT1011_POWER_3,
RT1011_POW_MIX_I_BIT, 0 , NULL, 0 ),
SND_SOC_DAPM_SUPPLY("MIX V" , RT1011_POWER_3,
RT1011_POW_MIX_V_BIT, 0 , NULL, 0 ),
SND_SOC_DAPM_SUPPLY("SUM I" , RT1011_POWER_3,
RT1011_POW_SUM_I_BIT, 0 , NULL, 0 ),
SND_SOC_DAPM_SUPPLY("SUM V" , RT1011_POWER_3,
RT1011_POW_SUM_V_BIT, 0 , NULL, 0 ),
SND_SOC_DAPM_SUPPLY("MIX T" , RT1011_POWER_3,
RT1011_POW_MIX_T_BIT, 0 , NULL, 0 ),
SND_SOC_DAPM_SUPPLY("VREF" , RT1011_POWER_3,
RT1011_POW_VREF_LV_BIT, 0 , NULL, 0 ),
SND_SOC_DAPM_SUPPLY("BOOST SWR" , RT1011_POWER_4,
RT1011_POW_EN_SWR_BIT, 0 , NULL, 0 ),
SND_SOC_DAPM_SUPPLY("BGOK SWR" , RT1011_POWER_4,
RT1011_POW_EN_PASS_BGOK_SWR_BIT, 0 , NULL, 0 ),
SND_SOC_DAPM_SUPPLY("VPOK SWR" , RT1011_POWER_4,
RT1011_POW_EN_PASS_VPOK_SWR_BIT, 0 , NULL, 0 ),
SND_SOC_DAPM_SUPPLY("TEMP REG" , RT1011_A_TEMP_SEN,
RT1011_POW_TEMP_REG_BIT, 0 , NULL, 0 ),
/* Audio Interface */
SND_SOC_DAPM_AIF_IN("AIF1RX" , "AIF1 Playback" , 0 , SND_SOC_NOPM, 0 , 0 ),
/* Digital Interface */
SND_SOC_DAPM_SUPPLY("DAC Power" , RT1011_POWER_1,
RT1011_POW_DAC_BIT, 0 , NULL, 0 ),
SND_SOC_DAPM_SUPPLY("CLK12M" , RT1011_POWER_1,
RT1011_POW_CLK12M_BIT, 0 , NULL, 0 ),
SND_SOC_DAPM_DAC_E("DAC" , NULL, RT1011_DAC_SET_3,
RT1011_DA_MUTE_EN_SFT, 1 , rt1011_dac_event,
SND_SOC_DAPM_PRE_PMD | SND_SOC_DAPM_POST_PMU),
/* Output Lines */
SND_SOC_DAPM_OUTPUT("SPO" ),
};
static const struct snd_soc_dapm_route rt1011_dapm_routes[] = {
{ "DAC" , NULL, "AIF1RX" },
{ "DAC" , NULL, "DAC Power" },
{ "DAC" , NULL, "LDO2" },
{ "DAC" , NULL, "ISENSE SPK" },
{ "DAC" , NULL, "VSENSE SPK" },
{ "DAC" , NULL, "CLK12M" },
{ "DAC" , NULL, "PLL" , rt1011_is_sys_clk_from_pll },
{ "DAC" , NULL, "BG" },
{ "DAC" , NULL, "BG MBIAS" },
{ "DAC" , NULL, "BOOST SWR" },
{ "DAC" , NULL, "BGOK SWR" },
{ "DAC" , NULL, "VPOK SWR" },
{ "DAC" , NULL, "DET VBAT" },
{ "DAC" , NULL, "MBIAS" },
{ "DAC" , NULL, "VREF" },
{ "DAC" , NULL, "ADC I" },
{ "DAC" , NULL, "ADC V" },
{ "DAC" , NULL, "ADC T" },
{ "DAC" , NULL, "DITHER ADC T" },
{ "DAC" , NULL, "MIX I" },
{ "DAC" , NULL, "MIX V" },
{ "DAC" , NULL, "SUM I" },
{ "DAC" , NULL, "SUM V" },
{ "DAC" , NULL, "MIX T" },
{ "DAC" , NULL, "TEMP REG" },
{ "SPO" , NULL, "DAC" },
};
static int rt1011_get_clk_info(int sclk, int rate)
{
int i;
static const int pd[] = {1 , 2 , 3 , 4 , 6 , 8 , 12 , 16 };
if (sclk <= 0 || rate <= 0 )
return -EINVAL;
rate = rate << 8 ;
for (i = 0 ; i < ARRAY_SIZE(pd); i++)
if (sclk == rate * pd[i])
return i;
return -EINVAL;
}
static int rt1011_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 rt1011_priv *rt1011 = snd_soc_component_get_drvdata(component);
unsigned int val_len = 0 , ch_len = 0 , val_clk, mask_clk;
int pre_div, bclk_ms, frame_size;
rt1011->lrck = params_rate(params);
pre_div = rt1011_get_clk_info(rt1011->sysclk, rt1011->lrck);
if (pre_div < 0 ) {
dev_warn(component->dev, "Force using PLL " );
snd_soc_dai_set_pll(dai, 0 , RT1011_PLL1_S_BCLK,
rt1011->lrck * 64 , rt1011->lrck * 256 );
snd_soc_dai_set_sysclk(dai, RT1011_FS_SYS_PRE_S_PLL1,
rt1011->lrck * 256 , SND_SOC_CLOCK_IN);
pre_div = 0 ;
}
frame_size = snd_soc_params_to_frame_size(params);
if (frame_size < 0 ) {
dev_err(component->dev, "Unsupported frame size: %d\n" ,
frame_size);
return -EINVAL;
}
bclk_ms = frame_size > 32 ;
rt1011->bclk = rt1011->lrck * (32 << bclk_ms);
dev_dbg(component->dev, "bclk_ms is %d and pre_div is %d for iis %d\n" ,
bclk_ms, pre_div, dai->id);
dev_dbg(component->dev, "lrck is %dHz and pre_div is %d for iis %d\n" ,
rt1011->lrck, pre_div, dai->id);
switch (params_width(params)) {
case 16 :
val_len |= RT1011_I2S_TX_DL_16B;
val_len |= RT1011_I2S_RX_DL_16B;
ch_len |= RT1011_I2S_CH_TX_LEN_16B;
ch_len |= RT1011_I2S_CH_RX_LEN_16B;
break ;
case 20 :
val_len |= RT1011_I2S_TX_DL_20B;
val_len |= RT1011_I2S_RX_DL_20B;
ch_len |= RT1011_I2S_CH_TX_LEN_20B;
ch_len |= RT1011_I2S_CH_RX_LEN_20B;
break ;
case 24 :
val_len |= RT1011_I2S_TX_DL_24B;
val_len |= RT1011_I2S_RX_DL_24B;
ch_len |= RT1011_I2S_CH_TX_LEN_24B;
ch_len |= RT1011_I2S_CH_RX_LEN_24B;
break ;
case 32 :
val_len |= RT1011_I2S_TX_DL_32B;
val_len |= RT1011_I2S_RX_DL_32B;
ch_len |= RT1011_I2S_CH_TX_LEN_32B;
ch_len |= RT1011_I2S_CH_RX_LEN_32B;
break ;
case 8 :
val_len |= RT1011_I2S_TX_DL_8B;
val_len |= RT1011_I2S_RX_DL_8B;
ch_len |= RT1011_I2S_CH_TX_LEN_8B;
ch_len |= RT1011_I2S_CH_RX_LEN_8B;
break ;
default :
return -EINVAL;
}
switch (dai->id) {
case RT1011_AIF1:
mask_clk = RT1011_FS_SYS_DIV_MASK;
val_clk = pre_div << RT1011_FS_SYS_DIV_SFT;
snd_soc_component_update_bits(component, RT1011_TDM_TOTAL_SET,
RT1011_I2S_TX_DL_MASK | RT1011_I2S_RX_DL_MASK,
val_len);
snd_soc_component_update_bits(component, RT1011_TDM1_SET_1,
RT1011_I2S_CH_TX_LEN_MASK |
RT1011_I2S_CH_RX_LEN_MASK,
ch_len);
break ;
default :
dev_err(component->dev, "Invalid dai->id: %d\n" , dai->id);
return -EINVAL;
}
snd_soc_component_update_bits(component,
RT1011_CLK_2, mask_clk, val_clk);
return 0 ;
}
static int rt1011_set_dai_fmt(struct snd_soc_dai *dai, unsigned int fmt)
{
struct snd_soc_component *component = dai->component;
struct snd_soc_dapm_context *dapm =
snd_soc_component_get_dapm(component);
unsigned int reg_val = 0 , reg_bclk_inv = 0 ;
int ret = 0 ;
snd_soc_dapm_mutex_lock(dapm);
switch (fmt & SND_SOC_DAIFMT_MASTER_MASK) {
case SND_SOC_DAIFMT_CBC_CFC:
reg_val |= RT1011_I2S_TDM_MS_S;
break ;
default :
ret = -EINVAL;
goto _set_fmt_err_;
}
switch (fmt & SND_SOC_DAIFMT_INV_MASK) {
case SND_SOC_DAIFMT_NB_NF:
break ;
case SND_SOC_DAIFMT_IB_NF:
reg_bclk_inv |= RT1011_TDM_INV_BCLK;
break ;
default :
ret = -EINVAL;
goto _set_fmt_err_;
}
switch (fmt & SND_SOC_DAIFMT_FORMAT_MASK) {
case SND_SOC_DAIFMT_I2S:
break ;
case SND_SOC_DAIFMT_LEFT_J:
reg_val |= RT1011_I2S_TDM_DF_LEFT;
break ;
case SND_SOC_DAIFMT_DSP_A:
reg_val |= RT1011_I2S_TDM_DF_PCM_A;
break ;
case SND_SOC_DAIFMT_DSP_B:
reg_val |= RT1011_I2S_TDM_DF_PCM_B;
break ;
default :
ret = -EINVAL;
goto _set_fmt_err_;
}
switch (dai->id) {
case RT1011_AIF1:
snd_soc_component_update_bits(component, RT1011_TDM_TOTAL_SET,
RT1011_I2S_TDM_MS_MASK | RT1011_I2S_TDM_DF_MASK,
reg_val);
snd_soc_component_update_bits(component, RT1011_TDM1_SET_1,
RT1011_TDM_INV_BCLK_MASK, reg_bclk_inv);
snd_soc_component_update_bits(component, RT1011_TDM2_SET_1,
RT1011_TDM_INV_BCLK_MASK, reg_bclk_inv);
break ;
default :
dev_err(component->dev, "Invalid dai->id: %d\n" , dai->id);
ret = -EINVAL;
}
_set_fmt_err_:
snd_soc_dapm_mutex_unlock(dapm);
return ret;
}
static int rt1011_set_component_sysclk(struct snd_soc_component *component,
int clk_id, int source, unsigned int freq, int dir)
{
struct rt1011_priv *rt1011 = snd_soc_component_get_drvdata(component);
unsigned int reg_val = 0 ;
if (freq == rt1011->sysclk && clk_id == rt1011->sysclk_src)
return 0 ;
/* disable MCLK detect in default */
snd_soc_component_update_bits(component, RT1011_CLK_DET,
RT1011_EN_MCLK_DET_MASK, 0 );
switch (clk_id) {
case RT1011_FS_SYS_PRE_S_MCLK:
reg_val |= RT1011_FS_SYS_PRE_MCLK;
snd_soc_component_update_bits(component, RT1011_CLK_DET,
RT1011_EN_MCLK_DET_MASK, RT1011_EN_MCLK_DET);
break ;
case RT1011_FS_SYS_PRE_S_BCLK:
reg_val |= RT1011_FS_SYS_PRE_BCLK;
break ;
case RT1011_FS_SYS_PRE_S_PLL1:
reg_val |= RT1011_FS_SYS_PRE_PLL1;
break ;
case RT1011_FS_SYS_PRE_S_RCCLK:
reg_val |= RT1011_FS_SYS_PRE_RCCLK;
break ;
default :
dev_err(component->dev, "Invalid clock id (%d)\n" , clk_id);
return -EINVAL;
}
snd_soc_component_update_bits(component, RT1011_CLK_2,
RT1011_FS_SYS_PRE_MASK, reg_val);
rt1011->sysclk = freq;
rt1011->sysclk_src = clk_id;
dev_dbg(component->dev, "Sysclk is %dHz and clock id is %d\n" ,
freq, clk_id);
return 0 ;
}
static int rt1011_set_component_pll(struct snd_soc_component *component,
int pll_id, int source, unsigned int freq_in,
unsigned int freq_out)
{
struct rt1011_priv *rt1011 = snd_soc_component_get_drvdata(component);
struct rl6231_pll_code pll_code;
int ret;
if (source == rt1011->pll_src && freq_in == rt1011->pll_in &&
freq_out == rt1011->pll_out)
return 0 ;
if (!freq_in || !freq_out) {
dev_dbg(component->dev, "PLL disabled\n" );
rt1011->pll_in = 0 ;
rt1011->pll_out = 0 ;
snd_soc_component_update_bits(component, RT1011_CLK_2,
RT1011_FS_SYS_PRE_MASK, RT1011_FS_SYS_PRE_BCLK);
return 0 ;
}
switch (source) {
case RT1011_PLL2_S_MCLK:
snd_soc_component_update_bits(component, RT1011_CLK_2,
RT1011_PLL2_SRC_MASK, RT1011_PLL2_SRC_MCLK);
snd_soc_component_update_bits(component, RT1011_CLK_2,
RT1011_PLL1_SRC_MASK, RT1011_PLL1_SRC_PLL2);
snd_soc_component_update_bits(component, RT1011_CLK_DET,
RT1011_EN_MCLK_DET_MASK, RT1011_EN_MCLK_DET);
break ;
case RT1011_PLL1_S_BCLK:
snd_soc_component_update_bits(component, RT1011_CLK_2,
RT1011_PLL1_SRC_MASK, RT1011_PLL1_SRC_BCLK);
break ;
case RT1011_PLL2_S_RCCLK:
snd_soc_component_update_bits(component, RT1011_CLK_2,
RT1011_PLL2_SRC_MASK, RT1011_PLL2_SRC_RCCLK);
snd_soc_component_update_bits(component, RT1011_CLK_2,
RT1011_PLL1_SRC_MASK, RT1011_PLL1_SRC_PLL2);
break ;
default :
dev_err(component->dev, "Unknown PLL Source %d\n" , source);
return -EINVAL;
}
ret = rl6231_pll_calc(freq_in, freq_out, &pll_code);
if (ret < 0 ) {
dev_err(component->dev, "Unsupported input clock %d\n" ,
freq_in);
return ret;
}
dev_dbg(component->dev, "bypass=%d m=%d n=%d k=%d\n" ,
pll_code.m_bp, (pll_code.m_bp ? 0 : pll_code.m_code),
pll_code.n_code, pll_code.k_code);
snd_soc_component_write(component, RT1011_PLL_1,
((pll_code.m_bp ? 0 : pll_code.m_code) << RT1011_PLL1_QM_SFT) |
(pll_code.m_bp << RT1011_PLL1_BPM_SFT) |
pll_code.n_code);
snd_soc_component_write(component, RT1011_PLL_2,
pll_code.k_code);
rt1011->pll_in = freq_in;
rt1011->pll_out = freq_out;
rt1011->pll_src = source;
return 0 ;
}
static int rt1011_set_tdm_slot(struct snd_soc_dai *dai,
unsigned int tx_mask, unsigned int rx_mask, int slots, int slot_width)
{
struct snd_soc_component *component = dai->component;
struct snd_soc_dapm_context *dapm =
snd_soc_component_get_dapm(component);
unsigned int val = 0 , tdm_en = 0 , rx_slotnum, tx_slotnum;
int ret = 0 , first_bit, last_bit;
snd_soc_dapm_mutex_lock(dapm);
if (rx_mask || tx_mask)
tdm_en = RT1011_TDM_I2S_DOCK_EN_1;
switch (slots) {
case 4 :
val |= RT1011_I2S_TX_4CH;
val |= RT1011_I2S_RX_4CH;
break ;
case 6 :
val |= RT1011_I2S_TX_6CH;
val |= RT1011_I2S_RX_6CH;
break ;
case 8 :
val |= RT1011_I2S_TX_8CH;
val |= RT1011_I2S_RX_8CH;
break ;
case 2 :
break ;
default :
ret = -EINVAL;
goto _set_tdm_err_;
}
switch (slot_width) {
case 20 :
val |= RT1011_I2S_CH_TX_LEN_20B;
val |= RT1011_I2S_CH_RX_LEN_20B;
break ;
case 24 :
val |= RT1011_I2S_CH_TX_LEN_24B;
val |= RT1011_I2S_CH_RX_LEN_24B;
break ;
case 32 :
val |= RT1011_I2S_CH_TX_LEN_32B;
val |= RT1011_I2S_CH_RX_LEN_32B;
break ;
case 16 :
break ;
default :
ret = -EINVAL;
goto _set_tdm_err_;
}
/* Rx slot configuration */
rx_slotnum = hweight_long(rx_mask);
if (rx_slotnum > 1 || !rx_slotnum) {
ret = -EINVAL;
dev_err(component->dev, "too many rx slots or zero slot\n" );
goto _set_tdm_err_;
}
first_bit = __ffs(rx_mask);
switch (first_bit) {
case 0 :
case 2 :
case 4 :
case 6 :
snd_soc_component_update_bits(component,
RT1011_CROSS_BQ_SET_1, RT1011_MONO_LR_SEL_MASK,
RT1011_MONO_L_CHANNEL);
snd_soc_component_update_bits(component,
RT1011_TDM1_SET_4,
RT1011_TDM_I2S_TX_L_DAC1_1_MASK |
RT1011_TDM_I2S_TX_R_DAC1_1_MASK,
(first_bit << RT1011_TDM_I2S_TX_L_DAC1_1_SFT) |
((first_bit+1 ) << RT1011_TDM_I2S_TX_R_DAC1_1_SFT));
break ;
case 1 :
case 3 :
case 5 :
case 7 :
snd_soc_component_update_bits(component,
RT1011_CROSS_BQ_SET_1, RT1011_MONO_LR_SEL_MASK,
RT1011_MONO_R_CHANNEL);
snd_soc_component_update_bits(component,
RT1011_TDM1_SET_4,
RT1011_TDM_I2S_TX_L_DAC1_1_MASK |
RT1011_TDM_I2S_TX_R_DAC1_1_MASK,
((first_bit-1 ) << RT1011_TDM_I2S_TX_L_DAC1_1_SFT) |
(first_bit << RT1011_TDM_I2S_TX_R_DAC1_1_SFT));
break ;
default :
ret = -EINVAL;
goto _set_tdm_err_;
}
/* Tx slot configuration */
tx_slotnum = hweight_long(tx_mask);
if (tx_slotnum > 2 || !tx_slotnum) {
ret = -EINVAL;
dev_err(component->dev, "too many tx slots or zero slot\n" );
goto _set_tdm_err_;
}
first_bit = __ffs(tx_mask);
last_bit = __fls(tx_mask);
if (last_bit - first_bit > 1 ) {
ret = -EINVAL;
dev_err(component->dev, "tx slot location error\n" );
goto _set_tdm_err_;
}
if (tx_slotnum == 1 ) {
snd_soc_component_update_bits(component, RT1011_TDM1_SET_2,
RT1011_TDM_I2S_DOCK_ADCDAT_LEN_1_MASK |
RT1011_TDM_ADCDAT1_DATA_LOCATION, first_bit);
switch (first_bit) {
case 1 :
snd_soc_component_update_bits(component,
RT1011_TDM1_SET_3,
RT1011_TDM_I2S_RX_ADC1_1_MASK,
RT1011_TDM_I2S_RX_ADC1_1_LL);
break ;
case 3 :
snd_soc_component_update_bits(component,
RT1011_TDM1_SET_3,
RT1011_TDM_I2S_RX_ADC2_1_MASK,
RT1011_TDM_I2S_RX_ADC2_1_LL);
break ;
case 5 :
snd_soc_component_update_bits(component,
RT1011_TDM1_SET_3,
RT1011_TDM_I2S_RX_ADC3_1_MASK,
RT1011_TDM_I2S_RX_ADC3_1_LL);
break ;
case 7 :
snd_soc_component_update_bits(component,
RT1011_TDM1_SET_3,
RT1011_TDM_I2S_RX_ADC4_1_MASK,
RT1011_TDM_I2S_RX_ADC4_1_LL);
break ;
case 0 :
snd_soc_component_update_bits(component,
RT1011_TDM1_SET_3,
RT1011_TDM_I2S_RX_ADC1_1_MASK, 0 );
break ;
case 2 :
snd_soc_component_update_bits(component,
RT1011_TDM1_SET_3,
RT1011_TDM_I2S_RX_ADC2_1_MASK, 0 );
break ;
case 4 :
snd_soc_component_update_bits(component,
RT1011_TDM1_SET_3,
RT1011_TDM_I2S_RX_ADC3_1_MASK, 0 );
break ;
case 6 :
snd_soc_component_update_bits(component,
RT1011_TDM1_SET_3,
RT1011_TDM_I2S_RX_ADC4_1_MASK, 0 );
break ;
default :
ret = -EINVAL;
dev_dbg(component->dev,
"tx slot location error\n" );
goto _set_tdm_err_;
}
} else if (tx_slotnum == 2 ) {
switch (first_bit) {
case 0 :
case 2 :
case 4 :
case 6 :
snd_soc_component_update_bits(component,
RT1011_TDM1_SET_2,
RT1011_TDM_I2S_DOCK_ADCDAT_LEN_1_MASK |
RT1011_TDM_ADCDAT1_DATA_LOCATION,
RT1011_TDM_I2S_DOCK_ADCDAT_2CH | first_bit);
break ;
default :
ret = -EINVAL;
dev_dbg(component->dev,
"tx slot location should be paired and start from slot0/2/4/6\n" );
goto _set_tdm_err_;
}
}
snd_soc_component_update_bits(component, RT1011_TDM1_SET_1,
RT1011_I2S_CH_TX_MASK | RT1011_I2S_CH_RX_MASK |
RT1011_I2S_CH_TX_LEN_MASK | RT1011_I2S_CH_RX_LEN_MASK, val);
snd_soc_component_update_bits(component, RT1011_TDM2_SET_1,
RT1011_I2S_CH_TX_MASK | RT1011_I2S_CH_RX_MASK |
RT1011_I2S_CH_TX_LEN_MASK | RT1011_I2S_CH_RX_LEN_MASK, val);
snd_soc_component_update_bits(component, RT1011_TDM1_SET_2,
RT1011_TDM_I2S_DOCK_EN_1_MASK, tdm_en);
snd_soc_component_update_bits(component, RT1011_TDM2_SET_2,
RT1011_TDM_I2S_DOCK_EN_2_MASK, tdm_en);
snd_soc_component_update_bits(component, RT1011_TDM_TOTAL_SET,
RT1011_ADCDAT1_PIN_CONFIG | RT1011_ADCDAT2_PIN_CONFIG,
RT1011_ADCDAT1_OUTPUT | RT1011_ADCDAT2_OUTPUT);
_set_tdm_err_:
snd_soc_dapm_mutex_unlock(dapm);
return ret;
}
static int rt1011_probe(struct snd_soc_component *component)
{
struct rt1011_priv *rt1011 = snd_soc_component_get_drvdata(component);
int i;
rt1011->component = component;
schedule_work(&rt1011->cali_work);
rt1011->i2s_ref = 0 ;
rt1011->bq_drc_params = devm_kcalloc(component->dev,
RT1011_ADVMODE_NUM, sizeof (struct rt1011_bq_drc_params *),
GFP_KERNEL);
if (!rt1011->bq_drc_params)
return -ENOMEM;
for (i = 0 ; i < RT1011_ADVMODE_NUM; i++) {
rt1011->bq_drc_params[i] = devm_kcalloc(component->dev,
RT1011_BQ_DRC_NUM, sizeof (struct rt1011_bq_drc_params),
GFP_KERNEL);
if (!rt1011->bq_drc_params[i])
return -ENOMEM;
}
return 0 ;
}
static void rt1011_remove(struct snd_soc_component *component)
{
struct rt1011_priv *rt1011 = snd_soc_component_get_drvdata(component);
cancel_work_sync(&rt1011->cali_work);
rt1011_reset(rt1011->regmap);
}
#ifdef CONFIG_PM
static int rt1011_suspend(struct snd_soc_component *component)
{
struct rt1011_priv *rt1011 = snd_soc_component_get_drvdata(component);
regcache_cache_only(rt1011->regmap, true );
regcache_mark_dirty(rt1011->regmap);
return 0 ;
}
static int rt1011_resume(struct snd_soc_component *component)
{
struct rt1011_priv *rt1011 = snd_soc_component_get_drvdata(component);
regcache_cache_only(rt1011->regmap, false );
regcache_sync(rt1011->regmap);
return 0 ;
}
#else
#define rt1011_suspend NULL
#define rt1011_resume NULL
#endif
static int rt1011_set_bias_level(struct snd_soc_component *component,
enum snd_soc_bias_level level)
{
switch (level) {
case SND_SOC_BIAS_OFF:
snd_soc_component_write(component,
RT1011_SYSTEM_RESET_1, 0 x0000);
snd_soc_component_write(component,
RT1011_SYSTEM_RESET_2, 0 x0000);
snd_soc_component_write(component,
RT1011_SYSTEM_RESET_3, 0 x0001);
snd_soc_component_write(component,
RT1011_SYSTEM_RESET_1, 0 x003f);
snd_soc_component_write(component,
RT1011_SYSTEM_RESET_2, 0 x7fd7);
snd_soc_component_write(component,
RT1011_SYSTEM_RESET_3, 0 x770f);
break ;
default :
break ;
}
return 0 ;
}
#define RT1011_STEREO_RATES SNDRV_PCM_RATE_8000_192000
#define RT1011_FORMATS (SNDRV_PCM_FMTBIT_S8 | \
SNDRV_PCM_FMTBIT_S20_3LE | SNDRV_PCM_FMTBIT_S16_LE | \
SNDRV_PCM_FMTBIT_S24_LE | SNDRV_PCM_FMTBIT_S32_LE)
static const struct snd_soc_dai_ops rt1011_aif_dai_ops = {
.hw_params = rt1011_hw_params,
.set_fmt = rt1011_set_dai_fmt,
.set_tdm_slot = rt1011_set_tdm_slot,
};
static struct snd_soc_dai_driver rt1011_dai[] = {
{
.name = "rt1011-aif" ,
.playback = {
.stream_name = "AIF1 Playback" ,
.channels_min = 1 ,
.channels_max = 2 ,
.rates = RT1011_STEREO_RATES,
.formats = RT1011_FORMATS,
},
.ops = &rt1011_aif_dai_ops,
},
};
static const struct snd_soc_component_driver soc_component_dev_rt1011 = {
.probe = rt1011_probe,
.remove = rt1011_remove,
.suspend = rt1011_suspend,
.resume = rt1011_resume,
.set_bias_level = rt1011_set_bias_level,
.controls = rt1011_snd_controls,
.num_controls = ARRAY_SIZE(rt1011_snd_controls),
.dapm_widgets = rt1011_dapm_widgets,
.num_dapm_widgets = ARRAY_SIZE(rt1011_dapm_widgets),
.dapm_routes = rt1011_dapm_routes,
.num_dapm_routes = ARRAY_SIZE(rt1011_dapm_routes),
.set_sysclk = rt1011_set_component_sysclk,
.set_pll = rt1011_set_component_pll,
.use_pmdown_time = 1 ,
.endianness = 1 ,
};
static const struct regmap_config rt1011_regmap = {
.reg_bits = 16 ,
.val_bits = 16 ,
.max_register = RT1011_MAX_REG + 1 ,
.volatile_reg = rt1011_volatile_register,
.readable_reg = rt1011_readable_register,
.cache_type = REGCACHE_MAPLE,
.reg_defaults = rt1011_reg,
.num_reg_defaults = ARRAY_SIZE(rt1011_reg),
.use_single_read = true ,
.use_single_write = true ,
};
#if defined (CONFIG_OF)
static const struct of_device_id rt1011_of_match[] = {
{ .compatible = "realtek,rt1011" , },
{ }
};
MODULE_DEVICE_TABLE(of, rt1011_of_match);
#endif
#ifdef CONFIG_ACPI
static const struct acpi_device_id rt1011_acpi_match[] = {
{ "10EC1011" },
{ }
};
MODULE_DEVICE_TABLE(acpi, rt1011_acpi_match);
#endif
static const struct i2c_device_id rt1011_i2c_id[] = {
{ "rt1011" },
{ }
};
MODULE_DEVICE_TABLE(i2c, rt1011_i2c_id);
static int rt1011_calibrate(struct rt1011_priv *rt1011, unsigned char cali_flag)
{
unsigned int value, count = 0 , r0[3 ];
unsigned int chk_cnt = 50 ; /* DONT change this */
unsigned int dc_offset;
unsigned int r0_integer, r0_factor, format;
struct device *dev = regmap_get_device(rt1011->regmap);
struct snd_soc_dapm_context *dapm =
snd_soc_component_get_dapm(rt1011->component);
int ret = 0 ;
snd_soc_dapm_mutex_lock(dapm);
regcache_cache_bypass(rt1011->regmap, true );
regmap_write(rt1011->regmap, RT1011_RESET, 0 x0000);
regmap_write(rt1011->regmap, RT1011_SYSTEM_RESET_3, 0 x740f);
regmap_write(rt1011->regmap, RT1011_SYSTEM_RESET_3, 0 x770f);
/* RC clock */
regmap_write(rt1011->regmap, RT1011_CLK_2, 0 x9400);
regmap_write(rt1011->regmap, RT1011_PLL_1, 0 x0800);
regmap_write(rt1011->regmap, RT1011_PLL_2, 0 x0020);
regmap_write(rt1011->regmap, RT1011_CLK_DET, 0 x0800);
/* ADC/DAC setting */
regmap_write(rt1011->regmap, RT1011_ADC_SET_5, 0 x0a20);
regmap_write(rt1011->regmap, RT1011_DAC_SET_2, 0 xe232);
regmap_write(rt1011->regmap, RT1011_ADC_SET_4, 0 xc000);
/* DC detection */
regmap_write(rt1011->regmap, RT1011_SPK_PRO_DC_DET_1, 0 xb00c);
regmap_write(rt1011->regmap, RT1011_SPK_PRO_DC_DET_2, 0 xcccc);
/* Power */
regmap_write(rt1011->regmap, RT1011_POWER_1, 0 xe0e0);
regmap_write(rt1011->regmap, RT1011_POWER_3, 0 x5003);
regmap_write(rt1011->regmap, RT1011_POWER_9, 0 xa860);
regmap_write(rt1011->regmap, RT1011_DAC_SET_2, 0 xa032);
/* POW_PLL / POW_BG / POW_BG_MBIAS_LV / POW_V/I */
regmap_write(rt1011->regmap, RT1011_POWER_2, 0 x0007);
regmap_write(rt1011->regmap, RT1011_POWER_3, 0 x5ff7);
regmap_write(rt1011->regmap, RT1011_A_TEMP_SEN, 0 x7f44);
regmap_write(rt1011->regmap, RT1011_A_TIMING_1, 0 x4054);
regmap_write(rt1011->regmap, RT1011_BAT_GAIN_1, 0 x309c);
/* DC offset from EFUSE */
regmap_write(rt1011->regmap, RT1011_DC_CALIB_CLASSD_3, 0 xcb00);
regmap_write(rt1011->regmap, RT1011_BOOST_CON_1, 0 xe080);
regmap_write(rt1011->regmap, RT1011_POWER_4, 0 x16f2);
regmap_write(rt1011->regmap, RT1011_POWER_6, 0 x36ad);
/* mixer */
regmap_write(rt1011->regmap, RT1011_MIXER_1, 0 x3f1d);
/* EFUSE read */
regmap_write(rt1011->regmap, RT1011_EFUSE_CONTROL_1, 0 x0d0a);
msleep(30 );
regmap_read(rt1011->regmap, RT1011_EFUSE_ADC_OFFSET_18_16, &value);
dc_offset = value << 16 ;
regmap_read(rt1011->regmap, RT1011_EFUSE_ADC_OFFSET_15_0, &value);
dc_offset |= (value & 0 xffff);
dev_info(dev, "ADC offset=0x%x\n" , dc_offset);
regmap_read(rt1011->regmap, RT1011_EFUSE_DAC_OFFSET_G0_20_16, &value);
dc_offset = value << 16 ;
regmap_read(rt1011->regmap, RT1011_EFUSE_DAC_OFFSET_G0_15_0, &value);
dc_offset |= (value & 0 xffff);
dev_info(dev, "Gain0 offset=0x%x\n" , dc_offset);
regmap_read(rt1011->regmap, RT1011_EFUSE_DAC_OFFSET_G1_20_16, &value);
dc_offset = value << 16 ;
regmap_read(rt1011->regmap, RT1011_EFUSE_DAC_OFFSET_G1_15_0, &value);
dc_offset |= (value & 0 xffff);
dev_info(dev, "Gain1 offset=0x%x\n" , dc_offset);
if (cali_flag) {
regmap_write(rt1011->regmap, RT1011_ADC_SET_1, 0 x2925);
/* Class D on */
regmap_write(rt1011->regmap, RT1011_CLASS_D_POS, 0 x010e);
regmap_write(rt1011->regmap,
RT1011_CLASSD_INTERNAL_SET_1, 0 x1701);
/* STP enable */
regmap_write(rt1011->regmap, RT1011_SPK_TEMP_PROTECT_0, 0 x8000);
regmap_write(rt1011->regmap, RT1011_SPK_TEMP_PROTECT_7, 0 xf000);
regmap_write(rt1011->regmap, RT1011_SPK_TEMP_PROTECT_4, 0 x4040);
regmap_write(rt1011->regmap, RT1011_SPK_TEMP_PROTECT_0, 0 xc000);
regmap_write(rt1011->regmap, RT1011_SPK_TEMP_PROTECT_6, 0 x07c2);
r0[0 ] = r0[1 ] = r0[2 ] = count = 0 ;
while (count < chk_cnt) {
msleep(100 );
regmap_read(rt1011->regmap,
RT1011_INIT_RECIPROCAL_SYN_24_16, &value);
r0[count%3 ] = value << 16 ;
regmap_read(rt1011->regmap,
RT1011_INIT_RECIPROCAL_SYN_15_0, &value);
r0[count%3 ] |= value;
if (r0[count%3 ] == 0 )
continue ;
count++;
if (r0[0 ] == r0[1 ] && r0[1 ] == r0[2 ])
break ;
}
if (count > chk_cnt) {
dev_err(dev, "Calibrate R0 Failure\n" );
ret = -EAGAIN;
} else {
format = 2147483648 U; /* 2^24 * 128 */
r0_integer = format / r0[0 ] / 128 ;
r0_factor = ((format / r0[0 ] * 100 ) / 128 )
- (r0_integer * 100 );
rt1011->r0_reg = r0[0 ];
rt1011->cali_done = 1 ;
dev_info(dev, "r0 resistance about %d.%02d ohm, reg=0x%X\n" ,
r0_integer, r0_factor, r0[0 ]);
}
}
/* depop */
regmap_write(rt1011->regmap, RT1011_SPK_TEMP_PROTECT_0, 0 x0000);
msleep(400 );
regmap_write(rt1011->regmap, RT1011_POWER_9, 0 xa840);
regmap_write(rt1011->regmap, RT1011_SPK_TEMP_PROTECT_6, 0 x0702);
regmap_write(rt1011->regmap, RT1011_MIXER_1, 0 xffdd);
regmap_write(rt1011->regmap, RT1011_CLASSD_INTERNAL_SET_1, 0 x0701);
regmap_write(rt1011->regmap, RT1011_DAC_SET_3, 0 xe004);
regmap_write(rt1011->regmap, RT1011_A_TEMP_SEN, 0 x7f40);
regmap_write(rt1011->regmap, RT1011_POWER_1, 0 x0000);
regmap_write(rt1011->regmap, RT1011_POWER_2, 0 x0000);
regmap_write(rt1011->regmap, RT1011_POWER_3, 0 x0002);
regmap_write(rt1011->regmap, RT1011_POWER_4, 0 x00f2);
regmap_write(rt1011->regmap, RT1011_RESET, 0 x0000);
if (cali_flag) {
if (count <= chk_cnt) {
regmap_write(rt1011->regmap,
RT1011_INIT_RECIPROCAL_REG_24_16,
((r0[0 ]>>16 ) & 0 x1ff));
regmap_write(rt1011->regmap,
RT1011_INIT_RECIPROCAL_REG_15_0,
(r0[0 ] & 0 xffff));
regmap_write(rt1011->regmap,
RT1011_SPK_TEMP_PROTECT_4, 0 x4080);
}
}
regcache_cache_bypass(rt1011->regmap, false );
regcache_mark_dirty(rt1011->regmap);
regcache_sync(rt1011->regmap);
snd_soc_dapm_mutex_unlock(dapm);
return ret;
}
static void rt1011_calibration_work(struct work_struct *work)
{
struct rt1011_priv *rt1011 =
container_of(work, struct rt1011_priv, cali_work);
struct snd_soc_component *component = rt1011->component;
unsigned int r0_integer, r0_factor, format;
if (rt1011->r0_calib)
rt1011_calibrate(rt1011, 0 );
else
rt1011_calibrate(rt1011, 1 );
/*
* This flag should reset after booting.
* The factory test will do calibration again and use this flag to check
* whether the calibration completed
*/
rt1011->cali_done = 0 ;
/* initial */
rt1011_reg_init(component);
/* Apply temperature and calibration data from device property */
if (rt1011->temperature_calib <= 0 xff &&
rt1011->temperature_calib > 0 ) {
snd_soc_component_update_bits(component,
RT1011_STP_INITIAL_RESISTANCE_TEMP, 0 x3ff,
(rt1011->temperature_calib << 2 ));
}
if (rt1011->r0_calib) {
rt1011->r0_reg = rt1011->r0_calib;
format = 2147483648 U; /* 2^24 * 128 */
r0_integer = format / rt1011->r0_reg / 128 ;
r0_factor = ((format / rt1011->r0_reg * 100 ) / 128 )
- (r0_integer * 100 );
dev_info(component->dev, "DP r0 resistance about %d.%02d ohm, reg=0x%X\n" ,
r0_integer, r0_factor, rt1011->r0_reg);
rt1011_r0_load(rt1011);
}
snd_soc_component_write(component, RT1011_ADC_SET_1, 0 x2925);
}
static int rt1011_parse_dp(struct rt1011_priv *rt1011, struct device *dev)
{
device_property_read_u32(dev, "realtek,temperature_calib" ,
&rt1011->temperature_calib);
device_property_read_u32(dev, "realtek,r0_calib" ,
&rt1011->r0_calib);
dev_dbg(dev, "%s: r0_calib: 0x%x, temperature_calib: 0x%x" ,
__func__, rt1011->r0_calib, rt1011->temperature_calib);
return 0 ;
}
static int rt1011_i2c_probe(struct i2c_client *i2c)
{
struct rt1011_priv *rt1011;
int ret;
unsigned int val;
rt1011 = devm_kzalloc(&i2c->dev, sizeof (struct rt1011_priv),
GFP_KERNEL);
if (!rt1011)
return -ENOMEM;
i2c_set_clientdata(i2c, rt1011);
rt1011_parse_dp(rt1011, &i2c->dev);
rt1011->regmap = devm_regmap_init_i2c(i2c, &rt1011_regmap);
if (IS_ERR(rt1011->regmap)) {
ret = PTR_ERR(rt1011->regmap);
dev_err(&i2c->dev, "Failed to allocate register map: %d\n" ,
ret);
return ret;
}
regmap_read(rt1011->regmap, RT1011_DEVICE_ID, &val);
if (val != RT1011_DEVICE_ID_NUM) {
dev_err(&i2c->dev,
"Device with ID register %x is not rt1011\n" , val);
return -ENODEV;
}
INIT_WORK(&rt1011->cali_work, rt1011_calibration_work);
return devm_snd_soc_register_component(&i2c->dev,
&soc_component_dev_rt1011,
rt1011_dai, ARRAY_SIZE(rt1011_dai));
}
static void rt1011_i2c_shutdown(struct i2c_client *client)
{
struct rt1011_priv *rt1011 = i2c_get_clientdata(client);
rt1011_reset(rt1011->regmap);
}
static struct i2c_driver rt1011_i2c_driver = {
.driver = {
.name = "rt1011" ,
.of_match_table = of_match_ptr(rt1011_of_match),
.acpi_match_table = ACPI_PTR(rt1011_acpi_match)
},
.probe = rt1011_i2c_probe,
.shutdown = rt1011_i2c_shutdown,
.id_table = rt1011_i2c_id,
};
module_i2c_driver(rt1011_i2c_driver);
MODULE_DESCRIPTION("ASoC RT1011 amplifier driver" );
MODULE_AUTHOR("Shuming Fan <shumingf@realtek.com>" );
MODULE_LICENSE("GPL" );
Messung V0.5 in Prozent C=94 H=90 G=91
¤ Dauer der Verarbeitung: 0.25 Sekunden
(vorverarbeitet am 2026-06-08)
¤
*© Formatika GbR, Deutschland