]> Gitweb @ Texas Instruments - Open Source Git Repositories - git.TI.com/gitweb - tas2557sw-android/tas2557-android-driver.git/blob - tas2557-core.c
add mix command for set channel
[tas2557sw-android/tas2557-android-driver.git] / tas2557-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 **     tas2557-core.c
19 **
20 ** Description:
21 **     TAS2557 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 "tas2557.h"
45 #include "tas2557-core.h"
47 #define TAS2557_CAL_NAME    "/data/tas2557_cal.bin"
49 //set default PLL CLKIN to GPI2 (MCLK) = 0x00
50 #define TAS2557_DEFAULT_PLL_CLKIN 0x00
52 static void tas2557_load_calibration(struct tas2557_priv *pTAS2557,
53         char *pFileName);
54 static void tas2557_load_data(struct tas2557_priv *pTAS2557, TData * pData,
55         unsigned int nType);
56 static void tas2557_load_block(struct tas2557_priv *pTAS2557, TBlock * pBlock);
57 static void tas2557_load_configuration(struct tas2557_priv *pTAS2557,
58         unsigned int nConfiguration, bool bLoadSame);
59         
60 #define TAS2557_UDELAY 0xFFFFFFFE
61 #define TAS2557_MDELAY 0xFFFFFFFD
63 #define FW_ERR_HEADER -1
64 #define FW_ERR_SIZE -2
66 #define TAS2557_BLOCK_PLL                               0x00
67 #define TAS2557_BLOCK_PGM_ALL                   0x0d
68 #define TAS2557_BLOCK_PGM_DEV_A                 0x01
69 #define TAS2557_BLOCK_PGM_DEV_B                 0x08
70 #define TAS2557_BLOCK_CFG_COEFF_DEV_A   0x03
71 #define TAS2557_BLOCK_CFG_COEFF_DEV_B   0x0a
72 #define TAS2557_BLOCK_CFG_PRE_DEV_A             0x04
73 #define TAS2557_BLOCK_CFG_PRE_DEV_B             0x0b
74 #define TAS2557_BLOCK_CFG_POST                  0x05
75 #define TAS2557_BLOCK_CFG_POST_POWER    0x06
76 #define TAS2557_BLOCK_CFG_CAL_A                 0x10
77 #define TAS2557_BLOCK_CFG_CAL_B                 0x20
79 static unsigned int p_tas2557_SA_chl_left_data[] =
80 {
81         TAS2557_SA_CHL_CTRL_REG, 0x08, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
82         0xFFFFFFFF, 0xFFFFFFFF
83 };
85 static unsigned int p_tas2557_SA_chl_right_data[] =
86 {
87         TAS2557_SA_CHL_CTRL_REG, 0x08, 0x00, 0x00, 0x00, 0x00, 0x40, 0x00, 0x00, 0x00,
88         0xFFFFFFFF, 0xFFFFFFFF
89 };
91 static unsigned int p_tas2557_SA_swap_data[] =
92 {
93         TAS2557_SA_COEFF_SWAP_REG, 0x04, 0x00, 0x00, 0x00, 0x01, // when DSP powered on, swap needed to update coefficient memory
94         0xFFFFFFFF, 0xFFFFFFFF
95 };
97 static unsigned int p_tas2557_dboost_data[] = {
98         TAS2557_DBOOST_CTL_REG, 0x08,   //enable, 0x0c=disable
99         TAS2557_DBOOST_CFG_REG, 0x03,   //threshold -18dB +hysteresis 4dB
100         0xFFFFFFFF, 0xFFFFFFFF
101 };
103 //This is only needed for PG1.0
104 static unsigned int p_tas2557_vpred_comp_data[] =
106 //Reverse attenuation compensation for Vpred 0.5dB
107         TAS2557_VPRED_COMP_REG, 0x04, 0x43, 0xca, 0xd0, 0x22,
108         0xFFFFFFFF, 0xFFFFFFFF
109 };
111 //This is only needed for PG1.0.
112 static unsigned int p_tas2557_thermal_foldback_data[] = {
113         TAS2557_THERMAL_FOLDBACK_REG, 0x04, 0x48, 0x00, 0x00, 0x00,     //disable
114         0xFFFFFFFF, 0xFFFFFFFF
115 };
117 static unsigned int p_tas2557_boost_8Ohm_data[] =
119         TAS2557_BOOST_HEADROOM, 0x04, 0x04, 0xcc, 0xcc, 0xcc,   // boost headroom 600mv
120     TAS2557_BOOSTOFF_EFFICIENCY, 0x04, 0x67, 0xae,0x14,0x7a, //boost off efficiency 0.81
121         0xFFFFFFFF, 0xFFFFFFFF
122 };
124 static unsigned int p_tas2557_boost_6Ohm_data[] =
126         TAS2557_BOOST_HEADROOM, 0x04, 0x06, 0x66, 0x66, 0x66, // boost headroom 800mv
127         0xFFFFFFFF, 0xFFFFFFFF
128 };
130 static unsigned int p_tas2557_boost_4Ohm_data[] =
132         TAS2557_BOOST_HEADROOM, 0x04, 0x06, 0x66, 0x66, 0x66, // boost headroom 800mv
133         TAS2557_BOOSTON_EFFICIENCY, 0x04, 0x73, 0x33, 0x33, 0x33,
134         TAS2557_BOOSTOFF_EFFICIENCY, 0x04, 0x60, 0x00,0x00,0x00, //boost off efficiency 0.75
135         0xFFFFFFFF, 0xFFFFFFFF
136 };
138 /* This is only required for PG2.0*/
139 static unsigned int p_tas2557_isense_threshold_data[] =
141         TAS2557_ISENSE_THRESHOLD, 0x04, 0, 0, 0, 0,     // Make Isense threshold zero
142         0xFFFFFFFF, 0xFFFFFFFF
143 };
145 #define TAS2557_STARTUP_DATA_PLL_CLKIN_INDEX 3
146 static unsigned int p_tas2557_startup_data[] = {
147         TAS2557_CLK_ERR_CTRL, 0x03,     //enable clock error detection
148         TAS2557_PLL_CLKIN_REG, TAS2557_DEFAULT_PLL_CLKIN,
149         TAS2557_POWER_CTRL2_REG, 0xA0,  //Class-D, Boost power up
150         TAS2557_POWER_CTRL2_REG, 0xA3,  //Class-D, Boost, IV sense power up
151         TAS2557_POWER_CTRL1_REG, 0xF8,  //PLL, DSP, clock dividers power up
152         TAS2557_UDELAY, 2000,           //delay
153         0xFFFFFFFF, 0xFFFFFFFF
154 };
156 static unsigned int p_tas2557_unmute_data[] = {
157         TAS2557_MUTE_REG, 0x00,         //unmute
158         TAS2557_SOFT_MUTE_REG, 0x00,    //soft unmute
159         0xFFFFFFFF, 0xFFFFFFFF
160 };
162 static unsigned int p_tas2557_shutdown_data[] = {
163         TAS2557_SOFT_MUTE_REG, 0x01,    //soft mute
164         TAS2557_UDELAY, 10000,          //delay 10ms
165         TAS2557_MUTE_REG, 0x03,         //mute
166         TAS2557_POWER_CTRL1_REG, 0x60,  //DSP power down
167         TAS2557_UDELAY, 2000,           //delay 2ms
168         TAS2557_POWER_CTRL2_REG, 0x00,  //Class-D, Boost power down
169         TAS2557_POWER_CTRL1_REG, 0x00,  //all power down
170         0xFFFFFFFF, 0xFFFFFFFF
171 };
173 #if 0
174 static unsigned int p_tas2557_shutdown_clk_err[] = {
175         TAS2557_CLK_ERR_CTRL, 0x09,     //enable clock error detection on PLL
176         0xFFFFFFFF, 0xFFFFFFFF
177 };
178 #endif
180 static unsigned int p_tas2557_mute_DSP_down_data[] = {
181         TAS2557_MUTE_REG, 0x03,         //mute
182         TAS2557_POWER_CTRL1_REG, 0x60,  //DSP power down
183         TAS2557_UDELAY, 0xFF,           //delay
184         0xFFFFFFFF, 0xFFFFFFFF
185 };
187 static int tas2557_dev_load_data(struct tas2557_priv *pTAS2557,
188         unsigned int *pData)
190         int ret = 0;
191         unsigned int n = 0;
192         unsigned int nRegister;
193         unsigned int nData;
195         do {
196                 nRegister = pData[n * 2];
197                 nData = pData[n * 2 + 1];
198                 if (nRegister == TAS2557_UDELAY)
199                         udelay(nData);
200                 else if (nRegister != 0xFFFFFFFF){
201                         ret = pTAS2557->write(pTAS2557, nRegister, nData);
202                         if(ret < 0) {
203                                 dev_err(pTAS2557->dev, "Reg Write err %d\n", ret);
204                                 break;
205                         }
206                 }
207                 n++;
208         } while (nRegister != 0xFFFFFFFF);
209         
210         return ret;
213 static int tas2557_dev_load_blk_data(struct tas2557_priv *pTAS2557,
214                                   unsigned int *pData) {
215         unsigned int nRegister;
216         unsigned int *nData;
217         unsigned char Buf[128];
218         unsigned int nLength = 0;
219         unsigned int i =0;
220         unsigned int nSize = 0;
221         int ret = 0;
223         do{
224                 nRegister = pData[nLength];
225                 nSize = pData[nLength + 1];
226                 nData = &pData[nLength + 2];
227                 if (nRegister == TAS2557_MDELAY){
228                         mdelay(nData[0]);
229                 }
230                 else{
231                         if (nRegister != 0xFFFFFFFF){
232                                 if(nSize > 128){ 
233                                         dev_err(pTAS2557->dev, 
234                                                 "%s, Line=%d, invalid size, maximum is 128 bytes!\n", 
235                                                 __FUNCTION__, __LINE__);
236                                         break;
237                                 }
238                                 
239                                 if(nSize > 1){
240                                         for(i = 0; i < nSize; i++) Buf[i] = (unsigned char)nData[i];
241                                         ret = pTAS2557->bulk_write(pTAS2557, nRegister, Buf, nSize);
242                                 }else if(nSize == 1){
243                                         ret = pTAS2557->write(pTAS2557,nRegister, nData[0]);
244                                 }else{
245                                         dev_err(pTAS2557->dev, 
246                                                 "%s, Line=%d,invalid size, minimum is 1 bytes!\n", 
247                                                 __FUNCTION__, __LINE__);
248                                 }
249                                 
250                                 if(ret < 0) break;
251                         }
252                 }
253                 nLength = nLength + 2 + pData[nLength+1] ;
254         } while (nRegister != 0xFFFFFFFF);
255         
256         return ret;
259 int tas2557_setLoad(struct tas2557_priv *pTAS2557, int load)
261         int ret = 0;
263         ret = pTAS2557->write(pTAS2557, 
264                         TAS2557_SNS_CTRL_REG, (load&0x03)<<1);
265         if(ret<0)
266                 goto err;
267         
268         switch(load)
269         {
270                 case 0: //8Ohm
271                 ret = tas2557_dev_load_blk_data(pTAS2557, 
272                         p_tas2557_boost_8Ohm_data);
273                 break;
274                 
275                 case 1: //6Ohm
276                 ret = tas2557_dev_load_blk_data(pTAS2557, 
277                         p_tas2557_boost_6Ohm_data);
278                 break;
279                 
280                 case 2: //4Ohm
281                 ret = tas2557_dev_load_blk_data(pTAS2557, 
282                         p_tas2557_boost_4Ohm_data);
283                 break;
284         }
285         
286 err:    
287         
288         return ret;
291 int tas2557_setChannel(struct tas2557_priv *pTAS2557, int channel)
293         int ret = -1;
294         
295         if(channel == LEFT_CHANNEL){
296                 ret = pTAS2557->update_bits(pTAS2557, TAS2557_ASI_CTRL_REG, 0x06, 0x00);        //ROM mode
297                 ret = tas2557_dev_load_blk_data(pTAS2557, p_tas2557_SA_chl_left_data);
298         }else if(channel == RIGHT_CHANNEL){
299                 ret = pTAS2557->update_bits(pTAS2557, TAS2557_ASI_CTRL_REG, 0x06, 0x02);        //ROM mode
300                 ret = tas2557_dev_load_blk_data(pTAS2557, p_tas2557_SA_chl_right_data);
301         }
302                 
303         if(pTAS2557->mbPowerUp && (ret >= 0)){
304                 ret = tas2557_dev_load_blk_data(pTAS2557, p_tas2557_SA_swap_data);
305         }
306         
307         return ret;
310 int tas2557_load_platdata(struct tas2557_priv *pTAS2557)
312         int ret = 0;
313         
314         ret = tas2557_setLoad(pTAS2557, pTAS2557->mnLoad);
315         ret = tas2557_setChannel(pTAS2557, pTAS2557->mnDevChl);
316                 
317         return ret;
320 int tas2557_load_default(struct tas2557_priv *pTAS2557)
322         int ret = 0;
323         
324         ret = tas2557_dev_load_blk_data(pTAS2557, p_tas2557_dboost_data);
325         if(ret < 0) goto err;
326         
327         /* This is not required for PG1.0 and 2.1, only PG2.0*/
328         if(pTAS2557->mnPGID 
329                 == TAS2557_PG_VERSION_2P0)
330                 ret = tas2557_dev_load_blk_data(pTAS2557, 
331                                 p_tas2557_isense_threshold_data);
332                                 
333         if(pTAS2557->mnPGID 
334                 == TAS2557_PG_VERSION_1P0){
335                 tas2557_dev_load_blk_data(pTAS2557, p_tas2557_vpred_comp_data);
336                 tas2557_dev_load_blk_data(pTAS2557, p_tas2557_thermal_foldback_data);
337         }
338         
339         tas2557_load_platdata(pTAS2557);
340         
341 err:
342         
343         return ret;
346 void tas2557_enable(struct tas2557_priv *pTAS2557, bool bEnable)
348         dev_dbg(pTAS2557->dev, "Enable: %d\n", bEnable);
349         if (bEnable) {
350                 if (!pTAS2557->mbPowerUp) {
351                         dev_dbg(pTAS2557->dev, "Enable: load startup sequence\n");
352                         tas2557_dev_load_data(pTAS2557, p_tas2557_startup_data);
353                         dev_dbg(pTAS2557->dev, "Enable: load unmute sequence\n");
354                         tas2557_dev_load_data(pTAS2557, p_tas2557_unmute_data);
355                         pTAS2557->mbPowerUp = true;
356                 }
357         } else {
358                 if (pTAS2557->mbPowerUp) {
359                         dev_dbg(pTAS2557->dev, "Enable: load shutdown sequence\n");
360                         tas2557_dev_load_data(pTAS2557, p_tas2557_shutdown_data);
361                         //tas2557_dev_load_data(pTAS2557, p_tas2557_shutdown_clk_err);
362                         pTAS2557->mbPowerUp = false;
363                 }
364         }
367 int tas2557_set_sampling_rate(struct tas2557_priv *pTAS2557, unsigned int nSamplingRate)
369         TConfiguration *pConfiguration;
370         unsigned int nConfiguration;
372         dev_dbg(pTAS2557->dev, "tas2557_setup_clocks: nSamplingRate = %d [Hz]\n",
373                 nSamplingRate);
375         if ((!pTAS2557->mpFirmware->mpPrograms) ||
376                 (!pTAS2557->mpFirmware->mpConfigurations)) {
377                 dev_err(pTAS2557->dev, "Firmware not loaded\n");
378                 return -EINVAL;
379         }
381         pConfiguration = &(pTAS2557->mpFirmware->mpConfigurations[pTAS2557->mnCurrentConfiguration]);
382         if (pConfiguration->mnSamplingRate == nSamplingRate) {
383                 dev_info(pTAS2557->dev, "Sampling rate for current configuration matches: %d\n",
384                         nSamplingRate);
385                 return 0;
386         }
388         for (nConfiguration = 0;
389                 nConfiguration < pTAS2557->mpFirmware->mnConfigurations;
390                 nConfiguration++) {
391                 pConfiguration =
392                         &(pTAS2557->mpFirmware->mpConfigurations[nConfiguration]);
393                 if ((pConfiguration->mnSamplingRate == nSamplingRate)
394                         &&(pConfiguration->mnProgram == pTAS2557->mnCurrentProgram)){
395                         dev_info(pTAS2557->dev,
396                                 "Found configuration: %s, with compatible sampling rate %d\n",
397                                 pConfiguration->mpName, nSamplingRate);
398                         tas2557_load_configuration(pTAS2557, nConfiguration, false);
399                         return 0;
400                 }
401         }
403         dev_err(pTAS2557->dev, "Cannot find a configuration that supports sampling rate: %d\n",
404                 nSamplingRate);
406         return -EINVAL;
409 static void fw_print_header(struct tas2557_priv *pTAS2557, TFirmware * pFirmware)
411         dev_info(pTAS2557->dev, "FW Size        = %d", pFirmware->mnFWSize);
412         dev_info(pTAS2557->dev, "Checksum       = 0x%04X", pFirmware->mnChecksum);
413         dev_info(pTAS2557->dev, "PPC Version    = 0x%04X", pFirmware->mnPPCVersion);
414         dev_info(pTAS2557->dev, "FW  Version    = 0x%04X", pFirmware->mnFWVersion);
415         dev_info(pTAS2557->dev, "Driver Version = 0x%04X", pFirmware->mnDriverVersion);
416         dev_info(pTAS2557->dev, "Timestamp      = %d", pFirmware->mnTimeStamp);
417         dev_info(pTAS2557->dev, "DDC Name       = %s", pFirmware->mpDDCName);
418         dev_info(pTAS2557->dev, "Description    = %s", pFirmware->mpDescription);
421 inline unsigned int fw_convert_number(unsigned char *pData)
423         return pData[3] + (pData[2] << 8) + (pData[1] << 16) + (pData[0] << 24);
426 static int fw_parse_header(struct tas2557_priv *pTAS2557, 
427         TFirmware * pFirmware, unsigned char *pData,
428         unsigned int nSize)
430         unsigned char *pDataStart = pData;
431         unsigned int n;
432         unsigned char pMagicNumber[] = { 0x35, 0x35, 0x35, 0x32 };
433         if (nSize < 102) {
434                 dev_err(pTAS2557->dev, "Firmware: Header too short");
435                 return -1;
436         }
438         if (memcmp(pData, pMagicNumber, 4)) {
439                 dev_err(pTAS2557->dev, "Firmware: Magic number doesn't match");
440                 return -1;
441         }
443         pData += 4;
445         pFirmware->mnFWSize = fw_convert_number(pData);
446         pData += 4;
448         pFirmware->mnChecksum = fw_convert_number(pData);
449         pData += 4;
451         pFirmware->mnPPCVersion = fw_convert_number(pData);
452         pData += 4;
454         pFirmware->mnFWVersion = fw_convert_number(pData);
455         pData += 4;
457         pFirmware->mnDriverVersion = fw_convert_number(pData);
458         pData += 4;             
459                         
460         pFirmware->mnTimeStamp = fw_convert_number(pData);
461         pData += 4;
463         memcpy(pFirmware->mpDDCName, pData, 64);
464         pData += 64;
466         n = strlen(pData);
467         pFirmware->mpDescription = kmemdup(pData, n + 1, GFP_KERNEL);
468         pData += n + 1;
470         if ((pData - pDataStart) >= nSize) {
471                 dev_err(pTAS2557->dev, "Firmware: Header too short after DDC description");
472                 return -1;
473         }
475         pFirmware->mnDeviceFamily = fw_convert_number(pData);
476         pData += 4;
478         if(pFirmware->mnDeviceFamily != 0){
479                 dev_err(pTAS2557->dev, 
480                         "deviceFamily %d, not TAS device", pFirmware->mnDeviceFamily);
481                 return -1;
482         }
483         
484         pFirmware->mnDevice = fw_convert_number(pData);
485         pData += 4;
487         if(pFirmware->mnDevice != 2){
488                 dev_err(pTAS2557->dev, 
489                         "device %d, not TAS2557", pFirmware->mnDevice);
490                 return -1;
491         }
492         
493         fw_print_header(pTAS2557, pFirmware);
495         return pData - pDataStart;
498 static int fw_parse_block_data(TBlock * pBlock, unsigned char *pData)
500         unsigned char *pDataStart = pData;
501         unsigned int n;
503         pBlock->mnType = fw_convert_number(pData);
504         pData += 4;
506         pBlock->mnCommands = fw_convert_number(pData);
507         pData += 4;
509         n = pBlock->mnCommands * 4;
510         pBlock->mpData = kmemdup(pData, n, GFP_KERNEL);
511         pData += n;
513         return pData - pDataStart;
516 static int fw_parse_data(TData * pImageData, unsigned char *pData)
518         unsigned char *pDataStart = pData;
519         unsigned int nBlock;
520         unsigned int n;
522         memcpy(pImageData->mpName, pData, 64);
523         pData += 64;
525         n = strlen(pData);
526         pImageData->mpDescription = kmemdup(pData, n + 1, GFP_KERNEL);
527         pData += n + 1;
529         pImageData->mnBlocks = (pData[0] << 8) + pData[1];
530         pData += 2;
532         pImageData->mpBlocks =
533                 kmalloc(sizeof(TBlock) * pImageData->mnBlocks, GFP_KERNEL);
535         for (nBlock = 0; nBlock < pImageData->mnBlocks; nBlock++) {
536                 n = fw_parse_block_data(&(pImageData->mpBlocks[nBlock]), pData);
537                 pData += n;
538         }
540         return pData - pDataStart;
543 static int fw_parse_pll_data(TFirmware * pFirmware, unsigned char *pData)
545         unsigned char *pDataStart = pData;
546         unsigned int n;
547         unsigned int nPLL;
548         TPLL *pPLL;
550         pFirmware->mnPLLs = (pData[0] << 8) + pData[1];
551         pData += 2;
553         pFirmware->mpPLLs = kmalloc(sizeof(TPLL) * pFirmware->mnPLLs, GFP_KERNEL);
554         for (nPLL = 0; nPLL < pFirmware->mnPLLs; nPLL++) {
555                 pPLL = &(pFirmware->mpPLLs[nPLL]);
557                 memcpy(pPLL->mpName, pData, 64);
558                 pData += 64;
560                 n = strlen(pData);
561                 pPLL->mpDescription = kmemdup(pData, n + 1, GFP_KERNEL);
562                 pData += n + 1;
564                 n = fw_parse_block_data(&(pPLL->mBlock), pData);
565                 pData += n;
566         }
568         return pData - pDataStart;
571 static int fw_parse_program_data(TFirmware * pFirmware, unsigned char *pData)
573         unsigned char *pDataStart = pData;
574         unsigned int n;
575         unsigned int nProgram;
576         TProgram *pProgram;
578         pFirmware->mnPrograms = (pData[0] << 8) + pData[1];
579         pData += 2;
581         pFirmware->mpPrograms =
582                 kmalloc(sizeof(TProgram) * pFirmware->mnPrograms, GFP_KERNEL);
583         for (nProgram = 0; nProgram < pFirmware->mnPrograms; nProgram++) {
584                 pProgram = &(pFirmware->mpPrograms[nProgram]);
585                 memcpy(pProgram->mpName, pData, 64);
586                 pData += 64;
588                 n = strlen(pData);
589                 pProgram->mpDescription = kmemdup(pData, n + 1, GFP_KERNEL);
590                 pData += n + 1;
592                 pProgram->mnAppMode = pData[0];
593                 pData++;
594                 
595                 pProgram->mnBoost = (pData[0] << 8) + pData[1];
596                 pData += 2;
597                 
598                 n = fw_parse_data(&(pProgram->mData), pData);
599                 pData += n;
600         }
602         return pData - pDataStart;
605 static int fw_parse_configuration_data(TFirmware * pFirmware,
606         unsigned char *pData)
608         unsigned char *pDataStart = pData;
609         unsigned int n;
610         unsigned int nConfiguration;
611         TConfiguration *pConfiguration;
613         pFirmware->mnConfigurations = (pData[0] << 8) + pData[1];
614         pData += 2;
616         pFirmware->mpConfigurations =
617                 kmalloc(sizeof(TConfiguration) * pFirmware->mnConfigurations,
618                 GFP_KERNEL);
619         for (nConfiguration = 0; nConfiguration < pFirmware->mnConfigurations;
620                 nConfiguration++) {
621                 pConfiguration = &(pFirmware->mpConfigurations[nConfiguration]);
622                 memcpy(pConfiguration->mpName, pData, 64);
623                 pData += 64;
625                 n = strlen(pData);
626                 pConfiguration->mpDescription = kmemdup(pData, n + 1, GFP_KERNEL);
627                 pData += n + 1;
629                 pConfiguration->mnProgram = pData[0];
630                 pData++;
632                 pConfiguration->mnPLL = pData[0];
633                 pData++;
635                 pConfiguration->mnSamplingRate = fw_convert_number(pData);
636                 pData += 4;
638                 n = fw_parse_data(&(pConfiguration->mData), pData);
639                 pData += n;
640         }
642         return pData - pDataStart;
645 int fw_parse_calibration_data(TFirmware * pFirmware, unsigned char *pData)
647         unsigned char *pDataStart = pData;
648         unsigned int n;
649         unsigned int nCalibration;
650         TCalibration *pCalibration;
652         pFirmware->mnCalibrations = (pData[0] << 8) + pData[1];
653         pData += 2;
655         pFirmware->mpCalibrations =
656                 kmalloc(sizeof(TCalibration) * pFirmware->mnCalibrations, GFP_KERNEL);
657         for (nCalibration = 0;
658                 nCalibration < pFirmware->mnCalibrations;
659                 nCalibration++) {
660                 pCalibration = &(pFirmware->mpCalibrations[nCalibration]);
661                 memcpy(pCalibration->mpName, pData, 64);
662                 pData += 64;
664                 n = strlen(pData);
665                 pCalibration->mpDescription = kmemdup(pData, n + 1, GFP_KERNEL);
666                 pData += n + 1;
668                 pCalibration->mnProgram = pData[0];
669                 pData++;
671                 pCalibration->mnConfiguration = pData[0];
672                 pData++;
674                 n = fw_parse_block_data(&(pCalibration->mBlock), pData);
675                 pData += n;
676         }
678         return pData - pDataStart;
681 static int fw_parse(struct tas2557_priv *pTAS2557,
682         TFirmware * pFirmware,
683         unsigned char *pData,
684         unsigned int nSize)
686         int nPosition = 0;
688         nPosition = fw_parse_header(pTAS2557, pFirmware, pData, nSize);
689         if (nPosition < 0) {
690                 dev_err(pTAS2557->dev, "Firmware: Wrong Header");
691                 return FW_ERR_HEADER;
692         }
694         if (nPosition >= nSize) {
695                 dev_err(pTAS2557->dev, "Firmware: Too short");
696                 return FW_ERR_SIZE;
697         }
699         pData += nPosition;
700         nSize -= nPosition;
701         nPosition = 0;
703         nPosition = fw_parse_pll_data(pFirmware, pData);
705         pData += nPosition;
706         nSize -= nPosition;
707         nPosition = 0;
709         nPosition = fw_parse_program_data(pFirmware, pData);
711         pData += nPosition;
712         nSize -= nPosition;
713         nPosition = 0;
715         nPosition = fw_parse_configuration_data(pFirmware, pData);
717         pData += nPosition;
718         nSize -= nPosition;
719         nPosition = 0;
721         if (nSize > 64)
722                 nPosition = fw_parse_calibration_data(pFirmware, pData);
724         return 0;
727 static void tas2557_load_block(struct tas2557_priv *pTAS2557, TBlock * pBlock)
729         unsigned int nCommand = 0;
730         unsigned char nBook;
731         unsigned char nPage;
732         unsigned char nOffset;
733         unsigned char nData;
734         unsigned int nLength;
735         unsigned char *pData = pBlock->mpData;
737         dev_dbg(pTAS2557->dev, "TAS2557 load block: Type = %d, commands = %d\n",
738                 pBlock->mnType, pBlock->mnCommands);
739         while (nCommand < pBlock->mnCommands) {
740                 pData = pBlock->mpData + nCommand * 4;
742                 nBook = pData[0];
743                 nPage = pData[1];
744                 nOffset = pData[2];
745                 nData = pData[3];
747                 nCommand++;
749                 if (nOffset <= 0x7F){
750                         pTAS2557->write(pTAS2557, TAS2557_REG(nBook, nPage, nOffset),
751                                 nData);
752                 }else if (nOffset == 0x81) {
753                         unsigned int nSleep = (nBook << 8) + nPage;
754                         msleep(nSleep);
755                 }else if (nOffset == 0x85) {
756                         pData += 4;
757                         nLength = (nBook << 8) + nPage;
758                         nBook = pData[0];
759                         nPage = pData[1];
760                         nOffset = pData[2];
761                         if (nLength > 1)
762                                 pTAS2557->bulk_write(pTAS2557, TAS2557_REG(nBook, nPage,
763                                                 nOffset), pData + 3, nLength);
764                         else
765                                 pTAS2557->write(pTAS2557, TAS2557_REG(nBook, nPage, nOffset),
766                                         pData[3]);
768                         nCommand++;
769                         if (nLength >= 2)
770                                 nCommand += ((nLength - 2) / 4) + 1;
771                 }
772         }
775 static void tas2557_load_data(struct tas2557_priv *pTAS2557, TData * pData,
776         unsigned int nType)
778         unsigned int nBlock;
779         TBlock *pBlock;
781         dev_dbg(pTAS2557->dev,
782                 "TAS2557 load data: %s, Blocks = %d, Block Type = %d\n", pData->mpName,
783                 pData->mnBlocks, nType);
785         for (nBlock = 0; nBlock < pData->mnBlocks; nBlock++) {
786                 pBlock = &(pData->mpBlocks[nBlock]);
787                 if (pBlock->mnType == nType)
788                         tas2557_load_block(pTAS2557, pBlock);
789         }
792 static void tas2557_load_configuration(struct tas2557_priv *pTAS2557,
793         unsigned int nConfiguration, bool bLoadSame)
795         TConfiguration *pCurrentConfiguration;
796         TConfiguration *pNewConfiguration;
797         TPLL *pNewPLL;
799         dev_dbg(pTAS2557->dev, "tas2557_load_configuration: %d\n", nConfiguration);
801         if ((!pTAS2557->mpFirmware->mpPrograms) ||
802                 (!pTAS2557->mpFirmware->mpConfigurations)) {
803                 dev_err(pTAS2557->dev, "Firmware not loaded\n");
804                 return;
805         }
807         if (nConfiguration >= pTAS2557->mpFirmware->mnConfigurations) {
808                 dev_err(pTAS2557->dev, "Configuration %d doesn't exist\n",
809                         nConfiguration);
810                 return;
811         }
813         if ((nConfiguration == pTAS2557->mnCurrentConfiguration) && (!bLoadSame)) {
814                 dev_info(pTAS2557->dev, "Configuration %d is already loaded\n",
815                         nConfiguration);
816                 return;
817         }
819         pCurrentConfiguration =
820                 &(pTAS2557->mpFirmware->mpConfigurations[pTAS2557->mnCurrentConfiguration]);
821         pNewConfiguration =
822                 &(pTAS2557->mpFirmware->mpConfigurations[nConfiguration]);
824         if (pNewConfiguration->mnProgram != pCurrentConfiguration->mnProgram) {
825                 dev_err(pTAS2557->dev,
826                         "Configuration %d, %s doesn't share the same program as current %d\n",
827                         nConfiguration, pNewConfiguration->mpName, pCurrentConfiguration->mnProgram);
828                 return;
829         }
831         if (pNewConfiguration->mnPLL >= pTAS2557->mpFirmware->mnPLLs) {
832                 dev_err(pTAS2557->dev,
833                         "Configuration %d, %s doesn't have a valid PLL index %d\n",
834                         nConfiguration, pNewConfiguration->mpName, pNewConfiguration->mnPLL);
835                 return;
836         }
837         
838         pNewPLL = &(pTAS2557->mpFirmware->mpPLLs[pNewConfiguration->mnPLL]);
840         if (pTAS2557->mbPowerUp) {
841                 if (pNewConfiguration->mnPLL != pCurrentConfiguration->mnPLL) {
842                         dev_dbg(pTAS2557->dev,
843                                 "TAS2557 is powered up -> mute and power down DSP before loading new configuration\n");
844                         //tas2557_dev_load_data(pTAS2557, p_tas2557_mute_DSP_down_data);
845                         tas2557_dev_load_data(pTAS2557, p_tas2557_shutdown_data);
846                         dev_dbg(pTAS2557->dev, "TAS2557: load new PLL: %s, block data\n",
847                                 pNewPLL->mpName);
848                         tas2557_load_block(pTAS2557, &(pNewPLL->mBlock));
849                         pTAS2557->mnCurrentSampleRate = pNewConfiguration->mnSamplingRate;
850                         dev_dbg(pTAS2557->dev,
851                                 "load new configuration: %s, pre block data\n",
852                                 pNewConfiguration->mpName);
853                         tas2557_load_data(pTAS2557, &(pNewConfiguration->mData),
854                                 TAS2557_BLOCK_CFG_PRE_DEV_A);
855                         dev_dbg(pTAS2557->dev,
856                                 "TAS2557: load new configuration: %s, coeff block data\n",
857                                 pNewConfiguration->mpName);
858                         tas2557_load_data(pTAS2557, &(pNewConfiguration->mData),
859                                 TAS2557_BLOCK_CFG_COEFF_DEV_A);
860                         if(pTAS2557->mnDevChl == LEFT_CHANNEL){
861                                 tas2557_dev_load_blk_data(pTAS2557, p_tas2557_SA_chl_left_data);
862                         }else if(pTAS2557->mnDevChl == RIGHT_CHANNEL){
863                                 tas2557_dev_load_blk_data(pTAS2557, p_tas2557_SA_chl_right_data);
864                         }
865                         dev_dbg(pTAS2557->dev, "TAS2557: power up TAS2557\n");
866                         tas2557_dev_load_data(pTAS2557, p_tas2557_startup_data);
867                         dev_dbg(pTAS2557->dev, "TAS2557: unmute TAS2557\n");
868                         tas2557_dev_load_data(pTAS2557, p_tas2557_unmute_data);
869                 } else {
870                         dev_dbg(pTAS2557->dev,
871                                 "TAS2557 is powered up, no change in PLL: load new configuration: %s, coeff block data\n",
872                                 pNewConfiguration->mpName);
873                         tas2557_load_data(pTAS2557, &(pNewConfiguration->mData),
874                                 TAS2557_BLOCK_CFG_COEFF_DEV_A); 
875                         if(pTAS2557->mnDevChl == LEFT_CHANNEL){
876                                 tas2557_dev_load_blk_data(pTAS2557, p_tas2557_SA_chl_left_data);
877                         }else if(pTAS2557->mnDevChl == RIGHT_CHANNEL){
878                                 tas2557_dev_load_blk_data(pTAS2557, p_tas2557_SA_chl_right_data);
879                         }       
880                 }
881                                 
882                 pTAS2557->mbLoadConfigurationPostPowerUp = false;
883         } else {
884                 dev_dbg(pTAS2557->dev,
885                         "TAS2557 was powered down\n");
886                 if (pNewConfiguration->mnPLL != pCurrentConfiguration->mnPLL) {
887                         dev_dbg(pTAS2557->dev, "TAS2557: load new PLL: %s, block data\n",
888                                 pNewPLL->mpName);
889                         tas2557_load_block(pTAS2557, &(pNewPLL->mBlock));
890                         pTAS2557->mnCurrentSampleRate = pNewConfiguration->mnSamplingRate;
891                         dev_dbg(pTAS2557->dev,
892                                 "load new configuration: %s, pre block data\n",
893                                 pNewConfiguration->mpName);
894                         tas2557_load_data(pTAS2557, &(pNewConfiguration->mData),
895                                 TAS2557_BLOCK_CFG_PRE_DEV_A);
896                 }
897                 
898                 dev_dbg(pTAS2557->dev,
899                                 "TAS2557: load new configuration: %s, coeff block data\n",
900                                 pNewConfiguration->mpName);
901                 tas2557_load_data(pTAS2557, &(pNewConfiguration->mData),
902                                 TAS2557_BLOCK_CFG_COEFF_DEV_A); 
903                                 
904                 if(pTAS2557->mnDevChl == LEFT_CHANNEL){
905                         tas2557_dev_load_blk_data(pTAS2557, p_tas2557_SA_chl_left_data);
906                 }else if(pTAS2557->mnDevChl == RIGHT_CHANNEL){
907                         tas2557_dev_load_blk_data(pTAS2557, p_tas2557_SA_chl_right_data);
908                 }               
909                 
910                 pTAS2557->mbLoadConfigurationPostPowerUp = true;
911         }
913         pTAS2557->mnCurrentConfiguration = nConfiguration;
916 int tas2557_set_config(struct tas2557_priv *pTAS2557, int config)
918         TConfiguration *pConfiguration;
919         TProgram *pProgram;
920         unsigned int nProgram = pTAS2557->mnCurrentProgram;
921         unsigned int nConfiguration = config;
923         if ((!pTAS2557->mpFirmware->mpPrograms) ||
924                 (!pTAS2557->mpFirmware->mpConfigurations)) {
925                 dev_err(pTAS2557->dev, "Firmware not loaded\n");
926                 return -1;
927         }
929         if (nConfiguration >= pTAS2557->mpFirmware->mnConfigurations) {
930                 dev_err(pTAS2557->dev, "Configuration %d doesn't exist\n",
931                         nConfiguration);
932                 return -1;
933         }
935         pConfiguration = &(pTAS2557->mpFirmware->mpConfigurations[nConfiguration]);
936         pProgram = &(pTAS2557->mpFirmware->mpPrograms[nProgram]);
938         if (nProgram != pConfiguration->mnProgram) {
939                 dev_err(pTAS2557->dev,
940                         "Configuration %d, %s with Program %d isn't compatible with existing Program %d, %s\n",
941                         nConfiguration, pConfiguration->mpName, pConfiguration->mnProgram,
942                         nProgram, pProgram->mpName);
943                 return -1;
944         }
946         tas2557_load_configuration(pTAS2557, nConfiguration, false);
948         return 0;
951 void tas2557_clear_firmware(TFirmware *pFirmware)
953         unsigned int n, nn;
954         if (!pFirmware) return;
955         if (pFirmware->mpDescription) kfree(pFirmware->mpDescription);  
957         for (n = 0; n < pFirmware->mnPLLs; n++)
958         {
959                 kfree(pFirmware->mpPLLs[n].mpDescription);
960                 kfree(pFirmware->mpPLLs[n].mBlock.mpData);
961         }
962         kfree(pFirmware->mpPLLs);
964         for (n = 0; n < pFirmware->mnPrograms; n++)
965         {
966                 kfree(pFirmware->mpPrograms[n].mpDescription);
967                 kfree(pFirmware->mpPrograms[n].mData.mpDescription);
968                 for (nn = 0; nn < pFirmware->mpPrograms[n].mData.mnBlocks; nn++)
969                         kfree(pFirmware->mpPrograms[n].mData.mpBlocks[nn].mpData);
970                 kfree(pFirmware->mpPrograms[n].mData.mpBlocks);
971         }
972         kfree(pFirmware->mpPrograms);
974         for (n = 0; n < pFirmware->mnConfigurations; n++)
975         {
976                 kfree(pFirmware->mpConfigurations[n].mpDescription);
977                 kfree(pFirmware->mpConfigurations[n].mData.mpDescription);
978                 for (nn = 0; nn < pFirmware->mpConfigurations[n].mData.mnBlocks; nn++)
979                         kfree(pFirmware->mpConfigurations[n].mData.mpBlocks[nn].mpData);
980                 kfree(pFirmware->mpConfigurations[n].mData.mpBlocks);
981         }
982         kfree(pFirmware->mpConfigurations);
984         for (n = 0; n < pFirmware->mnCalibrations; n++)
985         {
986                 kfree(pFirmware->mpCalibrations[n].mpDescription);
987                 kfree(pFirmware->mpCalibrations[n].mBlock.mpData);
988         }
989         kfree(pFirmware->mpCalibrations);
991         memset(pFirmware, 0x00, sizeof(TFirmware));
994 static void tas2557_load_calibration(struct tas2557_priv *pTAS2557,
995         char *pFileName)
997         int nResult;
998         int nFile;
999         mm_segment_t fs;
1000         unsigned char pBuffer[512];
1001         int nSize = 0;
1003         dev_dbg(pTAS2557->dev, "%s:\n", __func__);
1005         fs = get_fs();
1006         set_fs(KERNEL_DS);
1007         nFile = sys_open(pFileName, O_RDONLY, 0);
1009         dev_info(pTAS2557->dev, "TAS2557 calibration file = %s, handle = %d\n",
1010                 pFileName, nFile);
1012         if (nFile >= 0) {
1013                 nSize = sys_read(nFile, pBuffer, 512);
1014                 sys_close(nFile);
1015         } else {
1016                 dev_err(pTAS2557->dev, "TAS2557 cannot open calibration file: %s\n",
1017                         pFileName);
1018         }
1020         set_fs(fs);
1022         if (!nSize)
1023                 return;
1025         tas2557_clear_firmware(pTAS2557->mpCalFirmware);
1026                 
1027         dev_info(pTAS2557->dev, "TAS2557 calibration file size = %d\n", nSize);
1028         nResult = fw_parse(pTAS2557, pTAS2557->mpCalFirmware, pBuffer, nSize);
1030         if (nResult) {
1031                 dev_err(pTAS2557->dev, "TAS2557 calibration file is corrupt\n");
1032                 return;
1033         }
1035         dev_info(pTAS2557->dev, "TAS2557 calibration: %d calibrations\n",
1036                 pTAS2557->mpCalFirmware->mnCalibrations);
1039 void tas2557_fw_ready(const struct firmware *pFW, void *pContext)
1041         struct tas2557_priv *pTAS2557 = (struct tas2557_priv *) pContext;
1042         int nResult;
1043         unsigned int nProgram = 0;
1044         unsigned int nSampleRate = 0;
1046         dev_info(pTAS2557->dev, "%s:\n", __func__);
1048         if (unlikely(!pFW) || unlikely(!pFW->data)) {
1049                 dev_err(pTAS2557->dev, "%s firmware is not loaded.\n",
1050                         TAS2557_FW_NAME);
1051                 
1052                 nResult = tas2557_load_default(pTAS2557);
1053                 return;
1054         }
1056         if (pTAS2557->mpFirmware->mpConfigurations){
1057                 nProgram = pTAS2557->mnCurrentProgram;
1058                 nSampleRate = pTAS2557->mnCurrentSampleRate;
1059                 dev_dbg(pTAS2557->dev, "clear current firmware\n");
1060                 tas2557_clear_firmware(pTAS2557->mpFirmware);
1061         }       
1062                 
1063         nResult = fw_parse(pTAS2557, pTAS2557->mpFirmware, 
1064                 (unsigned char *) (pFW->data),  pFW->size);
1066         release_firmware(pFW);
1067         
1068         if (nResult) {
1069                 dev_err(pTAS2557->dev, "firmware is corrupt\n");
1070                 return;
1071         }
1073         if (!pTAS2557->mpFirmware->mnPrograms) {
1074                 dev_err(pTAS2557->dev, "firmware contains no programs\n");
1075                 return;
1076         }
1077         
1078         if (!pTAS2557->mpFirmware->mnConfigurations) {
1079                 dev_err(pTAS2557->dev, 
1080                         "firmware contains no configurations\n");
1081                 return;
1082         }
1083         
1084         if(nProgram >= pTAS2557->mpFirmware->mnPrograms){
1085                 dev_info(pTAS2557->dev, 
1086                         "no previous program, set to default\n");
1087                 nProgram = 0;
1088         }
1089                 
1090         pTAS2557->mnCurrentSampleRate = nSampleRate;
1092         tas2557_set_program(pTAS2557, nProgram);
1093 }       
1095 int tas2557_set_program(struct tas2557_priv *pTAS2557,
1096         unsigned int nProgram)
1098         TPLL *pPLL;
1099         TConfiguration *pConfiguration;
1100         unsigned int nConfiguration = 0;
1101         unsigned int nSampleRate = 0;
1102         unsigned int Value = 0;
1103         bool bFound = false;
1104         int nResult = -1;
1106         if ((!pTAS2557->mpFirmware->mpPrograms) ||
1107                 (!pTAS2557->mpFirmware->mpConfigurations)) {
1108                 dev_err(pTAS2557->dev, "Firmware not loaded\n");
1109                 return -1;
1110         }
1111         
1112         if (nProgram >= pTAS2557->mpFirmware->mnPrograms) {
1113                 dev_err(pTAS2557->dev, "TAS2557: Program %d doesn't exist\n",
1114                         nConfiguration);
1115                 return -1;
1116         }
1117         
1118         nConfiguration = 0;
1119         nSampleRate = pTAS2557->mnCurrentSampleRate;
1120         
1121         while (!bFound 
1122                 && (nConfiguration < pTAS2557->mpFirmware->mnConfigurations)) {
1123                 if (pTAS2557->mpFirmware->mpConfigurations[nConfiguration].mnProgram 
1124                         == nProgram){
1125                         if(nSampleRate == 0){
1126                                 bFound = true;
1127                                 dev_info(pTAS2557->dev, "find default configuration %d\n", nConfiguration);
1128                         }else if(nSampleRate 
1129                                 == pTAS2557->mpFirmware->mpConfigurations[nConfiguration].mnSamplingRate){
1130                                 bFound = true;
1131                                 dev_info(pTAS2557->dev, "find matching configuration %d\n", nConfiguration);
1132                         }else{
1133                                 nConfiguration++;
1134                         }
1135                 }else{
1136                         nConfiguration++;
1137                 }
1138         }
1139         
1140         if (!bFound) {
1141                 dev_err(pTAS2557->dev, 
1142                         "Program %d, no valid configuration found for sample rate %d, ignore\n",
1143                         nProgram, nSampleRate);
1144                 return -1;
1145         }
1146         
1147         pTAS2557->mnCurrentProgram = nProgram;
1148         
1149         nResult = tas2557_dev_load_data(pTAS2557, p_tas2557_mute_DSP_down_data);
1150         if(nResult < 0){
1151                 dev_err(pTAS2557->dev, 
1152                         "device register access error\n");
1153                 return -1;
1154         } 
1155                 
1156         pTAS2557->write(pTAS2557, TAS2557_SW_RESET_REG, 0x01);
1158         udelay(1000);
1159         pTAS2557->mnCurrentBook = 0;
1160         pTAS2557->mnCurrentPage = 0;
1161         
1162         nResult = tas2557_load_default(pTAS2557);       
1163         
1164         dev_info(pTAS2557->dev, "load program %d\n", nProgram);
1165         tas2557_load_data(pTAS2557,
1166                 &(pTAS2557->mpFirmware->mpPrograms[nProgram].mData),
1167                 TAS2557_BLOCK_PGM_DEV_A);
1169         nResult = pTAS2557->read(pTAS2557, TAS2557_CRC_CHECKSUM_REG, &Value);
1170         dev_info(pTAS2557->dev, "uCDSP Checksum: 0x%02x\n", Value);
1171         
1172         pTAS2557->mnCurrentConfiguration = nConfiguration;
1173         pConfiguration =
1174                 &(pTAS2557->mpFirmware->mpConfigurations[nConfiguration]);
1175         pPLL = &(pTAS2557->mpFirmware->mpPLLs[pConfiguration->mnPLL]);
1176         dev_dbg(pTAS2557->dev,
1177                 "TAS2557 load PLL: %s block for Configuration %s\n",
1178                 pPLL->mpName, pConfiguration->mpName);
1179         
1180         tas2557_load_block(pTAS2557, &(pPLL->mBlock));
1181         pTAS2557->mnCurrentSampleRate = pConfiguration->mnSamplingRate;
1182         dev_dbg(pTAS2557->dev,
1183                 "load configuration %s conefficient pre block\n",
1184                 pConfiguration->mpName);                
1185         tas2557_load_data(pTAS2557, &(pConfiguration->mData), TAS2557_BLOCK_CFG_PRE_DEV_A);
1187         nResult = pTAS2557->read(pTAS2557, TAS2557_PLL_CLKIN_REG, &Value);
1188         dev_info(pTAS2557->dev, "TAS2557 PLL_CLKIN = 0x%02X\n", Value);
1189         p_tas2557_startup_data[TAS2557_STARTUP_DATA_PLL_CLKIN_INDEX] = Value;
1191         tas2557_load_configuration(pTAS2557, nConfiguration, true);
1192         if (pTAS2557->mbPowerUp){
1193                 dev_dbg(pTAS2557->dev, "device powered up, load startup\n");
1194                 tas2557_dev_load_data(pTAS2557, p_tas2557_startup_data);
1195                 dev_dbg(pTAS2557->dev,
1196                         "device powered up, load unmute\n");
1197                 tas2557_dev_load_data(pTAS2557, p_tas2557_unmute_data);
1198         }
1200         return 0;
1203 int tas2557_set_calibration(struct tas2557_priv *pTAS2557,
1204         int nCalibration)
1206         if ((!pTAS2557->mpFirmware->mpPrograms) || (!pTAS2557->mpFirmware->mpConfigurations)) 
1207         {
1208                 dev_err(pTAS2557->dev, "Firmware not loaded\n\r");
1209                 return -1;
1210         }
1212         if (nCalibration == 0x00FF)
1213         {
1214                 dev_info(pTAS2557->dev, "load new calibration file %s\n", TAS2557_CAL_NAME);    
1215                 tas2557_load_calibration(pTAS2557, TAS2557_CAL_NAME);
1216                 nCalibration = 0;
1217         }
1219         if (nCalibration >= pTAS2557->mpFirmware->mnCalibrations) {
1220                 dev_err(pTAS2557->dev,
1221                         "Calibration %d doesn't exist\n", nCalibration);
1222                 return -1;
1223         }
1225         pTAS2557->mnCurrentCalibration = nCalibration;
1226         if(pTAS2557->mbPowerUp){
1227                 tas2557_load_block(pTAS2557, 
1228                         &(pTAS2557->mpCalFirmware->mpCalibrations[pTAS2557->mnCurrentCalibration].mBlock));
1229                 pTAS2557->mbLoadCalibrationPostPowerUp = false; 
1230         }else{
1231                 pTAS2557->mbLoadCalibrationPostPowerUp = true; 
1232         }
1234         return 0;
1237 int tas2557_parse_dt(struct device *dev,
1238                         struct tas2557_priv *pTAS2557)
1240         struct device_node *np = dev->of_node;
1241         int rc= 0, ret = 0;
1243         rc = of_property_read_u32(np, "ti,load", &pTAS2557->mnLoad);
1244         if (rc) {
1245                 dev_err(pTAS2557->dev, "Looking up %s property in node %s failed %d\n",
1246                         "ti,load", np->full_name, rc);
1247                 ret = -1;
1248         }else{
1249                 dev_dbg(pTAS2557->dev, "ti,load=%d", pTAS2557->mnLoad);
1250         }
1252         rc = of_property_read_u32(np, "ti,channel", &pTAS2557->mnDevChl);
1253         if (rc) {
1254                 dev_err(pTAS2557->dev, "Looking up %s property in node %s failed %d\n",
1255                         "ti,channel", np->full_name, rc);
1256                 ret = -1;
1257         }else{
1258                 dev_dbg(pTAS2557->dev, "ti,channel=%d", pTAS2557->mnDevChl);
1259         }
1260         
1261         pTAS2557->mnResetGPIO = of_get_named_gpio(np,
1262                                 "ti,cdc-reset-gpio", 0);
1263         if (pTAS2557->mnResetGPIO < 0) {
1264                 dev_err(pTAS2557->dev, "Looking up %s property in node %s failed %d\n",
1265                         "ti,cdc-reset-gpio", np->full_name,
1266                         pTAS2557->mnResetGPIO);
1267                 ret = -1;
1268         }else{
1269                 dev_dbg(pTAS2557->dev, "ti,cdc-reset-gpio=%d", pTAS2557->mnResetGPIO);
1270         }
1272         return ret;
1275 MODULE_AUTHOR("Texas Instruments Inc.");
1276 MODULE_DESCRIPTION("TAS2557 common functions for Android Linux");
1277 MODULE_LICENSE("GPLv2");