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 /*
92 static unsigned int p_tas2557_SA_swap_data[] =
93 {
94 TAS2557_SA_COEFF_SWAP_REG, 0x04, 0x00, 0x00, 0x00, 0x01, // when DSP powered on, swap needed to update coefficient memory
95 0xFFFFFFFF, 0xFFFFFFFF
96 };
97 */
99 static unsigned int p_tas2557_dboost_data[] = {
100 TAS2557_DBOOST_CTL_REG, 0x08, //enable, 0x0c=disable
101 TAS2557_DBOOST_CFG_REG, 0x03, //threshold -18dB +hysteresis 4dB
102 0xFFFFFFFF, 0xFFFFFFFF
103 };
105 //This is only needed for PG1.0
106 static unsigned int p_tas2557_vpred_comp_data[] =
107 {
108 //Reverse attenuation compensation for Vpred 0.5dB
109 TAS2557_VPRED_COMP_REG, 0x04, 0x43, 0xca, 0xd0, 0x22,
110 0xFFFFFFFF, 0xFFFFFFFF
111 };
113 //This is only needed for PG1.0.
114 static unsigned int p_tas2557_thermal_foldback_data[] = {
115 TAS2557_THERMAL_FOLDBACK_REG, 0x04, 0x48, 0x00, 0x00, 0x00, //disable
116 0xFFFFFFFF, 0xFFFFFFFF
117 };
119 static unsigned int p_tas2557_boost_8Ohm_data[] =
120 {
121 TAS2557_BOOST_HEADROOM, 0x04, 0x04, 0xcc, 0xcc, 0xcc, // boost headroom 600mv
122 TAS2557_BOOSTOFF_EFFICIENCY, 0x04, 0x67, 0xae,0x14,0x7a, //boost off efficiency 0.81
123 0xFFFFFFFF, 0xFFFFFFFF
124 };
126 static unsigned int p_tas2557_boost_6Ohm_data[] =
127 {
128 TAS2557_BOOST_HEADROOM, 0x04, 0x06, 0x66, 0x66, 0x66, // boost headroom 800mv
129 0xFFFFFFFF, 0xFFFFFFFF
130 };
132 static unsigned int p_tas2557_boost_4Ohm_data[] =
133 {
134 TAS2557_BOOST_HEADROOM, 0x04, 0x06, 0x66, 0x66, 0x66, // boost headroom 800mv
135 TAS2557_BOOSTON_EFFICIENCY, 0x04, 0x73, 0x33, 0x33, 0x33,
136 TAS2557_BOOSTOFF_EFFICIENCY, 0x04, 0x60, 0x00,0x00,0x00, //boost off efficiency 0.75
137 0xFFFFFFFF, 0xFFFFFFFF
138 };
140 /* This is only required for PG2.0*/
141 static unsigned int p_tas2557_isense_threshold_data[] =
142 {
143 TAS2557_ISENSE_THRESHOLD, 0x04, 0, 0, 0, 0, // Make Isense threshold zero
144 0xFFFFFFFF, 0xFFFFFFFF
145 };
147 #define TAS2557_STARTUP_DATA_PLL_CLKIN_INDEX 3
148 static unsigned int p_tas2557_startup_data[] = {
149 TAS2557_CLK_ERR_CTRL, 0x03, //enable clock error detection
150 TAS2557_PLL_CLKIN_REG, TAS2557_DEFAULT_PLL_CLKIN,
151 TAS2557_POWER_CTRL2_REG, 0xA0, //Class-D, Boost power up
152 TAS2557_POWER_CTRL2_REG, 0xA3, //Class-D, Boost, IV sense power up
153 TAS2557_POWER_CTRL1_REG, 0xF8, //PLL, DSP, clock dividers power up
154 TAS2557_UDELAY, 2000, //delay
155 0xFFFFFFFF, 0xFFFFFFFF
156 };
158 static unsigned int p_tas2557_unmute_data[] = {
159 TAS2557_MUTE_REG, 0x00, //unmute
160 TAS2557_SOFT_MUTE_REG, 0x00, //soft unmute
161 0xFFFFFFFF, 0xFFFFFFFF
162 };
164 static unsigned int p_tas2557_shutdown_data[] = {
165 TAS2557_SOFT_MUTE_REG, 0x01, //soft mute
166 TAS2557_UDELAY, 10000, //delay 10ms
167 TAS2557_MUTE_REG, 0x03, //mute
168 TAS2557_POWER_CTRL1_REG, 0x60, //DSP power down
169 TAS2557_UDELAY, 2000, //delay 2ms
170 TAS2557_POWER_CTRL2_REG, 0x00, //Class-D, Boost power down
171 TAS2557_POWER_CTRL1_REG, 0x00, //all power down
172 0xFFFFFFFF, 0xFFFFFFFF
173 };
175 #if 0
176 static unsigned int p_tas2557_shutdown_clk_err[] = {
177 TAS2557_CLK_ERR_CTRL, 0x09, //enable clock error detection on PLL
178 0xFFFFFFFF, 0xFFFFFFFF
179 };
180 #endif
182 static unsigned int p_tas2557_mute_DSP_down_data[] = {
183 TAS2557_MUTE_REG, 0x03, //mute
184 TAS2557_POWER_CTRL1_REG, 0x60, //DSP power down
185 TAS2557_UDELAY, 0xFF, //delay
186 0xFFFFFFFF, 0xFFFFFFFF
187 };
189 static int tas2557_dev_load_data(struct tas2557_priv *pTAS2557,
190 unsigned int *pData)
191 {
192 int ret = 0;
193 unsigned int n = 0;
194 unsigned int nRegister;
195 unsigned int nData;
197 do {
198 nRegister = pData[n * 2];
199 nData = pData[n * 2 + 1];
200 if (nRegister == TAS2557_UDELAY)
201 udelay(nData);
202 else if (nRegister != 0xFFFFFFFF){
203 ret = pTAS2557->write(pTAS2557, nRegister, nData);
204 if(ret < 0) {
205 dev_err(pTAS2557->dev, "Reg Write err %d\n", ret);
206 break;
207 }
208 }
209 n++;
210 } while (nRegister != 0xFFFFFFFF);
212 return ret;
213 }
215 static int tas2557_dev_load_blk_data(struct tas2557_priv *pTAS2557,
216 unsigned int *pData) {
217 unsigned int nRegister;
218 unsigned int *nData;
219 unsigned char Buf[128];
220 unsigned int nLength = 0;
221 unsigned int i =0;
222 unsigned int nSize = 0;
223 int ret = 0;
225 do{
226 nRegister = pData[nLength];
227 nSize = pData[nLength + 1];
228 nData = &pData[nLength + 2];
229 if (nRegister == TAS2557_MDELAY){
230 mdelay(nData[0]);
231 }
232 else{
233 if (nRegister != 0xFFFFFFFF){
234 if(nSize > 128){
235 dev_err(pTAS2557->dev,
236 "%s, Line=%d, invalid size, maximum is 128 bytes!\n",
237 __FUNCTION__, __LINE__);
238 break;
239 }
241 if(nSize > 1){
242 for(i = 0; i < nSize; i++) Buf[i] = (unsigned char)nData[i];
243 ret = pTAS2557->bulk_write(pTAS2557, nRegister, Buf, nSize);
244 }else if(nSize == 1){
245 ret = pTAS2557->write(pTAS2557,nRegister, nData[0]);
246 }else{
247 dev_err(pTAS2557->dev,
248 "%s, Line=%d,invalid size, minimum is 1 bytes!\n",
249 __FUNCTION__, __LINE__);
250 }
252 if(ret < 0) break;
253 }
254 }
255 nLength = nLength + 2 + pData[nLength+1] ;
256 } while (nRegister != 0xFFFFFFFF);
258 return ret;
259 }
261 int tas2557_setLoad(struct tas2557_priv *pTAS2557, int load)
262 {
263 int ret = 0;
265 ret = pTAS2557->write(pTAS2557,
266 TAS2557_SNS_CTRL_REG, (load&0x03)<<1);
267 if(ret<0)
268 goto err;
270 switch(load)
271 {
272 case 0: //8Ohm
273 ret = tas2557_dev_load_blk_data(pTAS2557,
274 p_tas2557_boost_8Ohm_data);
275 break;
277 case 1: //6Ohm
278 ret = tas2557_dev_load_blk_data(pTAS2557,
279 p_tas2557_boost_6Ohm_data);
280 break;
282 case 2: //4Ohm
283 ret = tas2557_dev_load_blk_data(pTAS2557,
284 p_tas2557_boost_4Ohm_data);
285 break;
286 }
288 err:
290 return ret;
291 }
293 int tas2557_load_platdata(struct tas2557_priv *pTAS2557)
294 {
295 int ret = 0;
297 ret = tas2557_setLoad(pTAS2557, pTAS2557->mnLoad);
298 if(pTAS2557->mnDevChl == LEFT_CHANNEL){
299 pTAS2557->update_bits(pTAS2557, TAS2557_ASI_CTRL_REG, 0x06, 0x00); //ROM mode
300 }else if(pTAS2557->mnDevChl == LEFT_CHANNEL){
301 pTAS2557->update_bits(pTAS2557, TAS2557_ASI_CTRL_REG, 0x06, 0x02); //ROM mode
302 }
304 return ret;
305 }
307 int tas2557_load_default(struct tas2557_priv *pTAS2557)
308 {
309 int ret = 0;
311 ret = tas2557_dev_load_blk_data(pTAS2557, p_tas2557_dboost_data);
312 if(ret < 0) goto err;
314 /* This is not required for PG1.0 and 2.1, only PG2.0*/
315 if(pTAS2557->mnPGID
316 == TAS2557_PG_VERSION_2P0)
317 ret = tas2557_dev_load_blk_data(pTAS2557,
318 p_tas2557_isense_threshold_data);
320 if(pTAS2557->mnPGID
321 == TAS2557_PG_VERSION_1P0){
322 tas2557_dev_load_blk_data(pTAS2557, p_tas2557_vpred_comp_data);
323 tas2557_dev_load_blk_data(pTAS2557, p_tas2557_thermal_foldback_data);
324 }
326 tas2557_load_platdata(pTAS2557);
328 err:
330 return ret;
331 }
333 void tas2557_enable(struct tas2557_priv *pTAS2557, bool bEnable)
334 {
335 dev_dbg(pTAS2557->dev, "Enable: %d\n", bEnable);
336 if (bEnable) {
337 if (!pTAS2557->mbPowerUp) {
338 dev_dbg(pTAS2557->dev, "Enable: load startup sequence\n");
339 tas2557_dev_load_data(pTAS2557, p_tas2557_startup_data);
340 dev_dbg(pTAS2557->dev, "Enable: load unmute sequence\n");
341 tas2557_dev_load_data(pTAS2557, p_tas2557_unmute_data);
342 pTAS2557->mbPowerUp = true;
343 }
344 } else {
345 if (pTAS2557->mbPowerUp) {
346 dev_dbg(pTAS2557->dev, "Enable: load shutdown sequence\n");
347 tas2557_dev_load_data(pTAS2557, p_tas2557_shutdown_data);
348 //tas2557_dev_load_data(pTAS2557, p_tas2557_shutdown_clk_err);
349 pTAS2557->mbPowerUp = false;
350 }
351 }
352 }
354 int tas2557_set_sampling_rate(struct tas2557_priv *pTAS2557, unsigned int nSamplingRate)
355 {
356 TConfiguration *pConfiguration;
357 unsigned int nConfiguration;
359 dev_dbg(pTAS2557->dev, "tas2557_setup_clocks: nSamplingRate = %d [Hz]\n",
360 nSamplingRate);
362 if ((!pTAS2557->mpFirmware->mpPrograms) ||
363 (!pTAS2557->mpFirmware->mpConfigurations)) {
364 dev_err(pTAS2557->dev, "Firmware not loaded\n");
365 return -EINVAL;
366 }
368 pConfiguration = &(pTAS2557->mpFirmware->mpConfigurations[pTAS2557->mnCurrentConfiguration]);
369 if (pConfiguration->mnSamplingRate == nSamplingRate) {
370 dev_info(pTAS2557->dev, "Sampling rate for current configuration matches: %d\n",
371 nSamplingRate);
372 return 0;
373 }
375 for (nConfiguration = 0;
376 nConfiguration < pTAS2557->mpFirmware->mnConfigurations;
377 nConfiguration++) {
378 pConfiguration =
379 &(pTAS2557->mpFirmware->mpConfigurations[nConfiguration]);
380 if ((pConfiguration->mnSamplingRate == nSamplingRate)
381 &&(pConfiguration->mnProgram == pTAS2557->mnCurrentProgram)){
382 dev_info(pTAS2557->dev,
383 "Found configuration: %s, with compatible sampling rate %d\n",
384 pConfiguration->mpName, nSamplingRate);
385 tas2557_load_configuration(pTAS2557, nConfiguration, false);
386 return 0;
387 }
388 }
390 dev_err(pTAS2557->dev, "Cannot find a configuration that supports sampling rate: %d\n",
391 nSamplingRate);
393 return -EINVAL;
394 }
396 static void fw_print_header(struct tas2557_priv *pTAS2557, TFirmware * pFirmware)
397 {
398 dev_info(pTAS2557->dev, "FW Size = %d", pFirmware->mnFWSize);
399 dev_info(pTAS2557->dev, "Checksum = 0x%04X", pFirmware->mnChecksum);
400 dev_info(pTAS2557->dev, "PPC Version = 0x%04X", pFirmware->mnPPCVersion);
401 dev_info(pTAS2557->dev, "FW Version = 0x%04X", pFirmware->mnFWVersion);
402 dev_info(pTAS2557->dev, "Driver Version = 0x%04X", pFirmware->mnDriverVersion);
403 dev_info(pTAS2557->dev, "Timestamp = %d", pFirmware->mnTimeStamp);
404 dev_info(pTAS2557->dev, "DDC Name = %s", pFirmware->mpDDCName);
405 dev_info(pTAS2557->dev, "Description = %s", pFirmware->mpDescription);
406 }
408 inline unsigned int fw_convert_number(unsigned char *pData)
409 {
410 return pData[3] + (pData[2] << 8) + (pData[1] << 16) + (pData[0] << 24);
411 }
413 static int fw_parse_header(struct tas2557_priv *pTAS2557,
414 TFirmware * pFirmware, unsigned char *pData,
415 unsigned int nSize)
416 {
417 unsigned char *pDataStart = pData;
418 unsigned int n;
419 unsigned char pMagicNumber[] = { 0x35, 0x35, 0x35, 0x32 };
420 if (nSize < 102) {
421 dev_err(pTAS2557->dev, "Firmware: Header too short");
422 return -1;
423 }
425 if (memcmp(pData, pMagicNumber, 4)) {
426 dev_err(pTAS2557->dev, "Firmware: Magic number doesn't match");
427 return -1;
428 }
430 pData += 4;
432 pFirmware->mnFWSize = fw_convert_number(pData);
433 pData += 4;
435 pFirmware->mnChecksum = fw_convert_number(pData);
436 pData += 4;
438 pFirmware->mnPPCVersion = fw_convert_number(pData);
439 pData += 4;
441 pFirmware->mnFWVersion = fw_convert_number(pData);
442 pData += 4;
444 pFirmware->mnDriverVersion = fw_convert_number(pData);
445 pData += 4;
447 pFirmware->mnTimeStamp = fw_convert_number(pData);
448 pData += 4;
450 memcpy(pFirmware->mpDDCName, pData, 64);
451 pData += 64;
453 n = strlen(pData);
454 pFirmware->mpDescription = kmemdup(pData, n + 1, GFP_KERNEL);
455 pData += n + 1;
457 if ((pData - pDataStart) >= nSize) {
458 dev_err(pTAS2557->dev, "Firmware: Header too short after DDC description");
459 return -1;
460 }
462 pFirmware->mnDeviceFamily = fw_convert_number(pData);
463 pData += 4;
465 if(pFirmware->mnDeviceFamily != 0){
466 dev_err(pTAS2557->dev,
467 "deviceFamily %d, not TAS device", pFirmware->mnDeviceFamily);
468 return -1;
469 }
471 pFirmware->mnDevice = fw_convert_number(pData);
472 pData += 4;
474 if(pFirmware->mnDevice != 2){
475 dev_err(pTAS2557->dev,
476 "device %d, not TAS2557", pFirmware->mnDevice);
477 return -1;
478 }
480 fw_print_header(pTAS2557, pFirmware);
482 return pData - pDataStart;
483 }
485 static int fw_parse_block_data(TBlock * pBlock, unsigned char *pData)
486 {
487 unsigned char *pDataStart = pData;
488 unsigned int n;
490 pBlock->mnType = fw_convert_number(pData);
491 pData += 4;
493 pBlock->mnCommands = fw_convert_number(pData);
494 pData += 4;
496 n = pBlock->mnCommands * 4;
497 pBlock->mpData = kmemdup(pData, n, GFP_KERNEL);
498 pData += n;
500 return pData - pDataStart;
501 }
503 static int fw_parse_data(TData * pImageData, unsigned char *pData)
504 {
505 unsigned char *pDataStart = pData;
506 unsigned int nBlock;
507 unsigned int n;
509 memcpy(pImageData->mpName, pData, 64);
510 pData += 64;
512 n = strlen(pData);
513 pImageData->mpDescription = kmemdup(pData, n + 1, GFP_KERNEL);
514 pData += n + 1;
516 pImageData->mnBlocks = (pData[0] << 8) + pData[1];
517 pData += 2;
519 pImageData->mpBlocks =
520 kmalloc(sizeof(TBlock) * pImageData->mnBlocks, GFP_KERNEL);
522 for (nBlock = 0; nBlock < pImageData->mnBlocks; nBlock++) {
523 n = fw_parse_block_data(&(pImageData->mpBlocks[nBlock]), pData);
524 pData += n;
525 }
527 return pData - pDataStart;
528 }
530 static int fw_parse_pll_data(TFirmware * pFirmware, unsigned char *pData)
531 {
532 unsigned char *pDataStart = pData;
533 unsigned int n;
534 unsigned int nPLL;
535 TPLL *pPLL;
537 pFirmware->mnPLLs = (pData[0] << 8) + pData[1];
538 pData += 2;
540 pFirmware->mpPLLs = kmalloc(sizeof(TPLL) * pFirmware->mnPLLs, GFP_KERNEL);
541 for (nPLL = 0; nPLL < pFirmware->mnPLLs; nPLL++) {
542 pPLL = &(pFirmware->mpPLLs[nPLL]);
544 memcpy(pPLL->mpName, pData, 64);
545 pData += 64;
547 n = strlen(pData);
548 pPLL->mpDescription = kmemdup(pData, n + 1, GFP_KERNEL);
549 pData += n + 1;
551 n = fw_parse_block_data(&(pPLL->mBlock), pData);
552 pData += n;
553 }
555 return pData - pDataStart;
556 }
558 static int fw_parse_program_data(TFirmware * pFirmware, unsigned char *pData)
559 {
560 unsigned char *pDataStart = pData;
561 unsigned int n;
562 unsigned int nProgram;
563 TProgram *pProgram;
565 pFirmware->mnPrograms = (pData[0] << 8) + pData[1];
566 pData += 2;
568 pFirmware->mpPrograms =
569 kmalloc(sizeof(TProgram) * pFirmware->mnPrograms, GFP_KERNEL);
570 for (nProgram = 0; nProgram < pFirmware->mnPrograms; nProgram++) {
571 pProgram = &(pFirmware->mpPrograms[nProgram]);
572 memcpy(pProgram->mpName, pData, 64);
573 pData += 64;
575 n = strlen(pData);
576 pProgram->mpDescription = kmemdup(pData, n + 1, GFP_KERNEL);
577 pData += n + 1;
579 pProgram->mnAppMode = pData[0];
580 pData++;
582 pProgram->mnBoost = (pData[0] << 8) + pData[1];
583 pData += 2;
585 n = fw_parse_data(&(pProgram->mData), pData);
586 pData += n;
587 }
589 return pData - pDataStart;
590 }
592 static int fw_parse_configuration_data(TFirmware * pFirmware,
593 unsigned char *pData)
594 {
595 unsigned char *pDataStart = pData;
596 unsigned int n;
597 unsigned int nConfiguration;
598 TConfiguration *pConfiguration;
600 pFirmware->mnConfigurations = (pData[0] << 8) + pData[1];
601 pData += 2;
603 pFirmware->mpConfigurations =
604 kmalloc(sizeof(TConfiguration) * pFirmware->mnConfigurations,
605 GFP_KERNEL);
606 for (nConfiguration = 0; nConfiguration < pFirmware->mnConfigurations;
607 nConfiguration++) {
608 pConfiguration = &(pFirmware->mpConfigurations[nConfiguration]);
609 memcpy(pConfiguration->mpName, pData, 64);
610 pData += 64;
612 n = strlen(pData);
613 pConfiguration->mpDescription = kmemdup(pData, n + 1, GFP_KERNEL);
614 pData += n + 1;
616 pConfiguration->mnProgram = pData[0];
617 pData++;
619 pConfiguration->mnPLL = pData[0];
620 pData++;
622 pConfiguration->mnSamplingRate = fw_convert_number(pData);
623 pData += 4;
625 n = fw_parse_data(&(pConfiguration->mData), pData);
626 pData += n;
627 }
629 return pData - pDataStart;
630 }
632 int fw_parse_calibration_data(TFirmware * pFirmware, unsigned char *pData)
633 {
634 unsigned char *pDataStart = pData;
635 unsigned int n;
636 unsigned int nCalibration;
637 TCalibration *pCalibration;
639 pFirmware->mnCalibrations = (pData[0] << 8) + pData[1];
640 pData += 2;
642 pFirmware->mpCalibrations =
643 kmalloc(sizeof(TCalibration) * pFirmware->mnCalibrations, GFP_KERNEL);
644 for (nCalibration = 0;
645 nCalibration < pFirmware->mnCalibrations;
646 nCalibration++) {
647 pCalibration = &(pFirmware->mpCalibrations[nCalibration]);
648 memcpy(pCalibration->mpName, pData, 64);
649 pData += 64;
651 n = strlen(pData);
652 pCalibration->mpDescription = kmemdup(pData, n + 1, GFP_KERNEL);
653 pData += n + 1;
655 pCalibration->mnProgram = pData[0];
656 pData++;
658 pCalibration->mnConfiguration = pData[0];
659 pData++;
661 n = fw_parse_block_data(&(pCalibration->mBlock), pData);
662 pData += n;
663 }
665 return pData - pDataStart;
666 }
668 static int fw_parse(struct tas2557_priv *pTAS2557,
669 TFirmware * pFirmware,
670 unsigned char *pData,
671 unsigned int nSize)
672 {
673 int nPosition = 0;
675 nPosition = fw_parse_header(pTAS2557, pFirmware, pData, nSize);
676 if (nPosition < 0) {
677 dev_err(pTAS2557->dev, "Firmware: Wrong Header");
678 return FW_ERR_HEADER;
679 }
681 if (nPosition >= nSize) {
682 dev_err(pTAS2557->dev, "Firmware: Too short");
683 return FW_ERR_SIZE;
684 }
686 pData += nPosition;
687 nSize -= nPosition;
688 nPosition = 0;
690 nPosition = fw_parse_pll_data(pFirmware, pData);
692 pData += nPosition;
693 nSize -= nPosition;
694 nPosition = 0;
696 nPosition = fw_parse_program_data(pFirmware, pData);
698 pData += nPosition;
699 nSize -= nPosition;
700 nPosition = 0;
702 nPosition = fw_parse_configuration_data(pFirmware, pData);
704 pData += nPosition;
705 nSize -= nPosition;
706 nPosition = 0;
708 if (nSize > 64)
709 nPosition = fw_parse_calibration_data(pFirmware, pData);
711 return 0;
712 }
714 static void tas2557_load_block(struct tas2557_priv *pTAS2557, TBlock * pBlock)
715 {
716 unsigned int nCommand = 0;
717 unsigned char nBook;
718 unsigned char nPage;
719 unsigned char nOffset;
720 unsigned char nData;
721 unsigned int nLength;
722 unsigned char *pData = pBlock->mpData;
724 dev_dbg(pTAS2557->dev, "TAS2557 load block: Type = %d, commands = %d\n",
725 pBlock->mnType, pBlock->mnCommands);
726 while (nCommand < pBlock->mnCommands) {
727 pData = pBlock->mpData + nCommand * 4;
729 nBook = pData[0];
730 nPage = pData[1];
731 nOffset = pData[2];
732 nData = pData[3];
734 nCommand++;
736 if (nOffset <= 0x7F){
737 pTAS2557->write(pTAS2557, TAS2557_REG(nBook, nPage, nOffset),
738 nData);
739 }else if (nOffset == 0x81) {
740 unsigned int nSleep = (nBook << 8) + nPage;
741 msleep(nSleep);
742 }else if (nOffset == 0x85) {
743 pData += 4;
744 nLength = (nBook << 8) + nPage;
745 nBook = pData[0];
746 nPage = pData[1];
747 nOffset = pData[2];
748 if (nLength > 1)
749 pTAS2557->bulk_write(pTAS2557, TAS2557_REG(nBook, nPage,
750 nOffset), pData + 3, nLength);
751 else
752 pTAS2557->write(pTAS2557, TAS2557_REG(nBook, nPage, nOffset),
753 pData[3]);
755 nCommand++;
756 if (nLength >= 2)
757 nCommand += ((nLength - 2) / 4) + 1;
758 }
759 }
760 }
762 static void tas2557_load_data(struct tas2557_priv *pTAS2557, TData * pData,
763 unsigned int nType)
764 {
765 unsigned int nBlock;
766 TBlock *pBlock;
768 dev_dbg(pTAS2557->dev,
769 "TAS2557 load data: %s, Blocks = %d, Block Type = %d\n", pData->mpName,
770 pData->mnBlocks, nType);
772 for (nBlock = 0; nBlock < pData->mnBlocks; nBlock++) {
773 pBlock = &(pData->mpBlocks[nBlock]);
774 if (pBlock->mnType == nType)
775 tas2557_load_block(pTAS2557, pBlock);
776 }
777 }
779 static void tas2557_load_configuration(struct tas2557_priv *pTAS2557,
780 unsigned int nConfiguration, bool bLoadSame)
781 {
782 TConfiguration *pCurrentConfiguration;
783 TConfiguration *pNewConfiguration;
784 TPLL *pNewPLL;
786 dev_dbg(pTAS2557->dev, "tas2557_load_configuration: %d\n", nConfiguration);
788 if ((!pTAS2557->mpFirmware->mpPrograms) ||
789 (!pTAS2557->mpFirmware->mpConfigurations)) {
790 dev_err(pTAS2557->dev, "Firmware not loaded\n");
791 return;
792 }
794 if (nConfiguration >= pTAS2557->mpFirmware->mnConfigurations) {
795 dev_err(pTAS2557->dev, "Configuration %d doesn't exist\n",
796 nConfiguration);
797 return;
798 }
800 if ((nConfiguration == pTAS2557->mnCurrentConfiguration) && (!bLoadSame)) {
801 dev_info(pTAS2557->dev, "Configuration %d is already loaded\n",
802 nConfiguration);
803 return;
804 }
806 pCurrentConfiguration =
807 &(pTAS2557->mpFirmware->mpConfigurations[pTAS2557->mnCurrentConfiguration]);
808 pNewConfiguration =
809 &(pTAS2557->mpFirmware->mpConfigurations[nConfiguration]);
811 if (pNewConfiguration->mnProgram != pCurrentConfiguration->mnProgram) {
812 dev_err(pTAS2557->dev,
813 "Configuration %d, %s doesn't share the same program as current %d\n",
814 nConfiguration, pNewConfiguration->mpName, pCurrentConfiguration->mnProgram);
815 return;
816 }
818 if (pNewConfiguration->mnPLL >= pTAS2557->mpFirmware->mnPLLs) {
819 dev_err(pTAS2557->dev,
820 "Configuration %d, %s doesn't have a valid PLL index %d\n",
821 nConfiguration, pNewConfiguration->mpName, pNewConfiguration->mnPLL);
822 return;
823 }
825 pNewPLL = &(pTAS2557->mpFirmware->mpPLLs[pNewConfiguration->mnPLL]);
827 if (pTAS2557->mbPowerUp) {
828 if (pNewConfiguration->mnPLL != pCurrentConfiguration->mnPLL) {
829 dev_dbg(pTAS2557->dev,
830 "TAS2557 is powered up -> mute and power down DSP before loading new configuration\n");
831 //tas2557_dev_load_data(pTAS2557, p_tas2557_mute_DSP_down_data);
832 tas2557_dev_load_data(pTAS2557, p_tas2557_shutdown_data);
833 dev_dbg(pTAS2557->dev, "TAS2557: load new PLL: %s, block data\n",
834 pNewPLL->mpName);
835 tas2557_load_block(pTAS2557, &(pNewPLL->mBlock));
836 pTAS2557->mnCurrentSampleRate = pNewConfiguration->mnSamplingRate;
837 dev_dbg(pTAS2557->dev,
838 "load new configuration: %s, pre block data\n",
839 pNewConfiguration->mpName);
840 tas2557_load_data(pTAS2557, &(pNewConfiguration->mData),
841 TAS2557_BLOCK_CFG_PRE_DEV_A);
842 dev_dbg(pTAS2557->dev,
843 "TAS2557: load new configuration: %s, coeff block data\n",
844 pNewConfiguration->mpName);
845 tas2557_load_data(pTAS2557, &(pNewConfiguration->mData),
846 TAS2557_BLOCK_CFG_COEFF_DEV_A);
847 if(pTAS2557->mnDevChl == LEFT_CHANNEL){
848 tas2557_dev_load_blk_data(pTAS2557, p_tas2557_SA_chl_left_data);
849 }else if(pTAS2557->mnDevChl == RIGHT_CHANNEL){
850 tas2557_dev_load_blk_data(pTAS2557, p_tas2557_SA_chl_right_data);
851 }
852 dev_dbg(pTAS2557->dev, "TAS2557: power up TAS2557\n");
853 tas2557_dev_load_data(pTAS2557, p_tas2557_startup_data);
854 dev_dbg(pTAS2557->dev, "TAS2557: unmute TAS2557\n");
855 tas2557_dev_load_data(pTAS2557, p_tas2557_unmute_data);
856 } else {
857 dev_dbg(pTAS2557->dev,
858 "TAS2557 is powered up, no change in PLL: load new configuration: %s, coeff block data\n",
859 pNewConfiguration->mpName);
860 tas2557_load_data(pTAS2557, &(pNewConfiguration->mData),
861 TAS2557_BLOCK_CFG_COEFF_DEV_A);
862 if(pTAS2557->mnDevChl == LEFT_CHANNEL){
863 tas2557_dev_load_blk_data(pTAS2557, p_tas2557_SA_chl_left_data);
864 }else if(pTAS2557->mnDevChl == RIGHT_CHANNEL){
865 tas2557_dev_load_blk_data(pTAS2557, p_tas2557_SA_chl_right_data);
866 }
867 }
869 pTAS2557->mbLoadConfigurationPostPowerUp = false;
870 } else {
871 dev_dbg(pTAS2557->dev,
872 "TAS2557 was powered down\n");
873 if (pNewConfiguration->mnPLL != pCurrentConfiguration->mnPLL) {
874 dev_dbg(pTAS2557->dev, "TAS2557: load new PLL: %s, block data\n",
875 pNewPLL->mpName);
876 tas2557_load_block(pTAS2557, &(pNewPLL->mBlock));
877 pTAS2557->mnCurrentSampleRate = pNewConfiguration->mnSamplingRate;
878 dev_dbg(pTAS2557->dev,
879 "load new configuration: %s, pre block data\n",
880 pNewConfiguration->mpName);
881 tas2557_load_data(pTAS2557, &(pNewConfiguration->mData),
882 TAS2557_BLOCK_CFG_PRE_DEV_A);
883 }
885 dev_dbg(pTAS2557->dev,
886 "TAS2557: load new configuration: %s, coeff block data\n",
887 pNewConfiguration->mpName);
888 tas2557_load_data(pTAS2557, &(pNewConfiguration->mData),
889 TAS2557_BLOCK_CFG_COEFF_DEV_A);
891 if(pTAS2557->mnDevChl == LEFT_CHANNEL){
892 tas2557_dev_load_blk_data(pTAS2557, p_tas2557_SA_chl_left_data);
893 }else if(pTAS2557->mnDevChl == RIGHT_CHANNEL){
894 tas2557_dev_load_blk_data(pTAS2557, p_tas2557_SA_chl_right_data);
895 }
897 pTAS2557->mbLoadConfigurationPostPowerUp = true;
898 }
900 pTAS2557->mnCurrentConfiguration = nConfiguration;
901 }
903 int tas2557_set_config(struct tas2557_priv *pTAS2557, int config)
904 {
905 TConfiguration *pConfiguration;
906 TProgram *pProgram;
907 unsigned int nProgram = pTAS2557->mnCurrentProgram;
908 unsigned int nConfiguration = config;
910 if ((!pTAS2557->mpFirmware->mpPrograms) ||
911 (!pTAS2557->mpFirmware->mpConfigurations)) {
912 dev_err(pTAS2557->dev, "Firmware not loaded\n");
913 return -1;
914 }
916 if (nConfiguration >= pTAS2557->mpFirmware->mnConfigurations) {
917 dev_err(pTAS2557->dev, "Configuration %d doesn't exist\n",
918 nConfiguration);
919 return -1;
920 }
922 pConfiguration = &(pTAS2557->mpFirmware->mpConfigurations[nConfiguration]);
923 pProgram = &(pTAS2557->mpFirmware->mpPrograms[nProgram]);
925 if (nProgram != pConfiguration->mnProgram) {
926 dev_err(pTAS2557->dev,
927 "Configuration %d, %s with Program %d isn't compatible with existing Program %d, %s\n",
928 nConfiguration, pConfiguration->mpName, pConfiguration->mnProgram,
929 nProgram, pProgram->mpName);
930 return -1;
931 }
933 tas2557_load_configuration(pTAS2557, nConfiguration, false);
935 return 0;
936 }
938 void tas2557_clear_firmware(TFirmware *pFirmware)
939 {
940 unsigned int n, nn;
941 if (!pFirmware) return;
942 if (pFirmware->mpDescription) kfree(pFirmware->mpDescription);
944 for (n = 0; n < pFirmware->mnPLLs; n++)
945 {
946 kfree(pFirmware->mpPLLs[n].mpDescription);
947 kfree(pFirmware->mpPLLs[n].mBlock.mpData);
948 }
949 kfree(pFirmware->mpPLLs);
951 for (n = 0; n < pFirmware->mnPrograms; n++)
952 {
953 kfree(pFirmware->mpPrograms[n].mpDescription);
954 kfree(pFirmware->mpPrograms[n].mData.mpDescription);
955 for (nn = 0; nn < pFirmware->mpPrograms[n].mData.mnBlocks; nn++)
956 kfree(pFirmware->mpPrograms[n].mData.mpBlocks[nn].mpData);
957 kfree(pFirmware->mpPrograms[n].mData.mpBlocks);
958 }
959 kfree(pFirmware->mpPrograms);
961 for (n = 0; n < pFirmware->mnConfigurations; n++)
962 {
963 kfree(pFirmware->mpConfigurations[n].mpDescription);
964 kfree(pFirmware->mpConfigurations[n].mData.mpDescription);
965 for (nn = 0; nn < pFirmware->mpConfigurations[n].mData.mnBlocks; nn++)
966 kfree(pFirmware->mpConfigurations[n].mData.mpBlocks[nn].mpData);
967 kfree(pFirmware->mpConfigurations[n].mData.mpBlocks);
968 }
969 kfree(pFirmware->mpConfigurations);
971 for (n = 0; n < pFirmware->mnCalibrations; n++)
972 {
973 kfree(pFirmware->mpCalibrations[n].mpDescription);
974 kfree(pFirmware->mpCalibrations[n].mBlock.mpData);
975 }
976 kfree(pFirmware->mpCalibrations);
978 memset(pFirmware, 0x00, sizeof(TFirmware));
979 }
981 static void tas2557_load_calibration(struct tas2557_priv *pTAS2557,
982 char *pFileName)
983 {
984 int nResult;
985 int nFile;
986 mm_segment_t fs;
987 unsigned char pBuffer[512];
988 int nSize = 0;
990 dev_dbg(pTAS2557->dev, "%s:\n", __func__);
992 fs = get_fs();
993 set_fs(KERNEL_DS);
994 nFile = sys_open(pFileName, O_RDONLY, 0);
996 dev_info(pTAS2557->dev, "TAS2557 calibration file = %s, handle = %d\n",
997 pFileName, nFile);
999 if (nFile >= 0) {
1000 nSize = sys_read(nFile, pBuffer, 512);
1001 sys_close(nFile);
1002 } else {
1003 dev_err(pTAS2557->dev, "TAS2557 cannot open calibration file: %s\n",
1004 pFileName);
1005 }
1007 set_fs(fs);
1009 if (!nSize)
1010 return;
1012 tas2557_clear_firmware(pTAS2557->mpCalFirmware);
1014 dev_info(pTAS2557->dev, "TAS2557 calibration file size = %d\n", nSize);
1015 nResult = fw_parse(pTAS2557, pTAS2557->mpCalFirmware, pBuffer, nSize);
1017 if (nResult) {
1018 dev_err(pTAS2557->dev, "TAS2557 calibration file is corrupt\n");
1019 return;
1020 }
1022 dev_info(pTAS2557->dev, "TAS2557 calibration: %d calibrations\n",
1023 pTAS2557->mpCalFirmware->mnCalibrations);
1024 }
1026 void tas2557_fw_ready(const struct firmware *pFW, void *pContext)
1027 {
1028 struct tas2557_priv *pTAS2557 = (struct tas2557_priv *) pContext;
1029 int nResult;
1030 unsigned int nProgram = 0;
1031 unsigned int nSampleRate = 0;
1033 dev_info(pTAS2557->dev, "%s:\n", __func__);
1035 if (unlikely(!pFW) || unlikely(!pFW->data)) {
1036 dev_err(pTAS2557->dev, "%s firmware is not loaded.\n",
1037 TAS2557_FW_NAME);
1039 nResult = tas2557_load_default(pTAS2557);
1040 return;
1041 }
1043 if (pTAS2557->mpFirmware->mpConfigurations){
1044 nProgram = pTAS2557->mnCurrentProgram;
1045 nSampleRate = pTAS2557->mnCurrentSampleRate;
1046 dev_dbg(pTAS2557->dev, "clear current firmware\n");
1047 tas2557_clear_firmware(pTAS2557->mpFirmware);
1048 }
1050 nResult = fw_parse(pTAS2557, pTAS2557->mpFirmware,
1051 (unsigned char *) (pFW->data), pFW->size);
1053 release_firmware(pFW);
1055 if (nResult) {
1056 dev_err(pTAS2557->dev, "firmware is corrupt\n");
1057 return;
1058 }
1060 if (!pTAS2557->mpFirmware->mnPrograms) {
1061 dev_err(pTAS2557->dev, "firmware contains no programs\n");
1062 return;
1063 }
1065 if (!pTAS2557->mpFirmware->mnConfigurations) {
1066 dev_err(pTAS2557->dev,
1067 "firmware contains no configurations\n");
1068 return;
1069 }
1071 if(nProgram >= pTAS2557->mpFirmware->mnPrograms){
1072 dev_info(pTAS2557->dev,
1073 "no previous program, set to default\n");
1074 nProgram = 0;
1075 }
1077 pTAS2557->mnCurrentSampleRate = nSampleRate;
1079 tas2557_set_program(pTAS2557, nProgram);
1080 }
1082 int tas2557_set_program(struct tas2557_priv *pTAS2557,
1083 unsigned int nProgram)
1084 {
1085 TPLL *pPLL;
1086 TConfiguration *pConfiguration;
1087 unsigned int nConfiguration = 0;
1088 unsigned int nSampleRate = 0;
1089 unsigned int Value = 0;
1090 bool bFound = false;
1091 int nResult = -1;
1093 if ((!pTAS2557->mpFirmware->mpPrograms) ||
1094 (!pTAS2557->mpFirmware->mpConfigurations)) {
1095 dev_err(pTAS2557->dev, "Firmware not loaded\n");
1096 return -1;
1097 }
1099 if (nProgram >= pTAS2557->mpFirmware->mnPrograms) {
1100 dev_err(pTAS2557->dev, "TAS2557: Program %d doesn't exist\n",
1101 nConfiguration);
1102 return -1;
1103 }
1105 nConfiguration = 0;
1106 nSampleRate = pTAS2557->mnCurrentSampleRate;
1108 while (!bFound
1109 && (nConfiguration < pTAS2557->mpFirmware->mnConfigurations)) {
1110 if (pTAS2557->mpFirmware->mpConfigurations[nConfiguration].mnProgram
1111 == nProgram){
1112 if(nSampleRate == 0){
1113 bFound = true;
1114 dev_info(pTAS2557->dev, "find default configuration %d\n", nConfiguration);
1115 }else if(nSampleRate
1116 == pTAS2557->mpFirmware->mpConfigurations[nConfiguration].mnSamplingRate){
1117 bFound = true;
1118 dev_info(pTAS2557->dev, "find matching configuration %d\n", nConfiguration);
1119 }else{
1120 nConfiguration++;
1121 }
1122 }else{
1123 nConfiguration++;
1124 }
1125 }
1127 if (!bFound) {
1128 dev_err(pTAS2557->dev,
1129 "Program %d, no valid configuration found for sample rate %d, ignore\n",
1130 nProgram, nSampleRate);
1131 return -1;
1132 }
1134 pTAS2557->mnCurrentProgram = nProgram;
1136 nResult = tas2557_dev_load_data(pTAS2557, p_tas2557_mute_DSP_down_data);
1137 if(nResult < 0){
1138 dev_err(pTAS2557->dev,
1139 "device register access error\n");
1140 return -1;
1141 }
1143 pTAS2557->write(pTAS2557, TAS2557_SW_RESET_REG, 0x01);
1145 udelay(1000);
1146 pTAS2557->mnCurrentBook = 0;
1147 pTAS2557->mnCurrentPage = 0;
1149 nResult = tas2557_load_default(pTAS2557);
1151 dev_info(pTAS2557->dev, "load program %d\n", nProgram);
1152 tas2557_load_data(pTAS2557,
1153 &(pTAS2557->mpFirmware->mpPrograms[nProgram].mData),
1154 TAS2557_BLOCK_PGM_DEV_A);
1156 nResult = pTAS2557->read(pTAS2557, TAS2557_CRC_CHECKSUM_REG, &Value);
1157 dev_info(pTAS2557->dev, "uCDSP Checksum: 0x%02x\n", Value);
1159 pTAS2557->mnCurrentConfiguration = nConfiguration;
1160 pConfiguration =
1161 &(pTAS2557->mpFirmware->mpConfigurations[nConfiguration]);
1162 pPLL = &(pTAS2557->mpFirmware->mpPLLs[pConfiguration->mnPLL]);
1163 dev_dbg(pTAS2557->dev,
1164 "TAS2557 load PLL: %s block for Configuration %s\n",
1165 pPLL->mpName, pConfiguration->mpName);
1167 tas2557_load_block(pTAS2557, &(pPLL->mBlock));
1168 pTAS2557->mnCurrentSampleRate = pConfiguration->mnSamplingRate;
1169 dev_dbg(pTAS2557->dev,
1170 "load configuration %s conefficient pre block\n",
1171 pConfiguration->mpName);
1172 tas2557_load_data(pTAS2557, &(pConfiguration->mData), TAS2557_BLOCK_CFG_PRE_DEV_A);
1174 nResult = pTAS2557->read(pTAS2557, TAS2557_PLL_CLKIN_REG, &Value);
1175 dev_info(pTAS2557->dev, "TAS2557 PLL_CLKIN = 0x%02X\n", Value);
1176 p_tas2557_startup_data[TAS2557_STARTUP_DATA_PLL_CLKIN_INDEX] = Value;
1178 tas2557_load_configuration(pTAS2557, nConfiguration, true);
1179 if (pTAS2557->mbPowerUp){
1180 dev_dbg(pTAS2557->dev, "device powered up, load startup\n");
1181 tas2557_dev_load_data(pTAS2557, p_tas2557_startup_data);
1182 dev_dbg(pTAS2557->dev,
1183 "device powered up, load unmute\n");
1184 tas2557_dev_load_data(pTAS2557, p_tas2557_unmute_data);
1185 }
1187 return 0;
1188 }
1190 int tas2557_set_calibration(struct tas2557_priv *pTAS2557,
1191 int nCalibration)
1192 {
1193 if ((!pTAS2557->mpFirmware->mpPrograms) || (!pTAS2557->mpFirmware->mpConfigurations))
1194 {
1195 dev_err(pTAS2557->dev, "Firmware not loaded\n\r");
1196 return -1;
1197 }
1199 if (nCalibration == 0x00FF)
1200 {
1201 dev_info(pTAS2557->dev, "load new calibration file %s\n", TAS2557_CAL_NAME);
1202 tas2557_load_calibration(pTAS2557, TAS2557_CAL_NAME);
1203 nCalibration = 0;
1204 }
1206 if (nCalibration >= pTAS2557->mpFirmware->mnCalibrations) {
1207 dev_err(pTAS2557->dev,
1208 "Calibration %d doesn't exist\n", nCalibration);
1209 return -1;
1210 }
1212 pTAS2557->mnCurrentCalibration = nCalibration;
1213 if(pTAS2557->mbPowerUp){
1214 tas2557_load_block(pTAS2557,
1215 &(pTAS2557->mpCalFirmware->mpCalibrations[pTAS2557->mnCurrentCalibration].mBlock));
1216 pTAS2557->mbLoadCalibrationPostPowerUp = false;
1217 }else{
1218 pTAS2557->mbLoadCalibrationPostPowerUp = true;
1219 }
1221 return 0;
1222 }
1224 int tas2557_parse_dt(struct device *dev,
1225 struct tas2557_priv *pTAS2557)
1226 {
1227 struct device_node *np = dev->of_node;
1228 int rc= 0, ret = 0;
1230 rc = of_property_read_u32(np, "ti,load", &pTAS2557->mnLoad);
1231 if (rc) {
1232 dev_err(pTAS2557->dev, "Looking up %s property in node %s failed %d\n",
1233 "ti,load", np->full_name, rc);
1234 ret = -1;
1235 }else{
1236 dev_dbg(pTAS2557->dev, "ti,load=%d", pTAS2557->mnLoad);
1237 }
1239 rc = of_property_read_u32(np, "ti,channel", &pTAS2557->mnDevChl);
1240 if (rc) {
1241 dev_err(pTAS2557->dev, "Looking up %s property in node %s failed %d\n",
1242 "ti,channel", np->full_name, rc);
1243 ret = -1;
1244 }else{
1245 dev_dbg(pTAS2557->dev, "ti,channel=%d", pTAS2557->mnDevChl);
1246 }
1248 pTAS2557->mnResetGPIO = of_get_named_gpio(np,
1249 "ti,cdc-reset-gpio", 0);
1250 if (pTAS2557->mnResetGPIO < 0) {
1251 dev_err(pTAS2557->dev, "Looking up %s property in node %s failed %d\n",
1252 "ti,cdc-reset-gpio", np->full_name,
1253 pTAS2557->mnResetGPIO);
1254 ret = -1;
1255 }else{
1256 dev_dbg(pTAS2557->dev, "ti,cdc-reset-gpio=%d", pTAS2557->mnResetGPIO);
1257 }
1259 return ret;
1260 }
1262 MODULE_AUTHOR("Texas Instruments Inc.");
1263 MODULE_DESCRIPTION("TAS2557 common functions for Android Linux");
1264 MODULE_LICENSE("GPLv2");