]> Gitweb @ Texas Instruments - Open Source Git Repositories - git.TI.com/gitweb - tas2555sw-android/tas2555-android-device-driver-stereo.git/blob - tas2555-core.c
99e74ecc64ed5dcba1739a1d1b6df2bb90e4554a
[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 PPC_WITH_DRIVER_VERSION         0x010bc000
48 #define TAS2555_CAL_NAME    "/data/tas2555_cal.bin"
50 //set default PLL CLKIN to GPI2 (MCLK) = 0x00
51 #define TAS2555_DEFAULT_PLL_CLKIN 0x00
53 static void tas2555_load_calibration(struct tas2555_priv *pTAS2555,
54         char *pFileName);
55 static void tas2555_load_data(struct tas2555_priv *pTAS2555, TData * pData,
56         unsigned int nType);
57 static void tas2555_load_block(struct tas2555_priv *pTAS2555, TBlock * pBlock);
58 static void tas2555_load_configuration(struct tas2555_priv *pTAS2555,
59         unsigned int nConfiguration, bool bLoadSame);
60         
61 #define TAS2555_UDELAY 0xFFFFFFFE
63 #define FW_ERR_HEADER -1
64 #define FW_ERR_SIZE -2
66 #define TAS2555_BLOCK_PLL                       0x00
67 #define TAS2555_BLOCK_MAIN_ALL          0x0d
68 #define TAS2555_BLOCK_MAIN_DEV_A        0x01
69 #define TAS2555_BLOCK_MAIN_DEV_B        0x08
70 #define TAS2555_BLOCK_COEFF_DEV_A       0x03
71 #define TAS2555_BLOCK_COEFF_DEV_B       0x0a
72 #define TAS2555_BLOCK_PRE_DEV_A         0x04
73 #define TAS2555_BLOCK_PRE_DEV_B         0x0B
74 #define TAS2555_BLOCK_POST                      0x05
75 #define TAS2555_BLOCK_POST_POWER_UP     0x06
77 static unsigned int p_tas2555_default_data[] = {
78         channel_both, TAS2555_ASI1_DAC_FORMAT_REG, 0x10,        //ASI1 DAC word length = 24 bits
80         channel_both, TAS2555_PLL_CLKIN_REG, TAS2555_DEFAULT_PLL_CLKIN, //PLL_CLKIN = GPIO1 (BCLK)
81         channel_both, TAS2555_MAIN_CLKIN_REG, 0x0F,     //NDIV_MUX_CLKIN = PLL_CLK
82         channel_both, TAS2555_PLL_P_VAL_REG, 0x01,      //PLL P = 1
83 //  TAS2555_PLL_J_VAL_REG,      0x10, //PLL J = 16
84         channel_both, TAS2555_PLL_J_VAL_REG, 0x30,      //PLL J = 48 -> PLL_CLK = 1.536MHz * 48 = 73.728MHz
85         channel_both, TAS2555_PLL_D_VAL_MSB_REG, 0x00,  //PLL D = 0
86         channel_both, TAS2555_PLL_D_VAL_LSB_REG, 0x00,
87         channel_both, TAS2555_PLL_N_VAL_REG, 0x03,      //PLL N = 3 -> NDIV_CLK = 24.576MHz
88         channel_both, TAS2555_DAC_MADC_VAL_REG, 0x08,   //MDAC = 8
89         channel_both, TAS2555_CLK_MISC_REG, 0x20,       //DSP CLK = PLL out
90 //  TAS2555_ISENSE_DIV_REG,     0x40, //Isense div and MADC final divider configure auto
91         channel_both, TAS2555_ISENSE_DIV_REG, 0x00,     //Isense div and MADC final divider configure auto
92 //  TAS2555_RAMP_CLK_DIV_LSB_REG,   0x20, //ramp_clk divider = 32 so that 12.288MHz/32 = 384KHz
93         channel_both, TAS2555_RAMP_CLK_DIV_LSB_REG, 0x40,       //ramp_clk divider = 64 so that 24.576MHz/64 = 384KHz
94         channel_both, TAS2555_DSP_MODE_SELECT_REG, 0x22,        //DSP ROM mode 2, default coeffs
96 //  TAS2555_SPK_CTRL_REG,       0x74, //DAC channel gain
97         channel_both, TAS2555_SPK_CTRL_REG, 0x7C,       //DAC channel gain
98 //  TAS2555_POWER_CTRL2_REG,    0xA3, //power up
99 //  TAS2555_POWER_CTRL1_REG,    0xF8, //power up
100 //  TAS2555_MUTE_REG,       0x00, //unmute
101 //  TAS2555_SOFT_MUTE_REG,      0x00, //soft unmute
102 //  TAS2555_CLK_ERR_CTRL,       0x09, //enable clock error detection on PLL
103         0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF
104 };
106 #define TAS2555_STARTUP_DATA_PLL_CLKIN_INDEX 5
107 static unsigned int p_tas2555_startup_data[] = {
108         channel_both, TAS2555_CLK_ERR_CTRL, 0x00,       //disable clock error detection on PLL
109         channel_both, TAS2555_PLL_CLKIN_REG, TAS2555_DEFAULT_PLL_CLKIN,
110         channel_both, TAS2555_POWER_CTRL2_REG, 0xA0,    //Class-D, Boost power up
111         channel_both, TAS2555_POWER_CTRL2_REG, 0xA3,    //Class-D, Boost, IV sense power up
112         channel_both, TAS2555_POWER_CTRL1_REG, 0xF8,    //PLL, DSP, clock dividers power up
113         channel_both, TAS2555_UDELAY, 2000,             //delay
114         0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF
115 };
117 static unsigned int p_tas2555_unmute_data[] = {
118         channel_both, TAS2555_MUTE_REG, 0x00,           //unmute
119         channel_both, TAS2555_SOFT_MUTE_REG, 0x00,      //soft unmute
120         0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF
121 };
123 static unsigned int p_tas2555_enter_broadcast_data[] = {
124         channel_both, TAS2555_TEST_MODE_REG, 0x0d,              //enter test mode
125         channel_both, TAS2555_BROADCAST_REG, 0x81,      //enable broadcast
126         0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF
127 };
129 static unsigned int p_tas2555_exit_broadcast_data[] = {
130         channel_broadcast, TAS2555_TEST_MODE_REG, 0x0d,         //enter test mode
131         channel_broadcast, TAS2555_BROADCAST_REG, 0x01, //disable broadcast
132         0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF
133 };
135 static unsigned int p_tas2555_shutdown_data[] = {
136         channel_both, TAS2555_SOFT_MUTE_REG, 0x01,      //soft mute
137         channel_both, TAS2555_UDELAY, 10000,            //delay 10ms
138         channel_both, TAS2555_MUTE_REG, 0x03,           //mute
139         channel_both, TAS2555_PLL_CLKIN_REG, 0x0F,      //PLL clock input = osc
140         channel_both, TAS2555_POWER_CTRL1_REG, 0x60,    //DSP power down
141         channel_both, TAS2555_UDELAY, 2000,             //delay 2ms
142         channel_both, TAS2555_POWER_CTRL2_REG, 0x00,    //Class-D, Boost power down
143         channel_both, TAS2555_POWER_CTRL1_REG, 0x00,    //all power down
144         0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF
145 };
148 static unsigned int p_tas2555_mute_DSP_down_data[] = {
149         channel_both, TAS2555_MUTE_REG, 0x03,           //mute
150         channel_both, TAS2555_PLL_CLKIN_REG, 0x0F,      //PLL clock input = osc
151         channel_both, TAS2555_POWER_CTRL1_REG, 0x60,    //DSP power down
152         channel_both, TAS2555_UDELAY, 0xFF,             //delay
153         0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF
154 };
156 static int tas2555_dev_load_data(struct tas2555_priv *pTAS2555,
157         unsigned int *pData)
159         int ret = 0;
160         unsigned int n = 0;
161         enum channel chl;
162         unsigned int nRegister;
163         unsigned int nData;
165         do {
166                 chl = pData[n * 3];
167                 nRegister = pData[n * 3 + 1];
168                 nData = pData[n * 3 + 2];
169                 if (nRegister == TAS2555_UDELAY)
170                         udelay(nData);
171                 else if (nRegister != 0xFFFFFFFF){
172                         ret = pTAS2555->write(pTAS2555, chl, nRegister, nData);
173                         if(ret < 0) {
174                                 dev_err(pTAS2555->dev, "Reg Write err %d\n", ret);
175                                 break;
176                         }
177                 }
178                 n++;
179         } while (nRegister != 0xFFFFFFFF);
180         
181         return ret;
184 int tas2555_load_default(struct tas2555_priv *pTAS2555)
186         return tas2555_dev_load_data(pTAS2555, p_tas2555_default_data);
189 void tas2555_enable(struct tas2555_priv *pTAS2555, bool bEnable)
191         dev_dbg(pTAS2555->dev, "Enable: %d\n", bEnable);
192         if (bEnable) {
193                 if (!pTAS2555->mbPowerUp) {
194                         TConfiguration *pConfiguration;
196                         if (!pTAS2555->mbCalibrationLoaded) {
197                                 tas2555_load_calibration(pTAS2555, TAS2555_CAL_NAME);
198                                 pTAS2555->mbCalibrationLoaded = true;
199                         }
200                         dev_dbg(pTAS2555->dev, "Enable: load startup sequence\n");
201                         tas2555_dev_load_data(pTAS2555, p_tas2555_startup_data);
202                         if (pTAS2555->mpFirmware->mpConfigurations) {
203                                 pConfiguration = &(pTAS2555->mpFirmware->mpConfigurations[pTAS2555->mnCurrentConfiguration]);
204                                 tas2555_load_data(pTAS2555, &(pConfiguration->mData),
205                                         TAS2555_BLOCK_POST_POWER_UP);
206                                 if (pTAS2555->mbLoadConfigurationPostPowerUp) {
207                                         dev_dbg(pTAS2555->dev,  "Enable: load configuration: %s, %s\n",
208                                                 pConfiguration->mpName, pConfiguration->mpDescription);
209                                         tas2555_load_data(pTAS2555, &(pConfiguration->mData),
210                                                 TAS2555_BLOCK_COEFF_DEV_A);
211                                         tas2555_load_data(pTAS2555, &(pConfiguration->mData),
212                                                 TAS2555_BLOCK_COEFF_DEV_B);
213                                         pTAS2555->mbLoadConfigurationPostPowerUp = false;
214                                         if (pTAS2555->mpCalFirmware->mnCalibrations) {
215                                                 dev_dbg(pTAS2555->dev, "Enable: load calibration\n");
216                                                 tas2555_load_block(pTAS2555, 
217                                                         &(pTAS2555->mpCalFirmware->mpCalibrations[pTAS2555->mnCurrentCalibration].mBlock));
218                                                 pTAS2555->mbLoadCalibrationPostPowerUp = false;
219                                         }
220                                 }else{
221                                         if (pTAS2555->mpCalFirmware->mnCalibrations) {
222                                                 if(pTAS2555->mbLoadCalibrationPostPowerUp){
223                                                         dev_dbg(pTAS2555->dev, "Enable: load calibration\n");
224                                                         tas2555_load_block(pTAS2555, 
225                                                                 &(pTAS2555->mpCalFirmware->mpCalibrations[pTAS2555->mnCurrentCalibration].mBlock));
226                                                         pTAS2555->mbLoadCalibrationPostPowerUp = false;
227                                                 }
228                                         }
229                                 }
230                         }
231                         dev_dbg(pTAS2555->dev, "Enable: load unmute sequence\n");
232                         tas2555_dev_load_data(pTAS2555, p_tas2555_unmute_data);
233                         pTAS2555->mbPowerUp = true;
234                 }
235         } else {
236                 if (pTAS2555->mbPowerUp) {
237                         dev_dbg(pTAS2555->dev, "Enable: load shutdown sequence\n");
238                         tas2555_dev_load_data(pTAS2555, p_tas2555_shutdown_data);
239                         //tas2555_dev_load_data(pTAS2555, p_tas2555_shutdown_clk_err);
240                         pTAS2555->mbPowerUp = false;
241                 }
242         }
245 int tas2555_set_bit_rate(struct tas2555_priv *pTAS2555, 
246         enum channel chn, unsigned int nBitRate)
248         int ret = 0, n = -1;
249         
250         dev_dbg(pTAS2555->dev, "tas2555_set_bit_rate: nBitRate = %d \n",
251                 nBitRate);
252         switch(nBitRate){
253                 case 16:
254                         n = 0;
255                 break;
256                 case 20:
257                         n = 1;
258                 break;
259                 case 24:
260                         n = 2;
261                 break;
262                 case 32:
263                         n = 3;
264                 break;
265         }
266         
267         if(n >= 0)
268                 ret = pTAS2555->update_bits(pTAS2555, chn,
269                         TAS2555_ASI1_DAC_FORMAT_REG, 0x18, n<<3);       
270                 
271         return ret;     
274 int tas2555_get_bit_rate(struct tas2555_priv *pTAS2555, 
275         enum channel chn, unsigned char *pBitRate)
277         int ret = 0;
278         unsigned int nValue = 0;
279         unsigned char bitRate;
280         
281         ret = pTAS2555->read(pTAS2555, chn,
282                 TAS2555_ASI1_DAC_FORMAT_REG, &nValue);
283         if(ret >=0){    
284                 bitRate = (nValue&0x18)>>3;
285                 if(bitRate == 0) bitRate = 16;
286                 else if(bitRate == 1) bitRate = 20;
287                 else if(bitRate == 2) bitRate = 24;
288                 else if(bitRate == 3) bitRate = 32;
289                 
290                 *pBitRate = bitRate;
291         }else{
292                 dev_err(pTAS2555->dev, "read left channel error %d\n", ret);
293         }
294                 
295         return ret;     
298 int tas2555_get_DAC_gain(struct tas2555_priv *pTAS2555, enum channel chl, unsigned char *pnGain)
300         int ret = 0;
301         unsigned int nValue = 0;
302         
303         ret = pTAS2555->read(pTAS2555, chl,
304                         TAS2555_SPK_CTRL_REG, &nValue);
305         if(ret >=0){
306                 *pnGain = 
307                         ((nValue&TAS2555_DAC_GAIN_MASK)>>TAS2555_DAC_GAIN_SHIFT);
308         }
309                 
310         return ret;     
313 int tas2555_set_DAC_gain(struct tas2555_priv *pTAS2555, enum channel chl, unsigned int nGain)
315         int ret = 0;
316         
317         ret = pTAS2555->update_bits(pTAS2555, chl,
318                         TAS2555_SPK_CTRL_REG, 
319                         TAS2555_DAC_GAIN_MASK, 
320                         (nGain<<TAS2555_DAC_GAIN_SHIFT));
321                 
322         return ret;     
325 int tas2555_set_sampling_rate(struct tas2555_priv *pTAS2555, unsigned int nSamplingRate)
327         TConfiguration *pConfiguration;
328         unsigned int nConfiguration;
330         dev_dbg(pTAS2555->dev, "tas2555_setup_clocks: nSamplingRate = %d [Hz]\n",
331                 nSamplingRate);
333         if ((!pTAS2555->mpFirmware->mpPrograms) ||
334                 (!pTAS2555->mpFirmware->mpConfigurations)) {
335                 dev_err(pTAS2555->dev, "Firmware not loaded\n");
336                 return -EINVAL;
337         }
339         pConfiguration = &(pTAS2555->mpFirmware->mpConfigurations[pTAS2555->mnCurrentConfiguration]);
340         if (pConfiguration->mnSamplingRate == nSamplingRate) {
341                 dev_info(pTAS2555->dev, "Sampling rate for current configuration matches: %d\n",
342                         nSamplingRate);
343                 return 0;
344         }
346         for (nConfiguration = 0;
347                 nConfiguration < pTAS2555->mpFirmware->mnConfigurations;
348                 nConfiguration++) {
349                 pConfiguration =
350                         &(pTAS2555->mpFirmware->mpConfigurations[nConfiguration]);
351                 if ((pConfiguration->mnSamplingRate == nSamplingRate)
352                         &&(pConfiguration->mnProgram == pTAS2555->mnCurrentProgram)){
353                         dev_info(pTAS2555->dev,
354                                 "Found configuration: %s, with compatible sampling rate %d\n",
355                                 pConfiguration->mpName, nSamplingRate);
356                         tas2555_load_configuration(pTAS2555, nConfiguration, false);
357                         return 0;
358                 }
359         }
361         dev_err(pTAS2555->dev, "Cannot find a configuration that supports sampling rate: %d\n",
362                 nSamplingRate);
364         return -EINVAL;
367 static void fw_print_header(struct tas2555_priv *pTAS2555, TFirmware * pFirmware)
369         dev_info(pTAS2555->dev, "FW Size       = %d", pFirmware->mnFWSize);
370         dev_info(pTAS2555->dev, "Checksum      = 0x%04X", pFirmware->mnChecksum);
371         dev_info(pTAS2555->dev, "PPC Version   = 0x%04X", pFirmware->mnPPCVersion);
372         dev_info(pTAS2555->dev, "DSPFWVersion  = 0x%04X", pFirmware->mnFWVersion);      
373         if(pFirmware->mnPPCVersion >= PPC_WITH_DRIVER_VERSION)
374         dev_info(pTAS2555->dev, "Driver Version= 0x%04X", pFirmware->mnDriverVersion);
375         dev_info(pTAS2555->dev, "Timestamp     = %d", pFirmware->mnTimeStamp);
376         dev_info(pTAS2555->dev, "DDC Name      = %s", pFirmware->mpDDCName);
377         dev_info(pTAS2555->dev, "Description   = %s", pFirmware->mpDescription);
380 inline unsigned int fw_convert_number(unsigned char *pData)
382         return pData[3] + (pData[2] << 8) + (pData[1] << 16) + (pData[0] << 24);
385 static int fw_parse_header(struct tas2555_priv *pTAS2555, 
386         TFirmware * pFirmware, unsigned char *pData,
387         unsigned int nSize)
389         unsigned char *pDataStart = pData;
390         unsigned int n;
391         unsigned char pMagicNumber[] = { 0x35, 0x35, 0x35, 0x32 };
392         if (nSize < 104) {
393                 dev_err(pTAS2555->dev, "Firmware: Header too short");
394                 return -1;
395         }
397         if (memcmp(pData, pMagicNumber, 4)) {
398                 dev_err(pTAS2555->dev, "Firmware: Magic number doesn't match");
399                 return -1;
400         }
402         pData += 4;
404         pFirmware->mnFWSize = fw_convert_number(pData);
405         pData += 4;
407         pFirmware->mnChecksum = fw_convert_number(pData);
408         pData += 4;
410         pFirmware->mnPPCVersion = fw_convert_number(pData);
411         pData += 4;
413         pFirmware->mnFWVersion = fw_convert_number(pData);
414         pData += 4;
416         if(pFirmware->mnPPCVersion >= PPC_WITH_DRIVER_VERSION){
417                 pFirmware->mnDriverVersion = fw_convert_number(pData);
418                 pData += 4;             
419         }       
421         pFirmware->mnTimeStamp = fw_convert_number(pData);
422         pData += 4;
424         memcpy(pFirmware->mpDDCName, pData, 64);
425         pData += 64;
427         n = strlen(pData);
428         pFirmware->mpDescription = kmemdup(pData, n + 1, GFP_KERNEL);
429         pData += n + 1;
431         if ((pData - pDataStart) >= nSize) {
432                 dev_err(pTAS2555->dev, "Firmware: Header too short after DDC description");
433                 return -1;
434         }
436         pFirmware->mnDeviceFamily = fw_convert_number(pData);
437         pData += 4;
439         pFirmware->mnDevice = fw_convert_number(pData);
440         pData += 4;
442         fw_print_header(pTAS2555, pFirmware);
444         return pData - pDataStart;
447 static int fw_parse_block_data(struct tas2555_priv *pTAS2555,
448         TBlock * pBlock, unsigned char *pData)
450         unsigned char *pDataStart = pData;
451         unsigned int n;
453         pBlock->mnType = fw_convert_number(pData);
454         pData += 4;
456         dev_dbg(pTAS2555->dev, "TBlock type[%d]\n", pBlock->mnType);
457                 
458         pBlock->mnCommands = fw_convert_number(pData);
459         pData += 4;
461         n = pBlock->mnCommands * 4;
462         pBlock->mpData = kmemdup(pData, n, GFP_KERNEL);
463         pData += n;
465         return pData - pDataStart;
468 static int fw_parse_data(struct tas2555_priv *pTAS2555, 
469         TData * pImageData, unsigned char *pData)
471         unsigned char *pDataStart = pData;
472         unsigned int nBlock;
473         unsigned int n;
475         memcpy(pImageData->mpName, pData, 64);
476         pData += 64;
478         n = strlen(pData);
479         pImageData->mpDescription = kmemdup(pData, n + 1, GFP_KERNEL);
480         pData += n + 1;
482         dev_dbg(pTAS2555->dev, "TData name=%s\n", pImageData->mpName);
483         dev_dbg(pTAS2555->dev, "TData Desc=%s\n", pImageData->mpDescription);
484                 
485         pImageData->mnBlocks = (pData[0] << 8) + pData[1];
486         pData += 2;
488         pImageData->mpBlocks =
489                 kmalloc(sizeof(TBlock) * pImageData->mnBlocks, GFP_KERNEL);
491         for (nBlock = 0; nBlock < pImageData->mnBlocks; nBlock++) {
492                 n = fw_parse_block_data(pTAS2555,
493                         &(pImageData->mpBlocks[nBlock]), pData);
494                 pData += n;
495         }
497         return pData - pDataStart;
500 static int fw_parse_pll_data(struct tas2555_priv *pTAS2555, 
501         TFirmware * pFirmware, unsigned char *pData)
503         unsigned char *pDataStart = pData;
504         unsigned int n;
505         unsigned int nPLL;
506         TPLL *pPLL;
508         pFirmware->mnPLLs = (pData[0] << 8) + pData[1];
509         pData += 2;
511         pFirmware->mpPLLs = kmalloc(sizeof(TPLL) * pFirmware->mnPLLs, GFP_KERNEL);
512         for (nPLL = 0; nPLL < pFirmware->mnPLLs; nPLL++) {
513                 pPLL = &(pFirmware->mpPLLs[nPLL]);
515                 memcpy(pPLL->mpName, pData, 64);
516                 pData += 64;
518                 n = strlen(pData);
519                 pPLL->mpDescription = kmemdup(pData, n + 1, GFP_KERNEL);
520                 pData += n + 1;
522                 dev_dbg(pTAS2555->dev, "PLL[%d] Name=%s\n", nPLL, pPLL->mpName);
523                 dev_dbg(pTAS2555->dev, "PLL[%d] Desc=%s\n", nPLL, pPLL->mpDescription);
524                 n = fw_parse_block_data(pTAS2555, &(pPLL->mBlock), pData);
525                 pData += n;
526         }
528         return pData - pDataStart;
531 static int fw_parse_program_data(struct tas2555_priv *pTAS2555,
532         TFirmware * pFirmware, unsigned char *pData)
534         unsigned char *pDataStart = pData;
535         unsigned int n;
536         unsigned int nProgram;
537         TProgram *pProgram;
539         pFirmware->mnPrograms = (pData[0] << 8) + pData[1];
540         pData += 2;
542         pFirmware->mpPrograms =
543                 kmalloc(sizeof(TProgram) * pFirmware->mnPrograms, GFP_KERNEL);
544         for (nProgram = 0; nProgram < pFirmware->mnPrograms; nProgram++) {
545                 pProgram = &(pFirmware->mpPrograms[nProgram]);
546                 memcpy(pProgram->mpName, pData, 64);
547                 pData += 64;
549                 n = strlen(pData);
550                 pProgram->mpDescription = kmemdup(pData, n + 1, GFP_KERNEL);
551                 pData += n + 1;
553                 dev_dbg(pTAS2555->dev, "Program[%d] Name=%s\n", nProgram, pProgram->mpName);
554                 dev_dbg(pTAS2555->dev, "Program[%d] Desc=%s\n", nProgram, pProgram->mpDescription);
555                 
556                 n = fw_parse_data(pTAS2555, &(pProgram->mData), pData);
557                 pData += n;
558         }
560         return pData - pDataStart;
563 static int fw_parse_configuration_data(struct tas2555_priv *pTAS2555,
564         TFirmware * pFirmware,
565         unsigned char *pData)
567         unsigned char *pDataStart = pData;
568         unsigned int n;
569         unsigned int nConfiguration;
570         TConfiguration *pConfiguration;
572         pFirmware->mnConfigurations = (pData[0] << 8) + pData[1];
573         pData += 2;
575         pFirmware->mpConfigurations =
576                 kmalloc(sizeof(TConfiguration) * pFirmware->mnConfigurations,
577                 GFP_KERNEL);
578         for (nConfiguration = 0; nConfiguration < pFirmware->mnConfigurations;
579                 nConfiguration++) {
580                 pConfiguration = &(pFirmware->mpConfigurations[nConfiguration]);
581                 memcpy(pConfiguration->mpName, pData, 64);
582                 pData += 64;
584                 n = strlen(pData);
585                 pConfiguration->mpDescription = kmemdup(pData, n + 1, GFP_KERNEL);
586                 pData += n + 1;
588                 pConfiguration->mnProgram = pData[0];
589                 pData++;
590                 
591                 dev_dbg(pTAS2555->dev, "Configuration[%d] Name=%s\n", nConfiguration, pConfiguration->mpName);
592                 dev_dbg(pTAS2555->dev, "Configuration[%d] Desc=%s\n", nConfiguration, pConfiguration->mpDescription);
594                 pConfiguration->mnPLL = pData[0];
595                 pData++;
597                 pConfiguration->mnSamplingRate = fw_convert_number(pData);
598                 pData += 4;
600                 n = fw_parse_data(pTAS2555, &(pConfiguration->mData), pData);
601                 pData += n;
602         }
604         return pData - pDataStart;
607 int fw_parse_calibration_data(struct tas2555_priv *pTAS2555,
608         TFirmware * pFirmware, unsigned char *pData)
610         unsigned char *pDataStart = pData;
611         unsigned int n;
612         unsigned int nCalibration;
613         TCalibration *pCalibration;
615         pFirmware->mnCalibrations = (pData[0] << 8) + pData[1];
616         pData += 2;
618         pFirmware->mpCalibrations =
619                 kmalloc(sizeof(TCalibration) * pFirmware->mnCalibrations, GFP_KERNEL);
620         for (nCalibration = 0;
621                 nCalibration < pFirmware->mnCalibrations;
622                 nCalibration++) {
623                 pCalibration = &(pFirmware->mpCalibrations[nCalibration]);
624                 memcpy(pCalibration->mpName, pData, 64);
625                 pData += 64;
627                 n = strlen(pData);
628                 pCalibration->mpDescription = kmemdup(pData, n + 1, GFP_KERNEL);
629                 pData += n + 1;
631                 pCalibration->mnProgram = pData[0];
632                 pData++;
634                 pCalibration->mnConfiguration = pData[0];
635                 pData++;
637                 n = fw_parse_block_data(pTAS2555, &(pCalibration->mBlock), pData);
638                 pData += n;
639         }
641         return pData - pDataStart;
644 static int fw_parse(struct tas2555_priv *pTAS2555,
645         TFirmware * pFirmware,
646         unsigned char *pData,
647         unsigned int nSize)
649         int nPosition = 0;
651         nPosition = fw_parse_header(pTAS2555, pFirmware, pData, nSize);
652         if (nPosition < 0) {
653                 dev_err(pTAS2555->dev, "Firmware: Wrong Header");
654                 return FW_ERR_HEADER;
655         }
657         if (nPosition >= nSize) {
658                 dev_err(pTAS2555->dev, "Firmware: Too short");
659                 return FW_ERR_SIZE;
660         }
662         pData += nPosition;
663         nSize -= nPosition;
664         nPosition = 0;
666         nPosition = fw_parse_pll_data(pTAS2555, pFirmware, pData);
668         pData += nPosition;
669         nSize -= nPosition;
670         nPosition = 0;
672         nPosition = fw_parse_program_data(pTAS2555, pFirmware, pData);
674         pData += nPosition;
675         nSize -= nPosition;
676         nPosition = 0;
678         nPosition = fw_parse_configuration_data(pTAS2555, pFirmware, pData);
680         pData += nPosition;
681         nSize -= nPosition;
682         nPosition = 0;
684         if (nSize > 64)
685                 nPosition = fw_parse_calibration_data(pTAS2555, pFirmware, pData);
687         return 0;
690 static void tas2555_load_block(struct tas2555_priv *pTAS2555, TBlock * pBlock)
692         unsigned int nCommand = 0;
693         unsigned char nBook;
694         unsigned char nPage;
695         unsigned char nOffset;
696         unsigned char nData;
697         unsigned int nLength;
698         enum channel chl;
699         unsigned char *pData = pBlock->mpData;
701         dev_dbg(pTAS2555->dev, "TAS2555 load block: Type = %d, commands = %d\n",
702                 pBlock->mnType, pBlock->mnCommands);
703         
704         if((pBlock->mnType == TAS2555_BLOCK_PLL)
705                 ||(pBlock->mnType == TAS2555_BLOCK_POST)
706                 ||(pBlock->mnType == TAS2555_BLOCK_POST_POWER_UP)){
707                 chl = channel_both;
708         }else if((pBlock->mnType == TAS2555_BLOCK_MAIN_DEV_A)
709                 ||(pBlock->mnType == TAS2555_BLOCK_COEFF_DEV_A)
710                 ||(pBlock->mnType == TAS2555_BLOCK_PRE_DEV_A)){
711                 chl = channel_left;
712         }else if((pBlock->mnType == TAS2555_BLOCK_MAIN_DEV_B)
713                 ||(pBlock->mnType == TAS2555_BLOCK_COEFF_DEV_B)
714                 ||(pBlock->mnType == TAS2555_BLOCK_PRE_DEV_B)){
715                 chl = channel_right;            
716         }else if(pBlock->mnType == TAS2555_BLOCK_MAIN_ALL){
717                 chl = channel_broadcast;                
718         }else{
719                 dev_err(pTAS2555->dev, "block type error %d\n", pBlock->mnType);
720                 return;
721         }
722         
723         if(chl == channel_broadcast){
724                 tas2555_dev_load_data(pTAS2555, p_tas2555_enter_broadcast_data);
725         }
726                         
727         while (nCommand < pBlock->mnCommands) {
728                 pData = pBlock->mpData + nCommand * 4;
730                 nBook = pData[0];
731                 nPage = pData[1];
732                 nOffset = pData[2];
733                 nData = pData[3];
735                 nCommand++;
737                 if (nOffset <= 0x7F){
738                         pTAS2555->write(pTAS2555, 
739                                                         chl, 
740                                                         TAS2555_REG(nBook, nPage, nOffset),
741                                                         nData);
742                 }else if (nOffset == 0x81) {
743                         unsigned int nSleep = (nBook << 8) + nPage;
744                         msleep(nSleep);
745                 }else if (nOffset == 0x85) {
746                         pData += 4;
747                         nLength = (nBook << 8) + nPage;
748                         nBook = pData[0];
749                         nPage = pData[1];
750                         nOffset = pData[2];
751                         if (nLength > 1)
752                                 pTAS2555->bulk_write(pTAS2555, 
753                                                                         chl, 
754                                                                         TAS2555_REG(nBook, nPage, nOffset), 
755                                                                         pData + 3, 
756                                                                         nLength);
757                         else
758                                 pTAS2555->write(pTAS2555, 
759                                                                 chl, 
760                                                                 TAS2555_REG(nBook, nPage, nOffset),
761                                                                 pData[3]);
763                         nCommand++;
764                         if (nLength >= 2)
765                                 nCommand += ((nLength - 2) / 4) + 1;
766                 }
767         }
768         
769         if(chl == channel_broadcast){
770                 tas2555_dev_load_data(pTAS2555, p_tas2555_exit_broadcast_data);
771         }
774 static void tas2555_load_data(struct tas2555_priv *pTAS2555, TData * pData,
775         unsigned int nType)
777         unsigned int nBlock;
778         TBlock *pBlock;
780         dev_dbg(pTAS2555->dev,
781                 "TAS2555 load data: %s, Blocks = %d, Block Type = %d\n", pData->mpName,
782                 pData->mnBlocks, nType);
784         for (nBlock = 0; nBlock < pData->mnBlocks; nBlock++) {
785                 pBlock = &(pData->mpBlocks[nBlock]);
786                 if (pBlock->mnType == nType)
787                         tas2555_load_block(pTAS2555, pBlock);
788         }
791 static void tas2555_load_configuration(struct tas2555_priv *pTAS2555,
792         unsigned int nConfiguration, bool bLoadSame)
794         TConfiguration *pCurrentConfiguration;
795         TConfiguration *pNewConfiguration;
796         TPLL *pNewPLL;
798         dev_dbg(pTAS2555->dev, "tas2555_load_configuration: %d\n", nConfiguration);
800         if ((!pTAS2555->mpFirmware->mpPrograms) ||
801                 (!pTAS2555->mpFirmware->mpConfigurations)) {
802                 dev_err(pTAS2555->dev, "Firmware not loaded\n");
803                 return;
804         }
806         if (nConfiguration >= pTAS2555->mpFirmware->mnConfigurations) {
807                 dev_err(pTAS2555->dev, "Configuration %d doesn't exist\n",
808                         nConfiguration);
809                 return;
810         }
812         if ((nConfiguration == pTAS2555->mnCurrentConfiguration) && (!bLoadSame)) {
813                 dev_info(pTAS2555->dev, "Configuration %d is already loaded\n",
814                         nConfiguration);
815                 return;
816         }
818         pCurrentConfiguration =
819                 &(pTAS2555->mpFirmware->mpConfigurations[pTAS2555->mnCurrentConfiguration]);
820         pNewConfiguration =
821                 &(pTAS2555->mpFirmware->mpConfigurations[nConfiguration]);
823         if (pNewConfiguration->mnProgram != pCurrentConfiguration->mnProgram) {
824                 dev_err(pTAS2555->dev,
825                         "Configuration %d, %s doesn't share the same program as current %d\n",
826                         nConfiguration, pNewConfiguration->mpName, pCurrentConfiguration->mnProgram);
827                 return;
828         }
830         if (pNewConfiguration->mnPLL >= pTAS2555->mpFirmware->mnPLLs) {
831                 dev_err(pTAS2555->dev,
832                         "Configuration %d, %s doesn't have a valid PLL index %d\n",
833                         nConfiguration, pNewConfiguration->mpName, pNewConfiguration->mnPLL);
834                 return;
835         }
836         
837         pNewPLL = &(pTAS2555->mpFirmware->mpPLLs[pNewConfiguration->mnPLL]);
839         if (pTAS2555->mbPowerUp) {
840                 if (pNewConfiguration->mnPLL != pCurrentConfiguration->mnPLL) {
841                         dev_dbg(pTAS2555->dev,
842                                 "TAS2555 is powered up -> mute and power down DSP before loading new configuration\n");
843                         //tas2555_dev_load_data(pTAS2555, p_tas2555_mute_DSP_down_data);
844                         tas2555_dev_load_data(pTAS2555, p_tas2555_shutdown_data);
846                         dev_dbg(pTAS2555->dev,
847                                 "load post block from current configuration: %s, before loading new configuration: %s\n",
848                                 pCurrentConfiguration->mpName, pNewConfiguration->mpName);
849                         tas2555_load_data(pTAS2555, &(pCurrentConfiguration->mData),
850                                 TAS2555_BLOCK_POST);
851                         dev_dbg(pTAS2555->dev, "TAS2555: load new PLL: %s, block data\n",
852                                 pNewPLL->mpName);
853                         tas2555_load_block(pTAS2555, &(pNewPLL->mBlock));
854                         pTAS2555->mnCurrentSampleRate = pNewConfiguration->mnSamplingRate;
855                         dev_dbg(pTAS2555->dev,
856                                 "load new configuration: %s, pre block data\n",
857                                 pNewConfiguration->mpName);
858                         tas2555_load_data(pTAS2555, &(pNewConfiguration->mData),
859                                 TAS2555_BLOCK_PRE_DEV_A);
860                         tas2555_load_data(pTAS2555, &(pNewConfiguration->mData),
861                                 TAS2555_BLOCK_PRE_DEV_B);
862                         dev_dbg(pTAS2555->dev, "TAS2555: power up TAS2555\n");
863                         tas2555_dev_load_data(pTAS2555, p_tas2555_startup_data);
864                         dev_dbg(pTAS2555->dev,
865                                 "TAS2555: load new configuration: %s, post power up block data\n",
866                                 pNewConfiguration->mpName);
867                         tas2555_load_data(pTAS2555, &(pNewConfiguration->mData),
868                                 TAS2555_BLOCK_POST_POWER_UP);
869                         dev_dbg(pTAS2555->dev,
870                                 "TAS2555: load new configuration: %s, coeff block data\n",
871                                 pNewConfiguration->mpName);
872                         tas2555_load_data(pTAS2555, &(pNewConfiguration->mData),
873                                 TAS2555_BLOCK_COEFF_DEV_A);
874                                 tas2555_load_data(pTAS2555, &(pNewConfiguration->mData),
875                                 TAS2555_BLOCK_COEFF_DEV_B);
876                         dev_dbg(pTAS2555->dev, "TAS2555: unmute TAS2555\n");
877                         tas2555_dev_load_data(pTAS2555, p_tas2555_unmute_data);
878                 } else {
879                         dev_dbg(pTAS2555->dev,
880                                 "TAS2555 is powered up, no change in PLL: load new configuration: %s, coeff block data\n",
881                                 pNewConfiguration->mpName);
882                         tas2555_load_data(pTAS2555, &(pNewConfiguration->mData),
883                                 TAS2555_BLOCK_COEFF_DEV_A);
884                         tas2555_load_data(pTAS2555, &(pNewConfiguration->mData),
885                                 TAS2555_BLOCK_COEFF_DEV_B);                                     
886                 }
887                 
888                 if (pTAS2555->mpCalFirmware->mnCalibrations) {
889                                 dev_dbg(pTAS2555->dev, "Enable: load calibration\n");
890                                 tas2555_load_block(pTAS2555, 
891                                         &(pTAS2555->mpCalFirmware->mpCalibrations[pTAS2555->mnCurrentCalibration].mBlock));
892                                 pTAS2555->mbLoadCalibrationPostPowerUp = false;
893                 }
894                 
895                 pTAS2555->mbLoadConfigurationPostPowerUp = false;
896         } else {
897                 dev_dbg(pTAS2555->dev,
898                         "TAS2555 was powered down -> set flag to load configuration data when OS powers up the TAS2555 the next time\n");
899                 if (pNewConfiguration->mnPLL != pCurrentConfiguration->mnPLL) {
900                         dev_dbg(pTAS2555->dev,
901                                 "load post block from current configuration: %s, before loading new configuration: %s\n",
902                                 pCurrentConfiguration->mpName, pNewConfiguration->mpName);
903                         tas2555_load_data(pTAS2555, &(pCurrentConfiguration->mData),
904                                 TAS2555_BLOCK_POST);
905                         dev_dbg(pTAS2555->dev, "TAS2555: load new PLL: %s, block data\n",
906                                 pNewPLL->mpName);
907                         tas2555_load_block(pTAS2555, &(pNewPLL->mBlock));
908                         pTAS2555->mnCurrentSampleRate = pNewConfiguration->mnSamplingRate;
909                         dev_dbg(pTAS2555->dev,
910                                 "load new configuration: %s, pre block data\n",
911                                 pNewConfiguration->mpName);
912                         tas2555_load_data(pTAS2555, &(pNewConfiguration->mData),
913                                 TAS2555_BLOCK_PRE_DEV_A);
914                         tas2555_load_data(pTAS2555, &(pNewConfiguration->mData),
915                                 TAS2555_BLOCK_PRE_DEV_B);
916                 }
917                 
918                 pTAS2555->mbLoadConfigurationPostPowerUp = true;
919         }
921         pTAS2555->mnCurrentConfiguration = nConfiguration;
924 int tas2555_set_config(struct tas2555_priv *pTAS2555, int config)
926         TConfiguration *pConfiguration;
927         TProgram *pProgram;
928         unsigned int nProgram = pTAS2555->mnCurrentProgram;
929         unsigned int nConfiguration = config;
931         if ((!pTAS2555->mpFirmware->mpPrograms) ||
932                 (!pTAS2555->mpFirmware->mpConfigurations)) {
933                 dev_err(pTAS2555->dev, "Firmware not loaded\n");
934                 return -1;
935         }
937         if (nConfiguration >= pTAS2555->mpFirmware->mnConfigurations) {
938                 dev_err(pTAS2555->dev, "Configuration %d doesn't exist\n",
939                         nConfiguration);
940                 return -1;
941         }
943         pConfiguration = &(pTAS2555->mpFirmware->mpConfigurations[nConfiguration]);
944         pProgram = &(pTAS2555->mpFirmware->mpPrograms[nProgram]);
946         if (nProgram != pConfiguration->mnProgram) {
947                 dev_err(pTAS2555->dev,
948                         "Configuration %d, %s with Program %d isn't compatible with existing Program %d, %s\n",
949                         nConfiguration, pConfiguration->mpName, pConfiguration->mnProgram,
950                         nProgram, pProgram->mpName);
951                 return -1;
952         }
954         tas2555_load_configuration(pTAS2555, nConfiguration, false);
956         return 0;
959 void tas2555_clear_firmware(TFirmware *pFirmware)
961         unsigned int n, nn;
962         if (!pFirmware) return;
963         if (pFirmware->mpDescription) kfree(pFirmware->mpDescription);  
965         for (n = 0; n < pFirmware->mnPLLs; n++)
966         {
967                 kfree(pFirmware->mpPLLs[n].mpDescription);
968                 kfree(pFirmware->mpPLLs[n].mBlock.mpData);
969         }
970         kfree(pFirmware->mpPLLs);
972         for (n = 0; n < pFirmware->mnPrograms; n++)
973         {
974                 kfree(pFirmware->mpPrograms[n].mpDescription);
975                 kfree(pFirmware->mpPrograms[n].mData.mpDescription);
976                 for (nn = 0; nn < pFirmware->mpPrograms[n].mData.mnBlocks; nn++)
977                         kfree(pFirmware->mpPrograms[n].mData.mpBlocks[nn].mpData);
978                 kfree(pFirmware->mpPrograms[n].mData.mpBlocks);
979         }
980         kfree(pFirmware->mpPrograms);
982         for (n = 0; n < pFirmware->mnConfigurations; n++)
983         {
984                 kfree(pFirmware->mpConfigurations[n].mpDescription);
985                 kfree(pFirmware->mpConfigurations[n].mData.mpDescription);
986                 for (nn = 0; nn < pFirmware->mpConfigurations[n].mData.mnBlocks; nn++)
987                         kfree(pFirmware->mpConfigurations[n].mData.mpBlocks[nn].mpData);
988                 kfree(pFirmware->mpConfigurations[n].mData.mpBlocks);
989         }
990         kfree(pFirmware->mpConfigurations);
992         for (n = 0; n < pFirmware->mnCalibrations; n++)
993         {
994                 kfree(pFirmware->mpCalibrations[n].mpDescription);
995                 kfree(pFirmware->mpCalibrations[n].mBlock.mpData);
996         }
997         kfree(pFirmware->mpCalibrations);
999         memset(pFirmware, 0x00, sizeof(TFirmware));
1002 static void tas2555_load_calibration(struct tas2555_priv *pTAS2555,
1003         char *pFileName)
1005         int nResult;
1006         int nFile;
1007         mm_segment_t fs;
1008         unsigned char pBuffer[512];
1009         int nSize = 0;
1011         dev_dbg(pTAS2555->dev, "%s:\n", __func__);
1013         fs = get_fs();
1014         set_fs(KERNEL_DS);
1015         nFile = sys_open(pFileName, O_RDONLY, 0);
1017         dev_info(pTAS2555->dev, "TAS2555 calibration file = %s, handle = %d\n",
1018                 pFileName, nFile);
1020         if (nFile >= 0) {
1021                 nSize = sys_read(nFile, pBuffer, 512);
1022                 sys_close(nFile);
1023         } else {
1024                 dev_err(pTAS2555->dev, "TAS2555 cannot open calibration file: %s\n",
1025                         pFileName);
1026         }
1028         set_fs(fs);
1030         if (!nSize)
1031                 return;
1033         tas2555_clear_firmware(pTAS2555->mpCalFirmware);
1034                 
1035         dev_info(pTAS2555->dev, "TAS2555 calibration file size = %d\n", nSize);
1036         nResult = fw_parse(pTAS2555, pTAS2555->mpCalFirmware, pBuffer, nSize);
1038         if (nResult) {
1039                 dev_err(pTAS2555->dev, "TAS2555 calibration file is corrupt\n");
1040                 return;
1041         }
1043         dev_info(pTAS2555->dev, "TAS2555 calibration: %d calibrations\n",
1044                 pTAS2555->mpCalFirmware->mnCalibrations);
1047 void tas2555_fw_ready(const struct firmware *pFW, void *pContext)
1049         struct tas2555_priv *pTAS2555 = (struct tas2555_priv *) pContext;
1050         int nResult;
1051         unsigned int nProgram = 0;
1052         unsigned int nSampleRate = 0;
1054         dev_info(pTAS2555->dev, "%s:\n", __func__);
1056         if (unlikely(!pFW) || unlikely(!pFW->data)) {
1057                 dev_err(pTAS2555->dev, "%s firmware is not loaded.\n",
1058                         TAS2555_FW_NAME);
1059                 return;
1060         }
1062         if (pTAS2555->mpFirmware->mpConfigurations){
1063                 nProgram = pTAS2555->mnCurrentProgram;
1064                 nSampleRate = pTAS2555->mnCurrentSampleRate;
1065                 dev_dbg(pTAS2555->dev, "clear current firmware\n");
1066                 tas2555_clear_firmware(pTAS2555->mpFirmware);
1067         }       
1068                 
1069         nResult = fw_parse(pTAS2555, pTAS2555->mpFirmware, 
1070                 (unsigned char *) (pFW->data),  pFW->size);
1072         release_firmware(pFW);
1073         
1074         if (nResult) {
1075                 dev_err(pTAS2555->dev, "firmware is corrupt\n");
1076                 return;
1077         }
1079         if (!pTAS2555->mpFirmware->mnPrograms) {
1080                 dev_err(pTAS2555->dev, "firmware contains no programs\n");
1081                 return;
1082         }
1083         
1084         if (!pTAS2555->mpFirmware->mnConfigurations) {
1085                 dev_err(pTAS2555->dev, 
1086                         "firmware contains no configurations\n");
1087                 return;
1088         }
1089         
1090         if(nProgram >= pTAS2555->mpFirmware->mnPrograms){
1091                 dev_info(pTAS2555->dev, 
1092                         "no previous program, set to default\n");
1093                 nProgram = 0;
1094         }
1095                 
1096         pTAS2555->mnCurrentSampleRate = nSampleRate;
1098         tas2555_set_program(pTAS2555, nProgram);
1099 }       
1101 int tas2555_set_program(struct tas2555_priv *pTAS2555,
1102         unsigned int nProgram)
1104         TPLL *pPLL;
1105         TConfiguration *pConfiguration;
1106         unsigned int nConfiguration = 0;
1107         unsigned int nSampleRate = 0;
1108         unsigned int Value = 0;
1109         bool bFound = false;
1110         int nResult = -1;
1112         if ((!pTAS2555->mpFirmware->mpPrograms) ||
1113                 (!pTAS2555->mpFirmware->mpConfigurations)) {
1114                 dev_err(pTAS2555->dev, "Firmware not loaded\n");
1115                 return -1;
1116         }
1117         
1118         if (nProgram >= pTAS2555->mpFirmware->mnPrograms) {
1119                 dev_err(pTAS2555->dev, "TAS2555: Program %d doesn't exist\n",
1120                         nConfiguration);
1121                 return -1;
1122         }
1123         
1124         nConfiguration = 0;
1125         nSampleRate = pTAS2555->mnCurrentSampleRate;
1126         
1127         while (!bFound 
1128                 && (nConfiguration < pTAS2555->mpFirmware->mnConfigurations)) {
1129                 if (pTAS2555->mpFirmware->mpConfigurations[nConfiguration].mnProgram 
1130                         == nProgram){
1131                         if(nSampleRate == 0){
1132                                 bFound = true;
1133                                 dev_info(pTAS2555->dev, "find default configuration %d\n", nConfiguration);
1134                         }else if(nSampleRate 
1135                                 == pTAS2555->mpFirmware->mpConfigurations[nConfiguration].mnSamplingRate){
1136                                 bFound = true;
1137                                 dev_info(pTAS2555->dev, "find matching configuration %d\n", nConfiguration);
1138                         }else{
1139                                 nConfiguration++;
1140                         }
1141                 }else{
1142                         nConfiguration++;
1143                 }
1144         }
1145         
1146         if (!bFound) {
1147                 dev_err(pTAS2555->dev, 
1148                         "Program %d, no valid configuration found for sample rate %d, ignore\n",
1149                         nProgram, nSampleRate);
1150                 return -1;
1151         }
1152         
1153         pTAS2555->mnCurrentProgram = nProgram;
1154         if(pTAS2555->mbPowerUp)
1155                 tas2555_dev_load_data(pTAS2555, p_tas2555_mute_DSP_down_data);
1156         pTAS2555->write(pTAS2555, channel_both, TAS2555_SW_RESET_REG, 0x01);
1157         udelay(1000);
1158         
1159         dev_info(pTAS2555->dev, "load program %d\n", nProgram);
1160         tas2555_load_data(pTAS2555,
1161                 &(pTAS2555->mpFirmware->mpPrograms[nProgram].mData),
1162                 TAS2555_BLOCK_MAIN_ALL);
1163         tas2555_load_data(pTAS2555,
1164                 &(pTAS2555->mpFirmware->mpPrograms[nProgram].mData),
1165                 TAS2555_BLOCK_MAIN_DEV_A);
1166         tas2555_load_data(pTAS2555,
1167                 &(pTAS2555->mpFirmware->mpPrograms[nProgram].mData),
1168                 TAS2555_BLOCK_MAIN_DEV_B);
1170         pTAS2555->mnCurrentConfiguration = nConfiguration;
1172         pConfiguration =
1173                 &(pTAS2555->mpFirmware->mpConfigurations[nConfiguration]);
1174         pPLL = &(pTAS2555->mpFirmware->mpPLLs[pConfiguration->mnPLL]);
1175         dev_dbg(pTAS2555->dev,
1176                 "TAS2555 load PLL: %s block for Configuration %s\n",
1177                 pPLL->mpName, pConfiguration->mpName);
1178         
1179         tas2555_load_block(pTAS2555, &(pPLL->mBlock));
1180         pTAS2555->mnCurrentSampleRate = pConfiguration->mnSamplingRate;
1181         dev_dbg(pTAS2555->dev,
1182                 "load configuration %s conefficient pre block\n",
1183                 pConfiguration->mpName);                
1184         tas2555_load_data(pTAS2555, &(pConfiguration->mData), TAS2555_BLOCK_PRE_DEV_A);
1185         tas2555_load_data(pTAS2555, &(pConfiguration->mData), TAS2555_BLOCK_PRE_DEV_B);
1187         nResult = pTAS2555->read(pTAS2555, channel_left, TAS2555_CRC_CHECKSUM_REG, &Value);
1188         dev_info(pTAS2555->dev, "Left uCDSP Checksum: 0x%02x\n", Value);
1189         nResult = pTAS2555->read(pTAS2555, channel_right, TAS2555_CRC_CHECKSUM_REG, &Value);
1190         dev_info(pTAS2555->dev, "Right uCDSP Checksum: 0x%02x\n", Value);       
1191         nResult = pTAS2555->read(pTAS2555, channel_left, TAS2555_PLL_CLKIN_REG, &Value);
1192         dev_info(pTAS2555->dev, "TAS2555 PLL_CLKIN = 0x%02X\n", Value);
1193         p_tas2555_startup_data[TAS2555_STARTUP_DATA_PLL_CLKIN_INDEX] = Value;
1195         if (pTAS2555->mbPowerUp){
1196                 dev_dbg(pTAS2555->dev, "device powered up, load startup\n");
1197                 tas2555_dev_load_data(pTAS2555, p_tas2555_startup_data);
1198                 dev_dbg(pTAS2555->dev, 
1199                         "device powered up, load configuration %s post power block\n",
1200                         pConfiguration->mpName);
1201                 tas2555_load_data(pTAS2555, &(pConfiguration->mData),
1202                         TAS2555_BLOCK_POST_POWER_UP);
1203         }
1204         
1205         tas2555_load_configuration(pTAS2555, nConfiguration, true);
1206         if (pTAS2555->mbPowerUp){
1207                 dev_dbg(pTAS2555->dev,
1208                         "device powered up, load unmute\n");
1209                 tas2555_dev_load_data(pTAS2555, p_tas2555_unmute_data);
1210         }
1212         return 0;
1215 int tas2555_set_calibration(struct tas2555_priv *pTAS2555,
1216         int nCalibration)
1218         if ((!pTAS2555->mpFirmware->mpPrograms) || (!pTAS2555->mpFirmware->mpConfigurations)) 
1219         {
1220                 dev_err(pTAS2555->dev, "Firmware not loaded\n\r");
1221                 return -1;
1222         }
1224         if (nCalibration == 0x00FF)
1225         {
1226                 dev_info(pTAS2555->dev, "load new calibration file %s\n", TAS2555_CAL_NAME);    
1227                 tas2555_load_calibration(pTAS2555, TAS2555_CAL_NAME);
1228                 nCalibration = 0;
1229         }
1231         if (nCalibration >= pTAS2555->mpFirmware->mnCalibrations) {
1232                 dev_err(pTAS2555->dev,
1233                         "Calibration %d doesn't exist\n", nCalibration);
1234                 return -1;
1235         }
1237         pTAS2555->mnCurrentCalibration = nCalibration;
1238         if(pTAS2555->mbPowerUp){
1239                 tas2555_load_block(pTAS2555, 
1240                         &(pTAS2555->mpCalFirmware->mpCalibrations[pTAS2555->mnCurrentCalibration].mBlock));
1241                 pTAS2555->mbLoadCalibrationPostPowerUp = false; 
1242         }else{
1243                 pTAS2555->mbLoadCalibrationPostPowerUp = true; 
1244         }
1246         return 0;
1249 int tas2555_parse_dt(struct device *dev,
1250                         struct tas2555_priv *pTAS2555)
1252         struct device_node *np = dev->of_node;
1253         int rc= 0, ret = 0;
1254         unsigned int value;
1255         
1256         pTAS2555->mnResetGPIO = of_get_named_gpio(np, "ti,cdc-reset-gpio", 0);
1257         if (pTAS2555->mnResetGPIO < 0) {
1258                 dev_err(pTAS2555->dev, "Looking up %s property in node %s failed %d\n",
1259                         "ti,cdc-reset-gpio", np->full_name,
1260                         pTAS2555->mnResetGPIO);
1261                 ret = -1;
1262         }else{
1263                 dev_dbg(pTAS2555->dev, "ti,cdc-reset-gpio=%d\n", pTAS2555->mnResetGPIO);
1264         }
1265         
1266         if(ret >=0){
1267                 rc = of_property_read_u32(np, "ti,left-channel", &value);
1268                 if (rc) {
1269                         dev_err(pTAS2555->dev, "Looking up %s property in node %s failed %d\n",
1270                                 "ti,left-channel", np->full_name, rc);
1271                         ret = -2;
1272                 }else{
1273                         pTAS2555->mnLAddr = value;
1274                         dev_dbg(pTAS2555->dev, "ti,left-channel=0x%x\n", pTAS2555->mnLAddr);
1275                 }
1276         }
1277         
1278         if(ret >=0){
1279                 rc = of_property_read_u32(np, "ti,right-channel", &value);
1280                 if (rc) {
1281                         dev_err(pTAS2555->dev, "Looking up %s property in node %s failed %d\n",
1282                                 "ti,right-channel", np->full_name, rc);
1283                         ret = -3;
1284                 }else{
1285                         pTAS2555->mnRAddr = value;
1286                         dev_dbg(pTAS2555->dev, "ti,right-channel=0x%x", pTAS2555->mnRAddr);
1287                 }
1288         }
1289         
1290         return ret;
1293 MODULE_AUTHOR("Texas Instruments Inc.");
1294 MODULE_DESCRIPTION("TAS2555 common functions for Android Linux");
1295 MODULE_LICENSE("GPLv2");