]> Gitweb @ Texas Instruments - Open Source Git Repositories - git.TI.com/gitweb - tas2557sw-android/tas2557-android-driver.git/blob - tas2557-core.c
1. add lock in IRQ service and timer function
[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"
48 static int tas2557_load_calibration(struct tas2557_priv *pTAS2557,
49         char *pFileName);
50 static int tas2557_load_data(struct tas2557_priv *pTAS2557, struct TData *pData,
51         unsigned int nType);
52 static void tas2557_clear_firmware(struct TFirmware *pFirmware);
53 static int tas2557_load_block(struct tas2557_priv *pTAS2557, struct TBlock *pBlock);
54 static int tas2557_load_configuration(struct tas2557_priv *pTAS2557,
55         unsigned int nConfiguration, bool bLoadSame);
57 #define TAS2557_UDELAY 0xFFFFFFFE
58 #define TAS2557_MDELAY 0xFFFFFFFD
60 #define TAS2557_BLOCK_PLL                               0x00
61 #define TAS2557_BLOCK_PGM_ALL                   0x0d
62 #define TAS2557_BLOCK_PGM_DEV_A                 0x01
63 #define TAS2557_BLOCK_PGM_DEV_B                 0x08
64 #define TAS2557_BLOCK_CFG_COEFF_DEV_A   0x03
65 #define TAS2557_BLOCK_CFG_COEFF_DEV_B   0x0a
66 #define TAS2557_BLOCK_CFG_PRE_DEV_A             0x04
67 #define TAS2557_BLOCK_CFG_PRE_DEV_B             0x0b
68 #define TAS2557_BLOCK_CFG_POST                  0x05
69 #define TAS2557_BLOCK_CFG_POST_POWER    0x06
71 static unsigned int p_tas2557_default_data[] = {
72         TAS2557_SAR_ADC2_REG, 0x05,     /* enable SAR ADC */
73 /*TODO TAS2555_CLK_ERR_CTRL2, 0x39,     enable clock error detection on PLL */
74 /*TODO TAS2555_CLK_ERR_CTRL3, 0x11,     enable clock error detection on PLL */
75         TAS2557_SAFE_GUARD_REG, TAS2557_SAFE_GUARD_PATTERN,     /* safe guard */
76         0xFFFFFFFF, 0xFFFFFFFF
77 };
79 static unsigned int p_tas2557_irq_config[] = {
80 /*      TAS2555_CLK_HALT_REG, 0x71,      TODO */
81         TAS2557_INT_GEN1_REG, 0x11,     /* enable spk OC and OV */
82         TAS2557_INT_GEN2_REG, 0x11,     /* enable clk err1 and die OT */
83         TAS2557_INT_GEN3_REG, 0x11,     /* enable clk err2 and brownout */
84         TAS2557_INT_GEN4_REG, 0x01,     /* disable SAR, enable clk halt */
85         TAS2557_INT_MODE_REG, 0x80,     /* active high until INT_STICKY_1 and INT_STICKY_2 are read to be cleared. */
86         TAS2557_GPIO4_PIN_REG, 0x07,    /* set GPIO4 as int1, default */
87         0xFFFFFFFF, 0xFFFFFFFF
88 };
90 static unsigned int p_tas2557_startup_data[] = {
91         TAS2557_GPI_PIN_REG, 0x15,      /* enable DIN, MCLK, CCI */
92         TAS2557_GPIO1_PIN_REG, 0x01,    /* enable BCLK */
93         TAS2557_GPIO2_PIN_REG, 0x01,    /* enable WCLK */
94         TAS2557_CLK_ERR_CTRL, 0x00,      /* enable clock error detection */
95         TAS2557_POWER_CTRL2_REG, 0xA0,   /* Class-D, Boost power up */
96         TAS2557_POWER_CTRL2_REG, 0xA3,   /* Class-D, Boost, IV sense power up */
97         TAS2557_POWER_CTRL1_REG, 0xF8,   /* PLL, DSP, clock dividers power up */
98         TAS2557_UDELAY, 2000,            /* delay */
99 /*      TAS2557_CLK_ERR_CTRL, 0x03,      TODO  enable clock error detection */
100         0xFFFFFFFF, 0xFFFFFFFF
101 };
103 static unsigned int p_tas2557_unmute_data[] = {
104         TAS2557_MUTE_REG, 0x00,          /* unmute */
105         TAS2557_SOFT_MUTE_REG, 0x00,     /* soft unmute */
106         0xFFFFFFFF, 0xFFFFFFFF
107 };
109 static unsigned int p_tas2557_shutdown_data[] = {
110         TAS2557_CLK_ERR_CTRL, 0x00,      /* disable clock error detection */
111         TAS2557_SOFT_MUTE_REG, 0x01,     /* soft mute */
112         TAS2557_UDELAY, 10000,           /* delay 10ms */
113         TAS2557_MUTE_REG, 0x03,          /* mute */
114         TAS2557_POWER_CTRL1_REG, 0x60,   /* DSP power down */
115         TAS2557_UDELAY, 2000,            /* delay 2ms */
116         TAS2557_POWER_CTRL2_REG, 0x00,   /* Class-D, Boost power down */
117         TAS2557_POWER_CTRL1_REG, 0x00,   /* all power down */
118         TAS2557_GPIO1_PIN_REG, 0x00,    /* disable BCLK */
119         TAS2557_GPIO2_PIN_REG, 0x00,    /* disable WCLK */
120         TAS2557_GPI_PIN_REG, 0x00,      /* disable DIN, MCLK, CCI */
121         0xFFFFFFFF, 0xFFFFFFFF
122 };
124 static unsigned int p_tas2557_mute_DSP_down_data[] = {
125         TAS2557_MUTE_REG, 0x03,          /* mute */
126         TAS2557_POWER_CTRL1_REG, 0x60,   /* DSP power down */
127         TAS2557_UDELAY, 0xFF,            /* delay */
128         0xFFFFFFFF, 0xFFFFFFFF
129 };
131 static int tas2557_dev_load_data(struct tas2557_priv *pTAS2557,
132         unsigned int *pData)
134         int ret = 0;
135         unsigned int n = 0;
136         unsigned int nRegister;
137         unsigned int nData;
139         do {
140                 nRegister = pData[n * 2];
141                 nData = pData[n * 2 + 1];
142                 if (nRegister == TAS2557_UDELAY)
143                         udelay(nData);
144                 else if (nRegister != 0xFFFFFFFF) {
145                         ret = pTAS2557->write(pTAS2557, nRegister, nData);
146                         if (ret < 0)
147                                 break;
148                 }
149                 n++;
150         } while (nRegister != 0xFFFFFFFF);
151         return ret;
154 int tas2557_configIRQ(struct tas2557_priv *pTAS2557)
156         return tas2557_dev_load_data(pTAS2557, p_tas2557_irq_config);
159 int tas2557_set_bit_rate(struct tas2557_priv *pTAS2557, unsigned int nBitRate)
161         int ret = 0, n = -1;
163         dev_dbg(pTAS2557->dev, "tas2557_set_bit_rate: nBitRate = %d\n", nBitRate);
165         switch (nBitRate) {
166         case 16:
167                 n = 0;
168                 break;
169         case 20:
170                 n = 1;
171                 break;
172         case 24:
173                 n = 2;
174                 break;
175         case 32:
176                 n = 3;
177                 break;
178         }
180         if (n >= 0)
181                 ret = pTAS2557->update_bits(pTAS2557, TAS2557_ASI1_DAC_FORMAT_REG, 0x18, n<<3);
182         return ret;
185 int tas2557_get_bit_rate(struct tas2557_priv *pTAS2557, unsigned char *pBitRate)
187         int ret = 0;
188         unsigned int nValue = 0;
189         unsigned char bitRate;
191         ret = pTAS2557->read(pTAS2557, TAS2557_ASI1_DAC_FORMAT_REG, &nValue);
192         if (ret >= 0) {
193                 bitRate = (nValue&0x18)>>3;
194                 if (bitRate == 0)
195                         bitRate = 16;
196                 else if (bitRate == 1)
197                         bitRate = 20;
198                 else if (bitRate == 2)
199                         bitRate = 24;
200                 else if (bitRate == 3)
201                         bitRate = 32;
202                 *pBitRate = bitRate;
203         }
205         return ret;
208 int tas2557_get_DAC_gain(struct tas2557_priv *pTAS2557, unsigned char *pnGain)
210         int ret = 0;
211         unsigned int nValue = 0;
213         ret = pTAS2557->read(pTAS2557, TAS2557_SPK_CTRL_REG, &nValue);
214         if (ret >= 0)
215                 *pnGain = ((nValue&TAS2557_DAC_GAIN_MASK)>>TAS2557_DAC_GAIN_SHIFT);
217         return ret;
220 int tas2557_set_DAC_gain(struct tas2557_priv *pTAS2557, unsigned int nGain)
222         int ret = 0;
224         ret = pTAS2557->update_bits(pTAS2557, TAS2557_SPK_CTRL_REG, TAS2557_DAC_GAIN_MASK,
225                 (nGain<<TAS2557_DAC_GAIN_SHIFT));
226         return ret;
229 /*
230 * die temperature calculation:
231 * DieTemp = readout / 2^23
232 */
233 int tas2557_get_die_temperature(struct tas2557_priv *pTAS2557, int *pTemperature)
235         unsigned char nBuf[4];
236         int temp;
237         int nResult = 0;
239         if (pTAS2557->mbPowerUp) {
240                 nResult = pTAS2557->bulk_read(pTAS2557, TAS2557_DIE_TEMP_REG, nBuf, 4);
241                 if (nResult >= 0) {
242                         temp = ((int)nBuf[0] << 24) | ((int)nBuf[1] << 16) | ((int)nBuf[2] << 8) | nBuf[3];
243                         *pTemperature = temp;
244                 }
245         } else
246                 dev_err(pTAS2557->dev, "Get Die Temperature when music is playing\n");
248         return nResult;
251 int tas2557_load_platdata(struct tas2557_priv *pTAS2557)
253         int nResult = 0;
255         if (gpio_is_valid(pTAS2557->mnGpioINT)) {
256                 nResult = tas2557_configIRQ(pTAS2557);
257                 if (nResult < 0)
258                         goto end;
259         }
261         nResult = tas2557_set_bit_rate(pTAS2557, pTAS2557->mnI2SBits);
263 end:
265         return nResult;
268 int tas2557_load_default(struct tas2557_priv *pTAS2557)
270         int nResult = 0;
272         nResult = tas2557_dev_load_data(pTAS2557, p_tas2557_default_data);
273         if (nResult < 0)
274                 goto end;
276         nResult = tas2557_load_platdata(pTAS2557);
277         if (nResult < 0)
278                 goto end;
280         /* enable DOUT tri-state for extra BCLKs */
281         nResult = pTAS2557->update_bits(pTAS2557, TAS2557_ASI1_DAC_FORMAT_REG, 0x01, 0x01);
282 end:
284         return nResult;
287 static void failsafe(struct tas2557_priv *pTAS2557)
289         dev_err(pTAS2557->dev, "%s\n", __func__);
290         tas2557_dev_load_data(pTAS2557, p_tas2557_shutdown_data);
291         pTAS2557->mbPowerUp = false;
292         pTAS2557->hw_reset(pTAS2557);
293         pTAS2557->write(pTAS2557, TAS2557_SW_RESET_REG, 0x01);
294         udelay(1000);
295         pTAS2557->write(pTAS2557, TAS2557_SPK_CTRL_REG, 0x04);
296         if (pTAS2557->mpFirmware != NULL)
297                 tas2557_clear_firmware(pTAS2557->mpFirmware);
301 /*
302 * tas2557_load_coefficient
303 */
304 static int tas2557_load_coefficient(struct tas2557_priv *pTAS2557,
305         int nPrevConfig, int nNewConfig, bool bPowerOn)
307         int nResult = 0;
308         struct TPLL *pPLL;
309         bool bRestorePower = false;
310         struct TProgram *pProgram;
311         struct TConfiguration *pPrevConfiguration;
312         struct TConfiguration *pNewConfiguration;
313         struct TCalibration *pCalibration = NULL;
315         if (!pTAS2557->mpFirmware->mnConfigurations) {
316                 dev_err(pTAS2557->dev, "%s, firmware not loaded\n", __func__);
317                 goto end;
318         }
320         if (nNewConfig >= pTAS2557->mpFirmware->mnConfigurations) {
321                 dev_err(pTAS2557->dev, "%s, invalid configuration New=%d, total=%d\n",
322                         __func__, nNewConfig, pTAS2557->mpFirmware->mnConfigurations);
323                 goto end;
324         }
326         if (nPrevConfig < 0)
327                 pPrevConfiguration = NULL;
328         else
329                 pPrevConfiguration = &(pTAS2557->mpFirmware->mpConfigurations[nPrevConfig]);
331         pNewConfiguration = &(pTAS2557->mpFirmware->mpConfigurations[nNewConfig]);
333         if (pPrevConfiguration) {
334                 if (pPrevConfiguration->mnPLL == pNewConfiguration->mnPLL) {
335                         dev_dbg(pTAS2557->dev, "%s, PLL same\n", __func__);
336                         goto prog_coefficient;
337                 }
338         }
340         pProgram = &(pTAS2557->mpFirmware->mpPrograms[pTAS2557->mnCurrentProgram]);
341         if (bPowerOn) {
342                 dev_dbg(pTAS2557->dev, "%s, power down to load new PLL\n", __func__);
343                 if (hrtimer_active(&pTAS2557->mtimer))
344                         hrtimer_cancel(&pTAS2557->mtimer);
346                 if (pProgram->mnAppMode == TAS2557_APP_TUNINGMODE)
347                         pTAS2557->enableIRQ(pTAS2557, false);
349                 nResult = tas2557_dev_load_data(pTAS2557, p_tas2557_mute_DSP_down_data);
350                 if (nResult < 0)
351                         goto end;
352                 bRestorePower = true;
353         }
355         /* load PLL */
356         pPLL = &(pTAS2557->mpFirmware->mpPLLs[pNewConfiguration->mnPLL]);
357         dev_dbg(pTAS2557->dev, "load PLL: %s block for Configuration %s\n",
358                 pPLL->mpName, pNewConfiguration->mpName);
359         nResult = tas2557_load_block(pTAS2557, &(pPLL->mBlock));
360         if (nResult < 0)
361                 goto end;
362         pTAS2557->mnCurrentSampleRate = pNewConfiguration->mnSamplingRate;
363         dev_dbg(pTAS2557->dev, "load configuration %s conefficient pre block\n",
364                 pNewConfiguration->mpName);
365         nResult = tas2557_load_data(pTAS2557, &(pNewConfiguration->mData), TAS2557_BLOCK_CFG_PRE_DEV_A);
366         if (nResult < 0)
367                 goto end;
369 prog_coefficient:
370         dev_dbg(pTAS2557->dev, "load new configuration: %s, coeff block data\n",
371                 pNewConfiguration->mpName);
372         nResult = tas2557_load_data(pTAS2557, &(pNewConfiguration->mData),
373                 TAS2557_BLOCK_CFG_COEFF_DEV_A);
374         if (nResult < 0)
375                 goto end;
376         pTAS2557->mnCurrentConfiguration = nNewConfig;
377         if (pTAS2557->mpCalFirmware->mnCalibrations) {
378                 pCalibration = &(pTAS2557->mpCalFirmware->mpCalibrations[pTAS2557->mnCurrentCalibration]);
379                 dev_dbg(pTAS2557->dev, "load calibration\n");
380                 nResult = tas2557_load_data(pTAS2557, &(pCalibration->mData),
381                         TAS2557_BLOCK_CFG_COEFF_DEV_A);
382                 if (nResult < 0)
383                         goto end;
384         }
386         if (bRestorePower) {
387                 pTAS2557->clearIRQ(pTAS2557);
388                 dev_dbg(pTAS2557->dev, "device powered up, load startup\n");
389                 nResult = tas2557_dev_load_data(pTAS2557, p_tas2557_startup_data);
390                 if (nResult < 0)
391                         goto end;
392                 dev_dbg(pTAS2557->dev,
393                         "device powered up, load unmute\n");
394                 nResult = tas2557_dev_load_data(pTAS2557, p_tas2557_unmute_data);
395                 if (nResult < 0)
396                         goto end;
397                 if (pProgram->mnAppMode == TAS2557_APP_TUNINGMODE) {
398                         pTAS2557->enableIRQ(pTAS2557, true);
399                         if (!hrtimer_active(&pTAS2557->mtimer)) {
400                                 pTAS2557->mnDieTvReadCounter = 0;
401                                 hrtimer_start(&pTAS2557->mtimer,
402                                         ns_to_ktime((u64)LOW_TEMPERATURE_CHECK_PERIOD * NSEC_PER_MSEC), HRTIMER_MODE_REL);
403                         }
404                 }
405         }
406 end:
408         return nResult;
411 int tas2557_enable(struct tas2557_priv *pTAS2557, bool bEnable)
413         int nResult = 0, nRetry = 10;
414         unsigned char nBuf[4];
415         unsigned int nValue;
416         struct TProgram *pProgram;
418         dev_dbg(pTAS2557->dev, "Enable: %d\n", bEnable);
420         if ((pTAS2557->mpFirmware->mnPrograms == 0)
421                 || (pTAS2557->mpFirmware->mnConfigurations == 0)) {
422                 dev_err(pTAS2557->dev, "%s, firmware not loaded\n", __func__);
423                 goto end;
424         }
425         /* check safe guard*/
426         nResult = pTAS2557->read(pTAS2557, TAS2557_SAFE_GUARD_REG, &nValue);
427         if (nResult < 0)
428                 goto end;
429         if ((nValue&0xff) != TAS2557_SAFE_GUARD_PATTERN) {
430                 dev_err(pTAS2557->dev, "ERROR safe guard failure!\n");
431                 nResult = -EPIPE;
432                 goto end;
433         }
435         pProgram = &(pTAS2557->mpFirmware->mpPrograms[pTAS2557->mnCurrentProgram]);
436         if (bEnable) {
437                 if (!pTAS2557->mbPowerUp) {
438                         if (pTAS2557->mbLoadConfigurationPrePowerUp) {
439                                 dev_dbg(pTAS2557->dev, "load coefficient before power\n");
440                                 nResult = tas2557_load_coefficient(pTAS2557,
441                                         pTAS2557->mnCurrentConfiguration, pTAS2557->mnNewConfiguration, false);
442                                 if (nResult < 0)
443                                         goto end;
444                                 pTAS2557->mbLoadConfigurationPrePowerUp = false;
445                         }
447                         if (pProgram->mnAppMode == TAS2557_APP_TUNINGMODE) {
448                                 dev_dbg(pTAS2557->dev, "Tuning mode, check PLL\n");
449                                 /* check PLL */
450 pllcheck:
451                                 nResult = pTAS2557->write(pTAS2557, TAS2557_POWER_CTRL1_REG, 0xf8);
452                                 if (nResult < 0)
453                                         goto end;
454                                 msleep(2);
455                                 /* check TAS2557 */
456                                 memset(nBuf, 0, 4);
457                                 nResult = pTAS2557->bulk_read(pTAS2557, TAS2557_XMEM_44_REG, nBuf, 4);
458                                 if (nResult < 0)
459                                         goto end;
460                                 nValue = ((unsigned int)nBuf[0] << 24) | ((unsigned int)nBuf[1] << 16) | ((unsigned int)nBuf[2] << 8) | nBuf[3];
461                                 if (nValue == 0) {
462                                         nResult = pTAS2557->write(pTAS2557, TAS2557_POWER_CTRL1_REG, 0x60);
463                                         if (nResult < 0)
464                                                 goto end;
465                                         msleep(2);
466                                         nResult = pTAS2557->write(pTAS2557, TAS2557_POWER_CTRL1_REG, 0x00);
467                                         if (nResult < 0)
468                                                 goto end;
469                                         msleep(2);
470                                         nRetry--;
471                                         nResult = -EAGAIN;
472                                         if (nRetry == 0)
473                                                 goto end;
475                                         dev_info(pTAS2557->dev, "PLL is absent, check again %d\n", nRetry);
476                                         goto pllcheck;
477                                 }
478                         }
480                         pTAS2557->clearIRQ(pTAS2557);
481                         /* power on device */
482                         dev_dbg(pTAS2557->dev, "Enable: load startup sequence\n");
483                         nResult = tas2557_dev_load_data(pTAS2557, p_tas2557_startup_data);
484                         if (nResult < 0)
485                                 goto end;
486                         dev_dbg(pTAS2557->dev, "Enable: load unmute sequence\n");
487                         nResult = tas2557_dev_load_data(pTAS2557, p_tas2557_unmute_data);
488                         if (nResult < 0)
489                                 goto end;
491                         if (pProgram->mnAppMode == TAS2557_APP_TUNINGMODE) {
492                                 /* turn on IRQ */
493                                 pTAS2557->enableIRQ(pTAS2557, true);
494                                 if (!hrtimer_active(&pTAS2557->mtimer)) {
495                                         pTAS2557->mnDieTvReadCounter = 0;
496                                         hrtimer_start(&pTAS2557->mtimer,
497                                                 ns_to_ktime((u64)LOW_TEMPERATURE_CHECK_PERIOD * NSEC_PER_MSEC), HRTIMER_MODE_REL);
498                                 }
499                         }
500                         pTAS2557->mbPowerUp = true;
501                 }
502         } else {
503                 if (pTAS2557->mbPowerUp) {
504                         if (hrtimer_active(&pTAS2557->mtimer))
505                                 hrtimer_cancel(&pTAS2557->mtimer);
507                         dev_dbg(pTAS2557->dev, "Enable: load shutdown sequence\n");
508                         if (pProgram->mnAppMode == TAS2557_APP_TUNINGMODE) {
509                                 /* turn off IRQ */
510                                 pTAS2557->enableIRQ(pTAS2557, false);
511                         }
512                         nResult = tas2557_dev_load_data(pTAS2557, p_tas2557_shutdown_data);
513                         if (nResult < 0)
514                                 goto end;
516                         pTAS2557->mbPowerUp = false;
517                 }
518         }
520         nResult = 0;
522 end:
523         if (nResult < 0) {
524                 if (nRetry == 0)
525                         dev_err(pTAS2557->dev, "PLL is absent and enable timeout\n");
526                 else
527                         dev_err(pTAS2557->dev, "enable failure %d\n", nResult);
528                 failsafe(pTAS2557);
529         }
531         return nResult;
534 int tas2557_set_sampling_rate(struct tas2557_priv *pTAS2557, unsigned int nSamplingRate)
536         struct TConfiguration *pConfiguration;
537         unsigned int nConfiguration;
538         int nResult = 0;
540         dev_dbg(pTAS2557->dev, "tas2557_setup_clocks: nSamplingRate = %d [Hz]\n",
541                 nSamplingRate);
543         if ((!pTAS2557->mpFirmware->mpPrograms) ||
544                 (!pTAS2557->mpFirmware->mpConfigurations)) {
545                 dev_err(pTAS2557->dev, "Firmware not loaded\n");
546                 nResult = -EINVAL;
547                 goto end;
548         }
550         pConfiguration = &(pTAS2557->mpFirmware->mpConfigurations[pTAS2557->mnCurrentConfiguration]);
551         if (pConfiguration->mnSamplingRate == nSamplingRate) {
552                 dev_info(pTAS2557->dev, "Sampling rate for current configuration matches: %d\n",
553                         nSamplingRate);
554                 nResult = 0;
555                 goto end;
556         }
558         for (nConfiguration = 0;
559                 nConfiguration < pTAS2557->mpFirmware->mnConfigurations;
560                 nConfiguration++) {
561                 pConfiguration =
562                         &(pTAS2557->mpFirmware->mpConfigurations[nConfiguration]);
563                 if ((pConfiguration->mnSamplingRate == nSamplingRate)
564                         && (pConfiguration->mnProgram == pTAS2557->mnCurrentProgram)) {
565                         dev_info(pTAS2557->dev,
566                                 "Found configuration: %s, with compatible sampling rate %d\n",
567                                 pConfiguration->mpName, nSamplingRate);
568                         nResult = tas2557_load_configuration(pTAS2557, nConfiguration, false);
569                         goto end;
570                 }
571         }
573         dev_err(pTAS2557->dev, "Cannot find a configuration that supports sampling rate: %d\n",
574                 nSamplingRate);
576 end:
578         return nResult;
581 static void fw_print_header(struct tas2557_priv *pTAS2557, struct TFirmware *pFirmware)
583         dev_info(pTAS2557->dev, "FW Size       = %d", pFirmware->mnFWSize);
584         dev_info(pTAS2557->dev, "Checksum      = 0x%04X", pFirmware->mnChecksum);
585         dev_info(pTAS2557->dev, "PPC Version   = 0x%04X", pFirmware->mnPPCVersion);
586         dev_info(pTAS2557->dev, "FW  Version    = 0x%04X", pFirmware->mnFWVersion);
587         dev_info(pTAS2557->dev, "Driver Version= 0x%04X", pFirmware->mnDriverVersion);
588         dev_info(pTAS2557->dev, "Timestamp     = %d", pFirmware->mnTimeStamp);
589         dev_info(pTAS2557->dev, "DDC Name      = %s", pFirmware->mpDDCName);
590         dev_info(pTAS2557->dev, "Description   = %s", pFirmware->mpDescription);
593 inline unsigned int fw_convert_number(unsigned char *pData)
595         return pData[3] + (pData[2] << 8) + (pData[1] << 16) + (pData[0] << 24);
598 static int fw_parse_header(struct tas2557_priv *pTAS2557,
599         struct TFirmware *pFirmware, unsigned char *pData, unsigned int nSize)
601         unsigned char *pDataStart = pData;
602         unsigned int n;
603         unsigned char pMagicNumber[] = { 0x35, 0x35, 0x35, 0x32 };
605         if (nSize < 104) {
606                 dev_err(pTAS2557->dev, "Firmware: Header too short");
607                 return -EINVAL;
608         }
610         if (memcmp(pData, pMagicNumber, 4)) {
611                 dev_err(pTAS2557->dev, "Firmware: Magic number doesn't match");
612                 return -EINVAL;
613         }
614         pData += 4;
616         pFirmware->mnFWSize = fw_convert_number(pData);
617         pData += 4;
619         pFirmware->mnChecksum = fw_convert_number(pData);
620         pData += 4;
622         pFirmware->mnPPCVersion = fw_convert_number(pData);
623         pData += 4;
625         pFirmware->mnFWVersion = fw_convert_number(pData);
626         pData += 4;
628         pFirmware->mnDriverVersion = fw_convert_number(pData);
629         pData += 4;
631         pFirmware->mnTimeStamp = fw_convert_number(pData);
632         pData += 4;
634         memcpy(pFirmware->mpDDCName, pData, 64);
635         pData += 64;
637         n = strlen(pData);
638         pFirmware->mpDescription = kmemdup(pData, n + 1, GFP_KERNEL);
639         pData += n + 1;
640         if ((pData - pDataStart) >= nSize) {
641                 dev_err(pTAS2557->dev, "Firmware: Header too short after DDC description");
642                 return -EINVAL;
643         }
645         pFirmware->mnDeviceFamily = fw_convert_number(pData);
646         pData += 4;
647         if (pFirmware->mnDeviceFamily != 0) {
648                 dev_err(pTAS2557->dev, "deviceFamily %d, not TAS device", pFirmware->mnDeviceFamily);
649                 return -EINVAL;
650         }
652         pFirmware->mnDevice = fw_convert_number(pData);
653         pData += 4;
655         if (pFirmware->mnDevice != 2) {
656                 dev_err(pTAS2557->dev, "device %d, not TAS2557", pFirmware->mnDevice);
657                 return -EINVAL;
658         }
660         fw_print_header(pTAS2557, pFirmware);
661         return pData - pDataStart;
664 static int fw_parse_block_data(struct tas2557_priv *pTAS2557, struct TFirmware *pFirmware,
665         struct TBlock *pBlock, unsigned char *pData)
667         unsigned char *pDataStart = pData;
668         unsigned int n;
670         pBlock->mnType = fw_convert_number(pData);
671         pData += 4;
673         if (pFirmware->mnDriverVersion >= PPC_DRIVER_VERSION) {
674                 pBlock->mbPChkSumPresent = pData[0];
675                 pData++;
677                 pBlock->mnPChkSum = pData[0];
678                 pData++;
680                 pBlock->mbYChkSumPresent = pData[0];
681                 pData++;
683                 pBlock->mnYChkSum = pData[0];
684                 pData++;
685         } else {
686                 pBlock->mbPChkSumPresent = 0;
687                 pBlock->mbYChkSumPresent = 0;
688         }
690         pBlock->mnCommands = fw_convert_number(pData);
691         pData += 4;
693         n = pBlock->mnCommands * 4;
694         pBlock->mpData = kmemdup(pData, n, GFP_KERNEL);
695         pData += n;
697         return pData - pDataStart;
700 static int fw_parse_data(struct tas2557_priv *pTAS2557, struct TFirmware *pFirmware,
701         struct TData *pImageData, unsigned char *pData)
703         unsigned char *pDataStart = pData;
704         unsigned int nBlock;
705         unsigned int n;
707         memcpy(pImageData->mpName, pData, 64);
708         pData += 64;
710         n = strlen(pData);
711         pImageData->mpDescription = kmemdup(pData, n + 1, GFP_KERNEL);
712         pData += n + 1;
714         pImageData->mnBlocks = (pData[0] << 8) + pData[1];
715         pData += 2;
717         pImageData->mpBlocks =
718                 kmalloc(sizeof(struct TBlock) * pImageData->mnBlocks, GFP_KERNEL);
719         for (nBlock = 0; nBlock < pImageData->mnBlocks; nBlock++) {
720                 n = fw_parse_block_data(pTAS2557, pFirmware,
721                         &(pImageData->mpBlocks[nBlock]), pData);
722                 pData += n;
723         }
725         return pData - pDataStart;
728 static int fw_parse_pll_data(struct tas2557_priv *pTAS2557,
729         struct TFirmware *pFirmware, unsigned char *pData)
731         unsigned char *pDataStart = pData;
732         unsigned int n;
733         unsigned int nPLL;
734         struct TPLL *pPLL;
736         pFirmware->mnPLLs = (pData[0] << 8) + pData[1];
737         pData += 2;
739         if (pFirmware->mnPLLs == 0)
740                 goto end;
742         pFirmware->mpPLLs = kmalloc_array(pFirmware->mnPLLs, sizeof(struct TPLL), GFP_KERNEL);
743         for (nPLL = 0; nPLL < pFirmware->mnPLLs; nPLL++) {
744                 pPLL = &(pFirmware->mpPLLs[nPLL]);
746                 memcpy(pPLL->mpName, pData, 64);
747                 pData += 64;
749                 n = strlen(pData);
750                 pPLL->mpDescription = kmemdup(pData, n + 1, GFP_KERNEL);
751                 pData += n + 1;
753                 n = fw_parse_block_data(pTAS2557, pFirmware, &(pPLL->mBlock), pData);
754                 pData += n;
755         }
757 end:
758         return pData - pDataStart;
761 static int fw_parse_program_data(struct tas2557_priv *pTAS2557,
762         struct TFirmware *pFirmware, unsigned char *pData)
764         unsigned char *pDataStart = pData;
765         unsigned int n;
766         unsigned int nProgram;
767         struct TProgram *pProgram;
769         pFirmware->mnPrograms = (pData[0] << 8) + pData[1];
770         pData += 2;
772         if (pFirmware->mnPrograms == 0)
773                 goto end;
775         pFirmware->mpPrograms =
776                 kmalloc(sizeof(struct TProgram) * pFirmware->mnPrograms, GFP_KERNEL);
777         for (nProgram = 0; nProgram < pFirmware->mnPrograms; nProgram++) {
778                 pProgram = &(pFirmware->mpPrograms[nProgram]);
779                 memcpy(pProgram->mpName, pData, 64);
780                 pData += 64;
782                 n = strlen(pData);
783                 pProgram->mpDescription = kmemdup(pData, n + 1, GFP_KERNEL);
784                 pData += n + 1;
786                 pProgram->mnAppMode = pData[0];
787                 pData++;
789                 pProgram->mnBoost = (pData[0] << 8) + pData[1];
790                 pData += 2;
792                 n = fw_parse_data(pTAS2557, pFirmware, &(pProgram->mData), pData);
793                 pData += n;
794         }
796 end:
798         return pData - pDataStart;
801 static int fw_parse_configuration_data(struct tas2557_priv *pTAS2557,
802         struct TFirmware *pFirmware, unsigned char *pData)
804         unsigned char *pDataStart = pData;
805         unsigned int n;
806         unsigned int nConfiguration;
807         struct TConfiguration *pConfiguration;
809         pFirmware->mnConfigurations = (pData[0] << 8) + pData[1];
810         pData += 2;
812         if (pFirmware->mnConfigurations == 0)
813                 goto end;
815         pFirmware->mpConfigurations =
816                 kmalloc(sizeof(struct TConfiguration) * pFirmware->mnConfigurations,
817                 GFP_KERNEL);
818         for (nConfiguration = 0; nConfiguration < pFirmware->mnConfigurations; nConfiguration++) {
819                 pConfiguration = &(pFirmware->mpConfigurations[nConfiguration]);
820                 memcpy(pConfiguration->mpName, pData, 64);
821                 pData += 64;
823                 n = strlen(pData);
824                 pConfiguration->mpDescription = kmemdup(pData, n + 1, GFP_KERNEL);
825                 pData += n + 1;
827                 pConfiguration->mnProgram = pData[0];
828                 pData++;
830                 pConfiguration->mnPLL = pData[0];
831                 pData++;
833                 pConfiguration->mnSamplingRate = fw_convert_number(pData);
834                 pData += 4;
836                 n = fw_parse_data(pTAS2557, pFirmware, &(pConfiguration->mData), pData);
837                 pData += n;
838         }
840 end:
842         return pData - pDataStart;
845 int fw_parse_calibration_data(struct tas2557_priv *pTAS2557,
846         struct TFirmware *pFirmware, unsigned char *pData)
848         unsigned char *pDataStart = pData;
849         unsigned int n;
850         unsigned int nCalibration;
851         struct TCalibration *pCalibration;
853         pFirmware->mnCalibrations = (pData[0] << 8) + pData[1];
854         pData += 2;
856         if (pFirmware->mnCalibrations == 0)
857                 goto end;
859         pFirmware->mpCalibrations =
860                 kmalloc(sizeof(struct TCalibration) * pFirmware->mnCalibrations, GFP_KERNEL);
861         for (nCalibration = 0; nCalibration < pFirmware->mnCalibrations; nCalibration++) {
862                 pCalibration = &(pFirmware->mpCalibrations[nCalibration]);
863                 memcpy(pCalibration->mpName, pData, 64);
864                 pData += 64;
866                 n = strlen(pData);
867                 pCalibration->mpDescription = kmemdup(pData, n + 1, GFP_KERNEL);
868                 pData += n + 1;
870                 pCalibration->mnProgram = pData[0];
871                 pData++;
873                 pCalibration->mnConfiguration = pData[0];
874                 pData++;
876                 n = fw_parse_data(pTAS2557, pFirmware, &(pCalibration->mData), pData);
877                 pData += n;
878         }
880 end:
882         return pData - pDataStart;
885 static int fw_parse(struct tas2557_priv *pTAS2557,
886         struct TFirmware *pFirmware, unsigned char *pData, unsigned int nSize)
888         int nPosition = 0;
890         nPosition = fw_parse_header(pTAS2557, pFirmware, pData, nSize);
891         if (nPosition < 0) {
892                 dev_err(pTAS2557->dev, "Firmware: Wrong Header");
893                 return -EINVAL;
894         }
896         if (nPosition >= nSize) {
897                 dev_err(pTAS2557->dev, "Firmware: Too short");
898                 return -EINVAL;
899         }
901         pData += nPosition;
902         nSize -= nPosition;
903         nPosition = 0;
905         nPosition = fw_parse_pll_data(pTAS2557, pFirmware, pData);
907         pData += nPosition;
908         nSize -= nPosition;
909         nPosition = 0;
911         nPosition = fw_parse_program_data(pTAS2557, pFirmware, pData);
913         pData += nPosition;
914         nSize -= nPosition;
915         nPosition = 0;
917         nPosition = fw_parse_configuration_data(pTAS2557, pFirmware, pData);
919         pData += nPosition;
920         nSize -= nPosition;
921         nPosition = 0;
923         if (nSize > 64)
924                 nPosition = fw_parse_calibration_data(pTAS2557, pFirmware, pData);
925         return 0;
929 static const unsigned char crc8_lookup_table[CRC8_TABLE_SIZE] = {
930 0x00, 0x4D, 0x9A, 0xD7, 0x79, 0x34, 0xE3, 0xAE, 0xF2, 0xBF, 0x68, 0x25, 0x8B, 0xC6, 0x11, 0x5C,
931 0xA9, 0xE4, 0x33, 0x7E, 0xD0, 0x9D, 0x4A, 0x07, 0x5B, 0x16, 0xC1, 0x8C, 0x22, 0x6F, 0xB8, 0xF5,
932 0x1F, 0x52, 0x85, 0xC8, 0x66, 0x2B, 0xFC, 0xB1, 0xED, 0xA0, 0x77, 0x3A, 0x94, 0xD9, 0x0E, 0x43,
933 0xB6, 0xFB, 0x2C, 0x61, 0xCF, 0x82, 0x55, 0x18, 0x44, 0x09, 0xDE, 0x93, 0x3D, 0x70, 0xA7, 0xEA,
934 0x3E, 0x73, 0xA4, 0xE9, 0x47, 0x0A, 0xDD, 0x90, 0xCC, 0x81, 0x56, 0x1B, 0xB5, 0xF8, 0x2F, 0x62,
935 0x97, 0xDA, 0x0D, 0x40, 0xEE, 0xA3, 0x74, 0x39, 0x65, 0x28, 0xFF, 0xB2, 0x1C, 0x51, 0x86, 0xCB,
936 0x21, 0x6C, 0xBB, 0xF6, 0x58, 0x15, 0xC2, 0x8F, 0xD3, 0x9E, 0x49, 0x04, 0xAA, 0xE7, 0x30, 0x7D,
937 0x88, 0xC5, 0x12, 0x5F, 0xF1, 0xBC, 0x6B, 0x26, 0x7A, 0x37, 0xE0, 0xAD, 0x03, 0x4E, 0x99, 0xD4,
938 0x7C, 0x31, 0xE6, 0xAB, 0x05, 0x48, 0x9F, 0xD2, 0x8E, 0xC3, 0x14, 0x59, 0xF7, 0xBA, 0x6D, 0x20,
939 0xD5, 0x98, 0x4F, 0x02, 0xAC, 0xE1, 0x36, 0x7B, 0x27, 0x6A, 0xBD, 0xF0, 0x5E, 0x13, 0xC4, 0x89,
940 0x63, 0x2E, 0xF9, 0xB4, 0x1A, 0x57, 0x80, 0xCD, 0x91, 0xDC, 0x0B, 0x46, 0xE8, 0xA5, 0x72, 0x3F,
941 0xCA, 0x87, 0x50, 0x1D, 0xB3, 0xFE, 0x29, 0x64, 0x38, 0x75, 0xA2, 0xEF, 0x41, 0x0C, 0xDB, 0x96,
942 0x42, 0x0F, 0xD8, 0x95, 0x3B, 0x76, 0xA1, 0xEC, 0xB0, 0xFD, 0x2A, 0x67, 0xC9, 0x84, 0x53, 0x1E,
943 0xEB, 0xA6, 0x71, 0x3C, 0x92, 0xDF, 0x08, 0x45, 0x19, 0x54, 0x83, 0xCE, 0x60, 0x2D, 0xFA, 0xB7,
944 0x5D, 0x10, 0xC7, 0x8A, 0x24, 0x69, 0xBE, 0xF3, 0xAF, 0xE2, 0x35, 0x78, 0xD6, 0x9B, 0x4C, 0x01,
945 0xF4, 0xB9, 0x6E, 0x23, 0x8D, 0xC0, 0x17, 0x5A, 0x06, 0x4B, 0x9C, 0xD1, 0x7F, 0x32, 0xE5, 0xA8
946 };
948 static int isInPageYRAM(struct tas2557_priv *pTAS2557, struct TYCRC *pCRCData,
949         unsigned char nBook, unsigned char nPage, unsigned char nReg, unsigned char len)
951         int nResult = 0;
953         if (nBook == TAS2557_YRAM_BOOK1) {
954                 if (nPage == TAS2557_YRAM1_PAGE) {
955                         if (nReg >= TAS2557_YRAM1_START_REG) {
956                                 pCRCData->mnOffset = nReg;
957                                 pCRCData->mnLen = len;
958                                 nResult = 1;
959                         } else if ((nReg + len) > TAS2557_YRAM1_START_REG) {
960                                 pCRCData->mnOffset = TAS2557_YRAM1_START_REG;
961                                 pCRCData->mnLen = len - (TAS2557_YRAM1_START_REG - nReg);
962                                 nResult = 1;
963                         } else
964                                 nResult = 0;
965                 } else if (nPage == TAS2557_YRAM3_PAGE) {
966                         if (nReg > TAS2557_YRAM3_END_REG) {
967                                 nResult = 0;
968                         } else if (nReg >= TAS2557_YRAM3_START_REG) {
969                                 if ((nReg + len) > TAS2557_YRAM3_END_REG) {
970                                         pCRCData->mnOffset = nReg;
971                                         pCRCData->mnLen = TAS2557_YRAM3_END_REG - nReg + 1;
972                                         nResult = 1;
973                                 } else {
974                                         pCRCData->mnOffset = nReg;
975                                         pCRCData->mnLen = len;
976                                         nResult = 1;
977                                 }
978                         } else {
979                                 if ((nReg + len) < TAS2557_YRAM3_START_REG)
980                                         nResult = 0;
981                                 else {
982                                         pCRCData->mnOffset = TAS2557_YRAM3_START_REG;
983                                         pCRCData->mnLen = len - (TAS2557_YRAM3_START_REG - nReg);
984                                         nResult = 1;
985                                 }
986                         }
987                 }
988         } else if (nBook == TAS2557_YRAM_BOOK2) {
989                 if (nPage == TAS2557_YRAM5_PAGE) {
990                         if (nReg > TAS2557_YRAM5_END_REG) {
991                                 nResult = 0;
992                         } else if (nReg >= TAS2557_YRAM5_START_REG) {
993                                 if ((nReg + len) > TAS2557_YRAM5_END_REG) {
994                                         pCRCData->mnOffset = nReg;
995                                         pCRCData->mnLen = TAS2557_YRAM5_END_REG - nReg + 1;
996                                         nResult = 1;
997                                 } else {
998                                         pCRCData->mnOffset = nReg;
999                                         pCRCData->mnLen = len;
1000                                         nResult = 1;
1001                                 }
1002                         } else {
1003                                 if ((nReg + len) < TAS2557_YRAM5_START_REG)
1004                                         nResult = 0;
1005                                 else {
1006                                         pCRCData->mnOffset = TAS2557_YRAM5_START_REG;
1007                                         pCRCData->mnLen = len - (TAS2557_YRAM5_START_REG - nReg);
1008                                         nResult = 1;
1009                                 }
1010                         }
1011                 }
1012         } else
1013                 nResult = 0;
1015         return nResult;
1018 static int isInBlockYRAM(struct tas2557_priv *pTAS2557, struct TYCRC *pCRCData,
1019         unsigned char nBook, unsigned char nPage, unsigned char nReg, unsigned char len)
1021         int nResult;
1023         if (nBook == TAS2557_YRAM_BOOK1) {
1024                 if (nPage < TAS2557_YRAM2_START_PAGE)
1025                         nResult = 0;
1026                 else if (nPage <= TAS2557_YRAM2_END_PAGE) {
1027                         if (nReg > TAS2557_YRAM2_END_REG)
1028                                 nResult = 0;
1029                         else if (nReg >= TAS2557_YRAM2_START_REG) {
1030                                 pCRCData->mnOffset = nReg;
1031                                 pCRCData->mnLen = len;
1032                                 nResult = 1;
1033                         } else {
1034                                 if ((nReg + len) < TAS2557_YRAM2_START_REG)
1035                                         nResult = 0;
1036                                 else {
1037                                         pCRCData->mnOffset = TAS2557_YRAM2_START_REG;
1038                                         pCRCData->mnLen = nReg + len - TAS2557_YRAM2_START_REG;
1039                                         nResult = 1;
1040                                 }
1041                         }
1042                 } else
1043                         nResult = 0;
1044         } else if (nBook == TAS2557_YRAM_BOOK2) {
1045                 if (nPage < TAS2557_YRAM4_START_PAGE)
1046                         nResult = 0;
1047                 else if (nPage <= TAS2557_YRAM4_END_PAGE) {
1048                         if (nReg > TAS2557_YRAM2_END_REG)
1049                                 nResult = 0;
1050                         else if (nReg >= TAS2557_YRAM2_START_REG) {
1051                                 pCRCData->mnOffset = nReg;
1052                                 pCRCData->mnLen = len;
1053                                 nResult = 1;
1054                         } else {
1055                                 if ((nReg + len) < TAS2557_YRAM2_START_REG)
1056                                         nResult = 0;
1057                                 else {
1058                                         pCRCData->mnOffset = TAS2557_YRAM2_START_REG;
1059                                         pCRCData->mnLen = nReg + len - TAS2557_YRAM2_START_REG;
1060                                         nResult = 1;
1061                                 }
1062                         }
1063                 } else
1064                         nResult = 0;
1065         } else
1066                 nResult = 0;
1068         return nResult;
1072 static int isYRAM(struct tas2557_priv *pTAS2557, struct TYCRC *pCRCData,
1073         unsigned char nBook, unsigned char nPage, unsigned char nReg, unsigned char len)
1075         int nResult;
1077         nResult = isInPageYRAM(pTAS2557, pCRCData, nBook, nPage, nReg, len);
1079         if (nResult == 0)
1080                 nResult = isInBlockYRAM(pTAS2557, pCRCData, nBook, nPage, nReg, len);
1082         return nResult;
1085 /*
1086  * crc8 - calculate a crc8 over the given input data.
1087  *
1088  * table: crc table used for calculation.
1089  * pdata: pointer to data buffer.
1090  * nbytes: number of bytes in data buffer.
1091  * crc: previous returned crc8 value.
1092  */
1093 static u8 ti_crc8(const u8 table[CRC8_TABLE_SIZE], u8 *pdata, size_t nbytes, u8 crc)
1095         /* loop over the buffer data */
1096         while (nbytes-- > 0)
1097                 crc = table[(crc ^ *pdata++) & 0xff];
1099         return crc;
1102 static int doSingleRegCheckSum(struct tas2557_priv *pTAS2557, 
1103         unsigned char nBook, unsigned char nPage, unsigned char nReg, unsigned char nValue)
1105         int nResult = 0;
1106         struct TYCRC sCRCData;
1107         unsigned int nData1 = 0;
1109         if ((nBook == TAS2557_BOOK_ID(TAS2557_SA_COEFF_SWAP_REG))
1110                 && (nPage == TAS2557_PAGE_ID(TAS2557_SA_COEFF_SWAP_REG))
1111                 && (nReg >= TAS2557_PAGE_REG(TAS2557_SA_COEFF_SWAP_REG))
1112                 && (nReg <= (TAS2557_PAGE_REG(TAS2557_SA_COEFF_SWAP_REG) + 4))) {
1113                 /* DSP swap command, pass */
1114                 nResult = 0;
1115                 goto end;
1116         }
1118         nResult = isYRAM(pTAS2557, &sCRCData, nBook, nPage, nReg, 1);
1119         if (nResult == 1) {
1120                 nResult = pTAS2557->read(pTAS2557, TAS2557_REG(nBook, nPage, nReg), &nData1);
1121                 if (nResult < 0)
1122                         goto end;
1124                 if (nData1 != nValue) {
1125                         dev_err(pTAS2557->dev, "error2 (line %d),B[0x%x]P[0x%x]R[0x%x] W[0x%x], R[0x%x]\n",
1126                                 __LINE__, nBook, nPage, nReg, nValue, nData1);
1127                         nResult = -EAGAIN;
1128                         goto end;
1129                 }
1131                 nResult = ti_crc8(crc8_lookup_table, &nValue, 1, 0);
1132         }
1134 end:
1136         return nResult;
1139 static int doMultiRegCheckSum(struct tas2557_priv *pTAS2557, 
1140         unsigned char nBook, unsigned char nPage, unsigned char nReg, unsigned int len)
1142         int nResult = 0, i;
1143         unsigned char nCRCChkSum = 0;
1144         unsigned char nBuf1[128];
1145         struct TYCRC TCRCData;
1147         if ((nReg + len-1) > 127) {
1148                 nResult = -EINVAL;
1149                 dev_err(pTAS2557->dev, "firmware error\n");
1150                 goto end;
1151         }
1153         if ((nBook == TAS2557_BOOK_ID(TAS2557_SA_COEFF_SWAP_REG))
1154                 && (nPage == TAS2557_PAGE_ID(TAS2557_SA_COEFF_SWAP_REG))
1155                 && (nReg == TAS2557_PAGE_REG(TAS2557_SA_COEFF_SWAP_REG))
1156                 && (len == 4)) {
1157                 /* DSP swap command, pass */
1158                 nResult = 0;
1159                 goto end;
1160         }
1162         nResult = isYRAM(pTAS2557, &TCRCData, nBook, nPage, nReg, len);
1163         if (nResult == 1) {
1164                 if (len == 1) {
1165                         dev_err(pTAS2557->dev, "firmware error\n");
1166                         nResult = -EINVAL;
1167                         goto end;
1168                 } else {
1169                         nResult = pTAS2557->bulk_read(pTAS2557, TAS2557_REG(nBook, nPage, TCRCData.mnOffset), nBuf1, TCRCData.mnLen);
1170                         if (nResult < 0)
1171                                 goto end;
1173                         for (i = 0; i < TCRCData.mnLen; i++) {
1174                                 if ((nBook == TAS2557_BOOK_ID(TAS2557_SA_COEFF_SWAP_REG))
1175                                         && (nPage == TAS2557_PAGE_ID(TAS2557_SA_COEFF_SWAP_REG))
1176                                         && ((i + TCRCData.mnOffset)
1177                                                 >= TAS2557_PAGE_REG(TAS2557_SA_COEFF_SWAP_REG))
1178                                         && ((i + TCRCData.mnOffset)
1179                                                 <= (TAS2557_PAGE_REG(TAS2557_SA_COEFF_SWAP_REG) + 4))) {
1180                                         /* DSP swap command, bypass */
1181                                         continue;
1182                                 } else
1183                                         nCRCChkSum += ti_crc8(crc8_lookup_table, &nBuf1[i], 1, 0);
1184                         }
1186                         nResult = nCRCChkSum;
1187                 }
1188         }
1190 end:
1192         return nResult;
1195 static int tas2557_load_block(struct tas2557_priv *pTAS2557, struct TBlock *pBlock)
1197         int nResult = 0;
1198         unsigned int nCommand = 0;
1199         unsigned char nBook;
1200         unsigned char nPage;
1201         unsigned char nOffset;
1202         unsigned char nData;
1203         unsigned int nLength;
1204         unsigned int nSleep;
1205         unsigned char nCRCChkSum = 0;
1206         unsigned int nValue1;
1207         int nRetry = 6;
1208         unsigned char *pData = pBlock->mpData;
1210         dev_dbg(pTAS2557->dev, "TAS2557 load block: Type = %d, commands = %d\n",
1211                 pBlock->mnType, pBlock->mnCommands);
1212 start:
1213         if (pBlock->mbPChkSumPresent) {
1214                 nResult = pTAS2557->write(pTAS2557, TAS2557_CRC_RESET_REG, 1);
1215                 if (nResult < 0)
1216                         goto end;
1217         }
1219         if (pBlock->mbYChkSumPresent)
1220                 nCRCChkSum = 0;
1222         nCommand = 0;
1224         while (nCommand < pBlock->mnCommands) {
1225                 pData = pBlock->mpData + nCommand * 4;
1227                 nBook = pData[0];
1228                 nPage = pData[1];
1229                 nOffset = pData[2];
1230                 nData = pData[3];
1232                 nCommand++;
1234                 if (nOffset <= 0x7F) {
1235                         nResult = pTAS2557->write(pTAS2557, TAS2557_REG(nBook, nPage, nOffset), nData);
1236                         if (nResult < 0)
1237                                 goto end;
1238                         if (pBlock->mbYChkSumPresent) {
1239                                 nResult = doSingleRegCheckSum(pTAS2557, nBook, nPage, nOffset, nData);
1240                                 if (nResult < 0)
1241                                         goto check;
1242                                 nCRCChkSum += (unsigned char)nResult;
1243                         }
1244                 } else if (nOffset == 0x81) {
1245                         nSleep = (nBook << 8) + nPage;
1246                         msleep(nSleep);
1247                 } else if (nOffset == 0x85) {
1248                         pData += 4;
1249                         nLength = (nBook << 8) + nPage;
1250                         nBook = pData[0];
1251                         nPage = pData[1];
1252                         nOffset = pData[2];
1253                         if (nLength > 1) {
1254                                 nResult = pTAS2557->bulk_write(pTAS2557, TAS2557_REG(nBook, nPage, nOffset), pData + 3, nLength);
1255                                 if (nResult < 0)
1256                                         goto end;
1257                                 if (pBlock->mbYChkSumPresent) {
1258                                         nResult = doMultiRegCheckSum(pTAS2557, nBook, nPage, nOffset, nLength);
1259                                         if (nResult < 0)
1260                                                 goto check;
1261                                         nCRCChkSum += (unsigned char)nResult;
1262                                 }
1263                         } else {
1264                                 nResult = pTAS2557->write(pTAS2557, TAS2557_REG(nBook, nPage, nOffset), pData[3]);
1265                                 if (nResult < 0)
1266                                         goto end;
1267                                 if (pBlock->mbYChkSumPresent) {
1268                                         nResult = doSingleRegCheckSum(pTAS2557, nBook, nPage, nOffset, pData[3]);
1269                                         if (nResult < 0)
1270                                                 goto check;
1271                                         nCRCChkSum += (unsigned char)nResult;
1272                                 }
1273                         }
1275                         nCommand++;
1277                         if (nLength >= 2)
1278                                 nCommand += ((nLength - 2) / 4) + 1;
1279                 }
1280         }
1281         if (pBlock->mbPChkSumPresent) {
1282                 nResult = pTAS2557->read(pTAS2557, TAS2557_CRC_CHECKSUM_REG, &nValue1);
1283                 if (nResult < 0)
1284                         goto end;
1285                 if ((nValue1&0xff) != pBlock->mnPChkSum) {
1286                         dev_err(pTAS2557->dev, "Block PChkSum Error: FW = 0x%x, Reg = 0x%x\n",
1287                                 pBlock->mnPChkSum, (nValue1&0xff));
1288                         nResult = -EAGAIN;
1289                         goto check;
1290                 }
1292                 nResult = 0;
1293                 dev_dbg(pTAS2557->dev, "Block[0x%x] PChkSum match\n", pBlock->mnType);
1294         }
1296         if (pBlock->mbYChkSumPresent) {
1297                 if (nCRCChkSum != pBlock->mnYChkSum) {
1298                         dev_err(pTAS2557->dev, "Block YChkSum Error: FW = 0x%x, YCRC = 0x%x\n",
1299                                 pBlock->mnYChkSum, nCRCChkSum);
1300                         nResult = -EAGAIN;
1301                         goto check;
1302                 }
1303                 nResult = 0;
1304                 dev_dbg(pTAS2557->dev, "Block[0x%x] YChkSum match\n", pBlock->mnType);
1305         }
1307 check:
1308         if (nResult == -EAGAIN) {
1309                 nRetry--;
1310                 if (nRetry > 0)
1311                         goto start;
1312         }
1314 end:
1315         if (nResult < 0) {
1316                 dev_err(pTAS2557->dev, "Block (%d) load error\n",
1317                                 pBlock->mnType);
1318         }
1319         return nResult;
1322 static int tas2557_load_data(struct tas2557_priv *pTAS2557, struct TData *pData, unsigned int nType)
1324         int nResult = 0;
1325         unsigned int nBlock;
1326         struct TBlock *pBlock;
1328         dev_dbg(pTAS2557->dev,
1329                 "TAS2557 load data: %s, Blocks = %d, Block Type = %d\n", pData->mpName, pData->mnBlocks, nType);
1331         for (nBlock = 0; nBlock < pData->mnBlocks; nBlock++) {
1332                 pBlock = &(pData->mpBlocks[nBlock]);
1333                 if (pBlock->mnType == nType) {
1334                         nResult = tas2557_load_block(pTAS2557, pBlock);
1335                         if (nResult < 0)
1336                                 break;
1337                 }
1338         }
1340         return nResult;
1343 static int tas2557_load_configuration(struct tas2557_priv *pTAS2557,
1344         unsigned int nConfiguration, bool bLoadSame)
1346         int nResult = 0;
1347         struct TConfiguration *pCurrentConfiguration = NULL;
1348         struct TConfiguration *pNewConfiguration = NULL;
1350         dev_dbg(pTAS2557->dev, "tas2557_load_configuration: %d\n", nConfiguration);
1352         if ((!pTAS2557->mpFirmware->mpPrograms) ||
1353                 (!pTAS2557->mpFirmware->mpConfigurations)) {
1354                 dev_err(pTAS2557->dev, "Firmware not loaded\n");
1355                 nResult = 0;
1356                 goto end;
1357         }
1359         if (nConfiguration >= pTAS2557->mpFirmware->mnConfigurations) {
1360                 dev_err(pTAS2557->dev, "Configuration %d doesn't exist\n",
1361                         nConfiguration);
1362                 nResult = 0;
1363                 goto end;
1364         }
1366         if ((nConfiguration == pTAS2557->mnCurrentConfiguration) && (!bLoadSame)) {
1367                 dev_info(pTAS2557->dev, "Configuration %d is already loaded\n",
1368                         nConfiguration);
1369                 nResult = 0;
1370                 goto end;
1371         }
1373         pCurrentConfiguration =
1374                 &(pTAS2557->mpFirmware->mpConfigurations[pTAS2557->mnCurrentConfiguration]);
1375         pNewConfiguration =
1376                 &(pTAS2557->mpFirmware->mpConfigurations[nConfiguration]);
1377         if (pNewConfiguration->mnProgram != pCurrentConfiguration->mnProgram) {
1378                 dev_err(pTAS2557->dev, "Configuration %d, %s doesn't share the same program as current %d\n",
1379                         nConfiguration, pNewConfiguration->mpName, pCurrentConfiguration->mnProgram);
1380                 nResult = 0;
1381                 goto end;
1382         }
1384         if (pNewConfiguration->mnPLL >= pTAS2557->mpFirmware->mnPLLs) {
1385                 dev_err(pTAS2557->dev, "Configuration %d, %s doesn't have a valid PLL index %d\n",
1386                         nConfiguration, pNewConfiguration->mpName, pNewConfiguration->mnPLL);
1387                 nResult = 0;
1388                 goto end;
1389         }
1391         if (pTAS2557->mbPowerUp) {
1392                 nResult = tas2557_load_coefficient(pTAS2557, pTAS2557->mnCurrentConfiguration, nConfiguration, true);
1393                 pTAS2557->mbLoadConfigurationPrePowerUp = false;
1394         } else {
1395                 dev_dbg(pTAS2557->dev,
1396                         "TAS2557 was powered down, will load coefficient when power up\n");
1397                 pTAS2557->mbLoadConfigurationPrePowerUp = true;
1398                 pTAS2557->mnNewConfiguration = nConfiguration;
1399         }
1401 end:
1403         if (nResult < 0)
1404                 failsafe(pTAS2557);
1406         return nResult;
1409 int tas2557_set_config(struct tas2557_priv *pTAS2557, int config)
1411         struct TConfiguration *pConfiguration;
1412         struct TProgram *pProgram;
1413         unsigned int nProgram = pTAS2557->mnCurrentProgram;
1414         unsigned int nConfiguration = config;
1415         int nResult = 0;
1417         if ((!pTAS2557->mpFirmware->mpPrograms) ||
1418                 (!pTAS2557->mpFirmware->mpConfigurations)) {
1419                 dev_err(pTAS2557->dev, "Firmware not loaded\n");
1420                 nResult = -EINVAL;
1421                 goto end;
1422         }
1424         if (nConfiguration >= pTAS2557->mpFirmware->mnConfigurations) {
1425                 dev_err(pTAS2557->dev, "Configuration %d doesn't exist\n",
1426                         nConfiguration);
1427                 nResult = -EINVAL;
1428                 goto end;
1429         }
1431         pConfiguration = &(pTAS2557->mpFirmware->mpConfigurations[nConfiguration]);
1432         pProgram = &(pTAS2557->mpFirmware->mpPrograms[nProgram]);
1434         if (nProgram != pConfiguration->mnProgram) {
1435                 dev_err(pTAS2557->dev,
1436                         "Configuration %d, %s with Program %d isn't compatible with existing Program %d, %s\n",
1437                         nConfiguration, pConfiguration->mpName, pConfiguration->mnProgram,
1438                         nProgram, pProgram->mpName);
1439                 nResult = -EINVAL;
1440                 goto end;
1441         }
1443         nResult = tas2557_load_configuration(pTAS2557, nConfiguration, false);
1445 end:
1447         return nResult;
1450 void tas2557_clear_firmware(struct TFirmware *pFirmware)
1452         unsigned int n, nn;
1454         if (!pFirmware)
1455                 return;
1457         kfree(pFirmware->mpDescription);
1459         if (pFirmware->mpPLLs != NULL) {
1460                 for (n = 0; n < pFirmware->mnPLLs; n++) {
1461                         kfree(pFirmware->mpPLLs[n].mpDescription);
1462                         kfree(pFirmware->mpPLLs[n].mBlock.mpData);
1463                 }
1464                 kfree(pFirmware->mpPLLs);
1465         }
1467         if (pFirmware->mpPrograms != NULL) {
1468                 for (n = 0; n < pFirmware->mnPrograms; n++) {
1469                         kfree(pFirmware->mpPrograms[n].mpDescription);
1470                         kfree(pFirmware->mpPrograms[n].mData.mpDescription);
1471                         for (nn = 0; nn < pFirmware->mpPrograms[n].mData.mnBlocks; nn++)
1472                                 kfree(pFirmware->mpPrograms[n].mData.mpBlocks[nn].mpData);
1473                         kfree(pFirmware->mpPrograms[n].mData.mpBlocks);
1474                 }
1475                 kfree(pFirmware->mpPrograms);
1476         }
1478         if (pFirmware->mpConfigurations != NULL) {
1479                 for (n = 0; n < pFirmware->mnConfigurations; n++) {
1480                         kfree(pFirmware->mpConfigurations[n].mpDescription);
1481                         kfree(pFirmware->mpConfigurations[n].mData.mpDescription);
1482                         for (nn = 0; nn < pFirmware->mpConfigurations[n].mData.mnBlocks; nn++)
1483                                 kfree(pFirmware->mpConfigurations[n].mData.mpBlocks[nn].mpData);
1484                         kfree(pFirmware->mpConfigurations[n].mData.mpBlocks);
1485                 }
1486                 kfree(pFirmware->mpConfigurations);
1487         }
1489         if (pFirmware->mpCalibrations != NULL) {
1490                 for (n = 0; n < pFirmware->mnCalibrations; n++) {
1491                         kfree(pFirmware->mpCalibrations[n].mpDescription);
1492                         kfree(pFirmware->mpCalibrations[n].mData.mpDescription);
1493                         for (nn = 0; nn < pFirmware->mpCalibrations[n].mData.mnBlocks; nn++)
1494                                 kfree(pFirmware->mpCalibrations[n].mData.mpBlocks[nn].mpData);
1495                         kfree(pFirmware->mpCalibrations[n].mData.mpBlocks);
1496                 }
1497                 kfree(pFirmware->mpCalibrations);
1498         }
1500         memset(pFirmware, 0x00, sizeof(struct TFirmware));
1503 static int tas2557_load_calibration(struct tas2557_priv *pTAS2557,      char *pFileName)
1505         int nResult = 0;
1506 /*
1507 *       int nFile;
1508 *       mm_segment_t fs;
1509 *       unsigned char pBuffer[1000];
1510 *       int nSize = 0;
1512 *       dev_dbg(pTAS2557->dev, "%s:\n", __func__);
1514 *       fs = get_fs();
1515 *       set_fs(KERNEL_DS);
1516 *       nFile = sys_open(pFileName, O_RDONLY, 0);
1518 *       dev_info(pTAS2557->dev, "TAS2557 calibration file = %s, handle = %d\n",
1519 *               pFileName, nFile);
1521 *       if (nFile >= 0) {
1522 *               nSize = sys_read(nFile, pBuffer, 1000);
1523 *               sys_close(nFile);
1524 *       } else {
1525 *               dev_err(pTAS2557->dev, "TAS2557 cannot open calibration file: %s\n",
1526 *                       pFileName);
1527 *       }
1529 *       set_fs(fs);
1531 *       if (!nSize)
1532 *               goto end;
1534 *       tas2557_clear_firmware(pTAS2557->mpCalFirmware);
1535 *       dev_info(pTAS2557->dev, "TAS2557 calibration file size = %d\n", nSize);
1536 *       nResult = fw_parse(pTAS2557, pTAS2557->mpCalFirmware, pBuffer, nSize);
1538 *       if (nResult)
1539 *               dev_err(pTAS2557->dev, "TAS2557 calibration file is corrupt\n");
1540 *       else
1541 *               dev_info(pTAS2557->dev, "TAS2557 calibration: %d calibrations\n",
1542 *                       pTAS2557->mpCalFirmware->mnCalibrations);
1544 *end:
1545 **/
1546         return nResult;
1549 void tas2557_fw_ready(const struct firmware *pFW, void *pContext)
1551         struct tas2557_priv *pTAS2557 = (struct tas2557_priv *) pContext;
1552         int nResult;
1553         unsigned int nProgram = 0;
1554         unsigned int nSampleRate = 0;
1556         dev_info(pTAS2557->dev, "%s:\n", __func__);
1558         if (unlikely(!pFW) || unlikely(!pFW->data)) {
1559                 dev_err(pTAS2557->dev, "%s firmware is not loaded.\n",
1560                         TAS2557_FW_NAME);
1561                 goto end;
1562         }
1564         if (pTAS2557->mpFirmware->mpConfigurations) {
1565                 nProgram = pTAS2557->mnCurrentProgram;
1566                 nSampleRate = pTAS2557->mnCurrentSampleRate;
1567                 dev_dbg(pTAS2557->dev, "clear current firmware\n");
1568                 tas2557_clear_firmware(pTAS2557->mpFirmware);
1569         }
1571         nResult = fw_parse(pTAS2557, pTAS2557->mpFirmware, (unsigned char *)(pFW->data), pFW->size);
1572         release_firmware(pFW);
1573         if (nResult < 0) {
1574                 dev_err(pTAS2557->dev, "firmware is corrupt\n");
1575                 goto end;
1576         }
1578         if (!pTAS2557->mpFirmware->mnPrograms) {
1579                 dev_err(pTAS2557->dev, "firmware contains no programs\n");
1580                 nResult = -EINVAL;
1581                 goto end;
1582         }
1584         if (!pTAS2557->mpFirmware->mnConfigurations) {
1585                 dev_err(pTAS2557->dev, "firmware contains no configurations\n");
1586                 nResult = -EINVAL;
1587                 goto end;
1588         }
1590         if (nProgram >= pTAS2557->mpFirmware->mnPrograms) {
1591                 dev_info(pTAS2557->dev,
1592                         "no previous program, set to default\n");
1593                 nProgram = 0;
1594         }
1596         pTAS2557->mnCurrentSampleRate = nSampleRate;
1598         nResult = tas2557_set_program(pTAS2557, nProgram, -1);
1600 end:
1601         return;
1604 int tas2557_set_program(struct tas2557_priv *pTAS2557, unsigned int nProgram, int nConfig)
1606         struct TProgram *pProgram;
1607         unsigned int nConfiguration = 0;
1608         unsigned int nSampleRate = 0;
1609         unsigned char nGain;
1610         bool bFound = false;
1611         int nResult = 0;
1613         if ((!pTAS2557->mpFirmware->mpPrograms) ||
1614                 (!pTAS2557->mpFirmware->mpConfigurations)) {
1615                 dev_err(pTAS2557->dev, "Firmware not loaded\n");
1616                 nResult = 0;
1617                 goto end;
1618         }
1620         if (nProgram >= pTAS2557->mpFirmware->mnPrograms) {
1621                 dev_err(pTAS2557->dev, "TAS2557: Program %d doesn't exist\n",
1622                         nProgram);
1623                 nResult = 0;
1624                 goto end;
1625         }
1627         if (nConfig < 0) {
1628                 nConfiguration = 0;
1629                 nSampleRate = pTAS2557->mnCurrentSampleRate;
1630                 while (!bFound && (nConfiguration < pTAS2557->mpFirmware->mnConfigurations)) {
1631                         if (pTAS2557->mpFirmware->mpConfigurations[nConfiguration].mnProgram == nProgram) {
1632                                 if (nSampleRate == 0) {
1633                                         bFound = true;
1634                                         dev_info(pTAS2557->dev, "find default configuration %d\n", nConfiguration);
1635                                 } else if (nSampleRate == pTAS2557->mpFirmware->mpConfigurations[nConfiguration].mnSamplingRate) {
1636                                         bFound = true;
1637                                         dev_info(pTAS2557->dev, "find matching configuration %d\n", nConfiguration);
1638                                 } else {
1639                                         nConfiguration++;
1640                                 }
1641                         } else {
1642                                 nConfiguration++;
1643                         }
1644                 }
1645                 if (!bFound) {
1646                         dev_err(pTAS2557->dev,
1647                                 "Program %d, no valid configuration found for sample rate %d, ignore\n",
1648                                 nProgram, nSampleRate);
1649                         nResult = 0;
1650                         goto end;
1651                 }
1652         } else {
1653                 if (pTAS2557->mpFirmware->mpConfigurations[nConfig].mnProgram != nProgram) {
1654                         dev_err(pTAS2557->dev, "%s, configuration program doesn't match\n", __func__);
1655                         nResult = 0;
1656                         goto end;
1657                 }
1658                 nConfiguration = nConfig;
1659         }
1661         pProgram = &(pTAS2557->mpFirmware->mpPrograms[nProgram]);
1662         if (pTAS2557->mbPowerUp) {
1663                 dev_info(pTAS2557->dev,
1664                         "device powered up, power down to load program %d (%s)\n",
1665                         nProgram, pProgram->mpName);
1666                 if (hrtimer_active(&pTAS2557->mtimer))
1667                         hrtimer_cancel(&pTAS2557->mtimer);
1669                 if (pProgram->mnAppMode == TAS2557_APP_TUNINGMODE)
1670                         pTAS2557->enableIRQ(pTAS2557, false);
1672                 nResult = tas2557_dev_load_data(pTAS2557, p_tas2557_mute_DSP_down_data);
1673                 if (nResult < 0)
1674                         goto end;
1675         }
1677         pTAS2557->hw_reset(pTAS2557);
1678         nResult = pTAS2557->write(pTAS2557, TAS2557_SW_RESET_REG, 0x01);
1679         if (nResult < 0)
1680                 goto end;
1681         msleep(1);
1682         nResult = tas2557_load_default(pTAS2557);
1683         if (nResult < 0)
1684                 goto end;
1686         dev_info(pTAS2557->dev, "load program %d (%s)\n", nProgram, pProgram->mpName);
1687         nResult = tas2557_load_data(pTAS2557, &(pProgram->mData), TAS2557_BLOCK_PGM_DEV_A);
1688         if (nResult < 0)
1689                 goto end;
1690         pTAS2557->mnCurrentProgram = nProgram;
1692         nResult = tas2557_get_DAC_gain(pTAS2557, &nGain);
1693         if (nResult < 0)
1694                 goto end;
1695         pTAS2557->mnDevGain = nGain;
1696         pTAS2557->mnDevCurrentGain = nGain;
1698         nResult = tas2557_load_coefficient(pTAS2557, -1, nConfiguration, false);
1699         if (nResult < 0)
1700                 goto end;
1702         if (pTAS2557->mbPowerUp) {
1703                 pTAS2557->clearIRQ(pTAS2557);
1704                 dev_dbg(pTAS2557->dev, "device powered up, load startup\n");
1705                 nResult = tas2557_dev_load_data(pTAS2557, p_tas2557_startup_data);
1706                 if (nResult < 0)
1707                         goto end;
1708                 dev_dbg(pTAS2557->dev,
1709                         "device powered up, load unmute\n");
1710                 nResult = tas2557_dev_load_data(pTAS2557, p_tas2557_unmute_data);
1711                 if (nResult < 0)
1712                         goto end;
1714                 if (pProgram->mnAppMode == TAS2557_APP_TUNINGMODE) {
1715                         pTAS2557->enableIRQ(pTAS2557, true);
1716                         if (!hrtimer_active(&pTAS2557->mtimer)) {
1717                                 pTAS2557->mnDieTvReadCounter = 0;
1718                                 hrtimer_start(&pTAS2557->mtimer,
1719                                         ns_to_ktime((u64)LOW_TEMPERATURE_CHECK_PERIOD * NSEC_PER_MSEC), HRTIMER_MODE_REL);
1720                         }
1721                 }
1722         }
1724 end:
1726         if (nResult < 0)
1727                 failsafe(pTAS2557);
1729         return nResult;
1732 int tas2557_set_calibration(struct tas2557_priv *pTAS2557, int nCalibration)
1734         struct TCalibration *pCalibration = NULL;
1735         struct TProgram *pProgram;
1736         int nResult = 0;
1738         if ((!pTAS2557->mpFirmware->mpPrograms)
1739                 || (!pTAS2557->mpFirmware->mpConfigurations)) {
1740                 dev_err(pTAS2557->dev, "Firmware not loaded\n\r");
1741                 nResult = 0;
1742                 goto end;
1743         }
1745         if (nCalibration == 0x00FF) {
1746                 dev_info(pTAS2557->dev, "load new calibration file %s\n", TAS2557_CAL_NAME);
1747                 nResult = tas2557_load_calibration(pTAS2557, TAS2557_CAL_NAME);
1748                 if (nResult < 0)
1749                         goto end;
1750                 nCalibration = 0;
1751         }
1753         if (nCalibration >= pTAS2557->mpCalFirmware->mnCalibrations) {
1754                 dev_err(pTAS2557->dev,
1755                         "Calibration %d doesn't exist\n", nCalibration);
1756                 nResult = 0;
1757                 goto end;
1758         }
1760         pTAS2557->mnCurrentCalibration = nCalibration;
1761         pCalibration = &(pTAS2557->mpCalFirmware->mpCalibrations[nCalibration]);
1762         pProgram = &(pTAS2557->mpFirmware->mpPrograms[pTAS2557->mnCurrentProgram]);
1764         if (pProgram->mnAppMode == TAS2557_APP_TUNINGMODE) {
1765                 dev_dbg(pTAS2557->dev, "Enable: load calibration\n");
1766                 nResult = tas2557_load_data(pTAS2557, &(pCalibration->mData), TAS2557_BLOCK_CFG_COEFF_DEV_A);
1767                 if (nResult < 0)
1768                         goto end;
1769         }
1771 end:
1772         if (nResult < 0) {
1773                 tas2557_clear_firmware(pTAS2557->mpCalFirmware);
1774                 nResult = tas2557_set_program(pTAS2557, pTAS2557->mnCurrentProgram, pTAS2557->mnCurrentConfiguration);
1775         }
1777         return nResult;
1780 int tas2557_parse_dt(struct device *dev, struct tas2557_priv *pTAS2557)
1782         struct device_node *np = dev->of_node;
1783         int rc = 0, ret = 0;
1784         unsigned int value;
1786         pTAS2557->mnResetGPIO = of_get_named_gpio(np, "ti,cdc-reset-gpio", 0);
1787         if (pTAS2557->mnResetGPIO < 0) {
1788                 dev_err(pTAS2557->dev, "Looking up %s property in node %s failed %d\n",
1789                         "ti,cdc-reset-gpio", np->full_name,
1790                         pTAS2557->mnResetGPIO);
1791                 ret = -EINVAL;
1792         } else
1793                         dev_dbg(pTAS2557->dev, "ti,cdc-reset-gpio=%d\n", pTAS2557->mnResetGPIO);
1795         if (ret >= 0) {
1796                 pTAS2557->mnGpioINT = of_get_named_gpio(np, "ti,irq-gpio", 0);
1797                 if (pTAS2557->mnGpioINT < 0) {
1798                         dev_err(pTAS2557->dev, "Looking up %s property in node %s failed %d\n",
1799                                 "ti,irq-gpio", np->full_name,
1800                                 pTAS2557->mnGpioINT);
1801                         ret = -EINVAL;
1802                 } else
1803                         dev_dbg(pTAS2557->dev, "ti,irq-gpio=%d\n", pTAS2557->mnGpioINT);
1804         }
1806         if (ret >= 0) {
1807                 rc = of_property_read_u32(np, "ti,i2s-bits", &value);
1808                 if (rc) {
1809                         dev_err(pTAS2557->dev, "Looking up %s property in node %s failed %d\n",
1810                                 "ti,i2s-bits", np->full_name, rc);
1811                         ret = -EINVAL;
1812                 } else {
1813                         pTAS2557->mnI2SBits = value;
1814                         dev_dbg(pTAS2557->dev, "ti,i2s-bits=%d\n", pTAS2557->mnI2SBits);
1815                 }
1816         }
1818         return ret;
1821 MODULE_AUTHOR("Texas Instruments Inc.");
1822 MODULE_DESCRIPTION("TAS2557 common functions for Android Linux");
1823 MODULE_LICENSE("GPL v2");