update: clock error detection, calibration_re reading,
[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_CRCCHK                       0x00000200
45 #define PPC_DRIVER_CONFDEV                      0x00000300
46 #define PPC_DRIVER_CFGDEV_NONCRC        0x00000101
48 #define TAS2557_CAL_NAME    "/data/tas2557_cal.bin"
51 static int tas2557_load_calibration(struct tas2557_priv *pTAS2557,
52         char *pFileName);
53 static int tas2557_load_data(struct tas2557_priv *pTAS2557, struct TData *pData,
54         unsigned int nType);
55 static void tas2557_clear_firmware(struct TFirmware *pFirmware);
56 static int tas2557_load_block(struct tas2557_priv *pTAS2557, struct TBlock *pBlock);
57 static int tas2557_load_configuration(struct tas2557_priv *pTAS2557,
58         unsigned int nConfiguration, bool bLoadSame);
60 #define TAS2557_UDELAY 0xFFFFFFFE
61 #define TAS2557_MDELAY 0xFFFFFFFD
63 #define TAS2557_BLOCK_PLL                               0x00
64 #define TAS2557_BLOCK_PGM_ALL                   0x0d
65 #define TAS2557_BLOCK_PGM_DEV_A                 0x01
66 #define TAS2557_BLOCK_PGM_DEV_B                 0x08
67 #define TAS2557_BLOCK_CFG_COEFF_DEV_A   0x03
68 #define TAS2557_BLOCK_CFG_COEFF_DEV_B   0x0a
69 #define TAS2557_BLOCK_CFG_PRE_DEV_A             0x04
70 #define TAS2557_BLOCK_CFG_PRE_DEV_B             0x0b
71 #define TAS2557_BLOCK_CFG_POST                  0x05
72 #define TAS2557_BLOCK_CFG_POST_POWER    0x06
74 static unsigned int p_tas2557_default_data[] = {
75         TAS2557_SAR_ADC2_REG, 0x05,     /* enable SAR ADC */
76         TAS2557_CLK_ERR_CTRL2, 0x21,    /*clk1:clock hysteresis, 0.34ms; clock halt, 22ms*/
77         TAS2557_CLK_ERR_CTRL3, 0x21,    /*clk2: rampDown 15dB/us, clock hysteresis, 10.66us; clock halt, 22ms */
78         TAS2557_SAFE_GUARD_REG, TAS2557_SAFE_GUARD_PATTERN,     /* safe guard */
79         0xFFFFFFFF, 0xFFFFFFFF
80 };
82 static unsigned int p_tas2557_irq_config[] = {
83         TAS2557_CLK_HALT_REG, 0x71,     /* enable clk halt detect2 interrupt */
84         TAS2557_INT_GEN1_REG, 0x11,     /* enable spk OC and OV */
85         TAS2557_INT_GEN2_REG, 0x11,     /* enable clk err1 and die OT */
86         TAS2557_INT_GEN3_REG, 0x11,     /* enable clk err2 and brownout */
87         TAS2557_INT_GEN4_REG, 0x01,     /* disable SAR, enable clk halt */
88         TAS2557_GPIO4_PIN_REG, 0x07,    /* set GPIO4 as int1, default */
89         TAS2557_INT_MODE_REG, 0x80,     /* active high until INT_STICKY_1 and INT_STICKY_2 are read to be cleared. */
90         0xFFFFFFFF, 0xFFFFFFFF
91 };
93 static unsigned int p_tas2557_startup_data[] = {
94         TAS2557_GPI_PIN_REG, 0x15,      /* enable DIN, MCLK, CCI */
95         TAS2557_GPIO1_PIN_REG, 0x01,    /* enable BCLK */
96         TAS2557_GPIO2_PIN_REG, 0x01,    /* enable WCLK */
97         TAS2557_POWER_CTRL2_REG, 0xA0,   /* Class-D, Boost power up */
98         TAS2557_POWER_CTRL2_REG, 0xA3,   /* Class-D, Boost, IV sense power up */
99         TAS2557_POWER_CTRL1_REG, 0xF8,   /* PLL, DSP, clock dividers power up */
100         TAS2557_UDELAY, 2000,           /* delay */
101         TAS2557_CLK_ERR_CTRL, 0x0b,     /* enable clock error detection */
102         0xFFFFFFFF, 0xFFFFFFFF
103 };
105 static unsigned int p_tas2557_unmute_data[] = {
106         TAS2557_MUTE_REG, 0x00,          /* unmute */
107         TAS2557_SOFT_MUTE_REG, 0x00,     /* soft unmute */
108         0xFFFFFFFF, 0xFFFFFFFF
109 };
111 static unsigned int p_tas2557_shutdown_data[] = {
112         TAS2557_CLK_ERR_CTRL, 0x00,      /* disable clock error detection */
113         TAS2557_SOFT_MUTE_REG, 0x01,     /* soft mute */
114         TAS2557_UDELAY, 10000,           /* delay 10ms */
115         TAS2557_MUTE_REG, 0x03,          /* mute */
116         TAS2557_POWER_CTRL1_REG, 0x60,   /* DSP power down */
117         TAS2557_UDELAY, 2000,            /* delay 2ms */
118         TAS2557_POWER_CTRL2_REG, 0x00,   /* Class-D, Boost power down */
119         TAS2557_POWER_CTRL1_REG, 0x00,   /* all power down */
120         TAS2557_GPIO1_PIN_REG, 0x00,    /* disable BCLK */
121         TAS2557_GPIO2_PIN_REG, 0x00,    /* disable WCLK */
122         TAS2557_GPI_PIN_REG, 0x00,      /* disable DIN, MCLK, CCI */
123         0xFFFFFFFF, 0xFFFFFFFF
124 };
126 static int tas2557_dev_load_data(struct tas2557_priv *pTAS2557,
127         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         int nResult = 0;
231         unsigned char nBuf[4];
232         int temp;
234         if (!pTAS2557->mpFirmware->mnConfigurations) {
235                 dev_err(pTAS2557->dev, "%s, firmware not loaded\n", __func__);
236                 goto end;
237         }
239         if (!pTAS2557->mbPowerUp) {
240                 dev_err(pTAS2557->dev, "%s, device not powered on\n", __func__);
241                 goto end;
242         }
244         nResult = pTAS2557->bulk_read(pTAS2557, TAS2557_DIE_TEMP_REG, nBuf, 4);
245         if (nResult >= 0) {
246                 temp = ((int)nBuf[0] << 24) | ((int)nBuf[1] << 16) | ((int)nBuf[2] << 8) | nBuf[3];
247                 *pTemperature = temp;
248         }
250 end:
252         return nResult;
255 int tas2557_load_platdata(struct tas2557_priv *pTAS2557)
257         int nResult = 0;
259         if (gpio_is_valid(pTAS2557->mnGpioINT)) {
260                 nResult = tas2557_configIRQ(pTAS2557);
261                 if (nResult < 0)
262                         goto end;
263         }
265         nResult = tas2557_set_bit_rate(pTAS2557, pTAS2557->mnI2SBits);
267 end:
269         return nResult;
272 int tas2557_load_default(struct tas2557_priv *pTAS2557)
274         int nResult = 0;
276         nResult = tas2557_dev_load_data(pTAS2557, p_tas2557_default_data);
277         if (nResult < 0)
278                 goto end;
280         nResult = tas2557_load_platdata(pTAS2557);
281         if (nResult < 0)
282                 goto end;
284         /* enable DOUT tri-state for extra BCLKs */
285         nResult = pTAS2557->update_bits(pTAS2557, TAS2557_ASI1_DAC_FORMAT_REG, 0x01, 0x01);
286 end:
288         return nResult;
291 static void failsafe(struct tas2557_priv *pTAS2557)
293         dev_err(pTAS2557->dev, "%s\n", __func__);
294         pTAS2557->mnErrCode |= ERROR_FAILSAFE;
295         if (hrtimer_active(&pTAS2557->mtimer))
296                 hrtimer_cancel(&pTAS2557->mtimer);
297         pTAS2557->enableIRQ(pTAS2557, false);
298         tas2557_dev_load_data(pTAS2557, p_tas2557_shutdown_data);
299         pTAS2557->mbPowerUp = false;
300         pTAS2557->hw_reset(pTAS2557);
301         pTAS2557->write(pTAS2557, TAS2557_SW_RESET_REG, 0x01);
302         udelay(1000);
303         pTAS2557->write(pTAS2557, TAS2557_SPK_CTRL_REG, 0x04);
304         if (pTAS2557->mpFirmware != NULL)
305                 tas2557_clear_firmware(pTAS2557->mpFirmware);
308 int tas2557_checkPLL(struct tas2557_priv *pTAS2557)
310         int nResult = 0;
311 /*
312 * TO DO
313 */
315         return nResult;
318 /*
319 * tas2557_load_coefficient
320 */
321 static int tas2557_load_coefficient(struct tas2557_priv *pTAS2557,
322         int nPrevConfig, int nNewConfig, bool bPowerOn)
324         int nResult = 0;
325         struct TPLL *pPLL;
326         struct TProgram *pProgram;
327         struct TConfiguration *pPrevConfiguration;
328         struct TConfiguration *pNewConfiguration;
329         struct TCalibration *pCalibration = NULL;
330         bool bRestorePower = false;
332         if (!pTAS2557->mpFirmware->mnConfigurations) {
333                 dev_err(pTAS2557->dev, "%s, firmware not loaded\n", __func__);
334                 goto end;
335         }
337         if (nNewConfig >= pTAS2557->mpFirmware->mnConfigurations) {
338                 dev_err(pTAS2557->dev, "%s, invalid configuration New=%d, total=%d\n",
339                         __func__, nNewConfig, pTAS2557->mpFirmware->mnConfigurations);
340                 goto end;
341         }
343         if (nPrevConfig < 0)
344                 pPrevConfiguration = NULL;
345         else
346                 pPrevConfiguration = &(pTAS2557->mpFirmware->mpConfigurations[nPrevConfig]);
348         pNewConfiguration = &(pTAS2557->mpFirmware->mpConfigurations[nNewConfig]);
349         pTAS2557->mnCurrentConfiguration = nNewConfig;
350         if (pPrevConfiguration) {
351                 if (pPrevConfiguration->mnPLL == pNewConfiguration->mnPLL) {
352                         dev_dbg(pTAS2557->dev, "%s, PLL same\n", __func__);
353                         goto prog_coefficient;
354                 }
355         }
357         pProgram = &(pTAS2557->mpFirmware->mpPrograms[pTAS2557->mnCurrentProgram]);
358         if (bPowerOn) {
359                 dev_dbg(pTAS2557->dev, "%s, power down to load new PLL\n", __func__);
360                 if (hrtimer_active(&pTAS2557->mtimer))
361                         hrtimer_cancel(&pTAS2557->mtimer);
363                 if (pProgram->mnAppMode == TAS2557_APP_TUNINGMODE)
364                         pTAS2557->enableIRQ(pTAS2557, false);
366                 nResult = tas2557_dev_load_data(pTAS2557, p_tas2557_shutdown_data);
367                 if (nResult < 0)
368                         goto end;
369                 bRestorePower = true;
370         }
372         /* load PLL */
373         pPLL = &(pTAS2557->mpFirmware->mpPLLs[pNewConfiguration->mnPLL]);
374         dev_dbg(pTAS2557->dev, "load PLL: %s block for Configuration %s\n",
375                 pPLL->mpName, pNewConfiguration->mpName);
376         nResult = tas2557_load_block(pTAS2557, &(pPLL->mBlock));
377         if (nResult < 0)
378                 goto end;
379         pTAS2557->mnCurrentSampleRate = pNewConfiguration->mnSamplingRate;
381         dev_dbg(pTAS2557->dev, "load configuration %s conefficient pre block\n",
382                 pNewConfiguration->mpName);
383         nResult = tas2557_load_data(pTAS2557, &(pNewConfiguration->mData), TAS2557_BLOCK_CFG_PRE_DEV_A);
384         if (nResult < 0)
385                 goto end;
387 prog_coefficient:
388         dev_dbg(pTAS2557->dev, "load new configuration: %s, coeff block data\n",
389                 pNewConfiguration->mpName);
390         nResult = tas2557_load_data(pTAS2557, &(pNewConfiguration->mData),
391                 TAS2557_BLOCK_CFG_COEFF_DEV_A);
392         if (nResult < 0)
393                 goto end;
395         if (pTAS2557->mpCalFirmware->mnCalibrations) {
396                 pCalibration = &(pTAS2557->mpCalFirmware->mpCalibrations[pTAS2557->mnCurrentCalibration]);
397                 dev_dbg(pTAS2557->dev, "load calibration\n");
398                 nResult = tas2557_load_data(pTAS2557, &(pCalibration->mData),
399                         TAS2557_BLOCK_CFG_COEFF_DEV_A);
400                 if (nResult < 0)
401                         goto end;
402         }
404         if (bRestorePower) {
405                 pTAS2557->clearIRQ(pTAS2557);
406                 dev_dbg(pTAS2557->dev, "device powered up, load startup\n");
407                 nResult = tas2557_dev_load_data(pTAS2557, p_tas2557_startup_data);
408                 if (nResult < 0)
409                         goto end;
410                 if (pProgram->mnAppMode == TAS2557_APP_TUNINGMODE) {
411                         nResult = tas2557_checkPLL(pTAS2557);
412                         if (nResult < 0) {
413                                 nResult = tas2557_dev_load_data(pTAS2557, p_tas2557_shutdown_data);
414                                 pTAS2557->mbPowerUp = false;
415                                 goto end;
416                         }
417                 }
418                 dev_dbg(pTAS2557->dev,
419                         "device powered up, load unmute\n");
420                 nResult = tas2557_dev_load_data(pTAS2557, p_tas2557_unmute_data);
421                 if (nResult < 0)
422                         goto end;
423                 if (pProgram->mnAppMode == TAS2557_APP_TUNINGMODE) {
424                         pTAS2557->enableIRQ(pTAS2557, true);
425                         if (!hrtimer_active(&pTAS2557->mtimer)) {
426                                 pTAS2557->mnDieTvReadCounter = 0;
427                                 hrtimer_start(&pTAS2557->mtimer,
428                                         ns_to_ktime((u64)LOW_TEMPERATURE_CHECK_PERIOD * NSEC_PER_MSEC), HRTIMER_MODE_REL);
429                         }
430                 }
431         }
432 end:
434         return nResult;
437 int tas2557_enable(struct tas2557_priv *pTAS2557, bool bEnable)
439         int nResult = 0;
440         unsigned int nValue;
441         struct TProgram *pProgram;
443         dev_dbg(pTAS2557->dev, "Enable: %d\n", bEnable);
445         if ((pTAS2557->mpFirmware->mnPrograms == 0)
446                 || (pTAS2557->mpFirmware->mnConfigurations == 0)) {
447                 dev_err(pTAS2557->dev, "%s, firmware not loaded\n", __func__);
448                 goto end;
449         }
450         /* check safe guard*/
451         nResult = pTAS2557->read(pTAS2557, TAS2557_SAFE_GUARD_REG, &nValue);
452         if (nResult < 0)
453                 goto end;
454         if ((nValue&0xff) != TAS2557_SAFE_GUARD_PATTERN) {
455                 dev_err(pTAS2557->dev, "ERROR safe guard failure!\n");
456                 nResult = -EPIPE;
457                 goto end;
458         }
460         pProgram = &(pTAS2557->mpFirmware->mpPrograms[pTAS2557->mnCurrentProgram]);
461         if (bEnable) {
462                 if (!pTAS2557->mbPowerUp) {
463                         if (pTAS2557->mbLoadConfigurationPrePowerUp) {
464                                 dev_dbg(pTAS2557->dev, "load coefficient before power\n");
465                                 nResult = tas2557_load_coefficient(pTAS2557,
466                                         pTAS2557->mnCurrentConfiguration, pTAS2557->mnNewConfiguration, false);
467                                 if (nResult < 0)
468                                         goto end;
469                                 pTAS2557->mbLoadConfigurationPrePowerUp = false;
470                         }
472                         pTAS2557->clearIRQ(pTAS2557);
473                         /* power on device */
474                         dev_dbg(pTAS2557->dev, "Enable: load startup sequence\n");
475                         nResult = tas2557_dev_load_data(pTAS2557, p_tas2557_startup_data);
476                         if (nResult < 0)
477                                 goto end;
478                         if (pProgram->mnAppMode == TAS2557_APP_TUNINGMODE) {
479                                 nResult = tas2557_checkPLL(pTAS2557);
480                                 if (nResult < 0) {
481                                         nResult = tas2557_dev_load_data(pTAS2557, p_tas2557_shutdown_data);
482                                         goto end;
483                                 }
484                         }
485                         dev_dbg(pTAS2557->dev, "Enable: load unmute sequence\n");
486                         nResult = tas2557_dev_load_data(pTAS2557, p_tas2557_unmute_data);
487                         if (nResult < 0)
488                                 goto end;
490                         if (pProgram->mnAppMode == TAS2557_APP_TUNINGMODE) {
491                                 /* turn on IRQ */
492                                 pTAS2557->enableIRQ(pTAS2557, true);
493                                 if (!hrtimer_active(&pTAS2557->mtimer)) {
494                                         pTAS2557->mnDieTvReadCounter = 0;
495                                         hrtimer_start(&pTAS2557->mtimer,
496                                                 ns_to_ktime((u64)LOW_TEMPERATURE_CHECK_PERIOD * NSEC_PER_MSEC), HRTIMER_MODE_REL);
497                                 }
498                         }
499                         pTAS2557->mbPowerUp = true;
500                 }
501         } else {
502                 if (pTAS2557->mbPowerUp) {
503                         if (hrtimer_active(&pTAS2557->mtimer))
504                                 hrtimer_cancel(&pTAS2557->mtimer);
506                         dev_dbg(pTAS2557->dev, "Enable: load shutdown sequence\n");
507                         if (pProgram->mnAppMode == TAS2557_APP_TUNINGMODE) {
508                                 /* turn off IRQ */
509                                 pTAS2557->enableIRQ(pTAS2557, false);
510                         }
511                         nResult = tas2557_dev_load_data(pTAS2557, p_tas2557_shutdown_data);
512                         if (nResult < 0)
513                                 goto end;
515                         pTAS2557->mbPowerUp = false;
516                 }
517         }
519         nResult = 0;
521 end:
522         if (nResult < 0) {
523                 if (pTAS2557->mnErrCode & (ERROR_DEVA_I2C_COMM | ERROR_PRAM_CRCCHK | ERROR_YRAM_CRCCHK))
524                         failsafe(pTAS2557);
525         }
527         return nResult;
530 int tas2557_set_sampling_rate(struct tas2557_priv *pTAS2557, unsigned int nSamplingRate)
532         int nResult = 0;
533         struct TConfiguration *pConfiguration;
534         unsigned int nConfiguration;
536         dev_dbg(pTAS2557->dev, "tas2557_setup_clocks: nSamplingRate = %d [Hz]\n",
537                 nSamplingRate);
539         if ((!pTAS2557->mpFirmware->mpPrograms) ||
540                 (!pTAS2557->mpFirmware->mpConfigurations)) {
541                 dev_err(pTAS2557->dev, "Firmware not loaded\n");
542                 nResult = -EINVAL;
543                 goto end;
544         }
546         pConfiguration = &(pTAS2557->mpFirmware->mpConfigurations[pTAS2557->mnCurrentConfiguration]);
547         if (pConfiguration->mnSamplingRate == nSamplingRate) {
548                 dev_info(pTAS2557->dev, "Sampling rate for current configuration matches: %d\n",
549                         nSamplingRate);
550                 nResult = 0;
551                 goto end;
552         }
554         for (nConfiguration = 0;
555                 nConfiguration < pTAS2557->mpFirmware->mnConfigurations;
556                 nConfiguration++) {
557                 pConfiguration =
558                         &(pTAS2557->mpFirmware->mpConfigurations[nConfiguration]);
559                 if ((pConfiguration->mnSamplingRate == nSamplingRate)
560                         && (pConfiguration->mnProgram == pTAS2557->mnCurrentProgram)) {
561                         dev_info(pTAS2557->dev,
562                                 "Found configuration: %s, with compatible sampling rate %d\n",
563                                 pConfiguration->mpName, nSamplingRate);
564                         nResult = tas2557_load_configuration(pTAS2557, nConfiguration, false);
565                         goto end;
566                 }
567         }
569         dev_err(pTAS2557->dev, "Cannot find a configuration that supports sampling rate: %d\n",
570                 nSamplingRate);
572 end:
574         return nResult;
577 static void fw_print_header(struct tas2557_priv *pTAS2557, struct TFirmware *pFirmware)
579         dev_info(pTAS2557->dev, "FW Size       = %d", pFirmware->mnFWSize);
580         dev_info(pTAS2557->dev, "Checksum      = 0x%04X", pFirmware->mnChecksum);
581         dev_info(pTAS2557->dev, "PPC Version   = 0x%04X", pFirmware->mnPPCVersion);
582         dev_info(pTAS2557->dev, "FW  Version    = 0x%04X", pFirmware->mnFWVersion);
583         dev_info(pTAS2557->dev, "Driver Version= 0x%04X", pFirmware->mnDriverVersion);
584         dev_info(pTAS2557->dev, "Timestamp     = %d", pFirmware->mnTimeStamp);
585         dev_info(pTAS2557->dev, "DDC Name      = %s", pFirmware->mpDDCName);
586         dev_info(pTAS2557->dev, "Description   = %s", pFirmware->mpDescription);
589 inline unsigned int fw_convert_number(unsigned char *pData)
591         return pData[3] + (pData[2] << 8) + (pData[1] << 16) + (pData[0] << 24);
594 static int fw_parse_header(struct tas2557_priv *pTAS2557,
595         struct TFirmware *pFirmware, unsigned char *pData, unsigned int nSize)
597         unsigned char *pDataStart = pData;
598         unsigned int n;
599         unsigned char pMagicNumber[] = { 0x35, 0x35, 0x35, 0x32 };
601         if (nSize < 104) {
602                 dev_err(pTAS2557->dev, "Firmware: Header too short");
603                 return -EINVAL;
604         }
606         if (memcmp(pData, pMagicNumber, 4)) {
607                 dev_err(pTAS2557->dev, "Firmware: Magic number doesn't match");
608                 return -EINVAL;
609         }
610         pData += 4;
612         pFirmware->mnFWSize = fw_convert_number(pData);
613         pData += 4;
615         pFirmware->mnChecksum = fw_convert_number(pData);
616         pData += 4;
618         pFirmware->mnPPCVersion = fw_convert_number(pData);
619         pData += 4;
621         pFirmware->mnFWVersion = fw_convert_number(pData);
622         pData += 4;
624         pFirmware->mnDriverVersion = fw_convert_number(pData);
625         pData += 4;
627         pFirmware->mnTimeStamp = fw_convert_number(pData);
628         pData += 4;
630         memcpy(pFirmware->mpDDCName, pData, 64);
631         pData += 64;
633         n = strlen(pData);
634         pFirmware->mpDescription = kmemdup(pData, n + 1, GFP_KERNEL);
635         pData += n + 1;
636         if ((pData - pDataStart) >= nSize) {
637                 dev_err(pTAS2557->dev, "Firmware: Header too short after DDC description");
638                 return -EINVAL;
639         }
641         pFirmware->mnDeviceFamily = fw_convert_number(pData);
642         pData += 4;
643         if (pFirmware->mnDeviceFamily != 0) {
644                 dev_err(pTAS2557->dev,
645                         "deviceFamily %d, not TAS device", pFirmware->mnDeviceFamily);
646                 return -EINVAL;
647         }
649         pFirmware->mnDevice = fw_convert_number(pData);
650         pData += 4;
652         if (pFirmware->mnDevice != 2) {
653                 dev_err(pTAS2557->dev,
654                         "device %d, not TAS2557 Dual Mono", pFirmware->mnDevice);
655                 return -EINVAL;
656         }
658         fw_print_header(pTAS2557, pFirmware);
659         return pData - pDataStart;
662 static int fw_parse_block_data(struct tas2557_priv *pTAS2557, struct TFirmware *pFirmware,
663         struct TBlock *pBlock, unsigned char *pData)
665         unsigned char *pDataStart = pData;
666         unsigned int n;
668         pBlock->mnType = fw_convert_number(pData);
669         pData += 4;
671         if (pFirmware->mnDriverVersion >= PPC_DRIVER_CRCCHK) {
672                 pBlock->mbPChkSumPresent = pData[0];
673                 pData++;
675                 pBlock->mnPChkSum = pData[0];
676                 pData++;
678                 pBlock->mbYChkSumPresent = pData[0];
679                 pData++;
681                 pBlock->mnYChkSum = pData[0];
682                 pData++;
683         } else {
684                 pBlock->mbPChkSumPresent = 0;
685                 pBlock->mbYChkSumPresent = 0;
686         }
688         pBlock->mnCommands = fw_convert_number(pData);
689         pData += 4;
691         n = pBlock->mnCommands * 4;
692         pBlock->mpData = kmemdup(pData, n, GFP_KERNEL);
693         pData += n;
694         return pData - pDataStart;
697 static int fw_parse_data(struct tas2557_priv *pTAS2557, struct TFirmware *pFirmware,
698         struct TData *pImageData, unsigned char *pData)
700         unsigned char *pDataStart = pData;
701         unsigned int nBlock;
702         unsigned int n;
704         memcpy(pImageData->mpName, pData, 64);
705         pData += 64;
707         n = strlen(pData);
708         pImageData->mpDescription = kmemdup(pData, n + 1, GFP_KERNEL);
709         pData += n + 1;
711         pImageData->mnBlocks = (pData[0] << 8) + pData[1];
712         pData += 2;
714         pImageData->mpBlocks =
715                 kmalloc(sizeof(struct TBlock) * pImageData->mnBlocks, GFP_KERNEL);
717         for (nBlock = 0; nBlock < pImageData->mnBlocks; nBlock++) {
718                 n = fw_parse_block_data(pTAS2557, pFirmware,
719                         &(pImageData->mpBlocks[nBlock]), pData);
720                 pData += n;
721         }
722         return pData - pDataStart;
725 static int fw_parse_pll_data(struct tas2557_priv *pTAS2557,
726         struct TFirmware *pFirmware, unsigned char *pData)
728         unsigned char *pDataStart = pData;
729         unsigned int n;
730         unsigned int nPLL;
731         struct TPLL *pPLL;
733         pFirmware->mnPLLs = (pData[0] << 8) + pData[1];
734         pData += 2;
736         if (pFirmware->mnPLLs == 0)
737                 goto end;
739         pFirmware->mpPLLs = kmalloc_array(pFirmware->mnPLLs, sizeof(struct TPLL), GFP_KERNEL);
740         for (nPLL = 0; nPLL < pFirmware->mnPLLs; nPLL++) {
741                 pPLL = &(pFirmware->mpPLLs[nPLL]);
743                 memcpy(pPLL->mpName, pData, 64);
744                 pData += 64;
746                 n = strlen(pData);
747                 pPLL->mpDescription = kmemdup(pData, n + 1, GFP_KERNEL);
748                 pData += n + 1;
750                 n = fw_parse_block_data(pTAS2557, pFirmware, &(pPLL->mBlock), pData);
751                 pData += n;
752         }
754 end:
755         return pData - pDataStart;
758 static int fw_parse_program_data(struct tas2557_priv *pTAS2557,
759         struct TFirmware *pFirmware, unsigned char *pData)
761         unsigned char *pDataStart = pData;
762         unsigned int n;
763         unsigned int nProgram;
764         struct TProgram *pProgram;
766         pFirmware->mnPrograms = (pData[0] << 8) + pData[1];
767         pData += 2;
769         if (pFirmware->mnPrograms == 0)
770                 goto end;
772         pFirmware->mpPrograms =
773                 kmalloc(sizeof(struct TProgram) * pFirmware->mnPrograms, GFP_KERNEL);
774         for (nProgram = 0; nProgram < pFirmware->mnPrograms; nProgram++) {
775                 pProgram = &(pFirmware->mpPrograms[nProgram]);
776                 memcpy(pProgram->mpName, pData, 64);
777                 pData += 64;
779                 n = strlen(pData);
780                 pProgram->mpDescription = kmemdup(pData, n + 1, GFP_KERNEL);
781                 pData += n + 1;
783                 pProgram->mnAppMode = pData[0];
784                 pData++;
786                 pProgram->mnBoost = (pData[0] << 8) + pData[1];
787                 pData += 2;
789                 n = fw_parse_data(pTAS2557, pFirmware, &(pProgram->mData), pData);
790                 pData += n;
791         }
793 end:
795         return pData - pDataStart;
798 static int fw_parse_configuration_data(struct tas2557_priv *pTAS2557,
799         struct TFirmware *pFirmware, unsigned char *pData)
801         unsigned char *pDataStart = pData;
802         unsigned int n;
803         unsigned int nConfiguration;
804         struct TConfiguration *pConfiguration;
806         pFirmware->mnConfigurations = (pData[0] << 8) + pData[1];
807         pData += 2;
809         if (pFirmware->mnConfigurations == 0)
810                 goto end;
812         pFirmware->mpConfigurations =
813                 kmalloc(sizeof(struct TConfiguration) * pFirmware->mnConfigurations,
814                 GFP_KERNEL);
815         for (nConfiguration = 0; nConfiguration < pFirmware->mnConfigurations;
816                 nConfiguration++) {
817                 pConfiguration = &(pFirmware->mpConfigurations[nConfiguration]);
818                 memcpy(pConfiguration->mpName, pData, 64);
819                 pData += 64;
821                 n = strlen(pData);
822                 pConfiguration->mpDescription = kmemdup(pData, n + 1, GFP_KERNEL);
823                 pData += n + 1;
825                 if ((pFirmware->mnDriverVersion >= PPC_DRIVER_CONFDEV)
826                         || ((pFirmware->mnDriverVersion >= PPC_DRIVER_CFGDEV_NONCRC)
827                                 && (pFirmware->mnDriverVersion < PPC_DRIVER_CRCCHK))) {
828                         pConfiguration->mnDevices = (pData[0] << 8) + pData[1];
829                         pData += 2;
830                 } else
831                         pConfiguration->mnDevices = 1;
833                 pConfiguration->mnProgram = pData[0];
834                 pData++;
836                 pConfiguration->mnPLL = pData[0];
837                 pData++;
839                 pConfiguration->mnSamplingRate = fw_convert_number(pData);
840                 pData += 4;
842                 n = fw_parse_data(pTAS2557, pFirmware, &(pConfiguration->mData), pData);
843                 pData += n;
844         }
846 end:
848         return pData - pDataStart;
851 int fw_parse_calibration_data(struct tas2557_priv *pTAS2557,
852         struct TFirmware *pFirmware, unsigned char *pData)
854         unsigned char *pDataStart = pData;
855         unsigned int n;
856         unsigned int nCalibration;
857         struct TCalibration *pCalibration;
859         pFirmware->mnCalibrations = (pData[0] << 8) + pData[1];
860         pData += 2;
862         if (pFirmware->mnCalibrations == 0)
863                 goto end;
865         pFirmware->mpCalibrations =
866                 kmalloc(sizeof(struct TCalibration) * pFirmware->mnCalibrations, GFP_KERNEL);
867         for (nCalibration = 0;
868                 nCalibration < pFirmware->mnCalibrations;
869                 nCalibration++) {
870                 pCalibration = &(pFirmware->mpCalibrations[nCalibration]);
871                 memcpy(pCalibration->mpName, pData, 64);
872                 pData += 64;
874                 n = strlen(pData);
875                 pCalibration->mpDescription = kmemdup(pData, n + 1, GFP_KERNEL);
876                 pData += n + 1;
878                 pCalibration->mnProgram = pData[0];
879                 pData++;
881                 pCalibration->mnConfiguration = pData[0];
882                 pData++;
884                 n = fw_parse_data(pTAS2557, pFirmware, &(pCalibration->mData), pData);
885                 pData += n;
886         }
888 end:
890         return pData - pDataStart;
893 static int fw_parse(struct tas2557_priv *pTAS2557,
894         struct TFirmware *pFirmware, unsigned char *pData, unsigned int nSize)
896         int nPosition = 0;
898         nPosition = fw_parse_header(pTAS2557, pFirmware, pData, nSize);
899         if (nPosition < 0) {
900                 dev_err(pTAS2557->dev, "Firmware: Wrong Header");
901                 return -EINVAL;
902         }
904         if (nPosition >= nSize) {
905                 dev_err(pTAS2557->dev, "Firmware: Too short");
906                 return -EINVAL;
907         }
909         pData += nPosition;
910         nSize -= nPosition;
911         nPosition = 0;
913         nPosition = fw_parse_pll_data(pTAS2557, pFirmware, pData);
915         pData += nPosition;
916         nSize -= nPosition;
917         nPosition = 0;
919         nPosition = fw_parse_program_data(pTAS2557, pFirmware, pData);
921         pData += nPosition;
922         nSize -= nPosition;
923         nPosition = 0;
925         nPosition = fw_parse_configuration_data(pTAS2557, pFirmware, pData);
927         pData += nPosition;
928         nSize -= nPosition;
929         nPosition = 0;
931         if (nSize > 64)
932                 nPosition = fw_parse_calibration_data(pTAS2557, pFirmware, pData);
933         return 0;
937 static const unsigned char crc8_lookup_table[CRC8_TABLE_SIZE] = {
938 0x00, 0x4D, 0x9A, 0xD7, 0x79, 0x34, 0xE3, 0xAE, 0xF2, 0xBF, 0x68, 0x25, 0x8B, 0xC6, 0x11, 0x5C,
939 0xA9, 0xE4, 0x33, 0x7E, 0xD0, 0x9D, 0x4A, 0x07, 0x5B, 0x16, 0xC1, 0x8C, 0x22, 0x6F, 0xB8, 0xF5,
940 0x1F, 0x52, 0x85, 0xC8, 0x66, 0x2B, 0xFC, 0xB1, 0xED, 0xA0, 0x77, 0x3A, 0x94, 0xD9, 0x0E, 0x43,
941 0xB6, 0xFB, 0x2C, 0x61, 0xCF, 0x82, 0x55, 0x18, 0x44, 0x09, 0xDE, 0x93, 0x3D, 0x70, 0xA7, 0xEA,
942 0x3E, 0x73, 0xA4, 0xE9, 0x47, 0x0A, 0xDD, 0x90, 0xCC, 0x81, 0x56, 0x1B, 0xB5, 0xF8, 0x2F, 0x62,
943 0x97, 0xDA, 0x0D, 0x40, 0xEE, 0xA3, 0x74, 0x39, 0x65, 0x28, 0xFF, 0xB2, 0x1C, 0x51, 0x86, 0xCB,
944 0x21, 0x6C, 0xBB, 0xF6, 0x58, 0x15, 0xC2, 0x8F, 0xD3, 0x9E, 0x49, 0x04, 0xAA, 0xE7, 0x30, 0x7D,
945 0x88, 0xC5, 0x12, 0x5F, 0xF1, 0xBC, 0x6B, 0x26, 0x7A, 0x37, 0xE0, 0xAD, 0x03, 0x4E, 0x99, 0xD4,
946 0x7C, 0x31, 0xE6, 0xAB, 0x05, 0x48, 0x9F, 0xD2, 0x8E, 0xC3, 0x14, 0x59, 0xF7, 0xBA, 0x6D, 0x20,
947 0xD5, 0x98, 0x4F, 0x02, 0xAC, 0xE1, 0x36, 0x7B, 0x27, 0x6A, 0xBD, 0xF0, 0x5E, 0x13, 0xC4, 0x89,
948 0x63, 0x2E, 0xF9, 0xB4, 0x1A, 0x57, 0x80, 0xCD, 0x91, 0xDC, 0x0B, 0x46, 0xE8, 0xA5, 0x72, 0x3F,
949 0xCA, 0x87, 0x50, 0x1D, 0xB3, 0xFE, 0x29, 0x64, 0x38, 0x75, 0xA2, 0xEF, 0x41, 0x0C, 0xDB, 0x96,
950 0x42, 0x0F, 0xD8, 0x95, 0x3B, 0x76, 0xA1, 0xEC, 0xB0, 0xFD, 0x2A, 0x67, 0xC9, 0x84, 0x53, 0x1E,
951 0xEB, 0xA6, 0x71, 0x3C, 0x92, 0xDF, 0x08, 0x45, 0x19, 0x54, 0x83, 0xCE, 0x60, 0x2D, 0xFA, 0xB7,
952 0x5D, 0x10, 0xC7, 0x8A, 0x24, 0x69, 0xBE, 0xF3, 0xAF, 0xE2, 0x35, 0x78, 0xD6, 0x9B, 0x4C, 0x01,
953 0xF4, 0xB9, 0x6E, 0x23, 0x8D, 0xC0, 0x17, 0x5A, 0x06, 0x4B, 0x9C, 0xD1, 0x7F, 0x32, 0xE5, 0xA8
954 };
956 static int isInPageYRAM(struct tas2557_priv *pTAS2557, struct TYCRC *pCRCData,
957         unsigned char nBook, unsigned char nPage, unsigned char nReg, unsigned char len)
959         int nResult = 0;
961         if (nBook == TAS2557_YRAM_BOOK1) {
962                 if (nPage == TAS2557_YRAM1_PAGE) {
963                         if (nReg >= TAS2557_YRAM1_START_REG) {
964                                 pCRCData->mnOffset = nReg;
965                                 pCRCData->mnLen = len;
966                                 nResult = 1;
967                         } else if ((nReg + len) > TAS2557_YRAM1_START_REG) {
968                                 pCRCData->mnOffset = TAS2557_YRAM1_START_REG;
969                                 pCRCData->mnLen = len - (TAS2557_YRAM1_START_REG - nReg);
970                                 nResult = 1;
971                         } else
972                                 nResult = 0;
973                 } else if (nPage == TAS2557_YRAM3_PAGE) {
974                         if (nReg > TAS2557_YRAM3_END_REG) {
975                                 nResult = 0;
976                         } else if (nReg >= TAS2557_YRAM3_START_REG) {
977                                 if ((nReg + len) > TAS2557_YRAM3_END_REG) {
978                                         pCRCData->mnOffset = nReg;
979                                         pCRCData->mnLen = TAS2557_YRAM3_END_REG - nReg + 1;
980                                         nResult = 1;
981                                 } else {
982                                         pCRCData->mnOffset = nReg;
983                                         pCRCData->mnLen = len;
984                                         nResult = 1;
985                                 }
986                         } else {
987                                 if ((nReg + len) < TAS2557_YRAM3_START_REG)
988                                         nResult = 0;
989                                 else {
990                                         pCRCData->mnOffset = TAS2557_YRAM3_START_REG;
991                                         pCRCData->mnLen = len - (TAS2557_YRAM3_START_REG - nReg);
992                                         nResult = 1;
993                                 }
994                         }
995                 }
996         } else if (nBook == TAS2557_YRAM_BOOK2) {
997                 if (nPage == TAS2557_YRAM5_PAGE) {
998                         if (nReg > TAS2557_YRAM5_END_REG) {
999                                 nResult = 0;
1000                         } else if (nReg >= TAS2557_YRAM5_START_REG) {
1001                                 if ((nReg + len) > TAS2557_YRAM5_END_REG) {
1002                                         pCRCData->mnOffset = nReg;
1003                                         pCRCData->mnLen = TAS2557_YRAM5_END_REG - nReg + 1;
1004                                         nResult = 1;
1005                                 } else {
1006                                         pCRCData->mnOffset = nReg;
1007                                         pCRCData->mnLen = len;
1008                                         nResult = 1;
1009                                 }
1010                         } else {
1011                                 if ((nReg + len) < TAS2557_YRAM5_START_REG)
1012                                         nResult = 0;
1013                                 else {
1014                                         pCRCData->mnOffset = TAS2557_YRAM5_START_REG;
1015                                         pCRCData->mnLen = len - (TAS2557_YRAM5_START_REG - nReg);
1016                                         nResult = 1;
1017                                 }
1018                         }
1019                 }
1020         } else
1021                 nResult = 0;
1023         return nResult;
1026 static int isInBlockYRAM(struct tas2557_priv *pTAS2557, struct TYCRC *pCRCData,
1027         unsigned char nBook, unsigned char nPage, unsigned char nReg, unsigned char len)
1029         int nResult;
1031         if (nBook == TAS2557_YRAM_BOOK1) {
1032                 if (nPage < TAS2557_YRAM2_START_PAGE)
1033                         nResult = 0;
1034                 else if (nPage <= TAS2557_YRAM2_END_PAGE) {
1035                         if (nReg > TAS2557_YRAM2_END_REG)
1036                                 nResult = 0;
1037                         else if (nReg >= TAS2557_YRAM2_START_REG) {
1038                                 pCRCData->mnOffset = nReg;
1039                                 pCRCData->mnLen = len;
1040                                 nResult = 1;
1041                         } else {
1042                                 if ((nReg + len) < TAS2557_YRAM2_START_REG)
1043                                         nResult = 0;
1044                                 else {
1045                                         pCRCData->mnOffset = TAS2557_YRAM2_START_REG;
1046                                         pCRCData->mnLen = nReg + len - TAS2557_YRAM2_START_REG;
1047                                         nResult = 1;
1048                                 }
1049                         }
1050                 } else
1051                         nResult = 0;
1052         } else if (nBook == TAS2557_YRAM_BOOK2) {
1053                 if (nPage < TAS2557_YRAM4_START_PAGE)
1054                         nResult = 0;
1055                 else if (nPage <= TAS2557_YRAM4_END_PAGE) {
1056                         if (nReg > TAS2557_YRAM2_END_REG)
1057                                 nResult = 0;
1058                         else if (nReg >= TAS2557_YRAM2_START_REG) {
1059                                 pCRCData->mnOffset = nReg;
1060                                 pCRCData->mnLen = len;
1061                                 nResult = 1;
1062                         } else {
1063                                 if ((nReg + len) < TAS2557_YRAM2_START_REG)
1064                                         nResult = 0;
1065                                 else {
1066                                         pCRCData->mnOffset = TAS2557_YRAM2_START_REG;
1067                                         pCRCData->mnLen = nReg + len - TAS2557_YRAM2_START_REG;
1068                                         nResult = 1;
1069                                 }
1070                         }
1071                 } else
1072                         nResult = 0;
1073         } else
1074                 nResult = 0;
1076         return nResult;
1080 static int isYRAM(struct tas2557_priv *pTAS2557, struct TYCRC *pCRCData,
1081         unsigned char nBook, unsigned char nPage, unsigned char nReg, unsigned char len)
1083         int nResult;
1085         nResult = isInPageYRAM(pTAS2557, pCRCData, nBook, nPage, nReg, len);
1087         if (nResult == 0)
1088                 nResult = isInBlockYRAM(pTAS2557, pCRCData, nBook, nPage, nReg, len);
1090         return nResult;
1093 /*
1094  * crc8 - calculate a crc8 over the given input data.
1095  *
1096  * table: crc table used for calculation.
1097  * pdata: pointer to data buffer.
1098  * nbytes: number of bytes in data buffer.
1099  * crc: previous returned crc8 value.
1100  */
1101 static u8 ti_crc8(const u8 table[CRC8_TABLE_SIZE], u8 *pdata, size_t nbytes, u8 crc)
1103         /* loop over the buffer data */
1104         while (nbytes-- > 0)
1105                 crc = table[(crc ^ *pdata++) & 0xff];
1107         return crc;
1110 static int doSingleRegCheckSum(struct tas2557_priv *pTAS2557, 
1111         unsigned char nBook, unsigned char nPage, unsigned char nReg, unsigned char nValue)
1113         int nResult = 0;
1114         struct TYCRC sCRCData;
1115         unsigned int nData1 = 0;
1117         if ((nBook == TAS2557_BOOK_ID(TAS2557_SA_COEFF_SWAP_REG))
1118                 && (nPage == TAS2557_PAGE_ID(TAS2557_SA_COEFF_SWAP_REG))
1119                 && (nReg >= TAS2557_PAGE_REG(TAS2557_SA_COEFF_SWAP_REG))
1120                 && (nReg <= (TAS2557_PAGE_REG(TAS2557_SA_COEFF_SWAP_REG) + 4))) {
1121                 /* DSP swap command, pass */
1122                 nResult = 0;
1123                 goto end;
1124         }
1126         nResult = isYRAM(pTAS2557, &sCRCData, nBook, nPage, nReg, 1);
1127         if (nResult == 1) {
1128                 nResult = pTAS2557->read(pTAS2557, TAS2557_REG(nBook, nPage, nReg), &nData1);
1129                 if (nResult < 0)
1130                         goto end;
1132                 if (nData1 != nValue) {
1133                         dev_err(pTAS2557->dev, "error2 (line %d),B[0x%x]P[0x%x]R[0x%x] W[0x%x], R[0x%x]\n",
1134                                 __LINE__, nBook, nPage, nReg, nValue, nData1);
1135                         nResult = -EAGAIN;
1136                         goto end;
1137                 }
1139                 nResult = ti_crc8(crc8_lookup_table, &nValue, 1, 0);
1140         }
1142 end:
1144         return nResult;
1147 static int doMultiRegCheckSum(struct tas2557_priv *pTAS2557, 
1148         unsigned char nBook, unsigned char nPage, unsigned char nReg, unsigned int len)
1150         int nResult = 0, i;
1151         unsigned char nCRCChkSum = 0;
1152         unsigned char nBuf1[128];
1153         struct TYCRC TCRCData;
1155         if ((nReg + len-1) > 127) {
1156                 nResult = -EINVAL;
1157                 dev_err(pTAS2557->dev, "firmware error\n");
1158                 goto end;
1159         }
1161         if ((nBook == TAS2557_BOOK_ID(TAS2557_SA_COEFF_SWAP_REG))
1162                 && (nPage == TAS2557_PAGE_ID(TAS2557_SA_COEFF_SWAP_REG))
1163                 && (nReg == TAS2557_PAGE_REG(TAS2557_SA_COEFF_SWAP_REG))
1164                 && (len == 4)) {
1165                 /* DSP swap command, pass */
1166                 nResult = 0;
1167                 goto end;
1168         }
1170         nResult = isYRAM(pTAS2557, &TCRCData, nBook, nPage, nReg, len);
1171         if (nResult == 1) {
1172                 if (len == 1) {
1173                         dev_err(pTAS2557->dev, "firmware error\n");
1174                         nResult = -EINVAL;
1175                         goto end;
1176                 } else {
1177                         nResult = pTAS2557->bulk_read(pTAS2557, TAS2557_REG(nBook, nPage, TCRCData.mnOffset), nBuf1, TCRCData.mnLen);
1178                         if (nResult < 0)
1179                                 goto end;
1181                         for (i = 0; i < TCRCData.mnLen; i++) {
1182                                 if ((nBook == TAS2557_BOOK_ID(TAS2557_SA_COEFF_SWAP_REG))
1183                                         && (nPage == TAS2557_PAGE_ID(TAS2557_SA_COEFF_SWAP_REG))
1184                                         && ((i + TCRCData.mnOffset)
1185                                                 >= TAS2557_PAGE_REG(TAS2557_SA_COEFF_SWAP_REG))
1186                                         && ((i + TCRCData.mnOffset)
1187                                                 <= (TAS2557_PAGE_REG(TAS2557_SA_COEFF_SWAP_REG) + 4))) {
1188                                         /* DSP swap command, bypass */
1189                                         continue;
1190                                 } else
1191                                         nCRCChkSum += ti_crc8(crc8_lookup_table, &nBuf1[i], 1, 0);
1192                         }
1194                         nResult = nCRCChkSum;
1195                 }
1196         }
1198 end:
1200         return nResult;
1203 static int tas2557_load_block(struct tas2557_priv *pTAS2557, struct TBlock *pBlock)
1205         int nResult = 0;
1206         unsigned int nCommand = 0;
1207         unsigned char nBook;
1208         unsigned char nPage;
1209         unsigned char nOffset;
1210         unsigned char nData;
1211         unsigned int nLength;
1212         unsigned int nSleep;
1213         unsigned char nCRCChkSum = 0;
1214         unsigned int nValue1;
1215         int nRetry = 6;
1216         unsigned char *pData = pBlock->mpData;
1218         dev_dbg(pTAS2557->dev, "TAS2557 load block: Type = %d, commands = %d\n",
1219                 pBlock->mnType, pBlock->mnCommands);
1220 start:
1221         if (pBlock->mbPChkSumPresent) {
1222                 nResult = pTAS2557->write(pTAS2557, TAS2557_CRC_RESET_REG, 1);
1223                 if (nResult < 0)
1224                         goto end;
1225         }
1227         if (pBlock->mbYChkSumPresent)
1228                 nCRCChkSum = 0;
1230         nCommand = 0;
1232         while (nCommand < pBlock->mnCommands) {
1233                 pData = pBlock->mpData + nCommand * 4;
1235                 nBook = pData[0];
1236                 nPage = pData[1];
1237                 nOffset = pData[2];
1238                 nData = pData[3];
1240                 nCommand++;
1242                 if (nOffset <= 0x7F) {
1243                         nResult = pTAS2557->write(pTAS2557, TAS2557_REG(nBook, nPage, nOffset), nData);
1244                         if (nResult < 0)
1245                                 goto end;
1246                         if (pBlock->mbYChkSumPresent) {
1247                                 nResult = doSingleRegCheckSum(pTAS2557, nBook, nPage, nOffset, nData);
1248                                 if (nResult < 0)
1249                                         goto check;
1250                                 nCRCChkSum += (unsigned char)nResult;
1251                         }
1252                 } else if (nOffset == 0x81) {
1253                         nSleep = (nBook << 8) + nPage;
1254                         msleep(nSleep);
1255                 } else if (nOffset == 0x85) {
1256                         pData += 4;
1257                         nLength = (nBook << 8) + nPage;
1258                         nBook = pData[0];
1259                         nPage = pData[1];
1260                         nOffset = pData[2];
1261                         if (nLength > 1) {
1262                                 nResult = pTAS2557->bulk_write(pTAS2557, TAS2557_REG(nBook, nPage, nOffset), pData + 3, nLength);
1263                                 if (nResult < 0)
1264                                         goto end;
1265                                 if (pBlock->mbYChkSumPresent) {
1266                                         nResult = doMultiRegCheckSum(pTAS2557, nBook, nPage, nOffset, nLength);
1267                                         if (nResult < 0)
1268                                                 goto check;
1269                                         nCRCChkSum += (unsigned char)nResult;
1270                                 }
1271                         } else {
1272                                 nResult = pTAS2557->write(pTAS2557, TAS2557_REG(nBook, nPage, nOffset), pData[3]);
1273                                 if (nResult < 0)
1274                                         goto end;
1275                                 if (pBlock->mbYChkSumPresent) {
1276                                         nResult = doSingleRegCheckSum(pTAS2557, nBook, nPage, nOffset, pData[3]);
1277                                         if (nResult < 0)
1278                                                 goto check;
1279                                         nCRCChkSum += (unsigned char)nResult;
1280                                 }
1281                         }
1283                         nCommand++;
1285                         if (nLength >= 2)
1286                                 nCommand += ((nLength - 2) / 4) + 1;
1287                 }
1288         }
1289         if (pBlock->mbPChkSumPresent) {
1290                 nResult = pTAS2557->read(pTAS2557, TAS2557_CRC_CHECKSUM_REG, &nValue1);
1291                 if (nResult < 0)
1292                         goto end;
1293                 if ((nValue1&0xff) != pBlock->mnPChkSum) {
1294                         dev_err(pTAS2557->dev, "Block PChkSum Error: FW = 0x%x, Reg = 0x%x\n",
1295                                 pBlock->mnPChkSum, (nValue1&0xff));
1296                         nResult = -EAGAIN;
1297                                 pTAS2557->mnErrCode |= ERROR_PRAM_CRCCHK;
1298                         goto check;
1299                 }
1301                 nResult = 0;
1302                 pTAS2557->mnErrCode &= ~ERROR_PRAM_CRCCHK;
1303                 dev_dbg(pTAS2557->dev, "Block[0x%x] PChkSum match\n", pBlock->mnType);
1304         }
1306         if (pBlock->mbYChkSumPresent) {
1307                 if (nCRCChkSum != pBlock->mnYChkSum) {
1308                         dev_err(pTAS2557->dev, "Block YChkSum Error: FW = 0x%x, YCRC = 0x%x\n",
1309                                 pBlock->mnYChkSum, nCRCChkSum);
1310                         nResult = -EAGAIN;
1311                         pTAS2557->mnErrCode |= ERROR_YRAM_CRCCHK;
1312                         goto check;
1313                 }
1314                 pTAS2557->mnErrCode &= ~ERROR_YRAM_CRCCHK;
1315                 nResult = 0;
1316                 dev_dbg(pTAS2557->dev, "Block[0x%x] YChkSum match\n", pBlock->mnType);
1317         }
1319 check:
1320         if (nResult == -EAGAIN) {
1321                 nRetry--;
1322                 if (nRetry > 0)
1323                         goto start;
1324         }
1326 end:
1327         if (nResult < 0) {
1328                 dev_err(pTAS2557->dev, "Block (%d) load error\n",
1329                                 pBlock->mnType);
1330         }
1331         return nResult;
1334 static int tas2557_load_data(struct tas2557_priv *pTAS2557, struct TData *pData, unsigned int nType)
1336         int nResult = 0;
1337         unsigned int nBlock;
1338         struct TBlock *pBlock;
1340         dev_dbg(pTAS2557->dev,
1341                 "TAS2557 load data: %s, Blocks = %d, Block Type = %d\n", pData->mpName, pData->mnBlocks, nType);
1343         for (nBlock = 0; nBlock < pData->mnBlocks; nBlock++) {
1344                 pBlock = &(pData->mpBlocks[nBlock]);
1345                 if (pBlock->mnType == nType) {
1346                         nResult = tas2557_load_block(pTAS2557, pBlock);
1347                         if (nResult < 0)
1348                                 break;
1349                 }
1350         }
1352         return nResult;
1355 static int tas2557_load_configuration(struct tas2557_priv *pTAS2557,
1356         unsigned int nConfiguration, bool bLoadSame)
1358         int nResult = 0;
1359         struct TConfiguration *pCurrentConfiguration = NULL;
1360         struct TConfiguration *pNewConfiguration = NULL;
1362         dev_dbg(pTAS2557->dev, "%s: %d\n", __func__, nConfiguration);
1364         if ((!pTAS2557->mpFirmware->mpPrograms) ||
1365                 (!pTAS2557->mpFirmware->mpConfigurations)) {
1366                 dev_err(pTAS2557->dev, "Firmware not loaded\n");
1367                 nResult = 0;
1368                 goto end;
1369         }
1371         if (nConfiguration >= pTAS2557->mpFirmware->mnConfigurations) {
1372                 dev_err(pTAS2557->dev, "Configuration %d doesn't exist\n",
1373                         nConfiguration);
1374                 nResult = 0;
1375                 goto end;
1376         }
1378         if ((nConfiguration == pTAS2557->mnCurrentConfiguration) && (!bLoadSame)) {
1379                 dev_info(pTAS2557->dev, "Configuration %d is already loaded\n",
1380                         nConfiguration);
1381                 nResult = 0;
1382                 goto end;
1383         }
1385         pCurrentConfiguration =
1386                 &(pTAS2557->mpFirmware->mpConfigurations[pTAS2557->mnCurrentConfiguration]);
1387         pNewConfiguration =
1388                 &(pTAS2557->mpFirmware->mpConfigurations[nConfiguration]);
1389         if (pNewConfiguration->mnProgram != pCurrentConfiguration->mnProgram) {
1390                 dev_err(pTAS2557->dev, "Configuration %d, %s doesn't share the same program as current %d\n",
1391                         nConfiguration, pNewConfiguration->mpName, pCurrentConfiguration->mnProgram);
1392                 nResult = 0;
1393                 goto end;
1394         }
1396         if (pNewConfiguration->mnPLL >= pTAS2557->mpFirmware->mnPLLs) {
1397                 dev_err(pTAS2557->dev, "Configuration %d, %s doesn't have a valid PLL index %d\n",
1398                         nConfiguration, pNewConfiguration->mpName, pNewConfiguration->mnPLL);
1399                 nResult = 0;
1400                 goto end;
1401         }
1403         if (pTAS2557->mbPowerUp) {
1404                 nResult = tas2557_load_coefficient(pTAS2557, pTAS2557->mnCurrentConfiguration, nConfiguration, true);
1405                 pTAS2557->mbLoadConfigurationPrePowerUp = false;
1406         } else {
1407                 dev_dbg(pTAS2557->dev,
1408                         "TAS2557 was powered down, will load coefficient when power up\n");
1409                 pTAS2557->mbLoadConfigurationPrePowerUp = true;
1410                 pTAS2557->mnNewConfiguration = nConfiguration;
1411         }
1413 end:
1415         if (nResult < 0) {
1416                 if (pTAS2557->mnErrCode & (ERROR_DEVA_I2C_COMM | ERROR_PRAM_CRCCHK | ERROR_YRAM_CRCCHK))
1417                         failsafe(pTAS2557);
1418         }
1420         return nResult;
1423 int tas2557_set_config(struct tas2557_priv *pTAS2557, int config)
1425         struct TConfiguration *pConfiguration;
1426         struct TProgram *pProgram;
1427         unsigned int nProgram = pTAS2557->mnCurrentProgram;
1428         unsigned int nConfiguration = config;
1429         int nResult = 0;
1431         if ((!pTAS2557->mpFirmware->mpPrograms) ||
1432                 (!pTAS2557->mpFirmware->mpConfigurations)) {
1433                 dev_err(pTAS2557->dev, "Firmware not loaded\n");
1434                 nResult = -EINVAL;
1435                 goto end;
1436         }
1438         if (nConfiguration >= pTAS2557->mpFirmware->mnConfigurations) {
1439                 dev_err(pTAS2557->dev, "Configuration %d doesn't exist\n",
1440                         nConfiguration);
1441                 nResult = -EINVAL;
1442                 goto end;
1443         }
1445         pConfiguration = &(pTAS2557->mpFirmware->mpConfigurations[nConfiguration]);
1446         pProgram = &(pTAS2557->mpFirmware->mpPrograms[nProgram]);
1448         if (nProgram != pConfiguration->mnProgram) {
1449                 dev_err(pTAS2557->dev,
1450                         "Configuration %d, %s with Program %d isn't compatible with existing Program %d, %s\n",
1451                         nConfiguration, pConfiguration->mpName, pConfiguration->mnProgram,
1452                         nProgram, pProgram->mpName);
1453                 nResult = -EINVAL;
1454                 goto end;
1455         }
1457         nResult = tas2557_load_configuration(pTAS2557, nConfiguration, false);
1459 end:
1461         return nResult;
1464 void tas2557_clear_firmware(struct TFirmware *pFirmware)
1466         unsigned int n, nn;
1468         if (!pFirmware)
1469                 return;
1471         kfree(pFirmware->mpDescription);
1473         if (pFirmware->mpPLLs != NULL) {
1474                 for (n = 0; n < pFirmware->mnPLLs; n++) {
1475                         kfree(pFirmware->mpPLLs[n].mpDescription);
1476                         kfree(pFirmware->mpPLLs[n].mBlock.mpData);
1477                 }
1478                 kfree(pFirmware->mpPLLs);
1479         }
1481         if (pFirmware->mpPrograms != NULL) {
1482                 for (n = 0; n < pFirmware->mnPrograms; n++) {
1483                         kfree(pFirmware->mpPrograms[n].mpDescription);
1484                         kfree(pFirmware->mpPrograms[n].mData.mpDescription);
1485                         for (nn = 0; nn < pFirmware->mpPrograms[n].mData.mnBlocks; nn++)
1486                                 kfree(pFirmware->mpPrograms[n].mData.mpBlocks[nn].mpData);
1487                         kfree(pFirmware->mpPrograms[n].mData.mpBlocks);
1488                 }
1489                 kfree(pFirmware->mpPrograms);
1490         }
1492         if (pFirmware->mpConfigurations != NULL) {
1493                 for (n = 0; n < pFirmware->mnConfigurations; n++) {
1494                         kfree(pFirmware->mpConfigurations[n].mpDescription);
1495                         kfree(pFirmware->mpConfigurations[n].mData.mpDescription);
1496                         for (nn = 0; nn < pFirmware->mpConfigurations[n].mData.mnBlocks; nn++)
1497                                 kfree(pFirmware->mpConfigurations[n].mData.mpBlocks[nn].mpData);
1498                         kfree(pFirmware->mpConfigurations[n].mData.mpBlocks);
1499                 }
1500                 kfree(pFirmware->mpConfigurations);
1501         }
1503         if (pFirmware->mpCalibrations != NULL) {
1504                 for (n = 0; n < pFirmware->mnCalibrations; n++) {
1505                         kfree(pFirmware->mpCalibrations[n].mpDescription);
1506                         kfree(pFirmware->mpCalibrations[n].mData.mpDescription);
1507                         for (nn = 0; nn < pFirmware->mpCalibrations[n].mData.mnBlocks; nn++)
1508                                 kfree(pFirmware->mpCalibrations[n].mData.mpBlocks[nn].mpData);
1509                         kfree(pFirmware->mpCalibrations[n].mData.mpBlocks);
1510                 }
1511                 kfree(pFirmware->mpCalibrations);
1512         }
1514         memset(pFirmware, 0x00, sizeof(struct TFirmware));
1517 static int tas2557_load_calibration(struct tas2557_priv *pTAS2557,      char *pFileName)
1519         int nResult = 0;
1520 /*
1521 *       int nFile;
1522 *       mm_segment_t fs;
1523 *       unsigned char pBuffer[1000];
1524 *       int nSize = 0;
1526 *       dev_dbg(pTAS2557->dev, "%s:\n", __func__);
1528 *       fs = get_fs();
1529 *       set_fs(KERNEL_DS);
1530 *       nFile = sys_open(pFileName, O_RDONLY, 0);
1532 *       dev_info(pTAS2557->dev, "TAS2557 calibration file = %s, handle = %d\n",
1533 *               pFileName, nFile);
1535 *       if (nFile >= 0) {
1536 *               nSize = sys_read(nFile, pBuffer, 1000);
1537 *               sys_close(nFile);
1538 *       } else {
1539 *               dev_err(pTAS2557->dev, "TAS2557 cannot open calibration file: %s\n",
1540 *                       pFileName);
1541 *       }
1543 *       set_fs(fs);
1545 *       if (!nSize)
1546 *               goto end;
1548 *       tas2557_clear_firmware(pTAS2557->mpCalFirmware);
1549 *       dev_info(pTAS2557->dev, "TAS2557 calibration file size = %d\n", nSize);
1550 *       nResult = fw_parse(pTAS2557, pTAS2557->mpCalFirmware, pBuffer, nSize);
1552 *       if (nResult)
1553 *               dev_err(pTAS2557->dev, "TAS2557 calibration file is corrupt\n");
1554 *       else
1555 *               dev_info(pTAS2557->dev, "TAS2557 calibration: %d calibrations\n",
1556 *                       pTAS2557->mpCalFirmware->mnCalibrations);
1558 *end:
1559 **/
1560         return nResult;
1563 void tas2557_fw_ready(const struct firmware *pFW, void *pContext)
1565         struct tas2557_priv *pTAS2557 = (struct tas2557_priv *) pContext;
1566         int nResult;
1567         unsigned int nProgram = 0;
1568         unsigned int nSampleRate = 0;
1570 #ifdef CONFIG_TAS2557_CODEC
1571         mutex_lock(&pTAS2557->codec_lock);
1572 #endif
1574 #ifdef CONFIG_TAS2557_MISC
1575         mutex_lock(&pTAS2557->file_lock);
1576 #endif
1578         dev_info(pTAS2557->dev, "%s:\n", __func__);
1580         if (unlikely(!pFW) || unlikely(!pFW->data)) {
1581                 dev_err(pTAS2557->dev, "%s firmware is not loaded.\n",
1582                         TAS2557_FW_NAME);
1583                 goto end;
1584         }
1586         if (pTAS2557->mpFirmware->mpConfigurations) {
1587                 nProgram = pTAS2557->mnCurrentProgram;
1588                 nSampleRate = pTAS2557->mnCurrentSampleRate;
1589                 dev_dbg(pTAS2557->dev, "clear current firmware\n");
1590                 tas2557_clear_firmware(pTAS2557->mpFirmware);
1591         }
1593         nResult = fw_parse(pTAS2557, pTAS2557->mpFirmware, (unsigned char *)(pFW->data), pFW->size);
1594         release_firmware(pFW);
1595         if (nResult < 0) {
1596                 dev_err(pTAS2557->dev, "firmware is corrupt\n");
1597                 goto end;
1598         }
1600         if (!pTAS2557->mpFirmware->mnPrograms) {
1601                 dev_err(pTAS2557->dev, "firmware contains no programs\n");
1602                 nResult = -EINVAL;
1603                 goto end;
1604         }
1606         if (!pTAS2557->mpFirmware->mnConfigurations) {
1607                 dev_err(pTAS2557->dev, "firmware contains no configurations\n");
1608                 nResult = -EINVAL;
1609                 goto end;
1610         }
1612         if (nProgram >= pTAS2557->mpFirmware->mnPrograms) {
1613                 dev_info(pTAS2557->dev,
1614                         "no previous program, set to default\n");
1615                 nProgram = 0;
1616         }
1618         pTAS2557->mnCurrentSampleRate = nSampleRate;
1619         nResult = tas2557_set_program(pTAS2557, nProgram, -1);
1621 end:
1623 #ifdef CONFIG_TAS2557_CODEC
1624         mutex_unlock(&pTAS2557->codec_lock);
1625 #endif
1627 #ifdef CONFIG_TAS2557_MISC
1628         mutex_unlock(&pTAS2557->file_lock);
1629 #endif
1632 int tas2557_set_program(struct tas2557_priv *pTAS2557,
1633         unsigned int nProgram, int nConfig)
1635         struct TProgram *pProgram;
1636         unsigned int nConfiguration = 0;
1637         unsigned int nSampleRate = 0;
1638         unsigned char nGain;
1639         bool bFound = false;
1640         int nResult = 0;
1642         if ((!pTAS2557->mpFirmware->mpPrograms) ||
1643                 (!pTAS2557->mpFirmware->mpConfigurations)) {
1644                 dev_err(pTAS2557->dev, "Firmware not loaded\n");
1645                 nResult = 0;
1646                 goto end;
1647         }
1649         if (nProgram >= pTAS2557->mpFirmware->mnPrograms) {
1650                 dev_err(pTAS2557->dev, "TAS2557: Program %d doesn't exist\n",
1651                         nProgram);
1652                 nResult = 0;
1653                 goto end;
1654         }
1656         if (nConfig < 0) {
1657                 nConfiguration = 0;
1658                 nSampleRate = pTAS2557->mnCurrentSampleRate;
1659                 while (!bFound && (nConfiguration < pTAS2557->mpFirmware->mnConfigurations)) {
1660                         if (pTAS2557->mpFirmware->mpConfigurations[nConfiguration].mnProgram == nProgram) {
1661                                 if (nSampleRate == 0) {
1662                                         bFound = true;
1663                                         dev_info(pTAS2557->dev, "find default configuration %d\n", nConfiguration);
1664                                 } else if (nSampleRate == pTAS2557->mpFirmware->mpConfigurations[nConfiguration].mnSamplingRate) {
1665                                         bFound = true;
1666                                         dev_info(pTAS2557->dev, "find matching configuration %d\n", nConfiguration);
1667                                 } else {
1668                                         nConfiguration++;
1669                                 }
1670                         } else {
1671                                 nConfiguration++;
1672                         }
1673                 }
1674                 if (!bFound) {
1675                         dev_err(pTAS2557->dev,
1676                                 "Program %d, no valid configuration found for sample rate %d, ignore\n",
1677                                 nProgram, nSampleRate);
1678                         nResult = 0;
1679                         goto end;
1680                 }
1681         } else {
1682                 if (pTAS2557->mpFirmware->mpConfigurations[nConfig].mnProgram != nProgram) {
1683                         dev_err(pTAS2557->dev, "%s, configuration program doesn't match\n", __func__);
1684                         nResult = 0;
1685                         goto end;
1686                 }
1687                 nConfiguration = nConfig;
1688         }
1690         pProgram = &(pTAS2557->mpFirmware->mpPrograms[nProgram]);
1691         if (pTAS2557->mbPowerUp) {
1692                 dev_info(pTAS2557->dev,
1693                         "device powered up, power down to load program %d (%s)\n",
1694                         nProgram, pProgram->mpName);
1695                 if (hrtimer_active(&pTAS2557->mtimer))
1696                         hrtimer_cancel(&pTAS2557->mtimer);
1698                 if (pProgram->mnAppMode == TAS2557_APP_TUNINGMODE)
1699                         pTAS2557->enableIRQ(pTAS2557, false);
1701                 nResult = tas2557_dev_load_data(pTAS2557, p_tas2557_shutdown_data);
1702                 if (nResult < 0)
1703                         goto end;
1704         }
1706         pTAS2557->hw_reset(pTAS2557);
1707         nResult = pTAS2557->write(pTAS2557, TAS2557_SW_RESET_REG, 0x01);
1708         if (nResult < 0)
1709                 goto end;
1710         msleep(1);
1711         nResult = tas2557_load_default(pTAS2557);
1712         if (nResult < 0)
1713                 goto end;
1715         dev_info(pTAS2557->dev, "load program %d (%s)\n", nProgram, pProgram->mpName);
1716         nResult = tas2557_load_data(pTAS2557, &(pProgram->mData), TAS2557_BLOCK_PGM_DEV_A);
1717         if (nResult < 0)
1718                 goto end;
1719         pTAS2557->mnCurrentProgram = nProgram;
1721         nResult = tas2557_get_DAC_gain(pTAS2557, &nGain);
1722         if (nResult < 0)
1723                 goto end;
1724         pTAS2557->mnDevGain = nGain;
1725         pTAS2557->mnDevCurrentGain = nGain;
1727         nResult = tas2557_load_coefficient(pTAS2557, -1, nConfiguration, false);
1728         if (nResult < 0)
1729                 goto end;
1731         if (pTAS2557->mbPowerUp) {
1732                 pTAS2557->clearIRQ(pTAS2557);
1733                 dev_dbg(pTAS2557->dev, "device powered up, load startup\n");
1734                 nResult = tas2557_dev_load_data(pTAS2557, p_tas2557_startup_data);
1735                 if (nResult < 0)
1736                         goto end;
1737                 if (pProgram->mnAppMode == TAS2557_APP_TUNINGMODE) {
1738                         nResult = tas2557_checkPLL(pTAS2557);
1739                         if (nResult < 0) {
1740                                 nResult = tas2557_dev_load_data(pTAS2557, p_tas2557_shutdown_data);
1741                                 pTAS2557->mbPowerUp = false;
1742                                 goto end;
1743                         }
1744                 }
1745                 dev_dbg(pTAS2557->dev, "device powered up, load unmute\n");
1746                 nResult = tas2557_dev_load_data(pTAS2557, p_tas2557_unmute_data);
1747                 if (nResult < 0)
1748                         goto end;
1750                 if (pProgram->mnAppMode == TAS2557_APP_TUNINGMODE) {
1751                         pTAS2557->enableIRQ(pTAS2557, true);
1752                         if (!hrtimer_active(&pTAS2557->mtimer)) {
1753                                 pTAS2557->mnDieTvReadCounter = 0;
1754                                 hrtimer_start(&pTAS2557->mtimer,
1755                                         ns_to_ktime((u64)LOW_TEMPERATURE_CHECK_PERIOD * NSEC_PER_MSEC), HRTIMER_MODE_REL);
1756                         }
1757                 }
1758         }
1760 end:
1762         if (nResult < 0) {
1763                 if (pTAS2557->mnErrCode & (ERROR_DEVA_I2C_COMM | ERROR_PRAM_CRCCHK | ERROR_YRAM_CRCCHK))
1764                         failsafe(pTAS2557);
1765         }
1766         return nResult;
1769 int tas2557_set_calibration(struct tas2557_priv *pTAS2557, int nCalibration)
1771         struct TCalibration *pCalibration = NULL;
1772         struct TProgram *pProgram;
1773         int nResult = 0;
1775         if ((!pTAS2557->mpFirmware->mpPrograms)
1776                 || (!pTAS2557->mpFirmware->mpConfigurations)) {
1777                 dev_err(pTAS2557->dev, "Firmware not loaded\n\r");
1778                 nResult = 0;
1779                 goto end;
1780         }
1782         if (nCalibration == 0x00FF) {
1783                 nResult = tas2557_load_calibration(pTAS2557, TAS2557_CAL_NAME);
1784                 if (nResult < 0) {
1785                         dev_info(pTAS2557->dev, "load new calibration file %s fail %d\n",
1786                                 TAS2557_CAL_NAME, nResult);
1787                         goto end;
1788                 }
1789                 nCalibration = 0;
1790         }
1792         if (nCalibration >= pTAS2557->mpCalFirmware->mnCalibrations) {
1793                 dev_err(pTAS2557->dev,
1794                         "Calibration %d doesn't exist\n", nCalibration);
1795                 nResult = 0;
1796                 goto end;
1797         }
1799         pTAS2557->mnCurrentCalibration = nCalibration;
1800         pCalibration = &(pTAS2557->mpCalFirmware->mpCalibrations[nCalibration]);
1801         pProgram = &(pTAS2557->mpFirmware->mpPrograms[pTAS2557->mnCurrentProgram]);
1803         if (pProgram->mnAppMode == TAS2557_APP_TUNINGMODE) {
1804                 dev_dbg(pTAS2557->dev, "%s, load calibration\n", __func__);
1805                 nResult = tas2557_load_data(pTAS2557, &(pCalibration->mData), TAS2557_BLOCK_CFG_COEFF_DEV_A);
1806                 if (nResult < 0)
1807                         goto end;
1808         }
1810 end:
1811         if (nResult < 0) {
1812                 tas2557_clear_firmware(pTAS2557->mpCalFirmware);
1813                 nResult = tas2557_set_program(pTAS2557, pTAS2557->mnCurrentProgram, pTAS2557->mnCurrentConfiguration);
1814         }
1816         return nResult;
1819 int tas2557_get_Cali_prm_r0(struct tas2557_priv *pTAS2557, int *prm_r0)
1821         int nResult = 0;
1822         int n, nn;
1823         struct TCalibration *pCalibration;
1824         struct TData *pData;
1825         struct TBlock *pBlock;
1826         int nReg;
1827         int nBook, nPage, nOffset;
1828         unsigned char *pCommands;
1829         int nCali_Re;
1830         bool bFound = false;
1831         int nBlockType;
1832         int len;
1834         if (!pTAS2557->mpCalFirmware->mnCalibrations) {
1835                 dev_err(pTAS2557->dev, "%s, no calibration data\n", __func__);
1836                 goto end;
1837         }
1839         if (pTAS2557->mnPGID == TAS2557_PG_VERSION_2P1)
1840                 nReg = TAS2557_PG2P1_CALI_R0_REG;
1841         else
1842                 nReg = TAS2557_PG1P0_CALI_R0_REG;
1844         nBlockType = TAS2557_BLOCK_CFG_COEFF_DEV_A;
1846         pCalibration = &(pTAS2557->mpCalFirmware->mpCalibrations[pTAS2557->mnCurrentCalibration]);
1847         pData = &(pCalibration->mData);
1849         for (n = 0; n < pData->mnBlocks; n++) {
1850                 pBlock = &(pData->mpBlocks[n]);
1851                 if (pBlock->mnType == nBlockType) {
1852                         pCommands = pBlock->mpData;
1853                         for (nn = 0 ; nn < pBlock->mnCommands;) {
1854                                 nBook = pCommands[4 * nn + 0];
1855                                 nPage = pCommands[4 * nn + 1];
1856                                 nOffset = pCommands[4 * nn + 2];
1857                                 if ((nOffset < 0x7f) || (nOffset == 0x81))
1858                                         nn++;
1859                                 else if (nOffset == 0x85) {
1860                                         len = ((int)nBook << 8) | nPage;
1862                                         nBook = pCommands[4 * nn + 4];
1863                                         nPage = pCommands[4 * nn + 5];
1864                                         nOffset = pCommands[4 * nn + 6];
1865                                         if ((nBook == TAS2557_BOOK_ID(nReg))
1866                                                 && (nPage == TAS2557_PAGE_ID(nReg))
1867                                                 && (nOffset == TAS2557_PAGE_REG(nReg))) {
1868                                                 nCali_Re = ((int)pCommands[4 * nn + 7] << 24)
1869                                                         | ((int)pCommands[4 * nn + 8] << 16)
1870                                                         | ((int)pCommands[4 * nn + 9] << 8)
1871                                                         | (int)pCommands[4 * nn + 10];
1872                                                 bFound = true;
1873                                                 goto end;
1874                                         }
1875                                         nn++;
1876                                         nn += ((len - 1) / 4);
1877                                         if ((len - 1) % 4)
1878                                                 nn++;
1879                                 } else
1880                                         dev_err(pTAS2557->dev, "%s, format error %d\n", __func__, nOffset);
1881                         }
1882                 }
1883         }
1885 end:
1887         if (bFound)
1888                 *prm_r0 = nCali_Re;
1890         return nResult;
1893 int tas2557_parse_dt(struct device *dev, struct tas2557_priv *pTAS2557)
1895         struct device_node *np = dev->of_node;
1896         int rc = 0, ret = 0;
1897         unsigned int value;
1899         pTAS2557->mnResetGPIO = of_get_named_gpio(np, "ti,cdc-reset-gpio", 0);
1900         if (!gpio_is_valid(pTAS2557->mnResetGPIO)) {
1901                 dev_err(pTAS2557->dev, "Looking up %s property in node %s failed %d\n",
1902                         "ti,cdc-reset-gpio", np->full_name,
1903                         pTAS2557->mnResetGPIO);
1904                 ret = -EINVAL;
1905                 goto end;
1906         } else
1907                 dev_dbg(pTAS2557->dev, "ti,cdc-reset-gpio=%d\n", pTAS2557->mnResetGPIO);
1909         pTAS2557->mnGpioINT = of_get_named_gpio(np, "ti,irq-gpio", 0);
1910         if (!gpio_is_valid(pTAS2557->mnGpioINT))
1911                 dev_err(pTAS2557->dev, "Looking up %s property in node %s failed %d\n",
1912                         "ti,irq-gpio", np->full_name,
1913                         pTAS2557->mnGpioINT);
1916         rc = of_property_read_u32(np, "ti,i2s-bits", &value);
1917         if (rc)
1918                 dev_err(pTAS2557->dev, "Looking up %s property in node %s failed %d\n",
1919                         "ti,i2s-bits", np->full_name, rc);
1920         else
1921                 pTAS2557->mnI2SBits = value;
1923 end:
1925         return ret;
1928 MODULE_AUTHOR("Texas Instruments Inc.");
1929 MODULE_DESCRIPTION("TAS2557 common functions for Android Linux");
1930 MODULE_LICENSE("GPL v2");