]> Gitweb @ Texas Instruments - Open Source Git Repositories - git.TI.com/gitweb - tas2557sw-android/tas2557-android-driver.git/blob - tas2557-core.c
If thermal sensor wrong, mute output. Correct the previous patch.
[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_MTPLLSRC                     0x00000400
47 #define PPC_DRIVER_CFGDEV_NONCRC        0x00000101
49 #define TAS2557_CAL_NAME    "/data/tas2557_cal.bin"
50 #define RESTART_MAX 3
52 static int tas2557_load_calibration(struct tas2557_priv *pTAS2557,
53         char *pFileName);
54 static int tas2557_load_data(struct tas2557_priv *pTAS2557, struct TData *pData,
55         unsigned int nType);
56 static void tas2557_clear_firmware(struct TFirmware *pFirmware);
57 static int tas2557_load_block(struct tas2557_priv *pTAS2557, struct TBlock *pBlock);
58 static int tas2557_load_configuration(struct tas2557_priv *pTAS2557,
59         unsigned int nConfiguration, bool bLoadSame);
61 #define TAS2557_UDELAY 0xFFFFFFFE
62 #define TAS2557_MDELAY 0xFFFFFFFD
64 #define TAS2557_BLOCK_PLL                               0x00
65 #define TAS2557_BLOCK_PGM_ALL                   0x0d
66 #define TAS2557_BLOCK_PGM_DEV_A                 0x01
67 #define TAS2557_BLOCK_PGM_DEV_B                 0x08
68 #define TAS2557_BLOCK_CFG_COEFF_DEV_A   0x03
69 #define TAS2557_BLOCK_CFG_COEFF_DEV_B   0x0a
70 #define TAS2557_BLOCK_CFG_PRE_DEV_A             0x04
71 #define TAS2557_BLOCK_CFG_PRE_DEV_B             0x0b
72 #define TAS2557_BLOCK_CFG_POST                  0x05
73 #define TAS2557_BLOCK_CFG_POST_POWER    0x06
75 static unsigned int p_tas2557_default_data[] = {
76         TAS2557_SAR_ADC2_REG, 0x05,     /* enable SAR ADC */
77         TAS2557_CLK_ERR_CTRL2, 0x21,    /*clk1:clock hysteresis, 0.34ms; clock halt, 22ms*/
78         TAS2557_CLK_ERR_CTRL3, 0x21,    /*clk2: rampDown 15dB/us, clock hysteresis, 10.66us; clock halt, 22ms */
79         TAS2557_SAFE_GUARD_REG, TAS2557_SAFE_GUARD_PATTERN,     /* safe guard */
80         0xFFFFFFFF, 0xFFFFFFFF
81 };
83 static unsigned int p_tas2557_irq_config[] = {
84         TAS2557_CLK_HALT_REG, 0x71,     /* enable clk halt detect2 interrupt */
85         TAS2557_INT_GEN1_REG, 0x11,     /* enable spk OC and OV */
86         TAS2557_INT_GEN2_REG, 0x11,     /* enable clk err1 and die OT */
87         TAS2557_INT_GEN3_REG, 0x11,     /* enable clk err2 and brownout */
88         TAS2557_INT_GEN4_REG, 0x01,     /* disable SAR, enable clk halt */
89         TAS2557_GPIO4_PIN_REG, 0x07,    /* set GPIO4 as int1, default */
90         TAS2557_INT_MODE_REG, 0x80,     /* active high until INT_STICKY_1 and INT_STICKY_2 are read to be cleared. */
91         0xFFFFFFFF, 0xFFFFFFFF
92 };
94 static unsigned int p_tas2557_startup_data[] = {
95         TAS2557_GPI_PIN_REG, 0x15,      /* enable DIN, MCLK, CCI */
96         TAS2557_GPIO1_PIN_REG, 0x01,    /* enable BCLK */
97         TAS2557_GPIO2_PIN_REG, 0x01,    /* enable WCLK */
98         TAS2557_POWER_CTRL2_REG, 0xA0,   /* Class-D, Boost power up */
99         TAS2557_POWER_CTRL2_REG, 0xA3,   /* Class-D, Boost, IV sense power up */
100         TAS2557_POWER_CTRL1_REG, 0xF8,   /* PLL, DSP, clock dividers power up */
101         TAS2557_UDELAY, 2000,           /* delay */
102         TAS2557_CLK_ERR_CTRL, 0x2b,     /* enable clock error detection */
103         0xFFFFFFFF, 0xFFFFFFFF
104 };
106 static unsigned int p_tas2557_unmute_data[] = {
107         TAS2557_MUTE_REG, 0x00,          /* unmute */
108         TAS2557_SOFT_MUTE_REG, 0x00,     /* soft unmute */
109         0xFFFFFFFF, 0xFFFFFFFF
110 };
112 static unsigned int p_tas2557_shutdown_data[] = {
113         TAS2557_CLK_ERR_CTRL, 0x00,      /* disable clock error detection */
114         TAS2557_SOFT_MUTE_REG, 0x01,     /* soft mute */
115         TAS2557_UDELAY, 10000,           /* delay 10ms */
116         TAS2557_MUTE_REG, 0x03,          /* mute */
117         TAS2557_POWER_CTRL1_REG, 0x60,   /* DSP power down */
118         TAS2557_UDELAY, 2000,            /* delay 2ms */
119         TAS2557_POWER_CTRL2_REG, 0x00,   /* Class-D, Boost power down */
120         TAS2557_POWER_CTRL1_REG, 0x00,   /* all power down */
121         TAS2557_GPIO1_PIN_REG, 0x00,    /* disable BCLK */
122         TAS2557_GPIO2_PIN_REG, 0x00,    /* disable WCLK */
123         TAS2557_GPI_PIN_REG, 0x00,      /* disable DIN, MCLK, CCI */
124         0xFFFFFFFF, 0xFFFFFFFF
125 };
127 static int tas2557_dev_load_data(struct tas2557_priv *pTAS2557,
128         unsigned int *pData)
130         int ret = 0;
131         unsigned int n = 0;
132         unsigned int nRegister;
133         unsigned int nData;
135         do {
136                 nRegister = pData[n * 2];
137                 nData = pData[n * 2 + 1];
138                 if (nRegister == TAS2557_UDELAY)
139                         udelay(nData);
140                 else if (nRegister != 0xFFFFFFFF) {
141                         ret = pTAS2557->write(pTAS2557, nRegister, nData);
142                         if (ret < 0)
143                                 break;
144                 }
145                 n++;
146         } while (nRegister != 0xFFFFFFFF);
147         return ret;
150 int tas2557_configIRQ(struct tas2557_priv *pTAS2557)
152         return tas2557_dev_load_data(pTAS2557, p_tas2557_irq_config);
155 int tas2557_set_bit_rate(struct tas2557_priv *pTAS2557, unsigned int nBitRate)
157         int ret = 0, n = -1;
159         dev_dbg(pTAS2557->dev, "tas2557_set_bit_rate: nBitRate = %d\n", nBitRate);
161         switch (nBitRate) {
162         case 16:
163                 n = 0;
164                 break;
165         case 20:
166                 n = 1;
167                 break;
168         case 24:
169                 n = 2;
170                 break;
171         case 32:
172                 n = 3;
173                 break;
174         }
176         if (n >= 0)
177                 ret = pTAS2557->update_bits(pTAS2557, TAS2557_ASI1_DAC_FORMAT_REG, 0x18, n<<3);
178         return ret;
181 int tas2557_get_bit_rate(struct tas2557_priv *pTAS2557, unsigned char *pBitRate)
183         int ret = 0;
184         unsigned int nValue = 0;
185         unsigned char bitRate;
187         ret = pTAS2557->read(pTAS2557, TAS2557_ASI1_DAC_FORMAT_REG, &nValue);
188         if (ret >= 0) {
189                 bitRate = (nValue&0x18)>>3;
190                 if (bitRate == 0)
191                         bitRate = 16;
192                 else if (bitRate == 1)
193                         bitRate = 20;
194                 else if (bitRate == 2)
195                         bitRate = 24;
196                 else if (bitRate == 3)
197                         bitRate = 32;
198                 *pBitRate = bitRate;
199         }
201         return ret;
204 int tas2557_get_DAC_gain(struct tas2557_priv *pTAS2557, unsigned char *pnGain)
206         int ret = 0;
207         unsigned int nValue = 0;
209         ret = pTAS2557->read(pTAS2557, TAS2557_SPK_CTRL_REG, &nValue);
210         if (ret >= 0)
211                 *pnGain = ((nValue&TAS2557_DAC_GAIN_MASK)>>TAS2557_DAC_GAIN_SHIFT);
213         return ret;
216 int tas2557_set_DAC_gain(struct tas2557_priv *pTAS2557, unsigned int nGain)
218         int ret = 0;
220         ret = pTAS2557->update_bits(pTAS2557, TAS2557_SPK_CTRL_REG, TAS2557_DAC_GAIN_MASK,
221                 (nGain<<TAS2557_DAC_GAIN_SHIFT));
222         return ret;
225 /*
226 * die temperature calculation:
227 * DieTemp = readout / 2^23
228 */
229 int tas2557_get_die_temperature(struct tas2557_priv *pTAS2557, int *pTemperature)
231         int nResult = 0;
232         unsigned char nBuf[4];
233         int temp;
235         if (!pTAS2557->mpFirmware->mnConfigurations) {
236                 dev_err(pTAS2557->dev, "%s, firmware not loaded\n", __func__);
237                 goto end;
238         }
240         if (!pTAS2557->mbPowerUp) {
241                 dev_err(pTAS2557->dev, "%s, device not powered on\n", __func__);
242                 goto end;
243         }
245         nResult = pTAS2557->bulk_read(pTAS2557, TAS2557_DIE_TEMP_REG, nBuf, 4);
246         if (nResult >= 0) {
247                 temp = ((int)nBuf[0] << 24) | ((int)nBuf[1] << 16) | ((int)nBuf[2] << 8) | nBuf[3];
248                 *pTemperature = temp;
249         }
251 end:
253         return nResult;
256 int tas2557_load_platdata(struct tas2557_priv *pTAS2557)
258         int nResult = 0;
260         if (gpio_is_valid(pTAS2557->mnGpioINT)) {
261                 nResult = tas2557_configIRQ(pTAS2557);
262                 if (nResult < 0)
263                         goto end;
264         }
266         nResult = tas2557_set_bit_rate(pTAS2557, pTAS2557->mnI2SBits);
268 end:
270         return nResult;
273 int tas2557_load_default(struct tas2557_priv *pTAS2557)
275         int nResult = 0;
277         nResult = tas2557_dev_load_data(pTAS2557, p_tas2557_default_data);
278         if (nResult < 0)
279                 goto end;
281         nResult = tas2557_load_platdata(pTAS2557);
282         if (nResult < 0)
283                 goto end;
285         /* enable DOUT tri-state for extra BCLKs */
286         nResult = pTAS2557->update_bits(pTAS2557, TAS2557_ASI1_DAC_FORMAT_REG, 0x01, 0x01);
287 end:
289         return nResult;
292 static void failsafe(struct tas2557_priv *pTAS2557)
294         dev_err(pTAS2557->dev, "%s\n", __func__);
295         pTAS2557->mnErrCode |= ERROR_FAILSAFE;
296         if (hrtimer_active(&pTAS2557->mtimer))
297                 hrtimer_cancel(&pTAS2557->mtimer);
299         if(pTAS2557->mnRestart < RESTART_MAX)
300         {
301                 pTAS2557->mnRestart ++;
302                 msleep(100);
303                 dev_err(pTAS2557->dev, "I2C COMM error, restart SmartAmp.\n");
304                 schedule_delayed_work(&pTAS2557->irq_work, msecs_to_jiffies(100));
305                 return;
306         }
307         pTAS2557->enableIRQ(pTAS2557, false, false);
308         tas2557_dev_load_data(pTAS2557, p_tas2557_shutdown_data);
309         pTAS2557->mbPowerUp = false;
310         pTAS2557->hw_reset(pTAS2557);
311         pTAS2557->write(pTAS2557, TAS2557_SW_RESET_REG, 0x01);
312         udelay(1000);
313         pTAS2557->write(pTAS2557, TAS2557_SPK_CTRL_REG, 0x04);
314         if (pTAS2557->mpFirmware != NULL)
315                 tas2557_clear_firmware(pTAS2557->mpFirmware);
318 int tas2557_checkPLL(struct tas2557_priv *pTAS2557)
320         int nResult = 0;
321 /*
322 * TO DO
323 */
325         return nResult;
328 /*
329 * tas2557_load_coefficient
330 */
331 static int tas2557_load_coefficient(struct tas2557_priv *pTAS2557,
332         int nPrevConfig, int nNewConfig, bool bPowerOn)
334         int nResult = 0;
335         struct TPLL *pPLL;
336         struct TProgram *pProgram;
337         struct TConfiguration *pPrevConfiguration;
338         struct TConfiguration *pNewConfiguration;
339         bool bRestorePower = false;
341         if (!pTAS2557->mpFirmware->mnConfigurations) {
342                 dev_err(pTAS2557->dev, "%s, firmware not loaded\n", __func__);
343                 goto end;
344         }
346         if (nNewConfig >= pTAS2557->mpFirmware->mnConfigurations) {
347                 dev_err(pTAS2557->dev, "%s, invalid configuration New=%d, total=%d\n",
348                         __func__, nNewConfig, pTAS2557->mpFirmware->mnConfigurations);
349                 goto end;
350         }
352         if (nPrevConfig < 0)
353                 pPrevConfiguration = NULL;
354         else if (nPrevConfig == nNewConfig) {
355                 dev_dbg(pTAS2557->dev, "%s, config [%d] already loaded\n",
356                         __func__, nNewConfig);
357                 goto end;
358         } else
359                 pPrevConfiguration = &(pTAS2557->mpFirmware->mpConfigurations[nPrevConfig]);
361         pNewConfiguration = &(pTAS2557->mpFirmware->mpConfigurations[nNewConfig]);
362         pTAS2557->mnCurrentConfiguration = nNewConfig;
363         if (pPrevConfiguration) {
364                 if (pPrevConfiguration->mnPLL == pNewConfiguration->mnPLL) {
365                         dev_dbg(pTAS2557->dev, "%s, PLL same\n", __func__);
366                         goto prog_coefficient;
367                 }
368         }
370         pProgram = &(pTAS2557->mpFirmware->mpPrograms[pTAS2557->mnCurrentProgram]);
371         if (bPowerOn) {
372                 dev_dbg(pTAS2557->dev, "%s, power down to load new PLL\n", __func__);
373                 if (hrtimer_active(&pTAS2557->mtimer))
374                         hrtimer_cancel(&pTAS2557->mtimer);
376                 if (pProgram->mnAppMode == TAS2557_APP_TUNINGMODE)
377                         pTAS2557->enableIRQ(pTAS2557, false, false);
379                 nResult = tas2557_dev_load_data(pTAS2557, p_tas2557_shutdown_data);
380                 if (nResult < 0)
381                         goto end;
382                 bRestorePower = true;
383         }
385         /* load PLL */
386         pPLL = &(pTAS2557->mpFirmware->mpPLLs[pNewConfiguration->mnPLL]);
387         dev_dbg(pTAS2557->dev, "load PLL: %s block for Configuration %s\n",
388                 pPLL->mpName, pNewConfiguration->mpName);
389         nResult = tas2557_load_block(pTAS2557, &(pPLL->mBlock));
390         if (nResult < 0)
391                 goto end;
392         pTAS2557->mnCurrentSampleRate = pNewConfiguration->mnSamplingRate;
394         dev_dbg(pTAS2557->dev, "load configuration %s conefficient pre block\n",
395                 pNewConfiguration->mpName);
396         nResult = tas2557_load_data(pTAS2557, &(pNewConfiguration->mData), TAS2557_BLOCK_CFG_PRE_DEV_A);
397         if (nResult < 0)
398                 goto end;
400 prog_coefficient:
401         dev_dbg(pTAS2557->dev, "load new configuration: %s, coeff block data\n",
402                 pNewConfiguration->mpName);
403         nResult = tas2557_load_data(pTAS2557, &(pNewConfiguration->mData),
404                 TAS2557_BLOCK_CFG_COEFF_DEV_A);
405         if (nResult < 0)
406                 goto end;
408         if (pTAS2557->mpCalFirmware->mnCalibrations) {
409                 nResult = tas2557_set_calibration(pTAS2557, pTAS2557->mnCurrentCalibration);
410                 if (nResult < 0)
411                         goto end;
412         }
414         if (bRestorePower) {
415                 pTAS2557->clearIRQ(pTAS2557);
416                 dev_dbg(pTAS2557->dev, "device powered up, load startup\n");
417                 nResult = tas2557_dev_load_data(pTAS2557, p_tas2557_startup_data);
418                 if (nResult < 0)
419                         goto end;
420                 if (pProgram->mnAppMode == TAS2557_APP_TUNINGMODE) {
421                         nResult = tas2557_checkPLL(pTAS2557);
422                         if (nResult < 0) {
423                                 nResult = tas2557_dev_load_data(pTAS2557, p_tas2557_shutdown_data);
424                                 pTAS2557->mbPowerUp = false;
425                                 goto end;
426                         }
427                 }
428                 dev_dbg(pTAS2557->dev,
429                         "device powered up, load unmute\n");
430                 nResult = tas2557_dev_load_data(pTAS2557, p_tas2557_unmute_data);
431                 if (nResult < 0)
432                         goto end;
433                 if (pProgram->mnAppMode == TAS2557_APP_TUNINGMODE) {
434                         pTAS2557->enableIRQ(pTAS2557, true, true);
435                         if (!hrtimer_active(&pTAS2557->mtimer)) {
436                                 pTAS2557->mnDieTvReadCounter = 0;
437                                 hrtimer_start(&pTAS2557->mtimer,
438                                         ns_to_ktime((u64)LOW_TEMPERATURE_CHECK_PERIOD * NSEC_PER_MSEC), HRTIMER_MODE_REL);
439                         }
440                 }
441         }
442 end:
444         pTAS2557->mnNewConfiguration = pTAS2557->mnCurrentConfiguration;
445         return nResult;
448 int tas2557_update_edge(struct tas2557_priv *pTAS2557)
450         int nResult = 0;
451         dev_dbg(pTAS2557->dev,
452                 "%s, edge: %d\n",
453                 __func__, pTAS2557->mnEdge);
455         nResult = pTAS2557->update_bits(pTAS2557, TAS2557_SPK_CTRL_REG, 0x7, pTAS2557->mnEdge);
457         return nResult;
460 int tas2557_enable(struct tas2557_priv *pTAS2557, bool bEnable)
462         int nResult = 0;
463         unsigned int nValue;
464         struct TProgram *pProgram;
466         dev_dbg(pTAS2557->dev, "Enable: %d\n", bEnable);
468         if ((pTAS2557->mpFirmware->mnPrograms == 0)
469                 || (pTAS2557->mpFirmware->mnConfigurations == 0)) {
470                 dev_err(pTAS2557->dev, "%s, firmware not loaded\n", __func__);
471                 goto end;
472         }
473         /* check safe guard*/
474         nResult = pTAS2557->read(pTAS2557, TAS2557_SAFE_GUARD_REG, &nValue);
475         if (nResult < 0)
476                 goto end;
477         if ((nValue&0xff) != TAS2557_SAFE_GUARD_PATTERN) {
478                 dev_err(pTAS2557->dev, "ERROR safe guard failure!\n");
479                 nResult = -EPIPE;
480                 pTAS2557->mnErrCode = ERROR_SAFE_GUARD;
481                 pTAS2557->mbPowerUp = true;
482                 goto end;
483         }
485         pProgram = &(pTAS2557->mpFirmware->mpPrograms[pTAS2557->mnCurrentProgram]);
486         if (bEnable) {
487                 if (!pTAS2557->mbPowerUp) {
488                         if (!pTAS2557->mbCalibrationLoaded) {
489                                 tas2557_set_calibration(pTAS2559, 0xFF);
490                                 pTAS2557->mbCalibrationLoaded = true;
491                         }
493                         if (pTAS2557->mbLoadConfigurationPrePowerUp) {
494                                 dev_dbg(pTAS2557->dev, "load coefficient before power\n");
495                                 pTAS2557->mbLoadConfigurationPrePowerUp = false;
496                                 nResult = tas2557_load_coefficient(pTAS2557,
497                                         pTAS2557->mnCurrentConfiguration, pTAS2557->mnNewConfiguration, false);
498                                 if (nResult < 0)
499                                         goto end;
500                         }
502                         pTAS2557->clearIRQ(pTAS2557);
503                         /* power on device */
504                         dev_dbg(pTAS2557->dev, "Enable: load startup sequence\n");
505                         nResult = tas2557_dev_load_data(pTAS2557, p_tas2557_startup_data);
506                         if (nResult < 0)
507                                 goto end;
508                         if (pProgram->mnAppMode == TAS2557_APP_TUNINGMODE) {
509                                 nResult = tas2557_checkPLL(pTAS2557);
510                                 if (nResult < 0) {
511                                         nResult = tas2557_dev_load_data(pTAS2557, p_tas2557_shutdown_data);
512                                         goto end;
513                                 }
514                         }
515                         dev_dbg(pTAS2557->dev, "Enable: load unmute sequence\n");
516                         nResult = tas2557_dev_load_data(pTAS2557, p_tas2557_unmute_data);
517                         if (nResult < 0)
518                                 goto end;
520                         pTAS2557->mbPowerUp = true;
522                         tas2557_get_die_temperature(pTAS2770, &nValue);
523                         if(nValue == 0x80000000)
524                         {
525                                 dev_err(pTAS2557->dev, "%s, thermal sensor is wrong, mute output\n", __func__);
526                                 nResult = tas2557_dev_load_data(pTAS2557, p_tas2557_shutdown_data);
527                                 pTAS2557->mbPowerUp = false;
528                                 goto end;
529                         }
531                         if (pProgram->mnAppMode == TAS2557_APP_TUNINGMODE) {
532                                 /* turn on IRQ */
533                                 pTAS2557->enableIRQ(pTAS2557, true, true);
534                                 if (!hrtimer_active(&pTAS2557->mtimer)) {
535                                         pTAS2557->mnDieTvReadCounter = 0;
536                                         hrtimer_start(&pTAS2557->mtimer,
537                                                 ns_to_ktime((u64)LOW_TEMPERATURE_CHECK_PERIOD * NSEC_PER_MSEC), HRTIMER_MODE_REL);
538                                 }
539                         }
540                         pTAS2557->mnRestart = 0;
541                 }
542         } else {
543                 if (pTAS2557->mbPowerUp) {
544                         if (hrtimer_active(&pTAS2557->mtimer))
545                                 hrtimer_cancel(&pTAS2557->mtimer);
547                         dev_dbg(pTAS2557->dev, "Enable: load shutdown sequence\n");
548                         if (pProgram->mnAppMode == TAS2557_APP_TUNINGMODE) {
549                                 /* turn off IRQ */
550                                 pTAS2557->enableIRQ(pTAS2557, false, false);
551                         }
552                         nResult = tas2557_dev_load_data(pTAS2557, p_tas2557_shutdown_data);
553                         if (nResult < 0)
554                                 goto end;
556                         pTAS2557->mbPowerUp = false;
557                         pTAS2557->mnRestart = 0;
558                 }
559         }
561         nResult = 0;
563 end:
564         if (nResult < 0) {
565                 if (pTAS2557->mnErrCode & (ERROR_DEVA_I2C_COMM | ERROR_PRAM_CRCCHK | ERROR_YRAM_CRCCHK | ERROR_SAFE_GUARD))
566                         failsafe(pTAS2557);
567         }
569         return nResult;
572 int tas2557_set_sampling_rate(struct tas2557_priv *pTAS2557, unsigned int nSamplingRate)
574         int nResult = 0;
575         struct TConfiguration *pConfiguration;
576         unsigned int nConfiguration;
578         dev_dbg(pTAS2557->dev, "tas2557_setup_clocks: nSamplingRate = %d [Hz]\n",
579                 nSamplingRate);
581         if ((!pTAS2557->mpFirmware->mpPrograms) ||
582                 (!pTAS2557->mpFirmware->mpConfigurations)) {
583                 dev_err(pTAS2557->dev, "Firmware not loaded\n");
584                 nResult = -EINVAL;
585                 goto end;
586         }
588         pConfiguration = &(pTAS2557->mpFirmware->mpConfigurations[pTAS2557->mnCurrentConfiguration]);
589         if (pConfiguration->mnSamplingRate == nSamplingRate) {
590                 dev_info(pTAS2557->dev, "Sampling rate for current configuration matches: %d\n",
591                         nSamplingRate);
592                 nResult = 0;
593                 goto end;
594         }
596         for (nConfiguration = 0;
597                 nConfiguration < pTAS2557->mpFirmware->mnConfigurations;
598                 nConfiguration++) {
599                 pConfiguration =
600                         &(pTAS2557->mpFirmware->mpConfigurations[nConfiguration]);
601                 if ((pConfiguration->mnSamplingRate == nSamplingRate)
602                         && (pConfiguration->mnProgram == pTAS2557->mnCurrentProgram)) {
603                         dev_info(pTAS2557->dev,
604                                 "Found configuration: %s, with compatible sampling rate %d\n",
605                                 pConfiguration->mpName, nSamplingRate);
606                         nResult = tas2557_load_configuration(pTAS2557, nConfiguration, false);
607                         goto end;
608                 }
609         }
611         dev_err(pTAS2557->dev, "Cannot find a configuration that supports sampling rate: %d\n",
612                 nSamplingRate);
614 end:
616         return nResult;
619 static void fw_print_header(struct tas2557_priv *pTAS2557, struct TFirmware *pFirmware)
621         dev_info(pTAS2557->dev, "FW Size       = %d", pFirmware->mnFWSize);
622         dev_info(pTAS2557->dev, "Checksum      = 0x%04X", pFirmware->mnChecksum);
623         dev_info(pTAS2557->dev, "PPC Version   = 0x%04X", pFirmware->mnPPCVersion);
624         dev_info(pTAS2557->dev, "FW  Version    = 0x%04X", pFirmware->mnFWVersion);
625         dev_info(pTAS2557->dev, "Driver Version= 0x%04X", pFirmware->mnDriverVersion);
626         dev_info(pTAS2557->dev, "Timestamp     = %d", pFirmware->mnTimeStamp);
627         dev_info(pTAS2557->dev, "DDC Name      = %s", pFirmware->mpDDCName);
628         dev_info(pTAS2557->dev, "Description   = %s", pFirmware->mpDescription);
631 inline unsigned int fw_convert_number(unsigned char *pData)
633         return pData[3] + (pData[2] << 8) + (pData[1] << 16) + (pData[0] << 24);
636 static int fw_parse_header(struct tas2557_priv *pTAS2557,
637         struct TFirmware *pFirmware, unsigned char *pData, unsigned int nSize)
639         unsigned char *pDataStart = pData;
640         unsigned int n;
641         unsigned char pMagicNumber[] = { 0x35, 0x35, 0x35, 0x32 };
643         if (nSize < 104) {
644                 dev_err(pTAS2557->dev, "Firmware: Header too short");
645                 return -EINVAL;
646         }
648         if (memcmp(pData, pMagicNumber, 4)) {
649                 dev_err(pTAS2557->dev, "Firmware: Magic number doesn't match");
650                 return -EINVAL;
651         }
652         pData += 4;
654         pFirmware->mnFWSize = fw_convert_number(pData);
655         pData += 4;
657         pFirmware->mnChecksum = fw_convert_number(pData);
658         pData += 4;
660         pFirmware->mnPPCVersion = fw_convert_number(pData);
661         pData += 4;
663         pFirmware->mnFWVersion = fw_convert_number(pData);
664         pData += 4;
666         pFirmware->mnDriverVersion = fw_convert_number(pData);
667         pData += 4;
669         pFirmware->mnTimeStamp = fw_convert_number(pData);
670         pData += 4;
672         memcpy(pFirmware->mpDDCName, pData, 64);
673         pData += 64;
675         n = strlen(pData);
676         pFirmware->mpDescription = kmemdup(pData, n + 1, GFP_KERNEL);
677         pData += n + 1;
678         if ((pData - pDataStart) >= nSize) {
679                 dev_err(pTAS2557->dev, "Firmware: Header too short after DDC description");
680                 return -EINVAL;
681         }
683         pFirmware->mnDeviceFamily = fw_convert_number(pData);
684         pData += 4;
685         if (pFirmware->mnDeviceFamily != 0) {
686                 dev_err(pTAS2557->dev,
687                         "deviceFamily %d, not TAS device", pFirmware->mnDeviceFamily);
688                 return -EINVAL;
689         }
691         pFirmware->mnDevice = fw_convert_number(pData);
692         pData += 4;
694         if (pFirmware->mnDevice != 2) {
695                 dev_err(pTAS2557->dev,
696                         "device %d, not TAS2557 Dual Mono", pFirmware->mnDevice);
697                 return -EINVAL;
698         }
700         fw_print_header(pTAS2557, pFirmware);
701         return pData - pDataStart;
704 static int fw_parse_block_data(struct tas2557_priv *pTAS2557, struct TFirmware *pFirmware,
705         struct TBlock *pBlock, unsigned char *pData)
707         unsigned char *pDataStart = pData;
708         unsigned int n;
710         pBlock->mnType = fw_convert_number(pData);
711         pData += 4;
713         if (pFirmware->mnDriverVersion >= PPC_DRIVER_CRCCHK) {
714                 pBlock->mbPChkSumPresent = pData[0];
715                 pData++;
717                 pBlock->mnPChkSum = pData[0];
718                 pData++;
720                 pBlock->mbYChkSumPresent = pData[0];
721                 pData++;
723                 pBlock->mnYChkSum = pData[0];
724                 pData++;
725         } else {
726                 pBlock->mbPChkSumPresent = 0;
727                 pBlock->mbYChkSumPresent = 0;
728         }
730         pBlock->mnCommands = fw_convert_number(pData);
731         pData += 4;
733         n = pBlock->mnCommands * 4;
734         pBlock->mpData = kmemdup(pData, n, GFP_KERNEL);
735         pData += n;
736         return pData - pDataStart;
739 static int fw_parse_data(struct tas2557_priv *pTAS2557, struct TFirmware *pFirmware,
740         struct TData *pImageData, unsigned char *pData)
742         unsigned char *pDataStart = pData;
743         unsigned int nBlock;
744         unsigned int n;
746         memcpy(pImageData->mpName, pData, 64);
747         pData += 64;
749         n = strlen(pData);
750         pImageData->mpDescription = kmemdup(pData, n + 1, GFP_KERNEL);
751         pData += n + 1;
753         pImageData->mnBlocks = (pData[0] << 8) + pData[1];
754         pData += 2;
756         pImageData->mpBlocks =
757                 kmalloc(sizeof(struct TBlock) * pImageData->mnBlocks, GFP_KERNEL);
759         for (nBlock = 0; nBlock < pImageData->mnBlocks; nBlock++) {
760                 n = fw_parse_block_data(pTAS2557, pFirmware,
761                         &(pImageData->mpBlocks[nBlock]), pData);
762                 pData += n;
763         }
764         return pData - pDataStart;
767 static int fw_parse_pll_data(struct tas2557_priv *pTAS2557,
768         struct TFirmware *pFirmware, unsigned char *pData)
770         unsigned char *pDataStart = pData;
771         unsigned int n;
772         unsigned int nPLL;
773         struct TPLL *pPLL;
775         pFirmware->mnPLLs = (pData[0] << 8) + pData[1];
776         pData += 2;
778         if (pFirmware->mnPLLs == 0)
779                 goto end;
781         pFirmware->mpPLLs = kmalloc_array(pFirmware->mnPLLs, sizeof(struct TPLL), GFP_KERNEL);
782         for (nPLL = 0; nPLL < pFirmware->mnPLLs; nPLL++) {
783                 pPLL = &(pFirmware->mpPLLs[nPLL]);
785                 memcpy(pPLL->mpName, pData, 64);
786                 pData += 64;
788                 n = strlen(pData);
789                 pPLL->mpDescription = kmemdup(pData, n + 1, GFP_KERNEL);
790                 pData += n + 1;
792                 n = fw_parse_block_data(pTAS2557, pFirmware, &(pPLL->mBlock), pData);
793                 pData += n;
794         }
796 end:
797         return pData - pDataStart;
800 static int fw_parse_program_data(struct tas2557_priv *pTAS2557,
801         struct TFirmware *pFirmware, unsigned char *pData)
803         unsigned char *pDataStart = pData;
804         unsigned int n;
805         unsigned int nProgram;
806         struct TProgram *pProgram;
808         pFirmware->mnPrograms = (pData[0] << 8) + pData[1];
809         pData += 2;
811         if (pFirmware->mnPrograms == 0)
812                 goto end;
814         pFirmware->mpPrograms =
815                 kmalloc(sizeof(struct TProgram) * pFirmware->mnPrograms, GFP_KERNEL);
816         for (nProgram = 0; nProgram < pFirmware->mnPrograms; nProgram++) {
817                 pProgram = &(pFirmware->mpPrograms[nProgram]);
818                 memcpy(pProgram->mpName, pData, 64);
819                 pData += 64;
821                 n = strlen(pData);
822                 pProgram->mpDescription = kmemdup(pData, n + 1, GFP_KERNEL);
823                 pData += n + 1;
825                 pProgram->mnAppMode = pData[0];
826                 pData++;
828                 pProgram->mnBoost = (pData[0] << 8) + pData[1];
829                 pData += 2;
831                 n = fw_parse_data(pTAS2557, pFirmware, &(pProgram->mData), pData);
832                 pData += n;
833         }
835 end:
837         return pData - pDataStart;
840 static int fw_parse_configuration_data(struct tas2557_priv *pTAS2557,
841         struct TFirmware *pFirmware, unsigned char *pData)
843         unsigned char *pDataStart = pData;
844         unsigned int n;
845         unsigned int nConfiguration;
846         struct TConfiguration *pConfiguration;
848         pFirmware->mnConfigurations = (pData[0] << 8) + pData[1];
849         pData += 2;
851         if (pFirmware->mnConfigurations == 0)
852                 goto end;
854         pFirmware->mpConfigurations =
855                 kmalloc(sizeof(struct TConfiguration) * pFirmware->mnConfigurations,
856                 GFP_KERNEL);
857         for (nConfiguration = 0; nConfiguration < pFirmware->mnConfigurations;
858                 nConfiguration++) {
859                 pConfiguration = &(pFirmware->mpConfigurations[nConfiguration]);
860                 memcpy(pConfiguration->mpName, pData, 64);
861                 pData += 64;
863                 n = strlen(pData);
864                 pConfiguration->mpDescription = kmemdup(pData, n + 1, GFP_KERNEL);
865                 pData += n + 1;
867                 if ((pFirmware->mnDriverVersion >= PPC_DRIVER_CONFDEV)
868                         || ((pFirmware->mnDriverVersion >= PPC_DRIVER_CFGDEV_NONCRC)
869                                 && (pFirmware->mnDriverVersion < PPC_DRIVER_CRCCHK))) {
870                         pConfiguration->mnDevices = (pData[0] << 8) + pData[1];
871                         pData += 2;
872                 } else
873                         pConfiguration->mnDevices = 1;
875                 pConfiguration->mnProgram = pData[0];
876                 pData++;
878                 pConfiguration->mnPLL = pData[0];
879                 pData++;
881                 pConfiguration->mnSamplingRate = fw_convert_number(pData);
882                 pData += 4;
884                 if (pFirmware->mnDriverVersion >= PPC_DRIVER_MTPLLSRC) {
885                         pConfiguration->mnPLLSrc = pData[0];
886                         pData++;
888                         pConfiguration->mnPLLSrcRate = fw_convert_number(pData);
889                         pData += 4;
890                 }
892                 n = fw_parse_data(pTAS2557, pFirmware, &(pConfiguration->mData), pData);
893                 pData += n;
894         }
896 end:
898         return pData - pDataStart;
901 int fw_parse_calibration_data(struct tas2557_priv *pTAS2557,
902         struct TFirmware *pFirmware, unsigned char *pData)
904         unsigned char *pDataStart = pData;
905         unsigned int n;
906         unsigned int nCalibration;
907         struct TCalibration *pCalibration;
909         pFirmware->mnCalibrations = (pData[0] << 8) + pData[1];
910         pData += 2;
912         if (pFirmware->mnCalibrations == 0)
913                 goto end;
915         pFirmware->mpCalibrations =
916                 kmalloc(sizeof(struct TCalibration) * pFirmware->mnCalibrations, GFP_KERNEL);
917         for (nCalibration = 0;
918                 nCalibration < pFirmware->mnCalibrations;
919                 nCalibration++) {
920                 pCalibration = &(pFirmware->mpCalibrations[nCalibration]);
921                 memcpy(pCalibration->mpName, pData, 64);
922                 pData += 64;
924                 n = strlen(pData);
925                 pCalibration->mpDescription = kmemdup(pData, n + 1, GFP_KERNEL);
926                 pData += n + 1;
928                 pCalibration->mnProgram = pData[0];
929                 pData++;
931                 pCalibration->mnConfiguration = pData[0];
932                 pData++;
934                 n = fw_parse_data(pTAS2557, pFirmware, &(pCalibration->mData), pData);
935                 pData += n;
936         }
938 end:
940         return pData - pDataStart;
943 static int fw_parse(struct tas2557_priv *pTAS2557,
944         struct TFirmware *pFirmware, unsigned char *pData, unsigned int nSize)
946         int nPosition = 0;
948         nPosition = fw_parse_header(pTAS2557, pFirmware, pData, nSize);
949         if (nPosition < 0) {
950                 dev_err(pTAS2557->dev, "Firmware: Wrong Header");
951                 return -EINVAL;
952         }
954         if (nPosition >= nSize) {
955                 dev_err(pTAS2557->dev, "Firmware: Too short");
956                 return -EINVAL;
957         }
959         pData += nPosition;
960         nSize -= nPosition;
961         nPosition = 0;
963         nPosition = fw_parse_pll_data(pTAS2557, pFirmware, pData);
965         pData += nPosition;
966         nSize -= nPosition;
967         nPosition = 0;
969         nPosition = fw_parse_program_data(pTAS2557, pFirmware, pData);
971         pData += nPosition;
972         nSize -= nPosition;
973         nPosition = 0;
975         nPosition = fw_parse_configuration_data(pTAS2557, pFirmware, pData);
977         pData += nPosition;
978         nSize -= nPosition;
979         nPosition = 0;
981         if (nSize > 64)
982                 nPosition = fw_parse_calibration_data(pTAS2557, pFirmware, pData);
983         return 0;
987 static const unsigned char crc8_lookup_table[CRC8_TABLE_SIZE] = {
988 0x00, 0x4D, 0x9A, 0xD7, 0x79, 0x34, 0xE3, 0xAE, 0xF2, 0xBF, 0x68, 0x25, 0x8B, 0xC6, 0x11, 0x5C,
989 0xA9, 0xE4, 0x33, 0x7E, 0xD0, 0x9D, 0x4A, 0x07, 0x5B, 0x16, 0xC1, 0x8C, 0x22, 0x6F, 0xB8, 0xF5,
990 0x1F, 0x52, 0x85, 0xC8, 0x66, 0x2B, 0xFC, 0xB1, 0xED, 0xA0, 0x77, 0x3A, 0x94, 0xD9, 0x0E, 0x43,
991 0xB6, 0xFB, 0x2C, 0x61, 0xCF, 0x82, 0x55, 0x18, 0x44, 0x09, 0xDE, 0x93, 0x3D, 0x70, 0xA7, 0xEA,
992 0x3E, 0x73, 0xA4, 0xE9, 0x47, 0x0A, 0xDD, 0x90, 0xCC, 0x81, 0x56, 0x1B, 0xB5, 0xF8, 0x2F, 0x62,
993 0x97, 0xDA, 0x0D, 0x40, 0xEE, 0xA3, 0x74, 0x39, 0x65, 0x28, 0xFF, 0xB2, 0x1C, 0x51, 0x86, 0xCB,
994 0x21, 0x6C, 0xBB, 0xF6, 0x58, 0x15, 0xC2, 0x8F, 0xD3, 0x9E, 0x49, 0x04, 0xAA, 0xE7, 0x30, 0x7D,
995 0x88, 0xC5, 0x12, 0x5F, 0xF1, 0xBC, 0x6B, 0x26, 0x7A, 0x37, 0xE0, 0xAD, 0x03, 0x4E, 0x99, 0xD4,
996 0x7C, 0x31, 0xE6, 0xAB, 0x05, 0x48, 0x9F, 0xD2, 0x8E, 0xC3, 0x14, 0x59, 0xF7, 0xBA, 0x6D, 0x20,
997 0xD5, 0x98, 0x4F, 0x02, 0xAC, 0xE1, 0x36, 0x7B, 0x27, 0x6A, 0xBD, 0xF0, 0x5E, 0x13, 0xC4, 0x89,
998 0x63, 0x2E, 0xF9, 0xB4, 0x1A, 0x57, 0x80, 0xCD, 0x91, 0xDC, 0x0B, 0x46, 0xE8, 0xA5, 0x72, 0x3F,
999 0xCA, 0x87, 0x50, 0x1D, 0xB3, 0xFE, 0x29, 0x64, 0x38, 0x75, 0xA2, 0xEF, 0x41, 0x0C, 0xDB, 0x96,
1000 0x42, 0x0F, 0xD8, 0x95, 0x3B, 0x76, 0xA1, 0xEC, 0xB0, 0xFD, 0x2A, 0x67, 0xC9, 0x84, 0x53, 0x1E,
1001 0xEB, 0xA6, 0x71, 0x3C, 0x92, 0xDF, 0x08, 0x45, 0x19, 0x54, 0x83, 0xCE, 0x60, 0x2D, 0xFA, 0xB7,
1002 0x5D, 0x10, 0xC7, 0x8A, 0x24, 0x69, 0xBE, 0xF3, 0xAF, 0xE2, 0x35, 0x78, 0xD6, 0x9B, 0x4C, 0x01,
1003 0xF4, 0xB9, 0x6E, 0x23, 0x8D, 0xC0, 0x17, 0x5A, 0x06, 0x4B, 0x9C, 0xD1, 0x7F, 0x32, 0xE5, 0xA8
1004 };
1006 static int isInPageYRAM(struct tas2557_priv *pTAS2557, struct TYCRC *pCRCData,
1007         unsigned char nBook, unsigned char nPage, unsigned char nReg, unsigned char len)
1009         int nResult = 0;
1011         if (nBook == TAS2557_YRAM_BOOK1) {
1012                 if (nPage == TAS2557_YRAM1_PAGE) {
1013                         if (nReg >= TAS2557_YRAM1_START_REG) {
1014                                 pCRCData->mnOffset = nReg;
1015                                 pCRCData->mnLen = len;
1016                                 nResult = 1;
1017                         } else if ((nReg + len) > TAS2557_YRAM1_START_REG) {
1018                                 pCRCData->mnOffset = TAS2557_YRAM1_START_REG;
1019                                 pCRCData->mnLen = len - (TAS2557_YRAM1_START_REG - nReg);
1020                                 nResult = 1;
1021                         } else
1022                                 nResult = 0;
1023                 } else if (nPage == TAS2557_YRAM3_PAGE) {
1024                         if (nReg > TAS2557_YRAM3_END_REG) {
1025                                 nResult = 0;
1026                         } else if (nReg >= TAS2557_YRAM3_START_REG) {
1027                                 if ((nReg + len) > TAS2557_YRAM3_END_REG) {
1028                                         pCRCData->mnOffset = nReg;
1029                                         pCRCData->mnLen = TAS2557_YRAM3_END_REG - nReg + 1;
1030                                         nResult = 1;
1031                                 } else {
1032                                         pCRCData->mnOffset = nReg;
1033                                         pCRCData->mnLen = len;
1034                                         nResult = 1;
1035                                 }
1036                         } else {
1037                                 if ((nReg + (len - 1)) < TAS2557_YRAM3_START_REG)
1038                                         nResult = 0;
1039                                 else {
1040                                         pCRCData->mnOffset = TAS2557_YRAM3_START_REG;
1041                                         pCRCData->mnLen = len - (TAS2557_YRAM3_START_REG - nReg);
1042                                         nResult = 1;
1043                                 }
1044                         }
1045                 }
1046         } else if (nBook == TAS2557_YRAM_BOOK2) {
1047                 if (nPage == TAS2557_YRAM5_PAGE) {
1048                         if (nReg > TAS2557_YRAM5_END_REG) {
1049                                 nResult = 0;
1050                         } else if (nReg >= TAS2557_YRAM5_START_REG) {
1051                                 if ((nReg + len) > TAS2557_YRAM5_END_REG) {
1052                                         pCRCData->mnOffset = nReg;
1053                                         pCRCData->mnLen = TAS2557_YRAM5_END_REG - nReg + 1;
1054                                         nResult = 1;
1055                                 } else {
1056                                         pCRCData->mnOffset = nReg;
1057                                         pCRCData->mnLen = len;
1058                                         nResult = 1;
1059                                 }
1060                         } else {
1061                                 if ((nReg + (len - 1)) < TAS2557_YRAM5_START_REG)
1062                                         nResult = 0;
1063                                 else {
1064                                         pCRCData->mnOffset = TAS2557_YRAM5_START_REG;
1065                                         pCRCData->mnLen = len - (TAS2557_YRAM5_START_REG - nReg);
1066                                         nResult = 1;
1067                                 }
1068                         }
1069                 }
1070         } else
1071                 nResult = 0;
1073         return nResult;
1076 static int isInBlockYRAM(struct tas2557_priv *pTAS2557, struct TYCRC *pCRCData,
1077         unsigned char nBook, unsigned char nPage, unsigned char nReg, unsigned char len)
1079         int nResult;
1081         if (nBook == TAS2557_YRAM_BOOK1) {
1082                 if (nPage < TAS2557_YRAM2_START_PAGE)
1083                         nResult = 0;
1084                 else if (nPage <= TAS2557_YRAM2_END_PAGE) {
1085                         if (nReg > TAS2557_YRAM2_END_REG)
1086                                 nResult = 0;
1087                         else if (nReg >= TAS2557_YRAM2_START_REG) {
1088                                 pCRCData->mnOffset = nReg;
1089                                 pCRCData->mnLen = len;
1090                                 nResult = 1;
1091                         } else {
1092                                 if ((nReg + (len - 1)) < TAS2557_YRAM2_START_REG)
1093                                         nResult = 0;
1094                                 else {
1095                                         pCRCData->mnOffset = TAS2557_YRAM2_START_REG;
1096                                         pCRCData->mnLen = nReg + len - TAS2557_YRAM2_START_REG;
1097                                         nResult = 1;
1098                                 }
1099                         }
1100                 } else
1101                         nResult = 0;
1102         } else if (nBook == TAS2557_YRAM_BOOK2) {
1103                 if (nPage < TAS2557_YRAM4_START_PAGE)
1104                         nResult = 0;
1105                 else if (nPage <= TAS2557_YRAM4_END_PAGE) {
1106                         if (nReg > TAS2557_YRAM2_END_REG)
1107                                 nResult = 0;
1108                         else if (nReg >= TAS2557_YRAM2_START_REG) {
1109                                 pCRCData->mnOffset = nReg;
1110                                 pCRCData->mnLen = len;
1111                                 nResult = 1;
1112                         } else {
1113                                 if ((nReg + (len - 1)) < TAS2557_YRAM2_START_REG)
1114                                         nResult = 0;
1115                                 else {
1116                                         pCRCData->mnOffset = TAS2557_YRAM2_START_REG;
1117                                         pCRCData->mnLen = nReg + len - TAS2557_YRAM2_START_REG;
1118                                         nResult = 1;
1119                                 }
1120                         }
1121                 } else
1122                         nResult = 0;
1123         } else
1124                 nResult = 0;
1126         return nResult;
1130 static int isYRAM(struct tas2557_priv *pTAS2557, struct TYCRC *pCRCData,
1131         unsigned char nBook, unsigned char nPage, unsigned char nReg, unsigned char len)
1133         int nResult;
1135         nResult = isInPageYRAM(pTAS2557, pCRCData, nBook, nPage, nReg, len);
1137         if (nResult == 0)
1138                 nResult = isInBlockYRAM(pTAS2557, pCRCData, nBook, nPage, nReg, len);
1140         return nResult;
1143 /*
1144  * crc8 - calculate a crc8 over the given input data.
1145  *
1146  * table: crc table used for calculation.
1147  * pdata: pointer to data buffer.
1148  * nbytes: number of bytes in data buffer.
1149  * crc: previous returned crc8 value.
1150  */
1151 static u8 ti_crc8(const u8 table[CRC8_TABLE_SIZE], u8 *pdata, size_t nbytes, u8 crc)
1153         /* loop over the buffer data */
1154         while (nbytes-- > 0)
1155                 crc = table[(crc ^ *pdata++) & 0xff];
1157         return crc;
1160 static int doSingleRegCheckSum(struct tas2557_priv *pTAS2557, 
1161         unsigned char nBook, unsigned char nPage, unsigned char nReg, unsigned char nValue)
1163         int nResult = 0;
1164         struct TYCRC sCRCData;
1165         unsigned int nData1 = 0;
1167         if ((nBook == TAS2557_BOOK_ID(TAS2557_SA_COEFF_SWAP_REG))
1168                 && (nPage == TAS2557_PAGE_ID(TAS2557_SA_COEFF_SWAP_REG))
1169                 && (nReg >= TAS2557_PAGE_REG(TAS2557_SA_COEFF_SWAP_REG))
1170                 && (nReg <= (TAS2557_PAGE_REG(TAS2557_SA_COEFF_SWAP_REG) + 4))) {
1171                 /* DSP swap command, pass */
1172                 nResult = 0;
1173                 goto end;
1174         }
1176         nResult = isYRAM(pTAS2557, &sCRCData, nBook, nPage, nReg, 1);
1177         if (nResult == 1) {
1178                 nResult = pTAS2557->read(pTAS2557, TAS2557_REG(nBook, nPage, nReg), &nData1);
1179                 if (nResult < 0)
1180                         goto end;
1182                 if (nData1 != nValue) {
1183                         dev_err(pTAS2557->dev, "error2 (line %d),B[0x%x]P[0x%x]R[0x%x] W[0x%x], R[0x%x]\n",
1184                                 __LINE__, nBook, nPage, nReg, nValue, nData1);
1185                         nResult = -EAGAIN;
1186                         goto end;
1187                 }
1189                 nResult = ti_crc8(crc8_lookup_table, &nValue, 1, 0);
1190         }
1192 end:
1194         return nResult;
1197 static int doMultiRegCheckSum(struct tas2557_priv *pTAS2557, 
1198         unsigned char nBook, unsigned char nPage, unsigned char nReg, unsigned int len)
1200         int nResult = 0, i;
1201         unsigned char nCRCChkSum = 0;
1202         unsigned char nBuf1[128];
1203         struct TYCRC TCRCData;
1205         if ((nReg + len-1) > 127) {
1206                 nResult = -EINVAL;
1207                 dev_err(pTAS2557->dev, "firmware error\n");
1208                 goto end;
1209         }
1211         if ((nBook == TAS2557_BOOK_ID(TAS2557_SA_COEFF_SWAP_REG))
1212                 && (nPage == TAS2557_PAGE_ID(TAS2557_SA_COEFF_SWAP_REG))
1213                 && (nReg == TAS2557_PAGE_REG(TAS2557_SA_COEFF_SWAP_REG))
1214                 && (len == 4)) {
1215                 /* DSP swap command, pass */
1216                 nResult = 0;
1217                 goto end;
1218         }
1220         nResult = isYRAM(pTAS2557, &TCRCData, nBook, nPage, nReg, len);
1221         if (nResult == 1) {
1222                 if (len == 1) {
1223                         dev_err(pTAS2557->dev, "firmware error\n");
1224                         nResult = -EINVAL;
1225                         goto end;
1226                 } else {
1227                         nResult = pTAS2557->bulk_read(pTAS2557, TAS2557_REG(nBook, nPage, TCRCData.mnOffset), nBuf1, TCRCData.mnLen);
1228                         if (nResult < 0)
1229                                 goto end;
1231                         for (i = 0; i < TCRCData.mnLen; i++) {
1232                                 if ((nBook == TAS2557_BOOK_ID(TAS2557_SA_COEFF_SWAP_REG))
1233                                         && (nPage == TAS2557_PAGE_ID(TAS2557_SA_COEFF_SWAP_REG))
1234                                         && ((i + TCRCData.mnOffset)
1235                                                 >= TAS2557_PAGE_REG(TAS2557_SA_COEFF_SWAP_REG))
1236                                         && ((i + TCRCData.mnOffset)
1237                                                 <= (TAS2557_PAGE_REG(TAS2557_SA_COEFF_SWAP_REG) + 4))) {
1238                                         /* DSP swap command, bypass */
1239                                         continue;
1240                                 } else
1241                                         nCRCChkSum += ti_crc8(crc8_lookup_table, &nBuf1[i], 1, 0);
1242                         }
1244                         nResult = nCRCChkSum;
1245                 }
1246         }
1248 end:
1250         return nResult;
1253 static int tas2557_load_block(struct tas2557_priv *pTAS2557, struct TBlock *pBlock)
1255         int nResult = 0;
1256         unsigned int nCommand = 0;
1257         unsigned char nBook;
1258         unsigned char nPage;
1259         unsigned char nOffset;
1260         unsigned char nData;
1261         unsigned int nLength;
1262         unsigned int nSleep;
1263         unsigned char nCRCChkSum = 0;
1264         unsigned int nValue1;
1265         int nRetry = 6;
1266         unsigned char *pData = pBlock->mpData;
1268         dev_dbg(pTAS2557->dev, "TAS2557 load block: Type = %d, commands = %d\n",
1269                 pBlock->mnType, pBlock->mnCommands);
1270 start:
1271         if (pBlock->mbPChkSumPresent) {
1272                 nResult = pTAS2557->write(pTAS2557, TAS2557_CRC_RESET_REG, 1);
1273                 if (nResult < 0)
1274                         goto end;
1275         }
1277         if (pBlock->mbYChkSumPresent)
1278                 nCRCChkSum = 0;
1280         nCommand = 0;
1282         while (nCommand < pBlock->mnCommands) {
1283                 pData = pBlock->mpData + nCommand * 4;
1285                 nBook = pData[0];
1286                 nPage = pData[1];
1287                 nOffset = pData[2];
1288                 nData = pData[3];
1290                 nCommand++;
1292                 if (nOffset <= 0x7F) {
1293                         nResult = pTAS2557->write(pTAS2557, TAS2557_REG(nBook, nPage, nOffset), nData);
1294                         if (nResult < 0)
1295                                 goto end;
1296                         if (pBlock->mbYChkSumPresent) {
1297                                 nResult = doSingleRegCheckSum(pTAS2557, nBook, nPage, nOffset, nData);
1298                                 if (nResult < 0)
1299                                         goto check;
1300                                 nCRCChkSum += (unsigned char)nResult;
1301                         }
1302                 } else if (nOffset == 0x81) {
1303                         nSleep = (nBook << 8) + nPage;
1304                         msleep(nSleep);
1305                 } else if (nOffset == 0x85) {
1306                         pData += 4;
1307                         nLength = (nBook << 8) + nPage;
1308                         nBook = pData[0];
1309                         nPage = pData[1];
1310                         nOffset = pData[2];
1311                         if (nLength > 1) {
1312                                 nResult = pTAS2557->bulk_write(pTAS2557, TAS2557_REG(nBook, nPage, nOffset), pData + 3, nLength);
1313                                 if (nResult < 0)
1314                                         goto end;
1315                                 if (pBlock->mbYChkSumPresent) {
1316                                         nResult = doMultiRegCheckSum(pTAS2557, nBook, nPage, nOffset, nLength);
1317                                         if (nResult < 0)
1318                                                 goto check;
1319                                         nCRCChkSum += (unsigned char)nResult;
1320                                 }
1321                         } else {
1322                                 nResult = pTAS2557->write(pTAS2557, TAS2557_REG(nBook, nPage, nOffset), pData[3]);
1323                                 if (nResult < 0)
1324                                         goto end;
1325                                 if (pBlock->mbYChkSumPresent) {
1326                                         nResult = doSingleRegCheckSum(pTAS2557, nBook, nPage, nOffset, pData[3]);
1327                                         if (nResult < 0)
1328                                                 goto check;
1329                                         nCRCChkSum += (unsigned char)nResult;
1330                                 }
1331                         }
1333                         nCommand++;
1335                         if (nLength >= 2)
1336                                 nCommand += ((nLength - 2) / 4) + 1;
1337                 }
1338         }
1339         if (pBlock->mbPChkSumPresent) {
1340                 nResult = pTAS2557->read(pTAS2557, TAS2557_CRC_CHECKSUM_REG, &nValue1);
1341                 if (nResult < 0)
1342                         goto end;
1343                 if ((nValue1&0xff) != pBlock->mnPChkSum) {
1344                         dev_err(pTAS2557->dev, "Block PChkSum Error: FW = 0x%x, Reg = 0x%x\n",
1345                                 pBlock->mnPChkSum, (nValue1&0xff));
1346                         nResult = -EAGAIN;
1347                                 pTAS2557->mnErrCode |= ERROR_PRAM_CRCCHK;
1348                         goto check;
1349                 }
1351                 nResult = 0;
1352                 pTAS2557->mnErrCode &= ~ERROR_PRAM_CRCCHK;
1353                 dev_dbg(pTAS2557->dev, "Block[0x%x] PChkSum match\n", pBlock->mnType);
1354         }
1356         if (pBlock->mbYChkSumPresent) {
1357                 if (nCRCChkSum != pBlock->mnYChkSum) {
1358                         dev_err(pTAS2557->dev, "Block YChkSum Error: FW = 0x%x, YCRC = 0x%x\n",
1359                                 pBlock->mnYChkSum, nCRCChkSum);
1360                         nResult = -EAGAIN;
1361                         pTAS2557->mnErrCode |= ERROR_YRAM_CRCCHK;
1362                         goto check;
1363                 }
1364                 pTAS2557->mnErrCode &= ~ERROR_YRAM_CRCCHK;
1365                 nResult = 0;
1366                 dev_dbg(pTAS2557->dev, "Block[0x%x] YChkSum match\n", pBlock->mnType);
1367         }
1369 check:
1370         if (nResult == -EAGAIN) {
1371                 nRetry--;
1372                 if (nRetry > 0)
1373                         goto start;
1374         }
1376 end:
1377         if (nResult < 0) {
1378                 dev_err(pTAS2557->dev, "Block (%d) load error\n",
1379                                 pBlock->mnType);
1380         }
1381         return nResult;
1384 static int tas2557_load_data(struct tas2557_priv *pTAS2557, struct TData *pData, unsigned int nType)
1386         int nResult = 0;
1387         unsigned int nBlock;
1388         struct TBlock *pBlock;
1390         dev_dbg(pTAS2557->dev,
1391                 "TAS2557 load data: %s, Blocks = %d, Block Type = %d\n", pData->mpName, pData->mnBlocks, nType);
1393         for (nBlock = 0; nBlock < pData->mnBlocks; nBlock++) {
1394                 pBlock = &(pData->mpBlocks[nBlock]);
1395                 if (pBlock->mnType == nType) {
1396                         nResult = tas2557_load_block(pTAS2557, pBlock);
1397                         if (nResult < 0)
1398                                 break;
1399                 }
1400         }
1402         return nResult;
1405 static int tas2557_load_configuration(struct tas2557_priv *pTAS2557,
1406         unsigned int nConfiguration, bool bLoadSame)
1408         int nResult = 0;
1409         struct TConfiguration *pCurrentConfiguration = NULL;
1410         struct TConfiguration *pNewConfiguration = NULL;
1412         dev_dbg(pTAS2557->dev, "%s: %d\n", __func__, nConfiguration);
1414         if ((!pTAS2557->mpFirmware->mpPrograms) ||
1415                 (!pTAS2557->mpFirmware->mpConfigurations)) {
1416                 dev_err(pTAS2557->dev, "Firmware not loaded\n");
1417                 nResult = 0;
1418                 goto end;
1419         }
1421         if (nConfiguration >= pTAS2557->mpFirmware->mnConfigurations) {
1422                 dev_err(pTAS2557->dev, "Configuration %d doesn't exist\n",
1423                         nConfiguration);
1424                 nResult = 0;
1425                 goto end;
1426         }
1428         if ((!pTAS2557->mbLoadConfigurationPrePowerUp)
1429                 && (nConfiguration == pTAS2557->mnCurrentConfiguration)
1430                 && (!bLoadSame)) {
1431                 dev_info(pTAS2557->dev, "Configuration %d is already loaded\n",
1432                         nConfiguration);
1433                 nResult = 0;
1434                 goto end;
1435         }
1437         pCurrentConfiguration =
1438                 &(pTAS2557->mpFirmware->mpConfigurations[pTAS2557->mnCurrentConfiguration]);
1439         pNewConfiguration =
1440                 &(pTAS2557->mpFirmware->mpConfigurations[nConfiguration]);
1441         if (pNewConfiguration->mnProgram != pCurrentConfiguration->mnProgram) {
1442                 dev_err(pTAS2557->dev, "Configuration %d, %s doesn't share the same program as current %d\n",
1443                         nConfiguration, pNewConfiguration->mpName, pCurrentConfiguration->mnProgram);
1444                 nResult = 0;
1445                 goto end;
1446         }
1448         if (pNewConfiguration->mnPLL >= pTAS2557->mpFirmware->mnPLLs) {
1449                 dev_err(pTAS2557->dev, "Configuration %d, %s doesn't have a valid PLL index %d\n",
1450                         nConfiguration, pNewConfiguration->mpName, pNewConfiguration->mnPLL);
1451                 nResult = 0;
1452                 goto end;
1453         }
1455         if (pTAS2557->mbPowerUp) {
1456                 pTAS2557->mbLoadConfigurationPrePowerUp = false;
1457                 nResult = tas2557_load_coefficient(pTAS2557, pTAS2557->mnCurrentConfiguration, nConfiguration, true);
1458         } else {
1459                 dev_dbg(pTAS2557->dev,
1460                         "TAS2557 was powered down, will load coefficient when power up\n");
1461                 pTAS2557->mbLoadConfigurationPrePowerUp = true;
1462                 pTAS2557->mnNewConfiguration = nConfiguration;
1463         }
1465 end:
1467         if (nResult < 0) {
1468                 if (pTAS2557->mnErrCode & (ERROR_DEVA_I2C_COMM | ERROR_PRAM_CRCCHK | ERROR_YRAM_CRCCHK))
1469                         failsafe(pTAS2557);
1470         }
1472         return nResult;
1475 int tas2557_set_config(struct tas2557_priv *pTAS2557, int config)
1477         struct TConfiguration *pConfiguration;
1478         struct TProgram *pProgram;
1479         unsigned int nProgram = pTAS2557->mnCurrentProgram;
1480         unsigned int nConfiguration = config;
1481         int nResult = 0;
1483         if ((!pTAS2557->mpFirmware->mpPrograms) ||
1484                 (!pTAS2557->mpFirmware->mpConfigurations)) {
1485                 dev_err(pTAS2557->dev, "Firmware not loaded\n");
1486                 nResult = -EINVAL;
1487                 goto end;
1488         }
1490         if (nConfiguration >= pTAS2557->mpFirmware->mnConfigurations) {
1491                 dev_err(pTAS2557->dev, "Configuration %d doesn't exist\n",
1492                         nConfiguration);
1493                 nResult = -EINVAL;
1494                 goto end;
1495         }
1497         pConfiguration = &(pTAS2557->mpFirmware->mpConfigurations[nConfiguration]);
1498         pProgram = &(pTAS2557->mpFirmware->mpPrograms[nProgram]);
1500         if (nProgram != pConfiguration->mnProgram) {
1501                 dev_err(pTAS2557->dev,
1502                         "Configuration %d, %s with Program %d isn't compatible with existing Program %d, %s\n",
1503                         nConfiguration, pConfiguration->mpName, pConfiguration->mnProgram,
1504                         nProgram, pProgram->mpName);
1505                 nResult = -EINVAL;
1506                 goto end;
1507         }
1509         nResult = tas2557_load_configuration(pTAS2557, nConfiguration, false);
1511 end:
1513         return nResult;
1516 void tas2557_clear_firmware(struct TFirmware *pFirmware)
1518         unsigned int n, nn;
1520         if (!pFirmware)
1521                 return;
1523         kfree(pFirmware->mpDescription);
1525         if (pFirmware->mpPLLs != NULL) {
1526                 for (n = 0; n < pFirmware->mnPLLs; n++) {
1527                         kfree(pFirmware->mpPLLs[n].mpDescription);
1528                         kfree(pFirmware->mpPLLs[n].mBlock.mpData);
1529                 }
1530                 kfree(pFirmware->mpPLLs);
1531         }
1533         if (pFirmware->mpPrograms != NULL) {
1534                 for (n = 0; n < pFirmware->mnPrograms; n++) {
1535                         kfree(pFirmware->mpPrograms[n].mpDescription);
1536                         kfree(pFirmware->mpPrograms[n].mData.mpDescription);
1537                         for (nn = 0; nn < pFirmware->mpPrograms[n].mData.mnBlocks; nn++)
1538                                 kfree(pFirmware->mpPrograms[n].mData.mpBlocks[nn].mpData);
1539                         kfree(pFirmware->mpPrograms[n].mData.mpBlocks);
1540                 }
1541                 kfree(pFirmware->mpPrograms);
1542         }
1544         if (pFirmware->mpConfigurations != NULL) {
1545                 for (n = 0; n < pFirmware->mnConfigurations; n++) {
1546                         kfree(pFirmware->mpConfigurations[n].mpDescription);
1547                         kfree(pFirmware->mpConfigurations[n].mData.mpDescription);
1548                         for (nn = 0; nn < pFirmware->mpConfigurations[n].mData.mnBlocks; nn++)
1549                                 kfree(pFirmware->mpConfigurations[n].mData.mpBlocks[nn].mpData);
1550                         kfree(pFirmware->mpConfigurations[n].mData.mpBlocks);
1551                 }
1552                 kfree(pFirmware->mpConfigurations);
1553         }
1555         if (pFirmware->mpCalibrations != NULL) {
1556                 for (n = 0; n < pFirmware->mnCalibrations; n++) {
1557                         kfree(pFirmware->mpCalibrations[n].mpDescription);
1558                         kfree(pFirmware->mpCalibrations[n].mData.mpDescription);
1559                         for (nn = 0; nn < pFirmware->mpCalibrations[n].mData.mnBlocks; nn++)
1560                                 kfree(pFirmware->mpCalibrations[n].mData.mpBlocks[nn].mpData);
1561                         kfree(pFirmware->mpCalibrations[n].mData.mpBlocks);
1562                 }
1563                 kfree(pFirmware->mpCalibrations);
1564         }
1566         memset(pFirmware, 0x00, sizeof(struct TFirmware));
1569 static int tas2557_load_calibration(struct tas2557_priv *pTAS2557,      char *pFileName)
1571         int nResult = 0;
1573         int nFile;
1574         mm_segment_t fs;
1575         unsigned char pBuffer[1000];
1576         int nSize = 0;
1578         dev_dbg(pTAS2557->dev, "%s:\n", __func__);
1580         fs = get_fs();
1581         set_fs(KERNEL_DS);
1582         nFile = sys_open(pFileName, O_RDONLY, 0);
1584         dev_info(pTAS2557->dev, "TAS2557 calibration file = %s, handle = %d\n",
1585                 pFileName, nFile);
1587         if (nFile >= 0) {
1588                 nSize = sys_read(nFile, pBuffer, 1000);
1589                 sys_close(nFile);
1590         } else {
1591                 dev_err(pTAS2557->dev, "TAS2557 cannot open calibration file: %s\n",
1592                         pFileName);
1593         }
1595         set_fs(fs);
1597         if (!nSize)
1598                 goto end;
1600         tas2557_clear_firmware(pTAS2557->mpCalFirmware);
1601         dev_info(pTAS2557->dev, "TAS2557 calibration file size = %d\n", nSize);
1602         nResult = fw_parse(pTAS2557, pTAS2557->mpCalFirmware, pBuffer, nSize);
1604         if (nResult)
1605                 dev_err(pTAS2557->dev, "TAS2557 calibration file is corrupt\n");
1606         else
1607                 dev_info(pTAS2557->dev, "TAS2557 calibration: %d calibrations\n",
1608                         pTAS2557->mpCalFirmware->mnCalibrations);
1609 end:
1611         return nResult;
1614 static bool tas2557_get_coefficient_in_block(struct tas2557_priv *pTAS2557,
1615         struct TBlock *pBlock, int nReg, int *pnValue)
1617         int nCoefficient = 0;
1618         bool bFound = false;
1619         unsigned char *pCommands;
1620         int nBook, nPage, nOffset, len;
1621         int i, n;
1623         pCommands = pBlock->mpData;
1624         for (i = 0 ; i < pBlock->mnCommands;) {
1625                 nBook = pCommands[4 * i + 0];
1626                 nPage = pCommands[4 * i + 1];
1627                 nOffset = pCommands[4 * i + 2];
1628                 if ((nOffset < 0x7f) || (nOffset == 0x81))
1629                         i++;
1630                 else if (nOffset == 0x85) {
1631                         len = ((int)nBook << 8) | nPage;
1632                         nBook = pCommands[4 * i + 4];
1633                         nPage = pCommands[4 * i + 5];
1634                         nOffset = pCommands[4 * i + 6];
1635                         n = 4 * i + 7;
1636                         i += 2;
1637                         i += ((len - 1) / 4);
1638                         if ((len - 1) % 4)
1639                                 i++;
1640                         if ((nBook != TAS2557_BOOK_ID(nReg))
1641                                 || (nPage != TAS2557_PAGE_ID(nReg)))
1642                                 continue;
1643                         if (nOffset > TAS2557_PAGE_REG(nReg))
1644                                 continue;
1645                         if ((len + nOffset) >= (TAS2557_PAGE_REG(nReg) + 4)) {
1646                                 n += (TAS2557_PAGE_REG(nReg) - nOffset);
1647                                 nCoefficient = ((int)pCommands[n] << 24)
1648                                                 | ((int)pCommands[n + 1] << 16)
1649                                                 | ((int)pCommands[n + 2] << 8)
1650                                                 | (int)pCommands[n + 3];
1651                                 bFound = true;
1652                                 break;
1653                         }
1654                 } else {
1655                         dev_err(pTAS2557->dev, "%s, format error %d\n", __func__, nOffset);
1656                         break;
1657                 }
1658         }
1660         if (bFound) {
1661                 *pnValue = nCoefficient;
1662                 dev_dbg(pTAS2557->dev, "%s, B[0x%x]P[0x%x]R[0x%x]=0x%x\n", __func__,
1663                         TAS2557_BOOK_ID(nReg), TAS2557_PAGE_ID(nReg), TAS2557_PAGE_REG(nReg),
1664                         nCoefficient);
1665         }
1667         return bFound;
1670 static bool tas2557_get_coefficient_in_data(struct tas2557_priv *pTAS2557,
1671         struct TData *pData, int blockType, int nReg, int *pnValue)
1673         bool bFound = false;
1674         struct TBlock *pBlock;
1675         int i;
1677         for (i = 0; i < pData->mnBlocks; i++) {
1678                 pBlock = &(pData->mpBlocks[i]);
1679                 if (pBlock->mnType == blockType) {
1680                         bFound = tas2557_get_coefficient_in_block(pTAS2557,
1681                                                 pBlock, nReg, pnValue);
1682                         if (bFound)
1683                                 break;
1684                 }
1685         }
1687         return bFound;
1690 static bool tas2557_find_Tmax_in_configuration(struct tas2557_priv *pTAS2557,
1691         struct TConfiguration *pConfiguration, int *pnTMax)
1693         struct TData *pData;
1694         bool bFound = false;
1695         int nBlockType, nReg, nCoefficient;
1697         if (pTAS2557->mnPGID == TAS2557_PG_VERSION_2P1)
1698                 nReg = TAS2557_PG2P1_CALI_T_REG;
1699         else
1700                 nReg = TAS2557_PG1P0_CALI_T_REG;
1702         nBlockType = TAS2557_BLOCK_CFG_COEFF_DEV_A;
1704         pData = &(pConfiguration->mData);
1705         bFound = tas2557_get_coefficient_in_data(pTAS2557, pData, nBlockType, nReg, &nCoefficient);
1706         if (bFound)
1707                 *pnTMax = nCoefficient;
1709         return bFound;
1712 void tas2557_fw_ready(const struct firmware *pFW, void *pContext)
1714         struct tas2557_priv *pTAS2557 = (struct tas2557_priv *) pContext;
1715         int nResult;
1716         unsigned int nProgram = 0;
1717         unsigned int nSampleRate = 0;
1719 #ifdef CONFIG_TAS2557_CODEC
1720         mutex_lock(&pTAS2557->codec_lock);
1721 #endif
1723 #ifdef CONFIG_TAS2557_MISC
1724         mutex_lock(&pTAS2557->file_lock);
1725 #endif
1727         dev_info(pTAS2557->dev, "%s:\n", __func__);
1729         if (unlikely(!pFW) || unlikely(!pFW->data)) {
1730                 dev_err(pTAS2557->dev, "%s firmware is not loaded.\n",
1731                         TAS2557_FW_NAME);
1732                 goto end;
1733         }
1735         if (pTAS2557->mpFirmware->mpConfigurations) {
1736                 nProgram = pTAS2557->mnCurrentProgram;
1737                 nSampleRate = pTAS2557->mnCurrentSampleRate;
1738                 dev_dbg(pTAS2557->dev, "clear current firmware\n");
1739                 tas2557_clear_firmware(pTAS2557->mpFirmware);
1740         }
1742         nResult = fw_parse(pTAS2557, pTAS2557->mpFirmware, (unsigned char *)(pFW->data), pFW->size);
1743         release_firmware(pFW);
1744         if (nResult < 0) {
1745                 dev_err(pTAS2557->dev, "firmware is corrupt\n");
1746                 goto end;
1747         }
1749         if (!pTAS2557->mpFirmware->mnPrograms) {
1750                 dev_err(pTAS2557->dev, "firmware contains no programs\n");
1751                 nResult = -EINVAL;
1752                 goto end;
1753         }
1755         if (!pTAS2557->mpFirmware->mnConfigurations) {
1756                 dev_err(pTAS2557->dev, "firmware contains no configurations\n");
1757                 nResult = -EINVAL;
1758                 goto end;
1759         }
1761         if (nProgram >= pTAS2557->mpFirmware->mnPrograms) {
1762                 dev_info(pTAS2557->dev,
1763                         "no previous program, set to default\n");
1764                 nProgram = 0;
1765         }
1767         pTAS2557->mnCurrentSampleRate = nSampleRate;
1768         nResult = tas2557_set_program(pTAS2557, nProgram, -1);
1770 end:
1772 #ifdef CONFIG_TAS2557_CODEC
1773         mutex_unlock(&pTAS2557->codec_lock);
1774 #endif
1776 #ifdef CONFIG_TAS2557_MISC
1777         mutex_unlock(&pTAS2557->file_lock);
1778 #endif
1781 int tas2557_set_program(struct tas2557_priv *pTAS2557,
1782         unsigned int nProgram, int nConfig)
1784         struct TProgram *pProgram;
1785         unsigned int nConfiguration = 0;
1786         unsigned int nSampleRate = 0;
1787         unsigned char nGain;
1788         bool bFound = false;
1789         int nResult = 0;
1791         if ((!pTAS2557->mpFirmware->mpPrograms) ||
1792                 (!pTAS2557->mpFirmware->mpConfigurations)) {
1793                 dev_err(pTAS2557->dev, "Firmware not loaded\n");
1794                 nResult = 0;
1795                 goto end;
1796         }
1798         if (nProgram >= pTAS2557->mpFirmware->mnPrograms) {
1799                 dev_err(pTAS2557->dev, "TAS2557: Program %d doesn't exist\n",
1800                         nProgram);
1801                 nResult = 0;
1802                 goto end;
1803         }
1805         if (nConfig < 0) {
1806                 nConfiguration = 0;
1807                 nSampleRate = pTAS2557->mnCurrentSampleRate;
1808                 while (!bFound && (nConfiguration < pTAS2557->mpFirmware->mnConfigurations)) {
1809                         if (pTAS2557->mpFirmware->mpConfigurations[nConfiguration].mnProgram == nProgram) {
1810                                 if (nSampleRate == 0) {
1811                                         bFound = true;
1812                                         dev_info(pTAS2557->dev, "find default configuration %d\n", nConfiguration);
1813                                 } else if (nSampleRate == pTAS2557->mpFirmware->mpConfigurations[nConfiguration].mnSamplingRate) {
1814                                         bFound = true;
1815                                         dev_info(pTAS2557->dev, "find matching configuration %d\n", nConfiguration);
1816                                 } else {
1817                                         nConfiguration++;
1818                                 }
1819                         } else {
1820                                 nConfiguration++;
1821                         }
1822                 }
1823                 if (!bFound) {
1824                         dev_err(pTAS2557->dev,
1825                                 "Program %d, no valid configuration found for sample rate %d, ignore\n",
1826                                 nProgram, nSampleRate);
1827                         nResult = 0;
1828                         goto end;
1829                 }
1830         } else {
1831                 if (pTAS2557->mpFirmware->mpConfigurations[nConfig].mnProgram != nProgram) {
1832                         dev_err(pTAS2557->dev, "%s, configuration program doesn't match\n", __func__);
1833                         nResult = 0;
1834                         goto end;
1835                 }
1836                 nConfiguration = nConfig;
1837         }
1839         pProgram = &(pTAS2557->mpFirmware->mpPrograms[nProgram]);
1840         if (pTAS2557->mbPowerUp) {
1841                 dev_info(pTAS2557->dev,
1842                         "device powered up, power down to load program %d (%s)\n",
1843                         nProgram, pProgram->mpName);
1844                 if (hrtimer_active(&pTAS2557->mtimer))
1845                         hrtimer_cancel(&pTAS2557->mtimer);
1847                 if (pProgram->mnAppMode == TAS2557_APP_TUNINGMODE)
1848                         pTAS2557->enableIRQ(pTAS2557, false, false);
1850                 nResult = tas2557_dev_load_data(pTAS2557, p_tas2557_shutdown_data);
1851                 if (nResult < 0)
1852                         goto end;
1853         }
1855         pTAS2557->hw_reset(pTAS2557);
1856         nResult = pTAS2557->write(pTAS2557, TAS2557_SW_RESET_REG, 0x01);
1857         if (nResult < 0)
1858                 goto end;
1859         msleep(1);
1860         nResult = tas2557_load_default(pTAS2557);
1861         if (nResult < 0)
1862                 goto end;
1864         dev_info(pTAS2557->dev, "load program %d (%s)\n", nProgram, pProgram->mpName);
1865         nResult = tas2557_load_data(pTAS2557, &(pProgram->mData), TAS2557_BLOCK_PGM_DEV_A);
1866         if (nResult < 0)
1867                 goto end;
1868         pTAS2557->mnCurrentProgram = nProgram;
1870         nResult = tas2557_get_DAC_gain(pTAS2557, &nGain);
1871         if (nResult < 0)
1872                 goto end;
1873         pTAS2557->mnDevGain = nGain;
1874         pTAS2557->mnDevCurrentGain = nGain;
1876         nResult = tas2557_load_coefficient(pTAS2557, -1, nConfiguration, false);
1877         if (nResult < 0)
1878                 goto end;
1880         tas2557_update_edge(pTAS2557);
1882         if (pTAS2557->mbPowerUp) {
1883                 pTAS2557->clearIRQ(pTAS2557);
1884                 dev_dbg(pTAS2557->dev, "device powered up, load startup\n");
1885                 nResult = tas2557_dev_load_data(pTAS2557, p_tas2557_startup_data);
1886                 if (nResult < 0)
1887                         goto end;
1888                 if (pProgram->mnAppMode == TAS2557_APP_TUNINGMODE) {
1889                         nResult = tas2557_checkPLL(pTAS2557);
1890                         if (nResult < 0) {
1891                                 nResult = tas2557_dev_load_data(pTAS2557, p_tas2557_shutdown_data);
1892                                 pTAS2557->mbPowerUp = false;
1893                                 goto end;
1894                         }
1895                 }
1896                 dev_dbg(pTAS2557->dev, "device powered up, load unmute\n");
1897                 nResult = tas2557_dev_load_data(pTAS2557, p_tas2557_unmute_data);
1898                 if (nResult < 0)
1899                         goto end;
1901                 if (pProgram->mnAppMode == TAS2557_APP_TUNINGMODE) {
1902                         pTAS2557->enableIRQ(pTAS2557, true, true);
1903                         if (!hrtimer_active(&pTAS2557->mtimer)) {
1904                                 pTAS2557->mnDieTvReadCounter = 0;
1905                                 hrtimer_start(&pTAS2557->mtimer,
1906                                         ns_to_ktime((u64)LOW_TEMPERATURE_CHECK_PERIOD * NSEC_PER_MSEC), HRTIMER_MODE_REL);
1907                         }
1908                 }
1909         }
1911 end:
1913         if (nResult < 0) {
1914                 if (pTAS2557->mnErrCode & (ERROR_DEVA_I2C_COMM | ERROR_PRAM_CRCCHK | ERROR_YRAM_CRCCHK))
1915                         failsafe(pTAS2557);
1916         }
1917         return nResult;
1920 int tas2557_set_calibration(struct tas2557_priv *pTAS2557, int nCalibration)
1922         struct TCalibration *pCalibration = NULL;
1923         struct TConfiguration *pConfiguration;
1924         struct TProgram *pProgram;
1925         int nTmax = 0;
1926         bool bFound = false;
1927         int nResult = 0;
1929         if ((!pTAS2557->mpFirmware->mpPrograms)
1930                 || (!pTAS2557->mpFirmware->mpConfigurations)) {
1931                 dev_err(pTAS2557->dev, "Firmware not loaded\n\r");
1932                 nResult = 0;
1933                 goto end;
1934         }
1936         if (nCalibration == 0x00FF) {
1937                 nResult = tas2557_load_calibration(pTAS2557, TAS2557_CAL_NAME);
1938                 if (nResult < 0) {
1939                         dev_info(pTAS2557->dev, "load new calibration file %s fail %d\n",
1940                                 TAS2557_CAL_NAME, nResult);
1941                         goto end;
1942                 }
1943                 nCalibration = 0;
1944         }
1946         if (nCalibration >= pTAS2557->mpCalFirmware->mnCalibrations) {
1947                 dev_err(pTAS2557->dev,
1948                         "Calibration %d doesn't exist\n", nCalibration);
1949                 nResult = 0;
1950                 goto end;
1951         }
1953         pTAS2557->mnCurrentCalibration = nCalibration;
1954         if (pTAS2557->mbLoadConfigurationPrePowerUp)
1955                 goto end;
1957         pCalibration = &(pTAS2557->mpCalFirmware->mpCalibrations[nCalibration]);
1958         pProgram = &(pTAS2557->mpFirmware->mpPrograms[pTAS2557->mnCurrentProgram]);
1959         pConfiguration = &(pTAS2557->mpFirmware->mpConfigurations[pTAS2557->mnCurrentConfiguration]);
1960         if (pProgram->mnAppMode == TAS2557_APP_TUNINGMODE) {
1961                 if (pTAS2557->mbBypassTMax) {
1962                         bFound = tas2557_find_Tmax_in_configuration(pTAS2557, pConfiguration, &nTmax);
1963                         if (bFound && (nTmax == TAS2557_COEFFICIENT_TMAX)) {
1964                                 dev_dbg(pTAS2557->dev, "%s, config[%s] bypass load calibration\n",
1965                                         __func__, pConfiguration->mpName);
1966                                 goto end;
1967                         }
1968                 }
1970                 dev_dbg(pTAS2557->dev, "%s, load calibration\n", __func__);
1971                 nResult = tas2557_load_data(pTAS2557, &(pCalibration->mData), TAS2557_BLOCK_CFG_COEFF_DEV_A);
1972                 if (nResult < 0)
1973                         goto end;
1974         }
1976 end:
1977         if (nResult < 0) {
1978                 tas2557_clear_firmware(pTAS2557->mpCalFirmware);
1979                 nResult = tas2557_set_program(pTAS2557, pTAS2557->mnCurrentProgram, pTAS2557->mnCurrentConfiguration);
1980         }
1982         return nResult;
1985 bool tas2557_get_Cali_prm_r0(struct tas2557_priv *pTAS2557, int *prm_r0)
1987         struct TCalibration *pCalibration;
1988         struct TData *pData;
1989         int nReg;
1990         int nCali_Re;
1991         bool bFound = false;
1992         int nBlockType;
1994         if (!pTAS2557->mpCalFirmware->mnCalibrations) {
1995                 dev_err(pTAS2557->dev, "%s, no calibration data\n", __func__);
1996                 goto end;
1997         }
1999         if (pTAS2557->mnPGID == TAS2557_PG_VERSION_2P1)
2000                 nReg = TAS2557_PG2P1_CALI_R0_REG;
2001         else
2002                 nReg = TAS2557_PG1P0_CALI_R0_REG;
2004         nBlockType = TAS2557_BLOCK_CFG_COEFF_DEV_A;
2006         pCalibration = &(pTAS2557->mpCalFirmware->mpCalibrations[pTAS2557->mnCurrentCalibration]);
2007         pData = &(pCalibration->mData);
2009         bFound = tas2557_get_coefficient_in_data(pTAS2557, pData, nBlockType, nReg, &nCali_Re);
2011 end:
2013         if (bFound)
2014                 *prm_r0 = nCali_Re;
2016         return bFound;
2019 int tas2557_parse_dt(struct device *dev, struct tas2557_priv *pTAS2557)
2021         struct device_node *np = dev->of_node;
2022         int rc = 0, ret = 0;
2023         unsigned int value;
2025         pTAS2557->mnResetGPIO = of_get_named_gpio(np, "ti,cdc-reset-gpio", 0);
2026         if (!gpio_is_valid(pTAS2557->mnResetGPIO)) {
2027                 dev_err(pTAS2557->dev, "Looking up %s property in node %s failed %d\n",
2028                         "ti,cdc-reset-gpio", np->full_name,
2029                         pTAS2557->mnResetGPIO);
2030                 ret = -EINVAL;
2031                 goto end;
2032         } else
2033                 dev_dbg(pTAS2557->dev, "ti,cdc-reset-gpio=%d\n", pTAS2557->mnResetGPIO);
2035         pTAS2557->mnGpioINT = of_get_named_gpio(np, "ti,irq-gpio", 0);
2036         if (!gpio_is_valid(pTAS2557->mnGpioINT))
2037                 dev_err(pTAS2557->dev, "Looking up %s property in node %s failed %d\n",
2038                         "ti,irq-gpio", np->full_name,
2039                         pTAS2557->mnGpioINT);
2042         rc = of_property_read_u32(np, "ti,i2s-bits", &value);
2043         if (rc)
2044                 dev_err(pTAS2557->dev, "Looking up %s property in node %s failed %d\n",
2045                         "ti,i2s-bits", np->full_name, rc);
2046         else
2047                 pTAS2557->mnI2SBits = value;
2049         rc = of_property_read_u32(np, "ti,bypass-tmax", &value);
2050         if (rc)
2051                 dev_err(pTAS2557->dev, "Looking up %s property in node %s failed %d\n",
2052                         "ti,bypass-tmax", np->full_name, rc);
2053         else
2054                 pTAS2557->mbBypassTMax = (value > 0);
2056 end:
2058         return ret;
2061 MODULE_AUTHOR("Texas Instruments Inc.");
2062 MODULE_DESCRIPTION("TAS2557 common functions for Android Linux");
2063 MODULE_LICENSE("GPL v2");