18c2ecf20Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0-only 28c2ecf20Sopenharmony_ci/* 38c2ecf20Sopenharmony_ci * max98088.c -- MAX98088 ALSA SoC Audio driver 48c2ecf20Sopenharmony_ci * 58c2ecf20Sopenharmony_ci * Copyright 2010 Maxim Integrated Products 68c2ecf20Sopenharmony_ci */ 78c2ecf20Sopenharmony_ci 88c2ecf20Sopenharmony_ci#include <linux/module.h> 98c2ecf20Sopenharmony_ci#include <linux/moduleparam.h> 108c2ecf20Sopenharmony_ci#include <linux/kernel.h> 118c2ecf20Sopenharmony_ci#include <linux/init.h> 128c2ecf20Sopenharmony_ci#include <linux/delay.h> 138c2ecf20Sopenharmony_ci#include <linux/pm.h> 148c2ecf20Sopenharmony_ci#include <linux/i2c.h> 158c2ecf20Sopenharmony_ci#include <linux/regmap.h> 168c2ecf20Sopenharmony_ci#include <linux/clk.h> 178c2ecf20Sopenharmony_ci#include <sound/core.h> 188c2ecf20Sopenharmony_ci#include <sound/pcm.h> 198c2ecf20Sopenharmony_ci#include <sound/pcm_params.h> 208c2ecf20Sopenharmony_ci#include <sound/soc.h> 218c2ecf20Sopenharmony_ci#include <sound/initval.h> 228c2ecf20Sopenharmony_ci#include <sound/tlv.h> 238c2ecf20Sopenharmony_ci#include <linux/slab.h> 248c2ecf20Sopenharmony_ci#include <asm/div64.h> 258c2ecf20Sopenharmony_ci#include <sound/max98088.h> 268c2ecf20Sopenharmony_ci#include "max98088.h" 278c2ecf20Sopenharmony_ci 288c2ecf20Sopenharmony_cienum max98088_type { 298c2ecf20Sopenharmony_ci MAX98088, 308c2ecf20Sopenharmony_ci MAX98089, 318c2ecf20Sopenharmony_ci}; 328c2ecf20Sopenharmony_ci 338c2ecf20Sopenharmony_cistruct max98088_cdata { 348c2ecf20Sopenharmony_ci unsigned int rate; 358c2ecf20Sopenharmony_ci unsigned int fmt; 368c2ecf20Sopenharmony_ci int eq_sel; 378c2ecf20Sopenharmony_ci}; 388c2ecf20Sopenharmony_ci 398c2ecf20Sopenharmony_cistruct max98088_priv { 408c2ecf20Sopenharmony_ci struct regmap *regmap; 418c2ecf20Sopenharmony_ci enum max98088_type devtype; 428c2ecf20Sopenharmony_ci struct max98088_pdata *pdata; 438c2ecf20Sopenharmony_ci struct clk *mclk; 448c2ecf20Sopenharmony_ci unsigned char mclk_prescaler; 458c2ecf20Sopenharmony_ci unsigned int sysclk; 468c2ecf20Sopenharmony_ci struct max98088_cdata dai[2]; 478c2ecf20Sopenharmony_ci int eq_textcnt; 488c2ecf20Sopenharmony_ci const char **eq_texts; 498c2ecf20Sopenharmony_ci struct soc_enum eq_enum; 508c2ecf20Sopenharmony_ci u8 ina_state; 518c2ecf20Sopenharmony_ci u8 inb_state; 528c2ecf20Sopenharmony_ci unsigned int ex_mode; 538c2ecf20Sopenharmony_ci unsigned int digmic; 548c2ecf20Sopenharmony_ci unsigned int mic1pre; 558c2ecf20Sopenharmony_ci unsigned int mic2pre; 568c2ecf20Sopenharmony_ci unsigned int extmic_mode; 578c2ecf20Sopenharmony_ci}; 588c2ecf20Sopenharmony_ci 598c2ecf20Sopenharmony_cistatic const struct reg_default max98088_reg[] = { 608c2ecf20Sopenharmony_ci { 0xf, 0x00 }, /* 0F interrupt enable */ 618c2ecf20Sopenharmony_ci 628c2ecf20Sopenharmony_ci { 0x10, 0x00 }, /* 10 master clock */ 638c2ecf20Sopenharmony_ci { 0x11, 0x00 }, /* 11 DAI1 clock mode */ 648c2ecf20Sopenharmony_ci { 0x12, 0x00 }, /* 12 DAI1 clock control */ 658c2ecf20Sopenharmony_ci { 0x13, 0x00 }, /* 13 DAI1 clock control */ 668c2ecf20Sopenharmony_ci { 0x14, 0x00 }, /* 14 DAI1 format */ 678c2ecf20Sopenharmony_ci { 0x15, 0x00 }, /* 15 DAI1 clock */ 688c2ecf20Sopenharmony_ci { 0x16, 0x00 }, /* 16 DAI1 config */ 698c2ecf20Sopenharmony_ci { 0x17, 0x00 }, /* 17 DAI1 TDM */ 708c2ecf20Sopenharmony_ci { 0x18, 0x00 }, /* 18 DAI1 filters */ 718c2ecf20Sopenharmony_ci { 0x19, 0x00 }, /* 19 DAI2 clock mode */ 728c2ecf20Sopenharmony_ci { 0x1a, 0x00 }, /* 1A DAI2 clock control */ 738c2ecf20Sopenharmony_ci { 0x1b, 0x00 }, /* 1B DAI2 clock control */ 748c2ecf20Sopenharmony_ci { 0x1c, 0x00 }, /* 1C DAI2 format */ 758c2ecf20Sopenharmony_ci { 0x1d, 0x00 }, /* 1D DAI2 clock */ 768c2ecf20Sopenharmony_ci { 0x1e, 0x00 }, /* 1E DAI2 config */ 778c2ecf20Sopenharmony_ci { 0x1f, 0x00 }, /* 1F DAI2 TDM */ 788c2ecf20Sopenharmony_ci 798c2ecf20Sopenharmony_ci { 0x20, 0x00 }, /* 20 DAI2 filters */ 808c2ecf20Sopenharmony_ci { 0x21, 0x00 }, /* 21 data config */ 818c2ecf20Sopenharmony_ci { 0x22, 0x00 }, /* 22 DAC mixer */ 828c2ecf20Sopenharmony_ci { 0x23, 0x00 }, /* 23 left ADC mixer */ 838c2ecf20Sopenharmony_ci { 0x24, 0x00 }, /* 24 right ADC mixer */ 848c2ecf20Sopenharmony_ci { 0x25, 0x00 }, /* 25 left HP mixer */ 858c2ecf20Sopenharmony_ci { 0x26, 0x00 }, /* 26 right HP mixer */ 868c2ecf20Sopenharmony_ci { 0x27, 0x00 }, /* 27 HP control */ 878c2ecf20Sopenharmony_ci { 0x28, 0x00 }, /* 28 left REC mixer */ 888c2ecf20Sopenharmony_ci { 0x29, 0x00 }, /* 29 right REC mixer */ 898c2ecf20Sopenharmony_ci { 0x2a, 0x00 }, /* 2A REC control */ 908c2ecf20Sopenharmony_ci { 0x2b, 0x00 }, /* 2B left SPK mixer */ 918c2ecf20Sopenharmony_ci { 0x2c, 0x00 }, /* 2C right SPK mixer */ 928c2ecf20Sopenharmony_ci { 0x2d, 0x00 }, /* 2D SPK control */ 938c2ecf20Sopenharmony_ci { 0x2e, 0x00 }, /* 2E sidetone */ 948c2ecf20Sopenharmony_ci { 0x2f, 0x00 }, /* 2F DAI1 playback level */ 958c2ecf20Sopenharmony_ci 968c2ecf20Sopenharmony_ci { 0x30, 0x00 }, /* 30 DAI1 playback level */ 978c2ecf20Sopenharmony_ci { 0x31, 0x00 }, /* 31 DAI2 playback level */ 988c2ecf20Sopenharmony_ci { 0x32, 0x00 }, /* 32 DAI2 playbakc level */ 998c2ecf20Sopenharmony_ci { 0x33, 0x00 }, /* 33 left ADC level */ 1008c2ecf20Sopenharmony_ci { 0x34, 0x00 }, /* 34 right ADC level */ 1018c2ecf20Sopenharmony_ci { 0x35, 0x00 }, /* 35 MIC1 level */ 1028c2ecf20Sopenharmony_ci { 0x36, 0x00 }, /* 36 MIC2 level */ 1038c2ecf20Sopenharmony_ci { 0x37, 0x00 }, /* 37 INA level */ 1048c2ecf20Sopenharmony_ci { 0x38, 0x00 }, /* 38 INB level */ 1058c2ecf20Sopenharmony_ci { 0x39, 0x00 }, /* 39 left HP volume */ 1068c2ecf20Sopenharmony_ci { 0x3a, 0x00 }, /* 3A right HP volume */ 1078c2ecf20Sopenharmony_ci { 0x3b, 0x00 }, /* 3B left REC volume */ 1088c2ecf20Sopenharmony_ci { 0x3c, 0x00 }, /* 3C right REC volume */ 1098c2ecf20Sopenharmony_ci { 0x3d, 0x00 }, /* 3D left SPK volume */ 1108c2ecf20Sopenharmony_ci { 0x3e, 0x00 }, /* 3E right SPK volume */ 1118c2ecf20Sopenharmony_ci { 0x3f, 0x00 }, /* 3F MIC config */ 1128c2ecf20Sopenharmony_ci 1138c2ecf20Sopenharmony_ci { 0x40, 0x00 }, /* 40 MIC threshold */ 1148c2ecf20Sopenharmony_ci { 0x41, 0x00 }, /* 41 excursion limiter filter */ 1158c2ecf20Sopenharmony_ci { 0x42, 0x00 }, /* 42 excursion limiter threshold */ 1168c2ecf20Sopenharmony_ci { 0x43, 0x00 }, /* 43 ALC */ 1178c2ecf20Sopenharmony_ci { 0x44, 0x00 }, /* 44 power limiter threshold */ 1188c2ecf20Sopenharmony_ci { 0x45, 0x00 }, /* 45 power limiter config */ 1198c2ecf20Sopenharmony_ci { 0x46, 0x00 }, /* 46 distortion limiter config */ 1208c2ecf20Sopenharmony_ci { 0x47, 0x00 }, /* 47 audio input */ 1218c2ecf20Sopenharmony_ci { 0x48, 0x00 }, /* 48 microphone */ 1228c2ecf20Sopenharmony_ci { 0x49, 0x00 }, /* 49 level control */ 1238c2ecf20Sopenharmony_ci { 0x4a, 0x00 }, /* 4A bypass switches */ 1248c2ecf20Sopenharmony_ci { 0x4b, 0x00 }, /* 4B jack detect */ 1258c2ecf20Sopenharmony_ci { 0x4c, 0x00 }, /* 4C input enable */ 1268c2ecf20Sopenharmony_ci { 0x4d, 0x00 }, /* 4D output enable */ 1278c2ecf20Sopenharmony_ci { 0x4e, 0xF0 }, /* 4E bias control */ 1288c2ecf20Sopenharmony_ci { 0x4f, 0x00 }, /* 4F DAC power */ 1298c2ecf20Sopenharmony_ci 1308c2ecf20Sopenharmony_ci { 0x50, 0x0F }, /* 50 DAC power */ 1318c2ecf20Sopenharmony_ci { 0x51, 0x00 }, /* 51 system */ 1328c2ecf20Sopenharmony_ci { 0x52, 0x00 }, /* 52 DAI1 EQ1 */ 1338c2ecf20Sopenharmony_ci { 0x53, 0x00 }, /* 53 DAI1 EQ1 */ 1348c2ecf20Sopenharmony_ci { 0x54, 0x00 }, /* 54 DAI1 EQ1 */ 1358c2ecf20Sopenharmony_ci { 0x55, 0x00 }, /* 55 DAI1 EQ1 */ 1368c2ecf20Sopenharmony_ci { 0x56, 0x00 }, /* 56 DAI1 EQ1 */ 1378c2ecf20Sopenharmony_ci { 0x57, 0x00 }, /* 57 DAI1 EQ1 */ 1388c2ecf20Sopenharmony_ci { 0x58, 0x00 }, /* 58 DAI1 EQ1 */ 1398c2ecf20Sopenharmony_ci { 0x59, 0x00 }, /* 59 DAI1 EQ1 */ 1408c2ecf20Sopenharmony_ci { 0x5a, 0x00 }, /* 5A DAI1 EQ1 */ 1418c2ecf20Sopenharmony_ci { 0x5b, 0x00 }, /* 5B DAI1 EQ1 */ 1428c2ecf20Sopenharmony_ci { 0x5c, 0x00 }, /* 5C DAI1 EQ2 */ 1438c2ecf20Sopenharmony_ci { 0x5d, 0x00 }, /* 5D DAI1 EQ2 */ 1448c2ecf20Sopenharmony_ci { 0x5e, 0x00 }, /* 5E DAI1 EQ2 */ 1458c2ecf20Sopenharmony_ci { 0x5f, 0x00 }, /* 5F DAI1 EQ2 */ 1468c2ecf20Sopenharmony_ci 1478c2ecf20Sopenharmony_ci { 0x60, 0x00 }, /* 60 DAI1 EQ2 */ 1488c2ecf20Sopenharmony_ci { 0x61, 0x00 }, /* 61 DAI1 EQ2 */ 1498c2ecf20Sopenharmony_ci { 0x62, 0x00 }, /* 62 DAI1 EQ2 */ 1508c2ecf20Sopenharmony_ci { 0x63, 0x00 }, /* 63 DAI1 EQ2 */ 1518c2ecf20Sopenharmony_ci { 0x64, 0x00 }, /* 64 DAI1 EQ2 */ 1528c2ecf20Sopenharmony_ci { 0x65, 0x00 }, /* 65 DAI1 EQ2 */ 1538c2ecf20Sopenharmony_ci { 0x66, 0x00 }, /* 66 DAI1 EQ3 */ 1548c2ecf20Sopenharmony_ci { 0x67, 0x00 }, /* 67 DAI1 EQ3 */ 1558c2ecf20Sopenharmony_ci { 0x68, 0x00 }, /* 68 DAI1 EQ3 */ 1568c2ecf20Sopenharmony_ci { 0x69, 0x00 }, /* 69 DAI1 EQ3 */ 1578c2ecf20Sopenharmony_ci { 0x6a, 0x00 }, /* 6A DAI1 EQ3 */ 1588c2ecf20Sopenharmony_ci { 0x6b, 0x00 }, /* 6B DAI1 EQ3 */ 1598c2ecf20Sopenharmony_ci { 0x6c, 0x00 }, /* 6C DAI1 EQ3 */ 1608c2ecf20Sopenharmony_ci { 0x6d, 0x00 }, /* 6D DAI1 EQ3 */ 1618c2ecf20Sopenharmony_ci { 0x6e, 0x00 }, /* 6E DAI1 EQ3 */ 1628c2ecf20Sopenharmony_ci { 0x6f, 0x00 }, /* 6F DAI1 EQ3 */ 1638c2ecf20Sopenharmony_ci 1648c2ecf20Sopenharmony_ci { 0x70, 0x00 }, /* 70 DAI1 EQ4 */ 1658c2ecf20Sopenharmony_ci { 0x71, 0x00 }, /* 71 DAI1 EQ4 */ 1668c2ecf20Sopenharmony_ci { 0x72, 0x00 }, /* 72 DAI1 EQ4 */ 1678c2ecf20Sopenharmony_ci { 0x73, 0x00 }, /* 73 DAI1 EQ4 */ 1688c2ecf20Sopenharmony_ci { 0x74, 0x00 }, /* 74 DAI1 EQ4 */ 1698c2ecf20Sopenharmony_ci { 0x75, 0x00 }, /* 75 DAI1 EQ4 */ 1708c2ecf20Sopenharmony_ci { 0x76, 0x00 }, /* 76 DAI1 EQ4 */ 1718c2ecf20Sopenharmony_ci { 0x77, 0x00 }, /* 77 DAI1 EQ4 */ 1728c2ecf20Sopenharmony_ci { 0x78, 0x00 }, /* 78 DAI1 EQ4 */ 1738c2ecf20Sopenharmony_ci { 0x79, 0x00 }, /* 79 DAI1 EQ4 */ 1748c2ecf20Sopenharmony_ci { 0x7a, 0x00 }, /* 7A DAI1 EQ5 */ 1758c2ecf20Sopenharmony_ci { 0x7b, 0x00 }, /* 7B DAI1 EQ5 */ 1768c2ecf20Sopenharmony_ci { 0x7c, 0x00 }, /* 7C DAI1 EQ5 */ 1778c2ecf20Sopenharmony_ci { 0x7d, 0x00 }, /* 7D DAI1 EQ5 */ 1788c2ecf20Sopenharmony_ci { 0x7e, 0x00 }, /* 7E DAI1 EQ5 */ 1798c2ecf20Sopenharmony_ci { 0x7f, 0x00 }, /* 7F DAI1 EQ5 */ 1808c2ecf20Sopenharmony_ci 1818c2ecf20Sopenharmony_ci { 0x80, 0x00 }, /* 80 DAI1 EQ5 */ 1828c2ecf20Sopenharmony_ci { 0x81, 0x00 }, /* 81 DAI1 EQ5 */ 1838c2ecf20Sopenharmony_ci { 0x82, 0x00 }, /* 82 DAI1 EQ5 */ 1848c2ecf20Sopenharmony_ci { 0x83, 0x00 }, /* 83 DAI1 EQ5 */ 1858c2ecf20Sopenharmony_ci { 0x84, 0x00 }, /* 84 DAI2 EQ1 */ 1868c2ecf20Sopenharmony_ci { 0x85, 0x00 }, /* 85 DAI2 EQ1 */ 1878c2ecf20Sopenharmony_ci { 0x86, 0x00 }, /* 86 DAI2 EQ1 */ 1888c2ecf20Sopenharmony_ci { 0x87, 0x00 }, /* 87 DAI2 EQ1 */ 1898c2ecf20Sopenharmony_ci { 0x88, 0x00 }, /* 88 DAI2 EQ1 */ 1908c2ecf20Sopenharmony_ci { 0x89, 0x00 }, /* 89 DAI2 EQ1 */ 1918c2ecf20Sopenharmony_ci { 0x8a, 0x00 }, /* 8A DAI2 EQ1 */ 1928c2ecf20Sopenharmony_ci { 0x8b, 0x00 }, /* 8B DAI2 EQ1 */ 1938c2ecf20Sopenharmony_ci { 0x8c, 0x00 }, /* 8C DAI2 EQ1 */ 1948c2ecf20Sopenharmony_ci { 0x8d, 0x00 }, /* 8D DAI2 EQ1 */ 1958c2ecf20Sopenharmony_ci { 0x8e, 0x00 }, /* 8E DAI2 EQ2 */ 1968c2ecf20Sopenharmony_ci { 0x8f, 0x00 }, /* 8F DAI2 EQ2 */ 1978c2ecf20Sopenharmony_ci 1988c2ecf20Sopenharmony_ci { 0x90, 0x00 }, /* 90 DAI2 EQ2 */ 1998c2ecf20Sopenharmony_ci { 0x91, 0x00 }, /* 91 DAI2 EQ2 */ 2008c2ecf20Sopenharmony_ci { 0x92, 0x00 }, /* 92 DAI2 EQ2 */ 2018c2ecf20Sopenharmony_ci { 0x93, 0x00 }, /* 93 DAI2 EQ2 */ 2028c2ecf20Sopenharmony_ci { 0x94, 0x00 }, /* 94 DAI2 EQ2 */ 2038c2ecf20Sopenharmony_ci { 0x95, 0x00 }, /* 95 DAI2 EQ2 */ 2048c2ecf20Sopenharmony_ci { 0x96, 0x00 }, /* 96 DAI2 EQ2 */ 2058c2ecf20Sopenharmony_ci { 0x97, 0x00 }, /* 97 DAI2 EQ2 */ 2068c2ecf20Sopenharmony_ci { 0x98, 0x00 }, /* 98 DAI2 EQ3 */ 2078c2ecf20Sopenharmony_ci { 0x99, 0x00 }, /* 99 DAI2 EQ3 */ 2088c2ecf20Sopenharmony_ci { 0x9a, 0x00 }, /* 9A DAI2 EQ3 */ 2098c2ecf20Sopenharmony_ci { 0x9b, 0x00 }, /* 9B DAI2 EQ3 */ 2108c2ecf20Sopenharmony_ci { 0x9c, 0x00 }, /* 9C DAI2 EQ3 */ 2118c2ecf20Sopenharmony_ci { 0x9d, 0x00 }, /* 9D DAI2 EQ3 */ 2128c2ecf20Sopenharmony_ci { 0x9e, 0x00 }, /* 9E DAI2 EQ3 */ 2138c2ecf20Sopenharmony_ci { 0x9f, 0x00 }, /* 9F DAI2 EQ3 */ 2148c2ecf20Sopenharmony_ci 2158c2ecf20Sopenharmony_ci { 0xa0, 0x00 }, /* A0 DAI2 EQ3 */ 2168c2ecf20Sopenharmony_ci { 0xa1, 0x00 }, /* A1 DAI2 EQ3 */ 2178c2ecf20Sopenharmony_ci { 0xa2, 0x00 }, /* A2 DAI2 EQ4 */ 2188c2ecf20Sopenharmony_ci { 0xa3, 0x00 }, /* A3 DAI2 EQ4 */ 2198c2ecf20Sopenharmony_ci { 0xa4, 0x00 }, /* A4 DAI2 EQ4 */ 2208c2ecf20Sopenharmony_ci { 0xa5, 0x00 }, /* A5 DAI2 EQ4 */ 2218c2ecf20Sopenharmony_ci { 0xa6, 0x00 }, /* A6 DAI2 EQ4 */ 2228c2ecf20Sopenharmony_ci { 0xa7, 0x00 }, /* A7 DAI2 EQ4 */ 2238c2ecf20Sopenharmony_ci { 0xa8, 0x00 }, /* A8 DAI2 EQ4 */ 2248c2ecf20Sopenharmony_ci { 0xa9, 0x00 }, /* A9 DAI2 EQ4 */ 2258c2ecf20Sopenharmony_ci { 0xaa, 0x00 }, /* AA DAI2 EQ4 */ 2268c2ecf20Sopenharmony_ci { 0xab, 0x00 }, /* AB DAI2 EQ4 */ 2278c2ecf20Sopenharmony_ci { 0xac, 0x00 }, /* AC DAI2 EQ5 */ 2288c2ecf20Sopenharmony_ci { 0xad, 0x00 }, /* AD DAI2 EQ5 */ 2298c2ecf20Sopenharmony_ci { 0xae, 0x00 }, /* AE DAI2 EQ5 */ 2308c2ecf20Sopenharmony_ci { 0xaf, 0x00 }, /* AF DAI2 EQ5 */ 2318c2ecf20Sopenharmony_ci 2328c2ecf20Sopenharmony_ci { 0xb0, 0x00 }, /* B0 DAI2 EQ5 */ 2338c2ecf20Sopenharmony_ci { 0xb1, 0x00 }, /* B1 DAI2 EQ5 */ 2348c2ecf20Sopenharmony_ci { 0xb2, 0x00 }, /* B2 DAI2 EQ5 */ 2358c2ecf20Sopenharmony_ci { 0xb3, 0x00 }, /* B3 DAI2 EQ5 */ 2368c2ecf20Sopenharmony_ci { 0xb4, 0x00 }, /* B4 DAI2 EQ5 */ 2378c2ecf20Sopenharmony_ci { 0xb5, 0x00 }, /* B5 DAI2 EQ5 */ 2388c2ecf20Sopenharmony_ci { 0xb6, 0x00 }, /* B6 DAI1 biquad */ 2398c2ecf20Sopenharmony_ci { 0xb7, 0x00 }, /* B7 DAI1 biquad */ 2408c2ecf20Sopenharmony_ci { 0xb8 ,0x00 }, /* B8 DAI1 biquad */ 2418c2ecf20Sopenharmony_ci { 0xb9, 0x00 }, /* B9 DAI1 biquad */ 2428c2ecf20Sopenharmony_ci { 0xba, 0x00 }, /* BA DAI1 biquad */ 2438c2ecf20Sopenharmony_ci { 0xbb, 0x00 }, /* BB DAI1 biquad */ 2448c2ecf20Sopenharmony_ci { 0xbc, 0x00 }, /* BC DAI1 biquad */ 2458c2ecf20Sopenharmony_ci { 0xbd, 0x00 }, /* BD DAI1 biquad */ 2468c2ecf20Sopenharmony_ci { 0xbe, 0x00 }, /* BE DAI1 biquad */ 2478c2ecf20Sopenharmony_ci { 0xbf, 0x00 }, /* BF DAI1 biquad */ 2488c2ecf20Sopenharmony_ci 2498c2ecf20Sopenharmony_ci { 0xc0, 0x00 }, /* C0 DAI2 biquad */ 2508c2ecf20Sopenharmony_ci { 0xc1, 0x00 }, /* C1 DAI2 biquad */ 2518c2ecf20Sopenharmony_ci { 0xc2, 0x00 }, /* C2 DAI2 biquad */ 2528c2ecf20Sopenharmony_ci { 0xc3, 0x00 }, /* C3 DAI2 biquad */ 2538c2ecf20Sopenharmony_ci { 0xc4, 0x00 }, /* C4 DAI2 biquad */ 2548c2ecf20Sopenharmony_ci { 0xc5, 0x00 }, /* C5 DAI2 biquad */ 2558c2ecf20Sopenharmony_ci { 0xc6, 0x00 }, /* C6 DAI2 biquad */ 2568c2ecf20Sopenharmony_ci { 0xc7, 0x00 }, /* C7 DAI2 biquad */ 2578c2ecf20Sopenharmony_ci { 0xc8, 0x00 }, /* C8 DAI2 biquad */ 2588c2ecf20Sopenharmony_ci { 0xc9, 0x00 }, /* C9 DAI2 biquad */ 2598c2ecf20Sopenharmony_ci}; 2608c2ecf20Sopenharmony_ci 2618c2ecf20Sopenharmony_cistatic bool max98088_readable_register(struct device *dev, unsigned int reg) 2628c2ecf20Sopenharmony_ci{ 2638c2ecf20Sopenharmony_ci switch (reg) { 2648c2ecf20Sopenharmony_ci case M98088_REG_00_IRQ_STATUS ... 0xC9: 2658c2ecf20Sopenharmony_ci case M98088_REG_FF_REV_ID: 2668c2ecf20Sopenharmony_ci return true; 2678c2ecf20Sopenharmony_ci default: 2688c2ecf20Sopenharmony_ci return false; 2698c2ecf20Sopenharmony_ci } 2708c2ecf20Sopenharmony_ci} 2718c2ecf20Sopenharmony_ci 2728c2ecf20Sopenharmony_cistatic bool max98088_writeable_register(struct device *dev, unsigned int reg) 2738c2ecf20Sopenharmony_ci{ 2748c2ecf20Sopenharmony_ci switch (reg) { 2758c2ecf20Sopenharmony_ci case M98088_REG_03_BATTERY_VOLTAGE ... 0xC9: 2768c2ecf20Sopenharmony_ci return true; 2778c2ecf20Sopenharmony_ci default: 2788c2ecf20Sopenharmony_ci return false; 2798c2ecf20Sopenharmony_ci } 2808c2ecf20Sopenharmony_ci} 2818c2ecf20Sopenharmony_ci 2828c2ecf20Sopenharmony_cistatic bool max98088_volatile_register(struct device *dev, unsigned int reg) 2838c2ecf20Sopenharmony_ci{ 2848c2ecf20Sopenharmony_ci switch (reg) { 2858c2ecf20Sopenharmony_ci case M98088_REG_00_IRQ_STATUS ... M98088_REG_03_BATTERY_VOLTAGE: 2868c2ecf20Sopenharmony_ci case M98088_REG_FF_REV_ID: 2878c2ecf20Sopenharmony_ci return true; 2888c2ecf20Sopenharmony_ci default: 2898c2ecf20Sopenharmony_ci return false; 2908c2ecf20Sopenharmony_ci } 2918c2ecf20Sopenharmony_ci} 2928c2ecf20Sopenharmony_ci 2938c2ecf20Sopenharmony_cistatic const struct regmap_config max98088_regmap = { 2948c2ecf20Sopenharmony_ci .reg_bits = 8, 2958c2ecf20Sopenharmony_ci .val_bits = 8, 2968c2ecf20Sopenharmony_ci 2978c2ecf20Sopenharmony_ci .readable_reg = max98088_readable_register, 2988c2ecf20Sopenharmony_ci .writeable_reg = max98088_writeable_register, 2998c2ecf20Sopenharmony_ci .volatile_reg = max98088_volatile_register, 3008c2ecf20Sopenharmony_ci .max_register = 0xff, 3018c2ecf20Sopenharmony_ci 3028c2ecf20Sopenharmony_ci .reg_defaults = max98088_reg, 3038c2ecf20Sopenharmony_ci .num_reg_defaults = ARRAY_SIZE(max98088_reg), 3048c2ecf20Sopenharmony_ci .cache_type = REGCACHE_RBTREE, 3058c2ecf20Sopenharmony_ci}; 3068c2ecf20Sopenharmony_ci 3078c2ecf20Sopenharmony_ci/* 3088c2ecf20Sopenharmony_ci * Load equalizer DSP coefficient configurations registers 3098c2ecf20Sopenharmony_ci */ 3108c2ecf20Sopenharmony_cistatic void m98088_eq_band(struct snd_soc_component *component, unsigned int dai, 3118c2ecf20Sopenharmony_ci unsigned int band, u16 *coefs) 3128c2ecf20Sopenharmony_ci{ 3138c2ecf20Sopenharmony_ci unsigned int eq_reg; 3148c2ecf20Sopenharmony_ci unsigned int i; 3158c2ecf20Sopenharmony_ci 3168c2ecf20Sopenharmony_ci if (WARN_ON(band > 4) || 3178c2ecf20Sopenharmony_ci WARN_ON(dai > 1)) 3188c2ecf20Sopenharmony_ci return; 3198c2ecf20Sopenharmony_ci 3208c2ecf20Sopenharmony_ci /* Load the base register address */ 3218c2ecf20Sopenharmony_ci eq_reg = dai ? M98088_REG_84_DAI2_EQ_BASE : M98088_REG_52_DAI1_EQ_BASE; 3228c2ecf20Sopenharmony_ci 3238c2ecf20Sopenharmony_ci /* Add the band address offset, note adjustment for word address */ 3248c2ecf20Sopenharmony_ci eq_reg += band * (M98088_COEFS_PER_BAND << 1); 3258c2ecf20Sopenharmony_ci 3268c2ecf20Sopenharmony_ci /* Step through the registers and coefs */ 3278c2ecf20Sopenharmony_ci for (i = 0; i < M98088_COEFS_PER_BAND; i++) { 3288c2ecf20Sopenharmony_ci snd_soc_component_write(component, eq_reg++, M98088_BYTE1(coefs[i])); 3298c2ecf20Sopenharmony_ci snd_soc_component_write(component, eq_reg++, M98088_BYTE0(coefs[i])); 3308c2ecf20Sopenharmony_ci } 3318c2ecf20Sopenharmony_ci} 3328c2ecf20Sopenharmony_ci 3338c2ecf20Sopenharmony_ci/* 3348c2ecf20Sopenharmony_ci * Excursion limiter modes 3358c2ecf20Sopenharmony_ci */ 3368c2ecf20Sopenharmony_cistatic const char *max98088_exmode_texts[] = { 3378c2ecf20Sopenharmony_ci "Off", "100Hz", "400Hz", "600Hz", "800Hz", "1000Hz", "200-400Hz", 3388c2ecf20Sopenharmony_ci "400-600Hz", "400-800Hz", 3398c2ecf20Sopenharmony_ci}; 3408c2ecf20Sopenharmony_ci 3418c2ecf20Sopenharmony_cistatic const unsigned int max98088_exmode_values[] = { 3428c2ecf20Sopenharmony_ci 0x00, 0x43, 0x10, 0x20, 0x30, 0x40, 0x11, 0x22, 0x32 3438c2ecf20Sopenharmony_ci}; 3448c2ecf20Sopenharmony_ci 3458c2ecf20Sopenharmony_cistatic SOC_VALUE_ENUM_SINGLE_DECL(max98088_exmode_enum, 3468c2ecf20Sopenharmony_ci M98088_REG_41_SPKDHP, 0, 127, 3478c2ecf20Sopenharmony_ci max98088_exmode_texts, 3488c2ecf20Sopenharmony_ci max98088_exmode_values); 3498c2ecf20Sopenharmony_ci 3508c2ecf20Sopenharmony_cistatic const char *max98088_ex_thresh[] = { /* volts PP */ 3518c2ecf20Sopenharmony_ci "0.6", "1.2", "1.8", "2.4", "3.0", "3.6", "4.2", "4.8"}; 3528c2ecf20Sopenharmony_cistatic SOC_ENUM_SINGLE_DECL(max98088_ex_thresh_enum, 3538c2ecf20Sopenharmony_ci M98088_REG_42_SPKDHP_THRESH, 0, 3548c2ecf20Sopenharmony_ci max98088_ex_thresh); 3558c2ecf20Sopenharmony_ci 3568c2ecf20Sopenharmony_cistatic const char *max98088_fltr_mode[] = {"Voice", "Music" }; 3578c2ecf20Sopenharmony_cistatic SOC_ENUM_SINGLE_DECL(max98088_filter_mode_enum, 3588c2ecf20Sopenharmony_ci M98088_REG_18_DAI1_FILTERS, 7, 3598c2ecf20Sopenharmony_ci max98088_fltr_mode); 3608c2ecf20Sopenharmony_ci 3618c2ecf20Sopenharmony_cistatic const char *max98088_extmic_text[] = { "None", "MIC1", "MIC2" }; 3628c2ecf20Sopenharmony_ci 3638c2ecf20Sopenharmony_cistatic SOC_ENUM_SINGLE_DECL(max98088_extmic_enum, 3648c2ecf20Sopenharmony_ci M98088_REG_48_CFG_MIC, 0, 3658c2ecf20Sopenharmony_ci max98088_extmic_text); 3668c2ecf20Sopenharmony_ci 3678c2ecf20Sopenharmony_cistatic const struct snd_kcontrol_new max98088_extmic_mux = 3688c2ecf20Sopenharmony_ci SOC_DAPM_ENUM("External MIC Mux", max98088_extmic_enum); 3698c2ecf20Sopenharmony_ci 3708c2ecf20Sopenharmony_cistatic const char *max98088_dai1_fltr[] = { 3718c2ecf20Sopenharmony_ci "Off", "fc=258/fs=16k", "fc=500/fs=16k", 3728c2ecf20Sopenharmony_ci "fc=258/fs=8k", "fc=500/fs=8k", "fc=200"}; 3738c2ecf20Sopenharmony_cistatic SOC_ENUM_SINGLE_DECL(max98088_dai1_dac_filter_enum, 3748c2ecf20Sopenharmony_ci M98088_REG_18_DAI1_FILTERS, 0, 3758c2ecf20Sopenharmony_ci max98088_dai1_fltr); 3768c2ecf20Sopenharmony_cistatic SOC_ENUM_SINGLE_DECL(max98088_dai1_adc_filter_enum, 3778c2ecf20Sopenharmony_ci M98088_REG_18_DAI1_FILTERS, 4, 3788c2ecf20Sopenharmony_ci max98088_dai1_fltr); 3798c2ecf20Sopenharmony_ci 3808c2ecf20Sopenharmony_cistatic int max98088_mic1pre_set(struct snd_kcontrol *kcontrol, 3818c2ecf20Sopenharmony_ci struct snd_ctl_elem_value *ucontrol) 3828c2ecf20Sopenharmony_ci{ 3838c2ecf20Sopenharmony_ci struct snd_soc_component *component = snd_soc_kcontrol_component(kcontrol); 3848c2ecf20Sopenharmony_ci struct max98088_priv *max98088 = snd_soc_component_get_drvdata(component); 3858c2ecf20Sopenharmony_ci unsigned int sel = ucontrol->value.integer.value[0]; 3868c2ecf20Sopenharmony_ci 3878c2ecf20Sopenharmony_ci max98088->mic1pre = sel; 3888c2ecf20Sopenharmony_ci snd_soc_component_update_bits(component, M98088_REG_35_LVL_MIC1, M98088_MICPRE_MASK, 3898c2ecf20Sopenharmony_ci (1+sel)<<M98088_MICPRE_SHIFT); 3908c2ecf20Sopenharmony_ci 3918c2ecf20Sopenharmony_ci return 0; 3928c2ecf20Sopenharmony_ci} 3938c2ecf20Sopenharmony_ci 3948c2ecf20Sopenharmony_cistatic int max98088_mic1pre_get(struct snd_kcontrol *kcontrol, 3958c2ecf20Sopenharmony_ci struct snd_ctl_elem_value *ucontrol) 3968c2ecf20Sopenharmony_ci{ 3978c2ecf20Sopenharmony_ci struct snd_soc_component *component = snd_soc_kcontrol_component(kcontrol); 3988c2ecf20Sopenharmony_ci struct max98088_priv *max98088 = snd_soc_component_get_drvdata(component); 3998c2ecf20Sopenharmony_ci 4008c2ecf20Sopenharmony_ci ucontrol->value.integer.value[0] = max98088->mic1pre; 4018c2ecf20Sopenharmony_ci return 0; 4028c2ecf20Sopenharmony_ci} 4038c2ecf20Sopenharmony_ci 4048c2ecf20Sopenharmony_cistatic int max98088_mic2pre_set(struct snd_kcontrol *kcontrol, 4058c2ecf20Sopenharmony_ci struct snd_ctl_elem_value *ucontrol) 4068c2ecf20Sopenharmony_ci{ 4078c2ecf20Sopenharmony_ci struct snd_soc_component *component = snd_soc_kcontrol_component(kcontrol); 4088c2ecf20Sopenharmony_ci struct max98088_priv *max98088 = snd_soc_component_get_drvdata(component); 4098c2ecf20Sopenharmony_ci unsigned int sel = ucontrol->value.integer.value[0]; 4108c2ecf20Sopenharmony_ci 4118c2ecf20Sopenharmony_ci max98088->mic2pre = sel; 4128c2ecf20Sopenharmony_ci snd_soc_component_update_bits(component, M98088_REG_36_LVL_MIC2, M98088_MICPRE_MASK, 4138c2ecf20Sopenharmony_ci (1+sel)<<M98088_MICPRE_SHIFT); 4148c2ecf20Sopenharmony_ci 4158c2ecf20Sopenharmony_ci return 0; 4168c2ecf20Sopenharmony_ci} 4178c2ecf20Sopenharmony_ci 4188c2ecf20Sopenharmony_cistatic int max98088_mic2pre_get(struct snd_kcontrol *kcontrol, 4198c2ecf20Sopenharmony_ci struct snd_ctl_elem_value *ucontrol) 4208c2ecf20Sopenharmony_ci{ 4218c2ecf20Sopenharmony_ci struct snd_soc_component *component = snd_soc_kcontrol_component(kcontrol); 4228c2ecf20Sopenharmony_ci struct max98088_priv *max98088 = snd_soc_component_get_drvdata(component); 4238c2ecf20Sopenharmony_ci 4248c2ecf20Sopenharmony_ci ucontrol->value.integer.value[0] = max98088->mic2pre; 4258c2ecf20Sopenharmony_ci return 0; 4268c2ecf20Sopenharmony_ci} 4278c2ecf20Sopenharmony_ci 4288c2ecf20Sopenharmony_cistatic const DECLARE_TLV_DB_RANGE(max98088_micboost_tlv, 4298c2ecf20Sopenharmony_ci 0, 1, TLV_DB_SCALE_ITEM(0, 2000, 0), 4308c2ecf20Sopenharmony_ci 2, 2, TLV_DB_SCALE_ITEM(3000, 0, 0) 4318c2ecf20Sopenharmony_ci); 4328c2ecf20Sopenharmony_ci 4338c2ecf20Sopenharmony_cistatic const DECLARE_TLV_DB_RANGE(max98088_hp_tlv, 4348c2ecf20Sopenharmony_ci 0, 6, TLV_DB_SCALE_ITEM(-6700, 400, 0), 4358c2ecf20Sopenharmony_ci 7, 14, TLV_DB_SCALE_ITEM(-4000, 300, 0), 4368c2ecf20Sopenharmony_ci 15, 21, TLV_DB_SCALE_ITEM(-1700, 200, 0), 4378c2ecf20Sopenharmony_ci 22, 27, TLV_DB_SCALE_ITEM(-400, 100, 0), 4388c2ecf20Sopenharmony_ci 28, 31, TLV_DB_SCALE_ITEM(150, 50, 0) 4398c2ecf20Sopenharmony_ci); 4408c2ecf20Sopenharmony_ci 4418c2ecf20Sopenharmony_cistatic const DECLARE_TLV_DB_RANGE(max98088_spk_tlv, 4428c2ecf20Sopenharmony_ci 0, 6, TLV_DB_SCALE_ITEM(-6200, 400, 0), 4438c2ecf20Sopenharmony_ci 7, 14, TLV_DB_SCALE_ITEM(-3500, 300, 0), 4448c2ecf20Sopenharmony_ci 15, 21, TLV_DB_SCALE_ITEM(-1200, 200, 0), 4458c2ecf20Sopenharmony_ci 22, 27, TLV_DB_SCALE_ITEM(100, 100, 0), 4468c2ecf20Sopenharmony_ci 28, 31, TLV_DB_SCALE_ITEM(650, 50, 0) 4478c2ecf20Sopenharmony_ci); 4488c2ecf20Sopenharmony_ci 4498c2ecf20Sopenharmony_cistatic const struct snd_kcontrol_new max98088_snd_controls[] = { 4508c2ecf20Sopenharmony_ci 4518c2ecf20Sopenharmony_ci SOC_DOUBLE_R_TLV("Headphone Volume", M98088_REG_39_LVL_HP_L, 4528c2ecf20Sopenharmony_ci M98088_REG_3A_LVL_HP_R, 0, 31, 0, max98088_hp_tlv), 4538c2ecf20Sopenharmony_ci SOC_DOUBLE_R_TLV("Speaker Volume", M98088_REG_3D_LVL_SPK_L, 4548c2ecf20Sopenharmony_ci M98088_REG_3E_LVL_SPK_R, 0, 31, 0, max98088_spk_tlv), 4558c2ecf20Sopenharmony_ci SOC_DOUBLE_R_TLV("Receiver Volume", M98088_REG_3B_LVL_REC_L, 4568c2ecf20Sopenharmony_ci M98088_REG_3C_LVL_REC_R, 0, 31, 0, max98088_spk_tlv), 4578c2ecf20Sopenharmony_ci 4588c2ecf20Sopenharmony_ci SOC_DOUBLE_R("Headphone Switch", M98088_REG_39_LVL_HP_L, 4598c2ecf20Sopenharmony_ci M98088_REG_3A_LVL_HP_R, 7, 1, 1), 4608c2ecf20Sopenharmony_ci SOC_DOUBLE_R("Speaker Switch", M98088_REG_3D_LVL_SPK_L, 4618c2ecf20Sopenharmony_ci M98088_REG_3E_LVL_SPK_R, 7, 1, 1), 4628c2ecf20Sopenharmony_ci SOC_DOUBLE_R("Receiver Switch", M98088_REG_3B_LVL_REC_L, 4638c2ecf20Sopenharmony_ci M98088_REG_3C_LVL_REC_R, 7, 1, 1), 4648c2ecf20Sopenharmony_ci 4658c2ecf20Sopenharmony_ci SOC_SINGLE("MIC1 Volume", M98088_REG_35_LVL_MIC1, 0, 31, 1), 4668c2ecf20Sopenharmony_ci SOC_SINGLE("MIC2 Volume", M98088_REG_36_LVL_MIC2, 0, 31, 1), 4678c2ecf20Sopenharmony_ci 4688c2ecf20Sopenharmony_ci SOC_SINGLE_EXT_TLV("MIC1 Boost Volume", 4698c2ecf20Sopenharmony_ci M98088_REG_35_LVL_MIC1, 5, 2, 0, 4708c2ecf20Sopenharmony_ci max98088_mic1pre_get, max98088_mic1pre_set, 4718c2ecf20Sopenharmony_ci max98088_micboost_tlv), 4728c2ecf20Sopenharmony_ci SOC_SINGLE_EXT_TLV("MIC2 Boost Volume", 4738c2ecf20Sopenharmony_ci M98088_REG_36_LVL_MIC2, 5, 2, 0, 4748c2ecf20Sopenharmony_ci max98088_mic2pre_get, max98088_mic2pre_set, 4758c2ecf20Sopenharmony_ci max98088_micboost_tlv), 4768c2ecf20Sopenharmony_ci 4778c2ecf20Sopenharmony_ci SOC_SINGLE("INA Volume", M98088_REG_37_LVL_INA, 0, 7, 1), 4788c2ecf20Sopenharmony_ci SOC_SINGLE("INB Volume", M98088_REG_38_LVL_INB, 0, 7, 1), 4798c2ecf20Sopenharmony_ci 4808c2ecf20Sopenharmony_ci SOC_SINGLE("ADCL Volume", M98088_REG_33_LVL_ADC_L, 0, 15, 0), 4818c2ecf20Sopenharmony_ci SOC_SINGLE("ADCR Volume", M98088_REG_34_LVL_ADC_R, 0, 15, 0), 4828c2ecf20Sopenharmony_ci 4838c2ecf20Sopenharmony_ci SOC_SINGLE("ADCL Boost Volume", M98088_REG_33_LVL_ADC_L, 4, 3, 0), 4848c2ecf20Sopenharmony_ci SOC_SINGLE("ADCR Boost Volume", M98088_REG_34_LVL_ADC_R, 4, 3, 0), 4858c2ecf20Sopenharmony_ci 4868c2ecf20Sopenharmony_ci SOC_SINGLE("EQ1 Switch", M98088_REG_49_CFG_LEVEL, 0, 1, 0), 4878c2ecf20Sopenharmony_ci SOC_SINGLE("EQ2 Switch", M98088_REG_49_CFG_LEVEL, 1, 1, 0), 4888c2ecf20Sopenharmony_ci 4898c2ecf20Sopenharmony_ci SOC_ENUM("EX Limiter Mode", max98088_exmode_enum), 4908c2ecf20Sopenharmony_ci SOC_ENUM("EX Limiter Threshold", max98088_ex_thresh_enum), 4918c2ecf20Sopenharmony_ci 4928c2ecf20Sopenharmony_ci SOC_ENUM("DAI1 Filter Mode", max98088_filter_mode_enum), 4938c2ecf20Sopenharmony_ci SOC_ENUM("DAI1 DAC Filter", max98088_dai1_dac_filter_enum), 4948c2ecf20Sopenharmony_ci SOC_ENUM("DAI1 ADC Filter", max98088_dai1_adc_filter_enum), 4958c2ecf20Sopenharmony_ci SOC_SINGLE("DAI2 DC Block Switch", M98088_REG_20_DAI2_FILTERS, 4968c2ecf20Sopenharmony_ci 0, 1, 0), 4978c2ecf20Sopenharmony_ci 4988c2ecf20Sopenharmony_ci SOC_SINGLE("ALC Switch", M98088_REG_43_SPKALC_COMP, 7, 1, 0), 4998c2ecf20Sopenharmony_ci SOC_SINGLE("ALC Threshold", M98088_REG_43_SPKALC_COMP, 0, 7, 0), 5008c2ecf20Sopenharmony_ci SOC_SINGLE("ALC Multiband", M98088_REG_43_SPKALC_COMP, 3, 1, 0), 5018c2ecf20Sopenharmony_ci SOC_SINGLE("ALC Release Time", M98088_REG_43_SPKALC_COMP, 4, 7, 0), 5028c2ecf20Sopenharmony_ci 5038c2ecf20Sopenharmony_ci SOC_SINGLE("PWR Limiter Threshold", M98088_REG_44_PWRLMT_CFG, 5048c2ecf20Sopenharmony_ci 4, 15, 0), 5058c2ecf20Sopenharmony_ci SOC_SINGLE("PWR Limiter Weight", M98088_REG_44_PWRLMT_CFG, 0, 7, 0), 5068c2ecf20Sopenharmony_ci SOC_SINGLE("PWR Limiter Time1", M98088_REG_45_PWRLMT_TIME, 0, 15, 0), 5078c2ecf20Sopenharmony_ci SOC_SINGLE("PWR Limiter Time2", M98088_REG_45_PWRLMT_TIME, 4, 15, 0), 5088c2ecf20Sopenharmony_ci 5098c2ecf20Sopenharmony_ci SOC_SINGLE("THD Limiter Threshold", M98088_REG_46_THDLMT_CFG, 4, 15, 0), 5108c2ecf20Sopenharmony_ci SOC_SINGLE("THD Limiter Time", M98088_REG_46_THDLMT_CFG, 0, 7, 0), 5118c2ecf20Sopenharmony_ci}; 5128c2ecf20Sopenharmony_ci 5138c2ecf20Sopenharmony_ci/* Left speaker mixer switch */ 5148c2ecf20Sopenharmony_cistatic const struct snd_kcontrol_new max98088_left_speaker_mixer_controls[] = { 5158c2ecf20Sopenharmony_ci SOC_DAPM_SINGLE("Left DAC1 Switch", M98088_REG_2B_MIX_SPK_LEFT, 0, 1, 0), 5168c2ecf20Sopenharmony_ci SOC_DAPM_SINGLE("Right DAC1 Switch", M98088_REG_2B_MIX_SPK_LEFT, 7, 1, 0), 5178c2ecf20Sopenharmony_ci SOC_DAPM_SINGLE("Left DAC2 Switch", M98088_REG_2B_MIX_SPK_LEFT, 0, 1, 0), 5188c2ecf20Sopenharmony_ci SOC_DAPM_SINGLE("Right DAC2 Switch", M98088_REG_2B_MIX_SPK_LEFT, 7, 1, 0), 5198c2ecf20Sopenharmony_ci SOC_DAPM_SINGLE("MIC1 Switch", M98088_REG_2B_MIX_SPK_LEFT, 5, 1, 0), 5208c2ecf20Sopenharmony_ci SOC_DAPM_SINGLE("MIC2 Switch", M98088_REG_2B_MIX_SPK_LEFT, 6, 1, 0), 5218c2ecf20Sopenharmony_ci SOC_DAPM_SINGLE("INA1 Switch", M98088_REG_2B_MIX_SPK_LEFT, 1, 1, 0), 5228c2ecf20Sopenharmony_ci SOC_DAPM_SINGLE("INA2 Switch", M98088_REG_2B_MIX_SPK_LEFT, 2, 1, 0), 5238c2ecf20Sopenharmony_ci SOC_DAPM_SINGLE("INB1 Switch", M98088_REG_2B_MIX_SPK_LEFT, 3, 1, 0), 5248c2ecf20Sopenharmony_ci SOC_DAPM_SINGLE("INB2 Switch", M98088_REG_2B_MIX_SPK_LEFT, 4, 1, 0), 5258c2ecf20Sopenharmony_ci}; 5268c2ecf20Sopenharmony_ci 5278c2ecf20Sopenharmony_ci/* Right speaker mixer switch */ 5288c2ecf20Sopenharmony_cistatic const struct snd_kcontrol_new max98088_right_speaker_mixer_controls[] = { 5298c2ecf20Sopenharmony_ci SOC_DAPM_SINGLE("Left DAC1 Switch", M98088_REG_2C_MIX_SPK_RIGHT, 7, 1, 0), 5308c2ecf20Sopenharmony_ci SOC_DAPM_SINGLE("Right DAC1 Switch", M98088_REG_2C_MIX_SPK_RIGHT, 0, 1, 0), 5318c2ecf20Sopenharmony_ci SOC_DAPM_SINGLE("Left DAC2 Switch", M98088_REG_2C_MIX_SPK_RIGHT, 7, 1, 0), 5328c2ecf20Sopenharmony_ci SOC_DAPM_SINGLE("Right DAC2 Switch", M98088_REG_2C_MIX_SPK_RIGHT, 0, 1, 0), 5338c2ecf20Sopenharmony_ci SOC_DAPM_SINGLE("MIC1 Switch", M98088_REG_2C_MIX_SPK_RIGHT, 5, 1, 0), 5348c2ecf20Sopenharmony_ci SOC_DAPM_SINGLE("MIC2 Switch", M98088_REG_2C_MIX_SPK_RIGHT, 6, 1, 0), 5358c2ecf20Sopenharmony_ci SOC_DAPM_SINGLE("INA1 Switch", M98088_REG_2C_MIX_SPK_RIGHT, 1, 1, 0), 5368c2ecf20Sopenharmony_ci SOC_DAPM_SINGLE("INA2 Switch", M98088_REG_2C_MIX_SPK_RIGHT, 2, 1, 0), 5378c2ecf20Sopenharmony_ci SOC_DAPM_SINGLE("INB1 Switch", M98088_REG_2C_MIX_SPK_RIGHT, 3, 1, 0), 5388c2ecf20Sopenharmony_ci SOC_DAPM_SINGLE("INB2 Switch", M98088_REG_2C_MIX_SPK_RIGHT, 4, 1, 0), 5398c2ecf20Sopenharmony_ci}; 5408c2ecf20Sopenharmony_ci 5418c2ecf20Sopenharmony_ci/* Left headphone mixer switch */ 5428c2ecf20Sopenharmony_cistatic const struct snd_kcontrol_new max98088_left_hp_mixer_controls[] = { 5438c2ecf20Sopenharmony_ci SOC_DAPM_SINGLE("Left DAC1 Switch", M98088_REG_25_MIX_HP_LEFT, 0, 1, 0), 5448c2ecf20Sopenharmony_ci SOC_DAPM_SINGLE("Right DAC1 Switch", M98088_REG_25_MIX_HP_LEFT, 7, 1, 0), 5458c2ecf20Sopenharmony_ci SOC_DAPM_SINGLE("Left DAC2 Switch", M98088_REG_25_MIX_HP_LEFT, 0, 1, 0), 5468c2ecf20Sopenharmony_ci SOC_DAPM_SINGLE("Right DAC2 Switch", M98088_REG_25_MIX_HP_LEFT, 7, 1, 0), 5478c2ecf20Sopenharmony_ci SOC_DAPM_SINGLE("MIC1 Switch", M98088_REG_25_MIX_HP_LEFT, 5, 1, 0), 5488c2ecf20Sopenharmony_ci SOC_DAPM_SINGLE("MIC2 Switch", M98088_REG_25_MIX_HP_LEFT, 6, 1, 0), 5498c2ecf20Sopenharmony_ci SOC_DAPM_SINGLE("INA1 Switch", M98088_REG_25_MIX_HP_LEFT, 1, 1, 0), 5508c2ecf20Sopenharmony_ci SOC_DAPM_SINGLE("INA2 Switch", M98088_REG_25_MIX_HP_LEFT, 2, 1, 0), 5518c2ecf20Sopenharmony_ci SOC_DAPM_SINGLE("INB1 Switch", M98088_REG_25_MIX_HP_LEFT, 3, 1, 0), 5528c2ecf20Sopenharmony_ci SOC_DAPM_SINGLE("INB2 Switch", M98088_REG_25_MIX_HP_LEFT, 4, 1, 0), 5538c2ecf20Sopenharmony_ci}; 5548c2ecf20Sopenharmony_ci 5558c2ecf20Sopenharmony_ci/* Right headphone mixer switch */ 5568c2ecf20Sopenharmony_cistatic const struct snd_kcontrol_new max98088_right_hp_mixer_controls[] = { 5578c2ecf20Sopenharmony_ci SOC_DAPM_SINGLE("Left DAC1 Switch", M98088_REG_26_MIX_HP_RIGHT, 7, 1, 0), 5588c2ecf20Sopenharmony_ci SOC_DAPM_SINGLE("Right DAC1 Switch", M98088_REG_26_MIX_HP_RIGHT, 0, 1, 0), 5598c2ecf20Sopenharmony_ci SOC_DAPM_SINGLE("Left DAC2 Switch", M98088_REG_26_MIX_HP_RIGHT, 7, 1, 0), 5608c2ecf20Sopenharmony_ci SOC_DAPM_SINGLE("Right DAC2 Switch", M98088_REG_26_MIX_HP_RIGHT, 0, 1, 0), 5618c2ecf20Sopenharmony_ci SOC_DAPM_SINGLE("MIC1 Switch", M98088_REG_26_MIX_HP_RIGHT, 5, 1, 0), 5628c2ecf20Sopenharmony_ci SOC_DAPM_SINGLE("MIC2 Switch", M98088_REG_26_MIX_HP_RIGHT, 6, 1, 0), 5638c2ecf20Sopenharmony_ci SOC_DAPM_SINGLE("INA1 Switch", M98088_REG_26_MIX_HP_RIGHT, 1, 1, 0), 5648c2ecf20Sopenharmony_ci SOC_DAPM_SINGLE("INA2 Switch", M98088_REG_26_MIX_HP_RIGHT, 2, 1, 0), 5658c2ecf20Sopenharmony_ci SOC_DAPM_SINGLE("INB1 Switch", M98088_REG_26_MIX_HP_RIGHT, 3, 1, 0), 5668c2ecf20Sopenharmony_ci SOC_DAPM_SINGLE("INB2 Switch", M98088_REG_26_MIX_HP_RIGHT, 4, 1, 0), 5678c2ecf20Sopenharmony_ci}; 5688c2ecf20Sopenharmony_ci 5698c2ecf20Sopenharmony_ci/* Left earpiece/receiver mixer switch */ 5708c2ecf20Sopenharmony_cistatic const struct snd_kcontrol_new max98088_left_rec_mixer_controls[] = { 5718c2ecf20Sopenharmony_ci SOC_DAPM_SINGLE("Left DAC1 Switch", M98088_REG_28_MIX_REC_LEFT, 0, 1, 0), 5728c2ecf20Sopenharmony_ci SOC_DAPM_SINGLE("Right DAC1 Switch", M98088_REG_28_MIX_REC_LEFT, 7, 1, 0), 5738c2ecf20Sopenharmony_ci SOC_DAPM_SINGLE("Left DAC2 Switch", M98088_REG_28_MIX_REC_LEFT, 0, 1, 0), 5748c2ecf20Sopenharmony_ci SOC_DAPM_SINGLE("Right DAC2 Switch", M98088_REG_28_MIX_REC_LEFT, 7, 1, 0), 5758c2ecf20Sopenharmony_ci SOC_DAPM_SINGLE("MIC1 Switch", M98088_REG_28_MIX_REC_LEFT, 5, 1, 0), 5768c2ecf20Sopenharmony_ci SOC_DAPM_SINGLE("MIC2 Switch", M98088_REG_28_MIX_REC_LEFT, 6, 1, 0), 5778c2ecf20Sopenharmony_ci SOC_DAPM_SINGLE("INA1 Switch", M98088_REG_28_MIX_REC_LEFT, 1, 1, 0), 5788c2ecf20Sopenharmony_ci SOC_DAPM_SINGLE("INA2 Switch", M98088_REG_28_MIX_REC_LEFT, 2, 1, 0), 5798c2ecf20Sopenharmony_ci SOC_DAPM_SINGLE("INB1 Switch", M98088_REG_28_MIX_REC_LEFT, 3, 1, 0), 5808c2ecf20Sopenharmony_ci SOC_DAPM_SINGLE("INB2 Switch", M98088_REG_28_MIX_REC_LEFT, 4, 1, 0), 5818c2ecf20Sopenharmony_ci}; 5828c2ecf20Sopenharmony_ci 5838c2ecf20Sopenharmony_ci/* Right earpiece/receiver mixer switch */ 5848c2ecf20Sopenharmony_cistatic const struct snd_kcontrol_new max98088_right_rec_mixer_controls[] = { 5858c2ecf20Sopenharmony_ci SOC_DAPM_SINGLE("Left DAC1 Switch", M98088_REG_29_MIX_REC_RIGHT, 7, 1, 0), 5868c2ecf20Sopenharmony_ci SOC_DAPM_SINGLE("Right DAC1 Switch", M98088_REG_29_MIX_REC_RIGHT, 0, 1, 0), 5878c2ecf20Sopenharmony_ci SOC_DAPM_SINGLE("Left DAC2 Switch", M98088_REG_29_MIX_REC_RIGHT, 7, 1, 0), 5888c2ecf20Sopenharmony_ci SOC_DAPM_SINGLE("Right DAC2 Switch", M98088_REG_29_MIX_REC_RIGHT, 0, 1, 0), 5898c2ecf20Sopenharmony_ci SOC_DAPM_SINGLE("MIC1 Switch", M98088_REG_29_MIX_REC_RIGHT, 5, 1, 0), 5908c2ecf20Sopenharmony_ci SOC_DAPM_SINGLE("MIC2 Switch", M98088_REG_29_MIX_REC_RIGHT, 6, 1, 0), 5918c2ecf20Sopenharmony_ci SOC_DAPM_SINGLE("INA1 Switch", M98088_REG_29_MIX_REC_RIGHT, 1, 1, 0), 5928c2ecf20Sopenharmony_ci SOC_DAPM_SINGLE("INA2 Switch", M98088_REG_29_MIX_REC_RIGHT, 2, 1, 0), 5938c2ecf20Sopenharmony_ci SOC_DAPM_SINGLE("INB1 Switch", M98088_REG_29_MIX_REC_RIGHT, 3, 1, 0), 5948c2ecf20Sopenharmony_ci SOC_DAPM_SINGLE("INB2 Switch", M98088_REG_29_MIX_REC_RIGHT, 4, 1, 0), 5958c2ecf20Sopenharmony_ci}; 5968c2ecf20Sopenharmony_ci 5978c2ecf20Sopenharmony_ci/* Left ADC mixer switch */ 5988c2ecf20Sopenharmony_cistatic const struct snd_kcontrol_new max98088_left_ADC_mixer_controls[] = { 5998c2ecf20Sopenharmony_ci SOC_DAPM_SINGLE("MIC1 Switch", M98088_REG_23_MIX_ADC_LEFT, 7, 1, 0), 6008c2ecf20Sopenharmony_ci SOC_DAPM_SINGLE("MIC2 Switch", M98088_REG_23_MIX_ADC_LEFT, 6, 1, 0), 6018c2ecf20Sopenharmony_ci SOC_DAPM_SINGLE("INA1 Switch", M98088_REG_23_MIX_ADC_LEFT, 3, 1, 0), 6028c2ecf20Sopenharmony_ci SOC_DAPM_SINGLE("INA2 Switch", M98088_REG_23_MIX_ADC_LEFT, 2, 1, 0), 6038c2ecf20Sopenharmony_ci SOC_DAPM_SINGLE("INB1 Switch", M98088_REG_23_MIX_ADC_LEFT, 1, 1, 0), 6048c2ecf20Sopenharmony_ci SOC_DAPM_SINGLE("INB2 Switch", M98088_REG_23_MIX_ADC_LEFT, 0, 1, 0), 6058c2ecf20Sopenharmony_ci}; 6068c2ecf20Sopenharmony_ci 6078c2ecf20Sopenharmony_ci/* Right ADC mixer switch */ 6088c2ecf20Sopenharmony_cistatic const struct snd_kcontrol_new max98088_right_ADC_mixer_controls[] = { 6098c2ecf20Sopenharmony_ci SOC_DAPM_SINGLE("MIC1 Switch", M98088_REG_24_MIX_ADC_RIGHT, 7, 1, 0), 6108c2ecf20Sopenharmony_ci SOC_DAPM_SINGLE("MIC2 Switch", M98088_REG_24_MIX_ADC_RIGHT, 6, 1, 0), 6118c2ecf20Sopenharmony_ci SOC_DAPM_SINGLE("INA1 Switch", M98088_REG_24_MIX_ADC_RIGHT, 3, 1, 0), 6128c2ecf20Sopenharmony_ci SOC_DAPM_SINGLE("INA2 Switch", M98088_REG_24_MIX_ADC_RIGHT, 2, 1, 0), 6138c2ecf20Sopenharmony_ci SOC_DAPM_SINGLE("INB1 Switch", M98088_REG_24_MIX_ADC_RIGHT, 1, 1, 0), 6148c2ecf20Sopenharmony_ci SOC_DAPM_SINGLE("INB2 Switch", M98088_REG_24_MIX_ADC_RIGHT, 0, 1, 0), 6158c2ecf20Sopenharmony_ci}; 6168c2ecf20Sopenharmony_ci 6178c2ecf20Sopenharmony_cistatic int max98088_mic_event(struct snd_soc_dapm_widget *w, 6188c2ecf20Sopenharmony_ci struct snd_kcontrol *kcontrol, int event) 6198c2ecf20Sopenharmony_ci{ 6208c2ecf20Sopenharmony_ci struct snd_soc_component *component = snd_soc_dapm_to_component(w->dapm); 6218c2ecf20Sopenharmony_ci struct max98088_priv *max98088 = snd_soc_component_get_drvdata(component); 6228c2ecf20Sopenharmony_ci 6238c2ecf20Sopenharmony_ci switch (event) { 6248c2ecf20Sopenharmony_ci case SND_SOC_DAPM_POST_PMU: 6258c2ecf20Sopenharmony_ci if (w->reg == M98088_REG_35_LVL_MIC1) { 6268c2ecf20Sopenharmony_ci snd_soc_component_update_bits(component, w->reg, M98088_MICPRE_MASK, 6278c2ecf20Sopenharmony_ci (1+max98088->mic1pre)<<M98088_MICPRE_SHIFT); 6288c2ecf20Sopenharmony_ci } else { 6298c2ecf20Sopenharmony_ci snd_soc_component_update_bits(component, w->reg, M98088_MICPRE_MASK, 6308c2ecf20Sopenharmony_ci (1+max98088->mic2pre)<<M98088_MICPRE_SHIFT); 6318c2ecf20Sopenharmony_ci } 6328c2ecf20Sopenharmony_ci break; 6338c2ecf20Sopenharmony_ci case SND_SOC_DAPM_POST_PMD: 6348c2ecf20Sopenharmony_ci snd_soc_component_update_bits(component, w->reg, M98088_MICPRE_MASK, 0); 6358c2ecf20Sopenharmony_ci break; 6368c2ecf20Sopenharmony_ci default: 6378c2ecf20Sopenharmony_ci return -EINVAL; 6388c2ecf20Sopenharmony_ci } 6398c2ecf20Sopenharmony_ci 6408c2ecf20Sopenharmony_ci return 0; 6418c2ecf20Sopenharmony_ci} 6428c2ecf20Sopenharmony_ci 6438c2ecf20Sopenharmony_ci/* 6448c2ecf20Sopenharmony_ci * The line inputs are 2-channel stereo inputs with the left 6458c2ecf20Sopenharmony_ci * and right channels sharing a common PGA power control signal. 6468c2ecf20Sopenharmony_ci */ 6478c2ecf20Sopenharmony_cistatic int max98088_line_pga(struct snd_soc_dapm_widget *w, 6488c2ecf20Sopenharmony_ci int event, int line, u8 channel) 6498c2ecf20Sopenharmony_ci{ 6508c2ecf20Sopenharmony_ci struct snd_soc_component *component = snd_soc_dapm_to_component(w->dapm); 6518c2ecf20Sopenharmony_ci struct max98088_priv *max98088 = snd_soc_component_get_drvdata(component); 6528c2ecf20Sopenharmony_ci u8 *state; 6538c2ecf20Sopenharmony_ci 6548c2ecf20Sopenharmony_ci if (WARN_ON(!(channel == 1 || channel == 2))) 6558c2ecf20Sopenharmony_ci return -EINVAL; 6568c2ecf20Sopenharmony_ci 6578c2ecf20Sopenharmony_ci switch (line) { 6588c2ecf20Sopenharmony_ci case LINE_INA: 6598c2ecf20Sopenharmony_ci state = &max98088->ina_state; 6608c2ecf20Sopenharmony_ci break; 6618c2ecf20Sopenharmony_ci case LINE_INB: 6628c2ecf20Sopenharmony_ci state = &max98088->inb_state; 6638c2ecf20Sopenharmony_ci break; 6648c2ecf20Sopenharmony_ci default: 6658c2ecf20Sopenharmony_ci return -EINVAL; 6668c2ecf20Sopenharmony_ci } 6678c2ecf20Sopenharmony_ci 6688c2ecf20Sopenharmony_ci switch (event) { 6698c2ecf20Sopenharmony_ci case SND_SOC_DAPM_POST_PMU: 6708c2ecf20Sopenharmony_ci *state |= channel; 6718c2ecf20Sopenharmony_ci snd_soc_component_update_bits(component, w->reg, 6728c2ecf20Sopenharmony_ci (1 << w->shift), (1 << w->shift)); 6738c2ecf20Sopenharmony_ci break; 6748c2ecf20Sopenharmony_ci case SND_SOC_DAPM_POST_PMD: 6758c2ecf20Sopenharmony_ci *state &= ~channel; 6768c2ecf20Sopenharmony_ci if (*state == 0) { 6778c2ecf20Sopenharmony_ci snd_soc_component_update_bits(component, w->reg, 6788c2ecf20Sopenharmony_ci (1 << w->shift), 0); 6798c2ecf20Sopenharmony_ci } 6808c2ecf20Sopenharmony_ci break; 6818c2ecf20Sopenharmony_ci default: 6828c2ecf20Sopenharmony_ci return -EINVAL; 6838c2ecf20Sopenharmony_ci } 6848c2ecf20Sopenharmony_ci 6858c2ecf20Sopenharmony_ci return 0; 6868c2ecf20Sopenharmony_ci} 6878c2ecf20Sopenharmony_ci 6888c2ecf20Sopenharmony_cistatic int max98088_pga_ina1_event(struct snd_soc_dapm_widget *w, 6898c2ecf20Sopenharmony_ci struct snd_kcontrol *k, int event) 6908c2ecf20Sopenharmony_ci{ 6918c2ecf20Sopenharmony_ci return max98088_line_pga(w, event, LINE_INA, 1); 6928c2ecf20Sopenharmony_ci} 6938c2ecf20Sopenharmony_ci 6948c2ecf20Sopenharmony_cistatic int max98088_pga_ina2_event(struct snd_soc_dapm_widget *w, 6958c2ecf20Sopenharmony_ci struct snd_kcontrol *k, int event) 6968c2ecf20Sopenharmony_ci{ 6978c2ecf20Sopenharmony_ci return max98088_line_pga(w, event, LINE_INA, 2); 6988c2ecf20Sopenharmony_ci} 6998c2ecf20Sopenharmony_ci 7008c2ecf20Sopenharmony_cistatic int max98088_pga_inb1_event(struct snd_soc_dapm_widget *w, 7018c2ecf20Sopenharmony_ci struct snd_kcontrol *k, int event) 7028c2ecf20Sopenharmony_ci{ 7038c2ecf20Sopenharmony_ci return max98088_line_pga(w, event, LINE_INB, 1); 7048c2ecf20Sopenharmony_ci} 7058c2ecf20Sopenharmony_ci 7068c2ecf20Sopenharmony_cistatic int max98088_pga_inb2_event(struct snd_soc_dapm_widget *w, 7078c2ecf20Sopenharmony_ci struct snd_kcontrol *k, int event) 7088c2ecf20Sopenharmony_ci{ 7098c2ecf20Sopenharmony_ci return max98088_line_pga(w, event, LINE_INB, 2); 7108c2ecf20Sopenharmony_ci} 7118c2ecf20Sopenharmony_ci 7128c2ecf20Sopenharmony_cistatic const struct snd_soc_dapm_widget max98088_dapm_widgets[] = { 7138c2ecf20Sopenharmony_ci 7148c2ecf20Sopenharmony_ci SND_SOC_DAPM_ADC("ADCL", "HiFi Capture", M98088_REG_4C_PWR_EN_IN, 1, 0), 7158c2ecf20Sopenharmony_ci SND_SOC_DAPM_ADC("ADCR", "HiFi Capture", M98088_REG_4C_PWR_EN_IN, 0, 0), 7168c2ecf20Sopenharmony_ci 7178c2ecf20Sopenharmony_ci SND_SOC_DAPM_DAC("DACL1", "HiFi Playback", 7188c2ecf20Sopenharmony_ci M98088_REG_4D_PWR_EN_OUT, 1, 0), 7198c2ecf20Sopenharmony_ci SND_SOC_DAPM_DAC("DACR1", "HiFi Playback", 7208c2ecf20Sopenharmony_ci M98088_REG_4D_PWR_EN_OUT, 0, 0), 7218c2ecf20Sopenharmony_ci SND_SOC_DAPM_DAC("DACL2", "Aux Playback", 7228c2ecf20Sopenharmony_ci M98088_REG_4D_PWR_EN_OUT, 1, 0), 7238c2ecf20Sopenharmony_ci SND_SOC_DAPM_DAC("DACR2", "Aux Playback", 7248c2ecf20Sopenharmony_ci M98088_REG_4D_PWR_EN_OUT, 0, 0), 7258c2ecf20Sopenharmony_ci 7268c2ecf20Sopenharmony_ci SND_SOC_DAPM_PGA("HP Left Out", M98088_REG_4D_PWR_EN_OUT, 7278c2ecf20Sopenharmony_ci 7, 0, NULL, 0), 7288c2ecf20Sopenharmony_ci SND_SOC_DAPM_PGA("HP Right Out", M98088_REG_4D_PWR_EN_OUT, 7298c2ecf20Sopenharmony_ci 6, 0, NULL, 0), 7308c2ecf20Sopenharmony_ci 7318c2ecf20Sopenharmony_ci SND_SOC_DAPM_PGA("SPK Left Out", M98088_REG_4D_PWR_EN_OUT, 7328c2ecf20Sopenharmony_ci 5, 0, NULL, 0), 7338c2ecf20Sopenharmony_ci SND_SOC_DAPM_PGA("SPK Right Out", M98088_REG_4D_PWR_EN_OUT, 7348c2ecf20Sopenharmony_ci 4, 0, NULL, 0), 7358c2ecf20Sopenharmony_ci 7368c2ecf20Sopenharmony_ci SND_SOC_DAPM_PGA("REC Left Out", M98088_REG_4D_PWR_EN_OUT, 7378c2ecf20Sopenharmony_ci 3, 0, NULL, 0), 7388c2ecf20Sopenharmony_ci SND_SOC_DAPM_PGA("REC Right Out", M98088_REG_4D_PWR_EN_OUT, 7398c2ecf20Sopenharmony_ci 2, 0, NULL, 0), 7408c2ecf20Sopenharmony_ci 7418c2ecf20Sopenharmony_ci SND_SOC_DAPM_MUX("External MIC", SND_SOC_NOPM, 0, 0, 7428c2ecf20Sopenharmony_ci &max98088_extmic_mux), 7438c2ecf20Sopenharmony_ci 7448c2ecf20Sopenharmony_ci SND_SOC_DAPM_MIXER("Left HP Mixer", SND_SOC_NOPM, 0, 0, 7458c2ecf20Sopenharmony_ci &max98088_left_hp_mixer_controls[0], 7468c2ecf20Sopenharmony_ci ARRAY_SIZE(max98088_left_hp_mixer_controls)), 7478c2ecf20Sopenharmony_ci 7488c2ecf20Sopenharmony_ci SND_SOC_DAPM_MIXER("Right HP Mixer", SND_SOC_NOPM, 0, 0, 7498c2ecf20Sopenharmony_ci &max98088_right_hp_mixer_controls[0], 7508c2ecf20Sopenharmony_ci ARRAY_SIZE(max98088_right_hp_mixer_controls)), 7518c2ecf20Sopenharmony_ci 7528c2ecf20Sopenharmony_ci SND_SOC_DAPM_MIXER("Left SPK Mixer", SND_SOC_NOPM, 0, 0, 7538c2ecf20Sopenharmony_ci &max98088_left_speaker_mixer_controls[0], 7548c2ecf20Sopenharmony_ci ARRAY_SIZE(max98088_left_speaker_mixer_controls)), 7558c2ecf20Sopenharmony_ci 7568c2ecf20Sopenharmony_ci SND_SOC_DAPM_MIXER("Right SPK Mixer", SND_SOC_NOPM, 0, 0, 7578c2ecf20Sopenharmony_ci &max98088_right_speaker_mixer_controls[0], 7588c2ecf20Sopenharmony_ci ARRAY_SIZE(max98088_right_speaker_mixer_controls)), 7598c2ecf20Sopenharmony_ci 7608c2ecf20Sopenharmony_ci SND_SOC_DAPM_MIXER("Left REC Mixer", SND_SOC_NOPM, 0, 0, 7618c2ecf20Sopenharmony_ci &max98088_left_rec_mixer_controls[0], 7628c2ecf20Sopenharmony_ci ARRAY_SIZE(max98088_left_rec_mixer_controls)), 7638c2ecf20Sopenharmony_ci 7648c2ecf20Sopenharmony_ci SND_SOC_DAPM_MIXER("Right REC Mixer", SND_SOC_NOPM, 0, 0, 7658c2ecf20Sopenharmony_ci &max98088_right_rec_mixer_controls[0], 7668c2ecf20Sopenharmony_ci ARRAY_SIZE(max98088_right_rec_mixer_controls)), 7678c2ecf20Sopenharmony_ci 7688c2ecf20Sopenharmony_ci SND_SOC_DAPM_MIXER("Left ADC Mixer", SND_SOC_NOPM, 0, 0, 7698c2ecf20Sopenharmony_ci &max98088_left_ADC_mixer_controls[0], 7708c2ecf20Sopenharmony_ci ARRAY_SIZE(max98088_left_ADC_mixer_controls)), 7718c2ecf20Sopenharmony_ci 7728c2ecf20Sopenharmony_ci SND_SOC_DAPM_MIXER("Right ADC Mixer", SND_SOC_NOPM, 0, 0, 7738c2ecf20Sopenharmony_ci &max98088_right_ADC_mixer_controls[0], 7748c2ecf20Sopenharmony_ci ARRAY_SIZE(max98088_right_ADC_mixer_controls)), 7758c2ecf20Sopenharmony_ci 7768c2ecf20Sopenharmony_ci SND_SOC_DAPM_PGA_E("MIC1 Input", M98088_REG_35_LVL_MIC1, 7778c2ecf20Sopenharmony_ci 5, 0, NULL, 0, max98088_mic_event, 7788c2ecf20Sopenharmony_ci SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_POST_PMD), 7798c2ecf20Sopenharmony_ci 7808c2ecf20Sopenharmony_ci SND_SOC_DAPM_PGA_E("MIC2 Input", M98088_REG_36_LVL_MIC2, 7818c2ecf20Sopenharmony_ci 5, 0, NULL, 0, max98088_mic_event, 7828c2ecf20Sopenharmony_ci SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_POST_PMD), 7838c2ecf20Sopenharmony_ci 7848c2ecf20Sopenharmony_ci SND_SOC_DAPM_PGA_E("INA1 Input", M98088_REG_4C_PWR_EN_IN, 7858c2ecf20Sopenharmony_ci 7, 0, NULL, 0, max98088_pga_ina1_event, 7868c2ecf20Sopenharmony_ci SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_POST_PMD), 7878c2ecf20Sopenharmony_ci 7888c2ecf20Sopenharmony_ci SND_SOC_DAPM_PGA_E("INA2 Input", M98088_REG_4C_PWR_EN_IN, 7898c2ecf20Sopenharmony_ci 7, 0, NULL, 0, max98088_pga_ina2_event, 7908c2ecf20Sopenharmony_ci SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_POST_PMD), 7918c2ecf20Sopenharmony_ci 7928c2ecf20Sopenharmony_ci SND_SOC_DAPM_PGA_E("INB1 Input", M98088_REG_4C_PWR_EN_IN, 7938c2ecf20Sopenharmony_ci 6, 0, NULL, 0, max98088_pga_inb1_event, 7948c2ecf20Sopenharmony_ci SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_POST_PMD), 7958c2ecf20Sopenharmony_ci 7968c2ecf20Sopenharmony_ci SND_SOC_DAPM_PGA_E("INB2 Input", M98088_REG_4C_PWR_EN_IN, 7978c2ecf20Sopenharmony_ci 6, 0, NULL, 0, max98088_pga_inb2_event, 7988c2ecf20Sopenharmony_ci SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_POST_PMD), 7998c2ecf20Sopenharmony_ci 8008c2ecf20Sopenharmony_ci SND_SOC_DAPM_MICBIAS("MICBIAS", M98088_REG_4C_PWR_EN_IN, 3, 0), 8018c2ecf20Sopenharmony_ci 8028c2ecf20Sopenharmony_ci SND_SOC_DAPM_OUTPUT("HPL"), 8038c2ecf20Sopenharmony_ci SND_SOC_DAPM_OUTPUT("HPR"), 8048c2ecf20Sopenharmony_ci SND_SOC_DAPM_OUTPUT("SPKL"), 8058c2ecf20Sopenharmony_ci SND_SOC_DAPM_OUTPUT("SPKR"), 8068c2ecf20Sopenharmony_ci SND_SOC_DAPM_OUTPUT("RECL"), 8078c2ecf20Sopenharmony_ci SND_SOC_DAPM_OUTPUT("RECR"), 8088c2ecf20Sopenharmony_ci 8098c2ecf20Sopenharmony_ci SND_SOC_DAPM_INPUT("MIC1"), 8108c2ecf20Sopenharmony_ci SND_SOC_DAPM_INPUT("MIC2"), 8118c2ecf20Sopenharmony_ci SND_SOC_DAPM_INPUT("INA1"), 8128c2ecf20Sopenharmony_ci SND_SOC_DAPM_INPUT("INA2"), 8138c2ecf20Sopenharmony_ci SND_SOC_DAPM_INPUT("INB1"), 8148c2ecf20Sopenharmony_ci SND_SOC_DAPM_INPUT("INB2"), 8158c2ecf20Sopenharmony_ci}; 8168c2ecf20Sopenharmony_ci 8178c2ecf20Sopenharmony_cistatic const struct snd_soc_dapm_route max98088_audio_map[] = { 8188c2ecf20Sopenharmony_ci /* Left headphone output mixer */ 8198c2ecf20Sopenharmony_ci {"Left HP Mixer", "Left DAC1 Switch", "DACL1"}, 8208c2ecf20Sopenharmony_ci {"Left HP Mixer", "Left DAC2 Switch", "DACL2"}, 8218c2ecf20Sopenharmony_ci {"Left HP Mixer", "Right DAC1 Switch", "DACR1"}, 8228c2ecf20Sopenharmony_ci {"Left HP Mixer", "Right DAC2 Switch", "DACR2"}, 8238c2ecf20Sopenharmony_ci {"Left HP Mixer", "MIC1 Switch", "MIC1 Input"}, 8248c2ecf20Sopenharmony_ci {"Left HP Mixer", "MIC2 Switch", "MIC2 Input"}, 8258c2ecf20Sopenharmony_ci {"Left HP Mixer", "INA1 Switch", "INA1 Input"}, 8268c2ecf20Sopenharmony_ci {"Left HP Mixer", "INA2 Switch", "INA2 Input"}, 8278c2ecf20Sopenharmony_ci {"Left HP Mixer", "INB1 Switch", "INB1 Input"}, 8288c2ecf20Sopenharmony_ci {"Left HP Mixer", "INB2 Switch", "INB2 Input"}, 8298c2ecf20Sopenharmony_ci 8308c2ecf20Sopenharmony_ci /* Right headphone output mixer */ 8318c2ecf20Sopenharmony_ci {"Right HP Mixer", "Left DAC1 Switch", "DACL1"}, 8328c2ecf20Sopenharmony_ci {"Right HP Mixer", "Left DAC2 Switch", "DACL2" }, 8338c2ecf20Sopenharmony_ci {"Right HP Mixer", "Right DAC1 Switch", "DACR1"}, 8348c2ecf20Sopenharmony_ci {"Right HP Mixer", "Right DAC2 Switch", "DACR2"}, 8358c2ecf20Sopenharmony_ci {"Right HP Mixer", "MIC1 Switch", "MIC1 Input"}, 8368c2ecf20Sopenharmony_ci {"Right HP Mixer", "MIC2 Switch", "MIC2 Input"}, 8378c2ecf20Sopenharmony_ci {"Right HP Mixer", "INA1 Switch", "INA1 Input"}, 8388c2ecf20Sopenharmony_ci {"Right HP Mixer", "INA2 Switch", "INA2 Input"}, 8398c2ecf20Sopenharmony_ci {"Right HP Mixer", "INB1 Switch", "INB1 Input"}, 8408c2ecf20Sopenharmony_ci {"Right HP Mixer", "INB2 Switch", "INB2 Input"}, 8418c2ecf20Sopenharmony_ci 8428c2ecf20Sopenharmony_ci /* Left speaker output mixer */ 8438c2ecf20Sopenharmony_ci {"Left SPK Mixer", "Left DAC1 Switch", "DACL1"}, 8448c2ecf20Sopenharmony_ci {"Left SPK Mixer", "Left DAC2 Switch", "DACL2"}, 8458c2ecf20Sopenharmony_ci {"Left SPK Mixer", "Right DAC1 Switch", "DACR1"}, 8468c2ecf20Sopenharmony_ci {"Left SPK Mixer", "Right DAC2 Switch", "DACR2"}, 8478c2ecf20Sopenharmony_ci {"Left SPK Mixer", "MIC1 Switch", "MIC1 Input"}, 8488c2ecf20Sopenharmony_ci {"Left SPK Mixer", "MIC2 Switch", "MIC2 Input"}, 8498c2ecf20Sopenharmony_ci {"Left SPK Mixer", "INA1 Switch", "INA1 Input"}, 8508c2ecf20Sopenharmony_ci {"Left SPK Mixer", "INA2 Switch", "INA2 Input"}, 8518c2ecf20Sopenharmony_ci {"Left SPK Mixer", "INB1 Switch", "INB1 Input"}, 8528c2ecf20Sopenharmony_ci {"Left SPK Mixer", "INB2 Switch", "INB2 Input"}, 8538c2ecf20Sopenharmony_ci 8548c2ecf20Sopenharmony_ci /* Right speaker output mixer */ 8558c2ecf20Sopenharmony_ci {"Right SPK Mixer", "Left DAC1 Switch", "DACL1"}, 8568c2ecf20Sopenharmony_ci {"Right SPK Mixer", "Left DAC2 Switch", "DACL2"}, 8578c2ecf20Sopenharmony_ci {"Right SPK Mixer", "Right DAC1 Switch", "DACR1"}, 8588c2ecf20Sopenharmony_ci {"Right SPK Mixer", "Right DAC2 Switch", "DACR2"}, 8598c2ecf20Sopenharmony_ci {"Right SPK Mixer", "MIC1 Switch", "MIC1 Input"}, 8608c2ecf20Sopenharmony_ci {"Right SPK Mixer", "MIC2 Switch", "MIC2 Input"}, 8618c2ecf20Sopenharmony_ci {"Right SPK Mixer", "INA1 Switch", "INA1 Input"}, 8628c2ecf20Sopenharmony_ci {"Right SPK Mixer", "INA2 Switch", "INA2 Input"}, 8638c2ecf20Sopenharmony_ci {"Right SPK Mixer", "INB1 Switch", "INB1 Input"}, 8648c2ecf20Sopenharmony_ci {"Right SPK Mixer", "INB2 Switch", "INB2 Input"}, 8658c2ecf20Sopenharmony_ci 8668c2ecf20Sopenharmony_ci /* Earpiece/Receiver output mixer */ 8678c2ecf20Sopenharmony_ci {"Left REC Mixer", "Left DAC1 Switch", "DACL1"}, 8688c2ecf20Sopenharmony_ci {"Left REC Mixer", "Left DAC2 Switch", "DACL2"}, 8698c2ecf20Sopenharmony_ci {"Left REC Mixer", "Right DAC1 Switch", "DACR1"}, 8708c2ecf20Sopenharmony_ci {"Left REC Mixer", "Right DAC2 Switch", "DACR2"}, 8718c2ecf20Sopenharmony_ci {"Left REC Mixer", "MIC1 Switch", "MIC1 Input"}, 8728c2ecf20Sopenharmony_ci {"Left REC Mixer", "MIC2 Switch", "MIC2 Input"}, 8738c2ecf20Sopenharmony_ci {"Left REC Mixer", "INA1 Switch", "INA1 Input"}, 8748c2ecf20Sopenharmony_ci {"Left REC Mixer", "INA2 Switch", "INA2 Input"}, 8758c2ecf20Sopenharmony_ci {"Left REC Mixer", "INB1 Switch", "INB1 Input"}, 8768c2ecf20Sopenharmony_ci {"Left REC Mixer", "INB2 Switch", "INB2 Input"}, 8778c2ecf20Sopenharmony_ci 8788c2ecf20Sopenharmony_ci /* Earpiece/Receiver output mixer */ 8798c2ecf20Sopenharmony_ci {"Right REC Mixer", "Left DAC1 Switch", "DACL1"}, 8808c2ecf20Sopenharmony_ci {"Right REC Mixer", "Left DAC2 Switch", "DACL2"}, 8818c2ecf20Sopenharmony_ci {"Right REC Mixer", "Right DAC1 Switch", "DACR1"}, 8828c2ecf20Sopenharmony_ci {"Right REC Mixer", "Right DAC2 Switch", "DACR2"}, 8838c2ecf20Sopenharmony_ci {"Right REC Mixer", "MIC1 Switch", "MIC1 Input"}, 8848c2ecf20Sopenharmony_ci {"Right REC Mixer", "MIC2 Switch", "MIC2 Input"}, 8858c2ecf20Sopenharmony_ci {"Right REC Mixer", "INA1 Switch", "INA1 Input"}, 8868c2ecf20Sopenharmony_ci {"Right REC Mixer", "INA2 Switch", "INA2 Input"}, 8878c2ecf20Sopenharmony_ci {"Right REC Mixer", "INB1 Switch", "INB1 Input"}, 8888c2ecf20Sopenharmony_ci {"Right REC Mixer", "INB2 Switch", "INB2 Input"}, 8898c2ecf20Sopenharmony_ci 8908c2ecf20Sopenharmony_ci {"HP Left Out", NULL, "Left HP Mixer"}, 8918c2ecf20Sopenharmony_ci {"HP Right Out", NULL, "Right HP Mixer"}, 8928c2ecf20Sopenharmony_ci {"SPK Left Out", NULL, "Left SPK Mixer"}, 8938c2ecf20Sopenharmony_ci {"SPK Right Out", NULL, "Right SPK Mixer"}, 8948c2ecf20Sopenharmony_ci {"REC Left Out", NULL, "Left REC Mixer"}, 8958c2ecf20Sopenharmony_ci {"REC Right Out", NULL, "Right REC Mixer"}, 8968c2ecf20Sopenharmony_ci 8978c2ecf20Sopenharmony_ci {"HPL", NULL, "HP Left Out"}, 8988c2ecf20Sopenharmony_ci {"HPR", NULL, "HP Right Out"}, 8998c2ecf20Sopenharmony_ci {"SPKL", NULL, "SPK Left Out"}, 9008c2ecf20Sopenharmony_ci {"SPKR", NULL, "SPK Right Out"}, 9018c2ecf20Sopenharmony_ci {"RECL", NULL, "REC Left Out"}, 9028c2ecf20Sopenharmony_ci {"RECR", NULL, "REC Right Out"}, 9038c2ecf20Sopenharmony_ci 9048c2ecf20Sopenharmony_ci /* Left ADC input mixer */ 9058c2ecf20Sopenharmony_ci {"Left ADC Mixer", "MIC1 Switch", "MIC1 Input"}, 9068c2ecf20Sopenharmony_ci {"Left ADC Mixer", "MIC2 Switch", "MIC2 Input"}, 9078c2ecf20Sopenharmony_ci {"Left ADC Mixer", "INA1 Switch", "INA1 Input"}, 9088c2ecf20Sopenharmony_ci {"Left ADC Mixer", "INA2 Switch", "INA2 Input"}, 9098c2ecf20Sopenharmony_ci {"Left ADC Mixer", "INB1 Switch", "INB1 Input"}, 9108c2ecf20Sopenharmony_ci {"Left ADC Mixer", "INB2 Switch", "INB2 Input"}, 9118c2ecf20Sopenharmony_ci 9128c2ecf20Sopenharmony_ci /* Right ADC input mixer */ 9138c2ecf20Sopenharmony_ci {"Right ADC Mixer", "MIC1 Switch", "MIC1 Input"}, 9148c2ecf20Sopenharmony_ci {"Right ADC Mixer", "MIC2 Switch", "MIC2 Input"}, 9158c2ecf20Sopenharmony_ci {"Right ADC Mixer", "INA1 Switch", "INA1 Input"}, 9168c2ecf20Sopenharmony_ci {"Right ADC Mixer", "INA2 Switch", "INA2 Input"}, 9178c2ecf20Sopenharmony_ci {"Right ADC Mixer", "INB1 Switch", "INB1 Input"}, 9188c2ecf20Sopenharmony_ci {"Right ADC Mixer", "INB2 Switch", "INB2 Input"}, 9198c2ecf20Sopenharmony_ci 9208c2ecf20Sopenharmony_ci /* Inputs */ 9218c2ecf20Sopenharmony_ci {"ADCL", NULL, "Left ADC Mixer"}, 9228c2ecf20Sopenharmony_ci {"ADCR", NULL, "Right ADC Mixer"}, 9238c2ecf20Sopenharmony_ci {"INA1 Input", NULL, "INA1"}, 9248c2ecf20Sopenharmony_ci {"INA2 Input", NULL, "INA2"}, 9258c2ecf20Sopenharmony_ci {"INB1 Input", NULL, "INB1"}, 9268c2ecf20Sopenharmony_ci {"INB2 Input", NULL, "INB2"}, 9278c2ecf20Sopenharmony_ci {"MIC1 Input", NULL, "MIC1"}, 9288c2ecf20Sopenharmony_ci {"MIC2 Input", NULL, "MIC2"}, 9298c2ecf20Sopenharmony_ci}; 9308c2ecf20Sopenharmony_ci 9318c2ecf20Sopenharmony_ci/* codec mclk clock divider coefficients */ 9328c2ecf20Sopenharmony_cistatic const struct { 9338c2ecf20Sopenharmony_ci u32 rate; 9348c2ecf20Sopenharmony_ci u8 sr; 9358c2ecf20Sopenharmony_ci} rate_table[] = { 9368c2ecf20Sopenharmony_ci {8000, 0x10}, 9378c2ecf20Sopenharmony_ci {11025, 0x20}, 9388c2ecf20Sopenharmony_ci {16000, 0x30}, 9398c2ecf20Sopenharmony_ci {22050, 0x40}, 9408c2ecf20Sopenharmony_ci {24000, 0x50}, 9418c2ecf20Sopenharmony_ci {32000, 0x60}, 9428c2ecf20Sopenharmony_ci {44100, 0x70}, 9438c2ecf20Sopenharmony_ci {48000, 0x80}, 9448c2ecf20Sopenharmony_ci {88200, 0x90}, 9458c2ecf20Sopenharmony_ci {96000, 0xA0}, 9468c2ecf20Sopenharmony_ci}; 9478c2ecf20Sopenharmony_ci 9488c2ecf20Sopenharmony_cistatic inline int rate_value(int rate, u8 *value) 9498c2ecf20Sopenharmony_ci{ 9508c2ecf20Sopenharmony_ci int i; 9518c2ecf20Sopenharmony_ci 9528c2ecf20Sopenharmony_ci for (i = 0; i < ARRAY_SIZE(rate_table); i++) { 9538c2ecf20Sopenharmony_ci if (rate_table[i].rate >= rate) { 9548c2ecf20Sopenharmony_ci *value = rate_table[i].sr; 9558c2ecf20Sopenharmony_ci return 0; 9568c2ecf20Sopenharmony_ci } 9578c2ecf20Sopenharmony_ci } 9588c2ecf20Sopenharmony_ci *value = rate_table[0].sr; 9598c2ecf20Sopenharmony_ci return -EINVAL; 9608c2ecf20Sopenharmony_ci} 9618c2ecf20Sopenharmony_ci 9628c2ecf20Sopenharmony_cistatic int max98088_dai1_hw_params(struct snd_pcm_substream *substream, 9638c2ecf20Sopenharmony_ci struct snd_pcm_hw_params *params, 9648c2ecf20Sopenharmony_ci struct snd_soc_dai *dai) 9658c2ecf20Sopenharmony_ci{ 9668c2ecf20Sopenharmony_ci struct snd_soc_component *component = dai->component; 9678c2ecf20Sopenharmony_ci struct max98088_priv *max98088 = snd_soc_component_get_drvdata(component); 9688c2ecf20Sopenharmony_ci struct max98088_cdata *cdata; 9698c2ecf20Sopenharmony_ci unsigned long long ni; 9708c2ecf20Sopenharmony_ci unsigned int rate; 9718c2ecf20Sopenharmony_ci u8 regval; 9728c2ecf20Sopenharmony_ci 9738c2ecf20Sopenharmony_ci cdata = &max98088->dai[0]; 9748c2ecf20Sopenharmony_ci 9758c2ecf20Sopenharmony_ci rate = params_rate(params); 9768c2ecf20Sopenharmony_ci 9778c2ecf20Sopenharmony_ci switch (params_width(params)) { 9788c2ecf20Sopenharmony_ci case 16: 9798c2ecf20Sopenharmony_ci snd_soc_component_update_bits(component, M98088_REG_14_DAI1_FORMAT, 9808c2ecf20Sopenharmony_ci M98088_DAI_WS, 0); 9818c2ecf20Sopenharmony_ci break; 9828c2ecf20Sopenharmony_ci case 24: 9838c2ecf20Sopenharmony_ci snd_soc_component_update_bits(component, M98088_REG_14_DAI1_FORMAT, 9848c2ecf20Sopenharmony_ci M98088_DAI_WS, M98088_DAI_WS); 9858c2ecf20Sopenharmony_ci break; 9868c2ecf20Sopenharmony_ci default: 9878c2ecf20Sopenharmony_ci return -EINVAL; 9888c2ecf20Sopenharmony_ci } 9898c2ecf20Sopenharmony_ci 9908c2ecf20Sopenharmony_ci snd_soc_component_update_bits(component, M98088_REG_51_PWR_SYS, M98088_SHDNRUN, 0); 9918c2ecf20Sopenharmony_ci 9928c2ecf20Sopenharmony_ci if (rate_value(rate, ®val)) 9938c2ecf20Sopenharmony_ci return -EINVAL; 9948c2ecf20Sopenharmony_ci 9958c2ecf20Sopenharmony_ci snd_soc_component_update_bits(component, M98088_REG_11_DAI1_CLKMODE, 9968c2ecf20Sopenharmony_ci M98088_CLKMODE_MASK, regval); 9978c2ecf20Sopenharmony_ci cdata->rate = rate; 9988c2ecf20Sopenharmony_ci 9998c2ecf20Sopenharmony_ci /* Configure NI when operating as master */ 10008c2ecf20Sopenharmony_ci if (snd_soc_component_read(component, M98088_REG_14_DAI1_FORMAT) 10018c2ecf20Sopenharmony_ci & M98088_DAI_MAS) { 10028c2ecf20Sopenharmony_ci unsigned long pclk; 10038c2ecf20Sopenharmony_ci 10048c2ecf20Sopenharmony_ci if (max98088->sysclk == 0) { 10058c2ecf20Sopenharmony_ci dev_err(component->dev, "Invalid system clock frequency\n"); 10068c2ecf20Sopenharmony_ci return -EINVAL; 10078c2ecf20Sopenharmony_ci } 10088c2ecf20Sopenharmony_ci ni = 65536ULL * (rate < 50000 ? 96ULL : 48ULL) 10098c2ecf20Sopenharmony_ci * (unsigned long long int)rate; 10108c2ecf20Sopenharmony_ci pclk = DIV_ROUND_CLOSEST(max98088->sysclk, max98088->mclk_prescaler); 10118c2ecf20Sopenharmony_ci ni = DIV_ROUND_CLOSEST_ULL(ni, pclk); 10128c2ecf20Sopenharmony_ci snd_soc_component_write(component, M98088_REG_12_DAI1_CLKCFG_HI, 10138c2ecf20Sopenharmony_ci (ni >> 8) & 0x7F); 10148c2ecf20Sopenharmony_ci snd_soc_component_write(component, M98088_REG_13_DAI1_CLKCFG_LO, 10158c2ecf20Sopenharmony_ci ni & 0xFF); 10168c2ecf20Sopenharmony_ci } 10178c2ecf20Sopenharmony_ci 10188c2ecf20Sopenharmony_ci /* Update sample rate mode */ 10198c2ecf20Sopenharmony_ci if (rate < 50000) 10208c2ecf20Sopenharmony_ci snd_soc_component_update_bits(component, M98088_REG_18_DAI1_FILTERS, 10218c2ecf20Sopenharmony_ci M98088_DAI_DHF, 0); 10228c2ecf20Sopenharmony_ci else 10238c2ecf20Sopenharmony_ci snd_soc_component_update_bits(component, M98088_REG_18_DAI1_FILTERS, 10248c2ecf20Sopenharmony_ci M98088_DAI_DHF, M98088_DAI_DHF); 10258c2ecf20Sopenharmony_ci 10268c2ecf20Sopenharmony_ci snd_soc_component_update_bits(component, M98088_REG_51_PWR_SYS, M98088_SHDNRUN, 10278c2ecf20Sopenharmony_ci M98088_SHDNRUN); 10288c2ecf20Sopenharmony_ci 10298c2ecf20Sopenharmony_ci return 0; 10308c2ecf20Sopenharmony_ci} 10318c2ecf20Sopenharmony_ci 10328c2ecf20Sopenharmony_cistatic int max98088_dai2_hw_params(struct snd_pcm_substream *substream, 10338c2ecf20Sopenharmony_ci struct snd_pcm_hw_params *params, 10348c2ecf20Sopenharmony_ci struct snd_soc_dai *dai) 10358c2ecf20Sopenharmony_ci{ 10368c2ecf20Sopenharmony_ci struct snd_soc_component *component = dai->component; 10378c2ecf20Sopenharmony_ci struct max98088_priv *max98088 = snd_soc_component_get_drvdata(component); 10388c2ecf20Sopenharmony_ci struct max98088_cdata *cdata; 10398c2ecf20Sopenharmony_ci unsigned long long ni; 10408c2ecf20Sopenharmony_ci unsigned int rate; 10418c2ecf20Sopenharmony_ci u8 regval; 10428c2ecf20Sopenharmony_ci 10438c2ecf20Sopenharmony_ci cdata = &max98088->dai[1]; 10448c2ecf20Sopenharmony_ci 10458c2ecf20Sopenharmony_ci rate = params_rate(params); 10468c2ecf20Sopenharmony_ci 10478c2ecf20Sopenharmony_ci switch (params_width(params)) { 10488c2ecf20Sopenharmony_ci case 16: 10498c2ecf20Sopenharmony_ci snd_soc_component_update_bits(component, M98088_REG_1C_DAI2_FORMAT, 10508c2ecf20Sopenharmony_ci M98088_DAI_WS, 0); 10518c2ecf20Sopenharmony_ci break; 10528c2ecf20Sopenharmony_ci case 24: 10538c2ecf20Sopenharmony_ci snd_soc_component_update_bits(component, M98088_REG_1C_DAI2_FORMAT, 10548c2ecf20Sopenharmony_ci M98088_DAI_WS, M98088_DAI_WS); 10558c2ecf20Sopenharmony_ci break; 10568c2ecf20Sopenharmony_ci default: 10578c2ecf20Sopenharmony_ci return -EINVAL; 10588c2ecf20Sopenharmony_ci } 10598c2ecf20Sopenharmony_ci 10608c2ecf20Sopenharmony_ci snd_soc_component_update_bits(component, M98088_REG_51_PWR_SYS, M98088_SHDNRUN, 0); 10618c2ecf20Sopenharmony_ci 10628c2ecf20Sopenharmony_ci if (rate_value(rate, ®val)) 10638c2ecf20Sopenharmony_ci return -EINVAL; 10648c2ecf20Sopenharmony_ci 10658c2ecf20Sopenharmony_ci snd_soc_component_update_bits(component, M98088_REG_19_DAI2_CLKMODE, 10668c2ecf20Sopenharmony_ci M98088_CLKMODE_MASK, regval); 10678c2ecf20Sopenharmony_ci cdata->rate = rate; 10688c2ecf20Sopenharmony_ci 10698c2ecf20Sopenharmony_ci /* Configure NI when operating as master */ 10708c2ecf20Sopenharmony_ci if (snd_soc_component_read(component, M98088_REG_1C_DAI2_FORMAT) 10718c2ecf20Sopenharmony_ci & M98088_DAI_MAS) { 10728c2ecf20Sopenharmony_ci unsigned long pclk; 10738c2ecf20Sopenharmony_ci 10748c2ecf20Sopenharmony_ci if (max98088->sysclk == 0) { 10758c2ecf20Sopenharmony_ci dev_err(component->dev, "Invalid system clock frequency\n"); 10768c2ecf20Sopenharmony_ci return -EINVAL; 10778c2ecf20Sopenharmony_ci } 10788c2ecf20Sopenharmony_ci ni = 65536ULL * (rate < 50000 ? 96ULL : 48ULL) 10798c2ecf20Sopenharmony_ci * (unsigned long long int)rate; 10808c2ecf20Sopenharmony_ci pclk = DIV_ROUND_CLOSEST(max98088->sysclk, max98088->mclk_prescaler); 10818c2ecf20Sopenharmony_ci ni = DIV_ROUND_CLOSEST_ULL(ni, pclk); 10828c2ecf20Sopenharmony_ci snd_soc_component_write(component, M98088_REG_1A_DAI2_CLKCFG_HI, 10838c2ecf20Sopenharmony_ci (ni >> 8) & 0x7F); 10848c2ecf20Sopenharmony_ci snd_soc_component_write(component, M98088_REG_1B_DAI2_CLKCFG_LO, 10858c2ecf20Sopenharmony_ci ni & 0xFF); 10868c2ecf20Sopenharmony_ci } 10878c2ecf20Sopenharmony_ci 10888c2ecf20Sopenharmony_ci /* Update sample rate mode */ 10898c2ecf20Sopenharmony_ci if (rate < 50000) 10908c2ecf20Sopenharmony_ci snd_soc_component_update_bits(component, M98088_REG_20_DAI2_FILTERS, 10918c2ecf20Sopenharmony_ci M98088_DAI_DHF, 0); 10928c2ecf20Sopenharmony_ci else 10938c2ecf20Sopenharmony_ci snd_soc_component_update_bits(component, M98088_REG_20_DAI2_FILTERS, 10948c2ecf20Sopenharmony_ci M98088_DAI_DHF, M98088_DAI_DHF); 10958c2ecf20Sopenharmony_ci 10968c2ecf20Sopenharmony_ci snd_soc_component_update_bits(component, M98088_REG_51_PWR_SYS, M98088_SHDNRUN, 10978c2ecf20Sopenharmony_ci M98088_SHDNRUN); 10988c2ecf20Sopenharmony_ci 10998c2ecf20Sopenharmony_ci return 0; 11008c2ecf20Sopenharmony_ci} 11018c2ecf20Sopenharmony_ci 11028c2ecf20Sopenharmony_cistatic int max98088_dai_set_sysclk(struct snd_soc_dai *dai, 11038c2ecf20Sopenharmony_ci int clk_id, unsigned int freq, int dir) 11048c2ecf20Sopenharmony_ci{ 11058c2ecf20Sopenharmony_ci struct snd_soc_component *component = dai->component; 11068c2ecf20Sopenharmony_ci struct max98088_priv *max98088 = snd_soc_component_get_drvdata(component); 11078c2ecf20Sopenharmony_ci 11088c2ecf20Sopenharmony_ci /* Requested clock frequency is already setup */ 11098c2ecf20Sopenharmony_ci if (freq == max98088->sysclk) 11108c2ecf20Sopenharmony_ci return 0; 11118c2ecf20Sopenharmony_ci 11128c2ecf20Sopenharmony_ci if (!IS_ERR(max98088->mclk)) { 11138c2ecf20Sopenharmony_ci freq = clk_round_rate(max98088->mclk, freq); 11148c2ecf20Sopenharmony_ci clk_set_rate(max98088->mclk, freq); 11158c2ecf20Sopenharmony_ci } 11168c2ecf20Sopenharmony_ci 11178c2ecf20Sopenharmony_ci /* Setup clocks for slave mode, and using the PLL 11188c2ecf20Sopenharmony_ci * PSCLK = 0x01 (when master clk is 10MHz to 20MHz) 11198c2ecf20Sopenharmony_ci * 0x02 (when master clk is 20MHz to 30MHz).. 11208c2ecf20Sopenharmony_ci */ 11218c2ecf20Sopenharmony_ci if ((freq >= 10000000) && (freq < 20000000)) { 11228c2ecf20Sopenharmony_ci snd_soc_component_write(component, M98088_REG_10_SYS_CLK, 0x10); 11238c2ecf20Sopenharmony_ci max98088->mclk_prescaler = 1; 11248c2ecf20Sopenharmony_ci } else if ((freq >= 20000000) && (freq < 30000000)) { 11258c2ecf20Sopenharmony_ci snd_soc_component_write(component, M98088_REG_10_SYS_CLK, 0x20); 11268c2ecf20Sopenharmony_ci max98088->mclk_prescaler = 2; 11278c2ecf20Sopenharmony_ci } else { 11288c2ecf20Sopenharmony_ci dev_err(component->dev, "Invalid master clock frequency\n"); 11298c2ecf20Sopenharmony_ci return -EINVAL; 11308c2ecf20Sopenharmony_ci } 11318c2ecf20Sopenharmony_ci 11328c2ecf20Sopenharmony_ci if (snd_soc_component_read(component, M98088_REG_51_PWR_SYS) & M98088_SHDNRUN) { 11338c2ecf20Sopenharmony_ci snd_soc_component_update_bits(component, M98088_REG_51_PWR_SYS, 11348c2ecf20Sopenharmony_ci M98088_SHDNRUN, 0); 11358c2ecf20Sopenharmony_ci snd_soc_component_update_bits(component, M98088_REG_51_PWR_SYS, 11368c2ecf20Sopenharmony_ci M98088_SHDNRUN, M98088_SHDNRUN); 11378c2ecf20Sopenharmony_ci } 11388c2ecf20Sopenharmony_ci 11398c2ecf20Sopenharmony_ci dev_dbg(dai->dev, "Clock source is %d at %uHz\n", clk_id, freq); 11408c2ecf20Sopenharmony_ci 11418c2ecf20Sopenharmony_ci max98088->sysclk = freq; 11428c2ecf20Sopenharmony_ci return 0; 11438c2ecf20Sopenharmony_ci} 11448c2ecf20Sopenharmony_ci 11458c2ecf20Sopenharmony_cistatic int max98088_dai1_set_fmt(struct snd_soc_dai *codec_dai, 11468c2ecf20Sopenharmony_ci unsigned int fmt) 11478c2ecf20Sopenharmony_ci{ 11488c2ecf20Sopenharmony_ci struct snd_soc_component *component = codec_dai->component; 11498c2ecf20Sopenharmony_ci struct max98088_priv *max98088 = snd_soc_component_get_drvdata(component); 11508c2ecf20Sopenharmony_ci struct max98088_cdata *cdata; 11518c2ecf20Sopenharmony_ci u8 reg15val; 11528c2ecf20Sopenharmony_ci u8 reg14val = 0; 11538c2ecf20Sopenharmony_ci 11548c2ecf20Sopenharmony_ci cdata = &max98088->dai[0]; 11558c2ecf20Sopenharmony_ci 11568c2ecf20Sopenharmony_ci if (fmt != cdata->fmt) { 11578c2ecf20Sopenharmony_ci cdata->fmt = fmt; 11588c2ecf20Sopenharmony_ci 11598c2ecf20Sopenharmony_ci switch (fmt & SND_SOC_DAIFMT_MASTER_MASK) { 11608c2ecf20Sopenharmony_ci case SND_SOC_DAIFMT_CBS_CFS: 11618c2ecf20Sopenharmony_ci /* Slave mode PLL */ 11628c2ecf20Sopenharmony_ci snd_soc_component_write(component, M98088_REG_12_DAI1_CLKCFG_HI, 11638c2ecf20Sopenharmony_ci 0x80); 11648c2ecf20Sopenharmony_ci snd_soc_component_write(component, M98088_REG_13_DAI1_CLKCFG_LO, 11658c2ecf20Sopenharmony_ci 0x00); 11668c2ecf20Sopenharmony_ci break; 11678c2ecf20Sopenharmony_ci case SND_SOC_DAIFMT_CBM_CFM: 11688c2ecf20Sopenharmony_ci /* Set to master mode */ 11698c2ecf20Sopenharmony_ci reg14val |= M98088_DAI_MAS; 11708c2ecf20Sopenharmony_ci break; 11718c2ecf20Sopenharmony_ci case SND_SOC_DAIFMT_CBS_CFM: 11728c2ecf20Sopenharmony_ci case SND_SOC_DAIFMT_CBM_CFS: 11738c2ecf20Sopenharmony_ci default: 11748c2ecf20Sopenharmony_ci dev_err(component->dev, "Clock mode unsupported"); 11758c2ecf20Sopenharmony_ci return -EINVAL; 11768c2ecf20Sopenharmony_ci } 11778c2ecf20Sopenharmony_ci 11788c2ecf20Sopenharmony_ci switch (fmt & SND_SOC_DAIFMT_FORMAT_MASK) { 11798c2ecf20Sopenharmony_ci case SND_SOC_DAIFMT_I2S: 11808c2ecf20Sopenharmony_ci reg14val |= M98088_DAI_DLY; 11818c2ecf20Sopenharmony_ci break; 11828c2ecf20Sopenharmony_ci case SND_SOC_DAIFMT_LEFT_J: 11838c2ecf20Sopenharmony_ci break; 11848c2ecf20Sopenharmony_ci default: 11858c2ecf20Sopenharmony_ci return -EINVAL; 11868c2ecf20Sopenharmony_ci } 11878c2ecf20Sopenharmony_ci 11888c2ecf20Sopenharmony_ci switch (fmt & SND_SOC_DAIFMT_INV_MASK) { 11898c2ecf20Sopenharmony_ci case SND_SOC_DAIFMT_NB_NF: 11908c2ecf20Sopenharmony_ci break; 11918c2ecf20Sopenharmony_ci case SND_SOC_DAIFMT_NB_IF: 11928c2ecf20Sopenharmony_ci reg14val |= M98088_DAI_WCI; 11938c2ecf20Sopenharmony_ci break; 11948c2ecf20Sopenharmony_ci case SND_SOC_DAIFMT_IB_NF: 11958c2ecf20Sopenharmony_ci reg14val |= M98088_DAI_BCI; 11968c2ecf20Sopenharmony_ci break; 11978c2ecf20Sopenharmony_ci case SND_SOC_DAIFMT_IB_IF: 11988c2ecf20Sopenharmony_ci reg14val |= M98088_DAI_BCI|M98088_DAI_WCI; 11998c2ecf20Sopenharmony_ci break; 12008c2ecf20Sopenharmony_ci default: 12018c2ecf20Sopenharmony_ci return -EINVAL; 12028c2ecf20Sopenharmony_ci } 12038c2ecf20Sopenharmony_ci 12048c2ecf20Sopenharmony_ci snd_soc_component_update_bits(component, M98088_REG_14_DAI1_FORMAT, 12058c2ecf20Sopenharmony_ci M98088_DAI_MAS | M98088_DAI_DLY | M98088_DAI_BCI | 12068c2ecf20Sopenharmony_ci M98088_DAI_WCI, reg14val); 12078c2ecf20Sopenharmony_ci 12088c2ecf20Sopenharmony_ci reg15val = M98088_DAI_BSEL64; 12098c2ecf20Sopenharmony_ci if (max98088->digmic) 12108c2ecf20Sopenharmony_ci reg15val |= M98088_DAI_OSR64; 12118c2ecf20Sopenharmony_ci snd_soc_component_write(component, M98088_REG_15_DAI1_CLOCK, reg15val); 12128c2ecf20Sopenharmony_ci } 12138c2ecf20Sopenharmony_ci 12148c2ecf20Sopenharmony_ci return 0; 12158c2ecf20Sopenharmony_ci} 12168c2ecf20Sopenharmony_ci 12178c2ecf20Sopenharmony_cistatic int max98088_dai2_set_fmt(struct snd_soc_dai *codec_dai, 12188c2ecf20Sopenharmony_ci unsigned int fmt) 12198c2ecf20Sopenharmony_ci{ 12208c2ecf20Sopenharmony_ci struct snd_soc_component *component = codec_dai->component; 12218c2ecf20Sopenharmony_ci struct max98088_priv *max98088 = snd_soc_component_get_drvdata(component); 12228c2ecf20Sopenharmony_ci struct max98088_cdata *cdata; 12238c2ecf20Sopenharmony_ci u8 reg1Cval = 0; 12248c2ecf20Sopenharmony_ci 12258c2ecf20Sopenharmony_ci cdata = &max98088->dai[1]; 12268c2ecf20Sopenharmony_ci 12278c2ecf20Sopenharmony_ci if (fmt != cdata->fmt) { 12288c2ecf20Sopenharmony_ci cdata->fmt = fmt; 12298c2ecf20Sopenharmony_ci 12308c2ecf20Sopenharmony_ci switch (fmt & SND_SOC_DAIFMT_MASTER_MASK) { 12318c2ecf20Sopenharmony_ci case SND_SOC_DAIFMT_CBS_CFS: 12328c2ecf20Sopenharmony_ci /* Slave mode PLL */ 12338c2ecf20Sopenharmony_ci snd_soc_component_write(component, M98088_REG_1A_DAI2_CLKCFG_HI, 12348c2ecf20Sopenharmony_ci 0x80); 12358c2ecf20Sopenharmony_ci snd_soc_component_write(component, M98088_REG_1B_DAI2_CLKCFG_LO, 12368c2ecf20Sopenharmony_ci 0x00); 12378c2ecf20Sopenharmony_ci break; 12388c2ecf20Sopenharmony_ci case SND_SOC_DAIFMT_CBM_CFM: 12398c2ecf20Sopenharmony_ci /* Set to master mode */ 12408c2ecf20Sopenharmony_ci reg1Cval |= M98088_DAI_MAS; 12418c2ecf20Sopenharmony_ci break; 12428c2ecf20Sopenharmony_ci case SND_SOC_DAIFMT_CBS_CFM: 12438c2ecf20Sopenharmony_ci case SND_SOC_DAIFMT_CBM_CFS: 12448c2ecf20Sopenharmony_ci default: 12458c2ecf20Sopenharmony_ci dev_err(component->dev, "Clock mode unsupported"); 12468c2ecf20Sopenharmony_ci return -EINVAL; 12478c2ecf20Sopenharmony_ci } 12488c2ecf20Sopenharmony_ci 12498c2ecf20Sopenharmony_ci switch (fmt & SND_SOC_DAIFMT_FORMAT_MASK) { 12508c2ecf20Sopenharmony_ci case SND_SOC_DAIFMT_I2S: 12518c2ecf20Sopenharmony_ci reg1Cval |= M98088_DAI_DLY; 12528c2ecf20Sopenharmony_ci break; 12538c2ecf20Sopenharmony_ci case SND_SOC_DAIFMT_LEFT_J: 12548c2ecf20Sopenharmony_ci break; 12558c2ecf20Sopenharmony_ci default: 12568c2ecf20Sopenharmony_ci return -EINVAL; 12578c2ecf20Sopenharmony_ci } 12588c2ecf20Sopenharmony_ci 12598c2ecf20Sopenharmony_ci switch (fmt & SND_SOC_DAIFMT_INV_MASK) { 12608c2ecf20Sopenharmony_ci case SND_SOC_DAIFMT_NB_NF: 12618c2ecf20Sopenharmony_ci break; 12628c2ecf20Sopenharmony_ci case SND_SOC_DAIFMT_NB_IF: 12638c2ecf20Sopenharmony_ci reg1Cval |= M98088_DAI_WCI; 12648c2ecf20Sopenharmony_ci break; 12658c2ecf20Sopenharmony_ci case SND_SOC_DAIFMT_IB_NF: 12668c2ecf20Sopenharmony_ci reg1Cval |= M98088_DAI_BCI; 12678c2ecf20Sopenharmony_ci break; 12688c2ecf20Sopenharmony_ci case SND_SOC_DAIFMT_IB_IF: 12698c2ecf20Sopenharmony_ci reg1Cval |= M98088_DAI_BCI|M98088_DAI_WCI; 12708c2ecf20Sopenharmony_ci break; 12718c2ecf20Sopenharmony_ci default: 12728c2ecf20Sopenharmony_ci return -EINVAL; 12738c2ecf20Sopenharmony_ci } 12748c2ecf20Sopenharmony_ci 12758c2ecf20Sopenharmony_ci snd_soc_component_update_bits(component, M98088_REG_1C_DAI2_FORMAT, 12768c2ecf20Sopenharmony_ci M98088_DAI_MAS | M98088_DAI_DLY | M98088_DAI_BCI | 12778c2ecf20Sopenharmony_ci M98088_DAI_WCI, reg1Cval); 12788c2ecf20Sopenharmony_ci 12798c2ecf20Sopenharmony_ci snd_soc_component_write(component, M98088_REG_1D_DAI2_CLOCK, 12808c2ecf20Sopenharmony_ci M98088_DAI_BSEL64); 12818c2ecf20Sopenharmony_ci } 12828c2ecf20Sopenharmony_ci 12838c2ecf20Sopenharmony_ci return 0; 12848c2ecf20Sopenharmony_ci} 12858c2ecf20Sopenharmony_ci 12868c2ecf20Sopenharmony_cistatic int max98088_dai1_mute(struct snd_soc_dai *codec_dai, int mute, 12878c2ecf20Sopenharmony_ci int direction) 12888c2ecf20Sopenharmony_ci{ 12898c2ecf20Sopenharmony_ci struct snd_soc_component *component = codec_dai->component; 12908c2ecf20Sopenharmony_ci int reg; 12918c2ecf20Sopenharmony_ci 12928c2ecf20Sopenharmony_ci if (mute) 12938c2ecf20Sopenharmony_ci reg = M98088_DAI_MUTE; 12948c2ecf20Sopenharmony_ci else 12958c2ecf20Sopenharmony_ci reg = 0; 12968c2ecf20Sopenharmony_ci 12978c2ecf20Sopenharmony_ci snd_soc_component_update_bits(component, M98088_REG_2F_LVL_DAI1_PLAY, 12988c2ecf20Sopenharmony_ci M98088_DAI_MUTE_MASK, reg); 12998c2ecf20Sopenharmony_ci return 0; 13008c2ecf20Sopenharmony_ci} 13018c2ecf20Sopenharmony_ci 13028c2ecf20Sopenharmony_cistatic int max98088_dai2_mute(struct snd_soc_dai *codec_dai, int mute, 13038c2ecf20Sopenharmony_ci int direction) 13048c2ecf20Sopenharmony_ci{ 13058c2ecf20Sopenharmony_ci struct snd_soc_component *component = codec_dai->component; 13068c2ecf20Sopenharmony_ci int reg; 13078c2ecf20Sopenharmony_ci 13088c2ecf20Sopenharmony_ci if (mute) 13098c2ecf20Sopenharmony_ci reg = M98088_DAI_MUTE; 13108c2ecf20Sopenharmony_ci else 13118c2ecf20Sopenharmony_ci reg = 0; 13128c2ecf20Sopenharmony_ci 13138c2ecf20Sopenharmony_ci snd_soc_component_update_bits(component, M98088_REG_31_LVL_DAI2_PLAY, 13148c2ecf20Sopenharmony_ci M98088_DAI_MUTE_MASK, reg); 13158c2ecf20Sopenharmony_ci return 0; 13168c2ecf20Sopenharmony_ci} 13178c2ecf20Sopenharmony_ci 13188c2ecf20Sopenharmony_cistatic int max98088_set_bias_level(struct snd_soc_component *component, 13198c2ecf20Sopenharmony_ci enum snd_soc_bias_level level) 13208c2ecf20Sopenharmony_ci{ 13218c2ecf20Sopenharmony_ci struct max98088_priv *max98088 = snd_soc_component_get_drvdata(component); 13228c2ecf20Sopenharmony_ci 13238c2ecf20Sopenharmony_ci switch (level) { 13248c2ecf20Sopenharmony_ci case SND_SOC_BIAS_ON: 13258c2ecf20Sopenharmony_ci break; 13268c2ecf20Sopenharmony_ci 13278c2ecf20Sopenharmony_ci case SND_SOC_BIAS_PREPARE: 13288c2ecf20Sopenharmony_ci /* 13298c2ecf20Sopenharmony_ci * SND_SOC_BIAS_PREPARE is called while preparing for a 13308c2ecf20Sopenharmony_ci * transition to ON or away from ON. If current bias_level 13318c2ecf20Sopenharmony_ci * is SND_SOC_BIAS_ON, then it is preparing for a transition 13328c2ecf20Sopenharmony_ci * away from ON. Disable the clock in that case, otherwise 13338c2ecf20Sopenharmony_ci * enable it. 13348c2ecf20Sopenharmony_ci */ 13358c2ecf20Sopenharmony_ci if (!IS_ERR(max98088->mclk)) { 13368c2ecf20Sopenharmony_ci if (snd_soc_component_get_bias_level(component) == 13378c2ecf20Sopenharmony_ci SND_SOC_BIAS_ON) 13388c2ecf20Sopenharmony_ci clk_disable_unprepare(max98088->mclk); 13398c2ecf20Sopenharmony_ci else 13408c2ecf20Sopenharmony_ci clk_prepare_enable(max98088->mclk); 13418c2ecf20Sopenharmony_ci } 13428c2ecf20Sopenharmony_ci break; 13438c2ecf20Sopenharmony_ci 13448c2ecf20Sopenharmony_ci case SND_SOC_BIAS_STANDBY: 13458c2ecf20Sopenharmony_ci if (snd_soc_component_get_bias_level(component) == SND_SOC_BIAS_OFF) 13468c2ecf20Sopenharmony_ci regcache_sync(max98088->regmap); 13478c2ecf20Sopenharmony_ci 13488c2ecf20Sopenharmony_ci snd_soc_component_update_bits(component, M98088_REG_4C_PWR_EN_IN, 13498c2ecf20Sopenharmony_ci M98088_MBEN, M98088_MBEN); 13508c2ecf20Sopenharmony_ci break; 13518c2ecf20Sopenharmony_ci 13528c2ecf20Sopenharmony_ci case SND_SOC_BIAS_OFF: 13538c2ecf20Sopenharmony_ci snd_soc_component_update_bits(component, M98088_REG_4C_PWR_EN_IN, 13548c2ecf20Sopenharmony_ci M98088_MBEN, 0); 13558c2ecf20Sopenharmony_ci regcache_mark_dirty(max98088->regmap); 13568c2ecf20Sopenharmony_ci break; 13578c2ecf20Sopenharmony_ci } 13588c2ecf20Sopenharmony_ci return 0; 13598c2ecf20Sopenharmony_ci} 13608c2ecf20Sopenharmony_ci 13618c2ecf20Sopenharmony_ci#define MAX98088_RATES SNDRV_PCM_RATE_8000_96000 13628c2ecf20Sopenharmony_ci#define MAX98088_FORMATS (SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S24_LE) 13638c2ecf20Sopenharmony_ci 13648c2ecf20Sopenharmony_cistatic const struct snd_soc_dai_ops max98088_dai1_ops = { 13658c2ecf20Sopenharmony_ci .set_sysclk = max98088_dai_set_sysclk, 13668c2ecf20Sopenharmony_ci .set_fmt = max98088_dai1_set_fmt, 13678c2ecf20Sopenharmony_ci .hw_params = max98088_dai1_hw_params, 13688c2ecf20Sopenharmony_ci .mute_stream = max98088_dai1_mute, 13698c2ecf20Sopenharmony_ci .no_capture_mute = 1, 13708c2ecf20Sopenharmony_ci}; 13718c2ecf20Sopenharmony_ci 13728c2ecf20Sopenharmony_cistatic const struct snd_soc_dai_ops max98088_dai2_ops = { 13738c2ecf20Sopenharmony_ci .set_sysclk = max98088_dai_set_sysclk, 13748c2ecf20Sopenharmony_ci .set_fmt = max98088_dai2_set_fmt, 13758c2ecf20Sopenharmony_ci .hw_params = max98088_dai2_hw_params, 13768c2ecf20Sopenharmony_ci .mute_stream = max98088_dai2_mute, 13778c2ecf20Sopenharmony_ci .no_capture_mute = 1, 13788c2ecf20Sopenharmony_ci}; 13798c2ecf20Sopenharmony_ci 13808c2ecf20Sopenharmony_cistatic struct snd_soc_dai_driver max98088_dai[] = { 13818c2ecf20Sopenharmony_ci{ 13828c2ecf20Sopenharmony_ci .name = "HiFi", 13838c2ecf20Sopenharmony_ci .playback = { 13848c2ecf20Sopenharmony_ci .stream_name = "HiFi Playback", 13858c2ecf20Sopenharmony_ci .channels_min = 1, 13868c2ecf20Sopenharmony_ci .channels_max = 2, 13878c2ecf20Sopenharmony_ci .rates = MAX98088_RATES, 13888c2ecf20Sopenharmony_ci .formats = MAX98088_FORMATS, 13898c2ecf20Sopenharmony_ci }, 13908c2ecf20Sopenharmony_ci .capture = { 13918c2ecf20Sopenharmony_ci .stream_name = "HiFi Capture", 13928c2ecf20Sopenharmony_ci .channels_min = 1, 13938c2ecf20Sopenharmony_ci .channels_max = 2, 13948c2ecf20Sopenharmony_ci .rates = MAX98088_RATES, 13958c2ecf20Sopenharmony_ci .formats = MAX98088_FORMATS, 13968c2ecf20Sopenharmony_ci }, 13978c2ecf20Sopenharmony_ci .ops = &max98088_dai1_ops, 13988c2ecf20Sopenharmony_ci}, 13998c2ecf20Sopenharmony_ci{ 14008c2ecf20Sopenharmony_ci .name = "Aux", 14018c2ecf20Sopenharmony_ci .playback = { 14028c2ecf20Sopenharmony_ci .stream_name = "Aux Playback", 14038c2ecf20Sopenharmony_ci .channels_min = 1, 14048c2ecf20Sopenharmony_ci .channels_max = 2, 14058c2ecf20Sopenharmony_ci .rates = MAX98088_RATES, 14068c2ecf20Sopenharmony_ci .formats = MAX98088_FORMATS, 14078c2ecf20Sopenharmony_ci }, 14088c2ecf20Sopenharmony_ci .ops = &max98088_dai2_ops, 14098c2ecf20Sopenharmony_ci} 14108c2ecf20Sopenharmony_ci}; 14118c2ecf20Sopenharmony_ci 14128c2ecf20Sopenharmony_cistatic const char *eq_mode_name[] = {"EQ1 Mode", "EQ2 Mode"}; 14138c2ecf20Sopenharmony_ci 14148c2ecf20Sopenharmony_cistatic int max98088_get_channel(struct snd_soc_component *component, const char *name) 14158c2ecf20Sopenharmony_ci{ 14168c2ecf20Sopenharmony_ci int ret; 14178c2ecf20Sopenharmony_ci 14188c2ecf20Sopenharmony_ci ret = match_string(eq_mode_name, ARRAY_SIZE(eq_mode_name), name); 14198c2ecf20Sopenharmony_ci if (ret < 0) 14208c2ecf20Sopenharmony_ci dev_err(component->dev, "Bad EQ channel name '%s'\n", name); 14218c2ecf20Sopenharmony_ci return ret; 14228c2ecf20Sopenharmony_ci} 14238c2ecf20Sopenharmony_ci 14248c2ecf20Sopenharmony_cistatic void max98088_setup_eq1(struct snd_soc_component *component) 14258c2ecf20Sopenharmony_ci{ 14268c2ecf20Sopenharmony_ci struct max98088_priv *max98088 = snd_soc_component_get_drvdata(component); 14278c2ecf20Sopenharmony_ci struct max98088_pdata *pdata = max98088->pdata; 14288c2ecf20Sopenharmony_ci struct max98088_eq_cfg *coef_set; 14298c2ecf20Sopenharmony_ci int best, best_val, save, i, sel, fs; 14308c2ecf20Sopenharmony_ci struct max98088_cdata *cdata; 14318c2ecf20Sopenharmony_ci 14328c2ecf20Sopenharmony_ci cdata = &max98088->dai[0]; 14338c2ecf20Sopenharmony_ci 14348c2ecf20Sopenharmony_ci if (!pdata || !max98088->eq_textcnt) 14358c2ecf20Sopenharmony_ci return; 14368c2ecf20Sopenharmony_ci 14378c2ecf20Sopenharmony_ci /* Find the selected configuration with nearest sample rate */ 14388c2ecf20Sopenharmony_ci fs = cdata->rate; 14398c2ecf20Sopenharmony_ci sel = cdata->eq_sel; 14408c2ecf20Sopenharmony_ci 14418c2ecf20Sopenharmony_ci best = 0; 14428c2ecf20Sopenharmony_ci best_val = INT_MAX; 14438c2ecf20Sopenharmony_ci for (i = 0; i < pdata->eq_cfgcnt; i++) { 14448c2ecf20Sopenharmony_ci if (strcmp(pdata->eq_cfg[i].name, max98088->eq_texts[sel]) == 0 && 14458c2ecf20Sopenharmony_ci abs(pdata->eq_cfg[i].rate - fs) < best_val) { 14468c2ecf20Sopenharmony_ci best = i; 14478c2ecf20Sopenharmony_ci best_val = abs(pdata->eq_cfg[i].rate - fs); 14488c2ecf20Sopenharmony_ci } 14498c2ecf20Sopenharmony_ci } 14508c2ecf20Sopenharmony_ci 14518c2ecf20Sopenharmony_ci dev_dbg(component->dev, "Selected %s/%dHz for %dHz sample rate\n", 14528c2ecf20Sopenharmony_ci pdata->eq_cfg[best].name, 14538c2ecf20Sopenharmony_ci pdata->eq_cfg[best].rate, fs); 14548c2ecf20Sopenharmony_ci 14558c2ecf20Sopenharmony_ci /* Disable EQ while configuring, and save current on/off state */ 14568c2ecf20Sopenharmony_ci save = snd_soc_component_read(component, M98088_REG_49_CFG_LEVEL); 14578c2ecf20Sopenharmony_ci snd_soc_component_update_bits(component, M98088_REG_49_CFG_LEVEL, M98088_EQ1EN, 0); 14588c2ecf20Sopenharmony_ci 14598c2ecf20Sopenharmony_ci coef_set = &pdata->eq_cfg[sel]; 14608c2ecf20Sopenharmony_ci 14618c2ecf20Sopenharmony_ci m98088_eq_band(component, 0, 0, coef_set->band1); 14628c2ecf20Sopenharmony_ci m98088_eq_band(component, 0, 1, coef_set->band2); 14638c2ecf20Sopenharmony_ci m98088_eq_band(component, 0, 2, coef_set->band3); 14648c2ecf20Sopenharmony_ci m98088_eq_band(component, 0, 3, coef_set->band4); 14658c2ecf20Sopenharmony_ci m98088_eq_band(component, 0, 4, coef_set->band5); 14668c2ecf20Sopenharmony_ci 14678c2ecf20Sopenharmony_ci /* Restore the original on/off state */ 14688c2ecf20Sopenharmony_ci snd_soc_component_update_bits(component, M98088_REG_49_CFG_LEVEL, M98088_EQ1EN, save); 14698c2ecf20Sopenharmony_ci} 14708c2ecf20Sopenharmony_ci 14718c2ecf20Sopenharmony_cistatic void max98088_setup_eq2(struct snd_soc_component *component) 14728c2ecf20Sopenharmony_ci{ 14738c2ecf20Sopenharmony_ci struct max98088_priv *max98088 = snd_soc_component_get_drvdata(component); 14748c2ecf20Sopenharmony_ci struct max98088_pdata *pdata = max98088->pdata; 14758c2ecf20Sopenharmony_ci struct max98088_eq_cfg *coef_set; 14768c2ecf20Sopenharmony_ci int best, best_val, save, i, sel, fs; 14778c2ecf20Sopenharmony_ci struct max98088_cdata *cdata; 14788c2ecf20Sopenharmony_ci 14798c2ecf20Sopenharmony_ci cdata = &max98088->dai[1]; 14808c2ecf20Sopenharmony_ci 14818c2ecf20Sopenharmony_ci if (!pdata || !max98088->eq_textcnt) 14828c2ecf20Sopenharmony_ci return; 14838c2ecf20Sopenharmony_ci 14848c2ecf20Sopenharmony_ci /* Find the selected configuration with nearest sample rate */ 14858c2ecf20Sopenharmony_ci fs = cdata->rate; 14868c2ecf20Sopenharmony_ci 14878c2ecf20Sopenharmony_ci sel = cdata->eq_sel; 14888c2ecf20Sopenharmony_ci best = 0; 14898c2ecf20Sopenharmony_ci best_val = INT_MAX; 14908c2ecf20Sopenharmony_ci for (i = 0; i < pdata->eq_cfgcnt; i++) { 14918c2ecf20Sopenharmony_ci if (strcmp(pdata->eq_cfg[i].name, max98088->eq_texts[sel]) == 0 && 14928c2ecf20Sopenharmony_ci abs(pdata->eq_cfg[i].rate - fs) < best_val) { 14938c2ecf20Sopenharmony_ci best = i; 14948c2ecf20Sopenharmony_ci best_val = abs(pdata->eq_cfg[i].rate - fs); 14958c2ecf20Sopenharmony_ci } 14968c2ecf20Sopenharmony_ci } 14978c2ecf20Sopenharmony_ci 14988c2ecf20Sopenharmony_ci dev_dbg(component->dev, "Selected %s/%dHz for %dHz sample rate\n", 14998c2ecf20Sopenharmony_ci pdata->eq_cfg[best].name, 15008c2ecf20Sopenharmony_ci pdata->eq_cfg[best].rate, fs); 15018c2ecf20Sopenharmony_ci 15028c2ecf20Sopenharmony_ci /* Disable EQ while configuring, and save current on/off state */ 15038c2ecf20Sopenharmony_ci save = snd_soc_component_read(component, M98088_REG_49_CFG_LEVEL); 15048c2ecf20Sopenharmony_ci snd_soc_component_update_bits(component, M98088_REG_49_CFG_LEVEL, M98088_EQ2EN, 0); 15058c2ecf20Sopenharmony_ci 15068c2ecf20Sopenharmony_ci coef_set = &pdata->eq_cfg[sel]; 15078c2ecf20Sopenharmony_ci 15088c2ecf20Sopenharmony_ci m98088_eq_band(component, 1, 0, coef_set->band1); 15098c2ecf20Sopenharmony_ci m98088_eq_band(component, 1, 1, coef_set->band2); 15108c2ecf20Sopenharmony_ci m98088_eq_band(component, 1, 2, coef_set->band3); 15118c2ecf20Sopenharmony_ci m98088_eq_band(component, 1, 3, coef_set->band4); 15128c2ecf20Sopenharmony_ci m98088_eq_band(component, 1, 4, coef_set->band5); 15138c2ecf20Sopenharmony_ci 15148c2ecf20Sopenharmony_ci /* Restore the original on/off state */ 15158c2ecf20Sopenharmony_ci snd_soc_component_update_bits(component, M98088_REG_49_CFG_LEVEL, M98088_EQ2EN, 15168c2ecf20Sopenharmony_ci save); 15178c2ecf20Sopenharmony_ci} 15188c2ecf20Sopenharmony_ci 15198c2ecf20Sopenharmony_cistatic int max98088_put_eq_enum(struct snd_kcontrol *kcontrol, 15208c2ecf20Sopenharmony_ci struct snd_ctl_elem_value *ucontrol) 15218c2ecf20Sopenharmony_ci{ 15228c2ecf20Sopenharmony_ci struct snd_soc_component *component = snd_soc_kcontrol_component(kcontrol); 15238c2ecf20Sopenharmony_ci struct max98088_priv *max98088 = snd_soc_component_get_drvdata(component); 15248c2ecf20Sopenharmony_ci struct max98088_pdata *pdata = max98088->pdata; 15258c2ecf20Sopenharmony_ci int channel = max98088_get_channel(component, kcontrol->id.name); 15268c2ecf20Sopenharmony_ci struct max98088_cdata *cdata; 15278c2ecf20Sopenharmony_ci int sel = ucontrol->value.enumerated.item[0]; 15288c2ecf20Sopenharmony_ci 15298c2ecf20Sopenharmony_ci if (channel < 0) 15308c2ecf20Sopenharmony_ci return channel; 15318c2ecf20Sopenharmony_ci 15328c2ecf20Sopenharmony_ci cdata = &max98088->dai[channel]; 15338c2ecf20Sopenharmony_ci 15348c2ecf20Sopenharmony_ci if (sel >= pdata->eq_cfgcnt) 15358c2ecf20Sopenharmony_ci return -EINVAL; 15368c2ecf20Sopenharmony_ci 15378c2ecf20Sopenharmony_ci cdata->eq_sel = sel; 15388c2ecf20Sopenharmony_ci 15398c2ecf20Sopenharmony_ci switch (channel) { 15408c2ecf20Sopenharmony_ci case 0: 15418c2ecf20Sopenharmony_ci max98088_setup_eq1(component); 15428c2ecf20Sopenharmony_ci break; 15438c2ecf20Sopenharmony_ci case 1: 15448c2ecf20Sopenharmony_ci max98088_setup_eq2(component); 15458c2ecf20Sopenharmony_ci break; 15468c2ecf20Sopenharmony_ci } 15478c2ecf20Sopenharmony_ci 15488c2ecf20Sopenharmony_ci return 0; 15498c2ecf20Sopenharmony_ci} 15508c2ecf20Sopenharmony_ci 15518c2ecf20Sopenharmony_cistatic int max98088_get_eq_enum(struct snd_kcontrol *kcontrol, 15528c2ecf20Sopenharmony_ci struct snd_ctl_elem_value *ucontrol) 15538c2ecf20Sopenharmony_ci{ 15548c2ecf20Sopenharmony_ci struct snd_soc_component *component = snd_soc_kcontrol_component(kcontrol); 15558c2ecf20Sopenharmony_ci struct max98088_priv *max98088 = snd_soc_component_get_drvdata(component); 15568c2ecf20Sopenharmony_ci int channel = max98088_get_channel(component, kcontrol->id.name); 15578c2ecf20Sopenharmony_ci struct max98088_cdata *cdata; 15588c2ecf20Sopenharmony_ci 15598c2ecf20Sopenharmony_ci if (channel < 0) 15608c2ecf20Sopenharmony_ci return channel; 15618c2ecf20Sopenharmony_ci 15628c2ecf20Sopenharmony_ci cdata = &max98088->dai[channel]; 15638c2ecf20Sopenharmony_ci ucontrol->value.enumerated.item[0] = cdata->eq_sel; 15648c2ecf20Sopenharmony_ci return 0; 15658c2ecf20Sopenharmony_ci} 15668c2ecf20Sopenharmony_ci 15678c2ecf20Sopenharmony_cistatic void max98088_handle_eq_pdata(struct snd_soc_component *component) 15688c2ecf20Sopenharmony_ci{ 15698c2ecf20Sopenharmony_ci struct max98088_priv *max98088 = snd_soc_component_get_drvdata(component); 15708c2ecf20Sopenharmony_ci struct max98088_pdata *pdata = max98088->pdata; 15718c2ecf20Sopenharmony_ci struct max98088_eq_cfg *cfg; 15728c2ecf20Sopenharmony_ci unsigned int cfgcnt; 15738c2ecf20Sopenharmony_ci int i, j; 15748c2ecf20Sopenharmony_ci const char **t; 15758c2ecf20Sopenharmony_ci int ret; 15768c2ecf20Sopenharmony_ci struct snd_kcontrol_new controls[] = { 15778c2ecf20Sopenharmony_ci SOC_ENUM_EXT((char *)eq_mode_name[0], 15788c2ecf20Sopenharmony_ci max98088->eq_enum, 15798c2ecf20Sopenharmony_ci max98088_get_eq_enum, 15808c2ecf20Sopenharmony_ci max98088_put_eq_enum), 15818c2ecf20Sopenharmony_ci SOC_ENUM_EXT((char *)eq_mode_name[1], 15828c2ecf20Sopenharmony_ci max98088->eq_enum, 15838c2ecf20Sopenharmony_ci max98088_get_eq_enum, 15848c2ecf20Sopenharmony_ci max98088_put_eq_enum), 15858c2ecf20Sopenharmony_ci }; 15868c2ecf20Sopenharmony_ci BUILD_BUG_ON(ARRAY_SIZE(controls) != ARRAY_SIZE(eq_mode_name)); 15878c2ecf20Sopenharmony_ci 15888c2ecf20Sopenharmony_ci cfg = pdata->eq_cfg; 15898c2ecf20Sopenharmony_ci cfgcnt = pdata->eq_cfgcnt; 15908c2ecf20Sopenharmony_ci 15918c2ecf20Sopenharmony_ci /* Setup an array of texts for the equalizer enum. 15928c2ecf20Sopenharmony_ci * This is based on Mark Brown's equalizer driver code. 15938c2ecf20Sopenharmony_ci */ 15948c2ecf20Sopenharmony_ci max98088->eq_textcnt = 0; 15958c2ecf20Sopenharmony_ci max98088->eq_texts = NULL; 15968c2ecf20Sopenharmony_ci for (i = 0; i < cfgcnt; i++) { 15978c2ecf20Sopenharmony_ci for (j = 0; j < max98088->eq_textcnt; j++) { 15988c2ecf20Sopenharmony_ci if (strcmp(cfg[i].name, max98088->eq_texts[j]) == 0) 15998c2ecf20Sopenharmony_ci break; 16008c2ecf20Sopenharmony_ci } 16018c2ecf20Sopenharmony_ci 16028c2ecf20Sopenharmony_ci if (j != max98088->eq_textcnt) 16038c2ecf20Sopenharmony_ci continue; 16048c2ecf20Sopenharmony_ci 16058c2ecf20Sopenharmony_ci /* Expand the array */ 16068c2ecf20Sopenharmony_ci t = krealloc(max98088->eq_texts, 16078c2ecf20Sopenharmony_ci sizeof(char *) * (max98088->eq_textcnt + 1), 16088c2ecf20Sopenharmony_ci GFP_KERNEL); 16098c2ecf20Sopenharmony_ci if (t == NULL) 16108c2ecf20Sopenharmony_ci continue; 16118c2ecf20Sopenharmony_ci 16128c2ecf20Sopenharmony_ci /* Store the new entry */ 16138c2ecf20Sopenharmony_ci t[max98088->eq_textcnt] = cfg[i].name; 16148c2ecf20Sopenharmony_ci max98088->eq_textcnt++; 16158c2ecf20Sopenharmony_ci max98088->eq_texts = t; 16168c2ecf20Sopenharmony_ci } 16178c2ecf20Sopenharmony_ci 16188c2ecf20Sopenharmony_ci /* Now point the soc_enum to .texts array items */ 16198c2ecf20Sopenharmony_ci max98088->eq_enum.texts = max98088->eq_texts; 16208c2ecf20Sopenharmony_ci max98088->eq_enum.items = max98088->eq_textcnt; 16218c2ecf20Sopenharmony_ci 16228c2ecf20Sopenharmony_ci ret = snd_soc_add_component_controls(component, controls, ARRAY_SIZE(controls)); 16238c2ecf20Sopenharmony_ci if (ret != 0) 16248c2ecf20Sopenharmony_ci dev_err(component->dev, "Failed to add EQ control: %d\n", ret); 16258c2ecf20Sopenharmony_ci} 16268c2ecf20Sopenharmony_ci 16278c2ecf20Sopenharmony_cistatic void max98088_handle_pdata(struct snd_soc_component *component) 16288c2ecf20Sopenharmony_ci{ 16298c2ecf20Sopenharmony_ci struct max98088_priv *max98088 = snd_soc_component_get_drvdata(component); 16308c2ecf20Sopenharmony_ci struct max98088_pdata *pdata = max98088->pdata; 16318c2ecf20Sopenharmony_ci u8 regval = 0; 16328c2ecf20Sopenharmony_ci 16338c2ecf20Sopenharmony_ci if (!pdata) { 16348c2ecf20Sopenharmony_ci dev_dbg(component->dev, "No platform data\n"); 16358c2ecf20Sopenharmony_ci return; 16368c2ecf20Sopenharmony_ci } 16378c2ecf20Sopenharmony_ci 16388c2ecf20Sopenharmony_ci /* Configure mic for analog/digital mic mode */ 16398c2ecf20Sopenharmony_ci if (pdata->digmic_left_mode) 16408c2ecf20Sopenharmony_ci regval |= M98088_DIGMIC_L; 16418c2ecf20Sopenharmony_ci 16428c2ecf20Sopenharmony_ci if (pdata->digmic_right_mode) 16438c2ecf20Sopenharmony_ci regval |= M98088_DIGMIC_R; 16448c2ecf20Sopenharmony_ci 16458c2ecf20Sopenharmony_ci max98088->digmic = (regval ? 1 : 0); 16468c2ecf20Sopenharmony_ci 16478c2ecf20Sopenharmony_ci snd_soc_component_write(component, M98088_REG_48_CFG_MIC, regval); 16488c2ecf20Sopenharmony_ci 16498c2ecf20Sopenharmony_ci /* Configure receiver output */ 16508c2ecf20Sopenharmony_ci regval = ((pdata->receiver_mode) ? M98088_REC_LINEMODE : 0); 16518c2ecf20Sopenharmony_ci snd_soc_component_update_bits(component, M98088_REG_2A_MIC_REC_CNTL, 16528c2ecf20Sopenharmony_ci M98088_REC_LINEMODE_MASK, regval); 16538c2ecf20Sopenharmony_ci 16548c2ecf20Sopenharmony_ci /* Configure equalizers */ 16558c2ecf20Sopenharmony_ci if (pdata->eq_cfgcnt) 16568c2ecf20Sopenharmony_ci max98088_handle_eq_pdata(component); 16578c2ecf20Sopenharmony_ci} 16588c2ecf20Sopenharmony_ci 16598c2ecf20Sopenharmony_cistatic int max98088_probe(struct snd_soc_component *component) 16608c2ecf20Sopenharmony_ci{ 16618c2ecf20Sopenharmony_ci struct max98088_priv *max98088 = snd_soc_component_get_drvdata(component); 16628c2ecf20Sopenharmony_ci struct max98088_cdata *cdata; 16638c2ecf20Sopenharmony_ci int ret = 0; 16648c2ecf20Sopenharmony_ci 16658c2ecf20Sopenharmony_ci regcache_mark_dirty(max98088->regmap); 16668c2ecf20Sopenharmony_ci 16678c2ecf20Sopenharmony_ci /* initialize private data */ 16688c2ecf20Sopenharmony_ci 16698c2ecf20Sopenharmony_ci max98088->sysclk = (unsigned)-1; 16708c2ecf20Sopenharmony_ci max98088->eq_textcnt = 0; 16718c2ecf20Sopenharmony_ci 16728c2ecf20Sopenharmony_ci cdata = &max98088->dai[0]; 16738c2ecf20Sopenharmony_ci cdata->rate = (unsigned)-1; 16748c2ecf20Sopenharmony_ci cdata->fmt = (unsigned)-1; 16758c2ecf20Sopenharmony_ci cdata->eq_sel = 0; 16768c2ecf20Sopenharmony_ci 16778c2ecf20Sopenharmony_ci cdata = &max98088->dai[1]; 16788c2ecf20Sopenharmony_ci cdata->rate = (unsigned)-1; 16798c2ecf20Sopenharmony_ci cdata->fmt = (unsigned)-1; 16808c2ecf20Sopenharmony_ci cdata->eq_sel = 0; 16818c2ecf20Sopenharmony_ci 16828c2ecf20Sopenharmony_ci max98088->ina_state = 0; 16838c2ecf20Sopenharmony_ci max98088->inb_state = 0; 16848c2ecf20Sopenharmony_ci max98088->ex_mode = 0; 16858c2ecf20Sopenharmony_ci max98088->digmic = 0; 16868c2ecf20Sopenharmony_ci max98088->mic1pre = 0; 16878c2ecf20Sopenharmony_ci max98088->mic2pre = 0; 16888c2ecf20Sopenharmony_ci 16898c2ecf20Sopenharmony_ci ret = snd_soc_component_read(component, M98088_REG_FF_REV_ID); 16908c2ecf20Sopenharmony_ci if (ret < 0) { 16918c2ecf20Sopenharmony_ci dev_err(component->dev, "Failed to read device revision: %d\n", 16928c2ecf20Sopenharmony_ci ret); 16938c2ecf20Sopenharmony_ci goto err_access; 16948c2ecf20Sopenharmony_ci } 16958c2ecf20Sopenharmony_ci dev_info(component->dev, "revision %c\n", ret - 0x40 + 'A'); 16968c2ecf20Sopenharmony_ci 16978c2ecf20Sopenharmony_ci snd_soc_component_write(component, M98088_REG_51_PWR_SYS, M98088_PWRSV); 16988c2ecf20Sopenharmony_ci 16998c2ecf20Sopenharmony_ci snd_soc_component_write(component, M98088_REG_0F_IRQ_ENABLE, 0x00); 17008c2ecf20Sopenharmony_ci 17018c2ecf20Sopenharmony_ci snd_soc_component_write(component, M98088_REG_22_MIX_DAC, 17028c2ecf20Sopenharmony_ci M98088_DAI1L_TO_DACL|M98088_DAI2L_TO_DACL| 17038c2ecf20Sopenharmony_ci M98088_DAI1R_TO_DACR|M98088_DAI2R_TO_DACR); 17048c2ecf20Sopenharmony_ci 17058c2ecf20Sopenharmony_ci snd_soc_component_write(component, M98088_REG_4E_BIAS_CNTL, 0xF0); 17068c2ecf20Sopenharmony_ci snd_soc_component_write(component, M98088_REG_50_DAC_BIAS2, 0x0F); 17078c2ecf20Sopenharmony_ci 17088c2ecf20Sopenharmony_ci snd_soc_component_write(component, M98088_REG_16_DAI1_IOCFG, 17098c2ecf20Sopenharmony_ci M98088_S1NORMAL|M98088_SDATA); 17108c2ecf20Sopenharmony_ci 17118c2ecf20Sopenharmony_ci snd_soc_component_write(component, M98088_REG_1E_DAI2_IOCFG, 17128c2ecf20Sopenharmony_ci M98088_S2NORMAL|M98088_SDATA); 17138c2ecf20Sopenharmony_ci 17148c2ecf20Sopenharmony_ci max98088_handle_pdata(component); 17158c2ecf20Sopenharmony_ci 17168c2ecf20Sopenharmony_cierr_access: 17178c2ecf20Sopenharmony_ci return ret; 17188c2ecf20Sopenharmony_ci} 17198c2ecf20Sopenharmony_ci 17208c2ecf20Sopenharmony_cistatic void max98088_remove(struct snd_soc_component *component) 17218c2ecf20Sopenharmony_ci{ 17228c2ecf20Sopenharmony_ci struct max98088_priv *max98088 = snd_soc_component_get_drvdata(component); 17238c2ecf20Sopenharmony_ci 17248c2ecf20Sopenharmony_ci kfree(max98088->eq_texts); 17258c2ecf20Sopenharmony_ci} 17268c2ecf20Sopenharmony_ci 17278c2ecf20Sopenharmony_cistatic const struct snd_soc_component_driver soc_component_dev_max98088 = { 17288c2ecf20Sopenharmony_ci .probe = max98088_probe, 17298c2ecf20Sopenharmony_ci .remove = max98088_remove, 17308c2ecf20Sopenharmony_ci .set_bias_level = max98088_set_bias_level, 17318c2ecf20Sopenharmony_ci .controls = max98088_snd_controls, 17328c2ecf20Sopenharmony_ci .num_controls = ARRAY_SIZE(max98088_snd_controls), 17338c2ecf20Sopenharmony_ci .dapm_widgets = max98088_dapm_widgets, 17348c2ecf20Sopenharmony_ci .num_dapm_widgets = ARRAY_SIZE(max98088_dapm_widgets), 17358c2ecf20Sopenharmony_ci .dapm_routes = max98088_audio_map, 17368c2ecf20Sopenharmony_ci .num_dapm_routes = ARRAY_SIZE(max98088_audio_map), 17378c2ecf20Sopenharmony_ci .suspend_bias_off = 1, 17388c2ecf20Sopenharmony_ci .idle_bias_on = 1, 17398c2ecf20Sopenharmony_ci .use_pmdown_time = 1, 17408c2ecf20Sopenharmony_ci .endianness = 1, 17418c2ecf20Sopenharmony_ci .non_legacy_dai_naming = 1, 17428c2ecf20Sopenharmony_ci}; 17438c2ecf20Sopenharmony_ci 17448c2ecf20Sopenharmony_cistatic int max98088_i2c_probe(struct i2c_client *i2c, 17458c2ecf20Sopenharmony_ci const struct i2c_device_id *id) 17468c2ecf20Sopenharmony_ci{ 17478c2ecf20Sopenharmony_ci struct max98088_priv *max98088; 17488c2ecf20Sopenharmony_ci int ret; 17498c2ecf20Sopenharmony_ci 17508c2ecf20Sopenharmony_ci max98088 = devm_kzalloc(&i2c->dev, sizeof(struct max98088_priv), 17518c2ecf20Sopenharmony_ci GFP_KERNEL); 17528c2ecf20Sopenharmony_ci if (max98088 == NULL) 17538c2ecf20Sopenharmony_ci return -ENOMEM; 17548c2ecf20Sopenharmony_ci 17558c2ecf20Sopenharmony_ci max98088->regmap = devm_regmap_init_i2c(i2c, &max98088_regmap); 17568c2ecf20Sopenharmony_ci if (IS_ERR(max98088->regmap)) 17578c2ecf20Sopenharmony_ci return PTR_ERR(max98088->regmap); 17588c2ecf20Sopenharmony_ci 17598c2ecf20Sopenharmony_ci max98088->mclk = devm_clk_get(&i2c->dev, "mclk"); 17608c2ecf20Sopenharmony_ci if (IS_ERR(max98088->mclk)) 17618c2ecf20Sopenharmony_ci if (PTR_ERR(max98088->mclk) == -EPROBE_DEFER) 17628c2ecf20Sopenharmony_ci return PTR_ERR(max98088->mclk); 17638c2ecf20Sopenharmony_ci 17648c2ecf20Sopenharmony_ci max98088->devtype = id->driver_data; 17658c2ecf20Sopenharmony_ci 17668c2ecf20Sopenharmony_ci i2c_set_clientdata(i2c, max98088); 17678c2ecf20Sopenharmony_ci max98088->pdata = i2c->dev.platform_data; 17688c2ecf20Sopenharmony_ci 17698c2ecf20Sopenharmony_ci ret = devm_snd_soc_register_component(&i2c->dev, 17708c2ecf20Sopenharmony_ci &soc_component_dev_max98088, &max98088_dai[0], 2); 17718c2ecf20Sopenharmony_ci return ret; 17728c2ecf20Sopenharmony_ci} 17738c2ecf20Sopenharmony_ci 17748c2ecf20Sopenharmony_cistatic const struct i2c_device_id max98088_i2c_id[] = { 17758c2ecf20Sopenharmony_ci { "max98088", MAX98088 }, 17768c2ecf20Sopenharmony_ci { "max98089", MAX98089 }, 17778c2ecf20Sopenharmony_ci { } 17788c2ecf20Sopenharmony_ci}; 17798c2ecf20Sopenharmony_ciMODULE_DEVICE_TABLE(i2c, max98088_i2c_id); 17808c2ecf20Sopenharmony_ci 17818c2ecf20Sopenharmony_ci#if defined(CONFIG_OF) 17828c2ecf20Sopenharmony_cistatic const struct of_device_id max98088_of_match[] = { 17838c2ecf20Sopenharmony_ci { .compatible = "maxim,max98088" }, 17848c2ecf20Sopenharmony_ci { .compatible = "maxim,max98089" }, 17858c2ecf20Sopenharmony_ci { } 17868c2ecf20Sopenharmony_ci}; 17878c2ecf20Sopenharmony_ciMODULE_DEVICE_TABLE(of, max98088_of_match); 17888c2ecf20Sopenharmony_ci#endif 17898c2ecf20Sopenharmony_ci 17908c2ecf20Sopenharmony_cistatic struct i2c_driver max98088_i2c_driver = { 17918c2ecf20Sopenharmony_ci .driver = { 17928c2ecf20Sopenharmony_ci .name = "max98088", 17938c2ecf20Sopenharmony_ci .of_match_table = of_match_ptr(max98088_of_match), 17948c2ecf20Sopenharmony_ci }, 17958c2ecf20Sopenharmony_ci .probe = max98088_i2c_probe, 17968c2ecf20Sopenharmony_ci .id_table = max98088_i2c_id, 17978c2ecf20Sopenharmony_ci}; 17988c2ecf20Sopenharmony_ci 17998c2ecf20Sopenharmony_cimodule_i2c_driver(max98088_i2c_driver); 18008c2ecf20Sopenharmony_ci 18018c2ecf20Sopenharmony_ciMODULE_DESCRIPTION("ALSA SoC MAX98088 driver"); 18028c2ecf20Sopenharmony_ciMODULE_AUTHOR("Peter Hsiang, Jesse Marroquin"); 18038c2ecf20Sopenharmony_ciMODULE_LICENSE("GPL"); 1804