]> Gitweb @ Texas Instruments - Open Source Git Repositories - git.TI.com/gitweb - tas2557sw-android/tas2557-android-driver.git/blob - tas2557-core.c
Fix warnings in some code scan
[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         int ret;
296         dev_err(pTAS2557->dev, "%s\n", __func__);
297         pTAS2557->mnErrCode |= ERROR_FAILSAFE;
298         if (hrtimer_active(&pTAS2557->mtimer))
299                 hrtimer_cancel(&pTAS2557->mtimer);
301         if(pTAS2557->mnRestart < RESTART_MAX)
302         {
303                 pTAS2557->mnRestart ++;
304                 msleep(100);
305                 dev_err(pTAS2557->dev, "I2C COMM error, restart SmartAmp.\n");
306                 schedule_delayed_work(&pTAS2557->irq_work, msecs_to_jiffies(100));
307                 return;
308         }
309         pTAS2557->enableIRQ(pTAS2557, false, false);
310         ret = tas2557_dev_load_data(pTAS2557, p_tas2557_shutdown_data);
311         if (ret < 0)
312                 dev_dbg(pTAS2557->dev, "failed load shutdown\n");
314         pTAS2557->mbPowerUp = false;
315         pTAS2557->hw_reset(pTAS2557);
316         ret = pTAS2557->write(pTAS2557, TAS2557_SW_RESET_REG, 0x01);
317         if (ret < 0)
318                 dev_dbg(pTAS2557->dev, "failed sw reset\n");
320         udelay(1000);
321         ret = pTAS2557->write(pTAS2557, TAS2557_SPK_CTRL_REG, 0x04);
322         if (ret < 0)
323                 dev_dbg(pTAS2557->dev, "failed in spk ctrl\n");
324         if (pTAS2557->mpFirmware != NULL)
325                 tas2557_clear_firmware(pTAS2557->mpFirmware);
328 int tas2557_checkPLL(struct tas2557_priv *pTAS2557)
330         int nResult = 0;
331 /*
332 * TO DO
333 */
335         return nResult;
338 /*
339 * tas2557_load_coefficient
340 */
341 static int tas2557_load_coefficient(struct tas2557_priv *pTAS2557,
342         int nPrevConfig, int nNewConfig, bool bPowerOn)
344         int nResult = 0;
345         struct TPLL *pPLL;
346         struct TProgram *pProgram;
347         struct TConfiguration *pPrevConfiguration;
348         struct TConfiguration *pNewConfiguration;
349         bool bRestorePower = false;
351         if (!pTAS2557->mpFirmware->mnConfigurations) {
352                 dev_err(pTAS2557->dev, "%s, firmware not loaded\n", __func__);
353                 goto end;
354         }
356         if (nNewConfig >= pTAS2557->mpFirmware->mnConfigurations) {
357                 dev_err(pTAS2557->dev, "%s, invalid configuration New=%d, total=%d\n",
358                         __func__, nNewConfig, pTAS2557->mpFirmware->mnConfigurations);
359                 goto end;
360         }
362         if (nPrevConfig < 0)
363                 pPrevConfiguration = NULL;
364         else if (nPrevConfig == nNewConfig) {
365                 dev_dbg(pTAS2557->dev, "%s, config [%d] already loaded\n",
366                         __func__, nNewConfig);
367                 goto end;
368         } else
369                 pPrevConfiguration = &(pTAS2557->mpFirmware->mpConfigurations[nPrevConfig]);
371         pNewConfiguration = &(pTAS2557->mpFirmware->mpConfigurations[nNewConfig]);
372         pTAS2557->mnCurrentConfiguration = nNewConfig;
373         if (pPrevConfiguration) {
374                 if (pPrevConfiguration->mnPLL == pNewConfiguration->mnPLL) {
375                         dev_dbg(pTAS2557->dev, "%s, PLL same\n", __func__);
376                         goto prog_coefficient;
377                 }
378         }
380         pProgram = &(pTAS2557->mpFirmware->mpPrograms[pTAS2557->mnCurrentProgram]);
381         if (bPowerOn) {
382                 dev_dbg(pTAS2557->dev, "%s, power down to load new PLL\n", __func__);
383                 if (hrtimer_active(&pTAS2557->mtimer))
384                         hrtimer_cancel(&pTAS2557->mtimer);
386                 if (pProgram->mnAppMode == TAS2557_APP_TUNINGMODE)
387                         pTAS2557->enableIRQ(pTAS2557, false, false);
389                 nResult = tas2557_dev_load_data(pTAS2557, p_tas2557_shutdown_data);
390                 if (nResult < 0)
391                         goto end;
392                 bRestorePower = true;
393         }
395         /* load PLL */
396         pPLL = &(pTAS2557->mpFirmware->mpPLLs[pNewConfiguration->mnPLL]);
397         dev_dbg(pTAS2557->dev, "load PLL: %s block for Configuration %s\n",
398                 pPLL->mpName, pNewConfiguration->mpName);
399         nResult = tas2557_load_block(pTAS2557, &(pPLL->mBlock));
400         if (nResult < 0)
401                 goto end;
402         pTAS2557->mnCurrentSampleRate = pNewConfiguration->mnSamplingRate;
404         dev_dbg(pTAS2557->dev, "load configuration %s conefficient pre block\n",
405                 pNewConfiguration->mpName);
406         nResult = tas2557_load_data(pTAS2557, &(pNewConfiguration->mData), TAS2557_BLOCK_CFG_PRE_DEV_A);
407         if (nResult < 0)
408                 goto end;
410 prog_coefficient:
411         dev_dbg(pTAS2557->dev, "load new configuration: %s, coeff block data\n",
412                 pNewConfiguration->mpName);
413         nResult = tas2557_load_data(pTAS2557, &(pNewConfiguration->mData),
414                 TAS2557_BLOCK_CFG_COEFF_DEV_A);
415         if (nResult < 0)
416                 goto end;
418         if (pTAS2557->mpCalFirmware->mnCalibrations) {
419                 nResult = tas2557_set_calibration(pTAS2557, pTAS2557->mnCurrentCalibration);
420                 if (nResult < 0)
421                         goto end;
422         }
424         if (bRestorePower) {
425                 pTAS2557->clearIRQ(pTAS2557);
426                 dev_dbg(pTAS2557->dev, "device powered up, load startup\n");
427                 nResult = tas2557_dev_load_data(pTAS2557, p_tas2557_startup_data);
428                 if (nResult < 0)
429                         goto end;
430                 if (pProgram->mnAppMode == TAS2557_APP_TUNINGMODE) {
431                         nResult = tas2557_checkPLL(pTAS2557);
432                         if (nResult < 0) {
433                                 nResult = tas2557_dev_load_data(pTAS2557, p_tas2557_shutdown_data);
434                                 pTAS2557->mbPowerUp = false;
435                                 goto end;
436                         }
437                 }
438                 dev_dbg(pTAS2557->dev,
439                         "device powered up, load unmute\n");
440                 nResult = tas2557_dev_load_data(pTAS2557, p_tas2557_unmute_data);
441                 if (nResult < 0)
442                         goto end;
443                 if (pProgram->mnAppMode == TAS2557_APP_TUNINGMODE) {
444                         pTAS2557->enableIRQ(pTAS2557, true, true);
445                         if (!hrtimer_active(&pTAS2557->mtimer)) {
446                                 pTAS2557->mnDieTvReadCounter = 0;
447                                 hrtimer_start(&pTAS2557->mtimer,
448                                         ns_to_ktime((u64)LOW_TEMPERATURE_CHECK_PERIOD * NSEC_PER_MSEC), HRTIMER_MODE_REL);
449                         }
450                 }
451         }
452 end:
454         pTAS2557->mnNewConfiguration = pTAS2557->mnCurrentConfiguration;
455         return nResult;
458 int tas2557_update_edge(struct tas2557_priv *pTAS2557)
460         int nResult = 0;
461         dev_dbg(pTAS2557->dev,
462                 "%s, edge: %d\n",
463                 __func__, pTAS2557->mnEdge);
465         nResult = pTAS2557->update_bits(pTAS2557, TAS2557_SPK_CTRL_REG, 0x7, pTAS2557->mnEdge);
467         return nResult;
470 int tas2557_enable(struct tas2557_priv *pTAS2557, bool bEnable)
472         int nResult = 0;
473         unsigned int nValue;
474         const char *pFWName;
475         struct TProgram *pProgram;
477         dev_dbg(pTAS2557->dev, "Enable: %d\n", bEnable);
479         if ((pTAS2557->mpFirmware->mnPrograms == 0)
480                 || (pTAS2557->mpFirmware->mnConfigurations == 0)) {
481                 dev_err(pTAS2557->dev, "%s, firmware not loaded\n", __func__);
482                 /*Load firmware*/
483                 if (pTAS2557->mnPGID == TAS2557_PG_VERSION_2P1) {
484                         dev_info(pTAS2557->dev, "PG2.1 Silicon found\n");
485                         pFWName = TAS2557_FW_NAME;
486                 } else if (pTAS2557->mnPGID == TAS2557_PG_VERSION_1P0) {
487                         dev_info(pTAS2557->dev, "PG1.0 Silicon found\n");
488                         pFWName = TAS2557_PG1P0_FW_NAME;
489                 } else {
490                         nResult = -ENOTSUPP;
491                         dev_info(pTAS2557->dev, "unsupport Silicon 0x%x\n", pTAS2557->mnPGID);
492                         goto end;
493                 }
494                 nResult = request_firmware_nowait(THIS_MODULE, 1, pFWName,
495                         pTAS2557->dev, GFP_KERNEL, pTAS2557, tas2557_fw_ready);
496                 if(nResult < 0)
497                         goto end;
498                 dev_err(pTAS2557->dev, "%s, firmware is loaded\n", __func__);
499         }
501         /* check safe guard*/
502         nResult = pTAS2557->read(pTAS2557, TAS2557_SAFE_GUARD_REG, &nValue);
503         if (nResult < 0)
504                 goto end;
505         if ((nValue&0xff) != TAS2557_SAFE_GUARD_PATTERN) {
506                 dev_err(pTAS2557->dev, "ERROR safe guard failure!\n");
507                 nResult = -EPIPE;
508                 pTAS2557->mnErrCode = ERROR_SAFE_GUARD;
509                 pTAS2557->mbPowerUp = true;
510                 goto end;
511         }
513         pProgram = &(pTAS2557->mpFirmware->mpPrograms[pTAS2557->mnCurrentProgram]);
514         if (bEnable) {
515                 if (!pTAS2557->mbPowerUp) {
516                         if (!pTAS2557->mbCalibrationLoaded) {
517                                 tas2557_set_calibration(pTAS2557, 0xFF);
518                                 pTAS2557->mbCalibrationLoaded = true;
519                         }
521                         if (pTAS2557->mbLoadConfigurationPrePowerUp) {
522                                 dev_dbg(pTAS2557->dev, "load coefficient before power\n");
523                                 pTAS2557->mbLoadConfigurationPrePowerUp = false;
524                                 nResult = tas2557_load_coefficient(pTAS2557,
525                                         pTAS2557->mnCurrentConfiguration, pTAS2557->mnNewConfiguration, false);
526                                 if (nResult < 0)
527                                         goto end;
528                         }
530                         pTAS2557->clearIRQ(pTAS2557);
531                         /* power on device */
532                         dev_dbg(pTAS2557->dev, "Enable: load startup sequence\n");
533                         nResult = tas2557_dev_load_data(pTAS2557, p_tas2557_startup_data);
534                         if (nResult < 0)
535                                 goto end;
536                         if (pProgram->mnAppMode == TAS2557_APP_TUNINGMODE) {
537                                 nResult = tas2557_checkPLL(pTAS2557);
538                                 if (nResult < 0) {
539                                         nResult = tas2557_dev_load_data(pTAS2557, p_tas2557_shutdown_data);
540                                         goto end;
541                                 }
542                         }
543                         dev_dbg(pTAS2557->dev, "Enable: load unmute sequence\n");
544                         nResult = tas2557_dev_load_data(pTAS2557, p_tas2557_unmute_data);
545                         if (nResult < 0)
546                                 goto end;
548                         pTAS2557->mbPowerUp = true;
550                         tas2557_get_die_temperature(pTAS2557, &nValue);
551                         if(nValue == 0x80000000)
552                         {
553                                 dev_err(pTAS2557->dev, "%s, thermal sensor is wrong, mute output\n", __func__);
554                                 nResult = tas2557_dev_load_data(pTAS2557, p_tas2557_shutdown_data);
555                                 pTAS2557->mbPowerUp = false;
556                                 goto end;
557                         }
559                         if (pProgram->mnAppMode == TAS2557_APP_TUNINGMODE) {
560                                 /* turn on IRQ */
561                                 pTAS2557->enableIRQ(pTAS2557, true, true);
562                                 if (!hrtimer_active(&pTAS2557->mtimer)) {
563                                         pTAS2557->mnDieTvReadCounter = 0;
564                                         hrtimer_start(&pTAS2557->mtimer,
565                                                 ns_to_ktime((u64)LOW_TEMPERATURE_CHECK_PERIOD * NSEC_PER_MSEC), HRTIMER_MODE_REL);
566                                 }
567                         }
568                         pTAS2557->mnRestart = 0;
569                 }
570         } else {
571                 if (pTAS2557->mbPowerUp) {
572                         if (hrtimer_active(&pTAS2557->mtimer))
573                                 hrtimer_cancel(&pTAS2557->mtimer);
575                         dev_dbg(pTAS2557->dev, "Enable: load shutdown sequence\n");
576                         if (pProgram->mnAppMode == TAS2557_APP_TUNINGMODE) {
577                                 /* turn off IRQ */
578                                 pTAS2557->enableIRQ(pTAS2557, false, false);
579                         }
580                         nResult = tas2557_dev_load_data(pTAS2557, p_tas2557_shutdown_data);
581                         if (nResult < 0)
582                                 goto end;
584                         pTAS2557->mbPowerUp = false;
585                         pTAS2557->mnRestart = 0;
586                 }
587         }
589         nResult = 0;
591 end:
592         if (nResult < 0) {
593                 if (pTAS2557->mnErrCode & (ERROR_DEVA_I2C_COMM | ERROR_PRAM_CRCCHK | ERROR_YRAM_CRCCHK | ERROR_SAFE_GUARD))
594                         failsafe(pTAS2557);
595         }
597         return nResult;
600 int tas2557_set_sampling_rate(struct tas2557_priv *pTAS2557, unsigned int nSamplingRate)
602         int nResult = 0;
603         struct TConfiguration *pConfiguration;
604         unsigned int nConfiguration;
606         dev_dbg(pTAS2557->dev, "tas2557_setup_clocks: nSamplingRate = %d [Hz]\n",
607                 nSamplingRate);
609         if ((!pTAS2557->mpFirmware->mpPrograms) ||
610                 (!pTAS2557->mpFirmware->mpConfigurations)) {
611                 dev_err(pTAS2557->dev, "Firmware not loaded\n");
612                 nResult = -EINVAL;
613                 goto end;
614         }
616         pConfiguration = &(pTAS2557->mpFirmware->mpConfigurations[pTAS2557->mnCurrentConfiguration]);
617         if (pConfiguration->mnSamplingRate == nSamplingRate) {
618                 dev_info(pTAS2557->dev, "Sampling rate for current configuration matches: %d\n",
619                         nSamplingRate);
620                 nResult = 0;
621                 goto end;
622         }
624         for (nConfiguration = 0;
625                 nConfiguration < pTAS2557->mpFirmware->mnConfigurations;
626                 nConfiguration++) {
627                 pConfiguration =
628                         &(pTAS2557->mpFirmware->mpConfigurations[nConfiguration]);
629                 if ((pConfiguration->mnSamplingRate == nSamplingRate)
630                         && (pConfiguration->mnProgram == pTAS2557->mnCurrentProgram)) {
631                         dev_info(pTAS2557->dev,
632                                 "Found configuration: %s, with compatible sampling rate %d\n",
633                                 pConfiguration->mpName, nSamplingRate);
634                         nResult = tas2557_load_configuration(pTAS2557, nConfiguration, false);
635                         goto end;
636                 }
637         }
639         dev_err(pTAS2557->dev, "Cannot find a configuration that supports sampling rate: %d\n",
640                 nSamplingRate);
642 end:
644         return nResult;
647 static void fw_print_header(struct tas2557_priv *pTAS2557, struct TFirmware *pFirmware)
649         dev_info(pTAS2557->dev, "FW Size       = %d", pFirmware->mnFWSize);
650         dev_info(pTAS2557->dev, "Checksum      = 0x%04X", pFirmware->mnChecksum);
651         dev_info(pTAS2557->dev, "PPC Version   = 0x%04X", pFirmware->mnPPCVersion);
652         dev_info(pTAS2557->dev, "FW  Version    = 0x%04X", pFirmware->mnFWVersion);
653         dev_info(pTAS2557->dev, "Driver Version= 0x%04X", pFirmware->mnDriverVersion);
654         dev_info(pTAS2557->dev, "Timestamp     = %d", pFirmware->mnTimeStamp);
655         dev_info(pTAS2557->dev, "DDC Name      = %s", pFirmware->mpDDCName);
656         dev_info(pTAS2557->dev, "Description   = %s", pFirmware->mpDescription);
659 inline unsigned int fw_convert_number(unsigned char *pData)
661         return pData[3] + (pData[2] << 8) + (pData[1] << 16) + (pData[0] << 24);
664 static int fw_parse_header(struct tas2557_priv *pTAS2557,
665         struct TFirmware *pFirmware, unsigned char *pData, unsigned int nSize)
667         unsigned char *pDataStart = pData;
668         unsigned int n;
669         unsigned char pMagicNumber[] = { 0x35, 0x35, 0x35, 0x32 };
671         if (nSize < 104) {
672                 dev_err(pTAS2557->dev, "Firmware: Header too short");
673                 return -EINVAL;
674         }
676         if (memcmp(pData, pMagicNumber, 4)) {
677                 dev_err(pTAS2557->dev, "Firmware: Magic number doesn't match");
678                 return -EINVAL;
679         }
680         pData += 4;
682         pFirmware->mnFWSize = fw_convert_number(pData);
683         pData += 4;
685         pFirmware->mnChecksum = fw_convert_number(pData);
686         pData += 4;
688         pFirmware->mnPPCVersion = fw_convert_number(pData);
689         pData += 4;
691         pFirmware->mnFWVersion = fw_convert_number(pData);
692         pData += 4;
694         pFirmware->mnDriverVersion = fw_convert_number(pData);
695         pData += 4;
697         pFirmware->mnTimeStamp = fw_convert_number(pData);
698         pData += 4;
700         memcpy(pFirmware->mpDDCName, pData, 64);
701         pData += 64;
703         n = strlen(pData);
704         pFirmware->mpDescription = kmemdup(pData, n + 1, GFP_KERNEL);
705         pData += n + 1;
706         if ((pData - pDataStart) >= nSize) {
707                 dev_err(pTAS2557->dev, "Firmware: Header too short after DDC description");
708                 return -EINVAL;
709         }
711         pFirmware->mnDeviceFamily = fw_convert_number(pData);
712         pData += 4;
713         if (pFirmware->mnDeviceFamily != 0) {
714                 dev_err(pTAS2557->dev,
715                         "deviceFamily %d, not TAS device", pFirmware->mnDeviceFamily);
716                 return -EINVAL;
717         }
719         pFirmware->mnDevice = fw_convert_number(pData);
720         pData += 4;
722         if (pFirmware->mnDevice != 2) {
723                 dev_err(pTAS2557->dev,
724                         "device %d, not TAS2557 Dual Mono", pFirmware->mnDevice);
725                 return -EINVAL;
726         }
728         fw_print_header(pTAS2557, pFirmware);
729         return pData - pDataStart;
732 static int fw_parse_block_data(struct tas2557_priv *pTAS2557, struct TFirmware *pFirmware,
733         struct TBlock *pBlock, unsigned char *pData)
735         unsigned char *pDataStart = pData;
736         unsigned int n;
738         pBlock->mnType = fw_convert_number(pData);
739         pData += 4;
741         if (pFirmware->mnDriverVersion >= PPC_DRIVER_CRCCHK) {
742                 pBlock->mbPChkSumPresent = pData[0];
743                 pData++;
745                 pBlock->mnPChkSum = pData[0];
746                 pData++;
748                 pBlock->mbYChkSumPresent = pData[0];
749                 pData++;
751                 pBlock->mnYChkSum = pData[0];
752                 pData++;
753         } else {
754                 pBlock->mbPChkSumPresent = 0;
755                 pBlock->mbYChkSumPresent = 0;
756         }
758         pBlock->mnCommands = fw_convert_number(pData);
759         pData += 4;
761         n = pBlock->mnCommands * 4;
762         pBlock->mpData = kmemdup(pData, n, GFP_KERNEL);
763         pData += n;
764         return pData - pDataStart;
767 static int fw_parse_data(struct tas2557_priv *pTAS2557, struct TFirmware *pFirmware,
768         struct TData *pImageData, unsigned char *pData)
770         unsigned char *pDataStart = pData;
771         unsigned int nBlock;
772         unsigned int n;
774         memcpy(pImageData->mpName, pData, 64);
775         pData += 64;
777         n = strlen(pData);
778         pImageData->mpDescription = kmemdup(pData, n + 1, GFP_KERNEL);
779         pData += n + 1;
781         pImageData->mnBlocks = (pData[0] << 8) + pData[1];
782         pData += 2;
784         pImageData->mpBlocks =
785                 kmalloc(sizeof(struct TBlock) * pImageData->mnBlocks, GFP_KERNEL);
786         if(pImageData->mpBlocks == NULL)
787         {
788                 dev_dbg(pTAS2557->dev, "failed malloc blocks mem\n");
789                 goto end;
790         }
792         for (nBlock = 0; nBlock < pImageData->mnBlocks; nBlock++) {
793                 n = fw_parse_block_data(pTAS2557, pFirmware,
794                         &(pImageData->mpBlocks[nBlock]), pData);
795                 pData += n;
796         }
797         return pData - pDataStart;
800 static int fw_parse_pll_data(struct tas2557_priv *pTAS2557,
801         struct TFirmware *pFirmware, unsigned char *pData)
803         unsigned char *pDataStart = pData;
804         unsigned int n;
805         unsigned int nPLL;
806         struct TPLL *pPLL;
808         pFirmware->mnPLLs = (pData[0] << 8) + pData[1];
809         pData += 2;
811         if (pFirmware->mnPLLs == 0)
812                 goto end;
814         pFirmware->mpPLLs = kmalloc_array(pFirmware->mnPLLs, sizeof(struct TPLL), GFP_KERNEL);
815         for (nPLL = 0; nPLL < pFirmware->mnPLLs; nPLL++) {
816                 pPLL = &(pFirmware->mpPLLs[nPLL]);
818                 memcpy(pPLL->mpName, pData, 64);
819                 pData += 64;
821                 n = strlen(pData);
822                 pPLL->mpDescription = kmemdup(pData, n + 1, GFP_KERNEL);
823                 pData += n + 1;
825                 n = fw_parse_block_data(pTAS2557, pFirmware, &(pPLL->mBlock), pData);
826                 pData += n;
827         }
829 end:
830         return pData - pDataStart;
833 static int fw_parse_program_data(struct tas2557_priv *pTAS2557,
834         struct TFirmware *pFirmware, unsigned char *pData)
836         unsigned char *pDataStart = pData;
837         unsigned int n;
838         unsigned int nProgram;
839         struct TProgram *pProgram;
841         pFirmware->mnPrograms = (pData[0] << 8) + pData[1];
842         pData += 2;
844         if (pFirmware->mnPrograms == 0)
845                 goto end;
847         pFirmware->mpPrograms =
848                 kmalloc(sizeof(struct TProgram) * pFirmware->mnPrograms, GFP_KERNEL);
849         if(pFirmware->mpPrograms == NULL)
850         {
851                 dev_dbg(pTAS2557->dev, "failed malloc program mem\n");
852                 goto end;
853         }
855         for (nProgram = 0; nProgram < pFirmware->mnPrograms; nProgram++) {
856                 pProgram = &(pFirmware->mpPrograms[nProgram]);
857                 memcpy(pProgram->mpName, pData, 64);
858                 pData += 64;
860                 n = strlen(pData);
861                 pProgram->mpDescription = kmemdup(pData, n + 1, GFP_KERNEL);
862                 pData += n + 1;
864                 pProgram->mnAppMode = pData[0];
865                 pData++;
867                 pProgram->mnBoost = (pData[0] << 8) + pData[1];
868                 pData += 2;
870                 n = fw_parse_data(pTAS2557, pFirmware, &(pProgram->mData), pData);
871                 pData += n;
872         }
874 end:
876         return pData - pDataStart;
879 static int fw_parse_configuration_data(struct tas2557_priv *pTAS2557,
880         struct TFirmware *pFirmware, unsigned char *pData)
882         unsigned char *pDataStart = pData;
883         unsigned int n;
884         unsigned int nConfiguration;
885         struct TConfiguration *pConfiguration;
887         pFirmware->mnConfigurations = (pData[0] << 8) + pData[1];
888         pData += 2;
890         if (pFirmware->mnConfigurations == 0)
891                 goto end;
893         pFirmware->mpConfigurations =
894                 kmalloc(sizeof(struct TConfiguration) * pFirmware->mnConfigurations,
895                 GFP_KERNEL);
896         if(pFirmware->mpConfigurations == NULL)
897         {
898                 dev_dbg(pTAS2557->dev, "failed malloc configuration mem\n");
899                 goto end;
900         }
902         for (nConfiguration = 0; nConfiguration < pFirmware->mnConfigurations;
903                 nConfiguration++) {
904                 pConfiguration = &(pFirmware->mpConfigurations[nConfiguration]);
905                 memcpy(pConfiguration->mpName, pData, 64);
906                 pData += 64;
908                 n = strlen(pData);
909                 pConfiguration->mpDescription = kmemdup(pData, n + 1, GFP_KERNEL);
910                 pData += n + 1;
912                 if ((pFirmware->mnDriverVersion >= PPC_DRIVER_CONFDEV)
913                         || ((pFirmware->mnDriverVersion >= PPC_DRIVER_CFGDEV_NONCRC)
914                                 && (pFirmware->mnDriverVersion < PPC_DRIVER_CRCCHK))) {
915                         pConfiguration->mnDevices = (pData[0] << 8) + pData[1];
916                         pData += 2;
917                 } else
918                         pConfiguration->mnDevices = 1;
920                 pConfiguration->mnProgram = pData[0];
921                 pData++;
923                 pConfiguration->mnPLL = pData[0];
924                 pData++;
926                 pConfiguration->mnSamplingRate = fw_convert_number(pData);
927                 pData += 4;
929                 if (pFirmware->mnDriverVersion >= PPC_DRIVER_MTPLLSRC) {
930                         pConfiguration->mnPLLSrc = pData[0];
931                         pData++;
933                         pConfiguration->mnPLLSrcRate = fw_convert_number(pData);
934                         pData += 4;
935                 }
937                 n = fw_parse_data(pTAS2557, pFirmware, &(pConfiguration->mData), pData);
938                 pData += n;
939         }
941 end:
943         return pData - pDataStart;
946 int fw_parse_calibration_data(struct tas2557_priv *pTAS2557,
947         struct TFirmware *pFirmware, unsigned char *pData)
949         unsigned char *pDataStart = pData;
950         unsigned int n;
951         unsigned int nCalibration;
952         struct TCalibration *pCalibration;
954         pFirmware->mnCalibrations = (pData[0] << 8) + pData[1];
955         pData += 2;
957         if (pFirmware->mnCalibrations == 0)
958                 goto end;
960         pFirmware->mpCalibrations =
961                 kmalloc(sizeof(struct TCalibration) * pFirmware->mnCalibrations, GFP_KERNEL);
962         if(pFirmware->mpCalibrations == NULL)
963         {
964                 dev_err(pTAS2557->dev, "failed to malloc calibration mem\n");
965                 goto end;
966         }
968         for (nCalibration = 0;
969                 nCalibration < pFirmware->mnCalibrations;
970                 nCalibration++) {
971                 pCalibration = &(pFirmware->mpCalibrations[nCalibration]);
972                 memcpy(pCalibration->mpName, pData, 64);
973                 pData += 64;
975                 n = strlen(pData);
976                 pCalibration->mpDescription = kmemdup(pData, n + 1, GFP_KERNEL);
977                 pData += n + 1;
979                 pCalibration->mnProgram = pData[0];
980                 pData++;
982                 pCalibration->mnConfiguration = pData[0];
983                 pData++;
985                 n = fw_parse_data(pTAS2557, pFirmware, &(pCalibration->mData), pData);
986                 pData += n;
987         }
989 end:
991         return pData - pDataStart;
994 static int fw_parse(struct tas2557_priv *pTAS2557,
995         struct TFirmware *pFirmware, unsigned char *pData, unsigned int nSize)
997         int nPosition = 0;
999         nPosition = fw_parse_header(pTAS2557, pFirmware, pData, nSize);
1000         if (nPosition < 0) {
1001                 dev_err(pTAS2557->dev, "Firmware: Wrong Header");
1002                 return -EINVAL;
1003         }
1005         if (nPosition >= nSize) {
1006                 dev_err(pTAS2557->dev, "Firmware: Too short");
1007                 return -EINVAL;
1008         }
1010         pData += nPosition;
1011         nSize -= nPosition;
1012         nPosition = 0;
1014         nPosition = fw_parse_pll_data(pTAS2557, pFirmware, pData);
1016         pData += nPosition;
1017         nSize -= nPosition;
1018         nPosition = 0;
1020         nPosition = fw_parse_program_data(pTAS2557, pFirmware, pData);
1022         pData += nPosition;
1023         nSize -= nPosition;
1024         nPosition = 0;
1026         nPosition = fw_parse_configuration_data(pTAS2557, pFirmware, pData);
1028         pData += nPosition;
1029         nSize -= nPosition;
1030         nPosition = 0;
1032         if (nSize > 64)
1033                 nPosition = fw_parse_calibration_data(pTAS2557, pFirmware, pData);
1034         return 0;
1038 static const unsigned char crc8_lookup_table[CRC8_TABLE_SIZE] = {
1039 0x00, 0x4D, 0x9A, 0xD7, 0x79, 0x34, 0xE3, 0xAE, 0xF2, 0xBF, 0x68, 0x25, 0x8B, 0xC6, 0x11, 0x5C,
1040 0xA9, 0xE4, 0x33, 0x7E, 0xD0, 0x9D, 0x4A, 0x07, 0x5B, 0x16, 0xC1, 0x8C, 0x22, 0x6F, 0xB8, 0xF5,
1041 0x1F, 0x52, 0x85, 0xC8, 0x66, 0x2B, 0xFC, 0xB1, 0xED, 0xA0, 0x77, 0x3A, 0x94, 0xD9, 0x0E, 0x43,
1042 0xB6, 0xFB, 0x2C, 0x61, 0xCF, 0x82, 0x55, 0x18, 0x44, 0x09, 0xDE, 0x93, 0x3D, 0x70, 0xA7, 0xEA,
1043 0x3E, 0x73, 0xA4, 0xE9, 0x47, 0x0A, 0xDD, 0x90, 0xCC, 0x81, 0x56, 0x1B, 0xB5, 0xF8, 0x2F, 0x62,
1044 0x97, 0xDA, 0x0D, 0x40, 0xEE, 0xA3, 0x74, 0x39, 0x65, 0x28, 0xFF, 0xB2, 0x1C, 0x51, 0x86, 0xCB,
1045 0x21, 0x6C, 0xBB, 0xF6, 0x58, 0x15, 0xC2, 0x8F, 0xD3, 0x9E, 0x49, 0x04, 0xAA, 0xE7, 0x30, 0x7D,
1046 0x88, 0xC5, 0x12, 0x5F, 0xF1, 0xBC, 0x6B, 0x26, 0x7A, 0x37, 0xE0, 0xAD, 0x03, 0x4E, 0x99, 0xD4,
1047 0x7C, 0x31, 0xE6, 0xAB, 0x05, 0x48, 0x9F, 0xD2, 0x8E, 0xC3, 0x14, 0x59, 0xF7, 0xBA, 0x6D, 0x20,
1048 0xD5, 0x98, 0x4F, 0x02, 0xAC, 0xE1, 0x36, 0x7B, 0x27, 0x6A, 0xBD, 0xF0, 0x5E, 0x13, 0xC4, 0x89,
1049 0x63, 0x2E, 0xF9, 0xB4, 0x1A, 0x57, 0x80, 0xCD, 0x91, 0xDC, 0x0B, 0x46, 0xE8, 0xA5, 0x72, 0x3F,
1050 0xCA, 0x87, 0x50, 0x1D, 0xB3, 0xFE, 0x29, 0x64, 0x38, 0x75, 0xA2, 0xEF, 0x41, 0x0C, 0xDB, 0x96,
1051 0x42, 0x0F, 0xD8, 0x95, 0x3B, 0x76, 0xA1, 0xEC, 0xB0, 0xFD, 0x2A, 0x67, 0xC9, 0x84, 0x53, 0x1E,
1052 0xEB, 0xA6, 0x71, 0x3C, 0x92, 0xDF, 0x08, 0x45, 0x19, 0x54, 0x83, 0xCE, 0x60, 0x2D, 0xFA, 0xB7,
1053 0x5D, 0x10, 0xC7, 0x8A, 0x24, 0x69, 0xBE, 0xF3, 0xAF, 0xE2, 0x35, 0x78, 0xD6, 0x9B, 0x4C, 0x01,
1054 0xF4, 0xB9, 0x6E, 0x23, 0x8D, 0xC0, 0x17, 0x5A, 0x06, 0x4B, 0x9C, 0xD1, 0x7F, 0x32, 0xE5, 0xA8
1055 };
1057 static int isInPageYRAM(struct tas2557_priv *pTAS2557, struct TYCRC *pCRCData,
1058         unsigned char nBook, unsigned char nPage, unsigned char nReg, unsigned char len)
1060         int nResult = 0;
1062         if (nBook == TAS2557_YRAM_BOOK1) {
1063                 if (nPage == TAS2557_YRAM1_PAGE) {
1064                         if (nReg >= TAS2557_YRAM1_START_REG) {
1065                                 pCRCData->mnOffset = nReg;
1066                                 pCRCData->mnLen = len;
1067                                 nResult = 1;
1068                         } else if ((nReg + len) > TAS2557_YRAM1_START_REG) {
1069                                 pCRCData->mnOffset = TAS2557_YRAM1_START_REG;
1070                                 pCRCData->mnLen = len - (TAS2557_YRAM1_START_REG - nReg);
1071                                 nResult = 1;
1072                         } else
1073                                 nResult = 0;
1074                 } else if (nPage == TAS2557_YRAM3_PAGE) {
1075                         if (nReg > TAS2557_YRAM3_END_REG) {
1076                                 nResult = 0;
1077                         } else if (nReg >= TAS2557_YRAM3_START_REG) {
1078                                 if ((nReg + len) > TAS2557_YRAM3_END_REG) {
1079                                         pCRCData->mnOffset = nReg;
1080                                         pCRCData->mnLen = TAS2557_YRAM3_END_REG - nReg + 1;
1081                                         nResult = 1;
1082                                 } else {
1083                                         pCRCData->mnOffset = nReg;
1084                                         pCRCData->mnLen = len;
1085                                         nResult = 1;
1086                                 }
1087                         } else {
1088                                 if ((nReg + (len - 1)) < TAS2557_YRAM3_START_REG)
1089                                         nResult = 0;
1090                                 else {
1091                                         pCRCData->mnOffset = TAS2557_YRAM3_START_REG;
1092                                         pCRCData->mnLen = len - (TAS2557_YRAM3_START_REG - nReg);
1093                                         nResult = 1;
1094                                 }
1095                         }
1096                 }
1097         } else if (nBook == TAS2557_YRAM_BOOK2) {
1098                 if (nPage == TAS2557_YRAM5_PAGE) {
1099                         if (nReg > TAS2557_YRAM5_END_REG) {
1100                                 nResult = 0;
1101                         } else if (nReg >= TAS2557_YRAM5_START_REG) {
1102                                 if ((nReg + len) > TAS2557_YRAM5_END_REG) {
1103                                         pCRCData->mnOffset = nReg;
1104                                         pCRCData->mnLen = TAS2557_YRAM5_END_REG - nReg + 1;
1105                                         nResult = 1;
1106                                 } else {
1107                                         pCRCData->mnOffset = nReg;
1108                                         pCRCData->mnLen = len;
1109                                         nResult = 1;
1110                                 }
1111                         } else {
1112                                 if ((nReg + (len - 1)) < TAS2557_YRAM5_START_REG)
1113                                         nResult = 0;
1114                                 else {
1115                                         pCRCData->mnOffset = TAS2557_YRAM5_START_REG;
1116                                         pCRCData->mnLen = len - (TAS2557_YRAM5_START_REG - nReg);
1117                                         nResult = 1;
1118                                 }
1119                         }
1120                 }
1121         } else
1122                 nResult = 0;
1124         return nResult;
1127 static int isInBlockYRAM(struct tas2557_priv *pTAS2557, struct TYCRC *pCRCData,
1128         unsigned char nBook, unsigned char nPage, unsigned char nReg, unsigned char len)
1130         int nResult;
1132         if (nBook == TAS2557_YRAM_BOOK1) {
1133                 if (nPage < TAS2557_YRAM2_START_PAGE)
1134                         nResult = 0;
1135                 else if (nPage <= TAS2557_YRAM2_END_PAGE) {
1136                         if (nReg > TAS2557_YRAM2_END_REG)
1137                                 nResult = 0;
1138                         else if (nReg >= TAS2557_YRAM2_START_REG) {
1139                                 pCRCData->mnOffset = nReg;
1140                                 pCRCData->mnLen = len;
1141                                 nResult = 1;
1142                         } else {
1143                                 if ((nReg + (len - 1)) < TAS2557_YRAM2_START_REG)
1144                                         nResult = 0;
1145                                 else {
1146                                         pCRCData->mnOffset = TAS2557_YRAM2_START_REG;
1147                                         pCRCData->mnLen = nReg + len - TAS2557_YRAM2_START_REG;
1148                                         nResult = 1;
1149                                 }
1150                         }
1151                 } else
1152                         nResult = 0;
1153         } else if (nBook == TAS2557_YRAM_BOOK2) {
1154                 if (nPage < TAS2557_YRAM4_START_PAGE)
1155                         nResult = 0;
1156                 else if (nPage <= TAS2557_YRAM4_END_PAGE) {
1157                         if (nReg > TAS2557_YRAM2_END_REG)
1158                                 nResult = 0;
1159                         else if (nReg >= TAS2557_YRAM2_START_REG) {
1160                                 pCRCData->mnOffset = nReg;
1161                                 pCRCData->mnLen = len;
1162                                 nResult = 1;
1163                         } else {
1164                                 if ((nReg + (len - 1)) < TAS2557_YRAM2_START_REG)
1165                                         nResult = 0;
1166                                 else {
1167                                         pCRCData->mnOffset = TAS2557_YRAM2_START_REG;
1168                                         pCRCData->mnLen = nReg + len - TAS2557_YRAM2_START_REG;
1169                                         nResult = 1;
1170                                 }
1171                         }
1172                 } else
1173                         nResult = 0;
1174         } else
1175                 nResult = 0;
1177         return nResult;
1181 static int isYRAM(struct tas2557_priv *pTAS2557, struct TYCRC *pCRCData,
1182         unsigned char nBook, unsigned char nPage, unsigned char nReg, unsigned char len)
1184         int nResult;
1186         nResult = isInPageYRAM(pTAS2557, pCRCData, nBook, nPage, nReg, len);
1188         if (nResult == 0)
1189                 nResult = isInBlockYRAM(pTAS2557, pCRCData, nBook, nPage, nReg, len);
1191         return nResult;
1194 /*
1195  * crc8 - calculate a crc8 over the given input data.
1196  *
1197  * table: crc table used for calculation.
1198  * pdata: pointer to data buffer.
1199  * nbytes: number of bytes in data buffer.
1200  * crc: previous returned crc8 value.
1201  */
1202 static u8 ti_crc8(const u8 table[CRC8_TABLE_SIZE], u8 *pdata, size_t nbytes, u8 crc)
1204         /* loop over the buffer data */
1205         while (nbytes-- > 0)
1206                 crc = table[(crc ^ *pdata++) & 0xff];
1208         return crc;
1211 static int doSingleRegCheckSum(struct tas2557_priv *pTAS2557, 
1212         unsigned char nBook, unsigned char nPage, unsigned char nReg, unsigned char nValue)
1214         int nResult = 0;
1215         struct TYCRC sCRCData;
1216         unsigned int nData1 = 0;
1218         if ((nBook == TAS2557_BOOK_ID(TAS2557_SA_COEFF_SWAP_REG))
1219                 && (nPage == TAS2557_PAGE_ID(TAS2557_SA_COEFF_SWAP_REG))
1220                 && (nReg >= TAS2557_PAGE_REG(TAS2557_SA_COEFF_SWAP_REG))
1221                 && (nReg <= (TAS2557_PAGE_REG(TAS2557_SA_COEFF_SWAP_REG) + 4))) {
1222                 /* DSP swap command, pass */
1223                 nResult = 0;
1224                 goto end;
1225         }
1227         nResult = isYRAM(pTAS2557, &sCRCData, nBook, nPage, nReg, 1);
1228         if (nResult == 1) {
1229                 nResult = pTAS2557->read(pTAS2557, TAS2557_REG(nBook, nPage, nReg), &nData1);
1230                 if (nResult < 0)
1231                         goto end;
1233                 if (nData1 != nValue) {
1234                         dev_err(pTAS2557->dev, "error2 (line %d),B[0x%x]P[0x%x]R[0x%x] W[0x%x], R[0x%x]\n",
1235                                 __LINE__, nBook, nPage, nReg, nValue, nData1);
1236                         nResult = -EAGAIN;
1237                         goto end;
1238                 }
1240                 nResult = ti_crc8(crc8_lookup_table, &nValue, 1, 0);
1241         }
1243 end:
1245         return nResult;
1248 static int doMultiRegCheckSum(struct tas2557_priv *pTAS2557, 
1249         unsigned char nBook, unsigned char nPage, unsigned char nReg, unsigned int len)
1251         int nResult = 0, i;
1252         unsigned char nCRCChkSum = 0;
1253         unsigned char nBuf1[128];
1254         struct TYCRC TCRCData;
1256         if ((nReg + len-1) > 127) {
1257                 nResult = -EINVAL;
1258                 dev_err(pTAS2557->dev, "firmware error\n");
1259                 goto end;
1260         }
1262         if ((nBook == TAS2557_BOOK_ID(TAS2557_SA_COEFF_SWAP_REG))
1263                 && (nPage == TAS2557_PAGE_ID(TAS2557_SA_COEFF_SWAP_REG))
1264                 && (nReg == TAS2557_PAGE_REG(TAS2557_SA_COEFF_SWAP_REG))
1265                 && (len == 4)) {
1266                 /* DSP swap command, pass */
1267                 nResult = 0;
1268                 goto end;
1269         }
1271         nResult = isYRAM(pTAS2557, &TCRCData, nBook, nPage, nReg, len);
1272         if (nResult == 1) {
1273                 if (len == 1) {
1274                         dev_err(pTAS2557->dev, "firmware error\n");
1275                         nResult = -EINVAL;
1276                         goto end;
1277                 } else {
1278                         nResult = pTAS2557->bulk_read(pTAS2557, TAS2557_REG(nBook, nPage, TCRCData.mnOffset), nBuf1, TCRCData.mnLen);
1279                         if (nResult < 0)
1280                                 goto end;
1282                         for (i = 0; i < TCRCData.mnLen; i++) {
1283                                 if ((nBook == TAS2557_BOOK_ID(TAS2557_SA_COEFF_SWAP_REG))
1284                                         && (nPage == TAS2557_PAGE_ID(TAS2557_SA_COEFF_SWAP_REG))
1285                                         && ((i + TCRCData.mnOffset)
1286                                                 >= TAS2557_PAGE_REG(TAS2557_SA_COEFF_SWAP_REG))
1287                                         && ((i + TCRCData.mnOffset)
1288                                                 <= (TAS2557_PAGE_REG(TAS2557_SA_COEFF_SWAP_REG) + 4))) {
1289                                         /* DSP swap command, bypass */
1290                                         continue;
1291                                 } else
1292                                         nCRCChkSum += ti_crc8(crc8_lookup_table, &nBuf1[i], 1, 0);
1293                         }
1295                         nResult = nCRCChkSum;
1296                 }
1297         }
1299 end:
1301         return nResult;
1304 static int tas2557_load_block(struct tas2557_priv *pTAS2557, struct TBlock *pBlock)
1306         int nResult = 0;
1307         unsigned int nCommand = 0;
1308         unsigned char nBook;
1309         unsigned char nPage;
1310         unsigned char nOffset;
1311         unsigned char nData;
1312         unsigned int nLength;
1313         unsigned int nSleep;
1314         unsigned char nCRCChkSum = 0;
1315         unsigned int nValue1;
1316         int nRetry = 6;
1317         unsigned char *pData = pBlock->mpData;
1319         dev_dbg(pTAS2557->dev, "TAS2557 load block: Type = %d, commands = %d\n",
1320                 pBlock->mnType, pBlock->mnCommands);
1321 start:
1322         if (pBlock->mbPChkSumPresent) {
1323                 nResult = pTAS2557->write(pTAS2557, TAS2557_CRC_RESET_REG, 1);
1324                 if (nResult < 0)
1325                         goto end;
1326         }
1328         if (pBlock->mbYChkSumPresent)
1329                 nCRCChkSum = 0;
1331         nCommand = 0;
1333         while (nCommand < pBlock->mnCommands) {
1334                 pData = pBlock->mpData + nCommand * 4;
1336                 nBook = pData[0];
1337                 nPage = pData[1];
1338                 nOffset = pData[2];
1339                 nData = pData[3];
1341                 nCommand++;
1343                 if (nOffset <= 0x7F) {
1344                         nResult = pTAS2557->write(pTAS2557, TAS2557_REG(nBook, nPage, nOffset), nData);
1345                         if (nResult < 0)
1346                                 goto end;
1347                         if (pBlock->mbYChkSumPresent) {
1348                                 nResult = doSingleRegCheckSum(pTAS2557, nBook, nPage, nOffset, nData);
1349                                 if (nResult < 0)
1350                                         goto check;
1351                                 nCRCChkSum += (unsigned char)nResult;
1352                         }
1353                 } else if (nOffset == 0x81) {
1354                         nSleep = (nBook << 8) + nPage;
1355                         msleep(nSleep);
1356                 } else if (nOffset == 0x85) {
1357                         pData += 4;
1358                         nLength = (nBook << 8) + nPage;
1359                         nBook = pData[0];
1360                         nPage = pData[1];
1361                         nOffset = pData[2];
1362                         if (nLength > 1) {
1363                                 nResult = pTAS2557->bulk_write(pTAS2557, TAS2557_REG(nBook, nPage, nOffset), pData + 3, nLength);
1364                                 if (nResult < 0)
1365                                         goto end;
1366                                 if (pBlock->mbYChkSumPresent) {
1367                                         nResult = doMultiRegCheckSum(pTAS2557, nBook, nPage, nOffset, nLength);
1368                                         if (nResult < 0)
1369                                                 goto check;
1370                                         nCRCChkSum += (unsigned char)nResult;
1371                                 }
1372                         } else {
1373                                 nResult = pTAS2557->write(pTAS2557, TAS2557_REG(nBook, nPage, nOffset), pData[3]);
1374                                 if (nResult < 0)
1375                                         goto end;
1376                                 if (pBlock->mbYChkSumPresent) {
1377                                         nResult = doSingleRegCheckSum(pTAS2557, nBook, nPage, nOffset, pData[3]);
1378                                         if (nResult < 0)
1379                                                 goto check;
1380                                         nCRCChkSum += (unsigned char)nResult;
1381                                 }
1382                         }
1384                         nCommand++;
1386                         if (nLength >= 2)
1387                                 nCommand += ((nLength - 2) / 4) + 1;
1388                 }
1389         }
1390         if (pBlock->mbPChkSumPresent) {
1391                 nResult = pTAS2557->read(pTAS2557, TAS2557_CRC_CHECKSUM_REG, &nValue1);
1392                 if (nResult < 0)
1393                         goto end;
1394                 if ((nValue1&0xff) != pBlock->mnPChkSum) {
1395                         dev_err(pTAS2557->dev, "Block PChkSum Error: FW = 0x%x, Reg = 0x%x\n",
1396                                 pBlock->mnPChkSum, (nValue1&0xff));
1397                         nResult = -EAGAIN;
1398                                 pTAS2557->mnErrCode |= ERROR_PRAM_CRCCHK;
1399                         goto check;
1400                 }
1402                 nResult = 0;
1403                 pTAS2557->mnErrCode &= ~ERROR_PRAM_CRCCHK;
1404                 dev_dbg(pTAS2557->dev, "Block[0x%x] PChkSum match\n", pBlock->mnType);
1405         }
1407         if (pBlock->mbYChkSumPresent) {
1408                 if (nCRCChkSum != pBlock->mnYChkSum) {
1409                         dev_err(pTAS2557->dev, "Block YChkSum Error: FW = 0x%x, YCRC = 0x%x\n",
1410                                 pBlock->mnYChkSum, nCRCChkSum);
1411                         nResult = -EAGAIN;
1412                         pTAS2557->mnErrCode |= ERROR_YRAM_CRCCHK;
1413                         goto check;
1414                 }
1415                 pTAS2557->mnErrCode &= ~ERROR_YRAM_CRCCHK;
1416                 nResult = 0;
1417                 dev_dbg(pTAS2557->dev, "Block[0x%x] YChkSum match\n", pBlock->mnType);
1418         }
1420 check:
1421         if (nResult == -EAGAIN) {
1422                 nRetry--;
1423                 if (nRetry > 0)
1424                         goto start;
1425         }
1427 end:
1428         if (nResult < 0) {
1429                 dev_err(pTAS2557->dev, "Block (%d) load error\n",
1430                                 pBlock->mnType);
1431         }
1432         return nResult;
1435 static int tas2557_load_data(struct tas2557_priv *pTAS2557, struct TData *pData, unsigned int nType)
1437         int nResult = 0;
1438         unsigned int nBlock;
1439         struct TBlock *pBlock;
1441         dev_dbg(pTAS2557->dev,
1442                 "TAS2557 load data: %s, Blocks = %d, Block Type = %d\n", pData->mpName, pData->mnBlocks, nType);
1444         for (nBlock = 0; nBlock < pData->mnBlocks; nBlock++) {
1445                 pBlock = &(pData->mpBlocks[nBlock]);
1446                 if (pBlock->mnType == nType) {
1447                         nResult = tas2557_load_block(pTAS2557, pBlock);
1448                         if (nResult < 0)
1449                                 break;
1450                 }
1451         }
1453         return nResult;
1456 static int tas2557_load_configuration(struct tas2557_priv *pTAS2557,
1457         unsigned int nConfiguration, bool bLoadSame)
1459         int nResult = 0;
1460         struct TConfiguration *pCurrentConfiguration = NULL;
1461         struct TConfiguration *pNewConfiguration = NULL;
1463         dev_dbg(pTAS2557->dev, "%s: %d\n", __func__, nConfiguration);
1465         if ((!pTAS2557->mpFirmware->mpPrograms) ||
1466                 (!pTAS2557->mpFirmware->mpConfigurations)) {
1467                 dev_err(pTAS2557->dev, "Firmware not loaded\n");
1468                 nResult = 0;
1469                 goto end;
1470         }
1472         if (nConfiguration >= pTAS2557->mpFirmware->mnConfigurations) {
1473                 dev_err(pTAS2557->dev, "Configuration %d doesn't exist\n",
1474                         nConfiguration);
1475                 nResult = 0;
1476                 goto end;
1477         }
1479         if ((!pTAS2557->mbLoadConfigurationPrePowerUp)
1480                 && (nConfiguration == pTAS2557->mnCurrentConfiguration)
1481                 && (!bLoadSame)) {
1482                 dev_info(pTAS2557->dev, "Configuration %d is already loaded\n",
1483                         nConfiguration);
1484                 nResult = 0;
1485                 goto end;
1486         }
1488         pCurrentConfiguration =
1489                 &(pTAS2557->mpFirmware->mpConfigurations[pTAS2557->mnCurrentConfiguration]);
1490         pNewConfiguration =
1491                 &(pTAS2557->mpFirmware->mpConfigurations[nConfiguration]);
1492         if (pNewConfiguration->mnProgram != pCurrentConfiguration->mnProgram) {
1493                 dev_err(pTAS2557->dev, "Configuration %d, %s doesn't share the same program as current %d\n",
1494                         nConfiguration, pNewConfiguration->mpName, pCurrentConfiguration->mnProgram);
1495                 nResult = 0;
1496                 goto end;
1497         }
1499         if (pNewConfiguration->mnPLL >= pTAS2557->mpFirmware->mnPLLs) {
1500                 dev_err(pTAS2557->dev, "Configuration %d, %s doesn't have a valid PLL index %d\n",
1501                         nConfiguration, pNewConfiguration->mpName, pNewConfiguration->mnPLL);
1502                 nResult = 0;
1503                 goto end;
1504         }
1506         if (pTAS2557->mbPowerUp) {
1507                 pTAS2557->mbLoadConfigurationPrePowerUp = false;
1508                 nResult = tas2557_load_coefficient(pTAS2557, pTAS2557->mnCurrentConfiguration, nConfiguration, true);
1509         } else {
1510                 dev_dbg(pTAS2557->dev,
1511                         "TAS2557 was powered down, will load coefficient when power up\n");
1512                 pTAS2557->mbLoadConfigurationPrePowerUp = true;
1513                 pTAS2557->mnNewConfiguration = nConfiguration;
1514         }
1516 end:
1518         if (nResult < 0) {
1519                 if (pTAS2557->mnErrCode & (ERROR_DEVA_I2C_COMM | ERROR_PRAM_CRCCHK | ERROR_YRAM_CRCCHK))
1520                         failsafe(pTAS2557);
1521         }
1523         return nResult;
1526 int tas2557_set_config(struct tas2557_priv *pTAS2557, int config)
1528         struct TConfiguration *pConfiguration;
1529         struct TProgram *pProgram;
1530         unsigned int nProgram = pTAS2557->mnCurrentProgram;
1531         unsigned int nConfiguration = config;
1532         int nResult = 0;
1534         if ((!pTAS2557->mpFirmware->mpPrograms) ||
1535                 (!pTAS2557->mpFirmware->mpConfigurations)) {
1536                 dev_err(pTAS2557->dev, "Firmware not loaded\n");
1537                 nResult = -EINVAL;
1538                 goto end;
1539         }
1541         if (nConfiguration >= pTAS2557->mpFirmware->mnConfigurations) {
1542                 dev_err(pTAS2557->dev, "Configuration %d doesn't exist\n",
1543                         nConfiguration);
1544                 nResult = -EINVAL;
1545                 goto end;
1546         }
1548         pConfiguration = &(pTAS2557->mpFirmware->mpConfigurations[nConfiguration]);
1549         pProgram = &(pTAS2557->mpFirmware->mpPrograms[nProgram]);
1551         if (nProgram != pConfiguration->mnProgram) {
1552                 dev_err(pTAS2557->dev,
1553                         "Configuration %d, %s with Program %d isn't compatible with existing Program %d, %s\n",
1554                         nConfiguration, pConfiguration->mpName, pConfiguration->mnProgram,
1555                         nProgram, pProgram->mpName);
1556                 nResult = -EINVAL;
1557                 goto end;
1558         }
1560         nResult = tas2557_load_configuration(pTAS2557, nConfiguration, false);
1562 end:
1564         return nResult;
1567 void tas2557_clear_firmware(struct TFirmware *pFirmware)
1569         unsigned int n, nn;
1571         if (!pFirmware)
1572                 return;
1574         kfree(pFirmware->mpDescription);
1576         if (pFirmware->mpPLLs != NULL) {
1577                 for (n = 0; n < pFirmware->mnPLLs; n++) {
1578                         kfree(pFirmware->mpPLLs[n].mpDescription);
1579                         kfree(pFirmware->mpPLLs[n].mBlock.mpData);
1580                 }
1581                 kfree(pFirmware->mpPLLs);
1582         }
1584         if (pFirmware->mpPrograms != NULL) {
1585                 for (n = 0; n < pFirmware->mnPrograms; n++) {
1586                         kfree(pFirmware->mpPrograms[n].mpDescription);
1587                         kfree(pFirmware->mpPrograms[n].mData.mpDescription);
1588                         for (nn = 0; nn < pFirmware->mpPrograms[n].mData.mnBlocks; nn++)
1589                                 kfree(pFirmware->mpPrograms[n].mData.mpBlocks[nn].mpData);
1590                         kfree(pFirmware->mpPrograms[n].mData.mpBlocks);
1591                 }
1592                 kfree(pFirmware->mpPrograms);
1593         }
1595         if (pFirmware->mpConfigurations != NULL) {
1596                 for (n = 0; n < pFirmware->mnConfigurations; n++) {
1597                         kfree(pFirmware->mpConfigurations[n].mpDescription);
1598                         kfree(pFirmware->mpConfigurations[n].mData.mpDescription);
1599                         for (nn = 0; nn < pFirmware->mpConfigurations[n].mData.mnBlocks; nn++)
1600                                 kfree(pFirmware->mpConfigurations[n].mData.mpBlocks[nn].mpData);
1601                         kfree(pFirmware->mpConfigurations[n].mData.mpBlocks);
1602                 }
1603                 kfree(pFirmware->mpConfigurations);
1604         }
1606         if (pFirmware->mpCalibrations != NULL) {
1607                 for (n = 0; n < pFirmware->mnCalibrations; n++) {
1608                         kfree(pFirmware->mpCalibrations[n].mpDescription);
1609                         kfree(pFirmware->mpCalibrations[n].mData.mpDescription);
1610                         for (nn = 0; nn < pFirmware->mpCalibrations[n].mData.mnBlocks; nn++)
1611                                 kfree(pFirmware->mpCalibrations[n].mData.mpBlocks[nn].mpData);
1612                         kfree(pFirmware->mpCalibrations[n].mData.mpBlocks);
1613                 }
1614                 kfree(pFirmware->mpCalibrations);
1615         }
1617         memset(pFirmware, 0x00, sizeof(struct TFirmware));
1620 static int tas2557_load_calibration(struct tas2557_priv *pTAS2557,      char *pFileName)
1622         int nResult = 0;
1624         int nFile;
1625         mm_segment_t fs;
1626         unsigned char pBuffer[1000];
1627         int nSize = 0;
1629         dev_dbg(pTAS2557->dev, "%s:\n", __func__);
1631         fs = get_fs();
1632         set_fs(KERNEL_DS);
1633         nFile = sys_open(pFileName, O_RDONLY, 0);
1635         dev_info(pTAS2557->dev, "TAS2557 calibration file = %s, handle = %d\n",
1636                 pFileName, nFile);
1638         if (nFile >= 0) {
1639                 nSize = sys_read(nFile, pBuffer, 1000);
1640                 sys_close(nFile);
1641         } else {
1642                 dev_err(pTAS2557->dev, "TAS2557 cannot open calibration file: %s\n",
1643                         pFileName);
1644         }
1646         set_fs(fs);
1648         if (!nSize)
1649                 goto end;
1651         tas2557_clear_firmware(pTAS2557->mpCalFirmware);
1652         dev_info(pTAS2557->dev, "TAS2557 calibration file size = %d\n", nSize);
1653         nResult = fw_parse(pTAS2557, pTAS2557->mpCalFirmware, pBuffer, nSize);
1655         if (nResult)
1656                 dev_err(pTAS2557->dev, "TAS2557 calibration file is corrupt\n");
1657         else
1658                 dev_info(pTAS2557->dev, "TAS2557 calibration: %d calibrations\n",
1659                         pTAS2557->mpCalFirmware->mnCalibrations);
1660 end:
1662         return nResult;
1665 static bool tas2557_get_coefficient_in_block(struct tas2557_priv *pTAS2557,
1666         struct TBlock *pBlock, int nReg, int *pnValue)
1668         int nCoefficient = 0;
1669         bool bFound = false;
1670         unsigned char *pCommands;
1671         int nBook, nPage, nOffset, len;
1672         int i, n;
1674         pCommands = pBlock->mpData;
1675         for (i = 0 ; i < pBlock->mnCommands;) {
1676                 nBook = pCommands[4 * i + 0];
1677                 nPage = pCommands[4 * i + 1];
1678                 nOffset = pCommands[4 * i + 2];
1679                 if ((nOffset < 0x7f) || (nOffset == 0x81))
1680                         i++;
1681                 else if (nOffset == 0x85) {
1682                         len = ((int)nBook << 8) | nPage;
1683                         nBook = pCommands[4 * i + 4];
1684                         nPage = pCommands[4 * i + 5];
1685                         nOffset = pCommands[4 * i + 6];
1686                         n = 4 * i + 7;
1687                         i += 2;
1688                         i += ((len - 1) / 4);
1689                         if ((len - 1) % 4)
1690                                 i++;
1691                         if ((nBook != TAS2557_BOOK_ID(nReg))
1692                                 || (nPage != TAS2557_PAGE_ID(nReg)))
1693                                 continue;
1694                         if (nOffset > TAS2557_PAGE_REG(nReg))
1695                                 continue;
1696                         if ((len + nOffset) >= (TAS2557_PAGE_REG(nReg) + 4)) {
1697                                 n += (TAS2557_PAGE_REG(nReg) - nOffset);
1698                                 nCoefficient = ((int)pCommands[n] << 24)
1699                                                 | ((int)pCommands[n + 1] << 16)
1700                                                 | ((int)pCommands[n + 2] << 8)
1701                                                 | (int)pCommands[n + 3];
1702                                 bFound = true;
1703                                 break;
1704                         }
1705                 } else {
1706                         dev_err(pTAS2557->dev, "%s, format error %d\n", __func__, nOffset);
1707                         break;
1708                 }
1709         }
1711         if (bFound) {
1712                 *pnValue = nCoefficient;
1713                 dev_dbg(pTAS2557->dev, "%s, B[0x%x]P[0x%x]R[0x%x]=0x%x\n", __func__,
1714                         TAS2557_BOOK_ID(nReg), TAS2557_PAGE_ID(nReg), TAS2557_PAGE_REG(nReg),
1715                         nCoefficient);
1716         }
1718         return bFound;
1721 static bool tas2557_get_coefficient_in_data(struct tas2557_priv *pTAS2557,
1722         struct TData *pData, int blockType, int nReg, int *pnValue)
1724         bool bFound = false;
1725         struct TBlock *pBlock;
1726         int i;
1728         for (i = 0; i < pData->mnBlocks; i++) {
1729                 pBlock = &(pData->mpBlocks[i]);
1730                 if (pBlock->mnType == blockType) {
1731                         bFound = tas2557_get_coefficient_in_block(pTAS2557,
1732                                                 pBlock, nReg, pnValue);
1733                         if (bFound)
1734                                 break;
1735                 }
1736         }
1738         return bFound;
1741 static bool tas2557_find_Tmax_in_configuration(struct tas2557_priv *pTAS2557,
1742         struct TConfiguration *pConfiguration, int *pnTMax)
1744         struct TData *pData;
1745         bool bFound = false;
1746         int nBlockType, nReg, nCoefficient;
1748         if (pTAS2557->mnPGID == TAS2557_PG_VERSION_2P1)
1749                 nReg = TAS2557_PG2P1_CALI_T_REG;
1750         else
1751                 nReg = TAS2557_PG1P0_CALI_T_REG;
1753         nBlockType = TAS2557_BLOCK_CFG_COEFF_DEV_A;
1755         pData = &(pConfiguration->mData);
1756         bFound = tas2557_get_coefficient_in_data(pTAS2557, pData, nBlockType, nReg, &nCoefficient);
1757         if (bFound)
1758                 *pnTMax = nCoefficient;
1760         return bFound;
1763 void tas2557_fw_ready(const struct firmware *pFW, void *pContext)
1765         struct tas2557_priv *pTAS2557 = (struct tas2557_priv *) pContext;
1766         int nResult;
1767         unsigned int nProgram = 0;
1768         unsigned int nSampleRate = 0;
1770 #ifdef CONFIG_TAS2557_CODEC
1771         mutex_lock(&pTAS2557->codec_lock);
1772 #endif
1774 #ifdef CONFIG_TAS2557_MISC
1775         mutex_lock(&pTAS2557->file_lock);
1776 #endif
1778         dev_info(pTAS2557->dev, "%s:\n", __func__);
1780         if (unlikely(!pFW) || unlikely(!pFW->data)) {
1781                 dev_err(pTAS2557->dev, "%s firmware is not loaded.\n",
1782                         TAS2557_FW_NAME);
1783                 goto end;
1784         }
1786         if (pTAS2557->mpFirmware->mpConfigurations) {
1787                 nProgram = pTAS2557->mnCurrentProgram;
1788                 nSampleRate = pTAS2557->mnCurrentSampleRate;
1789                 dev_dbg(pTAS2557->dev, "clear current firmware\n");
1790                 tas2557_clear_firmware(pTAS2557->mpFirmware);
1791         }
1793         nResult = fw_parse(pTAS2557, pTAS2557->mpFirmware, (unsigned char *)(pFW->data), pFW->size);
1794         release_firmware(pFW);
1795         if (nResult < 0) {
1796                 dev_err(pTAS2557->dev, "firmware is corrupt\n");
1797                 goto end;
1798         }
1800         if (!pTAS2557->mpFirmware->mnPrograms) {
1801                 dev_err(pTAS2557->dev, "firmware contains no programs\n");
1802                 nResult = -EINVAL;
1803                 goto end;
1804         }
1806         if (!pTAS2557->mpFirmware->mnConfigurations) {
1807                 dev_err(pTAS2557->dev, "firmware contains no configurations\n");
1808                 nResult = -EINVAL;
1809                 goto end;
1810         }
1812         if (nProgram >= pTAS2557->mpFirmware->mnPrograms) {
1813                 dev_info(pTAS2557->dev,
1814                         "no previous program, set to default\n");
1815                 nProgram = 0;
1816         }
1818         pTAS2557->mnCurrentSampleRate = nSampleRate;
1819         nResult = tas2557_set_program(pTAS2557, nProgram, -1);
1821 end:
1822         ;
1823 #ifdef CONFIG_TAS2557_CODEC
1824         mutex_unlock(&pTAS2557->codec_lock);
1825 #endif
1827 #ifdef CONFIG_TAS2557_MISC
1828         mutex_unlock(&pTAS2557->file_lock);
1829 #endif
1832 int tas2557_set_program(struct tas2557_priv *pTAS2557,
1833         unsigned int nProgram, int nConfig)
1835         struct TProgram *pProgram;
1836         unsigned int nConfiguration = 0;
1837         unsigned int nSampleRate = 0;
1838         unsigned char nGain;
1839         bool bFound = false;
1840         int nResult = 0;
1842         if ((!pTAS2557->mpFirmware->mpPrograms) ||
1843                 (!pTAS2557->mpFirmware->mpConfigurations)) {
1844                 dev_err(pTAS2557->dev, "Firmware not loaded\n");
1845                 nResult = 0;
1846                 goto end;
1847         }
1849         if (nProgram >= pTAS2557->mpFirmware->mnPrograms) {
1850                 dev_err(pTAS2557->dev, "TAS2557: Program %d doesn't exist\n",
1851                         nProgram);
1852                 nResult = 0;
1853                 goto end;
1854         }
1856         if (nConfig < 0) {
1857                 nConfiguration = 0;
1858                 nSampleRate = pTAS2557->mnCurrentSampleRate;
1859                 while (!bFound && (nConfiguration < pTAS2557->mpFirmware->mnConfigurations)) {
1860                         if (pTAS2557->mpFirmware->mpConfigurations[nConfiguration].mnProgram == nProgram) {
1861                                 if (nSampleRate == 0) {
1862                                         bFound = true;
1863                                         dev_info(pTAS2557->dev, "find default configuration %d\n", nConfiguration);
1864                                 } else if (nSampleRate == pTAS2557->mpFirmware->mpConfigurations[nConfiguration].mnSamplingRate) {
1865                                         bFound = true;
1866                                         dev_info(pTAS2557->dev, "find matching configuration %d\n", nConfiguration);
1867                                 } else {
1868                                         nConfiguration++;
1869                                 }
1870                         } else {
1871                                 nConfiguration++;
1872                         }
1873                 }
1874                 if (!bFound) {
1875                         dev_err(pTAS2557->dev,
1876                                 "Program %d, no valid configuration found for sample rate %d, ignore\n",
1877                                 nProgram, nSampleRate);
1878                         nResult = 0;
1879                         goto end;
1880                 }
1881         } else {
1882                 if (pTAS2557->mpFirmware->mpConfigurations[nConfig].mnProgram != nProgram) {
1883                         dev_err(pTAS2557->dev, "%s, configuration program doesn't match\n", __func__);
1884                         nResult = 0;
1885                         goto end;
1886                 }
1887                 nConfiguration = nConfig;
1888         }
1890         pProgram = &(pTAS2557->mpFirmware->mpPrograms[nProgram]);
1891         if (pTAS2557->mbPowerUp) {
1892                 dev_info(pTAS2557->dev,
1893                         "device powered up, power down to load program %d (%s)\n",
1894                         nProgram, pProgram->mpName);
1895                 if (hrtimer_active(&pTAS2557->mtimer))
1896                         hrtimer_cancel(&pTAS2557->mtimer);
1898                 if (pProgram->mnAppMode == TAS2557_APP_TUNINGMODE)
1899                         pTAS2557->enableIRQ(pTAS2557, false, false);
1901                 nResult = tas2557_dev_load_data(pTAS2557, p_tas2557_shutdown_data);
1902                 if (nResult < 0)
1903                         goto end;
1904         }
1906         pTAS2557->hw_reset(pTAS2557);
1907         nResult = pTAS2557->write(pTAS2557, TAS2557_SW_RESET_REG, 0x01);
1908         if (nResult < 0)
1909                 goto end;
1910         msleep(1);
1911         nResult = tas2557_load_default(pTAS2557);
1912         if (nResult < 0)
1913                 goto end;
1915         dev_info(pTAS2557->dev, "load program %d (%s)\n", nProgram, pProgram->mpName);
1916         nResult = tas2557_load_data(pTAS2557, &(pProgram->mData), TAS2557_BLOCK_PGM_DEV_A);
1917         if (nResult < 0)
1918                 goto end;
1919         pTAS2557->mnCurrentProgram = nProgram;
1921         nResult = tas2557_get_DAC_gain(pTAS2557, &nGain);
1922         if (nResult < 0)
1923                 goto end;
1924         pTAS2557->mnDevGain = nGain;
1925         pTAS2557->mnDevCurrentGain = nGain;
1927         nResult = tas2557_load_coefficient(pTAS2557, -1, nConfiguration, false);
1928         if (nResult < 0)
1929                 goto end;
1931         tas2557_update_edge(pTAS2557);
1933         if (pTAS2557->mbPowerUp) {
1934                 pTAS2557->clearIRQ(pTAS2557);
1935                 dev_dbg(pTAS2557->dev, "device powered up, load startup\n");
1936                 nResult = tas2557_dev_load_data(pTAS2557, p_tas2557_startup_data);
1937                 if (nResult < 0)
1938                         goto end;
1939                 if (pProgram->mnAppMode == TAS2557_APP_TUNINGMODE) {
1940                         nResult = tas2557_checkPLL(pTAS2557);
1941                         if (nResult < 0) {
1942                                 nResult = tas2557_dev_load_data(pTAS2557, p_tas2557_shutdown_data);
1943                                 pTAS2557->mbPowerUp = false;
1944                                 goto end;
1945                         }
1946                 }
1947                 dev_dbg(pTAS2557->dev, "device powered up, load unmute\n");
1948                 nResult = tas2557_dev_load_data(pTAS2557, p_tas2557_unmute_data);
1949                 if (nResult < 0)
1950                         goto end;
1952                 if (pProgram->mnAppMode == TAS2557_APP_TUNINGMODE) {
1953                         pTAS2557->enableIRQ(pTAS2557, true, true);
1954                         if (!hrtimer_active(&pTAS2557->mtimer)) {
1955                                 pTAS2557->mnDieTvReadCounter = 0;
1956                                 hrtimer_start(&pTAS2557->mtimer,
1957                                         ns_to_ktime((u64)LOW_TEMPERATURE_CHECK_PERIOD * NSEC_PER_MSEC), HRTIMER_MODE_REL);
1958                         }
1959                 }
1960         }
1962 end:
1964         if (nResult < 0) {
1965                 if (pTAS2557->mnErrCode & (ERROR_DEVA_I2C_COMM | ERROR_PRAM_CRCCHK | ERROR_YRAM_CRCCHK))
1966                         failsafe(pTAS2557);
1967         }
1968         return nResult;
1971 int tas2557_set_calibration(struct tas2557_priv *pTAS2557, int nCalibration)
1973         struct TCalibration *pCalibration = NULL;
1974         struct TConfiguration *pConfiguration;
1975         struct TProgram *pProgram;
1976         int nTmax = 0;
1977         bool bFound = false;
1978         int nResult = 0;
1980         if ((!pTAS2557->mpFirmware->mpPrograms)
1981                 || (!pTAS2557->mpFirmware->mpConfigurations)) {
1982                 dev_err(pTAS2557->dev, "Firmware not loaded\n\r");
1983                 nResult = 0;
1984                 goto end;
1985         }
1987         if (nCalibration == 0x00FF) {
1988                 nResult = tas2557_load_calibration(pTAS2557, TAS2557_CAL_NAME);
1989                 if (nResult < 0) {
1990                         dev_info(pTAS2557->dev, "load new calibration file %s fail %d\n",
1991                                 TAS2557_CAL_NAME, nResult);
1992                         goto end;
1993                 }
1994                 nCalibration = 0;
1995         }
1997         if (nCalibration >= pTAS2557->mpCalFirmware->mnCalibrations) {
1998                 dev_err(pTAS2557->dev,
1999                         "Calibration %d doesn't exist\n", nCalibration);
2000                 nResult = 0;
2001                 goto end;
2002         }
2004         pTAS2557->mnCurrentCalibration = nCalibration;
2005         if (pTAS2557->mbLoadConfigurationPrePowerUp)
2006                 goto end;
2008         pCalibration = &(pTAS2557->mpCalFirmware->mpCalibrations[nCalibration]);
2009         pProgram = &(pTAS2557->mpFirmware->mpPrograms[pTAS2557->mnCurrentProgram]);
2010         pConfiguration = &(pTAS2557->mpFirmware->mpConfigurations[pTAS2557->mnCurrentConfiguration]);
2011         if (pProgram->mnAppMode == TAS2557_APP_TUNINGMODE) {
2012                 if (pTAS2557->mbBypassTMax) {
2013                         bFound = tas2557_find_Tmax_in_configuration(pTAS2557, pConfiguration, &nTmax);
2014                         if (bFound && (nTmax == TAS2557_COEFFICIENT_TMAX)) {
2015                                 dev_dbg(pTAS2557->dev, "%s, config[%s] bypass load calibration\n",
2016                                         __func__, pConfiguration->mpName);
2017                                 goto end;
2018                         }
2019                 }
2021                 dev_dbg(pTAS2557->dev, "%s, load calibration\n", __func__);
2022                 nResult = tas2557_load_data(pTAS2557, &(pCalibration->mData), TAS2557_BLOCK_CFG_COEFF_DEV_A);
2023                 if (nResult < 0)
2024                         goto end;
2025         }
2027 end:
2028         if (nResult < 0) {
2029                 tas2557_clear_firmware(pTAS2557->mpCalFirmware);
2030                 nResult = tas2557_set_program(pTAS2557, pTAS2557->mnCurrentProgram, pTAS2557->mnCurrentConfiguration);
2031         }
2033         return nResult;
2036 bool tas2557_get_Cali_prm_r0(struct tas2557_priv *pTAS2557, int *prm_r0)
2038         struct TCalibration *pCalibration;
2039         struct TData *pData;
2040         int nReg;
2041         int nCali_Re;
2042         bool bFound = false;
2043         int nBlockType;
2045         if (!pTAS2557->mpCalFirmware->mnCalibrations) {
2046                 dev_err(pTAS2557->dev, "%s, no calibration data\n", __func__);
2047                 goto end;
2048         }
2050         if (pTAS2557->mnPGID == TAS2557_PG_VERSION_2P1)
2051                 nReg = TAS2557_PG2P1_CALI_R0_REG;
2052         else
2053                 nReg = TAS2557_PG1P0_CALI_R0_REG;
2055         nBlockType = TAS2557_BLOCK_CFG_COEFF_DEV_A;
2057         pCalibration = &(pTAS2557->mpCalFirmware->mpCalibrations[pTAS2557->mnCurrentCalibration]);
2058         pData = &(pCalibration->mData);
2060         bFound = tas2557_get_coefficient_in_data(pTAS2557, pData, nBlockType, nReg, &nCali_Re);
2062 end:
2064         if (bFound)
2065                 *prm_r0 = nCali_Re;
2067         return bFound;
2070 int tas2557_parse_dt(struct device *dev, struct tas2557_priv *pTAS2557)
2072         struct device_node *np = dev->of_node;
2073         int rc = 0, ret = 0;
2074         unsigned int value;
2076         pTAS2557->mnResetGPIO = of_get_named_gpio(np, "ti,cdc-reset-gpio", 0);
2077         if (!gpio_is_valid(pTAS2557->mnResetGPIO)) {
2078                 dev_err(pTAS2557->dev, "Looking up %s property in node %s failed %d\n",
2079                         "ti,cdc-reset-gpio", np->full_name,
2080                         pTAS2557->mnResetGPIO);
2081                 ret = -EINVAL;
2082                 goto end;
2083         } else
2084                 dev_dbg(pTAS2557->dev, "ti,cdc-reset-gpio=%d\n", pTAS2557->mnResetGPIO);
2086         pTAS2557->mnGpioINT = of_get_named_gpio(np, "ti,irq-gpio", 0);
2087         if (!gpio_is_valid(pTAS2557->mnGpioINT))
2088                 dev_err(pTAS2557->dev, "Looking up %s property in node %s failed %d\n",
2089                         "ti,irq-gpio", np->full_name,
2090                         pTAS2557->mnGpioINT);
2093         rc = of_property_read_u32(np, "ti,i2s-bits", &value);
2094         if (rc)
2095                 dev_err(pTAS2557->dev, "Looking up %s property in node %s failed %d\n",
2096                         "ti,i2s-bits", np->full_name, rc);
2097         else
2098                 pTAS2557->mnI2SBits = value;
2100         rc = of_property_read_u32(np, "ti,bypass-tmax", &value);
2101         if (rc)
2102                 dev_err(pTAS2557->dev, "Looking up %s property in node %s failed %d\n",
2103                         "ti,bypass-tmax", np->full_name, rc);
2104         else
2105                 pTAS2557->mbBypassTMax = (value > 0);
2107 end:
2109         return ret;
2112 MODULE_AUTHOR("Texas Instruments Inc.");
2113 MODULE_DESCRIPTION("TAS2557 common functions for Android Linux");
2114 MODULE_LICENSE("GPL v2");