| // SPDX-License-Identifier: GPL-2.0 |
| /* |
| * ALSA SoC Amlogic t9015c interenl codec driver |
| * |
| * Copyright (C) 2019 Amlogic,inc |
| * |
| */ |
| |
| #include <linux/module.h> |
| #include <linux/moduleparam.h> |
| #include <linux/slab.h> |
| #include <linux/of.h> |
| #include <linux/init.h> |
| #include <linux/i2c.h> |
| #include <linux/regmap.h> |
| #include <linux/amlogic/aml_gpio_consumer.h> |
| |
| #include <sound/initval.h> |
| #include <sound/core.h> |
| #include <sound/pcm.h> |
| #include <sound/pcm_params.h> |
| #include <sound/soc.h> |
| #include <sound/tlv.h> |
| |
| #include "tas5805.h" |
| |
| #define TAS5805M_DRV_NAME "tas5805" |
| |
| #define TAS5805M_RATES (SNDRV_PCM_RATE_8000 | \ |
| SNDRV_PCM_RATE_11025 | \ |
| SNDRV_PCM_RATE_16000 | \ |
| SNDRV_PCM_RATE_22050 | \ |
| SNDRV_PCM_RATE_32000 | \ |
| SNDRV_PCM_RATE_44100 | \ |
| SNDRV_PCM_RATE_48000) |
| #define TAS5805M_FORMATS (SNDRV_PCM_FMTBIT_S16_LE | \ |
| SNDRV_PCM_FMTBIT_S20_3LE |\ |
| SNDRV_PCM_FMTBIT_S24_LE | \ |
| SNDRV_PCM_FMTBIT_S32_LE) |
| |
| #define TAS5805M_REG_00 (0x00) |
| #define TAS5805M_REG_03 (0x03) |
| #define TAS5805M_REG_24 (0x24) |
| #define TAS5805M_REG_25 (0x25) |
| #define TAS5805M_REG_26 (0x26) |
| #define TAS5805M_REG_27 (0x27) |
| #define TAS5805M_REG_28 (0x28) |
| #define TAS5805M_REG_29 (0x29) |
| #define TAS5805M_REG_2A (0x2a) |
| #define TAS5805M_REG_2B (0x2b) |
| #define TAS5805M_REG_35 (0x35) |
| #define TAS5805M_DIG_VAL_CTL (0x4c) |
| #define TAS5805M_REG_7F (0x7f) |
| |
| #define TAS5805M_PAGE_00 (0x00) |
| #define TAS5805M_PAGE_2A (0x2a) |
| |
| #define TAS5805M_BOOK_00 (0x00) |
| #define TAS5805M_BOOK_8C (0x8c) |
| |
| #define TAS5805M_VOLUME_MAX (578) |
| #define TAS5805M_VOLUME_MIN (0) |
| |
| const u32 tas5805m_volume[] = { |
| 0x0000001B, //0, -110dB |
| 0x0000001E, //1, -109dB |
| 0x00000021, //2, -108dB |
| 0x00000025, //3, -107dB |
| 0x0000002A, //4, -106dB |
| 0x0000002F, //5, -105dB |
| 0x00000035, //6, -104dB |
| 0x0000003B, //7, -103dB |
| 0x00000043, //8, -102dB |
| 0x0000004B, //9, -101dB |
| 0x00000054, //10, -100dB |
| 0x0000005E, //11, -99dB |
| 0x0000006A, //12, -98dB |
| 0x00000076, //13, -97dB |
| 0x00000085, //14, -96dB |
| 0x00000095, //15, -95dB |
| 0x000000A7, //16, -94dB |
| 0x000000BC, //17, -93dB |
| 0x000000D3, //18, -92dB |
| 0x000000EC, //19, -91dB |
| 0x00000109, //20, -90dB |
| 0x0000012A, //21, -89dB |
| 0x0000014E, //22, -88dB |
| 0x00000177, //23, -87dB |
| 0x000001A4, //24, -86dB |
| 0x000001D8, //25, -85dB |
| 0x00000211, //26, -84dB |
| 0x00000252, //27, -83dB |
| 0x0000029A, //28, -82dB |
| 0x000002EC, //29, -81dB |
| 0x00000347, //30, -80dB |
| 0x000003AD, //31, -79dB |
| 0x00000420, //32, -78dB |
| 0x000004A1, //33, -77dB |
| 0x00000532, //34, -76dB |
| 0x000005D4, //35, -75dB |
| 0x0000068A, //36, -74dB |
| 0x00000756, //37, -73dB |
| 0x0000083B, //38, -72dB |
| 0x0000093C, //39, -71dB |
| 0x00000A5D, //40, -70dB |
| 0x00000BA0, //41, -69dB |
| 0x00000D0C, //42, -68dB |
| 0x00000EA3, //43, -67dB |
| 0x0000106C, //44, -66dB |
| 0x0000126D, //45, -65dB |
| 0x000014AD, //46, -64dB |
| 0x00001733, //47, -63dB |
| 0x00001A07, //48, -62dB |
| 0x00001D34, //49, -61dB |
| 0x000020C5, //50, -60dB |
| 0x000024C4, //51, -59dB |
| 0x00002941, //52, -58dB |
| 0x00002E49, //53, -57dB |
| 0x000033EF, //54, -56dB |
| 0x00003A45, //55, -55dB |
| 0x00004161, //56, -54dB |
| 0x0000495C, //57, -53dB |
| 0x0000524F, //58, -52dB |
| 0x00005C5A, //59, -51dB |
| 0x0000679F, //60, -50dB |
| 0x00007444, //61, -49dB |
| 0x00008274, //62, -48dB |
| 0x0000925F, //63, -47dB |
| 0x0000A43B, //64, -46dB |
| 0x0000B845, //65, -45dB |
| 0x0000CEC1, //66, -44dB |
| 0x0000E7FB, //67, -43dB |
| 0x00010449, //68, -42dB |
| 0x0001240C, //69, -41dB |
| 0x000147AE, //70, -40dB |
| 0x00016FAA, //71, -39dB |
| 0x00019C86, //72, -38dB |
| 0x0001CEDC, //73, -37dB |
| 0x00020756, //74, -36dB |
| 0x000246B5, //75, -35dB |
| 0x00028DCF, //76, -34dB |
| 0x0002DD96, //77, -33dB |
| 0x00033718, //78, -32dB |
| 0x00039B87, //79, -31dB |
| 0x00040C37, //80 -30 |
| 0x00041B3C, //81 -29.875 |
| 0x00042A79, //82 -29.75 |
| 0x000439EE, //83 -29.625 |
| 0x0004499D, //84 -29.5 |
| 0x00045986, //85 -29.375 |
| 0x000469AA, //86 -29.25 |
| 0x00047A0A, //87 -29.125 |
| 0x00048AA7, //88 -29 |
| 0x00049B81, //89 -28.875 |
| 0x0004AC9A, //90 -28.75 |
| 0x0004BDF2, //91 -28.625 |
| 0x0004CF8B, //92 -28.5 |
| 0x0004E165, //93 -28.375 |
| 0x0004F381, //94 -28.25 |
| 0x000505E0, //95 -28.125 |
| 0x00051884, //96 -28 |
| 0x00052B6D, //97 -27.875 |
| 0x00053E9C, //98 -27.75 |
| 0x00055212, //99 -27.625 |
| 0x000565D0, //100 -27.5 |
| 0x000579D8, //101 -27.375 |
| 0x00058E2A, //102 -27.25 |
| 0x0005A2C7, //103 -27.125 |
| 0x0005B7B1, //104 -27 |
| 0x0005CCE8, //105 -26.875 |
| 0x0005E26E, //106 -26.75 |
| 0x0005F844, //107 -26.625 |
| 0x00060E6C, //108 -26.5 |
| 0x000624E5, //109 -26.375 |
| 0x00063BB1, //110 -26.25 |
| 0x000652D3, //111 -26.125 |
| 0x00066A4A, //112 -26 |
| 0x00068218, //113 -25.875 |
| 0x00069A3E, //114 -25.75 |
| 0x0006B2BF, //115 -25.625 |
| 0x0006CB9A, //116 -25.5 |
| 0x0006E4D1, //117 -25.375 |
| 0x0006FE66, //118 -25.25 |
| 0x0007185A, //119 -25.125 |
| 0x000732AE, //120 -25 |
| 0x00074D63, //121 -24.875 |
| 0x0007687C, //122 -24.75 |
| 0x000783FA, //123 -24.625 |
| 0x00079FDD, //124 -24.5 |
| 0x0007BC28, //125 -24.375 |
| 0x0007D8DC, //126 -24.25 |
| 0x0007F5FA, //127 -24.125 |
| 0x00081385, //128 -24 |
| 0x0008317D, //129 -23.875 |
| 0x00084FE4, //130 -23.75 |
| 0x00086EBC, //131 -23.625 |
| 0x00088E07, //132 -23.5 |
| 0x0008ADC6, //133 -23.375 |
| 0x0008CDFA, //134 -23.25 |
| 0x0008EEA6, //135 -23.125 |
| 0x00090FCB, //136 -23 |
| 0x0009316C, //137 -22.875 |
| 0x00095389, //138 -22.75 |
| 0x00097624, //139 -22.625 |
| 0x00099940, //140 -22.5 |
| 0x0009BCDF, //141 -22.375 |
| 0x0009E101, //142 -22.25 |
| 0x000A05AA, //143 -22.125 |
| 0x000A2ADA, //144 -22 |
| 0x000A5095, //145 -21.875 |
| 0x000A76DC, //146 -21.75 |
| 0x000A9DB0, //147 -21.625 |
| 0x000AC515, //148 -21.5 |
| 0x000AED0C, //149 -21.375 |
| 0x000B1597, //150 -21.25 |
| 0x000B3EB9, //151 -21.125 |
| 0x000B6873, //152 -21 |
| 0x000B92C8, //153 -20.875 |
| 0x000BBDBA, //154 -20.75 |
| 0x000BE94C, //155 -20.625 |
| 0x000C157F, //156 -20.5 |
| 0x000C4256, //157 -20.375 |
| 0x000C6FD4, //158 -20.25 |
| 0x000C9DFB, //159 -20.125 |
| 0x000CCCCC, //160 -20 |
| 0x000CFC4C, //161 -19.875 |
| 0x000D2C7B, //162 -19.75 |
| 0x000D5D5E, //163 -19.625 |
| 0x000D8EF6, //164 -19.5 |
| 0x000DC146, //165 -19.375 |
| 0x000DF451, //166 -19.25 |
| 0x000E2819, //167 -19.125 |
| 0x000E5CA1, //168 -19 |
| 0x000E91EC, //169 -18.875 |
| 0x000EC7FD, //170 -18.75 |
| 0x000EFED6, //171 -18.625 |
| 0x000F367B, //172 -18.5 |
| 0x000F6EEF, //173 -18.375 |
| 0x000FA834, //174 -18.25 |
| 0x000FE24E, //175 -18.125 |
| 0x00101D3F, //176 -18 |
| 0x0010590B, //177 -17.875 |
| 0x001095B4, //178 -17.75 |
| 0x0010D33F, //179 -17.625 |
| 0x001111AE, //180 -17.5 |
| 0x00115105, //181 -17.375 |
| 0x00119147, //182 -17.25 |
| 0x0011D278, //183 -17.125 |
| 0x0012149A, //184 -17 |
| 0x001257B2, //185 -16.875 |
| 0x00129BC2, //186 -16.75 |
| 0x0012E0CF, //187 -16.625 |
| 0x001326DD, //188 -16.5 |
| 0x00136DEE, //189 -16.375 |
| 0x0013B607, //190 -16.25 |
| 0x0013FF2C, //191 -16.125 |
| 0x00144960, //192 -16 |
| 0x001494A8, //193 -15.875 |
| 0x0014E107, //194 -15.75 |
| 0x00152E81, //195 -15.625 |
| 0x00157D1A, //196 -15.5 |
| 0x0015CCD8, //197 -15.375 |
| 0x00161DBD, //198 -15.25 |
| 0x00166FCE, //199 -15.125 |
| 0x0016C310, //200 -15 |
| 0x00171787, //201 -14.875 |
| 0x00176D38, //202 -14.75 |
| 0x0017C426, //203 -14.625 |
| 0x00181C57, //204 -14.5 |
| 0x001875CF, //205 -14.375 |
| 0x0018D093, //206 -14.25 |
| 0x00192CA8, //207 -14.125 |
| 0x00198A13, //208 -14 |
| 0x0019E8D8, //209 -13.875 |
| 0x001A48FD, //210 -13.75 |
| 0x001AAA87, //211 -13.625 |
| 0x001B0D7B, //212 -13.5 |
| 0x001B71DD, //213 -13.375 |
| 0x001BD7B5, //214 -13.25 |
| 0x001C3F06, //215 -13.125 |
| 0x001CA7D7, //216 -13 |
| 0x001D122D, //217 -12.875 |
| 0x001D7E0D, //218 -12.75 |
| 0x001DEB7D, //219 -12.625 |
| 0x001E5A84, //220 -12.5 |
| 0x001ECB27, //221 -12.375 |
| 0x001F3D6B, //222 -12.25 |
| 0x001FB158, //223 -12.125 |
| 0x002026F3, //224 -12 |
| 0x00209E42, //225 -11.875 |
| 0x0021174C, //226 -11.75 |
| 0x00219217, //227 -11.625 |
| 0x00220EA9, //228 -11.5 |
| 0x00228D0A, //229 -11.375 |
| 0x00230D40, //230 -11.25 |
| 0x00238F52, //231 -11.125 |
| 0x00241346, //232 -11 |
| 0x00249924, //233 -10.875 |
| 0x002520F3, //234 -10.75 |
| 0x0025AABA, //235 -10.625 |
| 0x00263680, //236 -10.5 |
| 0x0026C44D, //237 -10.375 |
| 0x00275427, //238 -10.25 |
| 0x0027E618, //239 -10.125 |
| 0x00287A26, //240 -10 |
| 0x0029105A, //241 -9.875 |
| 0x0029A8BB, //242 -9.75 |
| 0x002A4351, //243 -9.625 |
| 0x002AE025, //244 -9.5 |
| 0x002B7F3F, //245 -9.375 |
| 0x002C20A8, //246 -9.25 |
| 0x002CC467, //247 -9.125 |
| 0x002D6A86, //248 -9 |
| 0x002E130D, //249 -8.875 |
| 0x002EBE06, //250 -8.75 |
| 0x002F6B79, //251 -8.625 |
| 0x00301B70, //252 -8.5 |
| 0x0030CDF4, //253 -8.375 |
| 0x0031830E, //254 -8.25 |
| 0x00323AC8, //255 -8.125 |
| 0x0032F52C, //256 -8 |
| 0x0033B244, //257 -7.875 |
| 0x0034721A, //258 -7.75 |
| 0x003534B7, //259 -7.625 |
| 0x0035FA26, //260 -7.5 |
| 0x0036C272, //261 -7.375 |
| 0x00378DA5, //262 -7.25 |
| 0x00385BCB, //263 -7.125 |
| 0x00392CED, //264 -7 |
| 0x003A0117, //265 -6.875 |
| 0x003AD855, //266 -6.75 |
| 0x003BB2B1, //267 -6.625 |
| 0x003C9038, //268 -6.5 |
| 0x003D70F5, //269 -6.375 |
| 0x003E54F3, //270 -6.25 |
| 0x003F3C40, //271 -6.125 |
| 0x004026E7, //272 -6 |
| 0x004114F4, //273 -5.875 |
| 0x00420675, //274 -5.75 |
| 0x0042FB77, //275 -5.625 |
| 0x0043F405, //276 -5.5 |
| 0x0044F02E, //277 -5.375 |
| 0x0045EFFE, //278 -5.25 |
| 0x0046F384, //279 -5.125 |
| 0x0047FACC, //280 -5 |
| 0x004905E6, //281 -4.875 |
| 0x004A14DF, //282 -4.75 |
| 0x004B27C5, //283 -4.625 |
| 0x004C3EA8, //284 -4.5 |
| 0x004D5995, //285 -4.375 |
| 0x004E789C, //286 -4.25 |
| 0x004F9BCD, //287 -4.125 |
| 0x0050C335, //288 -4 |
| 0x0051EEE6, //289 -3.875 |
| 0x00531EEF, //290 -3.75 |
| 0x00545361, //291 -3.625 |
| 0x00558C4B, //292 -3.5 |
| 0x0056C9BE, //293 -3.375 |
| 0x00580BCB, //294 -3.25 |
| 0x00595283, //295 -3.125 |
| 0x005A9DF7, //296 -3 |
| 0x005BEE3A, //297 -2.875 |
| 0x005D435C, //298 -2.75 |
| 0x005E9D70, //299 -2.625 |
| 0x005FFC88, //300 -2.5 |
| 0x006160B7, //301 -2.375 |
| 0x0062CA10, //302 -2.25 |
| 0x006438A6, //303 -2.125 |
| 0x0065AC8C, //304 -2 |
| 0x006725D6, //305 -1.875 |
| 0x0068A498, //306 -1.75 |
| 0x006A28E6, //307 -1.625 |
| 0x006BB2D6, //308 -1.5 |
| 0x006D427B, //309 -1.375 |
| 0x006ED7EB, //310 -1.25 |
| 0x0070733B, //311 -1.125 |
| 0x00721482, //312 -1 |
| 0x0073BBD6, //313 -0.875 |
| 0x0075694C, //314 -0.75 |
| 0x00771CFC, //315 -0.625 |
| 0x0078D6FC, //316 -0.5 |
| 0x007A9765, //317 -0.375 |
| 0x007C5E4E, //318 -0.25 |
| 0x007E2BCE, //319 -0.125 |
| 0x00800000, //320 0 |
| 0x0081DAFA, //321 0.125 |
| 0x0083BCD7, //322 0.25 |
| 0x0085A5B1, //323 0.375 |
| 0x008795A0, //324 0.5 |
| 0x00898CBF, //325 0.625 |
| 0x008B8B2A, //326 0.75 |
| 0x008D90FA, //327 0.875 |
| 0x008F9E4C, //328 1 |
| 0x0091B33C, //329 1.125 |
| 0x0093CFE5, //330 1.25 |
| 0x0095F464, //331 1.375 |
| 0x009820D7, //332 1.5 |
| 0x009A555A, //333 1.625 |
| 0x009C920D, //334 1.75 |
| 0x009ED70C, //335 1.875 |
| 0x00A12477, //336 2 |
| 0x00A37A6E, //337 2.125 |
| 0x00A5D90F, //338 2.25 |
| 0x00A8407C, //339 2.375 |
| 0x00AAB0D4, //340 2.5 |
| 0x00AD2A39, //341 2.625 |
| 0x00AFACCC, //342 2.75 |
| 0x00B238B0, //343 2.875 |
| 0x00B4CE07, //344 3 |
| 0x00B76CF4, //345 3.125 |
| 0x00BA159B, //346 3.25 |
| 0x00BCC81F, //347 3.375 |
| 0x00BF84A6, //348 3.5 |
| 0x00C24B54, //349 3.625 |
| 0x00C51C4F, //350 3.75 |
| 0x00C7F7BE, //351 3.875 |
| 0x00CADDC7, //352 4 |
| 0x00CDCE92, //353 4.125 |
| 0x00D0CA46, //354 4.25 |
| 0x00D3D10B, //355 4.375 |
| 0x00D6E30C, //356 4.5 |
| 0x00DA0072, //357 4.625 |
| 0x00DD2966, //358 4.75 |
| 0x00E05E15, //359 4.875 |
| 0x00E39EA8, //360 5 |
| 0x00E6EB4E, //361 5.125 |
| 0x00EA4431, //362 5.25 |
| 0x00EDA980, //363 5.375 |
| 0x00F11B69, //364 5.5 |
| 0x00F49A1B, //365 5.625 |
| 0x00F825C5, //366 5.75 |
| 0x00FBBE96, //367 5.875 |
| 0x00FF64C1, //368 6 |
| 0x01031876, //369 6.125 |
| 0x0106D9E8, //370 6.25 |
| 0x010AA94A, //371 6.375 |
| 0x010E86CF, //372 6.5 |
| 0x011272AB, //373 6.625 |
| 0x01166D15, //374 6.75 |
| 0x011A7643, //375 6.875 |
| 0x011E8E6A, //376 7 |
| 0x0122B5C2, //377 7.125 |
| 0x0126EC84, //378 7.25 |
| 0x012B32EA, //379 7.375 |
| 0x012F892C, //380 7.5 |
| 0x0133EF86, //381 7.625 |
| 0x01386634, //382 7.75 |
| 0x013CED72, //383 7.875 |
| 0x0141857E, //384 8 |
| 0x01462E96, //385 8.125 |
| 0x014AE8F9, //386 8.25 |
| 0x014FB4E8, //387 8.375 |
| 0x015492A3, //388 8.5 |
| 0x0159826D, //389 8.625 |
| 0x015E8488, //390 8.75 |
| 0x01639939, //391 8.875 |
| 0x0168C0C5, //392 9 |
| 0x016DFB71, //393 9.125 |
| 0x01734985, //394 9.25 |
| 0x0178AB48, //395 9.375 |
| 0x017E2104, //396 9.5 |
| 0x0183AB02, //397 9.625 |
| 0x0189498F, //398 9.75 |
| 0x018EFCF5, //399 9.875 |
| 0x0194C583, //400 10 |
| 0x019AA387, //401 10.125 |
| 0x01A09751, //402 10.25 |
| 0x01A6A131, //403 10.375 |
| 0x01ACC179, //404 10.5 |
| 0x01B2F87D, //405 10.625 |
| 0x01B94691, //406 10.75 |
| 0x01BFAC0A, //407 10.875 |
| 0x01C62940, //408 11 |
| 0x01CCBE8A, //409 11.125 |
| 0x01D36C42, //410 11.25 |
| 0x01DA32C2, //411 11.375 |
| 0x01E11266, //412 11.5 |
| 0x01E80B8C, //413 11.625 |
| 0x01EF1E92, //414 11.75 |
| 0x01F64BD9, //415 11.875 |
| 0x01FD93C1, //416 12 |
| 0x0204F6AE, //417 12.125 |
| 0x020C7504, //418 12.25 |
| 0x02140F28, //419 12.375 |
| 0x021BC582, //420 12.5 |
| 0x0223987A, //421 12.625 |
| 0x022B887B, //422 12.75 |
| 0x023395F0, //423 12.875 |
| 0x023BC147, //424 13 |
| 0x02440AEE, //425 13.125 |
| 0x024C7356, //426 13.25 |
| 0x0254FAF2, //427 13.375 |
| 0x025DA234, //428 13.5 |
| 0x02666992, //429 13.625 |
| 0x026F5184, //430 13.75 |
| 0x02785A83, //431 13.875 |
| 0x02818508, //432 14 |
| 0x028AD191, //433 14.125 |
| 0x0294409B, //434 14.25 |
| 0x029DD2A7, //435 14.375 |
| 0x02A78836, //436 14.5 |
| 0x02B161CD, //437 14.625 |
| 0x02BB5FF1, //438 14.75 |
| 0x02C5832A, //439 14.875 |
| 0x02CFCC01, //440 15 |
| 0x02DA3B02, //441 15.125 |
| 0x02E4D0BA, //442 15.25 |
| 0x02EF8DB9, //443 15.375 |
| 0x02FA7292, //444 15.5 |
| 0x03057FD7, //445 15.625 |
| 0x0310B61F, //446 15.75 |
| 0x031C1602, //447 15.875 |
| 0x0327A01A, //448 16 |
| 0x03335504, //449 16.125 |
| 0x033F355F, //450 16.25 |
| 0x034B41CC, //451 16.375 |
| 0x03577AEF, //452 16.5 |
| 0x0363E16D, //453 16.625 |
| 0x037075EF, //454 16.75 |
| 0x037D3920, //455 16.875 |
| 0x038A2BAC, //456 17 |
| 0x03974E44, //457 17.125 |
| 0x03A4A19A, //458 17.25 |
| 0x03B22662, //459 17.375 |
| 0x03BFDD55, //460 17.5 |
| 0x03CDC72C, //461 17.625 |
| 0x03DBE4A4, //462 17.75 |
| 0x03EA367D, //463 17.875 |
| 0x03F8BD79, //464 18 |
| 0x04077A5E, //465 18.125 |
| 0x04166DF2, //466 18.25 |
| 0x04259902, //467 18.375 |
| 0x0434FC5C, //468 18.5 |
| 0x044498CF, //469 18.625 |
| 0x04546F30, //470 18.75 |
| 0x04648056, //471 18.875 |
| 0x0474CD1B, //472 19 |
| 0x0485565C, //473 19.125 |
| 0x04961CFA, //474 19.25 |
| 0x04A721D8, //475 19.375 |
| 0x04B865DE, //476 19.5 |
| 0x04C9E9F5, //477 19.625 |
| 0x04DBAF0C, //478 19.75 |
| 0x04EDB613, //479 19.875 |
| 0x05000000, //480 20 |
| 0x05128DCA, //481 20.125 |
| 0x0525606D, //482 20.25 |
| 0x053878EA, //483 20.375 |
| 0x054BD842, //484 20.5 |
| 0x055F7F7E, //485 20.625 |
| 0x05736FA7, //486 20.75 |
| 0x0587A9CD, //487 20.875 |
| 0x059C2F01, //488 21 |
| 0x05B1005B, //489 21.125 |
| 0x05C61EF5, //490 21.25 |
| 0x05DB8BEE, //491 21.375 |
| 0x05F14868, //492 21.5 |
| 0x0607558B, //493 21.625 |
| 0x061DB482, //494 21.75 |
| 0x0634667C, //495 21.875 |
| 0x064B6CAD, //496 22 |
| 0x0662C84F, //497 22.125 |
| 0x067A7A9D, //498 22.25 |
| 0x069284DB, //499 22.375 |
| 0x06AAE84D, //500 22.5 |
| 0x06C3A63F, //501 22.625 |
| 0x06DCC001, //502 22.75 |
| 0x06F636E8, //503 22.875 |
| 0x07100C4D, //504 23 |
| 0x072A418F, //505 23.125 |
| 0x0744D811, //506 23.25 |
| 0x075FD13C, //507 23.375 |
| 0x077B2E7F, //508 23.5 |
| 0x0796F14D, //509 23.625 |
| 0x07B31B1F, //510 23.75 |
| 0x07CFAD73, //511 23.875 |
| 0x07ECA9CD, //512 24 |
| 0x080A11B5, //513 24.125 |
| 0x0827E6BD, //514 24.25 |
| 0x08462A77, //515 24.375 |
| 0x0864DE80, //516 24.5 |
| 0x08840477, //517 24.625 |
| 0x08A39E04, //518 24.75 |
| 0x08C3ACD3, //519 24.875 |
| 0x08E43298, //520 25 |
| 0x0905310C, //521 25.125 |
| 0x0926A9EF, //522 25.25 |
| 0x09489F07, //523 25.375 |
| 0x096B1222, //524 25.5 |
| 0x098E0512, //525 25.625 |
| 0x09B179B2, //526 25.75 |
| 0x09D571E3, //527 25.875 |
| 0x09F9EF8E, //528 26 |
| 0x0A1EF4A1, //529 26.125 |
| 0x0A448314, //530 26.25 |
| 0x0A6A9CE4, //531 26.375 |
| 0x0A914416, //532 26.5 |
| 0x0AB87AB7, //533 26.625 |
| 0x0AE042DB, //534 26.75 |
| 0x0B089E9E, //535 26.875 |
| 0x0B319024, //536 27 |
| 0x0B5B1998, //537 27.125 |
| 0x0B853D2F, //538 27.25 |
| 0x0BAFFD24, //539 27.375 |
| 0x0BDB5BBC, //540 27.5 |
| 0x0C075B43, //541 27.625 |
| 0x0C33FE0E, //542 27.75 |
| 0x0C61467B, //543 27.875 |
| 0x0C8F36F2, //544 28 |
| 0x0CBDD1E0, //545 28.125 |
| 0x0CED19C0, //546 28.25 |
| 0x0D1D1113, //547 28.375 |
| 0x0D4DBA63, //548 28.5 |
| 0x0D7F1845, //549 28.625 |
| 0x0DB12D58, //550 28.75 |
| 0x0DE3FC43, //551 28.875 |
| 0x0E1787B8, //552 29 |
| 0x0E4BD272, //553 29.125 |
| 0x0E80DF37, //554 29.25 |
| 0x0EB6B0D7, //555 29.375 |
| 0x0EED4A2D, //556 29.5 |
| 0x0F24AE1D, //557 29.625 |
| 0x0F5CDF98, //558 29.75 |
| 0x0F95E199, //559 29.875 |
| 0x0FCFB724, //560 30 |
| 0x11BD9C84, //561 31dB |
| 0x13E7C594, //562 32dB |
| 0x16558CCB, //563 33dB |
| 0x190F3254, //564 34dB |
| 0x1C1DF80E, //565 35dB |
| 0x1F8C4107, //566 36dB |
| 0x2365B4BF, //567 37dB |
| 0x27B766C2, //568 38dB |
| 0x2C900313, //569 39dB |
| 0x32000000, //570 40dB |
| 0x3819D612, //571 41dB |
| 0x3EF23ECA, //572 42dB |
| 0x46A07B07, //573 43dB |
| 0x4F3EA203, //574 44dB |
| 0x58E9F9F9, //575 45dB |
| 0x63C35B8E, //576 46dB |
| 0x6FEFA16D, //577 47dB |
| 0x7D982575, //578 48dB |
| }; |
| |
| #define TAS5805_EQ_PARAM_LENGTH 610 |
| #define TAS5805_EQ_PARAM_COUNT 1220 |
| #define TAS5805_DRC_PARAM_LENGTH 29 |
| #define TAS5805_DRC_PARAM_COUNT 58 |
| |
| struct tas5805m_priv { |
| struct regmap *regmap; |
| struct tas5805m_platform_data *pdata; |
| int vol; |
| bool mute; |
| struct snd_soc_component *component; |
| bool eq_enable; |
| char *m_eq_tab; |
| bool drc_enable; |
| char *m_drc_tab; |
| }; |
| |
| const struct regmap_config tas5805m_regmap = { |
| .reg_bits = 8, |
| .val_bits = 8, |
| .cache_type = REGCACHE_RBTREE, |
| }; |
| |
| static int tas5805m_vol_info(struct snd_kcontrol *kcontrol, |
| struct snd_ctl_elem_info *uinfo) |
| { |
| uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER; |
| uinfo->access = |
| (SNDRV_CTL_ELEM_ACCESS_TLV_READ | SNDRV_CTL_ELEM_ACCESS_READWRITE); |
| uinfo->count = 1; |
| |
| uinfo->value.integer.min = TAS5805M_VOLUME_MIN; |
| uinfo->value.integer.max = TAS5805M_VOLUME_MAX; |
| uinfo->value.integer.step = 1; |
| |
| return 0; |
| } |
| |
| static int tas5805m_mute_info(struct snd_kcontrol *kcontrol, |
| struct snd_ctl_elem_info *uinfo) |
| { |
| uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER; |
| uinfo->access = |
| (SNDRV_CTL_ELEM_ACCESS_TLV_READ | SNDRV_CTL_ELEM_ACCESS_READWRITE); |
| uinfo->count = 1; |
| |
| uinfo->value.integer.min = 0; |
| uinfo->value.integer.max = 1; |
| uinfo->value.integer.step = 1; |
| |
| return 0; |
| } |
| |
| static int tas5805m_vol_locked_get(struct snd_kcontrol *kcontrol, |
| struct snd_ctl_elem_value *ucontrol) |
| { |
| struct snd_soc_component *component = snd_soc_kcontrol_component(kcontrol); |
| struct tas5805m_priv *tas5805m = snd_soc_component_get_drvdata(component); |
| |
| ucontrol->value.integer.value[0] = tas5805m->vol; |
| |
| return 0; |
| } |
| |
| static inline int get_volume_index(int vol) |
| { |
| int index; |
| |
| index = vol; |
| |
| if (index < TAS5805M_VOLUME_MIN) |
| index = TAS5805M_VOLUME_MIN; |
| |
| if (index > TAS5805M_VOLUME_MAX) |
| index = TAS5805M_VOLUME_MAX; |
| |
| return index; |
| } |
| |
| static void tas5805m_set_volume(struct snd_soc_component *component, int vol) |
| { |
| unsigned int index; |
| u32 volume_hex; |
| u8 byte4; |
| u8 byte3; |
| u8 byte2; |
| u8 byte1; |
| |
| index = get_volume_index(vol); |
| volume_hex = tas5805m_volume[index]; |
| |
| byte4 = ((volume_hex >> 24) & 0xFF); |
| byte3 = ((volume_hex >> 16) & 0xFF); |
| byte2 = ((volume_hex >> 8) & 0xFF); |
| byte1 = ((volume_hex >> 0) & 0xFF); |
| |
| //w 58 00 00 |
| snd_soc_component_write(component, TAS5805M_REG_00, TAS5805M_PAGE_00); |
| //w 58 7f 8c |
| snd_soc_component_write(component, TAS5805M_REG_7F, TAS5805M_BOOK_8C); |
| //w 58 00 2a |
| snd_soc_component_write(component, TAS5805M_REG_00, TAS5805M_PAGE_2A); |
| //w 58 24 xx |
| snd_soc_component_write(component, TAS5805M_REG_24, byte4); |
| snd_soc_component_write(component, TAS5805M_REG_25, byte3); |
| snd_soc_component_write(component, TAS5805M_REG_26, byte2); |
| snd_soc_component_write(component, TAS5805M_REG_27, byte1); |
| //w 58 28 xx |
| snd_soc_component_write(component, TAS5805M_REG_28, byte4); |
| snd_soc_component_write(component, TAS5805M_REG_29, byte3); |
| snd_soc_component_write(component, TAS5805M_REG_2A, byte2); |
| snd_soc_component_write(component, TAS5805M_REG_2B, byte1); |
| } |
| |
| static int tas5805m_vol_locked_put(struct snd_kcontrol *kcontrol, |
| struct snd_ctl_elem_value *ucontrol) |
| { |
| struct snd_soc_component *component = snd_soc_kcontrol_component(kcontrol); |
| struct tas5805m_priv *tas5805m = snd_soc_component_get_drvdata(component); |
| |
| tas5805m->vol = ucontrol->value.integer.value[0]; |
| tas5805m_set_volume(component, tas5805m->vol); |
| |
| return 0; |
| } |
| |
| static int tas5805m_mute(struct snd_soc_component *component, bool mute) |
| { |
| //struct tas5805m_priv *tas5805m = snd_soc_component_get_drvdata(component); |
| u8 reg03_value = 0; |
| u8 reg35_value = 0; |
| |
| if (mute) { |
| //mute both left & right channels |
| reg03_value = 0x0b; |
| reg35_value = 0x00; |
| } else { |
| //unmute |
| reg03_value = 0x03; |
| reg35_value = 0x11; |
| } |
| |
| snd_soc_component_write(component, TAS5805M_REG_00, TAS5805M_PAGE_00); |
| snd_soc_component_write(component, TAS5805M_REG_7F, TAS5805M_BOOK_00); |
| snd_soc_component_write(component, TAS5805M_REG_00, TAS5805M_PAGE_00); |
| snd_soc_component_write(component, TAS5805M_REG_03, reg03_value); |
| snd_soc_component_write(component, TAS5805M_REG_35, reg35_value); |
| //tas5805m->mute = mute; |
| |
| return 0; |
| } |
| |
| static int tas5805m_mute_locked_put(struct snd_kcontrol *kcontrol, |
| struct snd_ctl_elem_value *ucontrol) |
| { |
| struct snd_soc_component *component = snd_soc_kcontrol_component(kcontrol); |
| struct tas5805m_priv *tas5805m = snd_soc_component_get_drvdata(component); |
| |
| tas5805m->mute = ucontrol->value.integer.value[0]; |
| tas5805m_mute(component, tas5805m->mute); |
| |
| return 0; |
| } |
| |
| static int tas5805m_mute_locked_get(struct snd_kcontrol *kcontrol, |
| struct snd_ctl_elem_value *ucontrol) |
| { |
| struct snd_soc_component *component = snd_soc_kcontrol_component(kcontrol); |
| struct tas5805m_priv *tas5805m = snd_soc_component_get_drvdata(component); |
| |
| ucontrol->value.integer.value[0] = tas5805m->mute; |
| |
| return 0; |
| } |
| |
| static int tas5805_set_EQ_enum(struct snd_kcontrol *kcontrol, |
| struct snd_ctl_elem_value *ucontrol) |
| { |
| struct snd_soc_component *component = snd_soc_kcontrol_component(kcontrol); |
| struct tas5805m_priv *tas5805m = snd_soc_component_get_drvdata(component); |
| |
| tas5805m->eq_enable = !!ucontrol->value.integer.value[0]; |
| |
| return 0; |
| } |
| |
| static int tas5805_get_EQ_enum(struct snd_kcontrol *kcontrol, |
| struct snd_ctl_elem_value *ucontrol) |
| { |
| struct snd_soc_component *component = snd_soc_kcontrol_component(kcontrol); |
| struct tas5805m_priv *tas5805m = snd_soc_component_get_drvdata(component); |
| |
| ucontrol->value.integer.value[0] = tas5805m->eq_enable; |
| |
| return 0; |
| } |
| |
| static int tas5805_set_DRC_enum(struct snd_kcontrol *kcontrol, |
| struct snd_ctl_elem_value *ucontrol) |
| { |
| struct snd_soc_component *component = snd_soc_kcontrol_component(kcontrol); |
| struct tas5805m_priv *tas5805m = snd_soc_component_get_drvdata(component); |
| |
| tas5805m->drc_enable = !!ucontrol->value.integer.value[0]; |
| |
| return 0; |
| } |
| |
| static int tas5805_get_DRC_enum(struct snd_kcontrol *kcontrol, |
| struct snd_ctl_elem_value *ucontrol) |
| { |
| struct snd_soc_component *component = snd_soc_kcontrol_component(kcontrol); |
| struct tas5805m_priv *tas5805m = snd_soc_component_get_drvdata(component); |
| |
| ucontrol->value.integer.value[0] = tas5805m->drc_enable; |
| |
| return 0; |
| } |
| |
| static int tas5805_set_DRC_param(struct snd_kcontrol *kcontrol, |
| const unsigned int __user *bytes, unsigned int size) |
| { |
| struct snd_soc_component *component = snd_soc_kcontrol_component(kcontrol); |
| struct tas5805m_priv *tas5805m = snd_soc_component_get_drvdata(component); |
| struct snd_ctl_tlv *tlv = (struct snd_ctl_tlv *)bytes; |
| char *p = tas5805m->m_drc_tab; |
| unsigned int i = 0, res; |
| |
| if (!p || size > TAS5805_DRC_PARAM_COUNT) |
| return -EINVAL; |
| |
| res = copy_from_user(p, tlv->tlv, size); |
| if (res) |
| return -EFAULT; |
| |
| for (i = 0; i < size / 2; i++) { |
| snd_soc_component_write(component, *p, *(p + 1)); |
| p += 2; |
| } |
| |
| return 0; |
| } |
| |
| static int tas5805_get_DRC_param(struct snd_kcontrol *kcontrol, |
| unsigned int __user *bytes, unsigned int size) |
| { |
| struct snd_soc_component *component = snd_soc_kcontrol_component(kcontrol); |
| struct tas5805m_priv *tas5805m = snd_soc_component_get_drvdata(component); |
| struct snd_ctl_tlv *tlv = (struct snd_ctl_tlv *)bytes; |
| char *p = tas5805m->m_drc_tab; |
| int res = 0; |
| |
| if (!p || size > TAS5805_DRC_PARAM_COUNT) |
| return -EINVAL; |
| |
| res = copy_to_user(tlv->tlv, p, size); |
| if (res) |
| return -EFAULT; |
| |
| return 0; |
| } |
| |
| static int tas5805_set_EQ_param(struct snd_kcontrol *kcontrol, |
| const unsigned int __user *bytes, unsigned int size) |
| { |
| struct snd_soc_component *component = snd_soc_kcontrol_component(kcontrol); |
| struct tas5805m_priv *tas5805m = snd_soc_component_get_drvdata(component); |
| struct snd_ctl_tlv *tlv = (struct snd_ctl_tlv *)bytes; |
| char *p = tas5805m->m_eq_tab; |
| unsigned int i = 0, res; |
| |
| if (!p || size > TAS5805_EQ_PARAM_COUNT) |
| return -EINVAL; |
| |
| res = copy_from_user(p, tlv->tlv, size); |
| if (res) |
| return -EFAULT; |
| |
| for (i = 0; i < size / 2; i++) { |
| snd_soc_component_write(component, *p, *(p + 1)); |
| p += 2; |
| } |
| |
| return 0; |
| } |
| |
| static int tas5805_get_EQ_param(struct snd_kcontrol *kcontrol, |
| unsigned int __user *bytes, unsigned int size) |
| { |
| struct snd_soc_component *component = snd_soc_kcontrol_component(kcontrol); |
| struct tas5805m_priv *tas5805m = snd_soc_component_get_drvdata(component); |
| struct snd_ctl_tlv *tlv = (struct snd_ctl_tlv *)bytes; |
| char *p = tas5805m->m_eq_tab; |
| int res = 0; |
| |
| if (!p || size > TAS5805_EQ_PARAM_COUNT) |
| return -EINVAL; |
| |
| res = copy_to_user(tlv->tlv, p, size); |
| if (res) |
| return -EFAULT; |
| |
| return 0; |
| } |
| |
| static const struct snd_kcontrol_new tas5805m_vol_control[] = { |
| { |
| .iface = SNDRV_CTL_ELEM_IFACE_MIXER, |
| .name = "Master Volume", |
| .info = tas5805m_vol_info, |
| .get = tas5805m_vol_locked_get, |
| .put = tas5805m_vol_locked_put, |
| }, |
| { |
| .iface = SNDRV_CTL_ELEM_IFACE_MIXER, |
| .name = "Maser Volume Mute", |
| .info = tas5805m_mute_info, |
| .get = tas5805m_mute_locked_get, |
| .put = tas5805m_mute_locked_put, |
| }, |
| SOC_SINGLE_BOOL_EXT("Set EQ Enable", 0, |
| tas5805_get_EQ_enum, tas5805_set_EQ_enum), |
| SOC_SINGLE_BOOL_EXT("Set DRC Enable", 0, |
| tas5805_get_DRC_enum, tas5805_set_DRC_enum), |
| SND_SOC_BYTES_TLV("EQ table", TAS5805_EQ_PARAM_COUNT, |
| tas5805_get_EQ_param, tas5805_set_EQ_param), |
| SND_SOC_BYTES_TLV("DRC table", TAS5805_DRC_PARAM_COUNT, |
| tas5805_get_DRC_param, tas5805_set_DRC_param), |
| }; |
| |
| static int tas5805m_set_bias_level(struct snd_soc_component *component, |
| enum snd_soc_bias_level level) |
| { |
| pr_debug("level = %d\n", level); |
| |
| switch (level) { |
| case SND_SOC_BIAS_ON: |
| break; |
| |
| case SND_SOC_BIAS_PREPARE: |
| /* Full power on */ |
| break; |
| |
| case SND_SOC_BIAS_STANDBY: |
| break; |
| |
| case SND_SOC_BIAS_OFF: |
| /* The chip runs through the power down sequence for us. */ |
| break; |
| } |
| component->dapm.bias_level = level; |
| |
| return 0; |
| } |
| |
| static int tas5805m_trigger(struct snd_pcm_substream *substream, int cmd, |
| struct snd_soc_dai *codec_dai) |
| { |
| struct tas5805m_priv *tas5805m = snd_soc_dai_get_drvdata(codec_dai); |
| struct snd_soc_component *component = tas5805m->component; |
| |
| if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) { |
| switch (cmd) { |
| case SNDRV_PCM_TRIGGER_START: |
| case SNDRV_PCM_TRIGGER_RESUME: |
| case SNDRV_PCM_TRIGGER_PAUSE_RELEASE: |
| pr_debug("%s(), start\n", __func__); |
| /* |
| *snd_soc_component_write(component, TAS5805M_REG_00, TAS5805M_PAGE_00); |
| *snd_soc_component_write(component, TAS5805M_REG_7F, TAS5805M_BOOK_00); |
| *snd_soc_component_write(component, TAS5805M_REG_00, TAS5805M_PAGE_00); |
| *snd_soc_component_write(component, TAS5805M_DIG_VAL_CTL, 0x30); |
| */ |
| if (!tas5805m->mute) |
| tas5805m_mute(component, 0); |
| break; |
| case SNDRV_PCM_TRIGGER_STOP: |
| case SNDRV_PCM_TRIGGER_SUSPEND: |
| case SNDRV_PCM_TRIGGER_PAUSE_PUSH: |
| pr_debug("%s(), stop\n", __func__); |
| /* |
| *snd_soc_component_write(component, TAS5805M_REG_00, TAS5805M_PAGE_00); |
| *snd_soc_component_write(component, TAS5805M_REG_7F, TAS5805M_BOOK_00); |
| *snd_soc_component_write(component, TAS5805M_REG_00, TAS5805M_PAGE_00); |
| *snd_soc_component_write(component, TAS5805M_DIG_VAL_CTL, 0xff); |
| */ |
| if (!tas5805m->mute) |
| tas5805m_mute(component, 1); |
| break; |
| } |
| } |
| return 0; |
| } |
| |
| static int reset_tas5805m_GPIO(struct device *dev) |
| { |
| struct tas5805m_priv *tas5805m = dev_get_drvdata(dev); |
| struct tas5805m_platform_data *pdata = tas5805m->pdata; |
| int ret = 0; |
| |
| if (pdata->reset_pin < 0) |
| return 0; |
| |
| ret = devm_gpio_request_one(dev, pdata->reset_pin, |
| GPIOF_OUT_INIT_LOW, |
| "tas5805m-reset-pin"); |
| if (ret < 0) |
| return -1; |
| |
| gpio_direction_output(pdata->reset_pin, GPIOF_OUT_INIT_LOW); |
| usleep_range(1 * 1000, 2 * 1000); |
| gpio_direction_output(pdata->reset_pin, GPIOF_OUT_INIT_HIGH); |
| usleep_range(5 * 1000, 6 * 1000); |
| |
| return 0; |
| } |
| |
| static int tas5805m_snd_suspend(struct snd_soc_component *component) |
| { |
| struct tas5805m_priv *tas5805m = snd_soc_component_get_drvdata(component); |
| struct tas5805m_platform_data *pdata = tas5805m->pdata; |
| |
| dev_info(component->dev, "tas5805m_suspend!\n"); |
| tas5805m_set_bias_level(component, SND_SOC_BIAS_OFF); |
| |
| if (pdata->reset_pin) |
| gpio_direction_output(pdata->reset_pin, GPIOF_OUT_INIT_LOW); |
| usleep_range(9, 15); |
| return 0; |
| } |
| |
| static int tas5805m_reg_init(struct snd_soc_component *component) |
| { |
| int i, j = 0; |
| |
| for (j = 0; j < ARRAY_SIZE(tas5805m_reset); j++) { |
| snd_soc_component_write(component, tas5805m_reset[j][0], |
| tas5805m_reset[j][1]); |
| }; |
| usleep_range(10 * 1000, 11 * 1000); |
| for (i = 0; i < ARRAY_SIZE(tas5805m_init_sequence); i++) { |
| snd_soc_component_write(component, tas5805m_init_sequence[i][0], |
| tas5805m_init_sequence[i][1]); |
| }; |
| return 0; |
| } |
| |
| static int tas5805m_snd_resume(struct snd_soc_component *component) |
| { |
| int ret; |
| struct tas5805m_priv *tas5805m = snd_soc_component_get_drvdata(component); |
| struct tas5805m_platform_data *pdata = tas5805m->pdata; |
| |
| dev_info(component->dev, "%s!\n", __func__); |
| if (pdata->reset_pin) |
| gpio_direction_output(pdata->reset_pin, GPIOF_OUT_INIT_HIGH); |
| |
| usleep_range(3 * 1000, 4 * 1000); |
| |
| ret = tas5805m_reg_init(component); |
| // regmap_register_patch(tas5805m->regmap, tas5805m_init_sequence, |
| // ARRAY_SIZE(tas5805m_init_sequence)); |
| if (ret != 0) { |
| dev_err(component->dev, "Failed to initialize TAS5805M: %d\n", ret); |
| goto err; |
| } |
| |
| tas5805m_set_volume(component, tas5805m->vol); |
| tas5805m_mute(component, tas5805m->mute); |
| tas5805m_set_bias_level(component, SND_SOC_BIAS_STANDBY); |
| |
| return 0; |
| err: |
| return ret; |
| } |
| |
| static int tas5805m_probe(struct snd_soc_component *component) |
| { |
| int ret; |
| struct tas5805m_priv *tas5805m = snd_soc_component_get_drvdata(component); |
| |
| usleep_range(20 * 1000, 21 * 1000); |
| ret = tas5805m_reg_init(component); |
| if (ret != 0) |
| goto err; |
| |
| tas5805m_set_volume(component, tas5805m->vol); |
| snd_soc_add_component_controls(component, tas5805m_vol_control, |
| ARRAY_SIZE(tas5805m_vol_control)); |
| tas5805m->component = component; |
| return 0; |
| |
| err: |
| return ret; |
| } |
| |
| static void tas5805m_remove(struct snd_soc_component *component) |
| { |
| struct tas5805m_priv *tas5805m = snd_soc_component_get_drvdata(component); |
| struct tas5805m_platform_data *pdata = tas5805m->pdata; |
| |
| if (pdata->reset_pin) |
| gpio_direction_output(pdata->reset_pin, GPIOF_OUT_INIT_LOW); |
| |
| usleep_range(9, 15); |
| } |
| |
| static const struct snd_soc_component_driver soc_codec_tas5805m = { |
| .probe = tas5805m_probe, |
| .remove = tas5805m_remove, |
| .suspend = tas5805m_snd_suspend, |
| .resume = tas5805m_snd_resume, |
| .set_bias_level = tas5805m_set_bias_level, |
| }; |
| |
| static const struct snd_soc_dai_ops tas5805m_dai_ops = { |
| //.digital_mute = tas5805m_mute, |
| .trigger = tas5805m_trigger, |
| }; |
| |
| static struct snd_soc_dai_driver tas5805m_dai = { |
| .name = "tas5805m-amplifier", |
| .playback = { |
| .stream_name = "Playback", |
| .channels_min = 2, |
| .channels_max = 8, |
| .rates = TAS5805M_RATES, |
| .formats = TAS5805M_FORMATS, |
| }, |
| .ops = &tas5805m_dai_ops, |
| }; |
| |
| static int tas5805m_parse_dt(struct tas5805m_priv *tas5805m, |
| struct device_node *np) |
| { |
| int ret = 0; |
| int reset_pin = -1; |
| |
| reset_pin = of_get_named_gpio(np, "reset_pin", 0); |
| if (reset_pin < 0) { |
| pr_err("%s fail to get reset pin from dts!\n", __func__); |
| ret = -1; |
| } else { |
| pr_info("%s pdata->reset_pin = %d!\n", __func__, |
| tas5805m->pdata->reset_pin); |
| } |
| tas5805m->pdata->reset_pin = reset_pin; |
| |
| return ret; |
| } |
| |
| static int tas5805m_i2c_probe(struct i2c_client *i2c, |
| const struct i2c_device_id *id) |
| { |
| struct regmap *regmap; |
| struct regmap_config config = tas5805m_regmap; |
| struct tas5805m_priv *tas5805m; |
| struct tas5805m_platform_data *pdata; |
| int ret = 0; |
| |
| tas5805m = devm_kzalloc(&i2c->dev, |
| sizeof(struct tas5805m_priv), GFP_KERNEL); |
| if (!tas5805m) |
| return -ENOMEM; |
| |
| regmap = devm_regmap_init_i2c(i2c, &config); |
| if (IS_ERR(regmap)) |
| return PTR_ERR(regmap); |
| |
| pdata = devm_kzalloc(&i2c->dev, |
| sizeof(struct tas5805m_platform_data), |
| GFP_KERNEL); |
| if (!pdata) { |
| pr_err("%s failed to kzalloc for tas5805 pdata\n", __func__); |
| return -ENOMEM; |
| } |
| tas5805m->pdata = pdata; |
| |
| tas5805m_parse_dt(tas5805m, i2c->dev.of_node); |
| tas5805m->regmap = regmap; |
| tas5805m->vol = 400; //10dB |
| |
| dev_set_drvdata(&i2c->dev, tas5805m); |
| |
| ret = devm_snd_soc_register_component(&i2c->dev, &soc_codec_tas5805m, |
| &tas5805m_dai, 1); |
| if (ret != 0) |
| return -ENOMEM; |
| |
| reset_tas5805m_GPIO(&i2c->dev); |
| |
| tas5805m->m_drc_tab = |
| devm_kzalloc(&i2c->dev, |
| sizeof(char) * TAS5805_DRC_PARAM_COUNT, |
| GFP_KERNEL); |
| if (!tas5805m->m_drc_tab) |
| return -ENOMEM; |
| |
| tas5805m->m_eq_tab = |
| devm_kzalloc(&i2c->dev, |
| sizeof(char) * TAS5805_EQ_PARAM_COUNT, |
| GFP_KERNEL); |
| if (!tas5805m->m_eq_tab) |
| return -ENOMEM; |
| |
| return ret; |
| } |
| |
| static int tas5805m_i2c_remove(struct i2c_client *i2c) |
| { |
| devm_kfree(&i2c->dev, i2c_get_clientdata(i2c)); |
| |
| return 0; |
| } |
| |
| static void tas5805m_i2c_shutdown(struct i2c_client *i2c) |
| { |
| struct tas5805m_priv *tas5805m = i2c_get_clientdata(i2c); |
| struct tas5805m_platform_data *pdata = tas5805m->pdata; |
| |
| if (pdata->reset_pin) |
| gpio_direction_output(pdata->reset_pin, GPIOF_OUT_INIT_LOW); |
| } |
| |
| static const struct i2c_device_id tas5805m_i2c_id[] = { |
| {"tas5805",}, |
| {} |
| }; |
| |
| MODULE_DEVICE_TABLE(i2c, tas5805m_i2c_id); |
| |
| #ifdef CONFIG_OF |
| static const struct of_device_id tas5805m_of_match[] = { |
| {.compatible = "ti, tas5805",}, |
| {} |
| }; |
| |
| MODULE_DEVICE_TABLE(of, tas5805m_of_match); |
| #endif |
| |
| static struct i2c_driver tas5805m_i2c_driver = { |
| .probe = tas5805m_i2c_probe, |
| .remove = tas5805m_i2c_remove, |
| .shutdown = tas5805m_i2c_shutdown, |
| .id_table = tas5805m_i2c_id, |
| .driver = { |
| .name = TAS5805M_DRV_NAME, |
| .of_match_table = tas5805m_of_match, |
| }, |
| }; |
| |
| module_i2c_driver(tas5805m_i2c_driver); |
| |
| MODULE_AUTHOR("Andy Liu <andy-liu@ti.com>"); |
| MODULE_DESCRIPTION("TAS5805M Audio Amplifier Driver"); |
| MODULE_LICENSE("GPL v2"); |