0a1b6a97d35385a615b6a3fe4dfcf353a68beb3c
[tas256xsw-android/tas2563-android-driver.git] / tas2563-codec.c
1 /*
2 ** =============================================================================
3 ** Copyright (c) 2016  Texas Instruments Inc.
4 **
5 ** This program is free software; you can redistribute it and/or modify it under
6 ** the terms of the GNU General Public License as published by the Free Software
7 ** Foundation; version 2.
8 **
9 ** This program is distributed in the hope that it will be useful, but WITHOUT
10 ** ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
11 ** FOR A PARTICULAR PURPOSE.See the GNU General Public License for more details.
12 **
13 ** File:
14 **     tas2563-codec.c
15 **
16 ** Description:
17 **     ALSA SoC driver for Texas Instruments TAS2563 High Performance 4W Smart
18 **     Amplifier
19 **
20 ** =============================================================================
21 */
23 #ifdef CONFIG_TAS2563_CODEC
24 #define DEBUG
25 #include <linux/module.h>
26 #include <linux/moduleparam.h>
27 #include <linux/init.h>
28 #include <linux/delay.h>
29 #include <linux/pm.h>
30 #include <linux/i2c.h>
31 #include <linux/gpio.h>
32 #include <linux/regulator/consumer.h>
33 #include <linux/firmware.h>
34 #include <linux/regmap.h>
35 #include <linux/of.h>
36 #include <linux/of_gpio.h>
37 #include <linux/slab.h>
38 #include <linux/slab.h>
39 #include <linux/syscalls.h>
40 #include <linux/fcntl.h>
41 #include <sound/core.h>
42 #include <sound/pcm.h>
43 #include <sound/pcm_params.h>
44 #include <sound/soc.h>
45 #include <sound/initval.h>
46 #include <sound/tlv.h>
47 #include <linux/crc8.h>
49 #include "tas2563.h"
50 #include "tas2563-codec.h"
52 #define PPC_DRIVER_CRCCHK                       0x00000200
53 #define PPC_DRIVER_CONFDEV                      0x00000000
54 #define PPC_DRIVER_MTPLLSRC                     0x00000400
55 #define PPC_DRIVER_CFGDEV_NONCRC        0x00000101
57 #define TAS2563_CAL_NAME    "/data/vendor/pa_cal/tas2563_cal.bin"
58 #define RESTART_MAX 3
60 #define TAS2563_UDELAY 0xFFFFFFFE
61 #define TAS2563_MDELAY 0xFFFFFFFE
62 #define KCONTROL_CODEC
64 #define TAS2563_BLOCK_PLL                               0x00
65 #define TAS2563_BLOCK_PGM_ALL                   0x0d
66 #define TAS2563_BLOCK_PGM_DEV_A                 0x01
67 #define TAS2563_BLOCK_PGM_DEV_B                 0x08
68 #define TAS2563_BLOCK_CFG_COEFF_DEV_A   0x03
69 #define TAS2563_BLOCK_CFG_COEFF_DEV_B   0x0a
70 #define TAS2563_BLOCK_CFG_PRE_DEV_A             0x04
71 #define TAS2563_BLOCK_CFG_PRE_DEV_B             0x0b
72 #define TAS2563_BLOCK_CFG_POST                  0x05
73 #define TAS2563_BLOCK_CFG_POST_POWER    0x06
75 static char pICN[] = {0x00, 0x03, 0x46, 0xdc};
76 static char const *iv_enable_text[] = {"Off", "On"};
77 static int tas2563iv_enable;
78 static const struct soc_enum tas2563_enum[] = {
79     SOC_ENUM_SINGLE_EXT(ARRAY_SIZE(iv_enable_text), iv_enable_text),
80 };
81 static int tas2563_set_fmt(struct tas2563_priv *pTAS2563, unsigned int fmt);
82 static void tas2563_clear_firmware(struct TFirmware *pFirmware);
84 static int fw_parse(struct tas2563_priv *pTAS2563,
85         struct TFirmware *pFirmware, unsigned char *pData, unsigned int nSize);
86 static bool tas2563_get_coefficient_in_block(struct tas2563_priv *pTAS2563,
87         struct TBlock *pBlock, int nReg, int *pnValue);
88 int tas2563_set_program(struct tas2563_priv *pTAS2563, unsigned int nProgram, int nConfig);
89 static int tas2563_set_calibration(struct tas2563_priv *pTAS2563, int nCalibration);
90 static int tas2563_load_configuration(struct tas2563_priv *pTAS2563,
91         unsigned int nConfiguration, bool bLoadSame);
92 static int tas2563_load_coefficient(struct tas2563_priv *pTAS2563,
93         int nPrevConfig, int nNewConfig, bool bPowerOn);
95 static unsigned int tas2563_codec_read(struct snd_soc_codec *codec,
96                 unsigned int reg)
97 {
98         struct tas2563_priv *pTAS2563 = snd_soc_codec_get_drvdata(codec);
99         int nResult = 0;
100         unsigned int value = 0;
102         nResult = pTAS2563->read(pTAS2563, reg, &value);
104         if (nResult < 0)
105                 dev_err(pTAS2563->dev, "%s, ERROR, reg=0x%x, E=%d\n",
106                         __func__, reg, nResult);
107         else
108                 dev_info(pTAS2563->dev, "%s, reg: 0x%x, value: 0x%x\n",
109                                 __func__, reg, value);
111         if (nResult >= 0)
112                 return value;
113         else
114                 return nResult;
117 static const unsigned char crc8_lookup_table[CRC8_TABLE_SIZE] = {
118 0x00, 0x4D, 0x9A, 0xD7, 0x79, 0x34, 0xE3, 0xAE, 0xF2, 0xBF, 0x68, 0x25, 0x8B, 0xC6, 0x11, 0x5C,
119 0xA9, 0xE4, 0x33, 0x7E, 0xD0, 0x9D, 0x4A, 0x07, 0x5B, 0x16, 0xC1, 0x8C, 0x22, 0x6F, 0xB8, 0xF5,
120 0x1F, 0x52, 0x85, 0xC8, 0x66, 0x2B, 0xFC, 0xB1, 0xED, 0xA0, 0x77, 0x3A, 0x94, 0xD9, 0x0E, 0x43,
121 0xB6, 0xFB, 0x2C, 0x61, 0xCF, 0x82, 0x55, 0x18, 0x44, 0x09, 0xDE, 0x93, 0x3D, 0x70, 0xA7, 0xEA,
122 0x3E, 0x73, 0xA4, 0xE9, 0x47, 0x0A, 0xDD, 0x90, 0xCC, 0x81, 0x56, 0x1B, 0xB5, 0xF8, 0x2F, 0x62,
123 0x97, 0xDA, 0x0D, 0x40, 0xEE, 0xA3, 0x74, 0x39, 0x65, 0x28, 0xFF, 0xB2, 0x1C, 0x51, 0x86, 0xCB,
124 0x21, 0x6C, 0xBB, 0xF6, 0x58, 0x15, 0xC2, 0x8F, 0xD3, 0x9E, 0x49, 0x04, 0xAA, 0xE7, 0x30, 0x7D,
125 0x88, 0xC5, 0x12, 0x5F, 0xF1, 0xBC, 0x6B, 0x26, 0x7A, 0x37, 0xE0, 0xAD, 0x03, 0x4E, 0x99, 0xD4,
126 0x7C, 0x31, 0xE6, 0xAB, 0x05, 0x48, 0x9F, 0xD2, 0x8E, 0xC3, 0x14, 0x59, 0xF7, 0xBA, 0x6D, 0x20,
127 0xD5, 0x98, 0x4F, 0x02, 0xAC, 0xE1, 0x36, 0x7B, 0x27, 0x6A, 0xBD, 0xF0, 0x5E, 0x13, 0xC4, 0x89,
128 0x63, 0x2E, 0xF9, 0xB4, 0x1A, 0x57, 0x80, 0xCD, 0x91, 0xDC, 0x0B, 0x46, 0xE8, 0xA5, 0x72, 0x3F,
129 0xCA, 0x87, 0x50, 0x1D, 0xB3, 0xFE, 0x29, 0x64, 0x38, 0x75, 0xA2, 0xEF, 0x41, 0x0C, 0xDB, 0x96,
130 0x42, 0x0F, 0xD8, 0x95, 0x3B, 0x76, 0xA1, 0xEC, 0xB0, 0xFD, 0x2A, 0x67, 0xC9, 0x84, 0x53, 0x1E,
131 0xEB, 0xA6, 0x71, 0x3C, 0x92, 0xDF, 0x08, 0x45, 0x19, 0x54, 0x83, 0xCE, 0x60, 0x2D, 0xFA, 0xB7,
132 0x5D, 0x10, 0xC7, 0x8A, 0x24, 0x69, 0xBE, 0xF3, 0xAF, 0xE2, 0x35, 0x78, 0xD6, 0x9B, 0x4C, 0x01,
133 0xF4, 0xB9, 0x6E, 0x23, 0x8D, 0xC0, 0x17, 0x5A, 0x06, 0x4B, 0x9C, 0xD1, 0x7F, 0x32, 0xE5, 0xA8
134 };
136 static int isInPageYRAM(struct tas2563_priv *pTAS2563, struct TYCRC *pCRCData,
137         unsigned char nBook, unsigned char nPage, unsigned char nReg, unsigned char len)
139         int nResult = 0;
141         if (nBook == TAS2563_YRAM_BOOK1) {
142                 if (nPage == TAS2563_YRAM1_PAGE) {
143                         if (nReg >= TAS2563_YRAM1_START_REG) {
144                                 pCRCData->mnOffset = nReg;
145                                 pCRCData->mnLen = len;
146                                 nResult = 1;
147                         } else if ((nReg + len) > TAS2563_YRAM1_START_REG) {
148                                 pCRCData->mnOffset = TAS2563_YRAM1_START_REG;
149                                 pCRCData->mnLen = len - (TAS2563_YRAM1_START_REG - nReg);
150                                 nResult = 1;
151                         } else
152                                 nResult = 0;
153                 } else if (nPage == TAS2563_YRAM3_PAGE) {
154                         if (nReg > TAS2563_YRAM3_END_REG) {
155                                 nResult = 0;
156                         } else if (nReg >= TAS2563_YRAM3_START_REG) {
157                                 if ((nReg + len) > TAS2563_YRAM3_END_REG) {
158                                         pCRCData->mnOffset = nReg;
159                                         pCRCData->mnLen = TAS2563_YRAM3_END_REG - nReg + 1;
160                                         nResult = 1;
161                                 } else {
162                                         pCRCData->mnOffset = nReg;
163                                         pCRCData->mnLen = len;
164                                         nResult = 1;
165                                 }
166                         } else {
167                                 if ((nReg + (len - 1)) < TAS2563_YRAM3_START_REG)
168                                         nResult = 0;
169                                 else {
170                                         pCRCData->mnOffset = TAS2563_YRAM3_START_REG;
171                                         pCRCData->mnLen = len - (TAS2563_YRAM3_START_REG - nReg);
172                                         nResult = 1;
173                                 }
174                         }
175                 }
176         } else if (nBook == TAS2563_YRAM_BOOK2) {
177                 if (nPage == TAS2563_YRAM5_PAGE) {
178                         if (nReg > TAS2563_YRAM5_END_REG) {
179                                 nResult = 0;
180                         } else if (nReg >= TAS2563_YRAM5_START_REG) {
181                                 if ((nReg + len) > TAS2563_YRAM5_END_REG) {
182                                         pCRCData->mnOffset = nReg;
183                                         pCRCData->mnLen = TAS2563_YRAM5_END_REG - nReg + 1;
184                                         nResult = 1;
185                                 } else {
186                                         pCRCData->mnOffset = nReg;
187                                         pCRCData->mnLen = len;
188                                         nResult = 1;
189                                 }
190                         } else {
191                                 if ((nReg + (len - 1)) < TAS2563_YRAM5_START_REG)
192                                         nResult = 0;
193                                 else {
194                                         pCRCData->mnOffset = TAS2563_YRAM5_START_REG;
195                                         pCRCData->mnLen = len - (TAS2563_YRAM5_START_REG - nReg);
196                                         nResult = 1;
197                                 }
198                         }
199                 }
200         } else
201                 nResult = 0;
203         return nResult;
206 static int isInBlockYRAM(struct tas2563_priv *pTAS2563, struct TYCRC *pCRCData,
207         unsigned char nBook, unsigned char nPage, unsigned char nReg, unsigned char len)
209         int nResult;
211         if (nBook == TAS2563_YRAM_BOOK1) {
212                 if (nPage < TAS2563_YRAM2_START_PAGE)
213                         nResult = 0;
214                 else if (nPage <= TAS2563_YRAM2_END_PAGE) {
215                         if (nReg > TAS2563_YRAM2_END_REG)
216                                 nResult = 0;
217                         else if (nReg >= TAS2563_YRAM2_START_REG) {
218                                 pCRCData->mnOffset = nReg;
219                                 pCRCData->mnLen = len;
220                                 nResult = 1;
221                         } else {
222                                 if ((nReg + (len - 1)) < TAS2563_YRAM2_START_REG)
223                                         nResult = 0;
224                                 else {
225                                         pCRCData->mnOffset = TAS2563_YRAM2_START_REG;
226                                         pCRCData->mnLen = nReg + len - TAS2563_YRAM2_START_REG;
227                                         nResult = 1;
228                                 }
229                         }
230                 } else
231                         nResult = 0;
232         } else if (nBook == TAS2563_YRAM_BOOK2) {
233                 if (nPage < TAS2563_YRAM4_START_PAGE)
234                         nResult = 0;
235                 else if (nPage <= TAS2563_YRAM4_END_PAGE) {
236                         if (nReg > TAS2563_YRAM2_END_REG)
237                                 nResult = 0;
238                         else if (nReg >= TAS2563_YRAM2_START_REG) {
239                                 pCRCData->mnOffset = nReg;
240                                 pCRCData->mnLen = len;
241                                 nResult = 1;
242                         } else {
243                                 if ((nReg + (len - 1)) < TAS2563_YRAM2_START_REG)
244                                         nResult = 0;
245                                 else {
246                                         pCRCData->mnOffset = TAS2563_YRAM2_START_REG;
247                                         pCRCData->mnLen = nReg + len - TAS2563_YRAM2_START_REG;
248                                         nResult = 1;
249                                 }
250                         }
251                 } else
252                         nResult = 0;
253         } else
254                 nResult = 0;
256         return nResult;
260 static int isYRAM(struct tas2563_priv *pTAS2563, struct TYCRC *pCRCData,
261         unsigned char nBook, unsigned char nPage, unsigned char nReg, unsigned char len)
263         int nResult;
265         nResult = isInPageYRAM(pTAS2563, pCRCData, nBook, nPage, nReg, len);
267         if (nResult == 0)
268                 nResult = isInBlockYRAM(pTAS2563, pCRCData, nBook, nPage, nReg, len);
270         return nResult;
273 /*
274  * crc8 - calculate a crc8 over the given input data.
275  *
276  * table: crc table used for calculation.
277  * pdata: pointer to data buffer.
278  * nbytes: number of bytes in data buffer.
279  * crc: previous returned crc8 value.
280  */
281 static u8 ti_crc8(const u8 table[CRC8_TABLE_SIZE], u8 *pdata, size_t nbytes, u8 crc)
283         /* loop over the buffer data */
284         while (nbytes-- > 0)
285                 crc = table[(crc ^ *pdata++) & 0xff];
287         return crc;
290 static int doSingleRegCheckSum(struct tas2563_priv *pTAS2563, 
291         unsigned char nBook, unsigned char nPage, unsigned char nReg, unsigned char nValue)
293         int nResult = 0;
294         struct TYCRC sCRCData;
295         unsigned int nData1 = 0;
297         if ((nBook == TAS2563_BOOK_ID(TAS2563_SA_COEFF_SWAP_REG))
298                 && (nPage == TAS2563_PAGE_ID(TAS2563_SA_COEFF_SWAP_REG))
299                 && (nReg >= TAS2563_PAGE_REG(TAS2563_SA_COEFF_SWAP_REG))
300                 && (nReg <= (TAS2563_PAGE_REG(TAS2563_SA_COEFF_SWAP_REG) + 4))) {
301                 /* DSP swap command, pass */
302                 nResult = 0;
303                 goto end;
304         }
306         nResult = isYRAM(pTAS2563, &sCRCData, nBook, nPage, nReg, 1);
307         if (nResult == 1) {
308                 nResult = pTAS2563->read(pTAS2563, TAS2563_REG(nBook, nPage, nReg), &nData1);
309                 if (nResult < 0)
310                         goto end;
312                 if (nData1 != nValue) {
313                         dev_err(pTAS2563->dev, "error2 (line %d),B[0x%x]P[0x%x]R[0x%x] W[0x%x], R[0x%x]\n",
314                                 __LINE__, nBook, nPage, nReg, nValue, nData1);
315                         nResult = -EAGAIN;
316                         goto end;
317                 }
319                 nResult = ti_crc8(crc8_lookup_table, &nValue, 1, 0);
320         }
322 end:
324         return nResult;
327 static int doMultiRegCheckSum(struct tas2563_priv *pTAS2563, 
328         unsigned char nBook, unsigned char nPage, unsigned char nReg, unsigned int len)
330         int nResult = 0, i;
331         unsigned char nCRCChkSum = 0;
332         unsigned char nBuf1[128];
333         struct TYCRC TCRCData;
334         
335         return 0;
337         if ((nReg + len-1) > 127) {
338                 nResult = -EINVAL;
339                 dev_err(pTAS2563->dev, "firmware error\n");
340                 goto end;
341         }
343         if ((nBook == TAS2563_BOOK_ID(TAS2563_SA_COEFF_SWAP_REG))
344                 && (nPage == TAS2563_PAGE_ID(TAS2563_SA_COEFF_SWAP_REG))
345                 && (nReg == TAS2563_PAGE_REG(TAS2563_SA_COEFF_SWAP_REG))
346                 && (len == 4)) {
347                 /* DSP swap command, pass */
348                 nResult = 0;
349                 goto end;
350         }
352         nResult = isYRAM(pTAS2563, &TCRCData, nBook, nPage, nReg, len);
353         dev_info(pTAS2563->dev, "isYRAM: nBook 0x%x, nPage 0x%x, nReg 0x%x\n", nBook, nPage, nReg);
354         dev_info(pTAS2563->dev, "isYRAM: TCRCData.mnLen 0x%x, len 0x%x, nResult %d\n", TCRCData.mnLen, len, nResult);
355         dev_info(pTAS2563->dev, "TCRCData.mnOffset %x\n", TCRCData.mnOffset);
356         if (nResult == 1) {
357                 if (len == 1) {
358                         dev_err(pTAS2563->dev, "firmware error\n");
359                         nResult = -EINVAL;
360                         goto end;
361                 } else {
362                         nResult = pTAS2563->bulk_read(pTAS2563, TAS2563_REG(nBook, nPage, TCRCData.mnOffset), nBuf1, TCRCData.mnLen);
363                         if (nResult < 0)
364                                 goto end;
366                         for (i = 0; i < TCRCData.mnLen; i++) {
367                                 if ((nBook == TAS2563_BOOK_ID(TAS2563_SA_COEFF_SWAP_REG))
368                                         && (nPage == TAS2563_PAGE_ID(TAS2563_SA_COEFF_SWAP_REG))
369                                         && ((i + TCRCData.mnOffset)
370                                                 >= TAS2563_PAGE_REG(TAS2563_SA_COEFF_SWAP_REG))
371                                         && ((i + TCRCData.mnOffset)
372                                                 <= (TAS2563_PAGE_REG(TAS2563_SA_COEFF_SWAP_REG) + 4))) {
373                                         /* DSP swap command, bypass */
374                                         continue;
375                                 } else
376                                         nCRCChkSum += ti_crc8(crc8_lookup_table, &nBuf1[i], 1, 0);
377                         }
379                         nResult = nCRCChkSum;
380                 }
381         }
383 end:
385         return nResult;
389 static int tas2563_load_block(struct tas2563_priv *pTAS2563, struct TBlock *pBlock)
391         int nResult = 0;
392         unsigned int nCommand = 0;
393         unsigned char nBook;
394         unsigned char nPage;
395         unsigned char nOffset;
396         unsigned char nData;
397         unsigned int nLength;
398         unsigned int nSleep;
399         unsigned char nCRCChkSum = 0;
400         unsigned int nValue;
401         int nRetry = 6;
402         unsigned char *pData = pBlock->mpData;
404         dev_info(pTAS2563->dev, "TAS2563 load block: Type = %d, commands = %d\n",
405                 pBlock->mnType, pBlock->mnCommands);
406 start:
407         if (pBlock->mbPChkSumPresent) {
408                 nResult = pTAS2563->write(pTAS2563, TAS2563_I2CChecksum, 0);
409                 if (nResult < 0)
410                         goto end;
411         }
413         if (pBlock->mbYChkSumPresent)
414                 nCRCChkSum = 0;
416         nCommand = 0;
418         while (nCommand < pBlock->mnCommands) {
419                 pData = pBlock->mpData + nCommand * 4;
421                 nBook = pData[0];
422                 nPage = pData[1];
423                 nOffset = pData[2];
424                 nData = pData[3];
426                 nCommand++;
428                 if (nOffset <= 0x7F) {
429                         nResult = pTAS2563->write(pTAS2563, TAS2563_REG(nBook, nPage, nOffset), nData);
430                         if (nResult < 0)
431                                 goto end;
432                         if (pBlock->mbYChkSumPresent) {
433                                 nResult = doSingleRegCheckSum(pTAS2563, nBook, nPage, nOffset, nData);
434                                 if (nResult < 0)
435                                         goto check;
436                                 nCRCChkSum += (unsigned char)nResult;
437                         }
438                 } else if (nOffset == 0x81) {
439                         nSleep = (nBook << 8) + nPage;
440                         msleep(nSleep);
441                 } else if (nOffset == 0x85) {
442                         pData += 4;
443                         nLength = (nBook << 8) + nPage;
444                         nBook = pData[0];
445                         nPage = pData[1];
446                         nOffset = pData[2];
447                         if (nLength > 1) {
448                                 nResult = pTAS2563->bulk_write(pTAS2563, TAS2563_REG(nBook, nPage, nOffset), pData + 3, nLength);
449                                 if (nResult < 0)
450                                         goto end;
451                                 if (pBlock->mbYChkSumPresent) {
452                                         nResult = doMultiRegCheckSum(pTAS2563, nBook, nPage, nOffset, nLength);
453                                         if (nResult < 0)
454                                                 goto check;
455                                         nCRCChkSum += (unsigned char)nResult;
456                                 }
457                         } else {
458                                 nResult = pTAS2563->write(pTAS2563, TAS2563_REG(nBook, nPage, nOffset), pData[3]);
459                                 if (nResult < 0)
460                                         goto end;
461                                 if (pBlock->mbYChkSumPresent) {
462                                         nResult = doSingleRegCheckSum(pTAS2563, nBook, nPage, nOffset, pData[3]);
463                                         if (nResult < 0)
464                                                 goto check;
465                                         nCRCChkSum += (unsigned char)nResult;
466                                 }
467                         }
469                         nCommand++;
471                         if (nLength >= 2)
472                                 nCommand += ((nLength - 2) / 4) + 1;
473                 }
474         }
475         if (pBlock->mbPChkSumPresent) {
476                 nResult = pTAS2563->read(pTAS2563, TAS2563_I2CChecksum, &nValue);
477                 dev_err(pTAS2563->dev, "Block PChkSum: FW = 0x%x, Reg = 0x%x\n",
478                                 pBlock->mnPChkSum, (nValue&0xff));
480                 if (nResult < 0)
481                         goto end;
482                 if ((nValue&0xff) != pBlock->mnPChkSum) {
483                         dev_err(pTAS2563->dev, "Block PChkSum Error: FW = 0x%x, Reg = 0x%x\n",
484                                 pBlock->mnPChkSum, (nValue&0xff));
485                         nResult = -EAGAIN;
486                                 pTAS2563->mnErrCode |= ERROR_PRAM_CRCCHK;
487                         goto check;
488                 }
490                 nResult = 0;
491                 pTAS2563->mnErrCode &= ~ERROR_PRAM_CRCCHK;
492                 dev_info(pTAS2563->dev, "Block[0x%x] PChkSum match\n", pBlock->mnType);
493         }
495         if (pBlock->mbYChkSumPresent) {
496                 //TBD, open it when FW ready
497                 dev_err(pTAS2563->dev, "Block YChkSum: FW = 0x%x, YCRC = 0x%x\n",
498                                 pBlock->mnYChkSum, nCRCChkSum);
499 /*
500                 if (nCRCChkSum != pBlock->mnYChkSum) {
501                         dev_err(pTAS2563->dev, "Block YChkSum Error: FW = 0x%x, YCRC = 0x%x\n",
502                                 pBlock->mnYChkSum, nCRCChkSum);
503                         nResult = -EAGAIN;
504                         pTAS2563->mnErrCode |= ERROR_YRAM_CRCCHK;
505                         goto check;
506                 }
507 */
508                 pTAS2563->mnErrCode &= ~ERROR_YRAM_CRCCHK;
509                 nResult = 0;
510                 dev_info(pTAS2563->dev, "Block[0x%x] YChkSum match\n", pBlock->mnType);
511         }
513 check:
514         if (nResult == -EAGAIN) {
515                 nRetry--;
516                 if (nRetry > 0)
517                         goto start;
518         }
520 end:
521         if (nResult < 0) {
522                 dev_err(pTAS2563->dev, "Block (%d) load error\n",
523                                 pBlock->mnType);
524         }
525         return nResult;
529 static int tas2563_load_data(struct tas2563_priv *pTAS2563, struct TData *pData, unsigned int nType)
531         int nResult = 0;
532         unsigned int nBlock;
533         struct TBlock *pBlock;
535         dev_info(pTAS2563->dev,
536                 "TAS2563 load data: %s, Blocks = %d, Block Type = %d\n", pData->mpName, pData->mnBlocks, nType);
538         for (nBlock = 0; nBlock < pData->mnBlocks; nBlock++) {
539                 pBlock = &(pData->mpBlocks[nBlock]);
540                 if (pBlock->mnType == nType) {
541                         nResult = tas2563_load_block(pTAS2563, pBlock);
542                         if (nResult < 0)
543                                 break;
544                 }
545         }
547         return nResult;
550 void tas2563_clear_firmware(struct TFirmware *pFirmware)
552         unsigned int n, nn;
554         if (!pFirmware)
555                 return;
557         kfree(pFirmware->mpDescription);
559         if (pFirmware->mpPLLs != NULL) {
560                 for (n = 0; n < pFirmware->mnPLLs; n++) {
561                         kfree(pFirmware->mpPLLs[n].mpDescription);
562                         kfree(pFirmware->mpPLLs[n].mBlock.mpData);
563                 }
564                 kfree(pFirmware->mpPLLs);
565         }
567         if (pFirmware->mpPrograms != NULL) {
568                 for (n = 0; n < pFirmware->mnPrograms; n++) {
569                         kfree(pFirmware->mpPrograms[n].mpDescription);
570                         kfree(pFirmware->mpPrograms[n].mData.mpDescription);
571                         for (nn = 0; nn < pFirmware->mpPrograms[n].mData.mnBlocks; nn++)
572                                 kfree(pFirmware->mpPrograms[n].mData.mpBlocks[nn].mpData);
573                         kfree(pFirmware->mpPrograms[n].mData.mpBlocks);
574                 }
575                 kfree(pFirmware->mpPrograms);
576         }
578         if (pFirmware->mpConfigurations != NULL) {
579                 for (n = 0; n < pFirmware->mnConfigurations; n++) {
580                         kfree(pFirmware->mpConfigurations[n].mpDescription);
581                         kfree(pFirmware->mpConfigurations[n].mData.mpDescription);
582                         for (nn = 0; nn < pFirmware->mpConfigurations[n].mData.mnBlocks; nn++)
583                                 kfree(pFirmware->mpConfigurations[n].mData.mpBlocks[nn].mpData);
584                         kfree(pFirmware->mpConfigurations[n].mData.mpBlocks);
585                 }
586                 kfree(pFirmware->mpConfigurations);
587         }
589         if (pFirmware->mpCalibrations != NULL) {
590                 for (n = 0; n < pFirmware->mnCalibrations; n++) {
591                         kfree(pFirmware->mpCalibrations[n].mpDescription);
592                         kfree(pFirmware->mpCalibrations[n].mData.mpDescription);
593                         for (nn = 0; nn < pFirmware->mpCalibrations[n].mData.mnBlocks; nn++)
594                                 kfree(pFirmware->mpCalibrations[n].mData.mpBlocks[nn].mpData);
595                         kfree(pFirmware->mpCalibrations[n].mData.mpBlocks);
596                 }
597                 kfree(pFirmware->mpCalibrations);
598         }
600         memset(pFirmware, 0x00, sizeof(struct TFirmware));
603 static int tas2563_load_configuration(struct tas2563_priv *pTAS2563,
604         unsigned int nConfiguration, bool bLoadSame)
606         int nResult = 0;
607         struct TConfiguration *pCurrentConfiguration = NULL;
608         struct TConfiguration *pNewConfiguration = NULL;
610         dev_info(pTAS2563->dev, "%s: %d\n", __func__, nConfiguration);
612         if ((!pTAS2563->mpFirmware->mpPrograms) ||
613                 (!pTAS2563->mpFirmware->mpConfigurations)) {
614                 dev_err(pTAS2563->dev, "%s, Firmware not loaded\n", __func__);
615                 nResult = 0;
616                 goto end;
617         }
619         if (nConfiguration >= pTAS2563->mpFirmware->mnConfigurations) {
620                 dev_err(pTAS2563->dev, "Configuration %d doesn't exist\n",
621                         nConfiguration);
622                 nResult = 0;
623                 goto end;
624         }
626         if ((!pTAS2563->mbLoadConfigurationPrePowerUp)
627                 && (nConfiguration == pTAS2563->mnCurrentConfiguration)
628                 && (!bLoadSame)) {
629                 dev_info(pTAS2563->dev, "Configuration %d is already loaded\n",
630                         nConfiguration);
631                 nResult = 0;
632                 goto end;
633         }
635         pCurrentConfiguration =
636                 &(pTAS2563->mpFirmware->mpConfigurations[pTAS2563->mnCurrentConfiguration]);
637         pNewConfiguration =
638                 &(pTAS2563->mpFirmware->mpConfigurations[nConfiguration]);
639         if (pNewConfiguration->mnProgram != pCurrentConfiguration->mnProgram) {
640                 dev_err(pTAS2563->dev, "Configuration %d, %s doesn't share the same program as current %d\n",
641                         nConfiguration, pNewConfiguration->mpName, pCurrentConfiguration->mnProgram);
642                 nResult = 0;
643                 goto end;
644         }
646         if (pTAS2563->mbPowerUp) {
647                 pTAS2563->mbLoadConfigurationPrePowerUp = false;
648                 nResult = tas2563_load_coefficient(pTAS2563, pTAS2563->mnCurrentConfiguration, nConfiguration, true);
649         } else {
650                 dev_info(pTAS2563->dev,
651                         "TAS2563 was powered down, will load coefficient when power up\n");
652                 pTAS2563->mbLoadConfigurationPrePowerUp = true;
653                 pTAS2563->mnNewConfiguration = nConfiguration;
654         }
656 end:
658 /*      if (nResult < 0) {
659                 if (pTAS2563->mnErrCode & (ERROR_DEVA_I2C_COMM | ERROR_PRAM_CRCCHK | ERROR_YRAM_CRCCHK))
660                         failsafe(pTAS2563);
661         }
662 */
663         return nResult;
666 static int tas2563_load_calibration(struct tas2563_priv *pTAS2563,      char *pFileName)
668         int nResult = 0;
670         int nFile;
671         mm_segment_t fs;
672         unsigned char pBuffer[1000];
673         int nSize = 0;
675         dev_info(pTAS2563->dev, "%s:\n", __func__);
677         fs = get_fs();
678         set_fs(KERNEL_DS);
679         nFile = sys_open(pFileName, O_RDONLY, 0);
681         dev_info(pTAS2563->dev, "TAS2563 calibration file = %s, handle = %d\n",
682                 pFileName, nFile);
684         if (nFile >= 0) {
685                 nSize = sys_read(nFile, pBuffer, 1000);
686                 sys_close(nFile);
687         } else {
688                 dev_err(pTAS2563->dev, "TAS2563 cannot open calibration file: %s\n",
689                         pFileName);
690         }
692         set_fs(fs);
694         if (!nSize)
695                 goto end;
697         tas2563_clear_firmware(pTAS2563->mpCalFirmware);
698         dev_info(pTAS2563->dev, "TAS2563 calibration file size = %d\n", nSize);
699         nResult = fw_parse(pTAS2563, pTAS2563->mpCalFirmware, pBuffer, nSize);
701         if (nResult)
702                 dev_err(pTAS2563->dev, "TAS2563 calibration file is corrupt\n");
703         else
704                 dev_info(pTAS2563->dev, "TAS2563 calibration: %d calibrations\n",
705                         pTAS2563->mpCalFirmware->mnCalibrations);
706 end:
708         return nResult;
712 static int tas2563iv_put(struct snd_kcontrol *kcontrol,
713                                    struct snd_ctl_elem_value *ucontrol)
715 #ifdef KCONTROL_CODEC
716         struct snd_soc_codec *codec = snd_soc_kcontrol_codec(kcontrol);
717 #else
718         struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol);
719 #endif
721     if (codec == NULL) {
722                 pr_err("%s: codec is NULL \n",  __func__);
723                 return 0;
724     }
726     tas2563iv_enable = ucontrol->value.integer.value[0];
728         if (tas2563iv_enable) {
729                 pr_debug("%s: tas2563iv_enable \n", __func__);
730                 snd_soc_update_bits(codec, TAS2563_PowerControl,
731                         TAS2563_PowerControl_OperationalMode10_Mask |
732                     TAS2563_PowerControl_ISNSPower_Mask |
733                     TAS2563_PowerControl_VSNSPower_Mask,
734                     TAS2563_PowerControl_OperationalMode10_Active |
735                     TAS2563_PowerControl_VSNSPower_Active |
736                     TAS2563_PowerControl_ISNSPower_Active);
737         } else {
738                 pr_debug("%s: tas2563iv_disable \n", __func__);
739                 snd_soc_update_bits(codec, TAS2563_PowerControl,
740                         TAS2563_PowerControl_OperationalMode10_Mask |
741                         TAS2563_PowerControl_ISNSPower_Mask |
742                         TAS2563_PowerControl_VSNSPower_Mask,
743                         TAS2563_PowerControl_OperationalMode10_Active |
744                         TAS2563_PowerControl_VSNSPower_PoweredDown |
745                         TAS2563_PowerControl_ISNSPower_PoweredDown);
746         }
748         pr_debug("%s: tas2563iv_enable = %d\n", __func__, tas2563iv_enable);
750         return 0;
753 static int tas2563iv_get(struct snd_kcontrol *kcontrol,
754                                   struct snd_ctl_elem_value *ucontrol)
756    int value;
757    ucontrol->value.integer.value[0] = tas2563iv_enable;
758    value=gpio_get_value(37);
759    pr_debug("%s: tas2563iv_enable = %d\n", __func__, tas2563iv_enable);
760    pr_debug("%s: gpio37 value = %d\n", __func__, value);
761    return 0;
764 static const struct snd_kcontrol_new tas2563_controls[] = {
765 SOC_ENUM_EXT("TAS2563 IVSENSE ENABLE", tas2563_enum[1],
766                     tas2563iv_get, tas2563iv_put),
767 };
769 static int tas2563_codec_write(struct snd_soc_codec *codec, unsigned int reg,
770         unsigned int value)
772         struct tas2563_priv *pTAS2563 = snd_soc_codec_get_drvdata(codec);
774         int nResult = 0;
776         nResult = pTAS2563->write(pTAS2563, reg, value);
777         if (nResult < 0)
778                 dev_err(pTAS2563->dev, "%s, ERROR, reg=0x%x, E=%d\n",
779                         __func__, reg, nResult);
780         else
781                 dev_info(pTAS2563->dev, "%s, reg: 0x%x, 0x%x\n",
782                         __func__, reg, value);
784         return nResult;
788 static void fw_print_header(struct tas2563_priv *pTAS2563, struct TFirmware *pFirmware)
790         dev_info(pTAS2563->dev, "FW Size       = %d", pFirmware->mnFWSize);
791         dev_info(pTAS2563->dev, "Checksum      = 0x%04X", pFirmware->mnChecksum);
792         dev_info(pTAS2563->dev, "PPC Version   = 0x%04X", pFirmware->mnPPCVersion);
793         dev_info(pTAS2563->dev, "FW  Version    = 0x%04X", pFirmware->mnFWVersion);
794         dev_info(pTAS2563->dev, "Driver Version= 0x%04X", pFirmware->mnDriverVersion);
795         dev_info(pTAS2563->dev, "Timestamp     = %d", pFirmware->mnTimeStamp);
796         dev_info(pTAS2563->dev, "DDC Name      = %s", pFirmware->mpDDCName);
797         dev_info(pTAS2563->dev, "Description   = %s", pFirmware->mpDescription);
800 inline unsigned int fw_convert_number(unsigned char *pData)
802         return pData[3] + (pData[2] << 8) + (pData[1] << 16) + (pData[0] << 24);
805 static int fw_parse_header(struct tas2563_priv *pTAS2563,
806         struct TFirmware *pFirmware, unsigned char *pData, unsigned int nSize)
808         unsigned char *pDataStart = pData;
809         unsigned int n;
810         unsigned char pMagicNumber[] = { 0x35, 0x35, 0x35, 0x32 };
812         if (nSize < 104) {
813                 dev_err(pTAS2563->dev, "Firmware: Header too short");
814                 return -EINVAL;
815         }
817         if (memcmp(pData, pMagicNumber, 4)) {
818                 dev_err(pTAS2563->dev, "Firmware: Magic number doesn't match");
819                 return -EINVAL;
820         }
821         pData += 4;
823         pFirmware->mnFWSize = fw_convert_number(pData);
824         pData += 4;
825         dev_info(pTAS2563->dev, "firmware size: %d", pFirmware->mnFWSize);
827         pFirmware->mnChecksum = fw_convert_number(pData);
828         pData += 4;
830         pFirmware->mnPPCVersion = fw_convert_number(pData);
831         pData += 4;
833         pFirmware->mnFWVersion = fw_convert_number(pData);
834         pData += 4;
836         pFirmware->mnDriverVersion = fw_convert_number(pData);
837         pData += 4;
839         pFirmware->mnTimeStamp = fw_convert_number(pData);
840         pData += 4;
841         dev_info(pTAS2563->dev, "FW timestamp: %d", pFirmware->mnTimeStamp);
843         memcpy(pFirmware->mpDDCName, pData, 64);
844         pData += 64;
846         n = strlen(pData);
847         pFirmware->mpDescription = kmemdup(pData, n + 1, GFP_KERNEL);
848         pData += n + 1;
849         if ((pData - pDataStart) >= nSize) {
850                 dev_err(pTAS2563->dev, "Firmware: Header too short after DDC description");
851                 return -EINVAL;
852         }
854         pFirmware->mnDeviceFamily = fw_convert_number(pData);
855         pData += 4;
856         if (pFirmware->mnDeviceFamily != 0) {
857                 dev_err(pTAS2563->dev,
858                         "deviceFamily %d, not TAS device", pFirmware->mnDeviceFamily);
859                 return -EINVAL;
860         }
862         pFirmware->mnDevice = fw_convert_number(pData);
863         pData += 4;
865         if (pFirmware->mnDevice != 5) {
866                 dev_err(pTAS2563->dev,
867                         "device %d, not TAS2563", pFirmware->mnDevice);
868                 return -EINVAL;
869         }
871         fw_print_header(pTAS2563, pFirmware);
872         return pData - pDataStart;
875 static int fw_parse_block_data(struct tas2563_priv *pTAS2563, struct TFirmware *pFirmware,
876         struct TBlock *pBlock, unsigned char *pData)
878         unsigned char *pDataStart = pData;
879         unsigned int n;
881         dev_info(pTAS2563->dev, "%s, %d", __func__, __LINE__);
883         pBlock->mnType = fw_convert_number(pData);
884         pData += 4;
885         dev_info(pTAS2563->dev, "%s, %d", __func__, __LINE__);
887         if (pFirmware->mnDriverVersion >= PPC_DRIVER_CRCCHK) {
888                 pBlock->mbPChkSumPresent = pData[0];
889                 pData++;
891                 pBlock->mnPChkSum = pData[0];
892                 pData++;
894                 pBlock->mbYChkSumPresent = pData[0];
895                 pData++;
897                 pBlock->mnYChkSum = pData[0];
898                 pData++;
899         } else {
900                 pBlock->mbPChkSumPresent = 0;
901                 pBlock->mbYChkSumPresent = 0;
902         }
904         pBlock->mnCommands = fw_convert_number(pData);
905         pData += 4;
907         n = pBlock->mnCommands * 4;
908         pBlock->mpData = kmemdup(pData, n, GFP_KERNEL);
909         pData += n;
910         dev_info(pTAS2563->dev, "%s, %d", __func__, __LINE__);
911         return pData - pDataStart;
914 static int fw_parse_data(struct tas2563_priv *pTAS2563, struct TFirmware *pFirmware,
915         struct TData *pImageData, unsigned char *pData)
917         unsigned char *pDataStart = pData;
918         unsigned int nBlock;
919         unsigned int n;
921         dev_info(pTAS2563->dev, "%s, %d", __func__, __LINE__);
922         memcpy(pImageData->mpName, pData, 64);
923         pData += 64;
925         n = strlen(pData);
926         pImageData->mpDescription = kmemdup(pData, n + 1, GFP_KERNEL);
927         pData += n + 1;
929         pImageData->mnBlocks = (pData[0] << 8) + pData[1];
930         pData += 2;
932         pImageData->mpBlocks =
933                 kmalloc(sizeof(struct TBlock) * pImageData->mnBlocks, GFP_KERNEL);
935         for (nBlock = 0; nBlock < pImageData->mnBlocks; nBlock++) {
936                 n = fw_parse_block_data(pTAS2563, pFirmware,
937                         &(pImageData->mpBlocks[nBlock]), pData);
938                 pData += n;
939         }
940         return pData - pDataStart;
943 #if 0
944 static int fw_parse_pll_data(struct tas2563_priv *pTAS2563,
945         struct TFirmware *pFirmware, unsigned char *pData)
947         unsigned char *pDataStart = pData;
948         unsigned int n;
949         unsigned int nPLL;
950         struct TPLL *pPLL;
952         pFirmware->mnPLLs = (pData[0] << 8) + pData[1];
953         pData += 2;
955         if (pFirmware->mnPLLs == 0)
956                 goto end;
958         pFirmware->mpPLLs = kmalloc_array(pFirmware->mnPLLs, sizeof(struct TPLL), GFP_KERNEL);
959         for (nPLL = 0; nPLL < pFirmware->mnPLLs; nPLL++) {
960                 pPLL = &(pFirmware->mpPLLs[nPLL]);
962                 memcpy(pPLL->mpName, pData, 64);
963                 pData += 64;
965                 n = strlen(pData);
966                 pPLL->mpDescription = kmemdup(pData, n + 1, GFP_KERNEL);
967                 pData += n + 1;
969                 n = fw_parse_block_data(pTAS2563, pFirmware, &(pPLL->mBlock), pData);
970                 pData += n;
971         }
973 end:
974         return pData - pDataStart;
976 #endif
978 static int fw_parse_program_data(struct tas2563_priv *pTAS2563,
979         struct TFirmware *pFirmware, unsigned char *pData)
981         unsigned char *pDataStart = pData;
982         unsigned int n;
983         unsigned int nProgram;
984         struct TProgram *pProgram;
986         pFirmware->mnPrograms = (pData[0] << 8) + pData[1];
987         pData += 2;
989         if (pFirmware->mnPrograms == 0)
990                 goto end;
992         pFirmware->mpPrograms =
993                 kmalloc(sizeof(struct TProgram) * pFirmware->mnPrograms, GFP_KERNEL);
994         for (nProgram = 0; nProgram < pFirmware->mnPrograms; nProgram++) {
995                 pProgram = &(pFirmware->mpPrograms[nProgram]);
996                 memcpy(pProgram->mpName, pData, 64);
997                 pData += 64;
999                 n = strlen(pData);
1000                 pProgram->mpDescription = kmemdup(pData, n + 1, GFP_KERNEL);
1001                 pData += n + 1;
1003                 pProgram->mnAppMode = pData[0];
1004                 pData++;
1006                 /*pProgram->mnBoost = (pData[0] << 8) + pData[1];
1007                 pData += 2;*/
1008                 pProgram->mnI2sMode = pData[0];
1009                 pData++;
1010                 dev_info(pTAS2563->dev, "FW i2sMode: %d", pProgram->mnI2sMode);
1012                 pProgram->mnISnsPD = pData[0];
1013                 pData++;
1015                 pProgram->mnVSnsPD = pData[0];
1016                 pData++;
1018                 pProgram->mnPowerLDG = pData[0];
1019                 pData++;
1021                 n = fw_parse_data(pTAS2563, pFirmware, &(pProgram->mData), pData);
1022                 pData += n;
1023                 dev_info(pTAS2563->dev, "program data number: %d", n);
1024         }
1026 end:
1028         return pData - pDataStart;
1031 static int fw_parse_configuration_data(struct tas2563_priv *pTAS2563,
1032         struct TFirmware *pFirmware, unsigned char *pData)
1034         unsigned char *pDataStart = pData;
1035         unsigned int n;
1036         unsigned int nConfiguration;
1037         struct TConfiguration *pConfiguration;
1039         pFirmware->mnConfigurations = (pData[0] << 8) + pData[1];
1040         pData += 2;
1042         if (pFirmware->mnConfigurations == 0)
1043                 goto end;
1045         pFirmware->mpConfigurations =
1046                 kmalloc(sizeof(struct TConfiguration) * pFirmware->mnConfigurations,
1047                 GFP_KERNEL);
1048         for (nConfiguration = 0; nConfiguration < pFirmware->mnConfigurations;
1049                 nConfiguration++) {
1050                 pConfiguration = &(pFirmware->mpConfigurations[nConfiguration]);
1051                 memcpy(pConfiguration->mpName, pData, 64);
1052                 pData += 64;
1054                 n = strlen(pData);
1055                 pConfiguration->mpDescription = kmemdup(pData, n + 1, GFP_KERNEL);
1056                 pData += n + 1;
1058 /*
1059                 if ((pFirmware->mnDriverVersion >= PPC_DRIVER_CONFDEV)
1060                         || ((pFirmware->mnDriverVersion >= PPC_DRIVER_CFGDEV_NONCRC)
1061                                 && (pFirmware->mnDriverVersion < PPC_DRIVER_CRCCHK))) {*/
1062                         pConfiguration->mnDevices = (pData[0] << 8) + pData[1];
1063                         pData += 2;
1064 /*              } else
1065                         pConfiguration->mnDevices = 1;*/
1067                 pConfiguration->mnProgram = pData[0];
1068                 pData++;
1069                 dev_info(pTAS2563->dev, "configuration, mnProgram: %d", pConfiguration->mnProgram);
1071                 pConfiguration->mnSamplingRate = fw_convert_number(pData);
1072                 pData += 4;
1073                 dev_info(pTAS2563->dev, "configuration samplerate: %d", pConfiguration->mnSamplingRate);
1075                 //if (pFirmware->mnDriverVersion >= PPC_DRIVER_MTPLLSRC) {
1076                         pConfiguration->mnPLLSrc = pData[0];
1077                         pData++;
1079                         pConfiguration->mnPLLSrcRate = fw_convert_number(pData);
1080                         pData += 4;
1081                 //}
1083                 pConfiguration->mnFsRate = (pData[0] << 8) + pData[1];
1084                 pData += 2;
1085                 dev_info(pTAS2563->dev, "Fs rate: %d", pConfiguration->mnFsRate);
1087                 n = fw_parse_data(pTAS2563, pFirmware, &(pConfiguration->mData), pData);
1088                 pData += n;
1089         }
1091 end:
1093         return pData - pDataStart;
1096 int fw_parse_calibration_data(struct tas2563_priv *pTAS2563,
1097         struct TFirmware *pFirmware, unsigned char *pData)
1099         unsigned char *pDataStart = pData;
1100         unsigned int n;
1101         unsigned int nCalibration;
1102         struct TCalibration *pCalibration;
1104         pFirmware->mnCalibrations = (pData[0] << 8) + pData[1];
1105         pData += 2;
1107         if (pFirmware->mnCalibrations == 0)
1108                 goto end;
1110         pFirmware->mpCalibrations =
1111                 kmalloc(sizeof(struct TCalibration) * pFirmware->mnCalibrations, GFP_KERNEL);
1112         for (nCalibration = 0;
1113                 nCalibration < pFirmware->mnCalibrations;
1114                 nCalibration++) {
1115                 pCalibration = &(pFirmware->mpCalibrations[nCalibration]);
1116                 memcpy(pCalibration->mpName, pData, 64);
1117                 pData += 64;
1119                 n = strlen(pData);
1120                 pCalibration->mpDescription = kmemdup(pData, n + 1, GFP_KERNEL);
1121                 pData += n + 1;
1123                 pCalibration->mnProgram = pData[0];
1124                 pData++;
1126                 pCalibration->mnConfiguration = pData[0];
1127                 pData++;
1129                 n = fw_parse_data(pTAS2563, pFirmware, &(pCalibration->mData), pData);
1130                 pData += n;
1131         }
1133 end:
1135         return pData - pDataStart;
1138 static int fw_parse(struct tas2563_priv *pTAS2563,
1139         struct TFirmware *pFirmware, unsigned char *pData, unsigned int nSize)
1141         int nPosition = 0;
1143         nPosition = fw_parse_header(pTAS2563, pFirmware, pData, nSize);
1144         dev_info(pTAS2563->dev, "header size: %d, line: %d\n", nPosition, __LINE__);
1145         if (nPosition < 0) {
1146                 dev_err(pTAS2563->dev, "Firmware: Wrong Header");
1147                 return -EINVAL;
1148         }
1150         if (nPosition >= nSize) {
1151                 dev_err(pTAS2563->dev, "Firmware: Too short");
1152                 return -EINVAL;
1153         }
1155         pData += nPosition;
1156         nSize -= nPosition;
1157         nPosition = 0;
1159         /*removed pll section*/
1160 /*      nPosition = fw_parse_pll_data(pTAS2563, pFirmware, pData);
1162         pData += nPosition;
1163         nSize -= nPosition;
1164         nPosition = 0;
1165 */
1167         nPosition = fw_parse_program_data(pTAS2563, pFirmware, pData);
1168         dev_info(pTAS2563->dev, "program size: %d, line: %d\n", nPosition, __LINE__);
1170         pData += nPosition;
1171         nSize -= nPosition;
1172         nPosition = 0;
1174         nPosition = fw_parse_configuration_data(pTAS2563, pFirmware, pData);
1175         dev_info(pTAS2563->dev, "config size: %d, line: %d\n", nPosition, __LINE__);
1177         pData += nPosition;
1178         nSize -= nPosition;
1179         nPosition = 0;
1181         if (nSize > 64)
1182                 nPosition = fw_parse_calibration_data(pTAS2563, pFirmware, pData);
1183         dev_info(pTAS2563->dev, "calib size: %d, line: %d\n", nPosition, __LINE__);
1184         return 0;
1188 static int tas2563_codec_suspend(struct snd_soc_codec *codec)
1190         struct tas2563_priv *pTAS2563 = snd_soc_codec_get_drvdata(codec);
1191         int ret = 0;
1193         mutex_lock(&pTAS2563->codec_lock);
1195         dev_info(pTAS2563->dev, "%s\n", __func__);
1196         pTAS2563->runtime_suspend(pTAS2563);
1198         mutex_unlock(&pTAS2563->codec_lock);
1199         return ret;
1202 static int tas2563_codec_resume(struct snd_soc_codec *codec)
1204         struct tas2563_priv *pTAS2563 = snd_soc_codec_get_drvdata(codec);
1205         int ret = 0;
1207         mutex_lock(&pTAS2563->codec_lock);
1209         dev_info(pTAS2563->dev, "%s\n", __func__);
1210         pTAS2563->runtime_resume(pTAS2563);
1212         mutex_unlock(&pTAS2563->codec_lock);
1213         return ret;
1216 static const struct snd_kcontrol_new tas2563_asi_controls[] = {
1217         SOC_DAPM_SINGLE("Left", TAS2563_TDMConfigurationReg2,
1218                 4, 1, 0),
1219         SOC_DAPM_SINGLE("Right", TAS2563_TDMConfigurationReg2,
1220                 4, 2, 0),
1221         SOC_DAPM_SINGLE("LeftRightDiv2", TAS2563_TDMConfigurationReg2,
1222                 4, 3, 0),
1223 };
1225 static int tas2563_set_power_state(struct tas2563_priv *pTAS2563, int state)
1227         int nResult = 0;
1228         /*unsigned int nValue;*/
1229         const char *pFWName;
1230         struct TProgram *pProgram;
1232         dev_info(pTAS2563->dev, "set power state: %d\n", state);
1234         if ((pTAS2563->mpFirmware->mnPrograms == 0)
1235                 || (pTAS2563->mpFirmware->mnConfigurations == 0)) {
1236                 dev_err(pTAS2563->dev, "%s, firmware not loaded\n", __func__);
1237                 pFWName = TAS2563_FW_NAME;
1238                 nResult = request_firmware_nowait(THIS_MODULE, 1, pFWName,
1239                         pTAS2563->dev, GFP_KERNEL, pTAS2563, tas2563_fw_ready);
1241                 if(nResult < 0) {
1242                         dev_err(pTAS2563->dev, "%s, firmware is loaded, %d\n", __func__, nResult);
1243                         goto end;
1244                 }
1245         }
1246         /* check safe guard*/
1247         /* TBD, add back when FW ready
1248         nResult = pTAS2563->read(pTAS2563, TAS2563_SAFE_GUARD_REG, &nValue);
1249         if (nResult < 0)
1250                 goto end;
1251         if ((nValue&0xff) != TAS2563_SAFE_GUARD_PATTERN) {
1252                 dev_err(pTAS2563->dev, "ERROR safe guard failure!\n");
1253                 nResult = -EPIPE;
1254                 goto end;
1255         }
1256         */
1257         
1258         pProgram = &(pTAS2563->mpFirmware->mpPrograms[pTAS2563->mnCurrentProgram]);
1259         dev_info(pTAS2563->dev, "%s, state: %d, mbPowerup %d\n", __func__, state, pTAS2563->mbPowerUp);
1260         if (state != TAS2563_POWER_SHUTDOWN) {
1261                 if (!pTAS2563->mbPowerUp) {
1262                         if (!pTAS2563->mbCalibrationLoaded) {
1263                                 nResult = tas2563_set_calibration(pTAS2563, 0xFF);
1264                                 if((nResult > 0) || (nResult == 0))
1265                                         pTAS2563->mbCalibrationLoaded = true;
1266                         }
1268                         if (pTAS2563->mbLoadConfigurationPrePowerUp) {
1269                                 dev_info(pTAS2563->dev, "load coefficient before power\n");
1270                                 pTAS2563->mbLoadConfigurationPrePowerUp = false;
1271                                 nResult = tas2563_load_coefficient(pTAS2563,
1272                                         pTAS2563->mnCurrentConfiguration, pTAS2563->mnNewConfiguration, false);
1273                                 if (nResult < 0)
1274                                         goto end;
1275                         }
1276                 }
1277         }
1279         switch (state) {
1280         case TAS2563_POWER_ACTIVE:
1281                 nResult = pTAS2563->update_bits(pTAS2563, TAS2563_PowerControl,
1282                         TAS2563_PowerControl_OperationalMode10_Mask |
1283                         TAS2563_PowerControl_ISNSPower_Mask |
1284                         TAS2563_PowerControl_VSNSPower_Mask,
1285                         TAS2563_PowerControl_OperationalMode10_Active |
1286                         TAS2563_PowerControl_VSNSPower_Active |
1287                         TAS2563_PowerControl_ISNSPower_Active);
1288                 if (nResult < 0)
1289                         return nResult;
1290                 pTAS2563->mbPowerUp = true;
1291                 dev_info(pTAS2563->dev, "set ICN to -80dB\n");
1292                 nResult = pTAS2563->bulk_write(pTAS2563, TAS2563_ICN_REG, pICN, 4);
1293                 break;
1295         case TAS2563_POWER_MUTE:
1296                 nResult = pTAS2563->update_bits(pTAS2563, TAS2563_PowerControl,
1297                         TAS2563_PowerControl_OperationalMode10_Mask |
1298                         TAS2563_PowerControl_ISNSPower_Mask |
1299                         TAS2563_PowerControl_VSNSPower_Mask,
1300                         TAS2563_PowerControl_OperationalMode10_Mute |
1301                         TAS2563_PowerControl_VSNSPower_Active |
1302                         TAS2563_PowerControl_ISNSPower_Active);
1303                         pTAS2563->mbPowerUp = true;
1304                 break;
1306         case TAS2563_POWER_SHUTDOWN:
1307                 nResult = pTAS2563->update_bits(pTAS2563, TAS2563_PowerControl,
1308                         TAS2563_PowerControl_OperationalMode10_Mask,
1309                         TAS2563_PowerControl_OperationalMode10_Shutdown);
1310                         pTAS2563->mbPowerUp = false;
1311                 break;
1313         default:
1314                 dev_err(pTAS2563->dev, "wrong power state setting %d\n", state);
1316         }
1318 end:
1319         pTAS2563->mnPowerState = state;
1320         return nResult;
1323 static int tas2563_dac_event(struct snd_soc_dapm_widget *w,
1324                         struct snd_kcontrol *kcontrol, int event)
1326 #ifdef KCONTROL_CODEC
1327         struct snd_soc_codec *codec = snd_soc_dapm_to_codec(w->dapm);
1328 #else
1329         struct snd_soc_codec *codec = w->codec;
1330 #endif
1331         struct tas2563_priv *pTAS2563 = snd_soc_codec_get_drvdata(codec);
1333         switch (event) {
1334         case SND_SOC_DAPM_POST_PMU:
1335                 tas2563_set_power_state(pTAS2563, TAS2563_POWER_ACTIVE);
1336                 break;
1337         case SND_SOC_DAPM_PRE_PMD:
1338                 tas2563_set_power_state(pTAS2563, TAS2563_POWER_SHUTDOWN);
1339                 break;
1341         }
1342         return 0;
1346 static const struct snd_soc_dapm_widget tas2563_dapm_widgets[] = {
1347         SND_SOC_DAPM_AIF_IN("ASI1", "ASI1 Playback", 0, SND_SOC_NOPM, 0, 0),
1348         SND_SOC_DAPM_AIF_OUT("Voltage Sense", "ASI1 Capture",  1, TAS2563_PowerControl, 2, 1),
1349         SND_SOC_DAPM_AIF_OUT("Current Sense", "ASI1 Capture",  0, TAS2563_PowerControl, 3, 1),
1350         SND_SOC_DAPM_MIXER("ASI1 Sel",
1351                 TAS2563_TDMConfigurationReg2, 4, 0,
1352                 &tas2563_asi_controls[0],
1353                 ARRAY_SIZE(tas2563_asi_controls)),
1354         SND_SOC_DAPM_DAC_E("DAC", NULL, SND_SOC_NOPM, 0, 0, tas2563_dac_event,
1355         SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_PRE_PMD),
1356         SND_SOC_DAPM_OUTPUT("OUT"),
1357         SND_SOC_DAPM_SIGGEN("VMON"),
1358         SND_SOC_DAPM_SIGGEN("IMON")
1359 };
1361 static const struct snd_soc_dapm_route tas2563_audio_map[] = {
1362         {"ASI1 Sel", "Left", "ASI1"},
1363         {"ASI1 Sel", "Right", "ASI1"},
1364         {"ASI1 Sel", "LeftRightDiv2", "ASI1"},
1365         {"DAC", NULL, "ASI1 Sel"},
1366         {"OUT", NULL, "DAC"},
1367         /*{"VMON", NULL, "Voltage Sense"},
1368         {"IMON", NULL, "Current Sense"},*/
1369         {"Voltage Sense", NULL, "VMON"},
1370         {"Current Sense", NULL, "IMON"},
1371 };
1374 static int tas2563_mute(struct snd_soc_dai *dai, int mute)
1376         struct snd_soc_codec *codec = dai->codec;
1377         struct tas2563_priv *pTAS2563 = snd_soc_codec_get_drvdata(codec);
1379         dev_info(pTAS2563->dev, "%s\n", __func__);
1380         mutex_lock(&pTAS2563->codec_lock);
1381         if (mute) {
1382                 dev_info(pTAS2563->dev, "mute: %s\n", __func__);
1383                 tas2563_set_power_state(pTAS2563, TAS2563_POWER_SHUTDOWN);
1384         } else {
1385                 dev_info(pTAS2563->dev, "unmute: %s\n", __func__);
1386                 tas2563_set_power_state(pTAS2563, TAS2563_POWER_ACTIVE);
1387         }
1388         mutex_unlock(&pTAS2563->codec_lock);
1389         return 0;
1392 #if 1
1393 static int tas2563_slot_config(struct snd_soc_codec *codec, struct tas2563_priv *pTAS2563, int blr_clk_ratio)
1395         int ret = 0;
1396         pTAS2563->update_bits(pTAS2563,
1397                         TAS2563_TDMConfigurationReg5, 0xff, 0x42);
1399         pTAS2563->update_bits(pTAS2563,
1400                         TAS2563_TDMConfigurationReg6, 0xff, 0x40);
1402         return ret;
1404 #endif
1406 static int tas2563_set_slot(struct tas2563_priv *pTAS2563, int slot_width)
1408         int ret = 0;
1409         dev_info(pTAS2563->dev, "%s, %d, ret = %d", __func__, __LINE__, ret);
1411         switch (slot_width) {
1412         case 16:
1413         ret = pTAS2563->update_bits(pTAS2563, 
1414                 TAS2563_TDMConfigurationReg2,
1415                 TAS2563_TDMConfigurationReg2_RXSLEN10_Mask,
1416                 TAS2563_TDMConfigurationReg2_RXSLEN10_16Bits);
1417         break;
1419         case 24:
1420         ret = pTAS2563->update_bits(pTAS2563, 
1421                 TAS2563_TDMConfigurationReg2,
1422                 TAS2563_TDMConfigurationReg2_RXSLEN10_Mask,
1423                 TAS2563_TDMConfigurationReg2_RXSLEN10_24Bits);
1424         break;
1426         case 32:
1427         ret = pTAS2563->update_bits(pTAS2563, 
1428                 TAS2563_TDMConfigurationReg2,
1429                 TAS2563_TDMConfigurationReg2_RXSLEN10_Mask,
1430                 TAS2563_TDMConfigurationReg2_RXSLEN10_32Bits);
1431         break;
1433         case 0:
1434         /* Do not change slot width */
1435         break;
1437         default:
1438                 dev_info(pTAS2563->dev, "slot width not supported");
1439                 ret = -EINVAL;
1440         }
1442         if (ret >= 0)
1443                 pTAS2563->mnSlot_width = slot_width;
1445         return ret;
1448 static int tas2563_set_bitwidth(struct tas2563_priv *pTAS2563, int bitwidth)
1450         int slot_width_tmp = 16;
1451         dev_info(pTAS2563->dev, "%s %d\n", __func__, __LINE__);
1453         switch (bitwidth) {
1454         case SNDRV_PCM_FORMAT_S16_LE:
1455                         pTAS2563->update_bits(pTAS2563, 
1456                         TAS2563_TDMConfigurationReg2,
1457                         TAS2563_TDMConfigurationReg2_RXWLEN32_Mask,
1458                         TAS2563_TDMConfigurationReg2_RXWLEN32_16Bits);
1459                         pTAS2563->mnCh_size = 16;
1460                         if (pTAS2563->mnSlot_width == 0)
1461                                 slot_width_tmp = 16;
1462                 break;
1463         case SNDRV_PCM_FORMAT_S24_LE:
1464                         pTAS2563->update_bits(pTAS2563, 
1465                         TAS2563_TDMConfigurationReg2,
1466                         TAS2563_TDMConfigurationReg2_RXWLEN32_Mask,
1467                         TAS2563_TDMConfigurationReg2_RXWLEN32_24Bits);
1468                         pTAS2563->mnCh_size = 24;
1469                         if (pTAS2563->mnSlot_width == 0)
1470                                 slot_width_tmp = 32;
1471                 break;
1472         case SNDRV_PCM_FORMAT_S32_LE:
1473                         pTAS2563->update_bits(pTAS2563,
1474                         TAS2563_TDMConfigurationReg2,
1475                         TAS2563_TDMConfigurationReg2_RXWLEN32_Mask,
1476                         TAS2563_TDMConfigurationReg2_RXWLEN32_32Bits);
1477                         pTAS2563->mnCh_size = 32;
1478                         if (pTAS2563->mnSlot_width == 0)
1479                                 slot_width_tmp = 32;
1480                 break;
1482         default:
1483                 dev_info(pTAS2563->dev, "Not supported params format\n");
1484         }
1486         /* If machine driver did not call set slot width */
1487         if (pTAS2563->mnSlot_width == 0)
1488                 tas2563_set_slot(pTAS2563, slot_width_tmp);
1490         dev_info(pTAS2563->dev, "mnCh_size: %d\n", pTAS2563->mnCh_size);
1491         pTAS2563->mnPCMFormat = bitwidth;
1493         return 0;
1496 static int tas2563_set_samplerate(struct tas2563_priv *pTAS2563, int samplerate)
1498         switch (samplerate) {
1499         case 48000:
1500                         pTAS2563->update_bits(pTAS2563,
1501                                 TAS2563_TDMConfigurationReg0,
1502                                 TAS2563_TDMConfigurationReg0_SAMPRATERAMP_Mask,
1503                                 TAS2563_TDMConfigurationReg0_SAMPRATERAMP_48KHz);
1504                         pTAS2563->update_bits(pTAS2563,
1505                                 TAS2563_TDMConfigurationReg0,
1506                                 TAS2563_TDMConfigurationReg0_SAMPRATE31_Mask,
1507                                 TAS2563_TDMConfigurationReg0_SAMPRATE31_44_1_48kHz);
1508                         break;
1509         case 44100:
1510                         pTAS2563->update_bits(pTAS2563,
1511                                 TAS2563_TDMConfigurationReg0,
1512                                 TAS2563_TDMConfigurationReg0_SAMPRATERAMP_Mask,
1513                                 TAS2563_TDMConfigurationReg0_SAMPRATERAMP_44_1KHz);
1514                         pTAS2563->update_bits(pTAS2563,
1515                                 TAS2563_TDMConfigurationReg0,
1516                                 TAS2563_TDMConfigurationReg0_SAMPRATE31_Mask,
1517                                 TAS2563_TDMConfigurationReg0_SAMPRATE31_44_1_48kHz);
1518                         break;
1519         case 96000:
1520                         pTAS2563->update_bits(pTAS2563,
1521                                 TAS2563_TDMConfigurationReg0,
1522                                 TAS2563_TDMConfigurationReg0_SAMPRATERAMP_Mask,
1523                                 TAS2563_TDMConfigurationReg0_SAMPRATERAMP_48KHz);
1524                         pTAS2563->update_bits(pTAS2563,
1525                                 TAS2563_TDMConfigurationReg0,
1526                                 TAS2563_TDMConfigurationReg0_SAMPRATE31_Mask,
1527                                 TAS2563_TDMConfigurationReg0_SAMPRATE31_88_2_96kHz);
1528                         break;
1529         case 88200:
1530                         pTAS2563->update_bits(pTAS2563,
1531                                 TAS2563_TDMConfigurationReg0,
1532                                 TAS2563_TDMConfigurationReg0_SAMPRATERAMP_Mask,
1533                                 TAS2563_TDMConfigurationReg0_SAMPRATERAMP_44_1KHz);
1534                         pTAS2563->update_bits(pTAS2563,
1535                                 TAS2563_TDMConfigurationReg0,
1536                                 TAS2563_TDMConfigurationReg0_SAMPRATE31_Mask,
1537                                 TAS2563_TDMConfigurationReg0_SAMPRATE31_88_2_96kHz);
1538                         break;
1539         case 19200:
1540                         pTAS2563->update_bits(pTAS2563,
1541                                 TAS2563_TDMConfigurationReg0,
1542                                 TAS2563_TDMConfigurationReg0_SAMPRATERAMP_Mask,
1543                                 TAS2563_TDMConfigurationReg0_SAMPRATERAMP_48KHz);
1544                         pTAS2563->update_bits(pTAS2563,
1545                                 TAS2563_TDMConfigurationReg0,
1546                                 TAS2563_TDMConfigurationReg0_SAMPRATE31_Mask,
1547                                 TAS2563_TDMConfigurationReg0_SAMPRATE31_176_4_192kHz);
1548                         break;
1549         case 17640:
1550                         pTAS2563->update_bits(pTAS2563,
1551                                 TAS2563_TDMConfigurationReg0,
1552                                 TAS2563_TDMConfigurationReg0_SAMPRATERAMP_Mask,
1553                                 TAS2563_TDMConfigurationReg0_SAMPRATERAMP_44_1KHz);
1554                         pTAS2563->update_bits(pTAS2563,
1555                                 TAS2563_TDMConfigurationReg0,
1556                                 TAS2563_TDMConfigurationReg0_SAMPRATE31_Mask,
1557                                 TAS2563_TDMConfigurationReg0_SAMPRATE31_176_4_192kHz);
1558                         break;
1559         default:
1560                         dev_info(pTAS2563->dev, "%s, unsupported sample rate, %d\n", __func__, samplerate);
1562         }
1564         pTAS2563->mnSamplingRate = samplerate;
1565         return 0;
1568 int tas2563_load_default(struct tas2563_priv *pTAS2563)
1570         int ret = 0;
1571         
1572         dev_info(pTAS2563->dev, "%s, %d, ret = %d", __func__, __LINE__, ret);
1574         ret = tas2563_set_slot(pTAS2563, pTAS2563->mnSlot_width);
1575         if (ret < 0)
1576                 goto end;
1577         dev_info(pTAS2563->dev, "%s, %d, ret = %d", __func__, __LINE__, ret);
1578         
1579         //if set format was not called by asoc, then set it default
1580         if(pTAS2563->mnASIFormat == 0)
1581                 pTAS2563->mnASIFormat = SND_SOC_DAIFMT_CBS_CFS 
1582                                 | SND_SOC_DAIFMT_IB_NF 
1583                                 | SND_SOC_DAIFMT_I2S;
1584         ret = tas2563_set_fmt(pTAS2563, pTAS2563->mnASIFormat);
1586         if (ret < 0)
1587                 goto end;
1588         dev_info(pTAS2563->dev, "%s, %d, ret = %d", __func__, __LINE__, ret);
1590         ret = tas2563_set_bitwidth(pTAS2563, pTAS2563->mnPCMFormat);
1591         if (ret < 0)
1592                 goto end;
1593         dev_info(pTAS2563->dev, "%s, %d, ret = %d", __func__, __LINE__, ret);
1595         ret = tas2563_set_samplerate(pTAS2563, pTAS2563->mnSamplingRate);
1596         if (ret < 0)
1597                 goto end;
1599 end:
1600 /* power up failed, restart later */
1601         dev_info(pTAS2563->dev, "%s, %d, ret = %d", __func__, __LINE__, ret);
1602         if (ret < 0)
1603                 schedule_delayed_work(&pTAS2563->irq_work,
1604                                 msecs_to_jiffies(1000));
1605         return ret;
1608 #if 0
1609 static void failsafe(struct tas2563_priv *pTAS2563)
1611         dev_err(pTAS2563->dev, "%s\n", __func__);
1612         pTAS2563->mnErrCode |= ERROR_FAILSAFE;
1613         if (hrtimer_active(&pTAS2563->mtimerwork))
1614                 hrtimer_cancel(&pTAS2563->mtimerwork);
1616         if(pTAS2563->mnRestart < RESTART_MAX)
1617         {
1618                 pTAS2563->mnRestart ++;
1619                 msleep(100);
1620                 dev_err(pTAS2563->dev, "I2C COMM error, restart SmartAmp.\n");
1621                 schedule_delayed_work(&pTAS2563->irq_work, msecs_to_jiffies(100));
1622                 return;
1623         }
1624         pTAS2563->enableIRQ(pTAS2563, false);
1625         tas2563_set_power_state(pTAS2563, TAS2563_POWER_SHUTDOWN);
1627         pTAS2563->mbPowerUp = false;
1628         pTAS2563->hw_reset(pTAS2563);
1629         pTAS2563->write(pTAS2563, TAS2563_SoftwareReset, TAS2563_SoftwareReset_SoftwareReset_Reset);
1630         udelay(1000);
1631         if (pTAS2563->mpFirmware != NULL)
1632                 tas2563_clear_firmware(pTAS2563->mpFirmware);
1634 #endif
1636 /*
1637 * tas2563_load_coefficient
1638 */
1639 static int tas2563_load_coefficient(struct tas2563_priv *pTAS2563,
1640         int nPrevConfig, int nNewConfig, bool bPowerOn)
1642         int nResult = 0;
1643 //      struct TPLL *pPLL;
1644         struct TProgram *pProgram;
1645         struct TConfiguration *pPrevConfiguration;
1646         struct TConfiguration *pNewConfiguration;
1647         bool bRestorePower = false;
1649         if (!pTAS2563->mpFirmware->mnConfigurations) {
1650                 dev_err(pTAS2563->dev, "%s, firmware not loaded\n", __func__);
1651                 goto end;
1652         }
1654         if (nNewConfig >= pTAS2563->mpFirmware->mnConfigurations) {
1655                 dev_err(pTAS2563->dev, "%s, invalid configuration New=%d, total=%d\n",
1656                         __func__, nNewConfig, pTAS2563->mpFirmware->mnConfigurations);
1657                 goto end;
1658         }
1660         if (nPrevConfig < 0)
1661                 pPrevConfiguration = NULL;
1662         else if (nPrevConfig == nNewConfig) {
1663                 dev_info(pTAS2563->dev, "%s, config [%d] already loaded\n",
1664                         __func__, nNewConfig);
1665                 goto end;
1666         } else
1667                 pPrevConfiguration = &(pTAS2563->mpFirmware->mpConfigurations[nPrevConfig]);
1669         pNewConfiguration = &(pTAS2563->mpFirmware->mpConfigurations[nNewConfig]);
1670         pTAS2563->mnCurrentConfiguration = nNewConfig;
1671 #if 0
1672         if (pPrevConfiguration) {
1673                 if (pPrevConfiguration->mnPLL == pNewConfiguration->mnPLL) {
1674                         dev_info(pTAS2563->dev, "%s, PLL same\n", __func__);
1675                         goto prog_coefficient;
1676                 }
1677         }
1679         pProgram = &(pTAS2563->mpFirmware->mpPrograms[pTAS2563->mnCurrentProgram]);
1680         if (bPowerOn) {
1681                 dev_info(pTAS2563->dev, "%s, power down to load new PLL\n", __func__);
1682                 if (hrtimer_active(&pTAS2563->mtimerwork))
1683                         hrtimer_cancel(&pTAS2563->mtimerwork);
1685                 if (pProgram->mnAppMode == TAS2563_APP_TUNINGMODE)
1686                         pTAS2563->enableIRQ(pTAS2563, false);
1688                 nResult = tas2563_set_power_state(pTAS2563, TAS2563_POWER_SHUTDOWN);
1689                 if (nResult < 0)
1690                         goto end;
1691                 bRestorePower = true;
1692         }
1694         /* load PLL */
1695         pPLL = &(pTAS2563->mpFirmware->mpPLLs[pNewConfiguration->mnPLL]);
1696         dev_info(pTAS2563->dev, "load PLL: %s block for Configuration %s\n",
1697                 pPLL->mpName, pNewConfiguration->mpName);
1698         nResult = tas2563_load_block(pTAS2563, &(pPLL->mBlock));
1699         if (nResult < 0)
1700                 goto end;
1701 #endif
1702         pTAS2563->mnCurrentSampleRate = pNewConfiguration->mnSamplingRate;
1704         dev_info(pTAS2563->dev, "load configuration %s conefficient pre block\n",
1705                 pNewConfiguration->mpName);
1706         nResult = tas2563_load_data(pTAS2563, &(pNewConfiguration->mData), TAS2563_BLOCK_CFG_PRE_DEV_A);
1707         if (nResult < 0)
1708                 goto end;
1710 //prog_coefficient:
1711         dev_info(pTAS2563->dev, "load new configuration: %s, coeff block data\n",
1712                 pNewConfiguration->mpName);
1713         nResult = tas2563_load_data(pTAS2563, &(pNewConfiguration->mData),
1714                 TAS2563_BLOCK_CFG_COEFF_DEV_A);
1715         if (nResult < 0)
1716                 goto end;
1718         if (pTAS2563->mpCalFirmware->mnCalibrations) {
1719                 nResult = tas2563_set_calibration(pTAS2563, pTAS2563->mnCurrentCalibration);
1720                 if (nResult < 0)
1721                         goto end;
1722         }
1724         if (bRestorePower) {
1725                 pTAS2563->clearIRQ(pTAS2563);
1726                 dev_info(pTAS2563->dev, "device powered up, load startup\n");
1727                 nResult = tas2563_set_power_state(pTAS2563, TAS2563_POWER_MUTE);
1728                 if (nResult < 0)
1729                         goto end;
1731                 dev_info(pTAS2563->dev,
1732                         "device powered up, load unmute\n");
1733                 nResult = tas2563_set_power_state(pTAS2563, TAS2563_POWER_ACTIVE);
1734                 if (nResult < 0)
1735                         goto end;
1736                 if (pProgram->mnAppMode == TAS2563_APP_TUNINGMODE) {
1737                         pTAS2563->enableIRQ(pTAS2563, true);
1738                         if (!hrtimer_active(&pTAS2563->mtimerwork)) {
1739                                 pTAS2563->mnDieTvReadCounter = 0;
1740                                 hrtimer_start(&pTAS2563->mtimerwork,
1741                                         ns_to_ktime((u64)LOW_TEMPERATURE_CHECK_PERIOD * NSEC_PER_MSEC), HRTIMER_MODE_REL);
1742                         }
1743                 }
1744         }
1745 end:
1747         pTAS2563->mnNewConfiguration = pTAS2563->mnCurrentConfiguration;
1748         return nResult;
1751 static bool tas2563_get_coefficient_in_data(struct tas2563_priv *pTAS2563,
1752         struct TData *pData, int blockType, int nReg, int *pnValue)
1754         bool bFound = false;
1755         struct TBlock *pBlock;
1756         int i;
1758         for (i = 0; i < pData->mnBlocks; i++) {
1759                 pBlock = &(pData->mpBlocks[i]);
1760                 if (pBlock->mnType == blockType) {
1761                         bFound = tas2563_get_coefficient_in_block(pTAS2563,
1762                                                 pBlock, nReg, pnValue);
1763                         if (bFound)
1764                                 break;
1765                 }
1766         }
1768         return bFound;
1771 static bool tas2563_find_Tmax_in_configuration(struct tas2563_priv *pTAS2563,
1772         struct TConfiguration *pConfiguration, int *pnTMax)
1774         struct TData *pData;
1775         bool bFound = false;
1776         int nBlockType, nReg, nCoefficient;
1778         nReg = TAS2563_CALI_T_REG;
1780         nBlockType = TAS2563_BLOCK_CFG_COEFF_DEV_A;
1782         pData = &(pConfiguration->mData);
1783         bFound = tas2563_get_coefficient_in_data(pTAS2563, pData, nBlockType, nReg, &nCoefficient);
1784         if (bFound)
1785                 *pnTMax = nCoefficient;
1787         return bFound;
1790 void tas2563_fw_ready(const struct firmware *pFW, void *pContext)
1792         struct tas2563_priv *pTAS2563 = (struct tas2563_priv *) pContext;
1793         int nResult;
1794         unsigned int nProgram = 0;
1795         unsigned int nSampleRate = 0;
1797 #ifdef CONFIG_TAS2563_CODEC
1798         mutex_lock(&pTAS2563->codec_lock);
1799 #endif
1801 #ifdef CONFIG_TAS2563_MISC
1802         mutex_lock(&pTAS2563->file_lock);
1803 #endif
1805         dev_info(pTAS2563->dev, "%s:\n", __func__);
1807         if (unlikely(!pFW) || unlikely(!pFW->data)) {
1808                 dev_err(pTAS2563->dev, "%s firmware is not loaded.\n",
1809                         TAS2563_FW_NAME);
1810                 goto end;
1811         }
1813         if (pTAS2563->mpFirmware->mpConfigurations) {
1814                 nProgram = pTAS2563->mnCurrentProgram;
1815                 nSampleRate = pTAS2563->mnCurrentSampleRate;
1816                 dev_info(pTAS2563->dev, "clear current firmware\n");
1817                 tas2563_clear_firmware(pTAS2563->mpFirmware);
1818         }
1820         nResult = fw_parse(pTAS2563, pTAS2563->mpFirmware, (unsigned char *)(pFW->data), pFW->size);
1821         release_firmware(pFW);
1822         if (nResult < 0) {
1823                 dev_err(pTAS2563->dev, "firmware is corrupt\n");
1824                 goto end;
1825         }
1827         if (!pTAS2563->mpFirmware->mnPrograms) {
1828                 dev_err(pTAS2563->dev, "firmware contains no programs\n");
1829                 nResult = -EINVAL;
1830                 goto end;
1831         }
1833         if (!pTAS2563->mpFirmware->mnConfigurations) {
1834                 dev_err(pTAS2563->dev, "firmware contains no configurations\n");
1835                 nResult = -EINVAL;
1836                 goto end;
1837         }
1839         if (nProgram >= pTAS2563->mpFirmware->mnPrograms) {
1840                 dev_info(pTAS2563->dev,
1841                         "no previous program, set to default\n");
1842                 nProgram = 0;
1843         }
1845         pTAS2563->mnCurrentSampleRate = nSampleRate;
1846         nResult = tas2563_set_program(pTAS2563, nProgram, -1);
1848 end:
1850 #ifdef CONFIG_TAS2563_CODEC
1851         mutex_unlock(&pTAS2563->codec_lock);
1852 #endif
1854 #ifdef CONFIG_TAS2563_MISC
1855         mutex_unlock(&pTAS2563->file_lock);
1856 #endif
1859 static bool tas2563_get_coefficient_in_block(struct tas2563_priv *pTAS2563,
1860         struct TBlock *pBlock, int nReg, int *pnValue)
1862         int nCoefficient = 0;
1863         bool bFound = false;
1864         unsigned char *pCommands;
1865         int nBook, nPage, nOffset, len;
1866         int i, n;
1868         pCommands = pBlock->mpData;
1869         for (i = 0 ; i < pBlock->mnCommands;) {
1870                 nBook = pCommands[4 * i + 0];
1871                 nPage = pCommands[4 * i + 1];
1872                 nOffset = pCommands[4 * i + 2];
1873                 if ((nOffset < 0x7f) || (nOffset == 0x81))
1874                         i++;
1875                 else if (nOffset == 0x85) {
1876                         len = ((int)nBook << 8) | nPage;
1877                         nBook = pCommands[4 * i + 4];
1878                         nPage = pCommands[4 * i + 5];
1879                         nOffset = pCommands[4 * i + 6];
1880                         n = 4 * i + 7;
1881                         i += 2;
1882                         i += ((len - 1) / 4);
1883                         if ((len - 1) % 4)
1884                                 i++;
1885                         if ((nBook != TAS2563_BOOK_ID(nReg))
1886                                 || (nPage != TAS2563_PAGE_ID(nReg)))
1887                                 continue;
1888                         if (nOffset > TAS2563_PAGE_REG(nReg))
1889                                 continue;
1890                         if ((len + nOffset) >= (TAS2563_PAGE_REG(nReg) + 4)) {
1891                                 n += (TAS2563_PAGE_REG(nReg) - nOffset);
1892                                 nCoefficient = ((int)pCommands[n] << 24)
1893                                                 | ((int)pCommands[n + 1] << 16)
1894                                                 | ((int)pCommands[n + 2] << 8)
1895                                                 | (int)pCommands[n + 3];
1896                                 bFound = true;
1897                                 break;
1898                         }
1899                 } else {
1900                         dev_err(pTAS2563->dev, "%s, format error %d\n", __func__, nOffset);
1901                         break;
1902                 }
1903         }
1905         if (bFound) {
1906                 *pnValue = nCoefficient;
1907                 dev_info(pTAS2563->dev, "%s, B[0x%x]P[0x%x]R[0x%x]=0x%x\n", __func__,
1908                         TAS2563_BOOK_ID(nReg), TAS2563_PAGE_ID(nReg), TAS2563_PAGE_REG(nReg),
1909                         nCoefficient);
1910         }
1912         return bFound;
1916 int tas2563_set_program(struct tas2563_priv *pTAS2563,
1917         unsigned int nProgram, int nConfig)
1919         struct TProgram *pProgram;
1920         unsigned int nConfiguration = 0;
1921         unsigned int nSampleRate = 0;
1922         bool bFound = false;
1923         int nResult = 0;
1925         if ((!pTAS2563->mpFirmware->mpPrograms) ||
1926                 (!pTAS2563->mpFirmware->mpConfigurations)) {
1927                 dev_err(pTAS2563->dev, "%s, Firmware not loaded\n", __func__);
1928                 nResult = 0;
1929                 goto end;
1930         }
1932         if (nProgram >= pTAS2563->mpFirmware->mnPrograms) {
1933                 dev_err(pTAS2563->dev, "TAS2563: Program %d doesn't exist\n",
1934                         nProgram);
1935                 nResult = 0;
1936                 goto end;
1937         }
1939         if (nConfig < 0) {
1940                 nConfiguration = 0;
1941                 nSampleRate = pTAS2563->mnCurrentSampleRate;
1942                 while (!bFound && (nConfiguration < pTAS2563->mpFirmware->mnConfigurations)) {
1943                         if (pTAS2563->mpFirmware->mpConfigurations[nConfiguration].mnProgram == nProgram) {
1944                                 if (nSampleRate == 0) {
1945                                         bFound = true;
1946                                         dev_info(pTAS2563->dev, "find default configuration %d\n", nConfiguration);
1947                                 } else if (nSampleRate == pTAS2563->mpFirmware->mpConfigurations[nConfiguration].mnSamplingRate) {
1948                                         bFound = true;
1949                                         dev_info(pTAS2563->dev, "find matching configuration %d\n", nConfiguration);
1950                                 } else {
1951                                         nConfiguration++;
1952                                 }
1953                         } else {
1954                                 nConfiguration++;
1955                         }
1956                 }
1957                 if (!bFound) {
1958                         dev_err(pTAS2563->dev,
1959                                 "Program %d, no valid configuration found for sample rate %d, ignore\n",
1960                                 nProgram, nSampleRate);
1961                         nResult = 0;
1962                         goto end;
1963                 }
1964         } else {
1965                 if (pTAS2563->mpFirmware->mpConfigurations[nConfig].mnProgram != nProgram) {
1966                         dev_err(pTAS2563->dev, "%s, configuration program doesn't match\n", __func__);
1967                         nResult = 0;
1968                         goto end;
1969                 }
1970                 nConfiguration = nConfig;
1971         }
1973         pProgram = &(pTAS2563->mpFirmware->mpPrograms[nProgram]);
1974         if (pTAS2563->mbPowerUp) {
1975                 dev_info(pTAS2563->dev,
1976                         "device powered up, power down to load program %d (%s)\n",
1977                         nProgram, pProgram->mpName);
1978                 if (hrtimer_active(&pTAS2563->mtimerwork))
1979                         hrtimer_cancel(&pTAS2563->mtimerwork);
1981                 if (pProgram->mnAppMode == TAS2563_APP_TUNINGMODE)
1982                         pTAS2563->enableIRQ(pTAS2563, false);
1984                 nResult = tas2563_set_power_state(pTAS2563, TAS2563_POWER_SHUTDOWN);
1985                 if (nResult < 0)
1986                         goto end;
1987         }
1989         pTAS2563->hw_reset(pTAS2563);
1990         nResult = pTAS2563->write(pTAS2563, TAS2563_SoftwareReset, 0x01);
1991         if (nResult < 0)
1992                 goto end;
1993         msleep(1);
1994         nResult = tas2563_load_default(pTAS2563);
1995         if (nResult < 0)
1996                 goto end;
1998         dev_info(pTAS2563->dev, "load program %d (%s)\n", nProgram, pProgram->mpName);
1999         nResult = tas2563_load_data(pTAS2563, &(pProgram->mData), TAS2563_BLOCK_PGM_DEV_A);
2000         if (nResult < 0)
2001                 goto end;
2002         pTAS2563->mnCurrentProgram = nProgram;
2004         nResult = tas2563_load_coefficient(pTAS2563, -1, nConfiguration, false);
2005         if (nResult < 0)
2006                 goto end;
2008         // Enable IV data
2009         nResult = pTAS2563->update_bits(pTAS2563, TAS2563_PowerControl,
2010                                         TAS2563_PowerControl_OperationalMode10_Mask |
2011                                 TAS2563_PowerControl_ISNSPower_Mask |
2012                                 TAS2563_PowerControl_VSNSPower_Mask,
2013                                 TAS2563_PowerControl_OperationalMode10_Active |
2014                                 TAS2563_PowerControl_VSNSPower_Active |
2015                                 TAS2563_PowerControl_ISNSPower_Active);
2016         if (nResult < 0)
2017                 dev_info(pTAS2563->dev, "Enable IV Data Failed: %s\n", __func__);
2019         if (pTAS2563->mbPowerUp) {
2020 //              pTAS2563->clearIRQ(pTAS2563);
2021 //              dev_info(pTAS2563->dev, "device powered up, load startup\n");
2022                 nResult = tas2563_set_power_state(pTAS2563, TAS2563_POWER_MUTE);
2024                 if (nResult < 0)
2025                         goto end;
2026                 if (pProgram->mnAppMode == TAS2563_APP_TUNINGMODE) {
2027 //                      nResult = tas2563_checkPLL(pTAS2563);
2028                         if (nResult < 0) {
2029                                 tas2563_set_power_state(pTAS2563, TAS2563_POWER_SHUTDOWN);
2030                                 pTAS2563->mbPowerUp = false;
2031                                 goto end;
2032                         }
2033                 }
2034                 dev_info(pTAS2563->dev, "device powered up, load unmute\n");
2035                 tas2563_set_power_state(pTAS2563, TAS2563_POWER_ACTIVE);
2036                 if (nResult < 0)
2037                         goto end;
2039                 if (pProgram->mnAppMode == TAS2563_APP_TUNINGMODE) {
2040                         pTAS2563->enableIRQ(pTAS2563, true);
2041                         if (!hrtimer_active(&pTAS2563->mtimerwork)) {
2042                                 pTAS2563->mnDieTvReadCounter = 0;
2043                                 hrtimer_start(&pTAS2563->mtimerwork,
2044                                         ns_to_ktime((u64)LOW_TEMPERATURE_CHECK_PERIOD * NSEC_PER_MSEC), HRTIMER_MODE_REL);
2045                         }
2046                 }
2047         }
2049 end:
2051 /*      if (nResult < 0) {
2052                 if (pTAS2563->mnErrCode & (ERROR_DEVA_I2C_COMM | ERROR_PRAM_CRCCHK | ERROR_YRAM_CRCCHK))
2053                         failsafe(pTAS2563);
2054         }*/
2055         return nResult;
2058 static int tas2563_set_calibration(struct tas2563_priv *pTAS2563, int nCalibration)
2060         struct TCalibration *pCalibration = NULL;
2061         struct TConfiguration *pConfiguration;
2062         struct TProgram *pProgram;
2063         int nTmax = 0;
2064         bool bFound = false;
2065         int nResult = 0;
2067         if ((!pTAS2563->mpFirmware->mpPrograms)
2068                 || (!pTAS2563->mpFirmware->mpConfigurations)) {
2069                 dev_err(pTAS2563->dev, "%s, Firmware not loaded\n\r", __func__);
2070                 nResult = 0;
2071                 goto end;
2072         }
2074         if (nCalibration == 0x00FF) {
2075                 nResult = tas2563_load_calibration(pTAS2563, TAS2563_CAL_NAME);
2076                 if (nResult < 0) {
2077                         dev_info(pTAS2563->dev, "load new calibration file %s fail %d\n",
2078                                 TAS2563_CAL_NAME, nResult);
2079                         goto end;
2080                 }
2081                 nCalibration = 0;
2082         }
2084         if (nCalibration >= pTAS2563->mpCalFirmware->mnCalibrations) {
2085                 dev_err(pTAS2563->dev,
2086                         "Calibration %d doesn't exist\n", nCalibration);
2087                 nResult = 0;
2088                 goto end;
2089         }
2091         pTAS2563->mnCurrentCalibration = nCalibration;
2092         if (pTAS2563->mbLoadConfigurationPrePowerUp)
2093                 goto end;
2095         pCalibration = &(pTAS2563->mpCalFirmware->mpCalibrations[nCalibration]);
2096         pProgram = &(pTAS2563->mpFirmware->mpPrograms[pTAS2563->mnCurrentProgram]);
2097         pConfiguration = &(pTAS2563->mpFirmware->mpConfigurations[pTAS2563->mnCurrentConfiguration]);
2098         if (pProgram->mnAppMode == TAS2563_APP_TUNINGMODE) {
2099                 if (pTAS2563->mbBypassTMax) {
2100                         bFound = tas2563_find_Tmax_in_configuration(pTAS2563, pConfiguration, &nTmax);
2101                         if (bFound && (nTmax == TAS2563_COEFFICIENT_TMAX)) {
2102                                 dev_info(pTAS2563->dev, "%s, config[%s] bypass load calibration\n",
2103                                         __func__, pConfiguration->mpName);
2104                                 goto end;
2105                         }
2106                 }
2108                 dev_info(pTAS2563->dev, "%s, load calibration\n", __func__);
2109                 nResult = tas2563_load_data(pTAS2563, &(pCalibration->mData), TAS2563_BLOCK_CFG_COEFF_DEV_A);
2110                 if (nResult < 0)
2111                         goto end;
2112         }
2114 end:
2115         if (nResult < 0) {
2116                 tas2563_clear_firmware(pTAS2563->mpCalFirmware);
2117                 nResult = tas2563_set_program(pTAS2563, pTAS2563->mnCurrentProgram, pTAS2563->mnCurrentConfiguration);
2118         }
2120         return nResult;
2123 bool tas2563_get_Cali_prm_r0(struct tas2563_priv *pTAS2563, int *prm_r0)
2125         struct TCalibration *pCalibration;
2126         struct TData *pData;
2127         int nReg;
2128         int nCali_Re;
2129         bool bFound = false;
2130         int nBlockType;
2132         if (!pTAS2563->mpCalFirmware->mnCalibrations) {
2133                 dev_err(pTAS2563->dev, "%s, no calibration data\n", __func__);
2134                 goto end;
2135         }
2137         nReg = TAS2563_CALI_R0_REG;
2138         nBlockType = TAS2563_BLOCK_CFG_COEFF_DEV_A;
2140         pCalibration = &(pTAS2563->mpCalFirmware->mpCalibrations[pTAS2563->mnCurrentCalibration]);
2141         pData = &(pCalibration->mData);
2143         bFound = tas2563_get_coefficient_in_data(pTAS2563, pData, nBlockType, nReg, &nCali_Re);
2145 end:
2147         if (bFound)
2148                 *prm_r0 = nCali_Re;
2150         return bFound;
2153 int tas2563_set_config(struct tas2563_priv *pTAS2563, int config)
2155         struct TConfiguration *pConfiguration;
2156         struct TProgram *pProgram;
2157         unsigned int nProgram = pTAS2563->mnCurrentProgram;
2158         unsigned int nConfiguration = config;
2159         int nResult = 0;
2161         if ((!pTAS2563->mpFirmware->mpPrograms) ||
2162                 (!pTAS2563->mpFirmware->mpConfigurations)) {
2163                 dev_err(pTAS2563->dev, "%s, Firmware not loaded\n", __func__);
2164                 nResult = -EINVAL;
2165                 goto end;
2166         }
2168         if (nConfiguration >= pTAS2563->mpFirmware->mnConfigurations) {
2169                 dev_err(pTAS2563->dev, "Configuration %d doesn't exist\n",
2170                         nConfiguration);
2171                 nResult = -EINVAL;
2172                 goto end;
2173         }
2175         pConfiguration = &(pTAS2563->mpFirmware->mpConfigurations[nConfiguration]);
2176         pProgram = &(pTAS2563->mpFirmware->mpPrograms[nProgram]);
2178         if (nProgram != pConfiguration->mnProgram) {
2179                 dev_err(pTAS2563->dev,
2180                         "Configuration %d, %s with Program %d isn't compatible with existing Program %d, %s\n",
2181                         nConfiguration, pConfiguration->mpName, pConfiguration->mnProgram,
2182                         nProgram, pProgram->mpName);
2183                 nResult = -EINVAL;
2184                 goto end;
2185         }
2187         nResult = tas2563_load_configuration(pTAS2563, nConfiguration, false);
2189 end:
2191         return nResult;
2194 static int tas2563_configuration_get(struct snd_kcontrol *pKcontrol,
2195         struct snd_ctl_elem_value *pValue)
2197 #ifdef KCONTROL_CODEC
2198         struct snd_soc_codec *codec = snd_soc_kcontrol_codec(pKcontrol);
2199 #else
2200         struct snd_soc_codec *codec = snd_kcontrol_chip(pKcontrol);
2201 #endif
2202         struct tas2563_priv *pTAS2563 = snd_soc_codec_get_drvdata(codec);
2204         mutex_lock(&pTAS2563->codec_lock);
2206         pValue->value.integer.value[0] = pTAS2563->mnCurrentConfiguration;
2207         dev_info(pTAS2563->dev, "tas2563_configuration_get = %d\n",
2208                 pTAS2563->mnCurrentConfiguration);
2210         mutex_unlock(&pTAS2563->codec_lock);
2211         return 0;
2214 static int tas2563_configuration_put(struct snd_kcontrol *pKcontrol,
2215         struct snd_ctl_elem_value *pValue)
2217 #ifdef KCONTROL_CODEC
2218         struct snd_soc_codec *codec = snd_soc_kcontrol_codec(pKcontrol);
2219 #else
2220         struct snd_soc_codec *codec = snd_kcontrol_chip(pKcontrol);
2221 #endif
2222         struct tas2563_priv *pTAS2563 = snd_soc_codec_get_drvdata(codec);
2223         unsigned int nConfiguration = pValue->value.integer.value[0];
2224         int ret = 0;
2226         mutex_lock(&pTAS2563->codec_lock);
2228         dev_info(pTAS2563->dev, "%s = %d\n", __func__, nConfiguration);
2229         ret = tas2563_set_config(pTAS2563, nConfiguration);
2231         mutex_unlock(&pTAS2563->codec_lock);
2232         return ret;
2236 static int tas2563_hw_params(struct snd_pcm_substream *substream,
2237                 struct snd_pcm_hw_params *params,
2238                 struct snd_soc_dai *dai)
2240         struct snd_soc_codec *codec = dai->codec;
2241         struct tas2563_priv *pTAS2563 = snd_soc_codec_get_drvdata(codec);
2242         int ret = 0;
2243         int blr_clk_ratio;
2245         dev_info(pTAS2563->dev, "%s, format: %d\n", __func__,
2246                 params_format(params));
2248         mutex_lock(&pTAS2563->codec_lock);
2250         ret = tas2563_set_bitwidth(pTAS2563, params_format(params));
2251         if(ret < 0)
2252         {
2253                 dev_info(pTAS2563->dev, "set bitwidth failed, %d\n", ret);
2254                 goto ret;
2255         }
2257         blr_clk_ratio = params_channels(params) * pTAS2563->mnCh_size;
2258         dev_info(pTAS2563->dev, "blr_clk_ratio: %d\n", blr_clk_ratio);
2259         if(blr_clk_ratio != 0)
2260                 tas2563_slot_config(pTAS2563->codec, pTAS2563, blr_clk_ratio);
2262         dev_info(pTAS2563->dev, "%s, sample rate: %d\n", __func__,
2263                 params_rate(params));
2265         ret = tas2563_set_samplerate(pTAS2563, params_rate(params));
2267         mutex_unlock(&pTAS2563->codec_lock);
2268 ret:
2269         return ret;
2272 static int tas2563_set_fmt(struct tas2563_priv *pTAS2563, unsigned int fmt)
2274         u8 tdm_rx_start_slot = 0, asi_cfg_1 = 0;
2275         int ret = 0;
2277         switch (fmt & SND_SOC_DAIFMT_MASTER_MASK) {
2278         case SND_SOC_DAIFMT_CBS_CFS:
2279                 asi_cfg_1 = 0x00;
2280                 break;
2281         default:
2282                 dev_err(pTAS2563->dev, "ASI format master is not found\n");
2283                 ret = -EINVAL;
2284         }
2286         switch (fmt & SND_SOC_DAIFMT_INV_MASK) {
2287         case SND_SOC_DAIFMT_NB_NF:
2288                 dev_info(pTAS2563->dev, "INV format: NBNF\n");
2289                 asi_cfg_1 |= TAS2563_TDMConfigurationReg1_RXEDGE_Rising;
2290                 break;
2291         case SND_SOC_DAIFMT_IB_NF:
2292                 dev_info(pTAS2563->dev, "INV format: IBNF\n");
2293                 asi_cfg_1 |= TAS2563_TDMConfigurationReg1_RXEDGE_Falling;
2294                 break;
2295         default:
2296                 dev_err(pTAS2563->dev, "ASI format Inverse is not found\n");
2297                 ret = -EINVAL;
2298         }
2300         pTAS2563->update_bits(pTAS2563, TAS2563_TDMConfigurationReg1,
2301                 TAS2563_TDMConfigurationReg1_RXEDGE_Mask,
2302                 asi_cfg_1);
2304         switch (fmt & SND_SOC_DAIFMT_FORMAT_MASK) {
2305         case (SND_SOC_DAIFMT_I2S):
2306                 tdm_rx_start_slot = 1;
2307                 break;
2308         case (SND_SOC_DAIFMT_DSP_A):
2309         case (SND_SOC_DAIFMT_DSP_B):
2310                 tdm_rx_start_slot = 1;
2311                 break;
2312         case (SND_SOC_DAIFMT_LEFT_J):
2313                 tdm_rx_start_slot = 0;
2314                 break;
2315         default:
2316         dev_err(pTAS2563->dev, "DAI Format is not found, fmt=0x%x\n", fmt);
2317         ret = -EINVAL;
2318                 break;
2319         }
2321         pTAS2563->update_bits(pTAS2563, TAS2563_TDMConfigurationReg1,
2322                 TAS2563_TDMConfigurationReg1_RXOFFSET51_Mask,
2323         (tdm_rx_start_slot << TAS2563_TDMConfigurationReg1_RXOFFSET51_Shift));
2325         pTAS2563->mnASIFormat = fmt;
2327         return 0;
2331 static int tas2563_set_dai_fmt(struct snd_soc_dai *dai, unsigned int fmt)
2333         struct snd_soc_codec *codec = dai->codec;
2334         struct tas2563_priv *pTAS2563 = snd_soc_codec_get_drvdata(codec);
2335         int ret = 0;
2337         dev_info(pTAS2563->dev, "%s, format=0x%x\n", __func__, fmt);
2339         mutex_lock(&pTAS2563->codec_lock);
2341         ret = tas2563_set_fmt(pTAS2563, fmt);
2343         mutex_unlock(&pTAS2563->codec_lock);
2344         return ret;
2347 static int tas2563_set_dai_tdm_slot(struct snd_soc_dai *dai,
2348                 unsigned int tx_mask, unsigned int rx_mask,
2349                 int slots, int slot_width)
2351         int ret = 0;
2352         struct snd_soc_codec *codec = dai->codec;
2353         struct tas2563_priv *pTAS2563 = snd_soc_codec_get_drvdata(codec);
2355         dev_info(pTAS2563->dev, "%s, tx_mask:%d, rx_mask:%d, slots:%d, slot_width:%d",
2356                         __func__, tx_mask, rx_mask, slots, slot_width);
2358         ret = tas2563_set_slot(pTAS2563, slot_width);
2360         return ret;
2363 static int tas2563_program_get(struct snd_kcontrol *pKcontrol,
2364         struct snd_ctl_elem_value *pValue)
2366 #ifdef KCONTROL_CODEC
2367         struct snd_soc_codec *codec = snd_soc_kcontrol_codec(pKcontrol);
2368 #else
2369         struct snd_soc_codec *codec = snd_kcontrol_chip(pKcontrol);
2370 #endif
2371         struct tas2563_priv *pTAS2563 = snd_soc_codec_get_drvdata(codec);
2373         mutex_lock(&pTAS2563->codec_lock);
2375         pValue->value.integer.value[0] = pTAS2563->mnCurrentProgram;
2376         dev_info(pTAS2563->dev, "tas2563_program_get = %d\n",
2377                 pTAS2563->mnCurrentProgram);
2379         mutex_unlock(&pTAS2563->codec_lock);
2380         return 0;
2383 static int tas2563_program_put(struct snd_kcontrol *pKcontrol,
2384         struct snd_ctl_elem_value *pValue)
2386 #ifdef KCONTROL_CODEC
2387         struct snd_soc_codec *codec = snd_soc_kcontrol_codec(pKcontrol);
2388 #else
2389         struct snd_soc_codec *codec = snd_kcontrol_chip(pKcontrol);
2390 #endif
2391         struct tas2563_priv *pTAS2563 = snd_soc_codec_get_drvdata(codec);
2392         unsigned int nProgram = pValue->value.integer.value[0];
2393         int ret = 0, nConfiguration = -1;
2395         mutex_lock(&pTAS2563->codec_lock);
2397         if (nProgram == pTAS2563->mnCurrentProgram)
2398                 nConfiguration = pTAS2563->mnCurrentConfiguration;
2399         ret = tas2563_set_program(pTAS2563, nProgram, nConfiguration);
2401         mutex_unlock(&pTAS2563->codec_lock);
2402         return ret;
2405 static int tas2563_calibration_get(struct snd_kcontrol *pKcontrol,
2406         struct snd_ctl_elem_value *pValue)
2408 #ifdef KCONTROL_CODEC
2409         struct snd_soc_codec *codec = snd_soc_kcontrol_codec(pKcontrol);
2410 #else
2411         struct snd_soc_codec *codec = snd_kcontrol_chip(pKcontrol);
2412 #endif
2413         struct tas2563_priv *pTAS2563 = snd_soc_codec_get_drvdata(codec);
2415         mutex_lock(&pTAS2563->codec_lock);
2417         pValue->value.integer.value[0] = pTAS2563->mnCurrentCalibration;
2418         dev_info(pTAS2563->dev,
2419                 "tas2563_calibration_get = %d\n",
2420                 pTAS2563->mnCurrentCalibration);
2422         mutex_unlock(&pTAS2563->codec_lock);
2423         return 0;
2426 static int tas2563_calibration_put(struct snd_kcontrol *pKcontrol,
2427         struct snd_ctl_elem_value *pValue)
2429 #ifdef KCONTROL_CODEC
2430         struct snd_soc_codec *codec = snd_soc_kcontrol_codec(pKcontrol);
2431 #else
2432         struct snd_soc_codec *codec = snd_kcontrol_chip(pKcontrol);
2433 #endif
2434         struct tas2563_priv *pTAS2563 = snd_soc_codec_get_drvdata(codec);
2435         unsigned int nCalibration = pValue->value.integer.value[0];
2436         int ret = 0;
2438         mutex_lock(&pTAS2563->codec_lock);
2440         ret = tas2563_set_calibration(pTAS2563, nCalibration);
2442         mutex_unlock(&pTAS2563->codec_lock);
2443         return ret;
2446 static struct snd_soc_dai_ops tas2563_dai_ops = {
2447         .digital_mute = tas2563_mute,
2448         .hw_params  = tas2563_hw_params,
2449         .set_fmt    = tas2563_set_dai_fmt,
2450         .set_tdm_slot = tas2563_set_dai_tdm_slot,
2451 };
2453 #define TAS2563_FORMATS (SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S20_3LE |\
2454                 SNDRV_PCM_FMTBIT_S24_LE | SNDRV_PCM_FMTBIT_S32_LE)
2456 #define TAS2563_RATES (SNDRV_PCM_RATE_44100 | SNDRV_PCM_RATE_48000 \
2457                                                 SNDRV_PCM_RATE_88200 |\
2458                                                 SNDRV_PCM_RATE_96000 |\
2459                                                 SNDRV_PCM_RATE_176400 |\
2460                                                 SNDRV_PCM_RATE_192000\
2461                                                 )
2463 static struct snd_soc_dai_driver tas2563_dai_driver[] = {
2464         {
2465                 .name = "tas2563 ASI1",
2466                 .id = 0,
2467                 .playback = {
2468                         .stream_name    = "ASI1 Playback",
2469                         .channels_min   = 2,
2470                         .channels_max   = 2,
2471                         .rates      = SNDRV_PCM_RATE_8000_192000,
2472                         .formats    = TAS2563_FORMATS,
2473                 },
2474                 .capture = {
2475                         .stream_name    = "ASI1 Capture",
2476                         .channels_min   = 0,
2477                         .channels_max   = 2,
2478                         .rates          = SNDRV_PCM_RATE_8000_192000,
2479                         .formats    = TAS2563_FORMATS,
2480                 },
2481                 .ops = &tas2563_dai_ops,
2482                 .symmetric_rates = 1,
2483         },
2484 };
2486 static int tas2563_codec_probe(struct snd_soc_codec *codec)
2488         int ret;
2489         struct tas2563_priv *pTAS2563 = snd_soc_codec_get_drvdata(codec);
2491         ret = snd_soc_add_codec_controls(codec, tas2563_controls,
2492                                          ARRAY_SIZE(tas2563_controls));
2493         if (ret < 0) {
2494                 pr_err("%s: add_codec_controls failed, err %d\n",
2495                         __func__, ret);
2496                 return ret;
2497         }
2498         pTAS2563->codec = codec;
2499         pTAS2563->set_calibration = tas2563_set_calibration;
2500         pTAS2563->set_config = tas2563_set_config;
2502         dev_err(pTAS2563->dev, "%s\n", __func__);
2504         return 0;
2507 static int tas2563_codec_remove(struct snd_soc_codec *codec)
2509         return 0;
2512 /*static DECLARE_TLV_DB_SCALE(dac_tlv, 0, 100, 0);*/
2513 static DECLARE_TLV_DB_SCALE(tas2563_digital_tlv, 1100, 50, 0);
2515 static const struct snd_kcontrol_new tas2563_snd_controls[] = {
2516         SOC_SINGLE_TLV("Amp Output Level", TAS2563_PlaybackConfigurationReg0,
2517                 0, 0x16, 0,
2518                 tas2563_digital_tlv),
2519         SOC_SINGLE_EXT("Program", SND_SOC_NOPM, 0, 0x00FF, 0, tas2563_program_get,
2520                 tas2563_program_put),
2521         SOC_SINGLE_EXT("Configuration", SND_SOC_NOPM, 0, 0x00FF, 0,
2522                 tas2563_configuration_get, tas2563_configuration_put),
2523         SOC_SINGLE_EXT("Calibration", SND_SOC_NOPM, 0, 0x00FF, 0,
2524                 tas2563_calibration_get, tas2563_calibration_put),
2525 };
2527 static struct snd_soc_codec_driver soc_codec_driver_tas2563 = {
2528         .probe                  = tas2563_codec_probe,
2529         .remove                 = tas2563_codec_remove,
2530         .read                   = tas2563_codec_read,
2531         .write                  = tas2563_codec_write,
2532         .suspend                = tas2563_codec_suspend,
2533         .resume                 = tas2563_codec_resume,
2534 #ifdef KCONTROL_CODEC
2535         .component_driver = {
2536 #endif
2537                 .controls               = tas2563_snd_controls,
2538                 .num_controls           = ARRAY_SIZE(tas2563_snd_controls),
2539                 .dapm_widgets           = tas2563_dapm_widgets,
2540                 .num_dapm_widgets       = ARRAY_SIZE(tas2563_dapm_widgets),
2541                 .dapm_routes            = tas2563_audio_map,
2542                 .num_dapm_routes        = ARRAY_SIZE(tas2563_audio_map),
2543 #ifdef KCONTROL_CODEC
2544         },
2545 #endif
2546 };
2548 int tas2563_register_codec(struct tas2563_priv *pTAS2563)
2550         int nResult = 0;
2552         dev_info(pTAS2563->dev, "%s, enter\n", __func__);
2553         nResult = snd_soc_register_codec(pTAS2563->dev,
2554                 &soc_codec_driver_tas2563,
2555                 tas2563_dai_driver, ARRAY_SIZE(tas2563_dai_driver));
2556         return nResult;
2559 int tas2563_deregister_codec(struct tas2563_priv *pTAS2563)
2561         snd_soc_unregister_codec(pTAS2563->dev);
2563         return 0;
2566 MODULE_AUTHOR("Texas Instruments Inc.");
2567 MODULE_DESCRIPTION("TAS2563 ALSA SOC Smart Amplifier driver");
2568 MODULE_LICENSE("GPL v2");
2569 #endif /* CONFIG_TAS2563_CODEC */