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);
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[] =
105 {
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[] =
118 {
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[] =
125 {
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[] =
131 {
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[] =
140 {
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)
189 {
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);
210 return ret;
211 }
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 }
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 }
250 if(ret < 0) break;
251 }
252 }
253 nLength = nLength + 2 + pData[nLength+1] ;
254 } while (nRegister != 0xFFFFFFFF);
256 return ret;
257 }
259 int tas2557_setLoad(struct tas2557_priv *pTAS2557, int load)
260 {
261 int ret = 0;
263 ret = pTAS2557->write(pTAS2557,
264 TAS2557_SNS_CTRL_REG, (load&0x03)<<1);
265 if(ret<0)
266 goto err;
268 switch(load)
269 {
270 case 0: //8Ohm
271 ret = tas2557_dev_load_blk_data(pTAS2557,
272 p_tas2557_boost_8Ohm_data);
273 break;
275 case 1: //6Ohm
276 ret = tas2557_dev_load_blk_data(pTAS2557,
277 p_tas2557_boost_6Ohm_data);
278 break;
280 case 2: //4Ohm
281 ret = tas2557_dev_load_blk_data(pTAS2557,
282 p_tas2557_boost_4Ohm_data);
283 break;
284 }
286 err:
288 return ret;
289 }
291 int tas2557_setChannel(struct tas2557_priv *pTAS2557, int channel)
292 {
293 int ret = -1;
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 }
303 if(pTAS2557->mbPowerUp && (ret >= 0)){
304 ret = tas2557_dev_load_blk_data(pTAS2557, p_tas2557_SA_swap_data);
305 }
307 return ret;
308 }
310 int tas2557_load_platdata(struct tas2557_priv *pTAS2557)
311 {
312 int ret = 0;
314 ret = tas2557_setLoad(pTAS2557, pTAS2557->mnLoad);
315 ret = tas2557_setChannel(pTAS2557, pTAS2557->mnDevChl);
317 return ret;
318 }
320 int tas2557_load_default(struct tas2557_priv *pTAS2557)
321 {
322 int ret = 0;
324 ret = tas2557_dev_load_blk_data(pTAS2557, p_tas2557_dboost_data);
325 if(ret < 0) goto err;
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);
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 }
339 tas2557_load_platdata(pTAS2557);
341 err:
343 return ret;
344 }
346 void tas2557_enable(struct tas2557_priv *pTAS2557, bool bEnable)
347 {
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 }
365 }
367 int tas2557_set_sampling_rate(struct tas2557_priv *pTAS2557, unsigned int nSamplingRate)
368 {
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;
407 }
409 static void fw_print_header(struct tas2557_priv *pTAS2557, TFirmware * pFirmware)
410 {
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);
419 }
421 inline unsigned int fw_convert_number(unsigned char *pData)
422 {
423 return pData[3] + (pData[2] << 8) + (pData[1] << 16) + (pData[0] << 24);
424 }
426 static int fw_parse_header(struct tas2557_priv *pTAS2557,
427 TFirmware * pFirmware, unsigned char *pData,
428 unsigned int nSize)
429 {
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;
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 }
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 }
493 fw_print_header(pTAS2557, pFirmware);
495 return pData - pDataStart;
496 }
498 static int fw_parse_block_data(TBlock * pBlock, unsigned char *pData)
499 {
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;
514 }
516 static int fw_parse_data(TData * pImageData, unsigned char *pData)
517 {
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;
541 }
543 static int fw_parse_pll_data(TFirmware * pFirmware, unsigned char *pData)
544 {
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;
569 }
571 static int fw_parse_program_data(TFirmware * pFirmware, unsigned char *pData)
572 {
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++;
595 pProgram->mnBoost = (pData[0] << 8) + pData[1];
596 pData += 2;
598 n = fw_parse_data(&(pProgram->mData), pData);
599 pData += n;
600 }
602 return pData - pDataStart;
603 }
605 static int fw_parse_configuration_data(TFirmware * pFirmware,
606 unsigned char *pData)
607 {
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;
643 }
645 int fw_parse_calibration_data(TFirmware * pFirmware, unsigned char *pData)
646 {
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;
679 }
681 static int fw_parse(struct tas2557_priv *pTAS2557,
682 TFirmware * pFirmware,
683 unsigned char *pData,
684 unsigned int nSize)
685 {
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;
725 }
727 static void tas2557_load_block(struct tas2557_priv *pTAS2557, TBlock * pBlock)
728 {
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 }
773 }
775 static void tas2557_load_data(struct tas2557_priv *pTAS2557, TData * pData,
776 unsigned int nType)
777 {
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 }
790 }
792 static void tas2557_load_configuration(struct tas2557_priv *pTAS2557,
793 unsigned int nConfiguration, bool bLoadSame)
794 {
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 }
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 }
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 }
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);
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 }
910 pTAS2557->mbLoadConfigurationPostPowerUp = true;
911 }
913 pTAS2557->mnCurrentConfiguration = nConfiguration;
914 }
916 int tas2557_set_config(struct tas2557_priv *pTAS2557, int config)
917 {
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;
949 }
951 void tas2557_clear_firmware(TFirmware *pFirmware)
952 {
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));
992 }
994 static void tas2557_load_calibration(struct tas2557_priv *pTAS2557,
995 char *pFileName)
996 {
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);
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);
1037 }
1039 void tas2557_fw_ready(const struct firmware *pFW, void *pContext)
1040 {
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);
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 }
1063 nResult = fw_parse(pTAS2557, pTAS2557->mpFirmware,
1064 (unsigned char *) (pFW->data), pFW->size);
1066 release_firmware(pFW);
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 }
1078 if (!pTAS2557->mpFirmware->mnConfigurations) {
1079 dev_err(pTAS2557->dev,
1080 "firmware contains no configurations\n");
1081 return;
1082 }
1084 if(nProgram >= pTAS2557->mpFirmware->mnPrograms){
1085 dev_info(pTAS2557->dev,
1086 "no previous program, set to default\n");
1087 nProgram = 0;
1088 }
1090 pTAS2557->mnCurrentSampleRate = nSampleRate;
1092 tas2557_set_program(pTAS2557, nProgram);
1093 }
1095 int tas2557_set_program(struct tas2557_priv *pTAS2557,
1096 unsigned int nProgram)
1097 {
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 }
1112 if (nProgram >= pTAS2557->mpFirmware->mnPrograms) {
1113 dev_err(pTAS2557->dev, "TAS2557: Program %d doesn't exist\n",
1114 nConfiguration);
1115 return -1;
1116 }
1118 nConfiguration = 0;
1119 nSampleRate = pTAS2557->mnCurrentSampleRate;
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 }
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 }
1147 pTAS2557->mnCurrentProgram = nProgram;
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 }
1156 pTAS2557->write(pTAS2557, TAS2557_SW_RESET_REG, 0x01);
1158 udelay(1000);
1159 pTAS2557->mnCurrentBook = 0;
1160 pTAS2557->mnCurrentPage = 0;
1162 nResult = tas2557_load_default(pTAS2557);
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);
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);
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;
1201 }
1203 int tas2557_set_calibration(struct tas2557_priv *pTAS2557,
1204 int nCalibration)
1205 {
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;
1235 }
1237 int tas2557_parse_dt(struct device *dev,
1238 struct tas2557_priv *pTAS2557)
1239 {
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 }
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;
1273 }
1275 MODULE_AUTHOR("Texas Instruments Inc.");
1276 MODULE_DESCRIPTION("TAS2557 common functions for Android Linux");
1277 MODULE_LICENSE("GPLv2");