Change Magic Number for kernel 4.19 support
[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         tas2557_get_die_temperature(pTAS2770, &nValue);
469         if(nValue == 0x80000000)
470         {
471                 dev_err(pTAS2557->dev, "%s, thermal sensor is wrong, mute output\n", __func__);
472                 goto end;
473         }
475         if ((pTAS2557->mpFirmware->mnPrograms == 0)
476                 || (pTAS2557->mpFirmware->mnConfigurations == 0)) {
477                 dev_err(pTAS2557->dev, "%s, firmware not loaded\n", __func__);
478                 goto end;
479         }
480         /* check safe guard*/
481         nResult = pTAS2557->read(pTAS2557, TAS2557_SAFE_GUARD_REG, &nValue);
482         if (nResult < 0)
483                 goto end;
484         if ((nValue&0xff) != TAS2557_SAFE_GUARD_PATTERN) {
485                 dev_err(pTAS2557->dev, "ERROR safe guard failure!\n");
486                 nResult = -EPIPE;
487                 pTAS2557->mnErrCode = ERROR_SAFE_GUARD;
488                 pTAS2557->mbPowerUp = true;
489                 goto end;
490         }
492         pProgram = &(pTAS2557->mpFirmware->mpPrograms[pTAS2557->mnCurrentProgram]);
493         if (bEnable) {
494                 if (!pTAS2557->mbPowerUp) {
495                         if (!pTAS2557->mbCalibrationLoaded) {
496                                 tas2557_set_calibration(pTAS2559, 0xFF);
497                                 pTAS2557->mbCalibrationLoaded = true;
498                         }
500                         if (pTAS2557->mbLoadConfigurationPrePowerUp) {
501                                 dev_dbg(pTAS2557->dev, "load coefficient before power\n");
502                                 pTAS2557->mbLoadConfigurationPrePowerUp = false;
503                                 nResult = tas2557_load_coefficient(pTAS2557,
504                                         pTAS2557->mnCurrentConfiguration, pTAS2557->mnNewConfiguration, false);
505                                 if (nResult < 0)
506                                         goto end;
507                         }
509                         pTAS2557->clearIRQ(pTAS2557);
510                         /* power on device */
511                         dev_dbg(pTAS2557->dev, "Enable: load startup sequence\n");
512                         nResult = tas2557_dev_load_data(pTAS2557, p_tas2557_startup_data);
513                         if (nResult < 0)
514                                 goto end;
515                         if (pProgram->mnAppMode == TAS2557_APP_TUNINGMODE) {
516                                 nResult = tas2557_checkPLL(pTAS2557);
517                                 if (nResult < 0) {
518                                         nResult = tas2557_dev_load_data(pTAS2557, p_tas2557_shutdown_data);
519                                         goto end;
520                                 }
521                         }
522                         dev_dbg(pTAS2557->dev, "Enable: load unmute sequence\n");
523                         nResult = tas2557_dev_load_data(pTAS2557, p_tas2557_unmute_data);
524                         if (nResult < 0)
525                                 goto end;
527                         if (pProgram->mnAppMode == TAS2557_APP_TUNINGMODE) {
528                                 /* turn on IRQ */
529                                 pTAS2557->enableIRQ(pTAS2557, true, true);
530                                 if (!hrtimer_active(&pTAS2557->mtimer)) {
531                                         pTAS2557->mnDieTvReadCounter = 0;
532                                         hrtimer_start(&pTAS2557->mtimer,
533                                                 ns_to_ktime((u64)LOW_TEMPERATURE_CHECK_PERIOD * NSEC_PER_MSEC), HRTIMER_MODE_REL);
534                                 }
535                         }
536                         pTAS2557->mbPowerUp = true;
537                         pTAS2557->mnRestart = 0;
538                 }
539         } else {
540                 if (pTAS2557->mbPowerUp) {
541                         if (hrtimer_active(&pTAS2557->mtimer))
542                                 hrtimer_cancel(&pTAS2557->mtimer);
544                         dev_dbg(pTAS2557->dev, "Enable: load shutdown sequence\n");
545                         if (pProgram->mnAppMode == TAS2557_APP_TUNINGMODE) {
546                                 /* turn off IRQ */
547                                 pTAS2557->enableIRQ(pTAS2557, false, false);
548                         }
549                         nResult = tas2557_dev_load_data(pTAS2557, p_tas2557_shutdown_data);
550                         if (nResult < 0)
551                                 goto end;
553                         pTAS2557->mbPowerUp = false;
554                         pTAS2557->mnRestart = 0;
555                 }
556         }
558         nResult = 0;
560 end:
561         if (nResult < 0) {
562                 if (pTAS2557->mnErrCode & (ERROR_DEVA_I2C_COMM | ERROR_PRAM_CRCCHK | ERROR_YRAM_CRCCHK | ERROR_SAFE_GUARD))
563                         failsafe(pTAS2557);
564         }
566         return nResult;
569 int tas2557_set_sampling_rate(struct tas2557_priv *pTAS2557, unsigned int nSamplingRate)
571         int nResult = 0;
572         struct TConfiguration *pConfiguration;
573         unsigned int nConfiguration;
575         dev_dbg(pTAS2557->dev, "tas2557_setup_clocks: nSamplingRate = %d [Hz]\n",
576                 nSamplingRate);
578         if ((!pTAS2557->mpFirmware->mpPrograms) ||
579                 (!pTAS2557->mpFirmware->mpConfigurations)) {
580                 dev_err(pTAS2557->dev, "Firmware not loaded\n");
581                 nResult = -EINVAL;
582                 goto end;
583         }
585         pConfiguration = &(pTAS2557->mpFirmware->mpConfigurations[pTAS2557->mnCurrentConfiguration]);
586         if (pConfiguration->mnSamplingRate == nSamplingRate) {
587                 dev_info(pTAS2557->dev, "Sampling rate for current configuration matches: %d\n",
588                         nSamplingRate);
589                 nResult = 0;
590                 goto end;
591         }
593         for (nConfiguration = 0;
594                 nConfiguration < pTAS2557->mpFirmware->mnConfigurations;
595                 nConfiguration++) {
596                 pConfiguration =
597                         &(pTAS2557->mpFirmware->mpConfigurations[nConfiguration]);
598                 if ((pConfiguration->mnSamplingRate == nSamplingRate)
599                         && (pConfiguration->mnProgram == pTAS2557->mnCurrentProgram)) {
600                         dev_info(pTAS2557->dev,
601                                 "Found configuration: %s, with compatible sampling rate %d\n",
602                                 pConfiguration->mpName, nSamplingRate);
603                         nResult = tas2557_load_configuration(pTAS2557, nConfiguration, false);
604                         goto end;
605                 }
606         }
608         dev_err(pTAS2557->dev, "Cannot find a configuration that supports sampling rate: %d\n",
609                 nSamplingRate);
611 end:
613         return nResult;
616 static void fw_print_header(struct tas2557_priv *pTAS2557, struct TFirmware *pFirmware)
618         dev_info(pTAS2557->dev, "FW Size       = %d", pFirmware->mnFWSize);
619         dev_info(pTAS2557->dev, "Checksum      = 0x%04X", pFirmware->mnChecksum);
620         dev_info(pTAS2557->dev, "PPC Version   = 0x%04X", pFirmware->mnPPCVersion);
621         dev_info(pTAS2557->dev, "FW  Version    = 0x%04X", pFirmware->mnFWVersion);
622         dev_info(pTAS2557->dev, "Driver Version= 0x%04X", pFirmware->mnDriverVersion);
623         dev_info(pTAS2557->dev, "Timestamp     = %d", pFirmware->mnTimeStamp);
624         dev_info(pTAS2557->dev, "DDC Name      = %s", pFirmware->mpDDCName);
625         dev_info(pTAS2557->dev, "Description   = %s", pFirmware->mpDescription);
628 inline unsigned int fw_convert_number(unsigned char *pData)
630         return pData[3] + (pData[2] << 8) + (pData[1] << 16) + (pData[0] << 24);
633 static int fw_parse_header(struct tas2557_priv *pTAS2557,
634         struct TFirmware *pFirmware, unsigned char *pData, unsigned int nSize)
636         unsigned char *pDataStart = pData;
637         unsigned int n;
638         unsigned char pMagicNumber[] = { 0x35, 0x35, 0x35, 0x32 };
640         if (nSize < 104) {
641                 dev_err(pTAS2557->dev, "Firmware: Header too short");
642                 return -EINVAL;
643         }
645         if (memcmp(pData, pMagicNumber, 4)) {
646                 dev_err(pTAS2557->dev, "Firmware: Magic number doesn't match");
647                 return -EINVAL;
648         }
649         pData += 4;
651         pFirmware->mnFWSize = fw_convert_number(pData);
652         pData += 4;
654         pFirmware->mnChecksum = fw_convert_number(pData);
655         pData += 4;
657         pFirmware->mnPPCVersion = fw_convert_number(pData);
658         pData += 4;
660         pFirmware->mnFWVersion = fw_convert_number(pData);
661         pData += 4;
663         pFirmware->mnDriverVersion = fw_convert_number(pData);
664         pData += 4;
666         pFirmware->mnTimeStamp = fw_convert_number(pData);
667         pData += 4;
669         memcpy(pFirmware->mpDDCName, pData, 64);
670         pData += 64;
672         n = strlen(pData);
673         pFirmware->mpDescription = kmemdup(pData, n + 1, GFP_KERNEL);
674         pData += n + 1;
675         if ((pData - pDataStart) >= nSize) {
676                 dev_err(pTAS2557->dev, "Firmware: Header too short after DDC description");
677                 return -EINVAL;
678         }
680         pFirmware->mnDeviceFamily = fw_convert_number(pData);
681         pData += 4;
682         if (pFirmware->mnDeviceFamily != 0) {
683                 dev_err(pTAS2557->dev,
684                         "deviceFamily %d, not TAS device", pFirmware->mnDeviceFamily);
685                 return -EINVAL;
686         }
688         pFirmware->mnDevice = fw_convert_number(pData);
689         pData += 4;
691         if (pFirmware->mnDevice != 2) {
692                 dev_err(pTAS2557->dev,
693                         "device %d, not TAS2557 Dual Mono", pFirmware->mnDevice);
694                 return -EINVAL;
695         }
697         fw_print_header(pTAS2557, pFirmware);
698         return pData - pDataStart;
701 static int fw_parse_block_data(struct tas2557_priv *pTAS2557, struct TFirmware *pFirmware,
702         struct TBlock *pBlock, unsigned char *pData)
704         unsigned char *pDataStart = pData;
705         unsigned int n;
707         pBlock->mnType = fw_convert_number(pData);
708         pData += 4;
710         if (pFirmware->mnDriverVersion >= PPC_DRIVER_CRCCHK) {
711                 pBlock->mbPChkSumPresent = pData[0];
712                 pData++;
714                 pBlock->mnPChkSum = pData[0];
715                 pData++;
717                 pBlock->mbYChkSumPresent = pData[0];
718                 pData++;
720                 pBlock->mnYChkSum = pData[0];
721                 pData++;
722         } else {
723                 pBlock->mbPChkSumPresent = 0;
724                 pBlock->mbYChkSumPresent = 0;
725         }
727         pBlock->mnCommands = fw_convert_number(pData);
728         pData += 4;
730         n = pBlock->mnCommands * 4;
731         pBlock->mpData = kmemdup(pData, n, GFP_KERNEL);
732         pData += n;
733         return pData - pDataStart;
736 static int fw_parse_data(struct tas2557_priv *pTAS2557, struct TFirmware *pFirmware,
737         struct TData *pImageData, unsigned char *pData)
739         unsigned char *pDataStart = pData;
740         unsigned int nBlock;
741         unsigned int n;
743         memcpy(pImageData->mpName, pData, 64);
744         pData += 64;
746         n = strlen(pData);
747         pImageData->mpDescription = kmemdup(pData, n + 1, GFP_KERNEL);
748         pData += n + 1;
750         pImageData->mnBlocks = (pData[0] << 8) + pData[1];
751         pData += 2;
753         pImageData->mpBlocks =
754                 kmalloc(sizeof(struct TBlock) * pImageData->mnBlocks, GFP_KERNEL);
756         for (nBlock = 0; nBlock < pImageData->mnBlocks; nBlock++) {
757                 n = fw_parse_block_data(pTAS2557, pFirmware,
758                         &(pImageData->mpBlocks[nBlock]), pData);
759                 pData += n;
760         }
761         return pData - pDataStart;
764 static int fw_parse_pll_data(struct tas2557_priv *pTAS2557,
765         struct TFirmware *pFirmware, unsigned char *pData)
767         unsigned char *pDataStart = pData;
768         unsigned int n;
769         unsigned int nPLL;
770         struct TPLL *pPLL;
772         pFirmware->mnPLLs = (pData[0] << 8) + pData[1];
773         pData += 2;
775         if (pFirmware->mnPLLs == 0)
776                 goto end;
778         pFirmware->mpPLLs = kmalloc_array(pFirmware->mnPLLs, sizeof(struct TPLL), GFP_KERNEL);
779         for (nPLL = 0; nPLL < pFirmware->mnPLLs; nPLL++) {
780                 pPLL = &(pFirmware->mpPLLs[nPLL]);
782                 memcpy(pPLL->mpName, pData, 64);
783                 pData += 64;
785                 n = strlen(pData);
786                 pPLL->mpDescription = kmemdup(pData, n + 1, GFP_KERNEL);
787                 pData += n + 1;
789                 n = fw_parse_block_data(pTAS2557, pFirmware, &(pPLL->mBlock), pData);
790                 pData += n;
791         }
793 end:
794         return pData - pDataStart;
797 static int fw_parse_program_data(struct tas2557_priv *pTAS2557,
798         struct TFirmware *pFirmware, unsigned char *pData)
800         unsigned char *pDataStart = pData;
801         unsigned int n;
802         unsigned int nProgram;
803         struct TProgram *pProgram;
805         pFirmware->mnPrograms = (pData[0] << 8) + pData[1];
806         pData += 2;
808         if (pFirmware->mnPrograms == 0)
809                 goto end;
811         pFirmware->mpPrograms =
812                 kmalloc(sizeof(struct TProgram) * pFirmware->mnPrograms, GFP_KERNEL);
813         for (nProgram = 0; nProgram < pFirmware->mnPrograms; nProgram++) {
814                 pProgram = &(pFirmware->mpPrograms[nProgram]);
815                 memcpy(pProgram->mpName, pData, 64);
816                 pData += 64;
818                 n = strlen(pData);
819                 pProgram->mpDescription = kmemdup(pData, n + 1, GFP_KERNEL);
820                 pData += n + 1;
822                 pProgram->mnAppMode = pData[0];
823                 pData++;
825                 pProgram->mnBoost = (pData[0] << 8) + pData[1];
826                 pData += 2;
828                 n = fw_parse_data(pTAS2557, pFirmware, &(pProgram->mData), pData);
829                 pData += n;
830         }
832 end:
834         return pData - pDataStart;
837 static int fw_parse_configuration_data(struct tas2557_priv *pTAS2557,
838         struct TFirmware *pFirmware, unsigned char *pData)
840         unsigned char *pDataStart = pData;
841         unsigned int n;
842         unsigned int nConfiguration;
843         struct TConfiguration *pConfiguration;
845         pFirmware->mnConfigurations = (pData[0] << 8) + pData[1];
846         pData += 2;
848         if (pFirmware->mnConfigurations == 0)
849                 goto end;
851         pFirmware->mpConfigurations =
852                 kmalloc(sizeof(struct TConfiguration) * pFirmware->mnConfigurations,
853                 GFP_KERNEL);
854         for (nConfiguration = 0; nConfiguration < pFirmware->mnConfigurations;
855                 nConfiguration++) {
856                 pConfiguration = &(pFirmware->mpConfigurations[nConfiguration]);
857                 memcpy(pConfiguration->mpName, pData, 64);
858                 pData += 64;
860                 n = strlen(pData);
861                 pConfiguration->mpDescription = kmemdup(pData, n + 1, GFP_KERNEL);
862                 pData += n + 1;
864                 if ((pFirmware->mnDriverVersion >= PPC_DRIVER_CONFDEV)
865                         || ((pFirmware->mnDriverVersion >= PPC_DRIVER_CFGDEV_NONCRC)
866                                 && (pFirmware->mnDriverVersion < PPC_DRIVER_CRCCHK))) {
867                         pConfiguration->mnDevices = (pData[0] << 8) + pData[1];
868                         pData += 2;
869                 } else
870                         pConfiguration->mnDevices = 1;
872                 pConfiguration->mnProgram = pData[0];
873                 pData++;
875                 pConfiguration->mnPLL = pData[0];
876                 pData++;
878                 pConfiguration->mnSamplingRate = fw_convert_number(pData);
879                 pData += 4;
881                 if (pFirmware->mnDriverVersion >= PPC_DRIVER_MTPLLSRC) {
882                         pConfiguration->mnPLLSrc = pData[0];
883                         pData++;
885                         pConfiguration->mnPLLSrcRate = fw_convert_number(pData);
886                         pData += 4;
887                 }
889                 n = fw_parse_data(pTAS2557, pFirmware, &(pConfiguration->mData), pData);
890                 pData += n;
891         }
893 end:
895         return pData - pDataStart;
898 int fw_parse_calibration_data(struct tas2557_priv *pTAS2557,
899         struct TFirmware *pFirmware, unsigned char *pData)
901         unsigned char *pDataStart = pData;
902         unsigned int n;
903         unsigned int nCalibration;
904         struct TCalibration *pCalibration;
906         pFirmware->mnCalibrations = (pData[0] << 8) + pData[1];
907         pData += 2;
909         if (pFirmware->mnCalibrations == 0)
910                 goto end;
912         pFirmware->mpCalibrations =
913                 kmalloc(sizeof(struct TCalibration) * pFirmware->mnCalibrations, GFP_KERNEL);
914         for (nCalibration = 0;
915                 nCalibration < pFirmware->mnCalibrations;
916                 nCalibration++) {
917                 pCalibration = &(pFirmware->mpCalibrations[nCalibration]);
918                 memcpy(pCalibration->mpName, pData, 64);
919                 pData += 64;
921                 n = strlen(pData);
922                 pCalibration->mpDescription = kmemdup(pData, n + 1, GFP_KERNEL);
923                 pData += n + 1;
925                 pCalibration->mnProgram = pData[0];
926                 pData++;
928                 pCalibration->mnConfiguration = pData[0];
929                 pData++;
931                 n = fw_parse_data(pTAS2557, pFirmware, &(pCalibration->mData), pData);
932                 pData += n;
933         }
935 end:
937         return pData - pDataStart;
940 static int fw_parse(struct tas2557_priv *pTAS2557,
941         struct TFirmware *pFirmware, unsigned char *pData, unsigned int nSize)
943         int nPosition = 0;
945         nPosition = fw_parse_header(pTAS2557, pFirmware, pData, nSize);
946         if (nPosition < 0) {
947                 dev_err(pTAS2557->dev, "Firmware: Wrong Header");
948                 return -EINVAL;
949         }
951         if (nPosition >= nSize) {
952                 dev_err(pTAS2557->dev, "Firmware: Too short");
953                 return -EINVAL;
954         }
956         pData += nPosition;
957         nSize -= nPosition;
958         nPosition = 0;
960         nPosition = fw_parse_pll_data(pTAS2557, pFirmware, pData);
962         pData += nPosition;
963         nSize -= nPosition;
964         nPosition = 0;
966         nPosition = fw_parse_program_data(pTAS2557, pFirmware, pData);
968         pData += nPosition;
969         nSize -= nPosition;
970         nPosition = 0;
972         nPosition = fw_parse_configuration_data(pTAS2557, pFirmware, pData);
974         pData += nPosition;
975         nSize -= nPosition;
976         nPosition = 0;
978         if (nSize > 64)
979                 nPosition = fw_parse_calibration_data(pTAS2557, pFirmware, pData);
980         return 0;
984 static const unsigned char crc8_lookup_table[CRC8_TABLE_SIZE] = {
985 0x00, 0x4D, 0x9A, 0xD7, 0x79, 0x34, 0xE3, 0xAE, 0xF2, 0xBF, 0x68, 0x25, 0x8B, 0xC6, 0x11, 0x5C,
986 0xA9, 0xE4, 0x33, 0x7E, 0xD0, 0x9D, 0x4A, 0x07, 0x5B, 0x16, 0xC1, 0x8C, 0x22, 0x6F, 0xB8, 0xF5,
987 0x1F, 0x52, 0x85, 0xC8, 0x66, 0x2B, 0xFC, 0xB1, 0xED, 0xA0, 0x77, 0x3A, 0x94, 0xD9, 0x0E, 0x43,
988 0xB6, 0xFB, 0x2C, 0x61, 0xCF, 0x82, 0x55, 0x18, 0x44, 0x09, 0xDE, 0x93, 0x3D, 0x70, 0xA7, 0xEA,
989 0x3E, 0x73, 0xA4, 0xE9, 0x47, 0x0A, 0xDD, 0x90, 0xCC, 0x81, 0x56, 0x1B, 0xB5, 0xF8, 0x2F, 0x62,
990 0x97, 0xDA, 0x0D, 0x40, 0xEE, 0xA3, 0x74, 0x39, 0x65, 0x28, 0xFF, 0xB2, 0x1C, 0x51, 0x86, 0xCB,
991 0x21, 0x6C, 0xBB, 0xF6, 0x58, 0x15, 0xC2, 0x8F, 0xD3, 0x9E, 0x49, 0x04, 0xAA, 0xE7, 0x30, 0x7D,
992 0x88, 0xC5, 0x12, 0x5F, 0xF1, 0xBC, 0x6B, 0x26, 0x7A, 0x37, 0xE0, 0xAD, 0x03, 0x4E, 0x99, 0xD4,
993 0x7C, 0x31, 0xE6, 0xAB, 0x05, 0x48, 0x9F, 0xD2, 0x8E, 0xC3, 0x14, 0x59, 0xF7, 0xBA, 0x6D, 0x20,
994 0xD5, 0x98, 0x4F, 0x02, 0xAC, 0xE1, 0x36, 0x7B, 0x27, 0x6A, 0xBD, 0xF0, 0x5E, 0x13, 0xC4, 0x89,
995 0x63, 0x2E, 0xF9, 0xB4, 0x1A, 0x57, 0x80, 0xCD, 0x91, 0xDC, 0x0B, 0x46, 0xE8, 0xA5, 0x72, 0x3F,
996 0xCA, 0x87, 0x50, 0x1D, 0xB3, 0xFE, 0x29, 0x64, 0x38, 0x75, 0xA2, 0xEF, 0x41, 0x0C, 0xDB, 0x96,
997 0x42, 0x0F, 0xD8, 0x95, 0x3B, 0x76, 0xA1, 0xEC, 0xB0, 0xFD, 0x2A, 0x67, 0xC9, 0x84, 0x53, 0x1E,
998 0xEB, 0xA6, 0x71, 0x3C, 0x92, 0xDF, 0x08, 0x45, 0x19, 0x54, 0x83, 0xCE, 0x60, 0x2D, 0xFA, 0xB7,
999 0x5D, 0x10, 0xC7, 0x8A, 0x24, 0x69, 0xBE, 0xF3, 0xAF, 0xE2, 0x35, 0x78, 0xD6, 0x9B, 0x4C, 0x01,
1000 0xF4, 0xB9, 0x6E, 0x23, 0x8D, 0xC0, 0x17, 0x5A, 0x06, 0x4B, 0x9C, 0xD1, 0x7F, 0x32, 0xE5, 0xA8
1001 };
1003 static int isInPageYRAM(struct tas2557_priv *pTAS2557, struct TYCRC *pCRCData,
1004         unsigned char nBook, unsigned char nPage, unsigned char nReg, unsigned char len)
1006         int nResult = 0;
1008         if (nBook == TAS2557_YRAM_BOOK1) {
1009                 if (nPage == TAS2557_YRAM1_PAGE) {
1010                         if (nReg >= TAS2557_YRAM1_START_REG) {
1011                                 pCRCData->mnOffset = nReg;
1012                                 pCRCData->mnLen = len;
1013                                 nResult = 1;
1014                         } else if ((nReg + len) > TAS2557_YRAM1_START_REG) {
1015                                 pCRCData->mnOffset = TAS2557_YRAM1_START_REG;
1016                                 pCRCData->mnLen = len - (TAS2557_YRAM1_START_REG - nReg);
1017                                 nResult = 1;
1018                         } else
1019                                 nResult = 0;
1020                 } else if (nPage == TAS2557_YRAM3_PAGE) {
1021                         if (nReg > TAS2557_YRAM3_END_REG) {
1022                                 nResult = 0;
1023                         } else if (nReg >= TAS2557_YRAM3_START_REG) {
1024                                 if ((nReg + len) > TAS2557_YRAM3_END_REG) {
1025                                         pCRCData->mnOffset = nReg;
1026                                         pCRCData->mnLen = TAS2557_YRAM3_END_REG - nReg + 1;
1027                                         nResult = 1;
1028                                 } else {
1029                                         pCRCData->mnOffset = nReg;
1030                                         pCRCData->mnLen = len;
1031                                         nResult = 1;
1032                                 }
1033                         } else {
1034                                 if ((nReg + (len - 1)) < TAS2557_YRAM3_START_REG)
1035                                         nResult = 0;
1036                                 else {
1037                                         pCRCData->mnOffset = TAS2557_YRAM3_START_REG;
1038                                         pCRCData->mnLen = len - (TAS2557_YRAM3_START_REG - nReg);
1039                                         nResult = 1;
1040                                 }
1041                         }
1042                 }
1043         } else if (nBook == TAS2557_YRAM_BOOK2) {
1044                 if (nPage == TAS2557_YRAM5_PAGE) {
1045                         if (nReg > TAS2557_YRAM5_END_REG) {
1046                                 nResult = 0;
1047                         } else if (nReg >= TAS2557_YRAM5_START_REG) {
1048                                 if ((nReg + len) > TAS2557_YRAM5_END_REG) {
1049                                         pCRCData->mnOffset = nReg;
1050                                         pCRCData->mnLen = TAS2557_YRAM5_END_REG - nReg + 1;
1051                                         nResult = 1;
1052                                 } else {
1053                                         pCRCData->mnOffset = nReg;
1054                                         pCRCData->mnLen = len;
1055                                         nResult = 1;
1056                                 }
1057                         } else {
1058                                 if ((nReg + (len - 1)) < TAS2557_YRAM5_START_REG)
1059                                         nResult = 0;
1060                                 else {
1061                                         pCRCData->mnOffset = TAS2557_YRAM5_START_REG;
1062                                         pCRCData->mnLen = len - (TAS2557_YRAM5_START_REG - nReg);
1063                                         nResult = 1;
1064                                 }
1065                         }
1066                 }
1067         } else
1068                 nResult = 0;
1070         return nResult;
1073 static int isInBlockYRAM(struct tas2557_priv *pTAS2557, struct TYCRC *pCRCData,
1074         unsigned char nBook, unsigned char nPage, unsigned char nReg, unsigned char len)
1076         int nResult;
1078         if (nBook == TAS2557_YRAM_BOOK1) {
1079                 if (nPage < TAS2557_YRAM2_START_PAGE)
1080                         nResult = 0;
1081                 else if (nPage <= TAS2557_YRAM2_END_PAGE) {
1082                         if (nReg > TAS2557_YRAM2_END_REG)
1083                                 nResult = 0;
1084                         else if (nReg >= TAS2557_YRAM2_START_REG) {
1085                                 pCRCData->mnOffset = nReg;
1086                                 pCRCData->mnLen = len;
1087                                 nResult = 1;
1088                         } else {
1089                                 if ((nReg + (len - 1)) < TAS2557_YRAM2_START_REG)
1090                                         nResult = 0;
1091                                 else {
1092                                         pCRCData->mnOffset = TAS2557_YRAM2_START_REG;
1093                                         pCRCData->mnLen = nReg + len - TAS2557_YRAM2_START_REG;
1094                                         nResult = 1;
1095                                 }
1096                         }
1097                 } else
1098                         nResult = 0;
1099         } else if (nBook == TAS2557_YRAM_BOOK2) {
1100                 if (nPage < TAS2557_YRAM4_START_PAGE)
1101                         nResult = 0;
1102                 else if (nPage <= TAS2557_YRAM4_END_PAGE) {
1103                         if (nReg > TAS2557_YRAM2_END_REG)
1104                                 nResult = 0;
1105                         else if (nReg >= TAS2557_YRAM2_START_REG) {
1106                                 pCRCData->mnOffset = nReg;
1107                                 pCRCData->mnLen = len;
1108                                 nResult = 1;
1109                         } else {
1110                                 if ((nReg + (len - 1)) < TAS2557_YRAM2_START_REG)
1111                                         nResult = 0;
1112                                 else {
1113                                         pCRCData->mnOffset = TAS2557_YRAM2_START_REG;
1114                                         pCRCData->mnLen = nReg + len - TAS2557_YRAM2_START_REG;
1115                                         nResult = 1;
1116                                 }
1117                         }
1118                 } else
1119                         nResult = 0;
1120         } else
1121                 nResult = 0;
1123         return nResult;
1127 static int isYRAM(struct tas2557_priv *pTAS2557, struct TYCRC *pCRCData,
1128         unsigned char nBook, unsigned char nPage, unsigned char nReg, unsigned char len)
1130         int nResult;
1132         nResult = isInPageYRAM(pTAS2557, pCRCData, nBook, nPage, nReg, len);
1134         if (nResult == 0)
1135                 nResult = isInBlockYRAM(pTAS2557, pCRCData, nBook, nPage, nReg, len);
1137         return nResult;
1140 /*
1141  * crc8 - calculate a crc8 over the given input data.
1142  *
1143  * table: crc table used for calculation.
1144  * pdata: pointer to data buffer.
1145  * nbytes: number of bytes in data buffer.
1146  * crc: previous returned crc8 value.
1147  */
1148 static u8 ti_crc8(const u8 table[CRC8_TABLE_SIZE], u8 *pdata, size_t nbytes, u8 crc)
1150         /* loop over the buffer data */
1151         while (nbytes-- > 0)
1152                 crc = table[(crc ^ *pdata++) & 0xff];
1154         return crc;
1157 static int doSingleRegCheckSum(struct tas2557_priv *pTAS2557, 
1158         unsigned char nBook, unsigned char nPage, unsigned char nReg, unsigned char nValue)
1160         int nResult = 0;
1161         struct TYCRC sCRCData;
1162         unsigned int nData1 = 0;
1164         if ((nBook == TAS2557_BOOK_ID(TAS2557_SA_COEFF_SWAP_REG))
1165                 && (nPage == TAS2557_PAGE_ID(TAS2557_SA_COEFF_SWAP_REG))
1166                 && (nReg >= TAS2557_PAGE_REG(TAS2557_SA_COEFF_SWAP_REG))
1167                 && (nReg <= (TAS2557_PAGE_REG(TAS2557_SA_COEFF_SWAP_REG) + 4))) {
1168                 /* DSP swap command, pass */
1169                 nResult = 0;
1170                 goto end;
1171         }
1173         nResult = isYRAM(pTAS2557, &sCRCData, nBook, nPage, nReg, 1);
1174         if (nResult == 1) {
1175                 nResult = pTAS2557->read(pTAS2557, TAS2557_REG(nBook, nPage, nReg), &nData1);
1176                 if (nResult < 0)
1177                         goto end;
1179                 if (nData1 != nValue) {
1180                         dev_err(pTAS2557->dev, "error2 (line %d),B[0x%x]P[0x%x]R[0x%x] W[0x%x], R[0x%x]\n",
1181                                 __LINE__, nBook, nPage, nReg, nValue, nData1);
1182                         nResult = -EAGAIN;
1183                         goto end;
1184                 }
1186                 nResult = ti_crc8(crc8_lookup_table, &nValue, 1, 0);
1187         }
1189 end:
1191         return nResult;
1194 static int doMultiRegCheckSum(struct tas2557_priv *pTAS2557, 
1195         unsigned char nBook, unsigned char nPage, unsigned char nReg, unsigned int len)
1197         int nResult = 0, i;
1198         unsigned char nCRCChkSum = 0;
1199         unsigned char nBuf1[128];
1200         struct TYCRC TCRCData;
1202         if ((nReg + len-1) > 127) {
1203                 nResult = -EINVAL;
1204                 dev_err(pTAS2557->dev, "firmware error\n");
1205                 goto end;
1206         }
1208         if ((nBook == TAS2557_BOOK_ID(TAS2557_SA_COEFF_SWAP_REG))
1209                 && (nPage == TAS2557_PAGE_ID(TAS2557_SA_COEFF_SWAP_REG))
1210                 && (nReg == TAS2557_PAGE_REG(TAS2557_SA_COEFF_SWAP_REG))
1211                 && (len == 4)) {
1212                 /* DSP swap command, pass */
1213                 nResult = 0;
1214                 goto end;
1215         }
1217         nResult = isYRAM(pTAS2557, &TCRCData, nBook, nPage, nReg, len);
1218         if (nResult == 1) {
1219                 if (len == 1) {
1220                         dev_err(pTAS2557->dev, "firmware error\n");
1221                         nResult = -EINVAL;
1222                         goto end;
1223                 } else {
1224                         nResult = pTAS2557->bulk_read(pTAS2557, TAS2557_REG(nBook, nPage, TCRCData.mnOffset), nBuf1, TCRCData.mnLen);
1225                         if (nResult < 0)
1226                                 goto end;
1228                         for (i = 0; i < TCRCData.mnLen; i++) {
1229                                 if ((nBook == TAS2557_BOOK_ID(TAS2557_SA_COEFF_SWAP_REG))
1230                                         && (nPage == TAS2557_PAGE_ID(TAS2557_SA_COEFF_SWAP_REG))
1231                                         && ((i + TCRCData.mnOffset)
1232                                                 >= TAS2557_PAGE_REG(TAS2557_SA_COEFF_SWAP_REG))
1233                                         && ((i + TCRCData.mnOffset)
1234                                                 <= (TAS2557_PAGE_REG(TAS2557_SA_COEFF_SWAP_REG) + 4))) {
1235                                         /* DSP swap command, bypass */
1236                                         continue;
1237                                 } else
1238                                         nCRCChkSum += ti_crc8(crc8_lookup_table, &nBuf1[i], 1, 0);
1239                         }
1241                         nResult = nCRCChkSum;
1242                 }
1243         }
1245 end:
1247         return nResult;
1250 static int tas2557_load_block(struct tas2557_priv *pTAS2557, struct TBlock *pBlock)
1252         int nResult = 0;
1253         unsigned int nCommand = 0;
1254         unsigned char nBook;
1255         unsigned char nPage;
1256         unsigned char nOffset;
1257         unsigned char nData;
1258         unsigned int nLength;
1259         unsigned int nSleep;
1260         unsigned char nCRCChkSum = 0;
1261         unsigned int nValue1;
1262         int nRetry = 6;
1263         unsigned char *pData = pBlock->mpData;
1265         dev_dbg(pTAS2557->dev, "TAS2557 load block: Type = %d, commands = %d\n",
1266                 pBlock->mnType, pBlock->mnCommands);
1267 start:
1268         if (pBlock->mbPChkSumPresent) {
1269                 nResult = pTAS2557->write(pTAS2557, TAS2557_CRC_RESET_REG, 1);
1270                 if (nResult < 0)
1271                         goto end;
1272         }
1274         if (pBlock->mbYChkSumPresent)
1275                 nCRCChkSum = 0;
1277         nCommand = 0;
1279         while (nCommand < pBlock->mnCommands) {
1280                 pData = pBlock->mpData + nCommand * 4;
1282                 nBook = pData[0];
1283                 nPage = pData[1];
1284                 nOffset = pData[2];
1285                 nData = pData[3];
1287                 nCommand++;
1289                 if (nOffset <= 0x7F) {
1290                         nResult = pTAS2557->write(pTAS2557, TAS2557_REG(nBook, nPage, nOffset), nData);
1291                         if (nResult < 0)
1292                                 goto end;
1293                         if (pBlock->mbYChkSumPresent) {
1294                                 nResult = doSingleRegCheckSum(pTAS2557, nBook, nPage, nOffset, nData);
1295                                 if (nResult < 0)
1296                                         goto check;
1297                                 nCRCChkSum += (unsigned char)nResult;
1298                         }
1299                 } else if (nOffset == 0x81) {
1300                         nSleep = (nBook << 8) + nPage;
1301                         msleep(nSleep);
1302                 } else if (nOffset == 0x85) {
1303                         pData += 4;
1304                         nLength = (nBook << 8) + nPage;
1305                         nBook = pData[0];
1306                         nPage = pData[1];
1307                         nOffset = pData[2];
1308                         if (nLength > 1) {
1309                                 nResult = pTAS2557->bulk_write(pTAS2557, TAS2557_REG(nBook, nPage, nOffset), pData + 3, nLength);
1310                                 if (nResult < 0)
1311                                         goto end;
1312                                 if (pBlock->mbYChkSumPresent) {
1313                                         nResult = doMultiRegCheckSum(pTAS2557, nBook, nPage, nOffset, nLength);
1314                                         if (nResult < 0)
1315                                                 goto check;
1316                                         nCRCChkSum += (unsigned char)nResult;
1317                                 }
1318                         } else {
1319                                 nResult = pTAS2557->write(pTAS2557, TAS2557_REG(nBook, nPage, nOffset), pData[3]);
1320                                 if (nResult < 0)
1321                                         goto end;
1322                                 if (pBlock->mbYChkSumPresent) {
1323                                         nResult = doSingleRegCheckSum(pTAS2557, nBook, nPage, nOffset, pData[3]);
1324                                         if (nResult < 0)
1325                                                 goto check;
1326                                         nCRCChkSum += (unsigned char)nResult;
1327                                 }
1328                         }
1330                         nCommand++;
1332                         if (nLength >= 2)
1333                                 nCommand += ((nLength - 2) / 4) + 1;
1334                 }
1335         }
1336         if (pBlock->mbPChkSumPresent) {
1337                 nResult = pTAS2557->read(pTAS2557, TAS2557_CRC_CHECKSUM_REG, &nValue1);
1338                 if (nResult < 0)
1339                         goto end;
1340                 if ((nValue1&0xff) != pBlock->mnPChkSum) {
1341                         dev_err(pTAS2557->dev, "Block PChkSum Error: FW = 0x%x, Reg = 0x%x\n",
1342                                 pBlock->mnPChkSum, (nValue1&0xff));
1343                         nResult = -EAGAIN;
1344                                 pTAS2557->mnErrCode |= ERROR_PRAM_CRCCHK;
1345                         goto check;
1346                 }
1348                 nResult = 0;
1349                 pTAS2557->mnErrCode &= ~ERROR_PRAM_CRCCHK;
1350                 dev_dbg(pTAS2557->dev, "Block[0x%x] PChkSum match\n", pBlock->mnType);
1351         }
1353         if (pBlock->mbYChkSumPresent) {
1354                 if (nCRCChkSum != pBlock->mnYChkSum) {
1355                         dev_err(pTAS2557->dev, "Block YChkSum Error: FW = 0x%x, YCRC = 0x%x\n",
1356                                 pBlock->mnYChkSum, nCRCChkSum);
1357                         nResult = -EAGAIN;
1358                         pTAS2557->mnErrCode |= ERROR_YRAM_CRCCHK;
1359                         goto check;
1360                 }
1361                 pTAS2557->mnErrCode &= ~ERROR_YRAM_CRCCHK;
1362                 nResult = 0;
1363                 dev_dbg(pTAS2557->dev, "Block[0x%x] YChkSum match\n", pBlock->mnType);
1364         }
1366 check:
1367         if (nResult == -EAGAIN) {
1368                 nRetry--;
1369                 if (nRetry > 0)
1370                         goto start;
1371         }
1373 end:
1374         if (nResult < 0) {
1375                 dev_err(pTAS2557->dev, "Block (%d) load error\n",
1376                                 pBlock->mnType);
1377         }
1378         return nResult;
1381 static int tas2557_load_data(struct tas2557_priv *pTAS2557, struct TData *pData, unsigned int nType)
1383         int nResult = 0;
1384         unsigned int nBlock;
1385         struct TBlock *pBlock;
1387         dev_dbg(pTAS2557->dev,
1388                 "TAS2557 load data: %s, Blocks = %d, Block Type = %d\n", pData->mpName, pData->mnBlocks, nType);
1390         for (nBlock = 0; nBlock < pData->mnBlocks; nBlock++) {
1391                 pBlock = &(pData->mpBlocks[nBlock]);
1392                 if (pBlock->mnType == nType) {
1393                         nResult = tas2557_load_block(pTAS2557, pBlock);
1394                         if (nResult < 0)
1395                                 break;
1396                 }
1397         }
1399         return nResult;
1402 static int tas2557_load_configuration(struct tas2557_priv *pTAS2557,
1403         unsigned int nConfiguration, bool bLoadSame)
1405         int nResult = 0;
1406         struct TConfiguration *pCurrentConfiguration = NULL;
1407         struct TConfiguration *pNewConfiguration = NULL;
1409         dev_dbg(pTAS2557->dev, "%s: %d\n", __func__, nConfiguration);
1411         if ((!pTAS2557->mpFirmware->mpPrograms) ||
1412                 (!pTAS2557->mpFirmware->mpConfigurations)) {
1413                 dev_err(pTAS2557->dev, "Firmware not loaded\n");
1414                 nResult = 0;
1415                 goto end;
1416         }
1418         if (nConfiguration >= pTAS2557->mpFirmware->mnConfigurations) {
1419                 dev_err(pTAS2557->dev, "Configuration %d doesn't exist\n",
1420                         nConfiguration);
1421                 nResult = 0;
1422                 goto end;
1423         }
1425         if ((!pTAS2557->mbLoadConfigurationPrePowerUp)
1426                 && (nConfiguration == pTAS2557->mnCurrentConfiguration)
1427                 && (!bLoadSame)) {
1428                 dev_info(pTAS2557->dev, "Configuration %d is already loaded\n",
1429                         nConfiguration);
1430                 nResult = 0;
1431                 goto end;
1432         }
1434         pCurrentConfiguration =
1435                 &(pTAS2557->mpFirmware->mpConfigurations[pTAS2557->mnCurrentConfiguration]);
1436         pNewConfiguration =
1437                 &(pTAS2557->mpFirmware->mpConfigurations[nConfiguration]);
1438         if (pNewConfiguration->mnProgram != pCurrentConfiguration->mnProgram) {
1439                 dev_err(pTAS2557->dev, "Configuration %d, %s doesn't share the same program as current %d\n",
1440                         nConfiguration, pNewConfiguration->mpName, pCurrentConfiguration->mnProgram);
1441                 nResult = 0;
1442                 goto end;
1443         }
1445         if (pNewConfiguration->mnPLL >= pTAS2557->mpFirmware->mnPLLs) {
1446                 dev_err(pTAS2557->dev, "Configuration %d, %s doesn't have a valid PLL index %d\n",
1447                         nConfiguration, pNewConfiguration->mpName, pNewConfiguration->mnPLL);
1448                 nResult = 0;
1449                 goto end;
1450         }
1452         if (pTAS2557->mbPowerUp) {
1453                 pTAS2557->mbLoadConfigurationPrePowerUp = false;
1454                 nResult = tas2557_load_coefficient(pTAS2557, pTAS2557->mnCurrentConfiguration, nConfiguration, true);
1455         } else {
1456                 dev_dbg(pTAS2557->dev,
1457                         "TAS2557 was powered down, will load coefficient when power up\n");
1458                 pTAS2557->mbLoadConfigurationPrePowerUp = true;
1459                 pTAS2557->mnNewConfiguration = nConfiguration;
1460         }
1462 end:
1464         if (nResult < 0) {
1465                 if (pTAS2557->mnErrCode & (ERROR_DEVA_I2C_COMM | ERROR_PRAM_CRCCHK | ERROR_YRAM_CRCCHK))
1466                         failsafe(pTAS2557);
1467         }
1469         return nResult;
1472 int tas2557_set_config(struct tas2557_priv *pTAS2557, int config)
1474         struct TConfiguration *pConfiguration;
1475         struct TProgram *pProgram;
1476         unsigned int nProgram = pTAS2557->mnCurrentProgram;
1477         unsigned int nConfiguration = config;
1478         int nResult = 0;
1480         if ((!pTAS2557->mpFirmware->mpPrograms) ||
1481                 (!pTAS2557->mpFirmware->mpConfigurations)) {
1482                 dev_err(pTAS2557->dev, "Firmware not loaded\n");
1483                 nResult = -EINVAL;
1484                 goto end;
1485         }
1487         if (nConfiguration >= pTAS2557->mpFirmware->mnConfigurations) {
1488                 dev_err(pTAS2557->dev, "Configuration %d doesn't exist\n",
1489                         nConfiguration);
1490                 nResult = -EINVAL;
1491                 goto end;
1492         }
1494         pConfiguration = &(pTAS2557->mpFirmware->mpConfigurations[nConfiguration]);
1495         pProgram = &(pTAS2557->mpFirmware->mpPrograms[nProgram]);
1497         if (nProgram != pConfiguration->mnProgram) {
1498                 dev_err(pTAS2557->dev,
1499                         "Configuration %d, %s with Program %d isn't compatible with existing Program %d, %s\n",
1500                         nConfiguration, pConfiguration->mpName, pConfiguration->mnProgram,
1501                         nProgram, pProgram->mpName);
1502                 nResult = -EINVAL;
1503                 goto end;
1504         }
1506         nResult = tas2557_load_configuration(pTAS2557, nConfiguration, false);
1508 end:
1510         return nResult;
1513 void tas2557_clear_firmware(struct TFirmware *pFirmware)
1515         unsigned int n, nn;
1517         if (!pFirmware)
1518                 return;
1520         kfree(pFirmware->mpDescription);
1522         if (pFirmware->mpPLLs != NULL) {
1523                 for (n = 0; n < pFirmware->mnPLLs; n++) {
1524                         kfree(pFirmware->mpPLLs[n].mpDescription);
1525                         kfree(pFirmware->mpPLLs[n].mBlock.mpData);
1526                 }
1527                 kfree(pFirmware->mpPLLs);
1528         }
1530         if (pFirmware->mpPrograms != NULL) {
1531                 for (n = 0; n < pFirmware->mnPrograms; n++) {
1532                         kfree(pFirmware->mpPrograms[n].mpDescription);
1533                         kfree(pFirmware->mpPrograms[n].mData.mpDescription);
1534                         for (nn = 0; nn < pFirmware->mpPrograms[n].mData.mnBlocks; nn++)
1535                                 kfree(pFirmware->mpPrograms[n].mData.mpBlocks[nn].mpData);
1536                         kfree(pFirmware->mpPrograms[n].mData.mpBlocks);
1537                 }
1538                 kfree(pFirmware->mpPrograms);
1539         }
1541         if (pFirmware->mpConfigurations != NULL) {
1542                 for (n = 0; n < pFirmware->mnConfigurations; n++) {
1543                         kfree(pFirmware->mpConfigurations[n].mpDescription);
1544                         kfree(pFirmware->mpConfigurations[n].mData.mpDescription);
1545                         for (nn = 0; nn < pFirmware->mpConfigurations[n].mData.mnBlocks; nn++)
1546                                 kfree(pFirmware->mpConfigurations[n].mData.mpBlocks[nn].mpData);
1547                         kfree(pFirmware->mpConfigurations[n].mData.mpBlocks);
1548                 }
1549                 kfree(pFirmware->mpConfigurations);
1550         }
1552         if (pFirmware->mpCalibrations != NULL) {
1553                 for (n = 0; n < pFirmware->mnCalibrations; n++) {
1554                         kfree(pFirmware->mpCalibrations[n].mpDescription);
1555                         kfree(pFirmware->mpCalibrations[n].mData.mpDescription);
1556                         for (nn = 0; nn < pFirmware->mpCalibrations[n].mData.mnBlocks; nn++)
1557                                 kfree(pFirmware->mpCalibrations[n].mData.mpBlocks[nn].mpData);
1558                         kfree(pFirmware->mpCalibrations[n].mData.mpBlocks);
1559                 }
1560                 kfree(pFirmware->mpCalibrations);
1561         }
1563         memset(pFirmware, 0x00, sizeof(struct TFirmware));
1566 static int tas2557_load_calibration(struct tas2557_priv *pTAS2557,      char *pFileName)
1568         int nResult = 0;
1570         int nFile;
1571         mm_segment_t fs;
1572         unsigned char pBuffer[1000];
1573         int nSize = 0;
1575         dev_dbg(pTAS2557->dev, "%s:\n", __func__);
1577         fs = get_fs();
1578         set_fs(KERNEL_DS);
1579         nFile = sys_open(pFileName, O_RDONLY, 0);
1581         dev_info(pTAS2557->dev, "TAS2557 calibration file = %s, handle = %d\n",
1582                 pFileName, nFile);
1584         if (nFile >= 0) {
1585                 nSize = sys_read(nFile, pBuffer, 1000);
1586                 sys_close(nFile);
1587         } else {
1588                 dev_err(pTAS2557->dev, "TAS2557 cannot open calibration file: %s\n",
1589                         pFileName);
1590         }
1592         set_fs(fs);
1594         if (!nSize)
1595                 goto end;
1597         tas2557_clear_firmware(pTAS2557->mpCalFirmware);
1598         dev_info(pTAS2557->dev, "TAS2557 calibration file size = %d\n", nSize);
1599         nResult = fw_parse(pTAS2557, pTAS2557->mpCalFirmware, pBuffer, nSize);
1601         if (nResult)
1602                 dev_err(pTAS2557->dev, "TAS2557 calibration file is corrupt\n");
1603         else
1604                 dev_info(pTAS2557->dev, "TAS2557 calibration: %d calibrations\n",
1605                         pTAS2557->mpCalFirmware->mnCalibrations);
1606 end:
1608         return nResult;
1611 static bool tas2557_get_coefficient_in_block(struct tas2557_priv *pTAS2557,
1612         struct TBlock *pBlock, int nReg, int *pnValue)
1614         int nCoefficient = 0;
1615         bool bFound = false;
1616         unsigned char *pCommands;
1617         int nBook, nPage, nOffset, len;
1618         int i, n;
1620         pCommands = pBlock->mpData;
1621         for (i = 0 ; i < pBlock->mnCommands;) {
1622                 nBook = pCommands[4 * i + 0];
1623                 nPage = pCommands[4 * i + 1];
1624                 nOffset = pCommands[4 * i + 2];
1625                 if ((nOffset < 0x7f) || (nOffset == 0x81))
1626                         i++;
1627                 else if (nOffset == 0x85) {
1628                         len = ((int)nBook << 8) | nPage;
1629                         nBook = pCommands[4 * i + 4];
1630                         nPage = pCommands[4 * i + 5];
1631                         nOffset = pCommands[4 * i + 6];
1632                         n = 4 * i + 7;
1633                         i += 2;
1634                         i += ((len - 1) / 4);
1635                         if ((len - 1) % 4)
1636                                 i++;
1637                         if ((nBook != TAS2557_BOOK_ID(nReg))
1638                                 || (nPage != TAS2557_PAGE_ID(nReg)))
1639                                 continue;
1640                         if (nOffset > TAS2557_PAGE_REG(nReg))
1641                                 continue;
1642                         if ((len + nOffset) >= (TAS2557_PAGE_REG(nReg) + 4)) {
1643                                 n += (TAS2557_PAGE_REG(nReg) - nOffset);
1644                                 nCoefficient = ((int)pCommands[n] << 24)
1645                                                 | ((int)pCommands[n + 1] << 16)
1646                                                 | ((int)pCommands[n + 2] << 8)
1647                                                 | (int)pCommands[n + 3];
1648                                 bFound = true;
1649                                 break;
1650                         }
1651                 } else {
1652                         dev_err(pTAS2557->dev, "%s, format error %d\n", __func__, nOffset);
1653                         break;
1654                 }
1655         }
1657         if (bFound) {
1658                 *pnValue = nCoefficient;
1659                 dev_dbg(pTAS2557->dev, "%s, B[0x%x]P[0x%x]R[0x%x]=0x%x\n", __func__,
1660                         TAS2557_BOOK_ID(nReg), TAS2557_PAGE_ID(nReg), TAS2557_PAGE_REG(nReg),
1661                         nCoefficient);
1662         }
1664         return bFound;
1667 static bool tas2557_get_coefficient_in_data(struct tas2557_priv *pTAS2557,
1668         struct TData *pData, int blockType, int nReg, int *pnValue)
1670         bool bFound = false;
1671         struct TBlock *pBlock;
1672         int i;
1674         for (i = 0; i < pData->mnBlocks; i++) {
1675                 pBlock = &(pData->mpBlocks[i]);
1676                 if (pBlock->mnType == blockType) {
1677                         bFound = tas2557_get_coefficient_in_block(pTAS2557,
1678                                                 pBlock, nReg, pnValue);
1679                         if (bFound)
1680                                 break;
1681                 }
1682         }
1684         return bFound;
1687 static bool tas2557_find_Tmax_in_configuration(struct tas2557_priv *pTAS2557,
1688         struct TConfiguration *pConfiguration, int *pnTMax)
1690         struct TData *pData;
1691         bool bFound = false;
1692         int nBlockType, nReg, nCoefficient;
1694         if (pTAS2557->mnPGID == TAS2557_PG_VERSION_2P1)
1695                 nReg = TAS2557_PG2P1_CALI_T_REG;
1696         else
1697                 nReg = TAS2557_PG1P0_CALI_T_REG;
1699         nBlockType = TAS2557_BLOCK_CFG_COEFF_DEV_A;
1701         pData = &(pConfiguration->mData);
1702         bFound = tas2557_get_coefficient_in_data(pTAS2557, pData, nBlockType, nReg, &nCoefficient);
1703         if (bFound)
1704                 *pnTMax = nCoefficient;
1706         return bFound;
1709 void tas2557_fw_ready(const struct firmware *pFW, void *pContext)
1711         struct tas2557_priv *pTAS2557 = (struct tas2557_priv *) pContext;
1712         int nResult;
1713         unsigned int nProgram = 0;
1714         unsigned int nSampleRate = 0;
1716 #ifdef CONFIG_TAS2557_CODEC
1717         mutex_lock(&pTAS2557->codec_lock);
1718 #endif
1720 #ifdef CONFIG_TAS2557_MISC
1721         mutex_lock(&pTAS2557->file_lock);
1722 #endif
1724         dev_info(pTAS2557->dev, "%s:\n", __func__);
1726         if (unlikely(!pFW) || unlikely(!pFW->data)) {
1727                 dev_err(pTAS2557->dev, "%s firmware is not loaded.\n",
1728                         TAS2557_FW_NAME);
1729                 goto end;
1730         }
1732         if (pTAS2557->mpFirmware->mpConfigurations) {
1733                 nProgram = pTAS2557->mnCurrentProgram;
1734                 nSampleRate = pTAS2557->mnCurrentSampleRate;
1735                 dev_dbg(pTAS2557->dev, "clear current firmware\n");
1736                 tas2557_clear_firmware(pTAS2557->mpFirmware);
1737         }
1739         nResult = fw_parse(pTAS2557, pTAS2557->mpFirmware, (unsigned char *)(pFW->data), pFW->size);
1740         release_firmware(pFW);
1741         if (nResult < 0) {
1742                 dev_err(pTAS2557->dev, "firmware is corrupt\n");
1743                 goto end;
1744         }
1746         if (!pTAS2557->mpFirmware->mnPrograms) {
1747                 dev_err(pTAS2557->dev, "firmware contains no programs\n");
1748                 nResult = -EINVAL;
1749                 goto end;
1750         }
1752         if (!pTAS2557->mpFirmware->mnConfigurations) {
1753                 dev_err(pTAS2557->dev, "firmware contains no configurations\n");
1754                 nResult = -EINVAL;
1755                 goto end;
1756         }
1758         if (nProgram >= pTAS2557->mpFirmware->mnPrograms) {
1759                 dev_info(pTAS2557->dev,
1760                         "no previous program, set to default\n");
1761                 nProgram = 0;
1762         }
1764         pTAS2557->mnCurrentSampleRate = nSampleRate;
1765         nResult = tas2557_set_program(pTAS2557, nProgram, -1);
1767 end:
1769 #ifdef CONFIG_TAS2557_CODEC
1770         mutex_unlock(&pTAS2557->codec_lock);
1771 #endif
1773 #ifdef CONFIG_TAS2557_MISC
1774         mutex_unlock(&pTAS2557->file_lock);
1775 #endif
1778 int tas2557_set_program(struct tas2557_priv *pTAS2557,
1779         unsigned int nProgram, int nConfig)
1781         struct TProgram *pProgram;
1782         unsigned int nConfiguration = 0;
1783         unsigned int nSampleRate = 0;
1784         unsigned char nGain;
1785         bool bFound = false;
1786         int nResult = 0;
1788         if ((!pTAS2557->mpFirmware->mpPrograms) ||
1789                 (!pTAS2557->mpFirmware->mpConfigurations)) {
1790                 dev_err(pTAS2557->dev, "Firmware not loaded\n");
1791                 nResult = 0;
1792                 goto end;
1793         }
1795         if (nProgram >= pTAS2557->mpFirmware->mnPrograms) {
1796                 dev_err(pTAS2557->dev, "TAS2557: Program %d doesn't exist\n",
1797                         nProgram);
1798                 nResult = 0;
1799                 goto end;
1800         }
1802         if (nConfig < 0) {
1803                 nConfiguration = 0;
1804                 nSampleRate = pTAS2557->mnCurrentSampleRate;
1805                 while (!bFound && (nConfiguration < pTAS2557->mpFirmware->mnConfigurations)) {
1806                         if (pTAS2557->mpFirmware->mpConfigurations[nConfiguration].mnProgram == nProgram) {
1807                                 if (nSampleRate == 0) {
1808                                         bFound = true;
1809                                         dev_info(pTAS2557->dev, "find default configuration %d\n", nConfiguration);
1810                                 } else if (nSampleRate == pTAS2557->mpFirmware->mpConfigurations[nConfiguration].mnSamplingRate) {
1811                                         bFound = true;
1812                                         dev_info(pTAS2557->dev, "find matching configuration %d\n", nConfiguration);
1813                                 } else {
1814                                         nConfiguration++;
1815                                 }
1816                         } else {
1817                                 nConfiguration++;
1818                         }
1819                 }
1820                 if (!bFound) {
1821                         dev_err(pTAS2557->dev,
1822                                 "Program %d, no valid configuration found for sample rate %d, ignore\n",
1823                                 nProgram, nSampleRate);
1824                         nResult = 0;
1825                         goto end;
1826                 }
1827         } else {
1828                 if (pTAS2557->mpFirmware->mpConfigurations[nConfig].mnProgram != nProgram) {
1829                         dev_err(pTAS2557->dev, "%s, configuration program doesn't match\n", __func__);
1830                         nResult = 0;
1831                         goto end;
1832                 }
1833                 nConfiguration = nConfig;
1834         }
1836         pProgram = &(pTAS2557->mpFirmware->mpPrograms[nProgram]);
1837         if (pTAS2557->mbPowerUp) {
1838                 dev_info(pTAS2557->dev,
1839                         "device powered up, power down to load program %d (%s)\n",
1840                         nProgram, pProgram->mpName);
1841                 if (hrtimer_active(&pTAS2557->mtimer))
1842                         hrtimer_cancel(&pTAS2557->mtimer);
1844                 if (pProgram->mnAppMode == TAS2557_APP_TUNINGMODE)
1845                         pTAS2557->enableIRQ(pTAS2557, false, false);
1847                 nResult = tas2557_dev_load_data(pTAS2557, p_tas2557_shutdown_data);
1848                 if (nResult < 0)
1849                         goto end;
1850         }
1852         pTAS2557->hw_reset(pTAS2557);
1853         nResult = pTAS2557->write(pTAS2557, TAS2557_SW_RESET_REG, 0x01);
1854         if (nResult < 0)
1855                 goto end;
1856         msleep(1);
1857         nResult = tas2557_load_default(pTAS2557);
1858         if (nResult < 0)
1859                 goto end;
1861         dev_info(pTAS2557->dev, "load program %d (%s)\n", nProgram, pProgram->mpName);
1862         nResult = tas2557_load_data(pTAS2557, &(pProgram->mData), TAS2557_BLOCK_PGM_DEV_A);
1863         if (nResult < 0)
1864                 goto end;
1865         pTAS2557->mnCurrentProgram = nProgram;
1867         nResult = tas2557_get_DAC_gain(pTAS2557, &nGain);
1868         if (nResult < 0)
1869                 goto end;
1870         pTAS2557->mnDevGain = nGain;
1871         pTAS2557->mnDevCurrentGain = nGain;
1873         nResult = tas2557_load_coefficient(pTAS2557, -1, nConfiguration, false);
1874         if (nResult < 0)
1875                 goto end;
1877         tas2557_update_edge(pTAS2557);
1879         if (pTAS2557->mbPowerUp) {
1880                 pTAS2557->clearIRQ(pTAS2557);
1881                 dev_dbg(pTAS2557->dev, "device powered up, load startup\n");
1882                 nResult = tas2557_dev_load_data(pTAS2557, p_tas2557_startup_data);
1883                 if (nResult < 0)
1884                         goto end;
1885                 if (pProgram->mnAppMode == TAS2557_APP_TUNINGMODE) {
1886                         nResult = tas2557_checkPLL(pTAS2557);
1887                         if (nResult < 0) {
1888                                 nResult = tas2557_dev_load_data(pTAS2557, p_tas2557_shutdown_data);
1889                                 pTAS2557->mbPowerUp = false;
1890                                 goto end;
1891                         }
1892                 }
1893                 dev_dbg(pTAS2557->dev, "device powered up, load unmute\n");
1894                 nResult = tas2557_dev_load_data(pTAS2557, p_tas2557_unmute_data);
1895                 if (nResult < 0)
1896                         goto end;
1898                 if (pProgram->mnAppMode == TAS2557_APP_TUNINGMODE) {
1899                         pTAS2557->enableIRQ(pTAS2557, true, true);
1900                         if (!hrtimer_active(&pTAS2557->mtimer)) {
1901                                 pTAS2557->mnDieTvReadCounter = 0;
1902                                 hrtimer_start(&pTAS2557->mtimer,
1903                                         ns_to_ktime((u64)LOW_TEMPERATURE_CHECK_PERIOD * NSEC_PER_MSEC), HRTIMER_MODE_REL);
1904                         }
1905                 }
1906         }
1908 end:
1910         if (nResult < 0) {
1911                 if (pTAS2557->mnErrCode & (ERROR_DEVA_I2C_COMM | ERROR_PRAM_CRCCHK | ERROR_YRAM_CRCCHK))
1912                         failsafe(pTAS2557);
1913         }
1914         return nResult;
1917 int tas2557_set_calibration(struct tas2557_priv *pTAS2557, int nCalibration)
1919         struct TCalibration *pCalibration = NULL;
1920         struct TConfiguration *pConfiguration;
1921         struct TProgram *pProgram;
1922         int nTmax = 0;
1923         bool bFound = false;
1924         int nResult = 0;
1926         if ((!pTAS2557->mpFirmware->mpPrograms)
1927                 || (!pTAS2557->mpFirmware->mpConfigurations)) {
1928                 dev_err(pTAS2557->dev, "Firmware not loaded\n\r");
1929                 nResult = 0;
1930                 goto end;
1931         }
1933         if (nCalibration == 0x00FF) {
1934                 nResult = tas2557_load_calibration(pTAS2557, TAS2557_CAL_NAME);
1935                 if (nResult < 0) {
1936                         dev_info(pTAS2557->dev, "load new calibration file %s fail %d\n",
1937                                 TAS2557_CAL_NAME, nResult);
1938                         goto end;
1939                 }
1940                 nCalibration = 0;
1941         }
1943         if (nCalibration >= pTAS2557->mpCalFirmware->mnCalibrations) {
1944                 dev_err(pTAS2557->dev,
1945                         "Calibration %d doesn't exist\n", nCalibration);
1946                 nResult = 0;
1947                 goto end;
1948         }
1950         pTAS2557->mnCurrentCalibration = nCalibration;
1951         if (pTAS2557->mbLoadConfigurationPrePowerUp)
1952                 goto end;
1954         pCalibration = &(pTAS2557->mpCalFirmware->mpCalibrations[nCalibration]);
1955         pProgram = &(pTAS2557->mpFirmware->mpPrograms[pTAS2557->mnCurrentProgram]);
1956         pConfiguration = &(pTAS2557->mpFirmware->mpConfigurations[pTAS2557->mnCurrentConfiguration]);
1957         if (pProgram->mnAppMode == TAS2557_APP_TUNINGMODE) {
1958                 if (pTAS2557->mbBypassTMax) {
1959                         bFound = tas2557_find_Tmax_in_configuration(pTAS2557, pConfiguration, &nTmax);
1960                         if (bFound && (nTmax == TAS2557_COEFFICIENT_TMAX)) {
1961                                 dev_dbg(pTAS2557->dev, "%s, config[%s] bypass load calibration\n",
1962                                         __func__, pConfiguration->mpName);
1963                                 goto end;
1964                         }
1965                 }
1967                 dev_dbg(pTAS2557->dev, "%s, load calibration\n", __func__);
1968                 nResult = tas2557_load_data(pTAS2557, &(pCalibration->mData), TAS2557_BLOCK_CFG_COEFF_DEV_A);
1969                 if (nResult < 0)
1970                         goto end;
1971         }
1973 end:
1974         if (nResult < 0) {
1975                 tas2557_clear_firmware(pTAS2557->mpCalFirmware);
1976                 nResult = tas2557_set_program(pTAS2557, pTAS2557->mnCurrentProgram, pTAS2557->mnCurrentConfiguration);
1977         }
1979         return nResult;
1982 bool tas2557_get_Cali_prm_r0(struct tas2557_priv *pTAS2557, int *prm_r0)
1984         struct TCalibration *pCalibration;
1985         struct TData *pData;
1986         int nReg;
1987         int nCali_Re;
1988         bool bFound = false;
1989         int nBlockType;
1991         if (!pTAS2557->mpCalFirmware->mnCalibrations) {
1992                 dev_err(pTAS2557->dev, "%s, no calibration data\n", __func__);
1993                 goto end;
1994         }
1996         if (pTAS2557->mnPGID == TAS2557_PG_VERSION_2P1)
1997                 nReg = TAS2557_PG2P1_CALI_R0_REG;
1998         else
1999                 nReg = TAS2557_PG1P0_CALI_R0_REG;
2001         nBlockType = TAS2557_BLOCK_CFG_COEFF_DEV_A;
2003         pCalibration = &(pTAS2557->mpCalFirmware->mpCalibrations[pTAS2557->mnCurrentCalibration]);
2004         pData = &(pCalibration->mData);
2006         bFound = tas2557_get_coefficient_in_data(pTAS2557, pData, nBlockType, nReg, &nCali_Re);
2008 end:
2010         if (bFound)
2011                 *prm_r0 = nCali_Re;
2013         return bFound;
2016 int tas2557_parse_dt(struct device *dev, struct tas2557_priv *pTAS2557)
2018         struct device_node *np = dev->of_node;
2019         int rc = 0, ret = 0;
2020         unsigned int value;
2022         pTAS2557->mnResetGPIO = of_get_named_gpio(np, "ti,cdc-reset-gpio", 0);
2023         if (!gpio_is_valid(pTAS2557->mnResetGPIO)) {
2024                 dev_err(pTAS2557->dev, "Looking up %s property in node %s failed %d\n",
2025                         "ti,cdc-reset-gpio", np->full_name,
2026                         pTAS2557->mnResetGPIO);
2027                 ret = -EINVAL;
2028                 goto end;
2029         } else
2030                 dev_dbg(pTAS2557->dev, "ti,cdc-reset-gpio=%d\n", pTAS2557->mnResetGPIO);
2032         pTAS2557->mnGpioINT = of_get_named_gpio(np, "ti,irq-gpio", 0);
2033         if (!gpio_is_valid(pTAS2557->mnGpioINT))
2034                 dev_err(pTAS2557->dev, "Looking up %s property in node %s failed %d\n",
2035                         "ti,irq-gpio", np->full_name,
2036                         pTAS2557->mnGpioINT);
2039         rc = of_property_read_u32(np, "ti,i2s-bits", &value);
2040         if (rc)
2041                 dev_err(pTAS2557->dev, "Looking up %s property in node %s failed %d\n",
2042                         "ti,i2s-bits", np->full_name, rc);
2043         else
2044                 pTAS2557->mnI2SBits = value;
2046         rc = of_property_read_u32(np, "ti,bypass-tmax", &value);
2047         if (rc)
2048                 dev_err(pTAS2557->dev, "Looking up %s property in node %s failed %d\n",
2049                         "ti,bypass-tmax", np->full_name, rc);
2050         else
2051                 pTAS2557->mbBypassTMax = (value > 0);
2053 end:
2055         return ret;
2058 MODULE_AUTHOR("Texas Instruments Inc.");
2059 MODULE_DESCRIPTION("TAS2557 common functions for Android Linux");
2060 MODULE_LICENSE("GPL v2");