448555cda251b79e32eab35bc7e6ee17f1ed090b
[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
47 #define TAS2557_CAL_NAME    "/data/tas2557_cal.bin"
50 static int tas2557_load_calibration(struct tas2557_priv *pTAS2557,
51         char *pFileName);
52 static int tas2557_load_data(struct tas2557_priv *pTAS2557, struct TData *pData,
53         unsigned int nType);
54 static void tas2557_clear_firmware(struct TFirmware *pFirmware);
55 static int tas2557_load_block(struct tas2557_priv *pTAS2557, struct TBlock *pBlock);
56 static int tas2557_load_configuration(struct tas2557_priv *pTAS2557,
57         unsigned int nConfiguration, bool bLoadSame);
59 #define TAS2557_UDELAY 0xFFFFFFFE
60 #define TAS2557_MDELAY 0xFFFFFFFD
62 #define TAS2557_BLOCK_PLL                               0x00
63 #define TAS2557_BLOCK_PGM_ALL                   0x0d
64 #define TAS2557_BLOCK_PGM_DEV_A                 0x01
65 #define TAS2557_BLOCK_PGM_DEV_B                 0x08
66 #define TAS2557_BLOCK_CFG_COEFF_DEV_A   0x03
67 #define TAS2557_BLOCK_CFG_COEFF_DEV_B   0x0a
68 #define TAS2557_BLOCK_CFG_PRE_DEV_A             0x04
69 #define TAS2557_BLOCK_CFG_PRE_DEV_B             0x0b
70 #define TAS2557_BLOCK_CFG_POST                  0x05
71 #define TAS2557_BLOCK_CFG_POST_POWER    0x06
73 static unsigned int p_tas2557_default_data[] = {
74         TAS2557_SAR_ADC2_REG, 0x05,     /* enable SAR ADC */
75         TAS2557_CLK_ERR_CTRL2, 0x21,    /*clk1:clock hysteresis, 0.34ms; clock halt, 22ms*/
76         TAS2557_CLK_ERR_CTRL3, 0x21,    /*clk2: rampDown 15dB/us, clock hysteresis, 10.66us; clock halt, 22ms */
77         TAS2557_SAFE_GUARD_REG, TAS2557_SAFE_GUARD_PATTERN,     /* safe guard */
78         0xFFFFFFFF, 0xFFFFFFFF
79 };
81 static unsigned int p_tas2557_irq_config[] = {
82         TAS2557_CLK_HALT_REG, 0x71,     /* enable clk halt detect2 interrupt */
83         TAS2557_INT_GEN1_REG, 0x11,     /* enable spk OC and OV */
84         TAS2557_INT_GEN2_REG, 0x11,     /* enable clk err1 and die OT */
85         TAS2557_INT_GEN3_REG, 0x11,     /* enable clk err2 and brownout */
86         TAS2557_INT_GEN4_REG, 0x01,     /* disable SAR, enable clk halt */
87         TAS2557_GPIO4_PIN_REG, 0x07,    /* set GPIO4 as int1, default */
88         TAS2557_INT_MODE_REG, 0x80,     /* active high until INT_STICKY_1 and INT_STICKY_2 are read to be cleared. */
89         0xFFFFFFFF, 0xFFFFFFFF
90 };
92 static unsigned int p_tas2557_startup_data[] = {
93         TAS2557_GPI_PIN_REG, 0x15,      /* enable DIN, MCLK, CCI */
94         TAS2557_GPIO1_PIN_REG, 0x01,    /* enable BCLK */
95         TAS2557_GPIO2_PIN_REG, 0x01,    /* enable WCLK */
96         TAS2557_POWER_CTRL2_REG, 0xA0,   /* Class-D, Boost power up */
97         TAS2557_POWER_CTRL2_REG, 0xA3,   /* Class-D, Boost, IV sense power up */
98         TAS2557_POWER_CTRL1_REG, 0xF8,   /* PLL, DSP, clock dividers power up */
99         TAS2557_UDELAY, 2000,           /* delay */
100         TAS2557_CLK_ERR_CTRL, 0x03,     /* enable clock error detection */
101         0xFFFFFFFF, 0xFFFFFFFF
102 };
104 static unsigned int p_tas2557_unmute_data[] = {
105         TAS2557_MUTE_REG, 0x00,          /* unmute */
106         TAS2557_SOFT_MUTE_REG, 0x00,     /* soft unmute */
107         0xFFFFFFFF, 0xFFFFFFFF
108 };
110 static unsigned int p_tas2557_shutdown_data[] = {
111         TAS2557_CLK_ERR_CTRL, 0x00,      /* disable clock error detection */
112         TAS2557_SOFT_MUTE_REG, 0x01,     /* soft mute */
113         TAS2557_UDELAY, 10000,           /* delay 10ms */
114         TAS2557_MUTE_REG, 0x03,          /* mute */
115         TAS2557_POWER_CTRL1_REG, 0x60,   /* DSP power down */
116         TAS2557_UDELAY, 2000,            /* delay 2ms */
117         TAS2557_POWER_CTRL2_REG, 0x00,   /* Class-D, Boost power down */
118         TAS2557_POWER_CTRL1_REG, 0x00,   /* all power down */
119         TAS2557_GPIO1_PIN_REG, 0x00,    /* disable BCLK */
120         TAS2557_GPIO2_PIN_REG, 0x00,    /* disable WCLK */
121         TAS2557_GPI_PIN_REG, 0x00,      /* disable DIN, MCLK, CCI */
122         0xFFFFFFFF, 0xFFFFFFFF
123 };
125 static int tas2557_dev_load_data(struct tas2557_priv *pTAS2557,
126         unsigned int *pData)
128         int ret = 0;
129         unsigned int n = 0;
130         unsigned int nRegister;
131         unsigned int nData;
133         do {
134                 nRegister = pData[n * 2];
135                 nData = pData[n * 2 + 1];
136                 if (nRegister == TAS2557_UDELAY)
137                         udelay(nData);
138                 else if (nRegister != 0xFFFFFFFF) {
139                         ret = pTAS2557->write(pTAS2557, nRegister, nData);
140                         if (ret < 0)
141                                 break;
142                 }
143                 n++;
144         } while (nRegister != 0xFFFFFFFF);
145         return ret;
148 int tas2557_configIRQ(struct tas2557_priv *pTAS2557)
150         return tas2557_dev_load_data(pTAS2557, p_tas2557_irq_config);
153 /*
154 * for PG2.1 Dual Mono
155 */
156 int tas2557_SA_DevChnSetup(struct tas2557_priv *pTAS2557, unsigned int mode)
158         int nResult = 0;
159         struct TProgram *pProgram;
160         unsigned char buf_mute[16] = {0};
161         unsigned char buf_DevA_Left[16] = {0x40, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0};
162         unsigned char buf_DevA_Right[16] = {0, 0, 0, 0, 0, 0, 0, 0, 0x40, 0, 0, 0, 0, 0, 0, 0};
163         unsigned char buf_DevA_MonoMix[16] = {0x20, 0, 0, 0, 0, 0, 0, 0, 0x20, 0, 0, 0, 0, 0, 0, 0};
164         unsigned char *pDevABuf;
166         dev_dbg(pTAS2557->dev, "%s, mode %d\n", __func__, mode);
167         if ((pTAS2557->mpFirmware->mnPrograms == 0)
168                 || (pTAS2557->mpFirmware->mnConfigurations == 0)) {
169                 dev_err(pTAS2557->dev, "%s, firmware not loaded\n", __func__);
170                 goto end;
171         }
173         pProgram = &(pTAS2557->mpFirmware->mpPrograms[pTAS2557->mnCurrentProgram]);
174         if (pProgram->mnAppMode != TAS2557_APP_TUNINGMODE) {
175                 dev_err(pTAS2557->dev, "%s, not tuning mode\n", __func__);
176                 goto end;
177         }
179         if (pTAS2557->mnPGID != TAS2557_PG_VERSION_2P1) {
180                 dev_err(pTAS2557->dev, "%s, currently we only support PG2.1\n", __func__);
181                 goto end;
182         }
184         if (pTAS2557->mbLoadConfigurationPrePowerUp) {
185                 dev_dbg(pTAS2557->dev, "%s, setup channel after coeff update\n", __func__);
186                 pTAS2557->mnChannelState = mode;
187                 goto end;
188         }
190         switch (mode) {
191         case TAS2557_DEVA_CHL_DEFAULT:
192         pDevABuf = pTAS2557->mnDevAChlData;
193         break;
195         case TAS2557_DEVA_CHL_MUTE:
196         pDevABuf = buf_mute;
197         break;
199         case TAS2557_DEVA_CHL_LEFT:
200         pDevABuf = buf_DevA_Left;
201         break;
203         case TAS2557_DEVA_CHL_RIGHT:
204         pDevABuf = buf_DevA_Right;
205         break;
207         case TAS2557_DEVA_CHL_MONOMIX:
208         pDevABuf = buf_DevA_MonoMix;
209         break;
210         default:
211         break;
212         }
214         if (pDevABuf) {
215                 nResult = pTAS2557->bulk_write(pTAS2557, TAS2557_SA_PG2P1_CHL_CTRL_REG, pDevABuf, 16);
216                 if (nResult < 0)
217                         goto end;
218                 pTAS2557->mnChannelState = mode;
219         }
221 end:
223         return nResult;
226 int tas2557_set_bit_rate(struct tas2557_priv *pTAS2557, unsigned int nBitRate)
228         int ret = 0, n = -1;
230         dev_dbg(pTAS2557->dev, "tas2557_set_bit_rate: nBitRate = %d\n", nBitRate);
232         switch (nBitRate) {
233         case 16:
234                 n = 0;
235                 break;
236         case 20:
237                 n = 1;
238                 break;
239         case 24:
240                 n = 2;
241                 break;
242         case 32:
243                 n = 3;
244                 break;
245         }
247         if (n >= 0)
248                 ret = pTAS2557->update_bits(pTAS2557, TAS2557_ASI1_DAC_FORMAT_REG, 0x18, n<<3);
249         return ret;
252 int tas2557_get_bit_rate(struct tas2557_priv *pTAS2557, unsigned char *pBitRate)
254         int ret = 0;
255         unsigned int nValue = 0;
256         unsigned char bitRate;
258         ret = pTAS2557->read(pTAS2557, TAS2557_ASI1_DAC_FORMAT_REG, &nValue);
259         if (ret >= 0) {
260                 bitRate = (nValue&0x18)>>3;
261                 if (bitRate == 0)
262                         bitRate = 16;
263                 else if (bitRate == 1)
264                         bitRate = 20;
265                 else if (bitRate == 2)
266                         bitRate = 24;
267                 else if (bitRate == 3)
268                         bitRate = 32;
269                 *pBitRate = bitRate;
270         }
272         return ret;
275 int tas2557_get_DAC_gain(struct tas2557_priv *pTAS2557, unsigned char *pnGain)
277         int ret = 0;
278         unsigned int nValue = 0;
280         ret = pTAS2557->read(pTAS2557, TAS2557_SPK_CTRL_REG, &nValue);
281         if (ret >= 0)
282                 *pnGain = ((nValue&TAS2557_DAC_GAIN_MASK)>>TAS2557_DAC_GAIN_SHIFT);
284         return ret;
287 int tas2557_set_DAC_gain(struct tas2557_priv *pTAS2557, unsigned int nGain)
289         int ret = 0;
291         ret = pTAS2557->update_bits(pTAS2557, TAS2557_SPK_CTRL_REG, TAS2557_DAC_GAIN_MASK,
292                 (nGain<<TAS2557_DAC_GAIN_SHIFT));
293         return ret;
296 /*
297 * die temperature calculation:
298 * DieTemp = readout / 2^23
299 */
300 int tas2557_get_die_temperature(struct tas2557_priv *pTAS2557, int *pTemperature)
302         unsigned char nBuf[4];
303         int temp;
304         int nResult = 0;
306         if (pTAS2557->mbPowerUp) {
307                 nResult = pTAS2557->bulk_read(pTAS2557, TAS2557_DIE_TEMP_REG, nBuf, 4);
308                 if (nResult >= 0) {
309                         temp = ((int)nBuf[0] << 24) | ((int)nBuf[1] << 16) | ((int)nBuf[2] << 8) | nBuf[3];
310                         *pTemperature = temp;
311                 }
312         } else
313                 dev_err(pTAS2557->dev, "Get Die Temperature when music is playing\n");
315         return nResult;
318 int tas2557_load_platdata(struct tas2557_priv *pTAS2557)
320         int nResult = 0;
322         if (gpio_is_valid(pTAS2557->mnGpioINT)) {
323                 nResult = tas2557_configIRQ(pTAS2557);
324                 if (nResult < 0)
325                         goto end;
326         }
328         nResult = tas2557_set_bit_rate(pTAS2557, pTAS2557->mnI2SBits);
330 end:
332         return nResult;
335 int tas2557_load_default(struct tas2557_priv *pTAS2557)
337         int nResult = 0;
339         nResult = tas2557_dev_load_data(pTAS2557, p_tas2557_default_data);
340         if (nResult < 0)
341                 goto end;
343         nResult = tas2557_load_platdata(pTAS2557);
344         if (nResult < 0)
345                 goto end;
347         /* enable DOUT tri-state for extra BCLKs */
348         nResult = pTAS2557->update_bits(pTAS2557, TAS2557_ASI1_DAC_FORMAT_REG, 0x01, 0x01);
349 end:
351         return nResult;
354 static void failsafe(struct tas2557_priv *pTAS2557)
356         dev_err(pTAS2557->dev, "%s\n", __func__);
357         pTAS2557->mnErrCode |= ERROR_FAILSAFE;
358         if (hrtimer_active(&pTAS2557->mtimer))
359                 hrtimer_cancel(&pTAS2557->mtimer);
360         pTAS2557->enableIRQ(pTAS2557, false);
361         tas2557_dev_load_data(pTAS2557, p_tas2557_shutdown_data);
362         pTAS2557->mbPowerUp = false;
363         pTAS2557->hw_reset(pTAS2557);
364         pTAS2557->write(pTAS2557, TAS2557_SW_RESET_REG, 0x01);
365         udelay(1000);
366         pTAS2557->write(pTAS2557, TAS2557_SPK_CTRL_REG, 0x04);
367         if (pTAS2557->mpFirmware != NULL)
368                 tas2557_clear_firmware(pTAS2557->mpFirmware);
371 int tas2557_checkPLL(struct tas2557_priv *pTAS2557)
373         int nResult = 0;
374 /*
375 * TO DO
376 */
378         return nResult;
381 /*
382 * tas2557_load_coefficient
383 */
384 static int tas2557_load_coefficient(struct tas2557_priv *pTAS2557,
385         int nPrevConfig, int nNewConfig, bool bPowerOn)
387         int nResult = 0;
388         struct TPLL *pPLL;
389         struct TProgram *pProgram;
390         struct TConfiguration *pPrevConfiguration;
391         struct TConfiguration *pNewConfiguration;
392         struct TCalibration *pCalibration = NULL;
393         bool bRestorePower = false;
395         if (!pTAS2557->mpFirmware->mnConfigurations) {
396                 dev_err(pTAS2557->dev, "%s, firmware not loaded\n", __func__);
397                 goto end;
398         }
400         if (nNewConfig >= pTAS2557->mpFirmware->mnConfigurations) {
401                 dev_err(pTAS2557->dev, "%s, invalid configuration New=%d, total=%d\n",
402                         __func__, nNewConfig, pTAS2557->mpFirmware->mnConfigurations);
403                 goto end;
404         }
406         if (nPrevConfig < 0)
407                 pPrevConfiguration = NULL;
408         else
409                 pPrevConfiguration = &(pTAS2557->mpFirmware->mpConfigurations[nPrevConfig]);
411         pNewConfiguration = &(pTAS2557->mpFirmware->mpConfigurations[nNewConfig]);
412         pTAS2557->mnCurrentConfiguration = nNewConfig;
413         if (pPrevConfiguration) {
414                 if (pPrevConfiguration->mnPLL == pNewConfiguration->mnPLL) {
415                         dev_dbg(pTAS2557->dev, "%s, PLL same\n", __func__);
416                         goto prog_coefficient;
417                 }
418         }
420         pProgram = &(pTAS2557->mpFirmware->mpPrograms[pTAS2557->mnCurrentProgram]);
421         if (bPowerOn) {
422                 dev_dbg(pTAS2557->dev, "%s, power down to load new PLL\n", __func__);
423                 if (hrtimer_active(&pTAS2557->mtimer))
424                         hrtimer_cancel(&pTAS2557->mtimer);
426                 if (pProgram->mnAppMode == TAS2557_APP_TUNINGMODE)
427                         pTAS2557->enableIRQ(pTAS2557, false);
429                 nResult = tas2557_dev_load_data(pTAS2557, p_tas2557_shutdown_data);
430                 if (nResult < 0)
431                         goto end;
432                 bRestorePower = true;
433         }
435         /* load PLL */
436         pPLL = &(pTAS2557->mpFirmware->mpPLLs[pNewConfiguration->mnPLL]);
437         dev_dbg(pTAS2557->dev, "load PLL: %s block for Configuration %s\n",
438                 pPLL->mpName, pNewConfiguration->mpName);
439         nResult = tas2557_load_block(pTAS2557, &(pPLL->mBlock));
440         if (nResult < 0)
441                 goto end;
442         pTAS2557->mnCurrentSampleRate = pNewConfiguration->mnSamplingRate;
444         dev_dbg(pTAS2557->dev, "load configuration %s conefficient pre block\n",
445                 pNewConfiguration->mpName);
446         nResult = tas2557_load_data(pTAS2557, &(pNewConfiguration->mData), TAS2557_BLOCK_CFG_PRE_DEV_A);
447         if (nResult < 0)
448                 goto end;
450 prog_coefficient:
451         dev_dbg(pTAS2557->dev, "load new configuration: %s, coeff block data\n",
452                 pNewConfiguration->mpName);
453         nResult = tas2557_load_data(pTAS2557, &(pNewConfiguration->mData),
454                 TAS2557_BLOCK_CFG_COEFF_DEV_A);
455         if (nResult < 0)
456                 goto end;
457         if (pTAS2557->mnChannelState == TAS2557_DEVA_CHL_DEFAULT) {
458                 nResult = pTAS2557->bulk_read(pTAS2557,
459                         TAS2557_SA_PG2P1_CHL_CTRL_REG, pTAS2557->mnDevAChlData, 16);
460                 if (nResult < 0)
461                         goto end;
462         } else {
463                 nResult = tas2557_SA_DevChnSetup(pTAS2557, pTAS2557->mnChannelState);
464                 if (nResult < 0)
465                         goto end;
466         }
468         if (pTAS2557->mpCalFirmware->mnCalibrations) {
469                 pCalibration = &(pTAS2557->mpCalFirmware->mpCalibrations[pTAS2557->mnCurrentCalibration]);
470                 dev_dbg(pTAS2557->dev, "load calibration\n");
471                 nResult = tas2557_load_data(pTAS2557, &(pCalibration->mData),
472                         TAS2557_BLOCK_CFG_COEFF_DEV_A);
473                 if (nResult < 0)
474                         goto end;
475         }
477         if (bRestorePower) {
478                 pTAS2557->clearIRQ(pTAS2557);
479                 dev_dbg(pTAS2557->dev, "device powered up, load startup\n");
480                 nResult = tas2557_dev_load_data(pTAS2557, p_tas2557_startup_data);
481                 if (nResult < 0)
482                         goto end;
483                 nResult = tas2557_checkPLL(pTAS2557);
484                 if (nResult < 0) {
485                         nResult = tas2557_dev_load_data(pTAS2557, p_tas2557_shutdown_data);
486                         pTAS2557->mbPowerUp = false;
487                         goto end;
488                 }
489                 dev_dbg(pTAS2557->dev,
490                         "device powered up, load unmute\n");
491                 nResult = tas2557_dev_load_data(pTAS2557, p_tas2557_unmute_data);
492                 if (nResult < 0)
493                         goto end;
494                 if (pProgram->mnAppMode == TAS2557_APP_TUNINGMODE) {
495                         pTAS2557->enableIRQ(pTAS2557, true);
496                         if (!hrtimer_active(&pTAS2557->mtimer)) {
497                                 pTAS2557->mnDieTvReadCounter = 0;
498                                 hrtimer_start(&pTAS2557->mtimer,
499                                         ns_to_ktime((u64)LOW_TEMPERATURE_CHECK_PERIOD * NSEC_PER_MSEC), HRTIMER_MODE_REL);
500                         }
501                 }
502         }
503 end:
505         return nResult;
508 int tas2557_enable(struct tas2557_priv *pTAS2557, bool bEnable)
510         int nResult = 0;
511         unsigned int nValue;
512         struct TProgram *pProgram;
514         dev_dbg(pTAS2557->dev, "Enable: %d\n", bEnable);
516         if ((pTAS2557->mpFirmware->mnPrograms == 0)
517                 || (pTAS2557->mpFirmware->mnConfigurations == 0)) {
518                 dev_err(pTAS2557->dev, "%s, firmware not loaded\n", __func__);
519                 goto end;
520         }
521         /* check safe guard*/
522         nResult = pTAS2557->read(pTAS2557, TAS2557_SAFE_GUARD_REG, &nValue);
523         if (nResult < 0)
524                 goto end;
525         if ((nValue&0xff) != TAS2557_SAFE_GUARD_PATTERN) {
526                 dev_err(pTAS2557->dev, "ERROR safe guard failure!\n");
527                 nResult = -EPIPE;
528                 goto end;
529         }
531         pProgram = &(pTAS2557->mpFirmware->mpPrograms[pTAS2557->mnCurrentProgram]);
532         if (bEnable) {
533                 if (!pTAS2557->mbPowerUp) {
534                         if (pTAS2557->mbLoadConfigurationPrePowerUp) {
535                                 dev_dbg(pTAS2557->dev, "load coefficient before power\n");
536                                 nResult = tas2557_load_coefficient(pTAS2557,
537                                         pTAS2557->mnCurrentConfiguration, pTAS2557->mnNewConfiguration, false);
538                                 if (nResult < 0)
539                                         goto end;
540                                 pTAS2557->mbLoadConfigurationPrePowerUp = false;
541                         }
543                         pTAS2557->clearIRQ(pTAS2557);
544                         /* power on device */
545                         dev_dbg(pTAS2557->dev, "Enable: load startup sequence\n");
546                         nResult = tas2557_dev_load_data(pTAS2557, p_tas2557_startup_data);
547                         if (nResult < 0)
548                                 goto end;
549                         if (pProgram->mnAppMode == TAS2557_APP_TUNINGMODE) {
550                                 nResult = tas2557_checkPLL(pTAS2557);
551                                 if (nResult < 0) {
552                                         nResult = tas2557_dev_load_data(pTAS2557, p_tas2557_shutdown_data);
553                                         goto end;
554                                 }
555                         }
556                         dev_dbg(pTAS2557->dev, "Enable: load unmute sequence\n");
557                         nResult = tas2557_dev_load_data(pTAS2557, p_tas2557_unmute_data);
558                         if (nResult < 0)
559                                 goto end;
561                         if (pProgram->mnAppMode == TAS2557_APP_TUNINGMODE) {
562                                 /* turn on IRQ */
563                                 pTAS2557->enableIRQ(pTAS2557, true);
564                                 if (!hrtimer_active(&pTAS2557->mtimer)) {
565                                         pTAS2557->mnDieTvReadCounter = 0;
566                                         hrtimer_start(&pTAS2557->mtimer,
567                                                 ns_to_ktime((u64)LOW_TEMPERATURE_CHECK_PERIOD * NSEC_PER_MSEC), HRTIMER_MODE_REL);
568                                 }
569                         }
570                         pTAS2557->mbPowerUp = true;
571                 }
572         } else {
573                 if (pTAS2557->mbPowerUp) {
574                         if (hrtimer_active(&pTAS2557->mtimer))
575                                 hrtimer_cancel(&pTAS2557->mtimer);
577                         dev_dbg(pTAS2557->dev, "Enable: load shutdown sequence\n");
578                         if (pProgram->mnAppMode == TAS2557_APP_TUNINGMODE) {
579                                 /* turn off IRQ */
580                                 pTAS2557->enableIRQ(pTAS2557, false);
581                         }
582                         nResult = tas2557_dev_load_data(pTAS2557, p_tas2557_shutdown_data);
583                         if (nResult < 0)
584                                 goto end;
586                         pTAS2557->mbPowerUp = false;
587                 }
588         }
590         nResult = 0;
592 end:
593         if (nResult < 0) {
594                 if (pTAS2557->mnErrCode & (ERROR_DEVA_I2C_COMM | ERROR_PRAM_CRCCHK | ERROR_YRAM_CRCCHK))
595                         failsafe(pTAS2557);
596         }
598         return nResult;
601 int tas2557_set_sampling_rate(struct tas2557_priv *pTAS2557, unsigned int nSamplingRate)
603         int nResult = 0;
604         struct TConfiguration *pConfiguration;
605         unsigned int nConfiguration;
607         dev_dbg(pTAS2557->dev, "tas2557_setup_clocks: nSamplingRate = %d [Hz]\n",
608                 nSamplingRate);
610         if ((!pTAS2557->mpFirmware->mpPrograms) ||
611                 (!pTAS2557->mpFirmware->mpConfigurations)) {
612                 dev_err(pTAS2557->dev, "Firmware not loaded\n");
613                 nResult = -EINVAL;
614                 goto end;
615         }
617         pConfiguration = &(pTAS2557->mpFirmware->mpConfigurations[pTAS2557->mnCurrentConfiguration]);
618         if (pConfiguration->mnSamplingRate == nSamplingRate) {
619                 dev_info(pTAS2557->dev, "Sampling rate for current configuration matches: %d\n",
620                         nSamplingRate);
621                 nResult = 0;
622                 goto end;
623         }
625         for (nConfiguration = 0;
626                 nConfiguration < pTAS2557->mpFirmware->mnConfigurations;
627                 nConfiguration++) {
628                 pConfiguration =
629                         &(pTAS2557->mpFirmware->mpConfigurations[nConfiguration]);
630                 if ((pConfiguration->mnSamplingRate == nSamplingRate)
631                         && (pConfiguration->mnProgram == pTAS2557->mnCurrentProgram)) {
632                         dev_info(pTAS2557->dev,
633                                 "Found configuration: %s, with compatible sampling rate %d\n",
634                                 pConfiguration->mpName, nSamplingRate);
635                         nResult = tas2557_load_configuration(pTAS2557, nConfiguration, false);
636                         goto end;
637                 }
638         }
640         dev_err(pTAS2557->dev, "Cannot find a configuration that supports sampling rate: %d\n",
641                 nSamplingRate);
643 end:
645         return nResult;
648 static void fw_print_header(struct tas2557_priv *pTAS2557, struct TFirmware *pFirmware)
650         dev_info(pTAS2557->dev, "FW Size       = %d", pFirmware->mnFWSize);
651         dev_info(pTAS2557->dev, "Checksum      = 0x%04X", pFirmware->mnChecksum);
652         dev_info(pTAS2557->dev, "PPC Version   = 0x%04X", pFirmware->mnPPCVersion);
653         dev_info(pTAS2557->dev, "FW  Version    = 0x%04X", pFirmware->mnFWVersion);
654         dev_info(pTAS2557->dev, "Driver Version= 0x%04X", pFirmware->mnDriverVersion);
655         dev_info(pTAS2557->dev, "Timestamp     = %d", pFirmware->mnTimeStamp);
656         dev_info(pTAS2557->dev, "DDC Name      = %s", pFirmware->mpDDCName);
657         dev_info(pTAS2557->dev, "Description   = %s", pFirmware->mpDescription);
660 inline unsigned int fw_convert_number(unsigned char *pData)
662         return pData[3] + (pData[2] << 8) + (pData[1] << 16) + (pData[0] << 24);
665 static int fw_parse_header(struct tas2557_priv *pTAS2557,
666         struct TFirmware *pFirmware, unsigned char *pData, unsigned int nSize)
668         unsigned char *pDataStart = pData;
669         unsigned int n;
670         unsigned char pMagicNumber[] = { 0x35, 0x35, 0x35, 0x32 };
672         if (nSize < 104) {
673                 dev_err(pTAS2557->dev, "Firmware: Header too short");
674                 return -EINVAL;
675         }
677         if (memcmp(pData, pMagicNumber, 4)) {
678                 dev_err(pTAS2557->dev, "Firmware: Magic number doesn't match");
679                 return -EINVAL;
680         }
681         pData += 4;
683         pFirmware->mnFWSize = fw_convert_number(pData);
684         pData += 4;
686         pFirmware->mnChecksum = fw_convert_number(pData);
687         pData += 4;
689         pFirmware->mnPPCVersion = fw_convert_number(pData);
690         pData += 4;
692         pFirmware->mnFWVersion = fw_convert_number(pData);
693         pData += 4;
695         pFirmware->mnDriverVersion = fw_convert_number(pData);
696         pData += 4;
698         pFirmware->mnTimeStamp = fw_convert_number(pData);
699         pData += 4;
701         memcpy(pFirmware->mpDDCName, pData, 64);
702         pData += 64;
704         n = strlen(pData);
705         pFirmware->mpDescription = kmemdup(pData, n + 1, GFP_KERNEL);
706         pData += n + 1;
707         if ((pData - pDataStart) >= nSize) {
708                 dev_err(pTAS2557->dev, "Firmware: Header too short after DDC description");
709                 return -EINVAL;
710         }
712         pFirmware->mnDeviceFamily = fw_convert_number(pData);
713         pData += 4;
714         if (pFirmware->mnDeviceFamily != 0) {
715                 dev_err(pTAS2557->dev,
716                         "deviceFamily %d, not TAS device", pFirmware->mnDeviceFamily);
717                 return -EINVAL;
718         }
720         pFirmware->mnDevice = fw_convert_number(pData);
721         pData += 4;
723         if (pFirmware->mnDevice != 2) {
724                 dev_err(pTAS2557->dev,
725                         "device %d, not TAS2557 Dual Mono", pFirmware->mnDevice);
726                 return -EINVAL;
727         }
729         fw_print_header(pTAS2557, pFirmware);
730         return pData - pDataStart;
733 static int fw_parse_block_data(struct tas2557_priv *pTAS2557, struct TFirmware *pFirmware,
734         struct TBlock *pBlock, unsigned char *pData)
736         unsigned char *pDataStart = pData;
737         unsigned int n;
739         pBlock->mnType = fw_convert_number(pData);
740         pData += 4;
742         if (pFirmware->mnDriverVersion >= PPC_DRIVER_CRCCHK) {
743                 pBlock->mbPChkSumPresent = pData[0];
744                 pData++;
746                 pBlock->mnPChkSum = pData[0];
747                 pData++;
749                 pBlock->mbYChkSumPresent = pData[0];
750                 pData++;
752                 pBlock->mnYChkSum = pData[0];
753                 pData++;
754         } else {
755                 pBlock->mbPChkSumPresent = 0;
756                 pBlock->mbYChkSumPresent = 0;
757         }
759         pBlock->mnCommands = fw_convert_number(pData);
760         pData += 4;
762         n = pBlock->mnCommands * 4;
763         pBlock->mpData = kmemdup(pData, n, GFP_KERNEL);
764         pData += n;
765         return pData - pDataStart;
768 static int fw_parse_data(struct tas2557_priv *pTAS2557, struct TFirmware *pFirmware,
769         struct TData *pImageData, unsigned char *pData)
771         unsigned char *pDataStart = pData;
772         unsigned int nBlock;
773         unsigned int n;
775         memcpy(pImageData->mpName, pData, 64);
776         pData += 64;
778         n = strlen(pData);
779         pImageData->mpDescription = kmemdup(pData, n + 1, GFP_KERNEL);
780         pData += n + 1;
782         pImageData->mnBlocks = (pData[0] << 8) + pData[1];
783         pData += 2;
785         pImageData->mpBlocks =
786                 kmalloc(sizeof(struct TBlock) * pImageData->mnBlocks, GFP_KERNEL);
788         for (nBlock = 0; nBlock < pImageData->mnBlocks; nBlock++) {
789                 n = fw_parse_block_data(pTAS2557, pFirmware,
790                         &(pImageData->mpBlocks[nBlock]), pData);
791                 pData += n;
792         }
793         return pData - pDataStart;
796 static int fw_parse_pll_data(struct tas2557_priv *pTAS2557,
797         struct TFirmware *pFirmware, unsigned char *pData)
799         unsigned char *pDataStart = pData;
800         unsigned int n;
801         unsigned int nPLL;
802         struct TPLL *pPLL;
804         pFirmware->mnPLLs = (pData[0] << 8) + pData[1];
805         pData += 2;
807         if (pFirmware->mnPLLs == 0)
808                 goto end;
810         pFirmware->mpPLLs = kmalloc_array(pFirmware->mnPLLs, sizeof(struct TPLL), GFP_KERNEL);
811         for (nPLL = 0; nPLL < pFirmware->mnPLLs; nPLL++) {
812                 pPLL = &(pFirmware->mpPLLs[nPLL]);
814                 memcpy(pPLL->mpName, pData, 64);
815                 pData += 64;
817                 n = strlen(pData);
818                 pPLL->mpDescription = kmemdup(pData, n + 1, GFP_KERNEL);
819                 pData += n + 1;
821                 n = fw_parse_block_data(pTAS2557, pFirmware, &(pPLL->mBlock), pData);
822                 pData += n;
823         }
825 end:
826         return pData - pDataStart;
829 static int fw_parse_program_data(struct tas2557_priv *pTAS2557,
830         struct TFirmware *pFirmware, unsigned char *pData)
832         unsigned char *pDataStart = pData;
833         unsigned int n;
834         unsigned int nProgram;
835         struct TProgram *pProgram;
837         pFirmware->mnPrograms = (pData[0] << 8) + pData[1];
838         pData += 2;
840         if (pFirmware->mnPrograms == 0)
841                 goto end;
843         pFirmware->mpPrograms =
844                 kmalloc(sizeof(struct TProgram) * pFirmware->mnPrograms, GFP_KERNEL);
845         for (nProgram = 0; nProgram < pFirmware->mnPrograms; nProgram++) {
846                 pProgram = &(pFirmware->mpPrograms[nProgram]);
847                 memcpy(pProgram->mpName, pData, 64);
848                 pData += 64;
850                 n = strlen(pData);
851                 pProgram->mpDescription = kmemdup(pData, n + 1, GFP_KERNEL);
852                 pData += n + 1;
854                 pProgram->mnAppMode = pData[0];
855                 pData++;
857                 pProgram->mnBoost = (pData[0] << 8) + pData[1];
858                 pData += 2;
860                 n = fw_parse_data(pTAS2557, pFirmware, &(pProgram->mData), pData);
861                 pData += n;
862         }
864 end:
866         return pData - pDataStart;
869 static int fw_parse_configuration_data(struct tas2557_priv *pTAS2557,
870         struct TFirmware *pFirmware, unsigned char *pData)
872         unsigned char *pDataStart = pData;
873         unsigned int n;
874         unsigned int nConfiguration;
875         struct TConfiguration *pConfiguration;
877         pFirmware->mnConfigurations = (pData[0] << 8) + pData[1];
878         pData += 2;
880         if (pFirmware->mnConfigurations == 0)
881                 goto end;
883         pFirmware->mpConfigurations =
884                 kmalloc(sizeof(struct TConfiguration) * pFirmware->mnConfigurations,
885                 GFP_KERNEL);
886         for (nConfiguration = 0; nConfiguration < pFirmware->mnConfigurations;
887                 nConfiguration++) {
888                 pConfiguration = &(pFirmware->mpConfigurations[nConfiguration]);
889                 memcpy(pConfiguration->mpName, pData, 64);
890                 pData += 64;
892                 n = strlen(pData);
893                 pConfiguration->mpDescription = kmemdup(pData, n + 1, GFP_KERNEL);
894                 pData += n + 1;
896                 if (pFirmware->mnDriverVersion >= PPC_DRIVER_CONFDEV) {
897                         pConfiguration->mnDevices = (pData[0] << 8) + pData[1];
898                         pData += 2;
899                 } else
900                         pConfiguration->mnDevices = 0;
902                 pConfiguration->mnProgram = pData[0];
903                 pData++;
905                 pConfiguration->mnPLL = pData[0];
906                 pData++;
908                 pConfiguration->mnSamplingRate = fw_convert_number(pData);
909                 pData += 4;
911                 n = fw_parse_data(pTAS2557, pFirmware, &(pConfiguration->mData), pData);
912                 pData += n;
913         }
915 end:
917         return pData - pDataStart;
920 int fw_parse_calibration_data(struct tas2557_priv *pTAS2557,
921         struct TFirmware *pFirmware, unsigned char *pData)
923         unsigned char *pDataStart = pData;
924         unsigned int n;
925         unsigned int nCalibration;
926         struct TCalibration *pCalibration;
928         pFirmware->mnCalibrations = (pData[0] << 8) + pData[1];
929         pData += 2;
931         if (pFirmware->mnCalibrations == 0)
932                 goto end;
934         pFirmware->mpCalibrations =
935                 kmalloc(sizeof(struct TCalibration) * pFirmware->mnCalibrations, GFP_KERNEL);
936         for (nCalibration = 0;
937                 nCalibration < pFirmware->mnCalibrations;
938                 nCalibration++) {
939                 pCalibration = &(pFirmware->mpCalibrations[nCalibration]);
940                 memcpy(pCalibration->mpName, pData, 64);
941                 pData += 64;
943                 n = strlen(pData);
944                 pCalibration->mpDescription = kmemdup(pData, n + 1, GFP_KERNEL);
945                 pData += n + 1;
947                 pCalibration->mnProgram = pData[0];
948                 pData++;
950                 pCalibration->mnConfiguration = pData[0];
951                 pData++;
953                 n = fw_parse_data(pTAS2557, pFirmware, &(pCalibration->mData), pData);
954                 pData += n;
955         }
957 end:
959         return pData - pDataStart;
962 static int fw_parse(struct tas2557_priv *pTAS2557,
963         struct TFirmware *pFirmware, unsigned char *pData, unsigned int nSize)
965         int nPosition = 0;
967         nPosition = fw_parse_header(pTAS2557, pFirmware, pData, nSize);
968         if (nPosition < 0) {
969                 dev_err(pTAS2557->dev, "Firmware: Wrong Header");
970                 return -EINVAL;
971         }
973         if (nPosition >= nSize) {
974                 dev_err(pTAS2557->dev, "Firmware: Too short");
975                 return -EINVAL;
976         }
978         pData += nPosition;
979         nSize -= nPosition;
980         nPosition = 0;
982         nPosition = fw_parse_pll_data(pTAS2557, pFirmware, pData);
984         pData += nPosition;
985         nSize -= nPosition;
986         nPosition = 0;
988         nPosition = fw_parse_program_data(pTAS2557, pFirmware, pData);
990         pData += nPosition;
991         nSize -= nPosition;
992         nPosition = 0;
994         nPosition = fw_parse_configuration_data(pTAS2557, pFirmware, pData);
996         pData += nPosition;
997         nSize -= nPosition;
998         nPosition = 0;
1000         if (nSize > 64)
1001                 nPosition = fw_parse_calibration_data(pTAS2557, pFirmware, pData);
1002         return 0;
1006 static const unsigned char crc8_lookup_table[CRC8_TABLE_SIZE] = {
1007 0x00, 0x4D, 0x9A, 0xD7, 0x79, 0x34, 0xE3, 0xAE, 0xF2, 0xBF, 0x68, 0x25, 0x8B, 0xC6, 0x11, 0x5C,
1008 0xA9, 0xE4, 0x33, 0x7E, 0xD0, 0x9D, 0x4A, 0x07, 0x5B, 0x16, 0xC1, 0x8C, 0x22, 0x6F, 0xB8, 0xF5,
1009 0x1F, 0x52, 0x85, 0xC8, 0x66, 0x2B, 0xFC, 0xB1, 0xED, 0xA0, 0x77, 0x3A, 0x94, 0xD9, 0x0E, 0x43,
1010 0xB6, 0xFB, 0x2C, 0x61, 0xCF, 0x82, 0x55, 0x18, 0x44, 0x09, 0xDE, 0x93, 0x3D, 0x70, 0xA7, 0xEA,
1011 0x3E, 0x73, 0xA4, 0xE9, 0x47, 0x0A, 0xDD, 0x90, 0xCC, 0x81, 0x56, 0x1B, 0xB5, 0xF8, 0x2F, 0x62,
1012 0x97, 0xDA, 0x0D, 0x40, 0xEE, 0xA3, 0x74, 0x39, 0x65, 0x28, 0xFF, 0xB2, 0x1C, 0x51, 0x86, 0xCB,
1013 0x21, 0x6C, 0xBB, 0xF6, 0x58, 0x15, 0xC2, 0x8F, 0xD3, 0x9E, 0x49, 0x04, 0xAA, 0xE7, 0x30, 0x7D,
1014 0x88, 0xC5, 0x12, 0x5F, 0xF1, 0xBC, 0x6B, 0x26, 0x7A, 0x37, 0xE0, 0xAD, 0x03, 0x4E, 0x99, 0xD4,
1015 0x7C, 0x31, 0xE6, 0xAB, 0x05, 0x48, 0x9F, 0xD2, 0x8E, 0xC3, 0x14, 0x59, 0xF7, 0xBA, 0x6D, 0x20,
1016 0xD5, 0x98, 0x4F, 0x02, 0xAC, 0xE1, 0x36, 0x7B, 0x27, 0x6A, 0xBD, 0xF0, 0x5E, 0x13, 0xC4, 0x89,
1017 0x63, 0x2E, 0xF9, 0xB4, 0x1A, 0x57, 0x80, 0xCD, 0x91, 0xDC, 0x0B, 0x46, 0xE8, 0xA5, 0x72, 0x3F,
1018 0xCA, 0x87, 0x50, 0x1D, 0xB3, 0xFE, 0x29, 0x64, 0x38, 0x75, 0xA2, 0xEF, 0x41, 0x0C, 0xDB, 0x96,
1019 0x42, 0x0F, 0xD8, 0x95, 0x3B, 0x76, 0xA1, 0xEC, 0xB0, 0xFD, 0x2A, 0x67, 0xC9, 0x84, 0x53, 0x1E,
1020 0xEB, 0xA6, 0x71, 0x3C, 0x92, 0xDF, 0x08, 0x45, 0x19, 0x54, 0x83, 0xCE, 0x60, 0x2D, 0xFA, 0xB7,
1021 0x5D, 0x10, 0xC7, 0x8A, 0x24, 0x69, 0xBE, 0xF3, 0xAF, 0xE2, 0x35, 0x78, 0xD6, 0x9B, 0x4C, 0x01,
1022 0xF4, 0xB9, 0x6E, 0x23, 0x8D, 0xC0, 0x17, 0x5A, 0x06, 0x4B, 0x9C, 0xD1, 0x7F, 0x32, 0xE5, 0xA8
1023 };
1025 static int isInPageYRAM(struct tas2557_priv *pTAS2557, struct TYCRC *pCRCData,
1026         unsigned char nBook, unsigned char nPage, unsigned char nReg, unsigned char len)
1028         int nResult = 0;
1030         if (nBook == TAS2557_YRAM_BOOK1) {
1031                 if (nPage == TAS2557_YRAM1_PAGE) {
1032                         if (nReg >= TAS2557_YRAM1_START_REG) {
1033                                 pCRCData->mnOffset = nReg;
1034                                 pCRCData->mnLen = len;
1035                                 nResult = 1;
1036                         } else if ((nReg + len) > TAS2557_YRAM1_START_REG) {
1037                                 pCRCData->mnOffset = TAS2557_YRAM1_START_REG;
1038                                 pCRCData->mnLen = len - (TAS2557_YRAM1_START_REG - nReg);
1039                                 nResult = 1;
1040                         } else
1041                                 nResult = 0;
1042                 } else if (nPage == TAS2557_YRAM3_PAGE) {
1043                         if (nReg > TAS2557_YRAM3_END_REG) {
1044                                 nResult = 0;
1045                         } else if (nReg >= TAS2557_YRAM3_START_REG) {
1046                                 if ((nReg + len) > TAS2557_YRAM3_END_REG) {
1047                                         pCRCData->mnOffset = nReg;
1048                                         pCRCData->mnLen = TAS2557_YRAM3_END_REG - nReg + 1;
1049                                         nResult = 1;
1050                                 } else {
1051                                         pCRCData->mnOffset = nReg;
1052                                         pCRCData->mnLen = len;
1053                                         nResult = 1;
1054                                 }
1055                         } else {
1056                                 if ((nReg + len) < TAS2557_YRAM3_START_REG)
1057                                         nResult = 0;
1058                                 else {
1059                                         pCRCData->mnOffset = TAS2557_YRAM3_START_REG;
1060                                         pCRCData->mnLen = len - (TAS2557_YRAM3_START_REG - nReg);
1061                                         nResult = 1;
1062                                 }
1063                         }
1064                 }
1065         } else if (nBook == TAS2557_YRAM_BOOK2) {
1066                 if (nPage == TAS2557_YRAM5_PAGE) {
1067                         if (nReg > TAS2557_YRAM5_END_REG) {
1068                                 nResult = 0;
1069                         } else if (nReg >= TAS2557_YRAM5_START_REG) {
1070                                 if ((nReg + len) > TAS2557_YRAM5_END_REG) {
1071                                         pCRCData->mnOffset = nReg;
1072                                         pCRCData->mnLen = TAS2557_YRAM5_END_REG - nReg + 1;
1073                                         nResult = 1;
1074                                 } else {
1075                                         pCRCData->mnOffset = nReg;
1076                                         pCRCData->mnLen = len;
1077                                         nResult = 1;
1078                                 }
1079                         } else {
1080                                 if ((nReg + len) < TAS2557_YRAM5_START_REG)
1081                                         nResult = 0;
1082                                 else {
1083                                         pCRCData->mnOffset = TAS2557_YRAM5_START_REG;
1084                                         pCRCData->mnLen = len - (TAS2557_YRAM5_START_REG - nReg);
1085                                         nResult = 1;
1086                                 }
1087                         }
1088                 }
1089         } else
1090                 nResult = 0;
1092         return nResult;
1095 static int isInBlockYRAM(struct tas2557_priv *pTAS2557, struct TYCRC *pCRCData,
1096         unsigned char nBook, unsigned char nPage, unsigned char nReg, unsigned char len)
1098         int nResult;
1100         if (nBook == TAS2557_YRAM_BOOK1) {
1101                 if (nPage < TAS2557_YRAM2_START_PAGE)
1102                         nResult = 0;
1103                 else if (nPage <= TAS2557_YRAM2_END_PAGE) {
1104                         if (nReg > TAS2557_YRAM2_END_REG)
1105                                 nResult = 0;
1106                         else if (nReg >= TAS2557_YRAM2_START_REG) {
1107                                 pCRCData->mnOffset = nReg;
1108                                 pCRCData->mnLen = len;
1109                                 nResult = 1;
1110                         } else {
1111                                 if ((nReg + len) < TAS2557_YRAM2_START_REG)
1112                                         nResult = 0;
1113                                 else {
1114                                         pCRCData->mnOffset = TAS2557_YRAM2_START_REG;
1115                                         pCRCData->mnLen = nReg + len - TAS2557_YRAM2_START_REG;
1116                                         nResult = 1;
1117                                 }
1118                         }
1119                 } else
1120                         nResult = 0;
1121         } else if (nBook == TAS2557_YRAM_BOOK2) {
1122                 if (nPage < TAS2557_YRAM4_START_PAGE)
1123                         nResult = 0;
1124                 else if (nPage <= TAS2557_YRAM4_END_PAGE) {
1125                         if (nReg > TAS2557_YRAM2_END_REG)
1126                                 nResult = 0;
1127                         else if (nReg >= TAS2557_YRAM2_START_REG) {
1128                                 pCRCData->mnOffset = nReg;
1129                                 pCRCData->mnLen = len;
1130                                 nResult = 1;
1131                         } else {
1132                                 if ((nReg + len) < TAS2557_YRAM2_START_REG)
1133                                         nResult = 0;
1134                                 else {
1135                                         pCRCData->mnOffset = TAS2557_YRAM2_START_REG;
1136                                         pCRCData->mnLen = nReg + len - TAS2557_YRAM2_START_REG;
1137                                         nResult = 1;
1138                                 }
1139                         }
1140                 } else
1141                         nResult = 0;
1142         } else
1143                 nResult = 0;
1145         return nResult;
1149 static int isYRAM(struct tas2557_priv *pTAS2557, struct TYCRC *pCRCData,
1150         unsigned char nBook, unsigned char nPage, unsigned char nReg, unsigned char len)
1152         int nResult;
1154         nResult = isInPageYRAM(pTAS2557, pCRCData, nBook, nPage, nReg, len);
1156         if (nResult == 0)
1157                 nResult = isInBlockYRAM(pTAS2557, pCRCData, nBook, nPage, nReg, len);
1159         return nResult;
1162 /*
1163  * crc8 - calculate a crc8 over the given input data.
1164  *
1165  * table: crc table used for calculation.
1166  * pdata: pointer to data buffer.
1167  * nbytes: number of bytes in data buffer.
1168  * crc: previous returned crc8 value.
1169  */
1170 static u8 ti_crc8(const u8 table[CRC8_TABLE_SIZE], u8 *pdata, size_t nbytes, u8 crc)
1172         /* loop over the buffer data */
1173         while (nbytes-- > 0)
1174                 crc = table[(crc ^ *pdata++) & 0xff];
1176         return crc;
1179 static int doSingleRegCheckSum(struct tas2557_priv *pTAS2557, 
1180         unsigned char nBook, unsigned char nPage, unsigned char nReg, unsigned char nValue)
1182         int nResult = 0;
1183         struct TYCRC sCRCData;
1184         unsigned int nData1 = 0;
1186         if ((nBook == TAS2557_BOOK_ID(TAS2557_SA_COEFF_SWAP_REG))
1187                 && (nPage == TAS2557_PAGE_ID(TAS2557_SA_COEFF_SWAP_REG))
1188                 && (nReg >= TAS2557_PAGE_REG(TAS2557_SA_COEFF_SWAP_REG))
1189                 && (nReg <= (TAS2557_PAGE_REG(TAS2557_SA_COEFF_SWAP_REG) + 4))) {
1190                 /* DSP swap command, pass */
1191                 nResult = 0;
1192                 goto end;
1193         }
1195         nResult = isYRAM(pTAS2557, &sCRCData, nBook, nPage, nReg, 1);
1196         if (nResult == 1) {
1197                 nResult = pTAS2557->read(pTAS2557, TAS2557_REG(nBook, nPage, nReg), &nData1);
1198                 if (nResult < 0)
1199                         goto end;
1201                 if (nData1 != nValue) {
1202                         dev_err(pTAS2557->dev, "error2 (line %d),B[0x%x]P[0x%x]R[0x%x] W[0x%x], R[0x%x]\n",
1203                                 __LINE__, nBook, nPage, nReg, nValue, nData1);
1204                         nResult = -EAGAIN;
1205                         goto end;
1206                 }
1208                 nResult = ti_crc8(crc8_lookup_table, &nValue, 1, 0);
1209         }
1211 end:
1213         return nResult;
1216 static int doMultiRegCheckSum(struct tas2557_priv *pTAS2557, 
1217         unsigned char nBook, unsigned char nPage, unsigned char nReg, unsigned int len)
1219         int nResult = 0, i;
1220         unsigned char nCRCChkSum = 0;
1221         unsigned char nBuf1[128];
1222         struct TYCRC TCRCData;
1224         if ((nReg + len-1) > 127) {
1225                 nResult = -EINVAL;
1226                 dev_err(pTAS2557->dev, "firmware error\n");
1227                 goto end;
1228         }
1230         if ((nBook == TAS2557_BOOK_ID(TAS2557_SA_COEFF_SWAP_REG))
1231                 && (nPage == TAS2557_PAGE_ID(TAS2557_SA_COEFF_SWAP_REG))
1232                 && (nReg == TAS2557_PAGE_REG(TAS2557_SA_COEFF_SWAP_REG))
1233                 && (len == 4)) {
1234                 /* DSP swap command, pass */
1235                 nResult = 0;
1236                 goto end;
1237         }
1239         nResult = isYRAM(pTAS2557, &TCRCData, nBook, nPage, nReg, len);
1240         if (nResult == 1) {
1241                 if (len == 1) {
1242                         dev_err(pTAS2557->dev, "firmware error\n");
1243                         nResult = -EINVAL;
1244                         goto end;
1245                 } else {
1246                         nResult = pTAS2557->bulk_read(pTAS2557, TAS2557_REG(nBook, nPage, TCRCData.mnOffset), nBuf1, TCRCData.mnLen);
1247                         if (nResult < 0)
1248                                 goto end;
1250                         for (i = 0; i < TCRCData.mnLen; i++) {
1251                                 if ((nBook == TAS2557_BOOK_ID(TAS2557_SA_COEFF_SWAP_REG))
1252                                         && (nPage == TAS2557_PAGE_ID(TAS2557_SA_COEFF_SWAP_REG))
1253                                         && ((i + TCRCData.mnOffset)
1254                                                 >= TAS2557_PAGE_REG(TAS2557_SA_COEFF_SWAP_REG))
1255                                         && ((i + TCRCData.mnOffset)
1256                                                 <= (TAS2557_PAGE_REG(TAS2557_SA_COEFF_SWAP_REG) + 4))) {
1257                                         /* DSP swap command, bypass */
1258                                         continue;
1259                                 } else
1260                                         nCRCChkSum += ti_crc8(crc8_lookup_table, &nBuf1[i], 1, 0);
1261                         }
1263                         nResult = nCRCChkSum;
1264                 }
1265         }
1267 end:
1269         return nResult;
1272 static int tas2557_load_block(struct tas2557_priv *pTAS2557, struct TBlock *pBlock)
1274         int nResult = 0;
1275         unsigned int nCommand = 0;
1276         unsigned char nBook;
1277         unsigned char nPage;
1278         unsigned char nOffset;
1279         unsigned char nData;
1280         unsigned int nLength;
1281         unsigned int nSleep;
1282         unsigned char nCRCChkSum = 0;
1283         unsigned int nValue1;
1284         int nRetry = 6;
1285         unsigned char *pData = pBlock->mpData;
1287         dev_dbg(pTAS2557->dev, "TAS2557 load block: Type = %d, commands = %d\n",
1288                 pBlock->mnType, pBlock->mnCommands);
1289 start:
1290         if (pBlock->mbPChkSumPresent) {
1291                 nResult = pTAS2557->write(pTAS2557, TAS2557_CRC_RESET_REG, 1);
1292                 if (nResult < 0)
1293                         goto end;
1294         }
1296         if (pBlock->mbYChkSumPresent)
1297                 nCRCChkSum = 0;
1299         nCommand = 0;
1301         while (nCommand < pBlock->mnCommands) {
1302                 pData = pBlock->mpData + nCommand * 4;
1304                 nBook = pData[0];
1305                 nPage = pData[1];
1306                 nOffset = pData[2];
1307                 nData = pData[3];
1309                 nCommand++;
1311                 if (nOffset <= 0x7F) {
1312                         nResult = pTAS2557->write(pTAS2557, TAS2557_REG(nBook, nPage, nOffset), nData);
1313                         if (nResult < 0)
1314                                 goto end;
1315                         if (pBlock->mbYChkSumPresent) {
1316                                 nResult = doSingleRegCheckSum(pTAS2557, nBook, nPage, nOffset, nData);
1317                                 if (nResult < 0)
1318                                         goto check;
1319                                 nCRCChkSum += (unsigned char)nResult;
1320                         }
1321                 } else if (nOffset == 0x81) {
1322                         nSleep = (nBook << 8) + nPage;
1323                         msleep(nSleep);
1324                 } else if (nOffset == 0x85) {
1325                         pData += 4;
1326                         nLength = (nBook << 8) + nPage;
1327                         nBook = pData[0];
1328                         nPage = pData[1];
1329                         nOffset = pData[2];
1330                         if (nLength > 1) {
1331                                 nResult = pTAS2557->bulk_write(pTAS2557, TAS2557_REG(nBook, nPage, nOffset), pData + 3, nLength);
1332                                 if (nResult < 0)
1333                                         goto end;
1334                                 if (pBlock->mbYChkSumPresent) {
1335                                         nResult = doMultiRegCheckSum(pTAS2557, nBook, nPage, nOffset, nLength);
1336                                         if (nResult < 0)
1337                                                 goto check;
1338                                         nCRCChkSum += (unsigned char)nResult;
1339                                 }
1340                         } else {
1341                                 nResult = pTAS2557->write(pTAS2557, TAS2557_REG(nBook, nPage, nOffset), pData[3]);
1342                                 if (nResult < 0)
1343                                         goto end;
1344                                 if (pBlock->mbYChkSumPresent) {
1345                                         nResult = doSingleRegCheckSum(pTAS2557, nBook, nPage, nOffset, pData[3]);
1346                                         if (nResult < 0)
1347                                                 goto check;
1348                                         nCRCChkSum += (unsigned char)nResult;
1349                                 }
1350                         }
1352                         nCommand++;
1354                         if (nLength >= 2)
1355                                 nCommand += ((nLength - 2) / 4) + 1;
1356                 }
1357         }
1358         if (pBlock->mbPChkSumPresent) {
1359                 nResult = pTAS2557->read(pTAS2557, TAS2557_CRC_CHECKSUM_REG, &nValue1);
1360                 if (nResult < 0)
1361                         goto end;
1362                 if ((nValue1&0xff) != pBlock->mnPChkSum) {
1363                         dev_err(pTAS2557->dev, "Block PChkSum Error: FW = 0x%x, Reg = 0x%x\n",
1364                                 pBlock->mnPChkSum, (nValue1&0xff));
1365                         nResult = -EAGAIN;
1366                                 pTAS2557->mnErrCode |= ERROR_PRAM_CRCCHK;
1367                         goto check;
1368                 }
1370                 nResult = 0;
1371                 pTAS2557->mnErrCode &= ~ERROR_PRAM_CRCCHK;
1372                 dev_dbg(pTAS2557->dev, "Block[0x%x] PChkSum match\n", pBlock->mnType);
1373         }
1375         if (pBlock->mbYChkSumPresent) {
1376                 if (nCRCChkSum != pBlock->mnYChkSum) {
1377                         dev_err(pTAS2557->dev, "Block YChkSum Error: FW = 0x%x, YCRC = 0x%x\n",
1378                                 pBlock->mnYChkSum, nCRCChkSum);
1379                         nResult = -EAGAIN;
1380                         pTAS2557->mnErrCode |= ERROR_YRAM_CRCCHK;
1381                         goto check;
1382                 }
1383                 pTAS2557->mnErrCode &= ~ERROR_YRAM_CRCCHK;
1384                 nResult = 0;
1385                 dev_dbg(pTAS2557->dev, "Block[0x%x] YChkSum match\n", pBlock->mnType);
1386         }
1388 check:
1389         if (nResult == -EAGAIN) {
1390                 nRetry--;
1391                 if (nRetry > 0)
1392                         goto start;
1393         }
1395 end:
1396         if (nResult < 0) {
1397                 dev_err(pTAS2557->dev, "Block (%d) load error\n",
1398                                 pBlock->mnType);
1399         }
1400         return nResult;
1403 static int tas2557_load_data(struct tas2557_priv *pTAS2557, struct TData *pData, unsigned int nType)
1405         int nResult = 0;
1406         unsigned int nBlock;
1407         struct TBlock *pBlock;
1409         dev_dbg(pTAS2557->dev,
1410                 "TAS2557 load data: %s, Blocks = %d, Block Type = %d\n", pData->mpName, pData->mnBlocks, nType);
1412         for (nBlock = 0; nBlock < pData->mnBlocks; nBlock++) {
1413                 pBlock = &(pData->mpBlocks[nBlock]);
1414                 if (pBlock->mnType == nType) {
1415                         nResult = tas2557_load_block(pTAS2557, pBlock);
1416                         if (nResult < 0)
1417                                 break;
1418                 }
1419         }
1421         return nResult;
1424 static int tas2557_load_configuration(struct tas2557_priv *pTAS2557,
1425         unsigned int nConfiguration, bool bLoadSame)
1427         int nResult = 0;
1428         struct TConfiguration *pCurrentConfiguration = NULL;
1429         struct TConfiguration *pNewConfiguration = NULL;
1431         dev_dbg(pTAS2557->dev, "%s: %d\n", __func__, nConfiguration);
1433         if ((!pTAS2557->mpFirmware->mpPrograms) ||
1434                 (!pTAS2557->mpFirmware->mpConfigurations)) {
1435                 dev_err(pTAS2557->dev, "Firmware not loaded\n");
1436                 nResult = 0;
1437                 goto end;
1438         }
1440         if (nConfiguration >= pTAS2557->mpFirmware->mnConfigurations) {
1441                 dev_err(pTAS2557->dev, "Configuration %d doesn't exist\n",
1442                         nConfiguration);
1443                 nResult = 0;
1444                 goto end;
1445         }
1447         if ((nConfiguration == pTAS2557->mnCurrentConfiguration) && (!bLoadSame)) {
1448                 dev_info(pTAS2557->dev, "Configuration %d is already loaded\n",
1449                         nConfiguration);
1450                 nResult = 0;
1451                 goto end;
1452         }
1454         pCurrentConfiguration =
1455                 &(pTAS2557->mpFirmware->mpConfigurations[pTAS2557->mnCurrentConfiguration]);
1456         pNewConfiguration =
1457                 &(pTAS2557->mpFirmware->mpConfigurations[nConfiguration]);
1458         if (pNewConfiguration->mnProgram != pCurrentConfiguration->mnProgram) {
1459                 dev_err(pTAS2557->dev, "Configuration %d, %s doesn't share the same program as current %d\n",
1460                         nConfiguration, pNewConfiguration->mpName, pCurrentConfiguration->mnProgram);
1461                 nResult = 0;
1462                 goto end;
1463         }
1465         if (pNewConfiguration->mnPLL >= pTAS2557->mpFirmware->mnPLLs) {
1466                 dev_err(pTAS2557->dev, "Configuration %d, %s doesn't have a valid PLL index %d\n",
1467                         nConfiguration, pNewConfiguration->mpName, pNewConfiguration->mnPLL);
1468                 nResult = 0;
1469                 goto end;
1470         }
1472         if (pTAS2557->mbPowerUp) {
1473                 nResult = tas2557_load_coefficient(pTAS2557, pTAS2557->mnCurrentConfiguration, nConfiguration, true);
1474                 pTAS2557->mbLoadConfigurationPrePowerUp = false;
1475         } else {
1476                 dev_dbg(pTAS2557->dev,
1477                         "TAS2557 was powered down, will load coefficient when power up\n");
1478                 pTAS2557->mbLoadConfigurationPrePowerUp = true;
1479                 pTAS2557->mnNewConfiguration = nConfiguration;
1480         }
1482 end:
1484         if (nResult < 0) {
1485                 if (pTAS2557->mnErrCode & (ERROR_DEVA_I2C_COMM | ERROR_PRAM_CRCCHK | ERROR_YRAM_CRCCHK))
1486                         failsafe(pTAS2557);
1487         }
1489         return nResult;
1492 int tas2557_set_config(struct tas2557_priv *pTAS2557, int config)
1494         struct TConfiguration *pConfiguration;
1495         struct TProgram *pProgram;
1496         unsigned int nProgram = pTAS2557->mnCurrentProgram;
1497         unsigned int nConfiguration = config;
1498         int nResult = 0;
1500         if ((!pTAS2557->mpFirmware->mpPrograms) ||
1501                 (!pTAS2557->mpFirmware->mpConfigurations)) {
1502                 dev_err(pTAS2557->dev, "Firmware not loaded\n");
1503                 nResult = -EINVAL;
1504                 goto end;
1505         }
1507         if (nConfiguration >= pTAS2557->mpFirmware->mnConfigurations) {
1508                 dev_err(pTAS2557->dev, "Configuration %d doesn't exist\n",
1509                         nConfiguration);
1510                 nResult = -EINVAL;
1511                 goto end;
1512         }
1514         pConfiguration = &(pTAS2557->mpFirmware->mpConfigurations[nConfiguration]);
1515         pProgram = &(pTAS2557->mpFirmware->mpPrograms[nProgram]);
1517         if (nProgram != pConfiguration->mnProgram) {
1518                 dev_err(pTAS2557->dev,
1519                         "Configuration %d, %s with Program %d isn't compatible with existing Program %d, %s\n",
1520                         nConfiguration, pConfiguration->mpName, pConfiguration->mnProgram,
1521                         nProgram, pProgram->mpName);
1522                 nResult = -EINVAL;
1523                 goto end;
1524         }
1526         nResult = tas2557_load_configuration(pTAS2557, nConfiguration, false);
1528 end:
1530         return nResult;
1533 void tas2557_clear_firmware(struct TFirmware *pFirmware)
1535         unsigned int n, nn;
1537         if (!pFirmware)
1538                 return;
1540         kfree(pFirmware->mpDescription);
1542         if (pFirmware->mpPLLs != NULL) {
1543                 for (n = 0; n < pFirmware->mnPLLs; n++) {
1544                         kfree(pFirmware->mpPLLs[n].mpDescription);
1545                         kfree(pFirmware->mpPLLs[n].mBlock.mpData);
1546                 }
1547                 kfree(pFirmware->mpPLLs);
1548         }
1550         if (pFirmware->mpPrograms != NULL) {
1551                 for (n = 0; n < pFirmware->mnPrograms; n++) {
1552                         kfree(pFirmware->mpPrograms[n].mpDescription);
1553                         kfree(pFirmware->mpPrograms[n].mData.mpDescription);
1554                         for (nn = 0; nn < pFirmware->mpPrograms[n].mData.mnBlocks; nn++)
1555                                 kfree(pFirmware->mpPrograms[n].mData.mpBlocks[nn].mpData);
1556                         kfree(pFirmware->mpPrograms[n].mData.mpBlocks);
1557                 }
1558                 kfree(pFirmware->mpPrograms);
1559         }
1561         if (pFirmware->mpConfigurations != NULL) {
1562                 for (n = 0; n < pFirmware->mnConfigurations; n++) {
1563                         kfree(pFirmware->mpConfigurations[n].mpDescription);
1564                         kfree(pFirmware->mpConfigurations[n].mData.mpDescription);
1565                         for (nn = 0; nn < pFirmware->mpConfigurations[n].mData.mnBlocks; nn++)
1566                                 kfree(pFirmware->mpConfigurations[n].mData.mpBlocks[nn].mpData);
1567                         kfree(pFirmware->mpConfigurations[n].mData.mpBlocks);
1568                 }
1569                 kfree(pFirmware->mpConfigurations);
1570         }
1572         if (pFirmware->mpCalibrations != NULL) {
1573                 for (n = 0; n < pFirmware->mnCalibrations; n++) {
1574                         kfree(pFirmware->mpCalibrations[n].mpDescription);
1575                         kfree(pFirmware->mpCalibrations[n].mData.mpDescription);
1576                         for (nn = 0; nn < pFirmware->mpCalibrations[n].mData.mnBlocks; nn++)
1577                                 kfree(pFirmware->mpCalibrations[n].mData.mpBlocks[nn].mpData);
1578                         kfree(pFirmware->mpCalibrations[n].mData.mpBlocks);
1579                 }
1580                 kfree(pFirmware->mpCalibrations);
1581         }
1583         memset(pFirmware, 0x00, sizeof(struct TFirmware));
1586 static int tas2557_load_calibration(struct tas2557_priv *pTAS2557,      char *pFileName)
1588         int nResult = 0;
1589 /*
1590 *       int nFile;
1591 *       mm_segment_t fs;
1592 *       unsigned char pBuffer[1000];
1593 *       int nSize = 0;
1595 *       dev_dbg(pTAS2557->dev, "%s:\n", __func__);
1597 *       fs = get_fs();
1598 *       set_fs(KERNEL_DS);
1599 *       nFile = sys_open(pFileName, O_RDONLY, 0);
1601 *       dev_info(pTAS2557->dev, "TAS2557 calibration file = %s, handle = %d\n",
1602 *               pFileName, nFile);
1604 *       if (nFile >= 0) {
1605 *               nSize = sys_read(nFile, pBuffer, 1000);
1606 *               sys_close(nFile);
1607 *       } else {
1608 *               dev_err(pTAS2557->dev, "TAS2557 cannot open calibration file: %s\n",
1609 *                       pFileName);
1610 *       }
1612 *       set_fs(fs);
1614 *       if (!nSize)
1615 *               goto end;
1617 *       tas2557_clear_firmware(pTAS2557->mpCalFirmware);
1618 *       dev_info(pTAS2557->dev, "TAS2557 calibration file size = %d\n", nSize);
1619 *       nResult = fw_parse(pTAS2557, pTAS2557->mpCalFirmware, pBuffer, nSize);
1621 *       if (nResult)
1622 *               dev_err(pTAS2557->dev, "TAS2557 calibration file is corrupt\n");
1623 *       else
1624 *               dev_info(pTAS2557->dev, "TAS2557 calibration: %d calibrations\n",
1625 *                       pTAS2557->mpCalFirmware->mnCalibrations);
1627 *end:
1628 **/
1629         return nResult;
1632 void tas2557_fw_ready(const struct firmware *pFW, void *pContext)
1634         struct tas2557_priv *pTAS2557 = (struct tas2557_priv *) pContext;
1635         int nResult;
1636         unsigned int nProgram = 0;
1637         unsigned int nSampleRate = 0;
1639 #ifdef CONFIG_TAS2557_CODEC
1640         mutex_lock(&pTAS2557->codec_lock);
1641 #endif
1643 #ifdef CONFIG_TAS2557_MISC
1644         mutex_lock(&pTAS2557->file_lock);
1645 #endif
1647         dev_info(pTAS2557->dev, "%s:\n", __func__);
1649         if (unlikely(!pFW) || unlikely(!pFW->data)) {
1650                 dev_err(pTAS2557->dev, "%s firmware is not loaded.\n",
1651                         TAS2557_FW_NAME);
1652                 goto end;
1653         }
1655         if (pTAS2557->mpFirmware->mpConfigurations) {
1656                 nProgram = pTAS2557->mnCurrentProgram;
1657                 nSampleRate = pTAS2557->mnCurrentSampleRate;
1658                 dev_dbg(pTAS2557->dev, "clear current firmware\n");
1659                 tas2557_clear_firmware(pTAS2557->mpFirmware);
1660         }
1662         nResult = fw_parse(pTAS2557, pTAS2557->mpFirmware, (unsigned char *)(pFW->data), pFW->size);
1663         release_firmware(pFW);
1664         if (nResult < 0) {
1665                 dev_err(pTAS2557->dev, "firmware is corrupt\n");
1666                 goto end;
1667         }
1669         if (!pTAS2557->mpFirmware->mnPrograms) {
1670                 dev_err(pTAS2557->dev, "firmware contains no programs\n");
1671                 nResult = -EINVAL;
1672                 goto end;
1673         }
1675         if (!pTAS2557->mpFirmware->mnConfigurations) {
1676                 dev_err(pTAS2557->dev, "firmware contains no configurations\n");
1677                 nResult = -EINVAL;
1678                 goto end;
1679         }
1681         if (nProgram >= pTAS2557->mpFirmware->mnPrograms) {
1682                 dev_info(pTAS2557->dev,
1683                         "no previous program, set to default\n");
1684                 nProgram = 0;
1685         }
1687         pTAS2557->mnCurrentSampleRate = nSampleRate;
1688         nResult = tas2557_set_program(pTAS2557, nProgram, -1);
1690 end:
1692 #ifdef CONFIG_TAS2557_CODEC
1693         mutex_unlock(&pTAS2557->codec_lock);
1694 #endif
1696 #ifdef CONFIG_TAS2557_MISC
1697         mutex_unlock(&pTAS2557->file_lock);
1698 #endif
1701 int tas2557_set_program(struct tas2557_priv *pTAS2557,
1702         unsigned int nProgram, int nConfig)
1704         struct TProgram *pProgram;
1705         unsigned int nConfiguration = 0;
1706         unsigned int nSampleRate = 0;
1707         unsigned char nGain;
1708         bool bFound = false;
1709         int nResult = 0;
1711         if ((!pTAS2557->mpFirmware->mpPrograms) ||
1712                 (!pTAS2557->mpFirmware->mpConfigurations)) {
1713                 dev_err(pTAS2557->dev, "Firmware not loaded\n");
1714                 nResult = 0;
1715                 goto end;
1716         }
1718         if (nProgram >= pTAS2557->mpFirmware->mnPrograms) {
1719                 dev_err(pTAS2557->dev, "TAS2557: Program %d doesn't exist\n",
1720                         nProgram);
1721                 nResult = 0;
1722                 goto end;
1723         }
1725         if (nConfig < 0) {
1726                 nConfiguration = 0;
1727                 nSampleRate = pTAS2557->mnCurrentSampleRate;
1728                 while (!bFound && (nConfiguration < pTAS2557->mpFirmware->mnConfigurations)) {
1729                         if (pTAS2557->mpFirmware->mpConfigurations[nConfiguration].mnProgram == nProgram) {
1730                                 if (nSampleRate == 0) {
1731                                         bFound = true;
1732                                         dev_info(pTAS2557->dev, "find default configuration %d\n", nConfiguration);
1733                                 } else if (nSampleRate == pTAS2557->mpFirmware->mpConfigurations[nConfiguration].mnSamplingRate) {
1734                                         bFound = true;
1735                                         dev_info(pTAS2557->dev, "find matching configuration %d\n", nConfiguration);
1736                                 } else {
1737                                         nConfiguration++;
1738                                 }
1739                         } else {
1740                                 nConfiguration++;
1741                         }
1742                 }
1743                 if (!bFound) {
1744                         dev_err(pTAS2557->dev,
1745                                 "Program %d, no valid configuration found for sample rate %d, ignore\n",
1746                                 nProgram, nSampleRate);
1747                         nResult = 0;
1748                         goto end;
1749                 }
1750         } else {
1751                 if (pTAS2557->mpFirmware->mpConfigurations[nConfig].mnProgram != nProgram) {
1752                         dev_err(pTAS2557->dev, "%s, configuration program doesn't match\n", __func__);
1753                         nResult = 0;
1754                         goto end;
1755                 }
1756                 nConfiguration = nConfig;
1757         }
1759         pProgram = &(pTAS2557->mpFirmware->mpPrograms[nProgram]);
1760         if (pTAS2557->mbPowerUp) {
1761                 dev_info(pTAS2557->dev,
1762                         "device powered up, power down to load program %d (%s)\n",
1763                         nProgram, pProgram->mpName);
1764                 if (hrtimer_active(&pTAS2557->mtimer))
1765                         hrtimer_cancel(&pTAS2557->mtimer);
1767                 if (pProgram->mnAppMode == TAS2557_APP_TUNINGMODE)
1768                         pTAS2557->enableIRQ(pTAS2557, false);
1770                 nResult = tas2557_dev_load_data(pTAS2557, p_tas2557_shutdown_data);
1771                 if (nResult < 0)
1772                         goto end;
1773         }
1775         pTAS2557->hw_reset(pTAS2557);
1776         nResult = pTAS2557->write(pTAS2557, TAS2557_SW_RESET_REG, 0x01);
1777         if (nResult < 0)
1778                 goto end;
1779         msleep(1);
1780         nResult = tas2557_load_default(pTAS2557);
1781         if (nResult < 0)
1782                 goto end;
1784         dev_info(pTAS2557->dev, "load program %d (%s)\n", nProgram, pProgram->mpName);
1785         nResult = tas2557_load_data(pTAS2557, &(pProgram->mData), TAS2557_BLOCK_PGM_DEV_A);
1786         if (nResult < 0)
1787                 goto end;
1788         pTAS2557->mnCurrentProgram = nProgram;
1790         nResult = tas2557_get_DAC_gain(pTAS2557, &nGain);
1791         if (nResult < 0)
1792                 goto end;
1793         pTAS2557->mnDevGain = nGain;
1794         pTAS2557->mnDevCurrentGain = nGain;
1796         nResult = tas2557_load_coefficient(pTAS2557, -1, nConfiguration, false);
1797         if (nResult < 0)
1798                 goto end;
1800         if (pTAS2557->mbPowerUp) {
1801                 pTAS2557->clearIRQ(pTAS2557);
1802                 dev_dbg(pTAS2557->dev, "device powered up, load startup\n");
1803                 nResult = tas2557_dev_load_data(pTAS2557, p_tas2557_startup_data);
1804                 if (nResult < 0)
1805                         goto end;
1806                 if (pProgram->mnAppMode == TAS2557_APP_TUNINGMODE) {
1807                         nResult = tas2557_checkPLL(pTAS2557);
1808                         if (nResult < 0) {
1809                                 nResult = tas2557_dev_load_data(pTAS2557, p_tas2557_shutdown_data);
1810                                 pTAS2557->mbPowerUp = false;
1811                                 goto end;
1812                         }
1813                 }
1814                 dev_dbg(pTAS2557->dev, "device powered up, load unmute\n");
1815                 nResult = tas2557_dev_load_data(pTAS2557, p_tas2557_unmute_data);
1816                 if (nResult < 0)
1817                         goto end;
1819                 if (pProgram->mnAppMode == TAS2557_APP_TUNINGMODE) {
1820                         pTAS2557->enableIRQ(pTAS2557, true);
1821                         if (!hrtimer_active(&pTAS2557->mtimer)) {
1822                                 pTAS2557->mnDieTvReadCounter = 0;
1823                                 hrtimer_start(&pTAS2557->mtimer,
1824                                         ns_to_ktime((u64)LOW_TEMPERATURE_CHECK_PERIOD * NSEC_PER_MSEC), HRTIMER_MODE_REL);
1825                         }
1826                 }
1827         }
1829 end:
1831         if (nResult < 0) {
1832                 if (pTAS2557->mnErrCode & (ERROR_DEVA_I2C_COMM | ERROR_PRAM_CRCCHK | ERROR_YRAM_CRCCHK))
1833                         failsafe(pTAS2557);
1834         }
1835         return nResult;
1838 int tas2557_set_calibration(struct tas2557_priv *pTAS2557, int nCalibration)
1840         struct TCalibration *pCalibration = NULL;
1841         struct TProgram *pProgram;
1842         int nResult = 0;
1844         if ((!pTAS2557->mpFirmware->mpPrograms)
1845                 || (!pTAS2557->mpFirmware->mpConfigurations)) {
1846                 dev_err(pTAS2557->dev, "Firmware not loaded\n\r");
1847                 nResult = 0;
1848                 goto end;
1849         }
1851         if (nCalibration == 0x00FF) {
1852                 nResult = tas2557_load_calibration(pTAS2557, TAS2557_CAL_NAME);
1853                 if (nResult < 0) {
1854                         dev_info(pTAS2557->dev, "load new calibration file %s fail %d\n",
1855                                 TAS2557_CAL_NAME, nResult);
1856                         goto end;
1857                 }
1858                 nCalibration = 0;
1859         }
1861         if (nCalibration >= pTAS2557->mpCalFirmware->mnCalibrations) {
1862                 dev_err(pTAS2557->dev,
1863                         "Calibration %d doesn't exist\n", nCalibration);
1864                 nResult = 0;
1865                 goto end;
1866         }
1868         pTAS2557->mnCurrentCalibration = nCalibration;
1869         pCalibration = &(pTAS2557->mpCalFirmware->mpCalibrations[nCalibration]);
1870         pProgram = &(pTAS2557->mpFirmware->mpPrograms[pTAS2557->mnCurrentProgram]);
1872         if (pProgram->mnAppMode == TAS2557_APP_TUNINGMODE) {
1873                 dev_dbg(pTAS2557->dev, "%s, load calibration\n", __func__);
1874                 nResult = tas2557_load_data(pTAS2557, &(pCalibration->mData), TAS2557_BLOCK_CFG_COEFF_DEV_A);
1875                 if (nResult < 0)
1876                         goto end;
1877         }
1879 end:
1880         if (nResult < 0) {
1881                 tas2557_clear_firmware(pTAS2557->mpCalFirmware);
1882                 nResult = tas2557_set_program(pTAS2557, pTAS2557->mnCurrentProgram, pTAS2557->mnCurrentConfiguration);
1883         }
1885         return nResult;
1888 int tas2557_parse_dt(struct device *dev, struct tas2557_priv *pTAS2557)
1890         struct device_node *np = dev->of_node;
1891         int rc = 0, ret = 0;
1892         unsigned int value;
1894         pTAS2557->mnResetGPIO = of_get_named_gpio(np, "ti,cdc-reset-gpio", 0);
1895         if (pTAS2557->mnResetGPIO < 0) {
1896                 dev_err(pTAS2557->dev, "Looking up %s property in node %s failed %d\n",
1897                         "ti,cdc-reset-gpio", np->full_name,
1898                         pTAS2557->mnResetGPIO);
1899                 ret = -EINVAL;
1900         } else
1901                         dev_dbg(pTAS2557->dev, "ti,cdc-reset-gpio=%d\n", pTAS2557->mnResetGPIO);
1903         if (ret >= 0) {
1904                 pTAS2557->mnGpioINT = of_get_named_gpio(np, "ti,irq-gpio", 0);
1905                 if (pTAS2557->mnGpioINT < 0) {
1906                         dev_err(pTAS2557->dev, "Looking up %s property in node %s failed %d\n",
1907                                 "ti,irq-gpio", np->full_name,
1908                                 pTAS2557->mnGpioINT);
1909                         ret = -EINVAL;
1910                 } else
1911                         dev_dbg(pTAS2557->dev, "ti,irq-gpio=%d\n", pTAS2557->mnGpioINT);
1912         }
1914         if (ret >= 0) {
1915                 rc = of_property_read_u32(np, "ti,i2s-bits", &value);
1916                 if (rc) {
1917                         dev_err(pTAS2557->dev, "Looking up %s property in node %s failed %d\n",
1918                                 "ti,i2s-bits", np->full_name, rc);
1919                         ret = -EINVAL;
1920                 } else {
1921                         pTAS2557->mnI2SBits = value;
1922                         dev_dbg(pTAS2557->dev, "ti,i2s-bits=%d\n", pTAS2557->mnI2SBits);
1923                 }
1924         }
1926         return ret;
1929 MODULE_AUTHOR("Texas Instruments Inc.");
1930 MODULE_DESCRIPTION("TAS2557 common functions for Android Linux");
1931 MODULE_LICENSE("GPL v2");