]> Gitweb @ Texas Instruments - Open Source Git Repositories - git.TI.com/gitweb - tas2557sw-android/tas2557-android-driver.git/blob - tas2557-core.c
23817333cfb27eca3c6a8db781f8af9aa73555f6
[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 ** File:
14 **     tas2557-core.c
15 **
16 ** Description:
17 **     TAS2557 common functions for Android Linux
18 **
19 ** =============================================================================
20 */
22 #define DEBUG
23 #include <linux/module.h>
24 #include <linux/moduleparam.h>
25 #include <linux/init.h>
26 #include <linux/delay.h>
27 #include <linux/pm.h>
28 #include <linux/i2c.h>
29 #include <linux/gpio.h>
30 #include <linux/regulator/consumer.h>
31 #include <linux/firmware.h>
32 #include <linux/regmap.h>
33 #include <linux/of.h>
34 #include <linux/of_gpio.h>
35 #include <linux/slab.h>
36 #include <linux/syscalls.h>
37 #include <linux/fcntl.h>
38 #include <linux/uaccess.h>
39 #include <linux/crc8.h>
41 #include "tas2557.h"
42 #include "tas2557-core.h"
44 #define PPC_DRIVER_VERSION 0x00000200
45 #define TAS2557_CAL_NAME "/data/tas2557_cal.bin"
47 static int tas2557_load_calibration(struct tas2557_priv *pTAS2557, char *pFileName);
48 static int tas2557_load_data(struct tas2557_priv *pTAS2557, struct TData *pData, unsigned int nType);
49 static void tas2557_clear_firmware(struct TFirmware *pFirmware);
50 static int tas2557_load_block(struct tas2557_priv *pTAS2557, struct TBlock *pBlock);
51 static int tas2557_load_configuration(struct tas2557_priv *pTAS2557, unsigned int nConfiguration, bool bLoadSame);
53 #define TAS2557_UDELAY 0xFFFFFFFE
54 #define TAS2557_MDELAY 0xFFFFFFFD
56 #define TAS2557_BLOCK_PLL                               0x00
57 #define TAS2557_BLOCK_PGM_ALL                   0x0d
58 #define TAS2557_BLOCK_PGM_DEV_A                 0x01
59 #define TAS2557_BLOCK_PGM_DEV_B                 0x08
60 #define TAS2557_BLOCK_CFG_COEFF_DEV_A   0x03
61 #define TAS2557_BLOCK_CFG_COEFF_DEV_B   0x0a
62 #define TAS2557_BLOCK_CFG_PRE_DEV_A             0x04
63 #define TAS2557_BLOCK_CFG_PRE_DEV_B             0x0b
64 #define TAS2557_BLOCK_CFG_POST                  0x05
65 #define TAS2557_BLOCK_CFG_POST_POWER    0x06
67 static unsigned int p_tas2557_default_data[] = {
68         TAS2557_SAR_ADC2_REG, 0x05,     /* enable SAR ADC */
69 /*TODO TAS2555_CLK_ERR_CTRL2, 0x39,     enable clock error detection on PLL */
70 /*TODO TAS2555_CLK_ERR_CTRL3, 0x11,     enable clock error detection on PLL */
71         TAS2557_SAFE_GUARD_REG, TAS2557_SAFE_GUARD_PATTERN,     /* safe guard */
72         0xFFFFFFFF, 0xFFFFFFFF
73 };
75 static unsigned int p_tas2557_irq_config[] = {
76 /*      TAS2555_CLK_HALT_REG, 0x71,      TODO */
77         TAS2557_INT_GEN1_REG, 0x11,     /* enable spk OC and OV */
78         TAS2557_INT_GEN2_REG, 0x11,     /* enable clk err1 and die OT */
79         TAS2557_INT_GEN3_REG, 0x11,     /* enable clk err2 and brownout */
80         TAS2557_INT_GEN4_REG, 0x01,     /* disable SAR, enable clk halt */
81         TAS2557_INT_MODE_REG, 0x80,     /* active high until INT_STICKY_1 and INT_STICKY_2 are read to be cleared. */
82         TAS2557_GPIO4_PIN_REG, 0x07,    /* set GPIO4 as int1, default */
83         0xFFFFFFFF, 0xFFFFFFFF
84 };
86 static unsigned int p_tas2557_startup_data[] = {
87         TAS2557_GPI_PIN_REG, 0x15,      /* enable DIN, MCLK, CCI */
88         TAS2557_GPIO1_PIN_REG, 0x01,    /* enable BCLK */
89         TAS2557_GPIO2_PIN_REG, 0x01,    /* enable WCLK */
90         TAS2557_CLK_ERR_CTRL, 0x00,      /* enable clock error detection */
91         TAS2557_POWER_CTRL2_REG, 0xA0,   /* Class-D, Boost power up */
92         TAS2557_POWER_CTRL2_REG, 0xA3,   /* Class-D, Boost, IV sense power up */
93         TAS2557_POWER_CTRL1_REG, 0xF8,   /* PLL, DSP, clock dividers power up */
94         TAS2557_UDELAY, 2000,            /* delay */
95 /*      TAS2557_CLK_ERR_CTRL, 0x03,      TODO  enable clock error detection */
96         0xFFFFFFFF, 0xFFFFFFFF
97 };
99 static unsigned int p_tas2557_unmute_data[] = {
100         TAS2557_MUTE_REG, 0x00,          /* unmute */
101         TAS2557_SOFT_MUTE_REG, 0x00,     /* soft unmute */
102         0xFFFFFFFF, 0xFFFFFFFF
103 };
105 static unsigned int p_tas2557_shutdown_data[] = {
106         TAS2557_CLK_ERR_CTRL, 0x00,      /* disable clock error detection */
107         TAS2557_SOFT_MUTE_REG, 0x01,     /* soft mute */
108         TAS2557_UDELAY, 10000,           /* delay 10ms */
109         TAS2557_MUTE_REG, 0x03,          /* mute */
110         TAS2557_POWER_CTRL1_REG, 0x60,   /* DSP power down */
111         TAS2557_UDELAY, 2000,            /* delay 2ms */
112         TAS2557_POWER_CTRL2_REG, 0x00,   /* Class-D, Boost power down */
113         TAS2557_POWER_CTRL1_REG, 0x00,   /* all power down */
114         TAS2557_GPIO1_PIN_REG, 0x00,    /* disable BCLK */
115         TAS2557_GPIO2_PIN_REG, 0x00,    /* disable WCLK */
116         TAS2557_GPI_PIN_REG, 0x00,      /* disable DIN, MCLK, CCI */
117         0xFFFFFFFF, 0xFFFFFFFF
118 };
120 static unsigned int p_tas2557_mute_DSP_down_data[] = {
121         TAS2557_MUTE_REG, 0x03,          /* mute */
122         TAS2557_POWER_CTRL1_REG, 0x60,   /* DSP power down */
123         TAS2557_UDELAY, 0xFF,            /* delay */
124         0xFFFFFFFF, 0xFFFFFFFF
125 };
127 static int tas2557_dev_load_data(struct tas2557_priv *pTAS2557, unsigned int *pData)
129         int ret = 0;
130         unsigned int n = 0;
131         unsigned int nRegister;
132         unsigned int nData;
134         do {
135                 nRegister = pData[n * 2];
136                 nData = pData[n * 2 + 1];
137                 if (nRegister == TAS2557_UDELAY)
138                         udelay(nData);
139                 else if (nRegister != 0xFFFFFFFF) {
140                         ret = pTAS2557->write(pTAS2557, nRegister, nData);
141                         if (ret < 0)
142                                 break;
143                 }
144                 n++;
145         } while (nRegister != 0xFFFFFFFF);
146         return ret;
149 int tas2557_configIRQ(struct tas2557_priv *pTAS2557)
151         return tas2557_dev_load_data(pTAS2557, p_tas2557_irq_config);
154 int tas2557_set_bit_rate(struct tas2557_priv *pTAS2557, unsigned int nBitRate)
156         int ret = 0, n = -1;
158         dev_dbg(pTAS2557->dev, "tas2557_set_bit_rate: nBitRate = %d\n", nBitRate);
160         switch (nBitRate) {
161         case 16:
162                 n = 0;
163                 break;
164         case 20:
165                 n = 1;
166                 break;
167         case 24:
168                 n = 2;
169                 break;
170         case 32:
171                 n = 3;
172                 break;
173         }
175         if (n >= 0)
176                 ret = pTAS2557->update_bits(pTAS2557, TAS2557_ASI1_DAC_FORMAT_REG, 0x18, n<<3);
177         return ret;
180 int tas2557_get_bit_rate(struct tas2557_priv *pTAS2557, unsigned char *pBitRate)
182         int ret = 0;
183         unsigned int nValue = 0;
184         unsigned char bitRate;
186         ret = pTAS2557->read(pTAS2557, TAS2557_ASI1_DAC_FORMAT_REG, &nValue);
187         if (ret >= 0) {
188                 bitRate = (nValue&0x18)>>3;
189                 if (bitRate == 0)
190                         bitRate = 16;
191                 else if (bitRate == 1)
192                         bitRate = 20;
193                 else if (bitRate == 2)
194                         bitRate = 24;
195                 else if (bitRate == 3)
196                         bitRate = 32;
197                 *pBitRate = bitRate;
198         }
200         return ret;
203 int tas2557_get_DAC_gain(struct tas2557_priv *pTAS2557, unsigned char *pnGain)
205         int ret = 0;
206         unsigned int nValue = 0;
208         ret = pTAS2557->read(pTAS2557, TAS2557_SPK_CTRL_REG, &nValue);
209         if (ret >= 0)
210                 *pnGain = ((nValue&TAS2557_DAC_GAIN_MASK)>>TAS2557_DAC_GAIN_SHIFT);
212         return ret;
215 int tas2557_set_DAC_gain(struct tas2557_priv *pTAS2557, unsigned int nGain)
217         int ret = 0;
219         ret = pTAS2557->update_bits(pTAS2557, TAS2557_SPK_CTRL_REG, TAS2557_DAC_GAIN_MASK,
220                 (nGain<<TAS2557_DAC_GAIN_SHIFT));
221         return ret;
224 /*
225 * die temperature calculation:
226 * DieTemp = readout / 2^23
227 */
228 int tas2557_get_die_temperature(struct tas2557_priv *pTAS2557, int *pTemperature)
230         unsigned char nBuf[4];
231         int temp;
232         int nResult = 0;
234         if (pTAS2557->mbPowerUp) {
235                 nResult = pTAS2557->bulk_read(pTAS2557, TAS2557_DIE_TEMP_REG, nBuf, 4);
236                 if (nResult >= 0) {
237                         temp = ((int)nBuf[0] << 24) | ((int)nBuf[1] << 16) | ((int)nBuf[2] << 8) | nBuf[3];
238                         *pTemperature = temp;
239                 }
240         } else
241                 dev_err(pTAS2557->dev, "Get Die Temperature when music is playing\n");
243         return nResult;
246 int tas2557_load_platdata(struct tas2557_priv *pTAS2557)
248         int nResult = 0;
249         unsigned char nGain;
251         if (gpio_is_valid(pTAS2557->mnGpioINT)) {
252                 nResult = tas2557_configIRQ(pTAS2557);
253                 if (nResult < 0)
254                         goto end;
255                 pTAS2557->enableIRQ(pTAS2557, false, true);
256         }
258         nResult = tas2557_set_bit_rate(pTAS2557, pTAS2557->mnI2SBits);
259         if (nResult < 0)
260                 goto end;
262         nResult = tas2557_get_DAC_gain(pTAS2557, &nGain);
263         if (nResult >= 0) {
264                 pTAS2557->mnDevGain = nGain;
265                 pTAS2557->mnDevCurrentGain = nGain;
266         }
268 end:
270         return nResult;
273 int tas2557_load_default(struct tas2557_priv *pTAS2557)
275         int nResult = 0;
277         nResult = tas2557_dev_load_data(pTAS2557, p_tas2557_default_data);
278         if (nResult < 0)
279                 goto end;
281         nResult = tas2557_load_platdata(pTAS2557);
282         if (nResult < 0)
283                 goto end;
285         /* enable DOUT tri-state for extra BCLKs */
286         nResult = pTAS2557->update_bits(pTAS2557, TAS2557_ASI1_DAC_FORMAT_REG, 0x01, 0x01);
287 end:
289         return nResult;
292 static void failsafe(struct tas2557_priv *pTAS2557)
294         dev_err(pTAS2557->dev, "%s\n", __func__);
295         tas2557_dev_load_data(pTAS2557, p_tas2557_shutdown_data);
296         pTAS2557->mbPowerUp = false;
297         pTAS2557->hw_reset(pTAS2557);
298         pTAS2557->write(pTAS2557, TAS2557_SW_RESET_REG, 0x01);
299         udelay(1000);
300         pTAS2557->write(pTAS2557, TAS2557_SPK_CTRL_REG, 0x04);
301         if (pTAS2557->mpFirmware != NULL)
302                 tas2557_clear_firmware(pTAS2557->mpFirmware);
305 int tas2557_enable(struct tas2557_priv *pTAS2557, bool bEnable)
307         int nResult = 0, nRetry = 10;
308         unsigned char nBuf[4];
309         unsigned int nValue;
310         struct TProgram *pProgram;
312         dev_dbg(pTAS2557->dev, "Enable: %d\n", bEnable);
314         if ((pTAS2557->mpFirmware->mnPrograms == 0)
315                 || (pTAS2557->mpFirmware->mnConfigurations == 0)) {
316                 dev_err(pTAS2557->dev, "%s, firmware not loaded\n", __func__);
317                 goto end;
318         }
319         /* check safe guard*/
320         nResult = pTAS2557->read(pTAS2557, TAS2557_SAFE_GUARD_REG, &nValue);
321         if (nResult < 0)
322                 goto end;
323         if ((nValue&0xff) != TAS2557_SAFE_GUARD_PATTERN) {
324                 dev_err(pTAS2557->dev, "ERROR safe guard failure!\n");
325                 nResult = -EPIPE;
326                 goto end;
327         }
329         pProgram = &(pTAS2557->mpFirmware->mpPrograms[pTAS2557->mnCurrentProgram]);
330         if (bEnable) {
331                 if (!pTAS2557->mbPowerUp) {
332                         if (pProgram->mnAppMode == TAS2557_APP_TUNINGMODE) {
333 pllcheck:               /* check PLL */
334                                 nResult = pTAS2557->write(pTAS2557, TAS2557_POWER_CTRL1_REG, 0xf8);
335                                 if (nResult < 0)
336                                         goto end;
337                                 msleep(2);
338                                 /* check TAS2557 */
339                                 memset(nBuf, 0, 4);
340                                 nResult = pTAS2557->bulk_read(pTAS2557, TAS2557_XMEM_44_REG, nBuf, 4);
341                                 if (nResult < 0)
342                                         goto end;
343                                 nValue = ((unsigned int)nBuf[0] << 24) | ((unsigned int)nBuf[1] << 16) | ((unsigned int)nBuf[2] << 8) | nBuf[3];
344                                 if (nValue == 0) {
345                                         nResult = pTAS2557->write(pTAS2557, TAS2557_POWER_CTRL1_REG, 0x60);
346                                         if (nResult < 0)
347                                                 goto end;
348                                         msleep(2);
349                                         nResult = pTAS2557->write(pTAS2557, TAS2557_POWER_CTRL1_REG, 0x00);
350                                         if (nResult < 0)
351                                                 goto end;
352                                         msleep(2);
353                                         nRetry--;
354                                         nResult = -EAGAIN;
355                                         if (nRetry == 0)
356                                                 goto end;
358                                         dev_info(pTAS2557->dev, "PLL is absent, check again %d\n", nRetry);
359                                         goto pllcheck;
360                                 }
361                         }
363                         /* power on device */
364                         dev_dbg(pTAS2557->dev, "Enable: load startup sequence\n");
365                         nResult = tas2557_dev_load_data(pTAS2557, p_tas2557_startup_data);
366                         if (nResult < 0)
367                                 goto end;
368                         dev_dbg(pTAS2557->dev, "Enable: load unmute sequence\n");
369                         nResult = tas2557_dev_load_data(pTAS2557, p_tas2557_unmute_data);
370                         if (nResult < 0)
371                                 goto end;
372                         pTAS2557->mbPowerUp = true;
374                         if (pProgram->mnAppMode == TAS2557_APP_TUNINGMODE) {
375                                 /* turn on IRQ */
376                                 nResult = pTAS2557->enableIRQ(pTAS2557, true, true);
377                                 if (nResult < 0)
378                                         goto end;
379                                 hrtimer_start(&pTAS2557->mtimer,
380                                         ns_to_ktime((u64)LOW_TEMPERATURE_CHECK_PERIOD * NSEC_PER_MSEC), HRTIMER_MODE_REL);
381                         }
382                 }
383         } else {
384                 if (pTAS2557->mbPowerUp) {
385                         if (pProgram->mnAppMode == TAS2557_APP_TUNINGMODE) {
386                                 if (hrtimer_active(&pTAS2557->mtimer))
387                                         hrtimer_cancel(&pTAS2557->mtimer);
389                                 dev_dbg(pTAS2557->dev, "Enable: load shutdown sequence\n");
390                                 /* turn off IRQ */
391                                 nResult = pTAS2557->enableIRQ(pTAS2557, false, true);
392                                 if (nResult < 0)
393                                         goto end;
394                         }
396                         nResult = tas2557_dev_load_data(pTAS2557, p_tas2557_shutdown_data);
397                         if (nResult < 0)
398                                 goto end;
400                         pTAS2557->mbPowerUp = false;
401                 }
402         }
404         nResult = 0;
406 end:
407         if (nResult < 0) {
408                 if (nRetry == 0)
409                         dev_err(pTAS2557->dev, "PLL is absent and enable timeout\n");
410                 else
411                         dev_err(pTAS2557->dev, "enable failure %d\n", nResult);
412                 failsafe(pTAS2557);
413         }
415         return nResult;
418 int tas2557_set_sampling_rate(struct tas2557_priv *pTAS2557, unsigned int nSamplingRate)
420         struct TConfiguration *pConfiguration;
421         unsigned int nConfiguration;
422         int nResult = 0;
424         dev_dbg(pTAS2557->dev, "tas2557_setup_clocks: nSamplingRate = %d [Hz]\n",
425                 nSamplingRate);
427         if ((!pTAS2557->mpFirmware->mpPrograms) ||
428                 (!pTAS2557->mpFirmware->mpConfigurations)) {
429                 dev_err(pTAS2557->dev, "Firmware not loaded\n");
430                 nResult = -EINVAL;
431                 goto end;
432         }
434         pConfiguration = &(pTAS2557->mpFirmware->mpConfigurations[pTAS2557->mnCurrentConfiguration]);
435         if (pConfiguration->mnSamplingRate == nSamplingRate) {
436                 dev_info(pTAS2557->dev, "Sampling rate for current configuration matches: %d\n",
437                         nSamplingRate);
438                 nResult = 0;
439                 goto end;
440         }
442         for (nConfiguration = 0;
443                 nConfiguration < pTAS2557->mpFirmware->mnConfigurations;
444                 nConfiguration++) {
445                 pConfiguration =
446                         &(pTAS2557->mpFirmware->mpConfigurations[nConfiguration]);
447                 if ((pConfiguration->mnSamplingRate == nSamplingRate)
448                         && (pConfiguration->mnProgram == pTAS2557->mnCurrentProgram)) {
449                         dev_info(pTAS2557->dev,
450                                 "Found configuration: %s, with compatible sampling rate %d\n",
451                                 pConfiguration->mpName, nSamplingRate);
452                         nResult = tas2557_load_configuration(pTAS2557, nConfiguration, false);
453                         goto end;
454                 }
455         }
457         dev_err(pTAS2557->dev, "Cannot find a configuration that supports sampling rate: %d\n",
458                 nSamplingRate);
460 end:
462         return nResult;
465 static void fw_print_header(struct tas2557_priv *pTAS2557, struct TFirmware *pFirmware)
467         dev_info(pTAS2557->dev, "FW Size       = %d", pFirmware->mnFWSize);
468         dev_info(pTAS2557->dev, "Checksum      = 0x%04X", pFirmware->mnChecksum);
469         dev_info(pTAS2557->dev, "PPC Version   = 0x%04X", pFirmware->mnPPCVersion);
470         dev_info(pTAS2557->dev, "FW  Version    = 0x%04X", pFirmware->mnFWVersion);
471         dev_info(pTAS2557->dev, "Driver Version= 0x%04X", pFirmware->mnDriverVersion);
472         dev_info(pTAS2557->dev, "Timestamp     = %d", pFirmware->mnTimeStamp);
473         dev_info(pTAS2557->dev, "DDC Name      = %s", pFirmware->mpDDCName);
474         dev_info(pTAS2557->dev, "Description   = %s", pFirmware->mpDescription);
477 inline unsigned int fw_convert_number(unsigned char *pData)
479         return pData[3] + (pData[2] << 8) + (pData[1] << 16) + (pData[0] << 24);
482 static int fw_parse_header(struct tas2557_priv *pTAS2557,
483         struct TFirmware *pFirmware, unsigned char *pData, unsigned int nSize)
485         unsigned char *pDataStart = pData;
486         unsigned int n;
487         unsigned char pMagicNumber[] = { 0x35, 0x35, 0x35, 0x32 };
489         if (nSize < 104) {
490                 dev_err(pTAS2557->dev, "Firmware: Header too short");
491                 return -EINVAL;
492         }
494         if (memcmp(pData, pMagicNumber, 4)) {
495                 dev_err(pTAS2557->dev, "Firmware: Magic number doesn't match");
496                 return -EINVAL;
497         }
498         pData += 4;
500         pFirmware->mnFWSize = fw_convert_number(pData);
501         pData += 4;
503         pFirmware->mnChecksum = fw_convert_number(pData);
504         pData += 4;
506         pFirmware->mnPPCVersion = fw_convert_number(pData);
507         pData += 4;
509         pFirmware->mnFWVersion = fw_convert_number(pData);
510         pData += 4;
512         pFirmware->mnDriverVersion = fw_convert_number(pData);
513         pData += 4;
515         pFirmware->mnTimeStamp = fw_convert_number(pData);
516         pData += 4;
518         memcpy(pFirmware->mpDDCName, pData, 64);
519         pData += 64;
521         n = strlen(pData);
522         pFirmware->mpDescription = kmemdup(pData, n + 1, GFP_KERNEL);
523         pData += n + 1;
524         if ((pData - pDataStart) >= nSize) {
525                 dev_err(pTAS2557->dev, "Firmware: Header too short after DDC description");
526                 return -EINVAL;
527         }
529         pFirmware->mnDeviceFamily = fw_convert_number(pData);
530         pData += 4;
531         if (pFirmware->mnDeviceFamily != 0) {
532                 dev_err(pTAS2557->dev, "deviceFamily %d, not TAS device", pFirmware->mnDeviceFamily);
533                 return -EINVAL;
534         }
536         pFirmware->mnDevice = fw_convert_number(pData);
537         pData += 4;
539         if (pFirmware->mnDevice != 2) {
540                 dev_err(pTAS2557->dev, "device %d, not TAS2557", pFirmware->mnDevice);
541                 return -EINVAL;
542         }
544         fw_print_header(pTAS2557, pFirmware);
545         return pData - pDataStart;
548 static int fw_parse_block_data(struct tas2557_priv *pTAS2557, struct TFirmware *pFirmware,
549         struct TBlock *pBlock, unsigned char *pData)
551         unsigned char *pDataStart = pData;
552         unsigned int n;
554         pBlock->mnType = fw_convert_number(pData);
555         pData += 4;
557         if (pFirmware->mnDriverVersion >= PPC_DRIVER_VERSION) {
558                 pBlock->mbPChkSumPresent = pData[0];
559                 pData++;
561                 pBlock->mnPChkSum = pData[0];
562                 pData++;
564                 pBlock->mbYChkSumPresent = pData[0];
565                 pData++;
567                 pBlock->mnYChkSum = pData[0];
568                 pData++;
569         } else {
570                 pBlock->mbPChkSumPresent = 0;
571                 pBlock->mbYChkSumPresent = 0;
572         }
574         pBlock->mnCommands = fw_convert_number(pData);
575         pData += 4;
577         n = pBlock->mnCommands * 4;
578         pBlock->mpData = kmemdup(pData, n, GFP_KERNEL);
579         pData += n;
581         return pData - pDataStart;
584 static int fw_parse_data(struct tas2557_priv *pTAS2557, struct TFirmware *pFirmware,
585         struct TData *pImageData, unsigned char *pData)
587         unsigned char *pDataStart = pData;
588         unsigned int nBlock;
589         unsigned int n;
591         memcpy(pImageData->mpName, pData, 64);
592         pData += 64;
594         n = strlen(pData);
595         pImageData->mpDescription = kmemdup(pData, n + 1, GFP_KERNEL);
596         pData += n + 1;
598         pImageData->mnBlocks = (pData[0] << 8) + pData[1];
599         pData += 2;
601         pImageData->mpBlocks =
602                 kmalloc(sizeof(struct TBlock) * pImageData->mnBlocks, GFP_KERNEL);
603         for (nBlock = 0; nBlock < pImageData->mnBlocks; nBlock++) {
604                 n = fw_parse_block_data(pTAS2557, pFirmware,
605                         &(pImageData->mpBlocks[nBlock]), pData);
606                 pData += n;
607         }
609         return pData - pDataStart;
612 static int fw_parse_pll_data(struct tas2557_priv *pTAS2557,
613         struct TFirmware *pFirmware, unsigned char *pData)
615         unsigned char *pDataStart = pData;
616         unsigned int n;
617         unsigned int nPLL;
618         struct TPLL *pPLL;
620         pFirmware->mnPLLs = (pData[0] << 8) + pData[1];
621         pData += 2;
623         if (pFirmware->mnPLLs == 0)
624                 goto end;
626         pFirmware->mpPLLs = kmalloc_array(pFirmware->mnPLLs, sizeof(struct TPLL), GFP_KERNEL);
627         for (nPLL = 0; nPLL < pFirmware->mnPLLs; nPLL++) {
628                 pPLL = &(pFirmware->mpPLLs[nPLL]);
630                 memcpy(pPLL->mpName, pData, 64);
631                 pData += 64;
633                 n = strlen(pData);
634                 pPLL->mpDescription = kmemdup(pData, n + 1, GFP_KERNEL);
635                 pData += n + 1;
637                 n = fw_parse_block_data(pTAS2557, pFirmware, &(pPLL->mBlock), pData);
638                 pData += n;
639         }
641 end:
642         return pData - pDataStart;
645 static int fw_parse_program_data(struct tas2557_priv *pTAS2557,
646         struct TFirmware *pFirmware, unsigned char *pData)
648         unsigned char *pDataStart = pData;
649         unsigned int n;
650         unsigned int nProgram;
651         struct TProgram *pProgram;
653         pFirmware->mnPrograms = (pData[0] << 8) + pData[1];
654         pData += 2;
656         if (pFirmware->mnPrograms == 0)
657                 goto end;
659         pFirmware->mpPrograms =
660                 kmalloc(sizeof(struct TProgram) * pFirmware->mnPrograms, GFP_KERNEL);
661         for (nProgram = 0; nProgram < pFirmware->mnPrograms; nProgram++) {
662                 pProgram = &(pFirmware->mpPrograms[nProgram]);
663                 memcpy(pProgram->mpName, pData, 64);
664                 pData += 64;
666                 n = strlen(pData);
667                 pProgram->mpDescription = kmemdup(pData, n + 1, GFP_KERNEL);
668                 pData += n + 1;
670                 pProgram->mnAppMode = pData[0];
671                 pData++;
673                 pProgram->mnBoost = (pData[0] << 8) + pData[1];
674                 pData += 2;
676                 n = fw_parse_data(pTAS2557, pFirmware, &(pProgram->mData), pData);
677                 pData += n;
678         }
680 end:
682         return pData - pDataStart;
685 static int fw_parse_configuration_data(struct tas2557_priv *pTAS2557,
686         struct TFirmware *pFirmware, unsigned char *pData)
688         unsigned char *pDataStart = pData;
689         unsigned int n;
690         unsigned int nConfiguration;
691         struct TConfiguration *pConfiguration;
693         pFirmware->mnConfigurations = (pData[0] << 8) + pData[1];
694         pData += 2;
696         if (pFirmware->mnConfigurations == 0)
697                 goto end;
699         pFirmware->mpConfigurations =
700                 kmalloc(sizeof(struct TConfiguration) * pFirmware->mnConfigurations,
701                 GFP_KERNEL);
702         for (nConfiguration = 0; nConfiguration < pFirmware->mnConfigurations; nConfiguration++) {
703                 pConfiguration = &(pFirmware->mpConfigurations[nConfiguration]);
704                 memcpy(pConfiguration->mpName, pData, 64);
705                 pData += 64;
707                 n = strlen(pData);
708                 pConfiguration->mpDescription = kmemdup(pData, n + 1, GFP_KERNEL);
709                 pData += n + 1;
711                 pConfiguration->mnProgram = pData[0];
712                 pData++;
714                 pConfiguration->mnPLL = pData[0];
715                 pData++;
717                 pConfiguration->mnSamplingRate = fw_convert_number(pData);
718                 pData += 4;
720                 n = fw_parse_data(pTAS2557, pFirmware, &(pConfiguration->mData), pData);
721                 pData += n;
722         }
724 end:
726         return pData - pDataStart;
729 int fw_parse_calibration_data(struct tas2557_priv *pTAS2557,
730         struct TFirmware *pFirmware, unsigned char *pData)
732         unsigned char *pDataStart = pData;
733         unsigned int n;
734         unsigned int nCalibration;
735         struct TCalibration *pCalibration;
737         pFirmware->mnCalibrations = (pData[0] << 8) + pData[1];
738         pData += 2;
740         if (pFirmware->mnCalibrations == 0)
741                 goto end;
743         pFirmware->mpCalibrations =
744                 kmalloc(sizeof(struct TCalibration) * pFirmware->mnCalibrations, GFP_KERNEL);
745         for (nCalibration = 0; nCalibration < pFirmware->mnCalibrations; nCalibration++) {
746                 pCalibration = &(pFirmware->mpCalibrations[nCalibration]);
747                 memcpy(pCalibration->mpName, pData, 64);
748                 pData += 64;
750                 n = strlen(pData);
751                 pCalibration->mpDescription = kmemdup(pData, n + 1, GFP_KERNEL);
752                 pData += n + 1;
754                 pCalibration->mnProgram = pData[0];
755                 pData++;
757                 pCalibration->mnConfiguration = pData[0];
758                 pData++;
760                 n = fw_parse_data(pTAS2557, pFirmware, &(pCalibration->mData), pData);
761                 pData += n;
762         }
764 end:
766         return pData - pDataStart;
769 static int fw_parse(struct tas2557_priv *pTAS2557,
770         struct TFirmware *pFirmware, unsigned char *pData, unsigned int nSize)
772         int nPosition = 0;
774         nPosition = fw_parse_header(pTAS2557, pFirmware, pData, nSize);
775         if (nPosition < 0) {
776                 dev_err(pTAS2557->dev, "Firmware: Wrong Header");
777                 return -EINVAL;
778         }
780         if (nPosition >= nSize) {
781                 dev_err(pTAS2557->dev, "Firmware: Too short");
782                 return -EINVAL;
783         }
785         pData += nPosition;
786         nSize -= nPosition;
787         nPosition = 0;
789         nPosition = fw_parse_pll_data(pTAS2557, pFirmware, pData);
791         pData += nPosition;
792         nSize -= nPosition;
793         nPosition = 0;
795         nPosition = fw_parse_program_data(pTAS2557, pFirmware, pData);
797         pData += nPosition;
798         nSize -= nPosition;
799         nPosition = 0;
801         nPosition = fw_parse_configuration_data(pTAS2557, pFirmware, pData);
803         pData += nPosition;
804         nSize -= nPosition;
805         nPosition = 0;
807         if (nSize > 64)
808                 nPosition = fw_parse_calibration_data(pTAS2557, pFirmware, pData);
809         return 0;
813 static const unsigned char crc8_lookup_table[CRC8_TABLE_SIZE] = {
814 0x00, 0x4D, 0x9A, 0xD7, 0x79, 0x34, 0xE3, 0xAE, 0xF2, 0xBF, 0x68, 0x25, 0x8B, 0xC6, 0x11, 0x5C,
815 0xA9, 0xE4, 0x33, 0x7E, 0xD0, 0x9D, 0x4A, 0x07, 0x5B, 0x16, 0xC1, 0x8C, 0x22, 0x6F, 0xB8, 0xF5,
816 0x1F, 0x52, 0x85, 0xC8, 0x66, 0x2B, 0xFC, 0xB1, 0xED, 0xA0, 0x77, 0x3A, 0x94, 0xD9, 0x0E, 0x43,
817 0xB6, 0xFB, 0x2C, 0x61, 0xCF, 0x82, 0x55, 0x18, 0x44, 0x09, 0xDE, 0x93, 0x3D, 0x70, 0xA7, 0xEA,
818 0x3E, 0x73, 0xA4, 0xE9, 0x47, 0x0A, 0xDD, 0x90, 0xCC, 0x81, 0x56, 0x1B, 0xB5, 0xF8, 0x2F, 0x62,
819 0x97, 0xDA, 0x0D, 0x40, 0xEE, 0xA3, 0x74, 0x39, 0x65, 0x28, 0xFF, 0xB2, 0x1C, 0x51, 0x86, 0xCB,
820 0x21, 0x6C, 0xBB, 0xF6, 0x58, 0x15, 0xC2, 0x8F, 0xD3, 0x9E, 0x49, 0x04, 0xAA, 0xE7, 0x30, 0x7D,
821 0x88, 0xC5, 0x12, 0x5F, 0xF1, 0xBC, 0x6B, 0x26, 0x7A, 0x37, 0xE0, 0xAD, 0x03, 0x4E, 0x99, 0xD4,
822 0x7C, 0x31, 0xE6, 0xAB, 0x05, 0x48, 0x9F, 0xD2, 0x8E, 0xC3, 0x14, 0x59, 0xF7, 0xBA, 0x6D, 0x20,
823 0xD5, 0x98, 0x4F, 0x02, 0xAC, 0xE1, 0x36, 0x7B, 0x27, 0x6A, 0xBD, 0xF0, 0x5E, 0x13, 0xC4, 0x89,
824 0x63, 0x2E, 0xF9, 0xB4, 0x1A, 0x57, 0x80, 0xCD, 0x91, 0xDC, 0x0B, 0x46, 0xE8, 0xA5, 0x72, 0x3F,
825 0xCA, 0x87, 0x50, 0x1D, 0xB3, 0xFE, 0x29, 0x64, 0x38, 0x75, 0xA2, 0xEF, 0x41, 0x0C, 0xDB, 0x96,
826 0x42, 0x0F, 0xD8, 0x95, 0x3B, 0x76, 0xA1, 0xEC, 0xB0, 0xFD, 0x2A, 0x67, 0xC9, 0x84, 0x53, 0x1E,
827 0xEB, 0xA6, 0x71, 0x3C, 0x92, 0xDF, 0x08, 0x45, 0x19, 0x54, 0x83, 0xCE, 0x60, 0x2D, 0xFA, 0xB7,
828 0x5D, 0x10, 0xC7, 0x8A, 0x24, 0x69, 0xBE, 0xF3, 0xAF, 0xE2, 0x35, 0x78, 0xD6, 0x9B, 0x4C, 0x01,
829 0xF4, 0xB9, 0x6E, 0x23, 0x8D, 0xC0, 0x17, 0x5A, 0x06, 0x4B, 0x9C, 0xD1, 0x7F, 0x32, 0xE5, 0xA8
830 };
832 static int isInPageYRAM(struct tas2557_priv *pTAS2557, struct TYCRC *pCRCData,
833         unsigned char nBook, unsigned char nPage, unsigned char nReg, unsigned char len)
835         int nResult = 0;
837         if (nBook == TAS2557_YRAM_BOOK1) {
838                 if (nPage == TAS2557_YRAM1_PAGE) {
839                         if (nReg >= TAS2557_YRAM1_START_REG) {
840                                 pCRCData->mnOffset = nReg;
841                                 pCRCData->mnLen = len;
842                                 nResult = 1;
843                         } else if ((nReg + len) > TAS2557_YRAM1_START_REG) {
844                                 pCRCData->mnOffset = TAS2557_YRAM1_START_REG;
845                                 pCRCData->mnLen = len - (TAS2557_YRAM1_START_REG - nReg);
846                                 nResult = 1;
847                         } else
848                                 nResult = 0;
849                 } else if (nPage == TAS2557_YRAM3_PAGE) {
850                         if (nReg > TAS2557_YRAM3_END_REG) {
851                                 nResult = 0;
852                         } else if (nReg >= TAS2557_YRAM3_START_REG) {
853                                 if ((nReg + len) > TAS2557_YRAM3_END_REG) {
854                                         pCRCData->mnOffset = nReg;
855                                         pCRCData->mnLen = TAS2557_YRAM3_END_REG - nReg + 1;
856                                         nResult = 1;
857                                 } else {
858                                         pCRCData->mnOffset = nReg;
859                                         pCRCData->mnLen = len;
860                                         nResult = 1;
861                                 }
862                         } else {
863                                 if ((nReg + len) < TAS2557_YRAM3_START_REG)
864                                         nResult = 0;
865                                 else {
866                                         pCRCData->mnOffset = TAS2557_YRAM3_START_REG;
867                                         pCRCData->mnLen = len - (TAS2557_YRAM3_START_REG - nReg);
868                                         nResult = 1;
869                                 }
870                         }
871                 }
872         } else if (nBook == TAS2557_YRAM_BOOK2) {
873                 if (nPage == TAS2557_YRAM5_PAGE) {
874                         if (nReg > TAS2557_YRAM5_END_REG) {
875                                 nResult = 0;
876                         } else if (nReg >= TAS2557_YRAM5_START_REG) {
877                                 if ((nReg + len) > TAS2557_YRAM5_END_REG) {
878                                         pCRCData->mnOffset = nReg;
879                                         pCRCData->mnLen = TAS2557_YRAM5_END_REG - nReg + 1;
880                                         nResult = 1;
881                                 } else {
882                                         pCRCData->mnOffset = nReg;
883                                         pCRCData->mnLen = len;
884                                         nResult = 1;
885                                 }
886                         } else {
887                                 if ((nReg + len) < TAS2557_YRAM5_START_REG)
888                                         nResult = 0;
889                                 else {
890                                         pCRCData->mnOffset = TAS2557_YRAM5_START_REG;
891                                         pCRCData->mnLen = len - (TAS2557_YRAM5_START_REG - nReg);
892                                         nResult = 1;
893                                 }
894                         }
895                 }
896         } else
897                 nResult = 0;
899         return nResult;
902 static int isInBlockYRAM(struct tas2557_priv *pTAS2557, struct TYCRC *pCRCData,
903         unsigned char nBook, unsigned char nPage, unsigned char nReg, unsigned char len)
905         int nResult;
907         if (nBook == TAS2557_YRAM_BOOK1) {
908                 if (nPage < TAS2557_YRAM2_START_PAGE)
909                         nResult = 0;
910                 else if (nPage <= TAS2557_YRAM2_END_PAGE) {
911                         if (nReg > TAS2557_YRAM2_END_REG)
912                                 nResult = 0;
913                         else if (nReg >= TAS2557_YRAM2_START_REG) {
914                                 pCRCData->mnOffset = nReg;
915                                 pCRCData->mnLen = len;
916                                 nResult = 1;
917                         } else {
918                                 if ((nReg + len) < TAS2557_YRAM2_START_REG)
919                                         nResult = 0;
920                                 else {
921                                         pCRCData->mnOffset = TAS2557_YRAM2_START_REG;
922                                         pCRCData->mnLen = nReg + len - TAS2557_YRAM2_START_REG;
923                                         nResult = 1;
924                                 }
925                         }
926                 } else
927                         nResult = 0;
928         } else if (nBook == TAS2557_YRAM_BOOK2) {
929                 if (nPage < TAS2557_YRAM4_START_PAGE)
930                         nResult = 0;
931                 else if (nPage <= TAS2557_YRAM4_END_PAGE) {
932                         if (nReg > TAS2557_YRAM2_END_REG)
933                                 nResult = 0;
934                         else if (nReg >= TAS2557_YRAM2_START_REG) {
935                                 pCRCData->mnOffset = nReg;
936                                 pCRCData->mnLen = len;
937                                 nResult = 1;
938                         } else {
939                                 if ((nReg + len) < TAS2557_YRAM2_START_REG)
940                                         nResult = 0;
941                                 else {
942                                         pCRCData->mnOffset = TAS2557_YRAM2_START_REG;
943                                         pCRCData->mnLen = nReg + len - TAS2557_YRAM2_START_REG;
944                                         nResult = 1;
945                                 }
946                         }
947                 } else
948                         nResult = 0;
949         } else
950                 nResult = 0;
952         return nResult;
956 static int isYRAM(struct tas2557_priv *pTAS2557, struct TYCRC *pCRCData,
957         unsigned char nBook, unsigned char nPage, unsigned char nReg, unsigned char len)
959         int nResult;
961         nResult = isInPageYRAM(pTAS2557, pCRCData, nBook, nPage, nReg, len);
963         if (nResult == 0)
964                 nResult = isInBlockYRAM(pTAS2557, pCRCData, nBook, nPage, nReg, len);
966         return nResult;
969 /*
970  * crc8 - calculate a crc8 over the given input data.
971  *
972  * table: crc table used for calculation.
973  * pdata: pointer to data buffer.
974  * nbytes: number of bytes in data buffer.
975  * crc: previous returned crc8 value.
976  */
977 static u8 ti_crc8(const u8 table[CRC8_TABLE_SIZE], u8 *pdata, size_t nbytes, u8 crc)
979         /* loop over the buffer data */
980         while (nbytes-- > 0)
981                 crc = table[(crc ^ *pdata++) & 0xff];
983         return crc;
986 static int doSingleRegCheckSum(struct tas2557_priv *pTAS2557, 
987         unsigned char nBook, unsigned char nPage, unsigned char nReg, unsigned char nValue)
989         int nResult = 0;
990         struct TYCRC sCRCData;
991         unsigned int nData1 = 0;
993         if ((nBook == TAS2557_BOOK_ID(TAS2557_SA_COEFF_SWAP_REG))
994                 && (nPage == TAS2557_PAGE_ID(TAS2557_SA_COEFF_SWAP_REG))
995                 && (nReg >= TAS2557_PAGE_REG(TAS2557_SA_COEFF_SWAP_REG))
996                 && (nReg <= (TAS2557_PAGE_REG(TAS2557_SA_COEFF_SWAP_REG) + 4))) {
997                 /* DSP swap command, pass */
998                 nResult = 0;
999                 goto end;
1000         }
1002         nResult = isYRAM(pTAS2557, &sCRCData, nBook, nPage, nReg, 1);
1003         if (nResult == 1) {
1004                 nResult = pTAS2557->read(pTAS2557, TAS2557_REG(nBook, nPage, nReg), &nData1);
1005                 if (nResult < 0)
1006                         goto end;
1008                 if (nData1 != nValue) {
1009                         dev_err(pTAS2557->dev, "error2 (line %d),B[0x%x]P[0x%x]R[0x%x] W[0x%x], R[0x%x]\n",
1010                                 __LINE__, nBook, nPage, nReg, nValue, nData1);
1011                         nResult = -EAGAIN;
1012                         goto end;
1013                 }
1015                 nResult = ti_crc8(crc8_lookup_table, &nValue, 1, 0);
1016         }
1018 end:
1020         return nResult;
1023 static int doMultiRegCheckSum(struct tas2557_priv *pTAS2557, 
1024         unsigned char nBook, unsigned char nPage, unsigned char nReg, unsigned int len)
1026         int nResult = 0, i;
1027         unsigned char nCRCChkSum = 0;
1028         unsigned char nBuf1[128];
1029         struct TYCRC TCRCData;
1031         if ((nReg + len-1) > 127) {
1032                 nResult = -EINVAL;
1033                 dev_err(pTAS2557->dev, "firmware error\n");
1034                 goto end;
1035         }
1037         if ((nBook == TAS2557_BOOK_ID(TAS2557_SA_COEFF_SWAP_REG))
1038                 && (nPage == TAS2557_PAGE_ID(TAS2557_SA_COEFF_SWAP_REG))
1039                 && (nReg == TAS2557_PAGE_REG(TAS2557_SA_COEFF_SWAP_REG))
1040                 && (len == 4)) {
1041                 /* DSP swap command, pass */
1042                 nResult = 0;
1043                 goto end;
1044         }
1046         nResult = isYRAM(pTAS2557, &TCRCData, nBook, nPage, nReg, len);
1047         if (nResult == 1) {
1048                 if (len == 1) {
1049                         dev_err(pTAS2557->dev, "firmware error\n");
1050                         nResult = -EINVAL;
1051                         goto end;
1052                 } else {
1053                         nResult = pTAS2557->bulk_read(pTAS2557, TAS2557_REG(nBook, nPage, TCRCData.mnOffset), nBuf1, TCRCData.mnLen);
1054                         if (nResult < 0)
1055                                 goto end;
1057                         for (i = 0; i < TCRCData.mnLen; i++) {
1058                                 if ((nBook == TAS2557_BOOK_ID(TAS2557_SA_COEFF_SWAP_REG))
1059                                         && (nPage == TAS2557_PAGE_ID(TAS2557_SA_COEFF_SWAP_REG))
1060                                         && ((i + TCRCData.mnOffset)
1061                                                 >= TAS2557_PAGE_REG(TAS2557_SA_COEFF_SWAP_REG))
1062                                         && ((i + TCRCData.mnOffset)
1063                                                 <= (TAS2557_PAGE_REG(TAS2557_SA_COEFF_SWAP_REG) + 4))) {
1064                                         /* DSP swap command, bypass */
1065                                         continue;
1066                                 } else
1067                                         nCRCChkSum += ti_crc8(crc8_lookup_table, &nBuf1[i], 1, 0);
1068                         }
1070                         nResult = nCRCChkSum;
1071                 }
1072         }
1074 end:
1076         return nResult;
1079 static int tas2557_load_block(struct tas2557_priv *pTAS2557, struct TBlock *pBlock)
1081         int nResult = 0;
1082         unsigned int nCommand = 0;
1083         unsigned char nBook;
1084         unsigned char nPage;
1085         unsigned char nOffset;
1086         unsigned char nData;
1087         unsigned int nLength;
1088         unsigned int nSleep;
1089         unsigned char nCRCChkSum = 0;
1090         unsigned int nValue1;
1091         int nRetry = 6;
1092         unsigned char *pData = pBlock->mpData;
1094         dev_dbg(pTAS2557->dev, "TAS2557 load block: Type = %d, commands = %d\n",
1095                 pBlock->mnType, pBlock->mnCommands);
1096 start:
1097         if (pBlock->mbPChkSumPresent) {
1098                 nResult = pTAS2557->write(pTAS2557, TAS2557_CRC_RESET_REG, 1);
1099                 if (nResult < 0)
1100                         goto end;
1101         }
1103         if (pBlock->mbYChkSumPresent)
1104                 nCRCChkSum = 0;
1106         nCommand = 0;
1108         while (nCommand < pBlock->mnCommands) {
1109                 pData = pBlock->mpData + nCommand * 4;
1111                 nBook = pData[0];
1112                 nPage = pData[1];
1113                 nOffset = pData[2];
1114                 nData = pData[3];
1116                 nCommand++;
1118                 if (nOffset <= 0x7F) {
1119                         nResult = pTAS2557->write(pTAS2557, TAS2557_REG(nBook, nPage, nOffset), nData);
1120                         if (nResult < 0)
1121                                 goto end;
1122                         if (pBlock->mbYChkSumPresent) {
1123                                 nResult = doSingleRegCheckSum(pTAS2557, nBook, nPage, nOffset, nData);
1124                                 if (nResult < 0)
1125                                         goto check;
1126                                 nCRCChkSum += (unsigned char)nResult;
1127                         }
1128                 } else if (nOffset == 0x81) {
1129                         nSleep = (nBook << 8) + nPage;
1130                         msleep(nSleep);
1131                 } else if (nOffset == 0x85) {
1132                         pData += 4;
1133                         nLength = (nBook << 8) + nPage;
1134                         nBook = pData[0];
1135                         nPage = pData[1];
1136                         nOffset = pData[2];
1137                         if (nLength > 1) {
1138                                 nResult = pTAS2557->bulk_write(pTAS2557, TAS2557_REG(nBook, nPage, nOffset), pData + 3, nLength);
1139                                 if (nResult < 0)
1140                                         goto end;
1141                                 if (pBlock->mbYChkSumPresent) {
1142                                         nResult = doMultiRegCheckSum(pTAS2557, nBook, nPage, nOffset, nLength);
1143                                         if (nResult < 0)
1144                                                 goto check;
1145                                         nCRCChkSum += (unsigned char)nResult;
1146                                 }
1147                         } else {
1148                                 nResult = pTAS2557->write(pTAS2557, TAS2557_REG(nBook, nPage, nOffset), pData[3]);
1149                                 if (nResult < 0)
1150                                         goto end;
1151                                 if (pBlock->mbYChkSumPresent) {
1152                                         nResult = doSingleRegCheckSum(pTAS2557, nBook, nPage, nOffset, pData[3]);
1153                                         if (nResult < 0)
1154                                                 goto check;
1155                                         nCRCChkSum += (unsigned char)nResult;
1156                                 }
1157                         }
1159                         nCommand++;
1161                         if (nLength >= 2)
1162                                 nCommand += ((nLength - 2) / 4) + 1;
1163                 }
1164         }
1165         if (pBlock->mbPChkSumPresent) {
1166                 nResult = pTAS2557->read(pTAS2557, TAS2557_CRC_CHECKSUM_REG, &nValue1);
1167                 if (nResult < 0)
1168                         goto end;
1169                 if ((nValue1&0xff) != pBlock->mnPChkSum) {
1170                         dev_err(pTAS2557->dev, "Block PChkSum Error: FW = 0x%x, Reg = 0x%x\n",
1171                                 pBlock->mnPChkSum, (nValue1&0xff));
1172                         nResult = -EAGAIN;
1173                         goto check;
1174                 }
1176                 nResult = 0;
1177                 dev_dbg(pTAS2557->dev, "Block[0x%x] PChkSum match\n", pBlock->mnType);
1178         }
1180         if (pBlock->mbYChkSumPresent) {
1181                 if (nCRCChkSum != pBlock->mnYChkSum) {
1182                         dev_err(pTAS2557->dev, "Block YChkSum Error: FW = 0x%x, YCRC = 0x%x\n",
1183                                 pBlock->mnYChkSum, nCRCChkSum);
1184                         nResult = -EAGAIN;
1185                         goto check;
1186                 }
1187                 nResult = 0;
1188                 dev_dbg(pTAS2557->dev, "Block[0x%x] YChkSum match\n", pBlock->mnType);
1189         }
1191 check:
1192         if (nResult == -EAGAIN) {
1193                 nRetry--;
1194                 if (nRetry > 0)
1195                         goto start;
1196         }
1198 end:
1199         if (nResult < 0) {
1200                 dev_err(pTAS2557->dev, "Block (%d) load error\n",
1201                                 pBlock->mnType);
1202         }
1203         return nResult;
1206 static int tas2557_load_data(struct tas2557_priv *pTAS2557, struct TData *pData, unsigned int nType)
1208         int nResult = 0;
1209         unsigned int nBlock;
1210         struct TBlock *pBlock;
1212         dev_dbg(pTAS2557->dev,
1213                 "TAS2557 load data: %s, Blocks = %d, Block Type = %d\n", pData->mpName, pData->mnBlocks, nType);
1215         for (nBlock = 0; nBlock < pData->mnBlocks; nBlock++) {
1216                 pBlock = &(pData->mpBlocks[nBlock]);
1217                 if (pBlock->mnType == nType) {
1218                         nResult = tas2557_load_block(pTAS2557, pBlock);
1219                         if (nResult < 0)
1220                                 break;
1221                 }
1222         }
1224         return nResult;
1227 static int tas2557_load_configuration(struct tas2557_priv *pTAS2557,
1228         unsigned int nConfiguration, bool bLoadSame)
1230         int nResult = 0;
1231         struct TProgram *pCurrentProgram = NULL;
1232         struct TConfiguration *pCurrentConfiguration = NULL;
1233         struct TConfiguration *pNewConfiguration = NULL;
1234         struct TCalibration *pCalibration = NULL;
1235         struct TPLL *pNewPLL = NULL;
1237         dev_dbg(pTAS2557->dev, "tas2557_load_configuration: %d\n", nConfiguration);
1239         if ((!pTAS2557->mpFirmware->mpPrograms) ||
1240                 (!pTAS2557->mpFirmware->mpConfigurations)) {
1241                 dev_err(pTAS2557->dev, "Firmware not loaded\n");
1242                 nResult = 0;
1243                 goto end;
1244         }
1246         if (nConfiguration >= pTAS2557->mpFirmware->mnConfigurations) {
1247                 dev_err(pTAS2557->dev, "Configuration %d doesn't exist\n",
1248                         nConfiguration);
1249                 nResult = 0;
1250                 goto end;
1251         }
1253         if ((nConfiguration == pTAS2557->mnCurrentConfiguration) && (!bLoadSame)) {
1254                 dev_info(pTAS2557->dev, "Configuration %d is already loaded\n",
1255                         nConfiguration);
1256                 nResult = 0;
1257                 goto end;
1258         }
1260         pCurrentConfiguration =
1261                 &(pTAS2557->mpFirmware->mpConfigurations[pTAS2557->mnCurrentConfiguration]);
1262         pNewConfiguration =
1263                 &(pTAS2557->mpFirmware->mpConfigurations[nConfiguration]);
1264         if (pNewConfiguration->mnProgram != pCurrentConfiguration->mnProgram) {
1265                 dev_err(pTAS2557->dev, "Configuration %d, %s doesn't share the same program as current %d\n",
1266                         nConfiguration, pNewConfiguration->mpName, pCurrentConfiguration->mnProgram);
1267                 nResult = 0;
1268                 goto end;
1269         }
1271         if (pNewConfiguration->mnPLL >= pTAS2557->mpFirmware->mnPLLs) {
1272                 dev_err(pTAS2557->dev, "Configuration %d, %s doesn't have a valid PLL index %d\n",
1273                         nConfiguration, pNewConfiguration->mpName, pNewConfiguration->mnPLL);
1274                 nResult = 0;
1275                 goto end;
1276         }
1278         pCurrentProgram = &(pTAS2557->mpFirmware->mpPrograms[pTAS2557->mnCurrentProgram]);
1279         pNewPLL = &(pTAS2557->mpFirmware->mpPLLs[pNewConfiguration->mnPLL]);
1281         if (pTAS2557->mpCalFirmware->mnCalibrations)
1282                 pCalibration = &(pTAS2557->mpCalFirmware->mpCalibrations[pTAS2557->mnCurrentCalibration]);
1284         if (pTAS2557->mbPowerUp) {
1285                 if (pNewConfiguration->mnPLL != pCurrentConfiguration->mnPLL) {
1286                         if (hrtimer_active(&pTAS2557->mtimer))
1287                                 hrtimer_cancel(&pTAS2557->mtimer);
1288                         nResult = pTAS2557->enableIRQ(pTAS2557, false, true);
1289                         if (nResult < 0)
1290                                 goto end;
1291                         dev_dbg(pTAS2557->dev,
1292                                 "TAS2557 is powered up, power down DSP before loading new configuration\n");
1293                         nResult = tas2557_dev_load_data(pTAS2557, p_tas2557_shutdown_data);
1294                         if (nResult < 0)
1295                                 goto end;
1296                         dev_dbg(pTAS2557->dev, "TAS2557: load new PLL: %s, block data\n", pNewPLL->mpName);
1297                         nResult = tas2557_load_block(pTAS2557, &(pNewPLL->mBlock));
1298                         if (nResult < 0)
1299                                 goto end;
1300                         pTAS2557->mnCurrentSampleRate = pNewConfiguration->mnSamplingRate;
1301                         dev_dbg(pTAS2557->dev, "load new configuration: %s, pre block data\n",
1302                                 pNewConfiguration->mpName);
1303                         nResult = tas2557_load_data(pTAS2557, &(pNewConfiguration->mData),
1304                                 TAS2557_BLOCK_CFG_PRE_DEV_A);
1305                         if (nResult < 0)
1306                                 goto end;
1307                         dev_dbg(pTAS2557->dev, "TAS2557: load new configuration: %s, coeff block data\n",
1308                                 pNewConfiguration->mpName);
1309                         nResult = tas2557_load_data(pTAS2557, &(pNewConfiguration->mData),
1310                                 TAS2557_BLOCK_CFG_COEFF_DEV_A);
1311                         if (nResult < 0)
1312                                 goto end;
1313                         if ((pTAS2557->mpCalFirmware->mnCalibrations)
1314                                 && (pCurrentProgram->mnAppMode == TAS2557_APP_TUNINGMODE)) {
1315                                 dev_dbg(pTAS2557->dev, "Enable: load calibration\n");
1316                                 nResult = tas2557_load_data(pTAS2557, &(pCalibration->mData),
1317                                         TAS2557_BLOCK_CFG_COEFF_DEV_A);
1318                                 if (nResult < 0)
1319                                         goto end;
1320                         }
1321                         dev_dbg(pTAS2557->dev, "TAS2557: power up TAS2557\n");
1322                         nResult = tas2557_dev_load_data(pTAS2557, p_tas2557_startup_data);
1323                         if (nResult < 0)
1324                                 goto end;
1325                         dev_dbg(pTAS2557->dev, "TAS2557: unmute TAS2557\n");
1326                         nResult = tas2557_dev_load_data(pTAS2557, p_tas2557_unmute_data);
1327                         if (nResult < 0)
1328                                 goto end;
1330                         if (pCurrentProgram->mnAppMode == TAS2557_APP_TUNINGMODE) {
1331                                 nResult = pTAS2557->enableIRQ(pTAS2557, true, false);
1332                                 hrtimer_start(&pTAS2557->mtimer,
1333                                         ns_to_ktime((u64)LOW_TEMPERATURE_CHECK_PERIOD * NSEC_PER_MSEC), HRTIMER_MODE_REL);
1334                         }
1335                 } else {
1336                         dev_dbg(pTAS2557->dev,
1337                                 "TAS2557 is powered up, no change in PLL: load new configuration: %s, coeff block data\n",
1338                                 pNewConfiguration->mpName);
1339                         nResult = tas2557_load_data(pTAS2557, &(pNewConfiguration->mData),
1340                                 TAS2557_BLOCK_CFG_COEFF_DEV_A);
1341                         if (nResult < 0)
1342                                 goto end;
1343                         if ((pTAS2557->mpCalFirmware->mnCalibrations)
1344                                 && (pCurrentProgram->mnAppMode == TAS2557_APP_TUNINGMODE)) {
1345                                 dev_dbg(pTAS2557->dev, "Enable: load calibration\n");
1346                                 nResult = tas2557_load_data(pTAS2557, &(pCalibration->mData), TAS2557_BLOCK_CFG_COEFF_DEV_A);
1347                                 if (nResult < 0)
1348                                         goto end;
1349                         }
1350                 }
1351                 pTAS2557->mbLoadConfigurationPostPowerUp = false;
1352         } else {
1353                 dev_dbg(pTAS2557->dev,
1354                         "TAS2557 was powered down\n");
1355                 if (pNewConfiguration->mnPLL != pCurrentConfiguration->mnPLL) {
1356                         dev_dbg(pTAS2557->dev, "TAS2557: load new PLL: %s, block data\n",
1357                                 pNewPLL->mpName);
1358                         nResult = tas2557_load_block(pTAS2557, &(pNewPLL->mBlock));
1359                         if (nResult < 0)
1360                                 goto end;
1361                         pTAS2557->mnCurrentSampleRate = pNewConfiguration->mnSamplingRate;
1362                         dev_dbg(pTAS2557->dev, "load new configuration: %s, pre block data\n", pNewConfiguration->mpName);
1363                         nResult = tas2557_load_data(pTAS2557, &(pNewConfiguration->mData), TAS2557_BLOCK_CFG_PRE_DEV_A);
1364                         if (nResult < 0)
1365                                 goto end;
1366                 }
1367                 dev_dbg(pTAS2557->dev, "TAS2557: load new configuration: %s, coeff block data\n", pNewConfiguration->mpName);
1368                 nResult = tas2557_load_data(pTAS2557, &(pNewConfiguration->mData), TAS2557_BLOCK_CFG_COEFF_DEV_A);
1369                 if (nResult < 0)
1370                         goto end;
1372                 if ((pTAS2557->mpCalFirmware->mnCalibrations)
1373                         && (pCurrentProgram->mnAppMode == TAS2557_APP_TUNINGMODE)) {
1374                         dev_dbg(pTAS2557->dev, "Enable: load calibration\n");
1375                         nResult = tas2557_load_data(pTAS2557, &(pCalibration->mData), TAS2557_BLOCK_CFG_COEFF_DEV_A);
1376                         if (nResult < 0)
1377                                 goto end;
1378                 }
1379                 pTAS2557->mbLoadConfigurationPostPowerUp = true;
1380         }
1381         pTAS2557->mnCurrentConfiguration = nConfiguration;
1383 end:
1385         if (nResult < 0)
1386                 failsafe(pTAS2557);
1388         return nResult;
1391 int tas2557_set_config(struct tas2557_priv *pTAS2557, int config)
1393         struct TConfiguration *pConfiguration;
1394         struct TProgram *pProgram;
1395         unsigned int nProgram = pTAS2557->mnCurrentProgram;
1396         unsigned int nConfiguration = config;
1397         int nResult = 0;
1399         if ((!pTAS2557->mpFirmware->mpPrograms) ||
1400                 (!pTAS2557->mpFirmware->mpConfigurations)) {
1401                 dev_err(pTAS2557->dev, "Firmware not loaded\n");
1402                 nResult = -EINVAL;
1403                 goto end;
1404         }
1406         if (nConfiguration >= pTAS2557->mpFirmware->mnConfigurations) {
1407                 dev_err(pTAS2557->dev, "Configuration %d doesn't exist\n",
1408                         nConfiguration);
1409                 nResult = -EINVAL;
1410                 goto end;
1411         }
1413         pConfiguration = &(pTAS2557->mpFirmware->mpConfigurations[nConfiguration]);
1414         pProgram = &(pTAS2557->mpFirmware->mpPrograms[nProgram]);
1416         if (nProgram != pConfiguration->mnProgram) {
1417                 dev_err(pTAS2557->dev,
1418                         "Configuration %d, %s with Program %d isn't compatible with existing Program %d, %s\n",
1419                         nConfiguration, pConfiguration->mpName, pConfiguration->mnProgram,
1420                         nProgram, pProgram->mpName);
1421                 nResult = -EINVAL;
1422                 goto end;
1423         }
1425         nResult = tas2557_load_configuration(pTAS2557, nConfiguration, false);
1427 end:
1429         return nResult;
1432 void tas2557_clear_firmware(struct TFirmware *pFirmware)
1434         unsigned int n, nn;
1436         if (!pFirmware)
1437                 return;
1439         kfree(pFirmware->mpDescription);
1441         if (pFirmware->mpPLLs != NULL) {
1442                 for (n = 0; n < pFirmware->mnPLLs; n++) {
1443                         kfree(pFirmware->mpPLLs[n].mpDescription);
1444                         kfree(pFirmware->mpPLLs[n].mBlock.mpData);
1445                 }
1446                 kfree(pFirmware->mpPLLs);
1447         }
1449         if (pFirmware->mpPrograms != NULL) {
1450                 for (n = 0; n < pFirmware->mnPrograms; n++) {
1451                         kfree(pFirmware->mpPrograms[n].mpDescription);
1452                         kfree(pFirmware->mpPrograms[n].mData.mpDescription);
1453                         for (nn = 0; nn < pFirmware->mpPrograms[n].mData.mnBlocks; nn++)
1454                                 kfree(pFirmware->mpPrograms[n].mData.mpBlocks[nn].mpData);
1455                         kfree(pFirmware->mpPrograms[n].mData.mpBlocks);
1456                 }
1457                 kfree(pFirmware->mpPrograms);
1458         }
1460         if (pFirmware->mpConfigurations != NULL) {
1461                 for (n = 0; n < pFirmware->mnConfigurations; n++) {
1462                         kfree(pFirmware->mpConfigurations[n].mpDescription);
1463                         kfree(pFirmware->mpConfigurations[n].mData.mpDescription);
1464                         for (nn = 0; nn < pFirmware->mpConfigurations[n].mData.mnBlocks; nn++)
1465                                 kfree(pFirmware->mpConfigurations[n].mData.mpBlocks[nn].mpData);
1466                         kfree(pFirmware->mpConfigurations[n].mData.mpBlocks);
1467                 }
1468                 kfree(pFirmware->mpConfigurations);
1469         }
1471         if (pFirmware->mpCalibrations != NULL) {
1472                 for (n = 0; n < pFirmware->mnCalibrations; n++) {
1473                         kfree(pFirmware->mpCalibrations[n].mpDescription);
1474                         kfree(pFirmware->mpCalibrations[n].mData.mpDescription);
1475                         for (nn = 0; nn < pFirmware->mpCalibrations[n].mData.mnBlocks; nn++)
1476                                 kfree(pFirmware->mpCalibrations[n].mData.mpBlocks[nn].mpData);
1477                         kfree(pFirmware->mpCalibrations[n].mData.mpBlocks);
1478                 }
1479                 kfree(pFirmware->mpCalibrations);
1480         }
1482         memset(pFirmware, 0x00, sizeof(struct TFirmware));
1485 static int tas2557_load_calibration(struct tas2557_priv *pTAS2557,      char *pFileName)
1487         int nResult = 0;
1488 /*
1489 *       int nFile;
1490 *       mm_segment_t fs;
1491 *       unsigned char pBuffer[1000];
1492 *       int nSize = 0;
1494 *       dev_dbg(pTAS2557->dev, "%s:\n", __func__);
1496 *       fs = get_fs();
1497 *       set_fs(KERNEL_DS);
1498 *       nFile = sys_open(pFileName, O_RDONLY, 0);
1500 *       dev_info(pTAS2557->dev, "TAS2557 calibration file = %s, handle = %d\n",
1501 *               pFileName, nFile);
1503 *       if (nFile >= 0) {
1504 *               nSize = sys_read(nFile, pBuffer, 1000);
1505 *               sys_close(nFile);
1506 *       } else {
1507 *               dev_err(pTAS2557->dev, "TAS2557 cannot open calibration file: %s\n",
1508 *                       pFileName);
1509 *       }
1511 *       set_fs(fs);
1513 *       if (!nSize)
1514 *               goto end;
1516 *       tas2557_clear_firmware(pTAS2557->mpCalFirmware);
1517 *       dev_info(pTAS2557->dev, "TAS2557 calibration file size = %d\n", nSize);
1518 *       nResult = fw_parse(pTAS2557, pTAS2557->mpCalFirmware, pBuffer, nSize);
1520 *       if (nResult)
1521 *               dev_err(pTAS2557->dev, "TAS2557 calibration file is corrupt\n");
1522 *       else
1523 *               dev_info(pTAS2557->dev, "TAS2557 calibration: %d calibrations\n",
1524 *                       pTAS2557->mpCalFirmware->mnCalibrations);
1526 *end:
1527 **/
1528         return nResult;
1531 void tas2557_fw_ready(const struct firmware *pFW, void *pContext)
1533         struct tas2557_priv *pTAS2557 = (struct tas2557_priv *) pContext;
1534         int nResult;
1535         unsigned int nProgram = 0;
1536         unsigned int nSampleRate = 0;
1538         dev_info(pTAS2557->dev, "%s:\n", __func__);
1540         if (unlikely(!pFW) || unlikely(!pFW->data)) {
1541                 dev_err(pTAS2557->dev, "%s firmware is not loaded.\n",
1542                         TAS2557_FW_NAME);
1543                 goto end;
1544         }
1546         if (pTAS2557->mpFirmware->mpConfigurations) {
1547                 nProgram = pTAS2557->mnCurrentProgram;
1548                 nSampleRate = pTAS2557->mnCurrentSampleRate;
1549                 dev_dbg(pTAS2557->dev, "clear current firmware\n");
1550                 tas2557_clear_firmware(pTAS2557->mpFirmware);
1551         }
1553         nResult = fw_parse(pTAS2557, pTAS2557->mpFirmware, (unsigned char *)(pFW->data), pFW->size);
1554         release_firmware(pFW);
1555         if (nResult < 0) {
1556                 dev_err(pTAS2557->dev, "firmware is corrupt\n");
1557                 goto end;
1558         }
1560         if (!pTAS2557->mpFirmware->mnPrograms) {
1561                 dev_err(pTAS2557->dev, "firmware contains no programs\n");
1562                 nResult = -EINVAL;
1563                 goto end;
1564         }
1566         if (!pTAS2557->mpFirmware->mnConfigurations) {
1567                 dev_err(pTAS2557->dev, "firmware contains no configurations\n");
1568                 nResult = -EINVAL;
1569                 goto end;
1570         }
1572         if (nProgram >= pTAS2557->mpFirmware->mnPrograms) {
1573                 dev_info(pTAS2557->dev,
1574                         "no previous program, set to default\n");
1575                 nProgram = 0;
1576         }
1578         pTAS2557->mnCurrentSampleRate = nSampleRate;
1580         nResult = tas2557_set_program(pTAS2557, nProgram, -1);
1582 end:
1583         return;
1586 int tas2557_set_program(struct tas2557_priv *pTAS2557, unsigned int nProgram, int nConfig)
1588         struct TPLL *pPLL;
1589         struct TConfiguration *pConfiguration;
1590         struct TProgram *pProgram;
1591         unsigned int nConfiguration = 0;
1592         unsigned int nSampleRate = 0;
1593         bool bFound = false;
1594         int nResult = 0;
1596         if ((!pTAS2557->mpFirmware->mpPrograms) ||
1597                 (!pTAS2557->mpFirmware->mpConfigurations)) {
1598                 dev_err(pTAS2557->dev, "Firmware not loaded\n");
1599                 nResult = 0;
1600                 goto end;
1601         }
1603         if (nProgram >= pTAS2557->mpFirmware->mnPrograms) {
1604                 dev_err(pTAS2557->dev, "TAS2557: Program %d doesn't exist\n",
1605                         nProgram);
1606                 nResult = 0;
1607                 goto end;
1608         }
1610         if (nConfig < 0) {
1611                 nConfiguration = 0;
1612                 nSampleRate = pTAS2557->mnCurrentSampleRate;
1613                 while (!bFound && (nConfiguration < pTAS2557->mpFirmware->mnConfigurations)) {
1614                         if (pTAS2557->mpFirmware->mpConfigurations[nConfiguration].mnProgram == nProgram) {
1615                                 if (nSampleRate == 0) {
1616                                         bFound = true;
1617                                         dev_info(pTAS2557->dev, "find default configuration %d\n", nConfiguration);
1618                                 } else if (nSampleRate == pTAS2557->mpFirmware->mpConfigurations[nConfiguration].mnSamplingRate) {
1619                                         bFound = true;
1620                                         dev_info(pTAS2557->dev, "find matching configuration %d\n", nConfiguration);
1621                                 } else {
1622                                         nConfiguration++;
1623                                 }
1624                         } else {
1625                                 nConfiguration++;
1626                         }
1627                 }
1628                 if (!bFound) {
1629                         dev_err(pTAS2557->dev,
1630                                 "Program %d, no valid configuration found for sample rate %d, ignore\n",
1631                                 nProgram, nSampleRate);
1632                         nResult = 0;
1633                         goto end;
1634                 }
1635         } else
1636                 nConfiguration = nConfig;
1638         pTAS2557->mnCurrentProgram = nProgram;
1639         if (pTAS2557->mbPowerUp) {
1640                 if (hrtimer_active(&pTAS2557->mtimer))
1641                         hrtimer_cancel(&pTAS2557->mtimer);
1642                 nResult = pTAS2557->enableIRQ(pTAS2557, false, true);
1643                 if (nResult < 0)
1644                         goto end;
1645                 nResult = tas2557_dev_load_data(pTAS2557, p_tas2557_mute_DSP_down_data);
1646                 if (nResult < 0)
1647                         goto end;
1648         }
1650         nResult = pTAS2557->write(pTAS2557, TAS2557_SW_RESET_REG, 0x01);
1651         if (nResult < 0)
1652                 goto end;
1653         msleep(1);
1654         nResult = tas2557_load_default(pTAS2557);
1655         if (nResult < 0)
1656                 goto end;
1657         dev_info(pTAS2557->dev, "load program %d\n", nProgram);
1658         pProgram = &(pTAS2557->mpFirmware->mpPrograms[nProgram]);
1659         nResult = tas2557_load_data(pTAS2557, &(pProgram->mData), TAS2557_BLOCK_PGM_ALL);
1660         if (nResult < 0)
1661                 goto end;
1662         nResult = tas2557_load_data(pTAS2557, &(pProgram->mData), TAS2557_BLOCK_PGM_DEV_A);
1663         if (nResult < 0)
1664                 goto end;
1665         pTAS2557->mnCurrentConfiguration = nConfiguration;
1666         pConfiguration = &(pTAS2557->mpFirmware->mpConfigurations[nConfiguration]);
1667         pPLL = &(pTAS2557->mpFirmware->mpPLLs[pConfiguration->mnPLL]);
1668         dev_dbg(pTAS2557->dev, "TAS2557 load PLL: %s block for Configuration %s\n", pPLL->mpName, pConfiguration->mpName);
1669         nResult = tas2557_load_block(pTAS2557, &(pPLL->mBlock));
1670         if (nResult < 0)
1671                 goto end;
1672         pTAS2557->mnCurrentSampleRate = pConfiguration->mnSamplingRate;
1673         dev_dbg(pTAS2557->dev, "load configuration %s conefficient pre block\n", pConfiguration->mpName);
1674         nResult = tas2557_load_data(pTAS2557, &(pConfiguration->mData), TAS2557_BLOCK_CFG_PRE_DEV_A);
1675         if (nResult < 0)
1676                 goto end;
1678         nResult = tas2557_load_configuration(pTAS2557, nConfiguration, true);
1679         if (nResult < 0)
1680                 goto end;
1682         if (pTAS2557->mbPowerUp) {
1683                 dev_dbg(pTAS2557->dev, "device powered up, load startup\n");
1684                 nResult = tas2557_dev_load_data(pTAS2557, p_tas2557_startup_data);
1685                 if (nResult < 0)
1686                         goto end;
1687                 dev_dbg(pTAS2557->dev,
1688                         "device powered up, load unmute\n");
1689                 nResult = tas2557_dev_load_data(pTAS2557, p_tas2557_unmute_data);
1690                 if (nResult < 0)
1691                         goto end;
1692                 if (pProgram->mnAppMode == TAS2557_APP_TUNINGMODE) {
1693                         nResult = pTAS2557->enableIRQ(pTAS2557, true, false);
1694                         hrtimer_start(&pTAS2557->mtimer, 
1695                                 ns_to_ktime((u64)LOW_TEMPERATURE_CHECK_PERIOD * NSEC_PER_MSEC), HRTIMER_MODE_REL);
1696                 }
1697         }
1699 end:
1701         if (nResult < 0)
1702                 failsafe(pTAS2557);
1704         return nResult;
1707 int tas2557_set_calibration(struct tas2557_priv *pTAS2557, int nCalibration)
1709         struct TCalibration *pCalibration = NULL;
1710         struct TProgram *pProgram;
1711         int nResult = 0;
1713         if ((!pTAS2557->mpFirmware->mpPrograms)
1714                 || (!pTAS2557->mpFirmware->mpConfigurations)) {
1715                 dev_err(pTAS2557->dev, "Firmware not loaded\n\r");
1716                 nResult = 0;
1717                 goto end;
1718         }
1720         if (nCalibration == 0x00FF) {
1721                 dev_info(pTAS2557->dev, "load new calibration file %s\n", TAS2557_CAL_NAME);
1722                 nResult = tas2557_load_calibration(pTAS2557, TAS2557_CAL_NAME);
1723                 if (nResult < 0)
1724                         goto end;
1725                 nCalibration = 0;
1726         }
1728         if (nCalibration >= pTAS2557->mpCalFirmware->mnCalibrations) {
1729                 dev_err(pTAS2557->dev,
1730                         "Calibration %d doesn't exist\n", nCalibration);
1731                 nResult = 0;
1732                 goto end;
1733         }
1735         pTAS2557->mnCurrentCalibration = nCalibration;
1736         pCalibration = &(pTAS2557->mpCalFirmware->mpCalibrations[nCalibration]);
1737         pProgram = &(pTAS2557->mpFirmware->mpPrograms[pTAS2557->mnCurrentProgram]);
1739         if (pProgram->mnAppMode == TAS2557_APP_TUNINGMODE) {
1740                 dev_dbg(pTAS2557->dev, "Enable: load calibration\n");
1741                 nResult = tas2557_load_data(pTAS2557, &(pCalibration->mData), TAS2557_BLOCK_CFG_COEFF_DEV_A);
1742                 if (nResult < 0)
1743                         goto end;
1744         }
1746 end:
1747         if (nResult < 0) {
1748                 tas2557_clear_firmware(pTAS2557->mpCalFirmware);
1749                 nResult = tas2557_set_program(pTAS2557, pTAS2557->mnCurrentProgram, pTAS2557->mnCurrentConfiguration);
1750         }
1752         return nResult;
1755 int tas2557_parse_dt(struct device *dev, struct tas2557_priv *pTAS2557)
1757         struct device_node *np = dev->of_node;
1758         int rc = 0, ret = 0;
1759         unsigned int value;
1761         pTAS2557->mnResetGPIO = of_get_named_gpio(np, "ti,cdc-reset-gpio", 0);
1762         if (pTAS2557->mnResetGPIO < 0) {
1763                 dev_err(pTAS2557->dev, "Looking up %s property in node %s failed %d\n",
1764                         "ti,cdc-reset-gpio", np->full_name,
1765                         pTAS2557->mnResetGPIO);
1766                 ret = -EINVAL;
1767         } else
1768                         dev_dbg(pTAS2557->dev, "ti,cdc-reset-gpio=%d\n", pTAS2557->mnResetGPIO);
1770         if (ret >= 0) {
1771                 rc = of_property_read_u32(np, "ti,i2s-bits", &value);
1772                 if (rc) {
1773                         dev_err(pTAS2557->dev, "Looking up %s property in node %s failed %d\n",
1774                                 "ti,i2s-bits", np->full_name, rc);
1775                         ret = -EINVAL;
1776                 } else {
1777                         pTAS2557->mnI2SBits = value;
1778                         dev_dbg(pTAS2557->dev, "ti,i2s-bits=%d\n", pTAS2557->mnI2SBits);
1779                 }
1780         }
1782         if (ret >= 0) {
1783                 pTAS2557->mnGpioINT = of_get_named_gpio(np, "ti,irq-gpio", 0);
1784                 if (pTAS2557->mnGpioINT < 0) {
1785                         dev_err(pTAS2557->dev, "Looking up %s property in node %s failed %d\n",
1786                                 "ti,irq-gpio", np->full_name,
1787                                 pTAS2557->mnGpioINT);
1788                         ret = -EINVAL;
1789                 } else
1790                         dev_dbg(pTAS2557->dev, "ti,irq-gpio=%d\n", pTAS2557->mnGpioINT);
1791         }
1792         return ret;
1795 MODULE_AUTHOR("Texas Instruments Inc.");
1796 MODULE_DESCRIPTION("TAS2557 common functions for Android Linux");
1797 MODULE_LICENSE("GPL v2");