]> Gitweb @ Texas Instruments - Open Source Git Repositories - git.TI.com/gitweb - tas2555sw-android/tas2555-android-device-driver-stereo.git/blob - tas2555-core.c
update for device bulk access and in-system tuning
[tas2555sw-android/tas2555-android-device-driver-stereo.git] / tas2555-core.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 ** You should have received a copy of the GNU General Public License along with
14 ** this program; if not, write to the Free Software Foundation, Inc., 51 Franklin
15 ** Street, Fifth Floor, Boston, MA 02110-1301, USA.
16 **
17 ** File:
18 **     tas2555-core.c
19 **
20 ** Description:
21 **     TAS2555 common functions for Android Linux
22 **
23 ** =============================================================================
24 */
26 #define DEBUG
27 #include <linux/module.h>
28 #include <linux/moduleparam.h>
29 #include <linux/init.h>
30 #include <linux/delay.h>
31 #include <linux/pm.h>
32 #include <linux/i2c.h>
33 #include <linux/gpio.h>
34 #include <linux/regulator/consumer.h>
35 #include <linux/firmware.h>
36 #include <linux/regmap.h>
37 #include <linux/of.h>
38 #include <linux/of_gpio.h>
39 #include <linux/slab.h>
40 #include <linux/syscalls.h>
41 #include <linux/fcntl.h>
42 #include <asm/uaccess.h>
44 #include "tas2555.h"
45 #include "tas2555-core.h"
47 #define TAS2555_CAL_NAME    "/data/tas2555_cal.bin"
49 //set default PLL CLKIN to GPI2 (MCLK) = 0x00
50 #define TAS2555_DEFAULT_PLL_CLKIN 0x00
52 static void tas2555_load_calibration(struct tas2555_priv *pTAS2555,
53         char *pFileName);
54 static void tas2555_load_data(struct tas2555_priv *pTAS2555, TData * pData,
55         unsigned int nType);
56 static void tas2555_load_block(struct tas2555_priv *pTAS2555, TBlock * pBlock);
57 static void tas2555_load_configuration(struct tas2555_priv *pTAS2555,
58         unsigned int nConfiguration, bool bLoadSame);
59         
60 #define TAS2555_UDELAY 0xFFFFFFFE
62 #define FW_ERR_HEADER -1
63 #define FW_ERR_SIZE -2
65 #define TAS2555_BLOCK_PLL                       0x00
66 #define TAS2555_BLOCK_MAIN_DEV_A        0x01
67 #define TAS2555_BLOCK_MAIN_DEV_B        0x08
68 #define TAS2555_BLOCK_COEFF_DEV_A       0x03
69 #define TAS2555_BLOCK_COEFF_DEV_B       0x0a
70 #define TAS2555_BLOCK_PRE_DEV_A         0x04
71 #define TAS2555_BLOCK_PRE_DEV_B         0x0B
72 #define TAS2555_BLOCK_POST                      0x05
73 #define TAS2555_BLOCK_POST_POWER_UP     0x06
75 static unsigned int p_tas2555_default_data[] = {
76         channel_both, TAS2555_ASI1_DAC_FORMAT_REG, 0x10,        //ASI1 DAC word length = 24 bits
78         channel_both, TAS2555_PLL_CLKIN_REG, TAS2555_DEFAULT_PLL_CLKIN, //PLL_CLKIN = GPIO1 (BCLK)
79         channel_both, TAS2555_MAIN_CLKIN_REG, 0x0F,     //NDIV_MUX_CLKIN = PLL_CLK
80         channel_both, TAS2555_PLL_P_VAL_REG, 0x01,      //PLL P = 1
81 //  TAS2555_PLL_J_VAL_REG,      0x10, //PLL J = 16
82         channel_both, TAS2555_PLL_J_VAL_REG, 0x30,      //PLL J = 48 -> PLL_CLK = 1.536MHz * 48 = 73.728MHz
83         channel_both, TAS2555_PLL_D_VAL_MSB_REG, 0x00,  //PLL D = 0
84         channel_both, TAS2555_PLL_D_VAL_LSB_REG, 0x00,
85         channel_both, TAS2555_PLL_N_VAL_REG, 0x03,      //PLL N = 3 -> NDIV_CLK = 24.576MHz
86         channel_both, TAS2555_DAC_MADC_VAL_REG, 0x08,   //MDAC = 8
87         channel_both, TAS2555_CLK_MISC_REG, 0x20,       //DSP CLK = PLL out
88 //  TAS2555_ISENSE_DIV_REG,     0x40, //Isense div and MADC final divider configure auto
89         channel_both, TAS2555_ISENSE_DIV_REG, 0x00,     //Isense div and MADC final divider configure auto
90 //  TAS2555_RAMP_CLK_DIV_LSB_REG,   0x20, //ramp_clk divider = 32 so that 12.288MHz/32 = 384KHz
91         channel_both, TAS2555_RAMP_CLK_DIV_LSB_REG, 0x40,       //ramp_clk divider = 64 so that 24.576MHz/64 = 384KHz
92         channel_both, TAS2555_DSP_MODE_SELECT_REG, 0x22,        //DSP ROM mode 2, default coeffs
94 //  TAS2555_SPK_CTRL_REG,       0x74, //DAC channel gain
95         channel_both, TAS2555_SPK_CTRL_REG, 0x7C,       //DAC channel gain
96 //  TAS2555_POWER_CTRL2_REG,    0xA3, //power up
97 //  TAS2555_POWER_CTRL1_REG,    0xF8, //power up
98 //  TAS2555_MUTE_REG,       0x00, //unmute
99 //  TAS2555_SOFT_MUTE_REG,      0x00, //soft unmute
100 //  TAS2555_CLK_ERR_CTRL,       0x09, //enable clock error detection on PLL
101         0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF
102 };
104 #define TAS2555_STARTUP_DATA_PLL_CLKIN_INDEX 5
105 static unsigned int p_tas2555_startup_data[] = {
106         channel_both, TAS2555_CLK_ERR_CTRL, 0x00,       //disable clock error detection on PLL
107         channel_both, TAS2555_PLL_CLKIN_REG, TAS2555_DEFAULT_PLL_CLKIN,
108         channel_both, TAS2555_POWER_CTRL2_REG, 0xA0,    //Class-D, Boost power up
109         channel_both, TAS2555_POWER_CTRL2_REG, 0xA3,    //Class-D, Boost, IV sense power up
110         channel_both, TAS2555_POWER_CTRL1_REG, 0xF8,    //PLL, DSP, clock dividers power up
111         channel_both, TAS2555_UDELAY, 2000,             //delay
112         0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF
113 };
115 static unsigned int p_tas2555_unmute_data[] = {
116         channel_both, TAS2555_MUTE_REG, 0x00,           //unmute
117         channel_both, TAS2555_SOFT_MUTE_REG, 0x00,      //soft unmute
118         0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF
119 };
121 static unsigned int p_tas2555_shutdown_data[] = {
122         channel_both, TAS2555_SOFT_MUTE_REG, 0x01,      //soft mute
123         channel_both, TAS2555_UDELAY, 10000,            //delay 10ms
124         channel_both, TAS2555_MUTE_REG, 0x03,           //mute
125         channel_both, TAS2555_PLL_CLKIN_REG, 0x0F,      //PLL clock input = osc
126         channel_both, TAS2555_POWER_CTRL1_REG, 0x60,    //DSP power down
127         channel_both, TAS2555_UDELAY, 2000,             //delay 2ms
128         channel_both, TAS2555_POWER_CTRL2_REG, 0x00,    //Class-D, Boost power down
129         channel_both, TAS2555_POWER_CTRL1_REG, 0x00,    //all power down
130         0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF
131 };
134 static unsigned int p_tas2555_mute_DSP_down_data[] = {
135         channel_both, TAS2555_MUTE_REG, 0x03,           //mute
136         channel_both, TAS2555_PLL_CLKIN_REG, 0x0F,      //PLL clock input = osc
137         channel_both, TAS2555_POWER_CTRL1_REG, 0x60,    //DSP power down
138         channel_both, TAS2555_UDELAY, 0xFF,             //delay
139         0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF
140 };
142 static int tas2555_dev_load_data(struct tas2555_priv *pTAS2555,
143         unsigned int *pData)
145         int ret = 0;
146         unsigned int n = 0;
147         enum channel chl;
148         unsigned int nRegister;
149         unsigned int nData;
151         do {
152                 chl = pData[n * 3];
153                 nRegister = pData[n * 3 + 1];
154                 nData = pData[n * 3 + 2];
155                 if (nRegister == TAS2555_UDELAY)
156                         udelay(nData);
157                 else if (nRegister != 0xFFFFFFFF){
158                         ret = pTAS2555->write(pTAS2555, chl, nRegister, nData);
159                         if(ret < 0) {
160                                 dev_err(pTAS2555->dev, "Reg Write err %d\n", ret);
161                                 break;
162                         }
163                 }
164                 n++;
165         } while (nRegister != 0xFFFFFFFF);
166         
167         return ret;
170 int tas2555_load_default(struct tas2555_priv *pTAS2555)
172         return tas2555_dev_load_data(pTAS2555, p_tas2555_default_data);
175 void tas2555_enable(struct tas2555_priv *pTAS2555, bool bEnable)
177         dev_dbg(pTAS2555->dev, "Enable: %d\n", bEnable);
178         if (bEnable) {
179                 if (!pTAS2555->mbPowerUp) {
180                         TConfiguration *pConfiguration;
182                         if (!pTAS2555->mbCalibrationLoaded) {
183                                 tas2555_load_calibration(pTAS2555, TAS2555_CAL_NAME);
184                                 pTAS2555->mbCalibrationLoaded = true;
185                         }
186                         dev_dbg(pTAS2555->dev, "Enable: load startup sequence\n");
187                         tas2555_dev_load_data(pTAS2555, p_tas2555_startup_data);
188                         if (pTAS2555->mpFirmware->mpConfigurations) {
189                                 pConfiguration = &(pTAS2555->mpFirmware->mpConfigurations[pTAS2555->mnCurrentConfiguration]);
190                                 tas2555_load_data(pTAS2555, &(pConfiguration->mData),
191                                         TAS2555_BLOCK_POST_POWER_UP);
192                                 if (pTAS2555->mbLoadConfigurationPostPowerUp) {
193                                         dev_dbg(pTAS2555->dev,  "Enable: load configuration: %s, %s\n",
194                                                 pConfiguration->mpName, pConfiguration->mpDescription);
195                                         tas2555_load_data(pTAS2555, &(pConfiguration->mData),
196                                                 TAS2555_BLOCK_COEFF_DEV_A);
197                                         tas2555_load_data(pTAS2555, &(pConfiguration->mData),
198                                                 TAS2555_BLOCK_COEFF_DEV_B);
199                                         pTAS2555->mbLoadConfigurationPostPowerUp = false;
200                                         if (pTAS2555->mpCalFirmware->mnCalibrations) {
201                                                 dev_dbg(pTAS2555->dev, "Enable: load calibration\n");
202                                                 tas2555_load_block(pTAS2555, 
203                                                         &(pTAS2555->mpCalFirmware->mpCalibrations[pTAS2555->mnCurrentCalibration].mBlock));
204                                                 pTAS2555->mbLoadCalibrationPostPowerUp = false;
205                                         }
206                                 }else{
207                                         if (pTAS2555->mpCalFirmware->mnCalibrations) {
208                                                 if(pTAS2555->mbLoadCalibrationPostPowerUp){
209                                                         dev_dbg(pTAS2555->dev, "Enable: load calibration\n");
210                                                         tas2555_load_block(pTAS2555, 
211                                                                 &(pTAS2555->mpCalFirmware->mpCalibrations[pTAS2555->mnCurrentCalibration].mBlock));
212                                                         pTAS2555->mbLoadCalibrationPostPowerUp = false;
213                                                 }
214                                         }
215                                 }
216                         }
217                         dev_dbg(pTAS2555->dev, "Enable: load unmute sequence\n");
218                         tas2555_dev_load_data(pTAS2555, p_tas2555_unmute_data);
219                         pTAS2555->mbPowerUp = true;
220                 }
221         } else {
222                 if (pTAS2555->mbPowerUp) {
223                         dev_dbg(pTAS2555->dev, "Enable: load shutdown sequence\n");
224                         tas2555_dev_load_data(pTAS2555, p_tas2555_shutdown_data);
225                         //tas2555_dev_load_data(pTAS2555, p_tas2555_shutdown_clk_err);
226                         pTAS2555->mbPowerUp = false;
227                 }
228         }
231 int tas2555_set_bit_rate(struct tas2555_priv *pTAS2555, 
232         enum channel chn, unsigned int nBitRate)
234         int ret = 0, n = -1;
235         
236         dev_dbg(pTAS2555->dev, "tas2555_set_bit_rate: nBitRate = %d \n",
237                 nBitRate);
238         switch(nBitRate){
239                 case 16:
240                         n = 0;
241                 break;
242                 case 20:
243                         n = 1;
244                 break;
245                 case 24:
246                         n = 2;
247                 break;
248                 case 32:
249                         n = 3;
250                 break;
251         }
252         
253         if(n >= 0)
254                 ret = pTAS2555->update_bits(pTAS2555, chn,
255                         TAS2555_ASI1_DAC_FORMAT_REG, 0x18, n<<3);       
256                 
257         return ret;     
260 int tas2555_get_bit_rate(struct tas2555_priv *pTAS2555, 
261         enum channel chn, unsigned char *pBitRate)
263         int ret = 0;
264         unsigned int nValue = 0;
265         unsigned char bitRate;
266         
267         ret = pTAS2555->read(pTAS2555, chn,
268                 TAS2555_ASI1_DAC_FORMAT_REG, &nValue);
269         if(ret >=0){    
270                 bitRate = (nValue&0x18)>>3;
271                 if(bitRate == 0) bitRate = 16;
272                 else if(bitRate == 1) bitRate = 20;
273                 else if(bitRate == 2) bitRate = 24;
274                 else if(bitRate == 3) bitRate = 32;
275                 
276                 *pBitRate = bitRate;
277         }else{
278                 dev_err(pTAS2555->dev, "read left channel error %d\n", ret);
279         }
280                 
281         return ret;     
284 int tas2555_get_DAC_gain(struct tas2555_priv *pTAS2555, enum channel chl, unsigned char *pnGain)
286         int ret = 0;
287         unsigned int nValue = 0;
288         
289         ret = pTAS2555->read(pTAS2555, chl,
290                         TAS2555_SPK_CTRL_REG, &nValue);
291         if(ret >=0){
292                 *pnGain = 
293                         ((nValue&TAS2555_DAC_GAIN_MASK)>>TAS2555_DAC_GAIN_SHIFT);
294         }
295                 
296         return ret;     
299 int tas2555_set_DAC_gain(struct tas2555_priv *pTAS2555, enum channel chl, unsigned int nGain)
301         int ret = 0;
302         
303         ret = pTAS2555->update_bits(pTAS2555, chl,
304                         TAS2555_SPK_CTRL_REG, 
305                         TAS2555_DAC_GAIN_MASK, 
306                         (nGain<<TAS2555_DAC_GAIN_SHIFT));
307                 
308         return ret;     
311 int tas2555_set_sampling_rate(struct tas2555_priv *pTAS2555, unsigned int nSamplingRate)
313         TConfiguration *pConfiguration;
314         unsigned int nConfiguration;
316         dev_dbg(pTAS2555->dev, "tas2555_setup_clocks: nSamplingRate = %d [Hz]\n",
317                 nSamplingRate);
319         if ((!pTAS2555->mpFirmware->mpPrograms) ||
320                 (!pTAS2555->mpFirmware->mpConfigurations)) {
321                 dev_err(pTAS2555->dev, "Firmware not loaded\n");
322                 return -EINVAL;
323         }
325         pConfiguration = &(pTAS2555->mpFirmware->mpConfigurations[pTAS2555->mnCurrentConfiguration]);
326         if (pConfiguration->mnSamplingRate == nSamplingRate) {
327                 dev_info(pTAS2555->dev, "Sampling rate for current configuration matches: %d\n",
328                         nSamplingRate);
329                 return 0;
330         }
332         for (nConfiguration = 0;
333                 nConfiguration < pTAS2555->mpFirmware->mnConfigurations;
334                 nConfiguration++) {
335                 pConfiguration =
336                         &(pTAS2555->mpFirmware->mpConfigurations[nConfiguration]);
337                 if ((pConfiguration->mnSamplingRate == nSamplingRate)
338                         &&(pConfiguration->mnProgram == pTAS2555->mnCurrentProgram)){
339                         dev_info(pTAS2555->dev,
340                                 "Found configuration: %s, with compatible sampling rate %d\n",
341                                 pConfiguration->mpName, nSamplingRate);
342                         tas2555_load_configuration(pTAS2555, nConfiguration, false);
343                         return 0;
344                 }
345         }
347         dev_err(pTAS2555->dev, "Cannot find a configuration that supports sampling rate: %d\n",
348                 nSamplingRate);
350         return -EINVAL;
353 static void fw_print_header(struct tas2555_priv *pTAS2555, TFirmware * pFirmware)
355         dev_info(pTAS2555->dev, "  FW Size       = %d", pFirmware->mnFWSize);
356         dev_info(pTAS2555->dev, "  Checksum      = 0x%04X", pFirmware->mnChecksum);
357         dev_info(pTAS2555->dev, "  PPC Version   = 0x%04X", pFirmware->mnPPCVersion);
358         dev_info(pTAS2555->dev, "  DSPFWVersion  = 0x%04X", pFirmware->mnDSPFWVersion);
359         dev_info(pTAS2555->dev, "  DRVFWVersion  = 0x%04X", pFirmware->mnDrvFWVersion);
360         dev_info(pTAS2555->dev, "  Timestamp     = %d", pFirmware->mnTimeStamp);
361         dev_info(pTAS2555->dev, "  DDC Name      = %s", pFirmware->mpDDCName);
362         dev_info(pTAS2555->dev, "  Description   = %s", pFirmware->mpDescription);
365 inline unsigned int fw_convert_number(unsigned char *pData)
367         return pData[3] + (pData[2] << 8) + (pData[1] << 16) + (pData[0] << 24);
370 static int fw_parse_header(struct tas2555_priv *pTAS2555, 
371         TFirmware * pFirmware, unsigned char *pData,
372         unsigned int nSize)
374         unsigned char *pDataStart = pData;
375         unsigned int n;
376         unsigned char pMagicNumber[] = { 0x35, 0x35, 0x35, 0x32 };
377         if (nSize < 104) {
378                 dev_err(pTAS2555->dev, "Firmware: Header too short");
379                 return -1;
380         }
382         if (memcmp(pData, pMagicNumber, 4)) {
383                 dev_err(pTAS2555->dev, "Firmware: Magic number doesn't match");
384                 return -1;
385         }
387         pData += 4;
389         pFirmware->mnFWSize = fw_convert_number(pData);
390         pData += 4;
392         pFirmware->mnChecksum = fw_convert_number(pData);
393         pData += 4;
395         pFirmware->mnPPCVersion = fw_convert_number(pData);
396         pData += 4;
398 //      pFirmware->mnDSPFWVersion = fw_convert_number(pData);
399 //      pData += 4;
400         
401         pFirmware->mnDrvFWVersion = fw_convert_number(pData);
402         pData += 4;
404         pFirmware->mnTimeStamp = fw_convert_number(pData);
405         pData += 4;
407         memcpy(pFirmware->mpDDCName, pData, 64);
408         pData += 64;
410         n = strlen(pData);
411         pFirmware->mpDescription = kmemdup(pData, n + 1, GFP_KERNEL);
412         pData += n + 1;
414         if ((pData - pDataStart) >= nSize) {
415                 dev_err(pTAS2555->dev, "Firmware: Header too short after DDC description");
416                 return -1;
417         }
419         pFirmware->mnDeviceFamily = fw_convert_number(pData);
420         pData += 4;
422         pFirmware->mnDevice = fw_convert_number(pData);
423         pData += 4;
425         fw_print_header(pTAS2555, pFirmware);
427         return pData - pDataStart;
430 static int fw_parse_block_data(struct tas2555_priv *pTAS2555,
431         TBlock * pBlock, unsigned char *pData)
433         unsigned char *pDataStart = pData;
434         unsigned int n;
436         pBlock->mnType = fw_convert_number(pData);
437         pData += 4;
439         dev_dbg(pTAS2555->dev, "TBlock type[%d]\n", pBlock->mnType);
440                 
441         pBlock->mnCommands = fw_convert_number(pData);
442         pData += 4;
444         n = pBlock->mnCommands * 4;
445         pBlock->mpData = kmemdup(pData, n, GFP_KERNEL);
446         pData += n;
448         return pData - pDataStart;
451 static int fw_parse_data(struct tas2555_priv *pTAS2555, 
452         TData * pImageData, unsigned char *pData)
454         unsigned char *pDataStart = pData;
455         unsigned int nBlock;
456         unsigned int n;
458         memcpy(pImageData->mpName, pData, 64);
459         pData += 64;
461         n = strlen(pData);
462         pImageData->mpDescription = kmemdup(pData, n + 1, GFP_KERNEL);
463         pData += n + 1;
465         dev_dbg(pTAS2555->dev, "TData name=%s\n", pImageData->mpName);
466         dev_dbg(pTAS2555->dev, "TData Desc=%s\n", pImageData->mpDescription);
467                 
468         pImageData->mnBlocks = (pData[0] << 8) + pData[1];
469         pData += 2;
471         pImageData->mpBlocks =
472                 kmalloc(sizeof(TBlock) * pImageData->mnBlocks, GFP_KERNEL);
474         for (nBlock = 0; nBlock < pImageData->mnBlocks; nBlock++) {
475                 n = fw_parse_block_data(pTAS2555,
476                         &(pImageData->mpBlocks[nBlock]), pData);
477                 pData += n;
478         }
480         return pData - pDataStart;
483 static int fw_parse_pll_data(struct tas2555_priv *pTAS2555, 
484         TFirmware * pFirmware, unsigned char *pData)
486         unsigned char *pDataStart = pData;
487         unsigned int n;
488         unsigned int nPLL;
489         TPLL *pPLL;
491         pFirmware->mnPLLs = (pData[0] << 8) + pData[1];
492         pData += 2;
494         pFirmware->mpPLLs = kmalloc(sizeof(TPLL) * pFirmware->mnPLLs, GFP_KERNEL);
495         for (nPLL = 0; nPLL < pFirmware->mnPLLs; nPLL++) {
496                 pPLL = &(pFirmware->mpPLLs[nPLL]);
498                 memcpy(pPLL->mpName, pData, 64);
499                 pData += 64;
501                 n = strlen(pData);
502                 pPLL->mpDescription = kmemdup(pData, n + 1, GFP_KERNEL);
503                 pData += n + 1;
505                 dev_dbg(pTAS2555->dev, "PLL[%d] Name=%s\n", nPLL, pPLL->mpName);
506                 dev_dbg(pTAS2555->dev, "PLL[%d] Desc=%s\n", nPLL, pPLL->mpDescription);
507                 n = fw_parse_block_data(pTAS2555, &(pPLL->mBlock), pData);
508                 pData += n;
509         }
511         return pData - pDataStart;
514 static int fw_parse_program_data(struct tas2555_priv *pTAS2555,
515         TFirmware * pFirmware, unsigned char *pData)
517         unsigned char *pDataStart = pData;
518         unsigned int n;
519         unsigned int nProgram;
520         TProgram *pProgram;
522         pFirmware->mnPrograms = (pData[0] << 8) + pData[1];
523         pData += 2;
525         pFirmware->mpPrograms =
526                 kmalloc(sizeof(TProgram) * pFirmware->mnPrograms, GFP_KERNEL);
527         for (nProgram = 0; nProgram < pFirmware->mnPrograms; nProgram++) {
528                 pProgram = &(pFirmware->mpPrograms[nProgram]);
529                 memcpy(pProgram->mpName, pData, 64);
530                 pData += 64;
532                 n = strlen(pData);
533                 pProgram->mpDescription = kmemdup(pData, n + 1, GFP_KERNEL);
534                 pData += n + 1;
536                 dev_dbg(pTAS2555->dev, "Program[%d] Name=%s\n", nProgram, pProgram->mpName);
537                 dev_dbg(pTAS2555->dev, "Program[%d] Desc=%s\n", nProgram, pProgram->mpDescription);
538                 
539                 n = fw_parse_data(pTAS2555, &(pProgram->mData), pData);
540                 pData += n;
541         }
543         return pData - pDataStart;
546 static int fw_parse_configuration_data(struct tas2555_priv *pTAS2555,
547         TFirmware * pFirmware,
548         unsigned char *pData)
550         unsigned char *pDataStart = pData;
551         unsigned int n;
552         unsigned int nConfiguration;
553         TConfiguration *pConfiguration;
555         pFirmware->mnConfigurations = (pData[0] << 8) + pData[1];
556         pData += 2;
558         pFirmware->mpConfigurations =
559                 kmalloc(sizeof(TConfiguration) * pFirmware->mnConfigurations,
560                 GFP_KERNEL);
561         for (nConfiguration = 0; nConfiguration < pFirmware->mnConfigurations;
562                 nConfiguration++) {
563                 pConfiguration = &(pFirmware->mpConfigurations[nConfiguration]);
564                 memcpy(pConfiguration->mpName, pData, 64);
565                 pData += 64;
567                 n = strlen(pData);
568                 pConfiguration->mpDescription = kmemdup(pData, n + 1, GFP_KERNEL);
569                 pData += n + 1;
571                 pConfiguration->mnProgram = pData[0];
572                 pData++;
573                 
574                 dev_dbg(pTAS2555->dev, "Configuration[%d] Name=%s\n", nConfiguration, pConfiguration->mpName);
575                 dev_dbg(pTAS2555->dev, "Configuration[%d] Desc=%s\n", nConfiguration, pConfiguration->mpDescription);
577                 pConfiguration->mnPLL = pData[0];
578                 pData++;
580                 pConfiguration->mnSamplingRate = fw_convert_number(pData);
581                 pData += 4;
583                 n = fw_parse_data(pTAS2555, &(pConfiguration->mData), pData);
584                 pData += n;
585         }
587         return pData - pDataStart;
590 int fw_parse_calibration_data(struct tas2555_priv *pTAS2555,
591         TFirmware * pFirmware, unsigned char *pData)
593         unsigned char *pDataStart = pData;
594         unsigned int n;
595         unsigned int nCalibration;
596         TCalibration *pCalibration;
598         pFirmware->mnCalibrations = (pData[0] << 8) + pData[1];
599         pData += 2;
601         pFirmware->mpCalibrations =
602                 kmalloc(sizeof(TCalibration) * pFirmware->mnCalibrations, GFP_KERNEL);
603         for (nCalibration = 0;
604                 nCalibration < pFirmware->mnCalibrations;
605                 nCalibration++) {
606                 pCalibration = &(pFirmware->mpCalibrations[nCalibration]);
607                 memcpy(pCalibration->mpName, pData, 64);
608                 pData += 64;
610                 n = strlen(pData);
611                 pCalibration->mpDescription = kmemdup(pData, n + 1, GFP_KERNEL);
612                 pData += n + 1;
614                 pCalibration->mnProgram = pData[0];
615                 pData++;
617                 pCalibration->mnConfiguration = pData[0];
618                 pData++;
620                 n = fw_parse_block_data(pTAS2555, &(pCalibration->mBlock), pData);
621                 pData += n;
622         }
624         return pData - pDataStart;
627 static int fw_parse(struct tas2555_priv *pTAS2555,
628         TFirmware * pFirmware,
629         unsigned char *pData,
630         unsigned int nSize)
632         int nPosition = 0;
634         nPosition = fw_parse_header(pTAS2555, pFirmware, pData, nSize);
635         if (nPosition < 0) {
636                 dev_err(pTAS2555->dev, "Firmware: Wrong Header");
637                 return FW_ERR_HEADER;
638         }
640         if (nPosition >= nSize) {
641                 dev_err(pTAS2555->dev, "Firmware: Too short");
642                 return FW_ERR_SIZE;
643         }
645         pData += nPosition;
646         nSize -= nPosition;
647         nPosition = 0;
649         nPosition = fw_parse_pll_data(pTAS2555, pFirmware, pData);
651         pData += nPosition;
652         nSize -= nPosition;
653         nPosition = 0;
655         nPosition = fw_parse_program_data(pTAS2555, pFirmware, pData);
657         pData += nPosition;
658         nSize -= nPosition;
659         nPosition = 0;
661         nPosition = fw_parse_configuration_data(pTAS2555, pFirmware, pData);
663         pData += nPosition;
664         nSize -= nPosition;
665         nPosition = 0;
667         if (nSize > 64)
668                 nPosition = fw_parse_calibration_data(pTAS2555, pFirmware, pData);
670         return 0;
673 static void tas2555_load_block(struct tas2555_priv *pTAS2555, TBlock * pBlock)
675         unsigned int nCommand = 0;
676         unsigned char nBook;
677         unsigned char nPage;
678         unsigned char nOffset;
679         unsigned char nData;
680         unsigned int nLength;
681         enum channel chl;
682         unsigned char *pData = pBlock->mpData;
684         dev_dbg(pTAS2555->dev, "TAS2555 load block: Type = %d, commands = %d\n",
685                 pBlock->mnType, pBlock->mnCommands);
686         
687         if((pBlock->mnType == TAS2555_BLOCK_PLL)
688                 ||(pBlock->mnType == TAS2555_BLOCK_POST)
689                 ||(pBlock->mnType == TAS2555_BLOCK_POST_POWER_UP)){
690                 chl = channel_both;
691         }else if((pBlock->mnType == TAS2555_BLOCK_MAIN_DEV_A)
692                 ||(pBlock->mnType == TAS2555_BLOCK_COEFF_DEV_A)
693                 ||(pBlock->mnType == TAS2555_BLOCK_PRE_DEV_A)){
694                 chl = channel_left;
695         }else if((pBlock->mnType == TAS2555_BLOCK_MAIN_DEV_B)
696                 ||(pBlock->mnType == TAS2555_BLOCK_COEFF_DEV_B)
697                 ||(pBlock->mnType == TAS2555_BLOCK_PRE_DEV_B)){
698                 chl = channel_right;            
699         }else{
700                 dev_err(pTAS2555->dev, "block type error %d\n", pBlock->mnType);
701                 return;
702         }
703                         
704         while (nCommand < pBlock->mnCommands) {
705                 pData = pBlock->mpData + nCommand * 4;
707                 nBook = pData[0];
708                 nPage = pData[1];
709                 nOffset = pData[2];
710                 nData = pData[3];
712                 nCommand++;
714                 if (nOffset <= 0x7F){
715                         pTAS2555->write(pTAS2555, 
716                                                         chl, 
717                                                         TAS2555_REG(nBook, nPage, nOffset),
718                                                         nData);
719                 }else if (nOffset == 0x81) {
720                         unsigned int nSleep = (nBook << 8) + nPage;
721                         msleep(nSleep);
722                 }else if (nOffset == 0x85) {
723                         pData += 4;
724                         nLength = (nBook << 8) + nPage;
725                         nBook = pData[0];
726                         nPage = pData[1];
727                         nOffset = pData[2];
728                         if (nLength > 1)
729                                 pTAS2555->bulk_write(pTAS2555, 
730                                                                         chl, 
731                                                                         TAS2555_REG(nBook, nPage, nOffset), 
732                                                                         pData + 3, 
733                                                                         nLength);
734                         else
735                                 pTAS2555->write(pTAS2555, 
736                                                                 chl, 
737                                                                 TAS2555_REG(nBook, nPage, nOffset),
738                                                                 pData[3]);
740                         nCommand++;
741                         if (nLength >= 2)
742                                 nCommand += ((nLength - 2) / 4) + 1;
743                 }
744         }
747 static void tas2555_load_data(struct tas2555_priv *pTAS2555, TData * pData,
748         unsigned int nType)
750         unsigned int nBlock;
751         TBlock *pBlock;
753         dev_dbg(pTAS2555->dev,
754                 "TAS2555 load data: %s, Blocks = %d, Block Type = %d\n", pData->mpName,
755                 pData->mnBlocks, nType);
757         for (nBlock = 0; nBlock < pData->mnBlocks; nBlock++) {
758                 pBlock = &(pData->mpBlocks[nBlock]);
759                 if (pBlock->mnType == nType)
760                         tas2555_load_block(pTAS2555, pBlock);
761         }
764 static void tas2555_load_configuration(struct tas2555_priv *pTAS2555,
765         unsigned int nConfiguration, bool bLoadSame)
767         TConfiguration *pCurrentConfiguration;
768         TConfiguration *pNewConfiguration;
769         TPLL *pNewPLL;
771         dev_dbg(pTAS2555->dev, "tas2555_load_configuration: %d\n", nConfiguration);
773         if ((!pTAS2555->mpFirmware->mpPrograms) ||
774                 (!pTAS2555->mpFirmware->mpConfigurations)) {
775                 dev_err(pTAS2555->dev, "Firmware not loaded\n");
776                 return;
777         }
779         if (nConfiguration >= pTAS2555->mpFirmware->mnConfigurations) {
780                 dev_err(pTAS2555->dev, "Configuration %d doesn't exist\n",
781                         nConfiguration);
782                 return;
783         }
785         if ((nConfiguration == pTAS2555->mnCurrentConfiguration) && (!bLoadSame)) {
786                 dev_info(pTAS2555->dev, "Configuration %d is already loaded\n",
787                         nConfiguration);
788                 return;
789         }
791         pCurrentConfiguration =
792                 &(pTAS2555->mpFirmware->mpConfigurations[pTAS2555->mnCurrentConfiguration]);
793         pNewConfiguration =
794                 &(pTAS2555->mpFirmware->mpConfigurations[nConfiguration]);
796         if (pNewConfiguration->mnProgram != pCurrentConfiguration->mnProgram) {
797                 dev_err(pTAS2555->dev,
798                         "Configuration %d, %s doesn't share the same program as current %d\n",
799                         nConfiguration, pNewConfiguration->mpName, pCurrentConfiguration->mnProgram);
800                 return;
801         }
803         if (pNewConfiguration->mnPLL >= pTAS2555->mpFirmware->mnPLLs) {
804                 dev_err(pTAS2555->dev,
805                         "Configuration %d, %s doesn't have a valid PLL index %d\n",
806                         nConfiguration, pNewConfiguration->mpName, pNewConfiguration->mnPLL);
807                 return;
808         }
809         
810         pNewPLL = &(pTAS2555->mpFirmware->mpPLLs[pNewConfiguration->mnPLL]);
812         if (pTAS2555->mbPowerUp) {
813                 if (pNewConfiguration->mnPLL != pCurrentConfiguration->mnPLL) {
814                         dev_dbg(pTAS2555->dev,
815                                 "TAS2555 is powered up -> mute and power down DSP before loading new configuration\n");
816                         //tas2555_dev_load_data(pTAS2555, p_tas2555_mute_DSP_down_data);
817                         tas2555_dev_load_data(pTAS2555, p_tas2555_shutdown_data);
819                         dev_dbg(pTAS2555->dev,
820                                 "load post block from current configuration: %s, before loading new configuration: %s\n",
821                                 pCurrentConfiguration->mpName, pNewConfiguration->mpName);
822                         tas2555_load_data(pTAS2555, &(pCurrentConfiguration->mData),
823                                 TAS2555_BLOCK_POST);
824                         dev_dbg(pTAS2555->dev, "TAS2555: load new PLL: %s, block data\n",
825                                 pNewPLL->mpName);
826                         tas2555_load_block(pTAS2555, &(pNewPLL->mBlock));
827                         pTAS2555->mnCurrentSampleRate = pNewConfiguration->mnSamplingRate;
828                         dev_dbg(pTAS2555->dev,
829                                 "load new configuration: %s, pre block data\n",
830                                 pNewConfiguration->mpName);
831                         tas2555_load_data(pTAS2555, &(pNewConfiguration->mData),
832                                 TAS2555_BLOCK_PRE_DEV_A);
833                         tas2555_load_data(pTAS2555, &(pNewConfiguration->mData),
834                                 TAS2555_BLOCK_PRE_DEV_B);
835                         dev_dbg(pTAS2555->dev, "TAS2555: power up TAS2555\n");
836                         tas2555_dev_load_data(pTAS2555, p_tas2555_startup_data);
837                         dev_dbg(pTAS2555->dev,
838                                 "TAS2555: load new configuration: %s, post power up block data\n",
839                                 pNewConfiguration->mpName);
840                         tas2555_load_data(pTAS2555, &(pNewConfiguration->mData),
841                                 TAS2555_BLOCK_POST_POWER_UP);
842                         dev_dbg(pTAS2555->dev,
843                                 "TAS2555: load new configuration: %s, coeff block data\n",
844                                 pNewConfiguration->mpName);
845                         tas2555_load_data(pTAS2555, &(pNewConfiguration->mData),
846                                 TAS2555_BLOCK_COEFF_DEV_A);
847                                 tas2555_load_data(pTAS2555, &(pNewConfiguration->mData),
848                                 TAS2555_BLOCK_COEFF_DEV_B);
849                         dev_dbg(pTAS2555->dev, "TAS2555: unmute TAS2555\n");
850                         tas2555_dev_load_data(pTAS2555, p_tas2555_unmute_data);
851                 } else {
852                         dev_dbg(pTAS2555->dev,
853                                 "TAS2555 is powered up, no change in PLL: load new configuration: %s, coeff block data\n",
854                                 pNewConfiguration->mpName);
855                         tas2555_load_data(pTAS2555, &(pNewConfiguration->mData),
856                                 TAS2555_BLOCK_COEFF_DEV_A);
857                         tas2555_load_data(pTAS2555, &(pNewConfiguration->mData),
858                                 TAS2555_BLOCK_COEFF_DEV_B);                                     
859                 }
860                 
861                 if (pTAS2555->mpCalFirmware->mnCalibrations) {
862                                 dev_dbg(pTAS2555->dev, "Enable: load calibration\n");
863                                 tas2555_load_block(pTAS2555, 
864                                         &(pTAS2555->mpCalFirmware->mpCalibrations[pTAS2555->mnCurrentCalibration].mBlock));
865                                 pTAS2555->mbLoadCalibrationPostPowerUp = false;
866                 }
867                 
868                 pTAS2555->mbLoadConfigurationPostPowerUp = false;
869         } else {
870                 dev_dbg(pTAS2555->dev,
871                         "TAS2555 was powered down -> set flag to load configuration data when OS powers up the TAS2555 the next time\n");
872                 if (pNewConfiguration->mnPLL != pCurrentConfiguration->mnPLL) {
873                         dev_dbg(pTAS2555->dev,
874                                 "load post block from current configuration: %s, before loading new configuration: %s\n",
875                                 pCurrentConfiguration->mpName, pNewConfiguration->mpName);
876                         tas2555_load_data(pTAS2555, &(pCurrentConfiguration->mData),
877                                 TAS2555_BLOCK_POST);
878                         dev_dbg(pTAS2555->dev, "TAS2555: load new PLL: %s, block data\n",
879                                 pNewPLL->mpName);
880                         tas2555_load_block(pTAS2555, &(pNewPLL->mBlock));
881                         pTAS2555->mnCurrentSampleRate = pNewConfiguration->mnSamplingRate;
882                         dev_dbg(pTAS2555->dev,
883                                 "load new configuration: %s, pre block data\n",
884                                 pNewConfiguration->mpName);
885                         tas2555_load_data(pTAS2555, &(pNewConfiguration->mData),
886                                 TAS2555_BLOCK_PRE_DEV_A);
887                         tas2555_load_data(pTAS2555, &(pNewConfiguration->mData),
888                                 TAS2555_BLOCK_PRE_DEV_B);
889                 }
890                 
891                 pTAS2555->mbLoadConfigurationPostPowerUp = true;
892         }
894         pTAS2555->mnCurrentConfiguration = nConfiguration;
897 int tas2555_set_config(struct tas2555_priv *pTAS2555, int config)
899         TConfiguration *pConfiguration;
900         TProgram *pProgram;
901         unsigned int nProgram = pTAS2555->mnCurrentProgram;
902         unsigned int nConfiguration = config;
904         if ((!pTAS2555->mpFirmware->mpPrograms) ||
905                 (!pTAS2555->mpFirmware->mpConfigurations)) {
906                 dev_err(pTAS2555->dev, "Firmware not loaded\n");
907                 return -1;
908         }
910         if (nConfiguration >= pTAS2555->mpFirmware->mnConfigurations) {
911                 dev_err(pTAS2555->dev, "Configuration %d doesn't exist\n",
912                         nConfiguration);
913                 return -1;
914         }
916         pConfiguration = &(pTAS2555->mpFirmware->mpConfigurations[nConfiguration]);
917         pProgram = &(pTAS2555->mpFirmware->mpPrograms[nProgram]);
919         if (nProgram != pConfiguration->mnProgram) {
920                 dev_err(pTAS2555->dev,
921                         "Configuration %d, %s with Program %d isn't compatible with existing Program %d, %s\n",
922                         nConfiguration, pConfiguration->mpName, pConfiguration->mnProgram,
923                         nProgram, pProgram->mpName);
924                 return -1;
925         }
927         tas2555_load_configuration(pTAS2555, nConfiguration, false);
929         return 0;
932 void tas2555_clear_firmware(TFirmware *pFirmware)
934         unsigned int n, nn;
935         if (!pFirmware) return;
936         if (pFirmware->mpDescription) kfree(pFirmware->mpDescription);  
938         for (n = 0; n < pFirmware->mnPLLs; n++)
939         {
940                 kfree(pFirmware->mpPLLs[n].mpDescription);
941                 kfree(pFirmware->mpPLLs[n].mBlock.mpData);
942         }
943         kfree(pFirmware->mpPLLs);
945         for (n = 0; n < pFirmware->mnPrograms; n++)
946         {
947                 kfree(pFirmware->mpPrograms[n].mpDescription);
948                 kfree(pFirmware->mpPrograms[n].mData.mpDescription);
949                 for (nn = 0; nn < pFirmware->mpPrograms[n].mData.mnBlocks; nn++)
950                         kfree(pFirmware->mpPrograms[n].mData.mpBlocks[nn].mpData);
951                 kfree(pFirmware->mpPrograms[n].mData.mpBlocks);
952         }
953         kfree(pFirmware->mpPrograms);
955         for (n = 0; n < pFirmware->mnConfigurations; n++)
956         {
957                 kfree(pFirmware->mpConfigurations[n].mpDescription);
958                 kfree(pFirmware->mpConfigurations[n].mData.mpDescription);
959                 for (nn = 0; nn < pFirmware->mpConfigurations[n].mData.mnBlocks; nn++)
960                         kfree(pFirmware->mpConfigurations[n].mData.mpBlocks[nn].mpData);
961                 kfree(pFirmware->mpConfigurations[n].mData.mpBlocks);
962         }
963         kfree(pFirmware->mpConfigurations);
965         for (n = 0; n < pFirmware->mnCalibrations; n++)
966         {
967                 kfree(pFirmware->mpCalibrations[n].mpDescription);
968                 kfree(pFirmware->mpCalibrations[n].mBlock.mpData);
969         }
970         kfree(pFirmware->mpCalibrations);
972         memset(pFirmware, 0x00, sizeof(TFirmware));
975 static void tas2555_load_calibration(struct tas2555_priv *pTAS2555,
976         char *pFileName)
978         int nResult;
979         int nFile;
980         mm_segment_t fs;
981         unsigned char pBuffer[512];
982         int nSize = 0;
984         dev_dbg(pTAS2555->dev, "%s:\n", __func__);
986         fs = get_fs();
987         set_fs(KERNEL_DS);
988         nFile = sys_open(pFileName, O_RDONLY, 0);
990         dev_info(pTAS2555->dev, "TAS2555 calibration file = %s, handle = %d\n",
991                 pFileName, nFile);
993         if (nFile >= 0) {
994                 nSize = sys_read(nFile, pBuffer, 512);
995                 sys_close(nFile);
996         } else {
997                 dev_err(pTAS2555->dev, "TAS2555 cannot open calibration file: %s\n",
998                         pFileName);
999         }
1001         set_fs(fs);
1003         if (!nSize)
1004                 return;
1006         tas2555_clear_firmware(pTAS2555->mpCalFirmware);
1007                 
1008         dev_info(pTAS2555->dev, "TAS2555 calibration file size = %d\n", nSize);
1009         nResult = fw_parse(pTAS2555, pTAS2555->mpCalFirmware, pBuffer, nSize);
1011         if (nResult) {
1012                 dev_err(pTAS2555->dev, "TAS2555 calibration file is corrupt\n");
1013                 return;
1014         }
1016         dev_info(pTAS2555->dev, "TAS2555 calibration: %d calibrations\n",
1017                 pTAS2555->mpCalFirmware->mnCalibrations);
1020 void tas2555_fw_ready(const struct firmware *pFW, void *pContext)
1022         struct tas2555_priv *pTAS2555 = (struct tas2555_priv *) pContext;
1023         int nResult;
1024         unsigned int nProgram = 0;
1025         unsigned int nSampleRate = 0;
1027         dev_info(pTAS2555->dev, "%s:\n", __func__);
1029         if (unlikely(!pFW) || unlikely(!pFW->data)) {
1030                 dev_err(pTAS2555->dev, "%s firmware is not loaded.\n",
1031                         TAS2555_FW_NAME);
1032                 return;
1033         }
1035         if (pTAS2555->mpFirmware->mpConfigurations){
1036                 nProgram = pTAS2555->mnCurrentProgram;
1037                 nSampleRate = pTAS2555->mnCurrentSampleRate;
1038                 dev_dbg(pTAS2555->dev, "clear current firmware\n");
1039                 tas2555_clear_firmware(pTAS2555->mpFirmware);
1040         }       
1041                 
1042         nResult = fw_parse(pTAS2555, pTAS2555->mpFirmware, 
1043                 (unsigned char *) (pFW->data),  pFW->size);
1045         release_firmware(pFW);
1046         
1047         if (nResult) {
1048                 dev_err(pTAS2555->dev, "firmware is corrupt\n");
1049                 return;
1050         }
1052         if (!pTAS2555->mpFirmware->mnPrograms) {
1053                 dev_err(pTAS2555->dev, "firmware contains no programs\n");
1054                 return;
1055         }
1056         
1057         if (!pTAS2555->mpFirmware->mnConfigurations) {
1058                 dev_err(pTAS2555->dev, 
1059                         "firmware contains no configurations\n");
1060                 return;
1061         }
1062         
1063         if(nProgram >= pTAS2555->mpFirmware->mnPrograms){
1064                 dev_info(pTAS2555->dev, 
1065                         "no previous program, set to default\n");
1066                 nProgram = 0;
1067         }
1068                 
1069         pTAS2555->mnCurrentSampleRate = nSampleRate;
1071         tas2555_set_program(pTAS2555, nProgram);
1072 }       
1074 int tas2555_set_program(struct tas2555_priv *pTAS2555,
1075         unsigned int nProgram)
1077         TPLL *pPLL;
1078         TConfiguration *pConfiguration;
1079         unsigned int nConfiguration = 0;
1080         unsigned int nSampleRate = 0;
1081         unsigned int Value = 0;
1082         bool bFound = false;
1083         int nResult = -1;
1085         if ((!pTAS2555->mpFirmware->mpPrograms) ||
1086                 (!pTAS2555->mpFirmware->mpConfigurations)) {
1087                 dev_err(pTAS2555->dev, "Firmware not loaded\n");
1088                 return -1;
1089         }
1090         
1091         if (nProgram >= pTAS2555->mpFirmware->mnPrograms) {
1092                 dev_err(pTAS2555->dev, "TAS2555: Program %d doesn't exist\n",
1093                         nConfiguration);
1094                 return -1;
1095         }
1096         
1097         nConfiguration = 0;
1098         nSampleRate = pTAS2555->mnCurrentSampleRate;
1099         
1100         while (!bFound 
1101                 && (nConfiguration < pTAS2555->mpFirmware->mnConfigurations)) {
1102                 if (pTAS2555->mpFirmware->mpConfigurations[nConfiguration].mnProgram 
1103                         == nProgram){
1104                         if(nSampleRate == 0){
1105                                 bFound = true;
1106                                 dev_info(pTAS2555->dev, "find default configuration %d\n", nConfiguration);
1107                         }else if(nSampleRate 
1108                                 == pTAS2555->mpFirmware->mpConfigurations[nConfiguration].mnSamplingRate){
1109                                 bFound = true;
1110                                 dev_info(pTAS2555->dev, "find matching configuration %d\n", nConfiguration);
1111                         }else{
1112                                 nConfiguration++;
1113                         }
1114                 }else{
1115                         nConfiguration++;
1116                 }
1117         }
1118         
1119         if (!bFound) {
1120                 dev_err(pTAS2555->dev, 
1121                         "Program %d, no valid configuration found for sample rate %d, ignore\n",
1122                         nProgram, nSampleRate);
1123                 return -1;
1124         }
1125         
1126         pTAS2555->mnCurrentProgram = nProgram;
1127         if(pTAS2555->mbPowerUp)
1128                 tas2555_dev_load_data(pTAS2555, p_tas2555_mute_DSP_down_data);
1129         pTAS2555->write(pTAS2555, channel_both, TAS2555_SW_RESET_REG, 0x01);
1130         udelay(1000);
1131         
1132         dev_info(pTAS2555->dev, "load program %d\n", nProgram);
1133         tas2555_load_data(pTAS2555,
1134                 &(pTAS2555->mpFirmware->mpPrograms[nProgram].mData),
1135                 TAS2555_BLOCK_MAIN_DEV_A);
1136         tas2555_load_data(pTAS2555,
1137                 &(pTAS2555->mpFirmware->mpPrograms[nProgram].mData),
1138                 TAS2555_BLOCK_MAIN_DEV_B);
1140         pTAS2555->mnCurrentConfiguration = nConfiguration;
1142         pConfiguration =
1143                 &(pTAS2555->mpFirmware->mpConfigurations[nConfiguration]);
1144         pPLL = &(pTAS2555->mpFirmware->mpPLLs[pConfiguration->mnPLL]);
1145         dev_dbg(pTAS2555->dev,
1146                 "TAS2555 load PLL: %s block for Configuration %s\n",
1147                 pPLL->mpName, pConfiguration->mpName);
1148         
1149         tas2555_load_block(pTAS2555, &(pPLL->mBlock));
1150         pTAS2555->mnCurrentSampleRate = pConfiguration->mnSamplingRate;
1151         dev_dbg(pTAS2555->dev,
1152                 "load configuration %s conefficient pre block\n",
1153                 pConfiguration->mpName);                
1154         tas2555_load_data(pTAS2555, &(pConfiguration->mData), TAS2555_BLOCK_PRE_DEV_A);
1155         tas2555_load_data(pTAS2555, &(pConfiguration->mData), TAS2555_BLOCK_PRE_DEV_B);
1157         nResult = pTAS2555->read(pTAS2555, channel_left, TAS2555_CRC_CHECKSUM_REG, &Value);
1158         dev_info(pTAS2555->dev, "Left uCDSP Checksum: 0x%02x\n", Value);
1159         nResult = pTAS2555->read(pTAS2555, channel_right, TAS2555_CRC_CHECKSUM_REG, &Value);
1160         dev_info(pTAS2555->dev, "Right uCDSP Checksum: 0x%02x\n", Value);       
1161         nResult = pTAS2555->read(pTAS2555, channel_left, TAS2555_PLL_CLKIN_REG, &Value);
1162         dev_info(pTAS2555->dev, "TAS2555 PLL_CLKIN = 0x%02X\n", Value);
1163         p_tas2555_startup_data[TAS2555_STARTUP_DATA_PLL_CLKIN_INDEX] = Value;
1165         if (pTAS2555->mbPowerUp){
1166                 dev_dbg(pTAS2555->dev, "device powered up, load startup\n");
1167                 tas2555_dev_load_data(pTAS2555, p_tas2555_startup_data);
1168                 dev_dbg(pTAS2555->dev, 
1169                         "device powered up, load configuration %s post power block\n",
1170                         pConfiguration->mpName);
1171                 tas2555_load_data(pTAS2555, &(pConfiguration->mData),
1172                         TAS2555_BLOCK_POST_POWER_UP);
1173         }
1174         
1175         tas2555_load_configuration(pTAS2555, nConfiguration, true);
1176         if (pTAS2555->mbPowerUp){
1177                 dev_dbg(pTAS2555->dev,
1178                         "device powered up, load unmute\n");
1179                 tas2555_dev_load_data(pTAS2555, p_tas2555_unmute_data);
1180         }
1182         return 0;
1185 int tas2555_set_calibration(struct tas2555_priv *pTAS2555,
1186         int nCalibration)
1188         if ((!pTAS2555->mpFirmware->mpPrograms) || (!pTAS2555->mpFirmware->mpConfigurations)) 
1189         {
1190                 dev_err(pTAS2555->dev, "Firmware not loaded\n\r");
1191                 return -1;
1192         }
1194         if (nCalibration == 0x00FF)
1195         {
1196                 dev_info(pTAS2555->dev, "load new calibration file %s\n", TAS2555_CAL_NAME);    
1197                 tas2555_load_calibration(pTAS2555, TAS2555_CAL_NAME);
1198                 nCalibration = 0;
1199         }
1201         if (nCalibration >= pTAS2555->mpFirmware->mnCalibrations) {
1202                 dev_err(pTAS2555->dev,
1203                         "Calibration %d doesn't exist\n", nCalibration);
1204                 return -1;
1205         }
1207         pTAS2555->mnCurrentCalibration = nCalibration;
1208         if(pTAS2555->mbPowerUp){
1209                 tas2555_load_block(pTAS2555, 
1210                         &(pTAS2555->mpCalFirmware->mpCalibrations[pTAS2555->mnCurrentCalibration].mBlock));
1211                 pTAS2555->mbLoadCalibrationPostPowerUp = false; 
1212         }else{
1213                 pTAS2555->mbLoadCalibrationPostPowerUp = true; 
1214         }
1216         return 0;
1219 int tas2555_parse_dt(struct device *dev,
1220                         struct tas2555_priv *pTAS2555)
1222         struct device_node *np = dev->of_node;
1223         int rc= 0, ret = 0;
1224         unsigned int value;
1225         
1226         pTAS2555->mnResetGPIO = of_get_named_gpio(np, "ti,cdc-reset-gpio", 0);
1227         if (pTAS2555->mnResetGPIO < 0) {
1228                 dev_err(pTAS2555->dev, "Looking up %s property in node %s failed %d\n",
1229                         "ti,cdc-reset-gpio", np->full_name,
1230                         pTAS2555->mnResetGPIO);
1231                 ret = -1;
1232         }else{
1233                 dev_dbg(pTAS2555->dev, "ti,cdc-reset-gpio=%d\n", pTAS2555->mnResetGPIO);
1234         }
1235         
1236         if(ret >=0){
1237                 rc = of_property_read_u32(np, "ti,left-channel", &value);
1238                 if (rc) {
1239                         dev_err(pTAS2555->dev, "Looking up %s property in node %s failed %d\n",
1240                                 "ti,left-channel", np->full_name, rc);
1241                         ret = -2;
1242                 }else{
1243                         pTAS2555->mnLAddr = value;
1244                         dev_dbg(pTAS2555->dev, "ti,left-channel=0x%x\n", pTAS2555->mnLAddr);
1245                 }
1246         }
1247         
1248         if(ret >=0){
1249                 rc = of_property_read_u32(np, "ti,right-channel", &value);
1250                 if (rc) {
1251                         dev_err(pTAS2555->dev, "Looking up %s property in node %s failed %d\n",
1252                                 "ti,right-channel", np->full_name, rc);
1253                         ret = -3;
1254                 }else{
1255                         pTAS2555->mnRAddr = value;
1256                         dev_dbg(pTAS2555->dev, "ti,right-channel=0x%x", pTAS2555->mnRAddr);
1257                 }
1258         }
1259         
1260         return ret;
1263 MODULE_AUTHOR("Texas Instruments Inc.");
1264 MODULE_DESCRIPTION("TAS2555 common functions for Android Linux");
1265 MODULE_LICENSE("GPLv2");