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)
129 {
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;
148 }
150 int tas2557_configIRQ(struct tas2557_priv *pTAS2557)
151 {
152 return tas2557_dev_load_data(pTAS2557, p_tas2557_irq_config);
153 }
155 int tas2557_set_bit_rate(struct tas2557_priv *pTAS2557, unsigned int nBitRate)
156 {
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;
179 }
181 int tas2557_get_bit_rate(struct tas2557_priv *pTAS2557, unsigned char *pBitRate)
182 {
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;
202 }
204 int tas2557_get_DAC_gain(struct tas2557_priv *pTAS2557, unsigned char *pnGain)
205 {
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;
214 }
216 int tas2557_set_DAC_gain(struct tas2557_priv *pTAS2557, unsigned int nGain)
217 {
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;
223 }
225 /*
226 * die temperature calculation:
227 * DieTemp = readout / 2^23
228 */
229 int tas2557_get_die_temperature(struct tas2557_priv *pTAS2557, int *pTemperature)
230 {
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;
254 }
256 int tas2557_load_platdata(struct tas2557_priv *pTAS2557)
257 {
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;
271 }
273 int tas2557_load_default(struct tas2557_priv *pTAS2557)
274 {
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;
290 }
292 static void failsafe(struct tas2557_priv *pTAS2557)
293 {
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);
316 }
318 int tas2557_checkPLL(struct tas2557_priv *pTAS2557)
319 {
320 int nResult = 0;
321 /*
322 * TO DO
323 */
325 return nResult;
326 }
328 /*
329 * tas2557_load_coefficient
330 */
331 static int tas2557_load_coefficient(struct tas2557_priv *pTAS2557,
332 int nPrevConfig, int nNewConfig, bool bPowerOn)
333 {
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 return nResult;
445 }
447 int tas2557_enable(struct tas2557_priv *pTAS2557, bool bEnable)
448 {
449 int nResult = 0;
450 unsigned int nValue;
451 struct TProgram *pProgram;
453 dev_dbg(pTAS2557->dev, "Enable: %d\n", bEnable);
455 tas2557_get_die_temperature(pTAS2770, &nValue);
456 if(nValue == 0x80000000)
457 {
458 dev_err(pTAS2557->dev, "%s, thermal sensor is wrong, mute output\n", __func__);
459 goto end;
460 }
462 if ((pTAS2557->mpFirmware->mnPrograms == 0)
463 || (pTAS2557->mpFirmware->mnConfigurations == 0)) {
464 dev_err(pTAS2557->dev, "%s, firmware not loaded\n", __func__);
465 goto end;
466 }
467 /* check safe guard*/
468 nResult = pTAS2557->read(pTAS2557, TAS2557_SAFE_GUARD_REG, &nValue);
469 if (nResult < 0)
470 goto end;
471 if ((nValue&0xff) != TAS2557_SAFE_GUARD_PATTERN) {
472 dev_err(pTAS2557->dev, "ERROR safe guard failure!\n");
473 nResult = -EPIPE;
474 pTAS2557->mnErrCode = ERROR_SAFE_GUARD;
475 pTAS2557->mbPowerUp = true;
476 goto end;
477 }
479 pProgram = &(pTAS2557->mpFirmware->mpPrograms[pTAS2557->mnCurrentProgram]);
480 if (bEnable) {
481 if (!pTAS2557->mbPowerUp) {
482 if (pTAS2557->mbLoadConfigurationPrePowerUp) {
483 dev_dbg(pTAS2557->dev, "load coefficient before power\n");
484 pTAS2557->mbLoadConfigurationPrePowerUp = false;
485 nResult = tas2557_load_coefficient(pTAS2557,
486 pTAS2557->mnCurrentConfiguration, pTAS2557->mnNewConfiguration, false);
487 if (nResult < 0)
488 goto end;
489 }
491 pTAS2557->clearIRQ(pTAS2557);
492 /* power on device */
493 dev_dbg(pTAS2557->dev, "Enable: load startup sequence\n");
494 nResult = tas2557_dev_load_data(pTAS2557, p_tas2557_startup_data);
495 if (nResult < 0)
496 goto end;
497 if (pProgram->mnAppMode == TAS2557_APP_TUNINGMODE) {
498 nResult = tas2557_checkPLL(pTAS2557);
499 if (nResult < 0) {
500 nResult = tas2557_dev_load_data(pTAS2557, p_tas2557_shutdown_data);
501 goto end;
502 }
503 }
504 dev_dbg(pTAS2557->dev, "Enable: load unmute sequence\n");
505 nResult = tas2557_dev_load_data(pTAS2557, p_tas2557_unmute_data);
506 if (nResult < 0)
507 goto end;
509 if (pProgram->mnAppMode == TAS2557_APP_TUNINGMODE) {
510 /* turn on IRQ */
511 pTAS2557->enableIRQ(pTAS2557, true, true);
512 if (!hrtimer_active(&pTAS2557->mtimer)) {
513 pTAS2557->mnDieTvReadCounter = 0;
514 hrtimer_start(&pTAS2557->mtimer,
515 ns_to_ktime((u64)LOW_TEMPERATURE_CHECK_PERIOD * NSEC_PER_MSEC), HRTIMER_MODE_REL);
516 }
517 }
518 pTAS2557->mbPowerUp = true;
519 pTAS2557->mnRestart = 0;
520 }
521 } else {
522 if (pTAS2557->mbPowerUp) {
523 if (hrtimer_active(&pTAS2557->mtimer))
524 hrtimer_cancel(&pTAS2557->mtimer);
526 dev_dbg(pTAS2557->dev, "Enable: load shutdown sequence\n");
527 if (pProgram->mnAppMode == TAS2557_APP_TUNINGMODE) {
528 /* turn off IRQ */
529 pTAS2557->enableIRQ(pTAS2557, false, false);
530 }
531 nResult = tas2557_dev_load_data(pTAS2557, p_tas2557_shutdown_data);
532 if (nResult < 0)
533 goto end;
535 pTAS2557->mbPowerUp = false;
536 pTAS2557->mnRestart = 0;
537 }
538 }
540 nResult = 0;
542 end:
543 if (nResult < 0) {
544 if (pTAS2557->mnErrCode & (ERROR_DEVA_I2C_COMM | ERROR_PRAM_CRCCHK | ERROR_YRAM_CRCCHK | ERROR_SAFE_GUARD))
545 failsafe(pTAS2557);
546 }
548 return nResult;
549 }
551 int tas2557_set_sampling_rate(struct tas2557_priv *pTAS2557, unsigned int nSamplingRate)
552 {
553 int nResult = 0;
554 struct TConfiguration *pConfiguration;
555 unsigned int nConfiguration;
557 dev_dbg(pTAS2557->dev, "tas2557_setup_clocks: nSamplingRate = %d [Hz]\n",
558 nSamplingRate);
560 if ((!pTAS2557->mpFirmware->mpPrograms) ||
561 (!pTAS2557->mpFirmware->mpConfigurations)) {
562 dev_err(pTAS2557->dev, "Firmware not loaded\n");
563 nResult = -EINVAL;
564 goto end;
565 }
567 pConfiguration = &(pTAS2557->mpFirmware->mpConfigurations[pTAS2557->mnCurrentConfiguration]);
568 if (pConfiguration->mnSamplingRate == nSamplingRate) {
569 dev_info(pTAS2557->dev, "Sampling rate for current configuration matches: %d\n",
570 nSamplingRate);
571 nResult = 0;
572 goto end;
573 }
575 for (nConfiguration = 0;
576 nConfiguration < pTAS2557->mpFirmware->mnConfigurations;
577 nConfiguration++) {
578 pConfiguration =
579 &(pTAS2557->mpFirmware->mpConfigurations[nConfiguration]);
580 if ((pConfiguration->mnSamplingRate == nSamplingRate)
581 && (pConfiguration->mnProgram == pTAS2557->mnCurrentProgram)) {
582 dev_info(pTAS2557->dev,
583 "Found configuration: %s, with compatible sampling rate %d\n",
584 pConfiguration->mpName, nSamplingRate);
585 nResult = tas2557_load_configuration(pTAS2557, nConfiguration, false);
586 goto end;
587 }
588 }
590 dev_err(pTAS2557->dev, "Cannot find a configuration that supports sampling rate: %d\n",
591 nSamplingRate);
593 end:
595 return nResult;
596 }
598 static void fw_print_header(struct tas2557_priv *pTAS2557, struct TFirmware *pFirmware)
599 {
600 dev_info(pTAS2557->dev, "FW Size = %d", pFirmware->mnFWSize);
601 dev_info(pTAS2557->dev, "Checksum = 0x%04X", pFirmware->mnChecksum);
602 dev_info(pTAS2557->dev, "PPC Version = 0x%04X", pFirmware->mnPPCVersion);
603 dev_info(pTAS2557->dev, "FW Version = 0x%04X", pFirmware->mnFWVersion);
604 dev_info(pTAS2557->dev, "Driver Version= 0x%04X", pFirmware->mnDriverVersion);
605 dev_info(pTAS2557->dev, "Timestamp = %d", pFirmware->mnTimeStamp);
606 dev_info(pTAS2557->dev, "DDC Name = %s", pFirmware->mpDDCName);
607 dev_info(pTAS2557->dev, "Description = %s", pFirmware->mpDescription);
608 }
610 inline unsigned int fw_convert_number(unsigned char *pData)
611 {
612 return pData[3] + (pData[2] << 8) + (pData[1] << 16) + (pData[0] << 24);
613 }
615 static int fw_parse_header(struct tas2557_priv *pTAS2557,
616 struct TFirmware *pFirmware, unsigned char *pData, unsigned int nSize)
617 {
618 unsigned char *pDataStart = pData;
619 unsigned int n;
620 unsigned char pMagicNumber[] = { 0x35, 0x35, 0x35, 0x32 };
622 if (nSize < 104) {
623 dev_err(pTAS2557->dev, "Firmware: Header too short");
624 return -EINVAL;
625 }
627 if (memcmp(pData, pMagicNumber, 4)) {
628 dev_err(pTAS2557->dev, "Firmware: Magic number doesn't match");
629 return -EINVAL;
630 }
631 pData += 4;
633 pFirmware->mnFWSize = fw_convert_number(pData);
634 pData += 4;
636 pFirmware->mnChecksum = fw_convert_number(pData);
637 pData += 4;
639 pFirmware->mnPPCVersion = fw_convert_number(pData);
640 pData += 4;
642 pFirmware->mnFWVersion = fw_convert_number(pData);
643 pData += 4;
645 pFirmware->mnDriverVersion = fw_convert_number(pData);
646 pData += 4;
648 pFirmware->mnTimeStamp = fw_convert_number(pData);
649 pData += 4;
651 memcpy(pFirmware->mpDDCName, pData, 64);
652 pData += 64;
654 n = strlen(pData);
655 pFirmware->mpDescription = kmemdup(pData, n + 1, GFP_KERNEL);
656 pData += n + 1;
657 if ((pData - pDataStart) >= nSize) {
658 dev_err(pTAS2557->dev, "Firmware: Header too short after DDC description");
659 return -EINVAL;
660 }
662 pFirmware->mnDeviceFamily = fw_convert_number(pData);
663 pData += 4;
664 if (pFirmware->mnDeviceFamily != 0) {
665 dev_err(pTAS2557->dev,
666 "deviceFamily %d, not TAS device", pFirmware->mnDeviceFamily);
667 return -EINVAL;
668 }
670 pFirmware->mnDevice = fw_convert_number(pData);
671 pData += 4;
673 if (pFirmware->mnDevice != 2) {
674 dev_err(pTAS2557->dev,
675 "device %d, not TAS2557 Dual Mono", pFirmware->mnDevice);
676 return -EINVAL;
677 }
679 fw_print_header(pTAS2557, pFirmware);
680 return pData - pDataStart;
681 }
683 static int fw_parse_block_data(struct tas2557_priv *pTAS2557, struct TFirmware *pFirmware,
684 struct TBlock *pBlock, unsigned char *pData)
685 {
686 unsigned char *pDataStart = pData;
687 unsigned int n;
689 pBlock->mnType = fw_convert_number(pData);
690 pData += 4;
692 if (pFirmware->mnDriverVersion >= PPC_DRIVER_CRCCHK) {
693 pBlock->mbPChkSumPresent = pData[0];
694 pData++;
696 pBlock->mnPChkSum = pData[0];
697 pData++;
699 pBlock->mbYChkSumPresent = pData[0];
700 pData++;
702 pBlock->mnYChkSum = pData[0];
703 pData++;
704 } else {
705 pBlock->mbPChkSumPresent = 0;
706 pBlock->mbYChkSumPresent = 0;
707 }
709 pBlock->mnCommands = fw_convert_number(pData);
710 pData += 4;
712 n = pBlock->mnCommands * 4;
713 pBlock->mpData = kmemdup(pData, n, GFP_KERNEL);
714 pData += n;
715 return pData - pDataStart;
716 }
718 static int fw_parse_data(struct tas2557_priv *pTAS2557, struct TFirmware *pFirmware,
719 struct TData *pImageData, unsigned char *pData)
720 {
721 unsigned char *pDataStart = pData;
722 unsigned int nBlock;
723 unsigned int n;
725 memcpy(pImageData->mpName, pData, 64);
726 pData += 64;
728 n = strlen(pData);
729 pImageData->mpDescription = kmemdup(pData, n + 1, GFP_KERNEL);
730 pData += n + 1;
732 pImageData->mnBlocks = (pData[0] << 8) + pData[1];
733 pData += 2;
735 pImageData->mpBlocks =
736 kmalloc(sizeof(struct TBlock) * pImageData->mnBlocks, GFP_KERNEL);
738 for (nBlock = 0; nBlock < pImageData->mnBlocks; nBlock++) {
739 n = fw_parse_block_data(pTAS2557, pFirmware,
740 &(pImageData->mpBlocks[nBlock]), pData);
741 pData += n;
742 }
743 return pData - pDataStart;
744 }
746 static int fw_parse_pll_data(struct tas2557_priv *pTAS2557,
747 struct TFirmware *pFirmware, unsigned char *pData)
748 {
749 unsigned char *pDataStart = pData;
750 unsigned int n;
751 unsigned int nPLL;
752 struct TPLL *pPLL;
754 pFirmware->mnPLLs = (pData[0] << 8) + pData[1];
755 pData += 2;
757 if (pFirmware->mnPLLs == 0)
758 goto end;
760 pFirmware->mpPLLs = kmalloc_array(pFirmware->mnPLLs, sizeof(struct TPLL), GFP_KERNEL);
761 for (nPLL = 0; nPLL < pFirmware->mnPLLs; nPLL++) {
762 pPLL = &(pFirmware->mpPLLs[nPLL]);
764 memcpy(pPLL->mpName, pData, 64);
765 pData += 64;
767 n = strlen(pData);
768 pPLL->mpDescription = kmemdup(pData, n + 1, GFP_KERNEL);
769 pData += n + 1;
771 n = fw_parse_block_data(pTAS2557, pFirmware, &(pPLL->mBlock), pData);
772 pData += n;
773 }
775 end:
776 return pData - pDataStart;
777 }
779 static int fw_parse_program_data(struct tas2557_priv *pTAS2557,
780 struct TFirmware *pFirmware, unsigned char *pData)
781 {
782 unsigned char *pDataStart = pData;
783 unsigned int n;
784 unsigned int nProgram;
785 struct TProgram *pProgram;
787 pFirmware->mnPrograms = (pData[0] << 8) + pData[1];
788 pData += 2;
790 if (pFirmware->mnPrograms == 0)
791 goto end;
793 pFirmware->mpPrograms =
794 kmalloc(sizeof(struct TProgram) * pFirmware->mnPrograms, GFP_KERNEL);
795 for (nProgram = 0; nProgram < pFirmware->mnPrograms; nProgram++) {
796 pProgram = &(pFirmware->mpPrograms[nProgram]);
797 memcpy(pProgram->mpName, pData, 64);
798 pData += 64;
800 n = strlen(pData);
801 pProgram->mpDescription = kmemdup(pData, n + 1, GFP_KERNEL);
802 pData += n + 1;
804 pProgram->mnAppMode = pData[0];
805 pData++;
807 pProgram->mnBoost = (pData[0] << 8) + pData[1];
808 pData += 2;
810 n = fw_parse_data(pTAS2557, pFirmware, &(pProgram->mData), pData);
811 pData += n;
812 }
814 end:
816 return pData - pDataStart;
817 }
819 static int fw_parse_configuration_data(struct tas2557_priv *pTAS2557,
820 struct TFirmware *pFirmware, unsigned char *pData)
821 {
822 unsigned char *pDataStart = pData;
823 unsigned int n;
824 unsigned int nConfiguration;
825 struct TConfiguration *pConfiguration;
827 pFirmware->mnConfigurations = (pData[0] << 8) + pData[1];
828 pData += 2;
830 if (pFirmware->mnConfigurations == 0)
831 goto end;
833 pFirmware->mpConfigurations =
834 kmalloc(sizeof(struct TConfiguration) * pFirmware->mnConfigurations,
835 GFP_KERNEL);
836 for (nConfiguration = 0; nConfiguration < pFirmware->mnConfigurations;
837 nConfiguration++) {
838 pConfiguration = &(pFirmware->mpConfigurations[nConfiguration]);
839 memcpy(pConfiguration->mpName, pData, 64);
840 pData += 64;
842 n = strlen(pData);
843 pConfiguration->mpDescription = kmemdup(pData, n + 1, GFP_KERNEL);
844 pData += n + 1;
846 if ((pFirmware->mnDriverVersion >= PPC_DRIVER_CONFDEV)
847 || ((pFirmware->mnDriverVersion >= PPC_DRIVER_CFGDEV_NONCRC)
848 && (pFirmware->mnDriverVersion < PPC_DRIVER_CRCCHK))) {
849 pConfiguration->mnDevices = (pData[0] << 8) + pData[1];
850 pData += 2;
851 } else
852 pConfiguration->mnDevices = 1;
854 pConfiguration->mnProgram = pData[0];
855 pData++;
857 pConfiguration->mnPLL = pData[0];
858 pData++;
860 pConfiguration->mnSamplingRate = fw_convert_number(pData);
861 pData += 4;
863 if (pFirmware->mnDriverVersion >= PPC_DRIVER_MTPLLSRC) {
864 pConfiguration->mnPLLSrc = pData[0];
865 pData++;
867 pConfiguration->mnPLLSrcRate = fw_convert_number(pData);
868 pData += 4;
869 }
871 n = fw_parse_data(pTAS2557, pFirmware, &(pConfiguration->mData), pData);
872 pData += n;
873 }
875 end:
877 return pData - pDataStart;
878 }
880 int fw_parse_calibration_data(struct tas2557_priv *pTAS2557,
881 struct TFirmware *pFirmware, unsigned char *pData)
882 {
883 unsigned char *pDataStart = pData;
884 unsigned int n;
885 unsigned int nCalibration;
886 struct TCalibration *pCalibration;
888 pFirmware->mnCalibrations = (pData[0] << 8) + pData[1];
889 pData += 2;
891 if (pFirmware->mnCalibrations == 0)
892 goto end;
894 pFirmware->mpCalibrations =
895 kmalloc(sizeof(struct TCalibration) * pFirmware->mnCalibrations, GFP_KERNEL);
896 for (nCalibration = 0;
897 nCalibration < pFirmware->mnCalibrations;
898 nCalibration++) {
899 pCalibration = &(pFirmware->mpCalibrations[nCalibration]);
900 memcpy(pCalibration->mpName, pData, 64);
901 pData += 64;
903 n = strlen(pData);
904 pCalibration->mpDescription = kmemdup(pData, n + 1, GFP_KERNEL);
905 pData += n + 1;
907 pCalibration->mnProgram = pData[0];
908 pData++;
910 pCalibration->mnConfiguration = pData[0];
911 pData++;
913 n = fw_parse_data(pTAS2557, pFirmware, &(pCalibration->mData), pData);
914 pData += n;
915 }
917 end:
919 return pData - pDataStart;
920 }
922 static int fw_parse(struct tas2557_priv *pTAS2557,
923 struct TFirmware *pFirmware, unsigned char *pData, unsigned int nSize)
924 {
925 int nPosition = 0;
927 nPosition = fw_parse_header(pTAS2557, pFirmware, pData, nSize);
928 if (nPosition < 0) {
929 dev_err(pTAS2557->dev, "Firmware: Wrong Header");
930 return -EINVAL;
931 }
933 if (nPosition >= nSize) {
934 dev_err(pTAS2557->dev, "Firmware: Too short");
935 return -EINVAL;
936 }
938 pData += nPosition;
939 nSize -= nPosition;
940 nPosition = 0;
942 nPosition = fw_parse_pll_data(pTAS2557, pFirmware, pData);
944 pData += nPosition;
945 nSize -= nPosition;
946 nPosition = 0;
948 nPosition = fw_parse_program_data(pTAS2557, pFirmware, pData);
950 pData += nPosition;
951 nSize -= nPosition;
952 nPosition = 0;
954 nPosition = fw_parse_configuration_data(pTAS2557, pFirmware, pData);
956 pData += nPosition;
957 nSize -= nPosition;
958 nPosition = 0;
960 if (nSize > 64)
961 nPosition = fw_parse_calibration_data(pTAS2557, pFirmware, pData);
962 return 0;
963 }
966 static const unsigned char crc8_lookup_table[CRC8_TABLE_SIZE] = {
967 0x00, 0x4D, 0x9A, 0xD7, 0x79, 0x34, 0xE3, 0xAE, 0xF2, 0xBF, 0x68, 0x25, 0x8B, 0xC6, 0x11, 0x5C,
968 0xA9, 0xE4, 0x33, 0x7E, 0xD0, 0x9D, 0x4A, 0x07, 0x5B, 0x16, 0xC1, 0x8C, 0x22, 0x6F, 0xB8, 0xF5,
969 0x1F, 0x52, 0x85, 0xC8, 0x66, 0x2B, 0xFC, 0xB1, 0xED, 0xA0, 0x77, 0x3A, 0x94, 0xD9, 0x0E, 0x43,
970 0xB6, 0xFB, 0x2C, 0x61, 0xCF, 0x82, 0x55, 0x18, 0x44, 0x09, 0xDE, 0x93, 0x3D, 0x70, 0xA7, 0xEA,
971 0x3E, 0x73, 0xA4, 0xE9, 0x47, 0x0A, 0xDD, 0x90, 0xCC, 0x81, 0x56, 0x1B, 0xB5, 0xF8, 0x2F, 0x62,
972 0x97, 0xDA, 0x0D, 0x40, 0xEE, 0xA3, 0x74, 0x39, 0x65, 0x28, 0xFF, 0xB2, 0x1C, 0x51, 0x86, 0xCB,
973 0x21, 0x6C, 0xBB, 0xF6, 0x58, 0x15, 0xC2, 0x8F, 0xD3, 0x9E, 0x49, 0x04, 0xAA, 0xE7, 0x30, 0x7D,
974 0x88, 0xC5, 0x12, 0x5F, 0xF1, 0xBC, 0x6B, 0x26, 0x7A, 0x37, 0xE0, 0xAD, 0x03, 0x4E, 0x99, 0xD4,
975 0x7C, 0x31, 0xE6, 0xAB, 0x05, 0x48, 0x9F, 0xD2, 0x8E, 0xC3, 0x14, 0x59, 0xF7, 0xBA, 0x6D, 0x20,
976 0xD5, 0x98, 0x4F, 0x02, 0xAC, 0xE1, 0x36, 0x7B, 0x27, 0x6A, 0xBD, 0xF0, 0x5E, 0x13, 0xC4, 0x89,
977 0x63, 0x2E, 0xF9, 0xB4, 0x1A, 0x57, 0x80, 0xCD, 0x91, 0xDC, 0x0B, 0x46, 0xE8, 0xA5, 0x72, 0x3F,
978 0xCA, 0x87, 0x50, 0x1D, 0xB3, 0xFE, 0x29, 0x64, 0x38, 0x75, 0xA2, 0xEF, 0x41, 0x0C, 0xDB, 0x96,
979 0x42, 0x0F, 0xD8, 0x95, 0x3B, 0x76, 0xA1, 0xEC, 0xB0, 0xFD, 0x2A, 0x67, 0xC9, 0x84, 0x53, 0x1E,
980 0xEB, 0xA6, 0x71, 0x3C, 0x92, 0xDF, 0x08, 0x45, 0x19, 0x54, 0x83, 0xCE, 0x60, 0x2D, 0xFA, 0xB7,
981 0x5D, 0x10, 0xC7, 0x8A, 0x24, 0x69, 0xBE, 0xF3, 0xAF, 0xE2, 0x35, 0x78, 0xD6, 0x9B, 0x4C, 0x01,
982 0xF4, 0xB9, 0x6E, 0x23, 0x8D, 0xC0, 0x17, 0x5A, 0x06, 0x4B, 0x9C, 0xD1, 0x7F, 0x32, 0xE5, 0xA8
983 };
985 static int isInPageYRAM(struct tas2557_priv *pTAS2557, struct TYCRC *pCRCData,
986 unsigned char nBook, unsigned char nPage, unsigned char nReg, unsigned char len)
987 {
988 int nResult = 0;
990 if (nBook == TAS2557_YRAM_BOOK1) {
991 if (nPage == TAS2557_YRAM1_PAGE) {
992 if (nReg >= TAS2557_YRAM1_START_REG) {
993 pCRCData->mnOffset = nReg;
994 pCRCData->mnLen = len;
995 nResult = 1;
996 } else if ((nReg + len) > TAS2557_YRAM1_START_REG) {
997 pCRCData->mnOffset = TAS2557_YRAM1_START_REG;
998 pCRCData->mnLen = len - (TAS2557_YRAM1_START_REG - nReg);
999 nResult = 1;
1000 } else
1001 nResult = 0;
1002 } else if (nPage == TAS2557_YRAM3_PAGE) {
1003 if (nReg > TAS2557_YRAM3_END_REG) {
1004 nResult = 0;
1005 } else if (nReg >= TAS2557_YRAM3_START_REG) {
1006 if ((nReg + len) > TAS2557_YRAM3_END_REG) {
1007 pCRCData->mnOffset = nReg;
1008 pCRCData->mnLen = TAS2557_YRAM3_END_REG - nReg + 1;
1009 nResult = 1;
1010 } else {
1011 pCRCData->mnOffset = nReg;
1012 pCRCData->mnLen = len;
1013 nResult = 1;
1014 }
1015 } else {
1016 if ((nReg + (len - 1)) < TAS2557_YRAM3_START_REG)
1017 nResult = 0;
1018 else {
1019 pCRCData->mnOffset = TAS2557_YRAM3_START_REG;
1020 pCRCData->mnLen = len - (TAS2557_YRAM3_START_REG - nReg);
1021 nResult = 1;
1022 }
1023 }
1024 }
1025 } else if (nBook == TAS2557_YRAM_BOOK2) {
1026 if (nPage == TAS2557_YRAM5_PAGE) {
1027 if (nReg > TAS2557_YRAM5_END_REG) {
1028 nResult = 0;
1029 } else if (nReg >= TAS2557_YRAM5_START_REG) {
1030 if ((nReg + len) > TAS2557_YRAM5_END_REG) {
1031 pCRCData->mnOffset = nReg;
1032 pCRCData->mnLen = TAS2557_YRAM5_END_REG - nReg + 1;
1033 nResult = 1;
1034 } else {
1035 pCRCData->mnOffset = nReg;
1036 pCRCData->mnLen = len;
1037 nResult = 1;
1038 }
1039 } else {
1040 if ((nReg + (len - 1)) < TAS2557_YRAM5_START_REG)
1041 nResult = 0;
1042 else {
1043 pCRCData->mnOffset = TAS2557_YRAM5_START_REG;
1044 pCRCData->mnLen = len - (TAS2557_YRAM5_START_REG - nReg);
1045 nResult = 1;
1046 }
1047 }
1048 }
1049 } else
1050 nResult = 0;
1052 return nResult;
1053 }
1055 static int isInBlockYRAM(struct tas2557_priv *pTAS2557, struct TYCRC *pCRCData,
1056 unsigned char nBook, unsigned char nPage, unsigned char nReg, unsigned char len)
1057 {
1058 int nResult;
1060 if (nBook == TAS2557_YRAM_BOOK1) {
1061 if (nPage < TAS2557_YRAM2_START_PAGE)
1062 nResult = 0;
1063 else if (nPage <= TAS2557_YRAM2_END_PAGE) {
1064 if (nReg > TAS2557_YRAM2_END_REG)
1065 nResult = 0;
1066 else if (nReg >= TAS2557_YRAM2_START_REG) {
1067 pCRCData->mnOffset = nReg;
1068 pCRCData->mnLen = len;
1069 nResult = 1;
1070 } else {
1071 if ((nReg + (len - 1)) < TAS2557_YRAM2_START_REG)
1072 nResult = 0;
1073 else {
1074 pCRCData->mnOffset = TAS2557_YRAM2_START_REG;
1075 pCRCData->mnLen = nReg + len - TAS2557_YRAM2_START_REG;
1076 nResult = 1;
1077 }
1078 }
1079 } else
1080 nResult = 0;
1081 } else if (nBook == TAS2557_YRAM_BOOK2) {
1082 if (nPage < TAS2557_YRAM4_START_PAGE)
1083 nResult = 0;
1084 else if (nPage <= TAS2557_YRAM4_END_PAGE) {
1085 if (nReg > TAS2557_YRAM2_END_REG)
1086 nResult = 0;
1087 else if (nReg >= TAS2557_YRAM2_START_REG) {
1088 pCRCData->mnOffset = nReg;
1089 pCRCData->mnLen = len;
1090 nResult = 1;
1091 } else {
1092 if ((nReg + (len - 1)) < TAS2557_YRAM2_START_REG)
1093 nResult = 0;
1094 else {
1095 pCRCData->mnOffset = TAS2557_YRAM2_START_REG;
1096 pCRCData->mnLen = nReg + len - TAS2557_YRAM2_START_REG;
1097 nResult = 1;
1098 }
1099 }
1100 } else
1101 nResult = 0;
1102 } else
1103 nResult = 0;
1105 return nResult;
1106 }
1109 static int isYRAM(struct tas2557_priv *pTAS2557, struct TYCRC *pCRCData,
1110 unsigned char nBook, unsigned char nPage, unsigned char nReg, unsigned char len)
1111 {
1112 int nResult;
1114 nResult = isInPageYRAM(pTAS2557, pCRCData, nBook, nPage, nReg, len);
1116 if (nResult == 0)
1117 nResult = isInBlockYRAM(pTAS2557, pCRCData, nBook, nPage, nReg, len);
1119 return nResult;
1120 }
1122 /*
1123 * crc8 - calculate a crc8 over the given input data.
1124 *
1125 * table: crc table used for calculation.
1126 * pdata: pointer to data buffer.
1127 * nbytes: number of bytes in data buffer.
1128 * crc: previous returned crc8 value.
1129 */
1130 static u8 ti_crc8(const u8 table[CRC8_TABLE_SIZE], u8 *pdata, size_t nbytes, u8 crc)
1131 {
1132 /* loop over the buffer data */
1133 while (nbytes-- > 0)
1134 crc = table[(crc ^ *pdata++) & 0xff];
1136 return crc;
1137 }
1139 static int doSingleRegCheckSum(struct tas2557_priv *pTAS2557,
1140 unsigned char nBook, unsigned char nPage, unsigned char nReg, unsigned char nValue)
1141 {
1142 int nResult = 0;
1143 struct TYCRC sCRCData;
1144 unsigned int nData1 = 0;
1146 if ((nBook == TAS2557_BOOK_ID(TAS2557_SA_COEFF_SWAP_REG))
1147 && (nPage == TAS2557_PAGE_ID(TAS2557_SA_COEFF_SWAP_REG))
1148 && (nReg >= TAS2557_PAGE_REG(TAS2557_SA_COEFF_SWAP_REG))
1149 && (nReg <= (TAS2557_PAGE_REG(TAS2557_SA_COEFF_SWAP_REG) + 4))) {
1150 /* DSP swap command, pass */
1151 nResult = 0;
1152 goto end;
1153 }
1155 nResult = isYRAM(pTAS2557, &sCRCData, nBook, nPage, nReg, 1);
1156 if (nResult == 1) {
1157 nResult = pTAS2557->read(pTAS2557, TAS2557_REG(nBook, nPage, nReg), &nData1);
1158 if (nResult < 0)
1159 goto end;
1161 if (nData1 != nValue) {
1162 dev_err(pTAS2557->dev, "error2 (line %d),B[0x%x]P[0x%x]R[0x%x] W[0x%x], R[0x%x]\n",
1163 __LINE__, nBook, nPage, nReg, nValue, nData1);
1164 nResult = -EAGAIN;
1165 goto end;
1166 }
1168 nResult = ti_crc8(crc8_lookup_table, &nValue, 1, 0);
1169 }
1171 end:
1173 return nResult;
1174 }
1176 static int doMultiRegCheckSum(struct tas2557_priv *pTAS2557,
1177 unsigned char nBook, unsigned char nPage, unsigned char nReg, unsigned int len)
1178 {
1179 int nResult = 0, i;
1180 unsigned char nCRCChkSum = 0;
1181 unsigned char nBuf1[128];
1182 struct TYCRC TCRCData;
1184 if ((nReg + len-1) > 127) {
1185 nResult = -EINVAL;
1186 dev_err(pTAS2557->dev, "firmware error\n");
1187 goto end;
1188 }
1190 if ((nBook == TAS2557_BOOK_ID(TAS2557_SA_COEFF_SWAP_REG))
1191 && (nPage == TAS2557_PAGE_ID(TAS2557_SA_COEFF_SWAP_REG))
1192 && (nReg == TAS2557_PAGE_REG(TAS2557_SA_COEFF_SWAP_REG))
1193 && (len == 4)) {
1194 /* DSP swap command, pass */
1195 nResult = 0;
1196 goto end;
1197 }
1199 nResult = isYRAM(pTAS2557, &TCRCData, nBook, nPage, nReg, len);
1200 if (nResult == 1) {
1201 if (len == 1) {
1202 dev_err(pTAS2557->dev, "firmware error\n");
1203 nResult = -EINVAL;
1204 goto end;
1205 } else {
1206 nResult = pTAS2557->bulk_read(pTAS2557, TAS2557_REG(nBook, nPage, TCRCData.mnOffset), nBuf1, TCRCData.mnLen);
1207 if (nResult < 0)
1208 goto end;
1210 for (i = 0; i < TCRCData.mnLen; i++) {
1211 if ((nBook == TAS2557_BOOK_ID(TAS2557_SA_COEFF_SWAP_REG))
1212 && (nPage == TAS2557_PAGE_ID(TAS2557_SA_COEFF_SWAP_REG))
1213 && ((i + TCRCData.mnOffset)
1214 >= TAS2557_PAGE_REG(TAS2557_SA_COEFF_SWAP_REG))
1215 && ((i + TCRCData.mnOffset)
1216 <= (TAS2557_PAGE_REG(TAS2557_SA_COEFF_SWAP_REG) + 4))) {
1217 /* DSP swap command, bypass */
1218 continue;
1219 } else
1220 nCRCChkSum += ti_crc8(crc8_lookup_table, &nBuf1[i], 1, 0);
1221 }
1223 nResult = nCRCChkSum;
1224 }
1225 }
1227 end:
1229 return nResult;
1230 }
1232 static int tas2557_load_block(struct tas2557_priv *pTAS2557, struct TBlock *pBlock)
1233 {
1234 int nResult = 0;
1235 unsigned int nCommand = 0;
1236 unsigned char nBook;
1237 unsigned char nPage;
1238 unsigned char nOffset;
1239 unsigned char nData;
1240 unsigned int nLength;
1241 unsigned int nSleep;
1242 unsigned char nCRCChkSum = 0;
1243 unsigned int nValue1;
1244 int nRetry = 6;
1245 unsigned char *pData = pBlock->mpData;
1247 dev_dbg(pTAS2557->dev, "TAS2557 load block: Type = %d, commands = %d\n",
1248 pBlock->mnType, pBlock->mnCommands);
1249 start:
1250 if (pBlock->mbPChkSumPresent) {
1251 nResult = pTAS2557->write(pTAS2557, TAS2557_CRC_RESET_REG, 1);
1252 if (nResult < 0)
1253 goto end;
1254 }
1256 if (pBlock->mbYChkSumPresent)
1257 nCRCChkSum = 0;
1259 nCommand = 0;
1261 while (nCommand < pBlock->mnCommands) {
1262 pData = pBlock->mpData + nCommand * 4;
1264 nBook = pData[0];
1265 nPage = pData[1];
1266 nOffset = pData[2];
1267 nData = pData[3];
1269 nCommand++;
1271 if (nOffset <= 0x7F) {
1272 nResult = pTAS2557->write(pTAS2557, TAS2557_REG(nBook, nPage, nOffset), nData);
1273 if (nResult < 0)
1274 goto end;
1275 if (pBlock->mbYChkSumPresent) {
1276 nResult = doSingleRegCheckSum(pTAS2557, nBook, nPage, nOffset, nData);
1277 if (nResult < 0)
1278 goto check;
1279 nCRCChkSum += (unsigned char)nResult;
1280 }
1281 } else if (nOffset == 0x81) {
1282 nSleep = (nBook << 8) + nPage;
1283 msleep(nSleep);
1284 } else if (nOffset == 0x85) {
1285 pData += 4;
1286 nLength = (nBook << 8) + nPage;
1287 nBook = pData[0];
1288 nPage = pData[1];
1289 nOffset = pData[2];
1290 if (nLength > 1) {
1291 nResult = pTAS2557->bulk_write(pTAS2557, TAS2557_REG(nBook, nPage, nOffset), pData + 3, nLength);
1292 if (nResult < 0)
1293 goto end;
1294 if (pBlock->mbYChkSumPresent) {
1295 nResult = doMultiRegCheckSum(pTAS2557, nBook, nPage, nOffset, nLength);
1296 if (nResult < 0)
1297 goto check;
1298 nCRCChkSum += (unsigned char)nResult;
1299 }
1300 } else {
1301 nResult = pTAS2557->write(pTAS2557, TAS2557_REG(nBook, nPage, nOffset), pData[3]);
1302 if (nResult < 0)
1303 goto end;
1304 if (pBlock->mbYChkSumPresent) {
1305 nResult = doSingleRegCheckSum(pTAS2557, nBook, nPage, nOffset, pData[3]);
1306 if (nResult < 0)
1307 goto check;
1308 nCRCChkSum += (unsigned char)nResult;
1309 }
1310 }
1312 nCommand++;
1314 if (nLength >= 2)
1315 nCommand += ((nLength - 2) / 4) + 1;
1316 }
1317 }
1318 if (pBlock->mbPChkSumPresent) {
1319 nResult = pTAS2557->read(pTAS2557, TAS2557_CRC_CHECKSUM_REG, &nValue1);
1320 if (nResult < 0)
1321 goto end;
1322 if ((nValue1&0xff) != pBlock->mnPChkSum) {
1323 dev_err(pTAS2557->dev, "Block PChkSum Error: FW = 0x%x, Reg = 0x%x\n",
1324 pBlock->mnPChkSum, (nValue1&0xff));
1325 nResult = -EAGAIN;
1326 pTAS2557->mnErrCode |= ERROR_PRAM_CRCCHK;
1327 goto check;
1328 }
1330 nResult = 0;
1331 pTAS2557->mnErrCode &= ~ERROR_PRAM_CRCCHK;
1332 dev_dbg(pTAS2557->dev, "Block[0x%x] PChkSum match\n", pBlock->mnType);
1333 }
1335 if (pBlock->mbYChkSumPresent) {
1336 if (nCRCChkSum != pBlock->mnYChkSum) {
1337 dev_err(pTAS2557->dev, "Block YChkSum Error: FW = 0x%x, YCRC = 0x%x\n",
1338 pBlock->mnYChkSum, nCRCChkSum);
1339 nResult = -EAGAIN;
1340 pTAS2557->mnErrCode |= ERROR_YRAM_CRCCHK;
1341 goto check;
1342 }
1343 pTAS2557->mnErrCode &= ~ERROR_YRAM_CRCCHK;
1344 nResult = 0;
1345 dev_dbg(pTAS2557->dev, "Block[0x%x] YChkSum match\n", pBlock->mnType);
1346 }
1348 check:
1349 if (nResult == -EAGAIN) {
1350 nRetry--;
1351 if (nRetry > 0)
1352 goto start;
1353 }
1355 end:
1356 if (nResult < 0) {
1357 dev_err(pTAS2557->dev, "Block (%d) load error\n",
1358 pBlock->mnType);
1359 }
1360 return nResult;
1361 }
1363 static int tas2557_load_data(struct tas2557_priv *pTAS2557, struct TData *pData, unsigned int nType)
1364 {
1365 int nResult = 0;
1366 unsigned int nBlock;
1367 struct TBlock *pBlock;
1369 dev_dbg(pTAS2557->dev,
1370 "TAS2557 load data: %s, Blocks = %d, Block Type = %d\n", pData->mpName, pData->mnBlocks, nType);
1372 for (nBlock = 0; nBlock < pData->mnBlocks; nBlock++) {
1373 pBlock = &(pData->mpBlocks[nBlock]);
1374 if (pBlock->mnType == nType) {
1375 nResult = tas2557_load_block(pTAS2557, pBlock);
1376 if (nResult < 0)
1377 break;
1378 }
1379 }
1381 return nResult;
1382 }
1384 static int tas2557_load_configuration(struct tas2557_priv *pTAS2557,
1385 unsigned int nConfiguration, bool bLoadSame)
1386 {
1387 int nResult = 0;
1388 struct TConfiguration *pCurrentConfiguration = NULL;
1389 struct TConfiguration *pNewConfiguration = NULL;
1391 dev_dbg(pTAS2557->dev, "%s: %d\n", __func__, nConfiguration);
1393 if ((!pTAS2557->mpFirmware->mpPrograms) ||
1394 (!pTAS2557->mpFirmware->mpConfigurations)) {
1395 dev_err(pTAS2557->dev, "Firmware not loaded\n");
1396 nResult = 0;
1397 goto end;
1398 }
1400 if (nConfiguration >= pTAS2557->mpFirmware->mnConfigurations) {
1401 dev_err(pTAS2557->dev, "Configuration %d doesn't exist\n",
1402 nConfiguration);
1403 nResult = 0;
1404 goto end;
1405 }
1407 if ((!pTAS2557->mbLoadConfigurationPrePowerUp)
1408 && (nConfiguration == pTAS2557->mnCurrentConfiguration)
1409 && (!bLoadSame)) {
1410 dev_info(pTAS2557->dev, "Configuration %d is already loaded\n",
1411 nConfiguration);
1412 nResult = 0;
1413 goto end;
1414 }
1416 pCurrentConfiguration =
1417 &(pTAS2557->mpFirmware->mpConfigurations[pTAS2557->mnCurrentConfiguration]);
1418 pNewConfiguration =
1419 &(pTAS2557->mpFirmware->mpConfigurations[nConfiguration]);
1420 if (pNewConfiguration->mnProgram != pCurrentConfiguration->mnProgram) {
1421 dev_err(pTAS2557->dev, "Configuration %d, %s doesn't share the same program as current %d\n",
1422 nConfiguration, pNewConfiguration->mpName, pCurrentConfiguration->mnProgram);
1423 nResult = 0;
1424 goto end;
1425 }
1427 if (pNewConfiguration->mnPLL >= pTAS2557->mpFirmware->mnPLLs) {
1428 dev_err(pTAS2557->dev, "Configuration %d, %s doesn't have a valid PLL index %d\n",
1429 nConfiguration, pNewConfiguration->mpName, pNewConfiguration->mnPLL);
1430 nResult = 0;
1431 goto end;
1432 }
1434 if (pTAS2557->mbPowerUp) {
1435 pTAS2557->mbLoadConfigurationPrePowerUp = false;
1436 nResult = tas2557_load_coefficient(pTAS2557, pTAS2557->mnCurrentConfiguration, nConfiguration, true);
1437 } else {
1438 dev_dbg(pTAS2557->dev,
1439 "TAS2557 was powered down, will load coefficient when power up\n");
1440 pTAS2557->mbLoadConfigurationPrePowerUp = true;
1441 pTAS2557->mnNewConfiguration = nConfiguration;
1442 }
1444 end:
1446 if (nResult < 0) {
1447 if (pTAS2557->mnErrCode & (ERROR_DEVA_I2C_COMM | ERROR_PRAM_CRCCHK | ERROR_YRAM_CRCCHK))
1448 failsafe(pTAS2557);
1449 }
1451 return nResult;
1452 }
1454 int tas2557_set_config(struct tas2557_priv *pTAS2557, int config)
1455 {
1456 struct TConfiguration *pConfiguration;
1457 struct TProgram *pProgram;
1458 unsigned int nProgram = pTAS2557->mnCurrentProgram;
1459 unsigned int nConfiguration = config;
1460 int nResult = 0;
1462 if ((!pTAS2557->mpFirmware->mpPrograms) ||
1463 (!pTAS2557->mpFirmware->mpConfigurations)) {
1464 dev_err(pTAS2557->dev, "Firmware not loaded\n");
1465 nResult = -EINVAL;
1466 goto end;
1467 }
1469 if (nConfiguration >= pTAS2557->mpFirmware->mnConfigurations) {
1470 dev_err(pTAS2557->dev, "Configuration %d doesn't exist\n",
1471 nConfiguration);
1472 nResult = -EINVAL;
1473 goto end;
1474 }
1476 pConfiguration = &(pTAS2557->mpFirmware->mpConfigurations[nConfiguration]);
1477 pProgram = &(pTAS2557->mpFirmware->mpPrograms[nProgram]);
1479 if (nProgram != pConfiguration->mnProgram) {
1480 dev_err(pTAS2557->dev,
1481 "Configuration %d, %s with Program %d isn't compatible with existing Program %d, %s\n",
1482 nConfiguration, pConfiguration->mpName, pConfiguration->mnProgram,
1483 nProgram, pProgram->mpName);
1484 nResult = -EINVAL;
1485 goto end;
1486 }
1488 nResult = tas2557_load_configuration(pTAS2557, nConfiguration, false);
1490 end:
1492 return nResult;
1493 }
1495 void tas2557_clear_firmware(struct TFirmware *pFirmware)
1496 {
1497 unsigned int n, nn;
1499 if (!pFirmware)
1500 return;
1502 kfree(pFirmware->mpDescription);
1504 if (pFirmware->mpPLLs != NULL) {
1505 for (n = 0; n < pFirmware->mnPLLs; n++) {
1506 kfree(pFirmware->mpPLLs[n].mpDescription);
1507 kfree(pFirmware->mpPLLs[n].mBlock.mpData);
1508 }
1509 kfree(pFirmware->mpPLLs);
1510 }
1512 if (pFirmware->mpPrograms != NULL) {
1513 for (n = 0; n < pFirmware->mnPrograms; n++) {
1514 kfree(pFirmware->mpPrograms[n].mpDescription);
1515 kfree(pFirmware->mpPrograms[n].mData.mpDescription);
1516 for (nn = 0; nn < pFirmware->mpPrograms[n].mData.mnBlocks; nn++)
1517 kfree(pFirmware->mpPrograms[n].mData.mpBlocks[nn].mpData);
1518 kfree(pFirmware->mpPrograms[n].mData.mpBlocks);
1519 }
1520 kfree(pFirmware->mpPrograms);
1521 }
1523 if (pFirmware->mpConfigurations != NULL) {
1524 for (n = 0; n < pFirmware->mnConfigurations; n++) {
1525 kfree(pFirmware->mpConfigurations[n].mpDescription);
1526 kfree(pFirmware->mpConfigurations[n].mData.mpDescription);
1527 for (nn = 0; nn < pFirmware->mpConfigurations[n].mData.mnBlocks; nn++)
1528 kfree(pFirmware->mpConfigurations[n].mData.mpBlocks[nn].mpData);
1529 kfree(pFirmware->mpConfigurations[n].mData.mpBlocks);
1530 }
1531 kfree(pFirmware->mpConfigurations);
1532 }
1534 if (pFirmware->mpCalibrations != NULL) {
1535 for (n = 0; n < pFirmware->mnCalibrations; n++) {
1536 kfree(pFirmware->mpCalibrations[n].mpDescription);
1537 kfree(pFirmware->mpCalibrations[n].mData.mpDescription);
1538 for (nn = 0; nn < pFirmware->mpCalibrations[n].mData.mnBlocks; nn++)
1539 kfree(pFirmware->mpCalibrations[n].mData.mpBlocks[nn].mpData);
1540 kfree(pFirmware->mpCalibrations[n].mData.mpBlocks);
1541 }
1542 kfree(pFirmware->mpCalibrations);
1543 }
1545 memset(pFirmware, 0x00, sizeof(struct TFirmware));
1546 }
1548 static int tas2557_load_calibration(struct tas2557_priv *pTAS2557, char *pFileName)
1549 {
1550 int nResult = 0;
1551 /*
1552 * int nFile;
1553 * mm_segment_t fs;
1554 * unsigned char pBuffer[1000];
1555 * int nSize = 0;
1556 *
1557 * dev_dbg(pTAS2557->dev, "%s:\n", __func__);
1558 *
1559 * fs = get_fs();
1560 * set_fs(KERNEL_DS);
1561 * nFile = sys_open(pFileName, O_RDONLY, 0);
1562 *
1563 * dev_info(pTAS2557->dev, "TAS2557 calibration file = %s, handle = %d\n",
1564 * pFileName, nFile);
1565 *
1566 * if (nFile >= 0) {
1567 * nSize = sys_read(nFile, pBuffer, 1000);
1568 * sys_close(nFile);
1569 * } else {
1570 * dev_err(pTAS2557->dev, "TAS2557 cannot open calibration file: %s\n",
1571 * pFileName);
1572 * }
1573 *
1574 * set_fs(fs);
1575 *
1576 * if (!nSize)
1577 * goto end;
1578 *
1579 * tas2557_clear_firmware(pTAS2557->mpCalFirmware);
1580 * dev_info(pTAS2557->dev, "TAS2557 calibration file size = %d\n", nSize);
1581 * nResult = fw_parse(pTAS2557, pTAS2557->mpCalFirmware, pBuffer, nSize);
1582 *
1583 * if (nResult)
1584 * dev_err(pTAS2557->dev, "TAS2557 calibration file is corrupt\n");
1585 * else
1586 * dev_info(pTAS2557->dev, "TAS2557 calibration: %d calibrations\n",
1587 * pTAS2557->mpCalFirmware->mnCalibrations);
1588 *
1589 *end:
1590 **/
1591 return nResult;
1592 }
1594 static bool tas2557_get_coefficient_in_block(struct tas2557_priv *pTAS2557,
1595 struct TBlock *pBlock, int nReg, int *pnValue)
1596 {
1597 int nCoefficient = 0;
1598 bool bFound = false;
1599 unsigned char *pCommands;
1600 int nBook, nPage, nOffset, len;
1601 int i, n;
1603 pCommands = pBlock->mpData;
1604 for (i = 0 ; i < pBlock->mnCommands;) {
1605 nBook = pCommands[4 * i + 0];
1606 nPage = pCommands[4 * i + 1];
1607 nOffset = pCommands[4 * i + 2];
1608 if ((nOffset < 0x7f) || (nOffset == 0x81))
1609 i++;
1610 else if (nOffset == 0x85) {
1611 len = ((int)nBook << 8) | nPage;
1612 nBook = pCommands[4 * i + 4];
1613 nPage = pCommands[4 * i + 5];
1614 nOffset = pCommands[4 * i + 6];
1615 n = 4 * i + 7;
1616 i += 2;
1617 i += ((len - 1) / 4);
1618 if ((len - 1) % 4)
1619 i++;
1620 if ((nBook != TAS2557_BOOK_ID(nReg))
1621 || (nPage != TAS2557_PAGE_ID(nReg)))
1622 continue;
1623 if (nOffset > TAS2557_PAGE_REG(nReg))
1624 continue;
1625 if ((len + nOffset) >= (TAS2557_PAGE_REG(nReg) + 4)) {
1626 n += (TAS2557_PAGE_REG(nReg) - nOffset);
1627 nCoefficient = ((int)pCommands[n] << 24)
1628 | ((int)pCommands[n + 1] << 16)
1629 | ((int)pCommands[n + 2] << 8)
1630 | (int)pCommands[n + 3];
1631 bFound = true;
1632 break;
1633 }
1634 } else {
1635 dev_err(pTAS2557->dev, "%s, format error %d\n", __func__, nOffset);
1636 break;
1637 }
1638 }
1640 if (bFound) {
1641 *pnValue = nCoefficient;
1642 dev_dbg(pTAS2557->dev, "%s, B[0x%x]P[0x%x]R[0x%x]=0x%x\n", __func__,
1643 TAS2557_BOOK_ID(nReg), TAS2557_PAGE_ID(nReg), TAS2557_PAGE_REG(nReg),
1644 nCoefficient);
1645 }
1647 return bFound;
1648 }
1650 static bool tas2557_get_coefficient_in_data(struct tas2557_priv *pTAS2557,
1651 struct TData *pData, int blockType, int nReg, int *pnValue)
1652 {
1653 bool bFound = false;
1654 struct TBlock *pBlock;
1655 int i;
1657 for (i = 0; i < pData->mnBlocks; i++) {
1658 pBlock = &(pData->mpBlocks[i]);
1659 if (pBlock->mnType == blockType) {
1660 bFound = tas2557_get_coefficient_in_block(pTAS2557,
1661 pBlock, nReg, pnValue);
1662 if (bFound)
1663 break;
1664 }
1665 }
1667 return bFound;
1668 }
1670 static bool tas2557_find_Tmax_in_configuration(struct tas2557_priv *pTAS2557,
1671 struct TConfiguration *pConfiguration, int *pnTMax)
1672 {
1673 struct TData *pData;
1674 bool bFound = false;
1675 int nBlockType, nReg, nCoefficient;
1677 if (pTAS2557->mnPGID == TAS2557_PG_VERSION_2P1)
1678 nReg = TAS2557_PG2P1_CALI_T_REG;
1679 else
1680 nReg = TAS2557_PG1P0_CALI_T_REG;
1682 nBlockType = TAS2557_BLOCK_CFG_COEFF_DEV_A;
1684 pData = &(pConfiguration->mData);
1685 bFound = tas2557_get_coefficient_in_data(pTAS2557, pData, nBlockType, nReg, &nCoefficient);
1686 if (bFound)
1687 *pnTMax = nCoefficient;
1689 return bFound;
1690 }
1692 void tas2557_fw_ready(const struct firmware *pFW, void *pContext)
1693 {
1694 struct tas2557_priv *pTAS2557 = (struct tas2557_priv *) pContext;
1695 int nResult;
1696 unsigned int nProgram = 0;
1697 unsigned int nSampleRate = 0;
1699 #ifdef CONFIG_TAS2557_CODEC
1700 mutex_lock(&pTAS2557->codec_lock);
1701 #endif
1703 #ifdef CONFIG_TAS2557_MISC
1704 mutex_lock(&pTAS2557->file_lock);
1705 #endif
1707 dev_info(pTAS2557->dev, "%s:\n", __func__);
1709 if (unlikely(!pFW) || unlikely(!pFW->data)) {
1710 dev_err(pTAS2557->dev, "%s firmware is not loaded.\n",
1711 TAS2557_FW_NAME);
1712 goto end;
1713 }
1715 if (pTAS2557->mpFirmware->mpConfigurations) {
1716 nProgram = pTAS2557->mnCurrentProgram;
1717 nSampleRate = pTAS2557->mnCurrentSampleRate;
1718 dev_dbg(pTAS2557->dev, "clear current firmware\n");
1719 tas2557_clear_firmware(pTAS2557->mpFirmware);
1720 }
1722 nResult = fw_parse(pTAS2557, pTAS2557->mpFirmware, (unsigned char *)(pFW->data), pFW->size);
1723 release_firmware(pFW);
1724 if (nResult < 0) {
1725 dev_err(pTAS2557->dev, "firmware is corrupt\n");
1726 goto end;
1727 }
1729 if (!pTAS2557->mpFirmware->mnPrograms) {
1730 dev_err(pTAS2557->dev, "firmware contains no programs\n");
1731 nResult = -EINVAL;
1732 goto end;
1733 }
1735 if (!pTAS2557->mpFirmware->mnConfigurations) {
1736 dev_err(pTAS2557->dev, "firmware contains no configurations\n");
1737 nResult = -EINVAL;
1738 goto end;
1739 }
1741 if (nProgram >= pTAS2557->mpFirmware->mnPrograms) {
1742 dev_info(pTAS2557->dev,
1743 "no previous program, set to default\n");
1744 nProgram = 0;
1745 }
1747 pTAS2557->mnCurrentSampleRate = nSampleRate;
1748 nResult = tas2557_set_program(pTAS2557, nProgram, -1);
1750 end:
1752 #ifdef CONFIG_TAS2557_CODEC
1753 mutex_unlock(&pTAS2557->codec_lock);
1754 #endif
1756 #ifdef CONFIG_TAS2557_MISC
1757 mutex_unlock(&pTAS2557->file_lock);
1758 #endif
1759 }
1761 int tas2557_set_program(struct tas2557_priv *pTAS2557,
1762 unsigned int nProgram, int nConfig)
1763 {
1764 struct TProgram *pProgram;
1765 unsigned int nConfiguration = 0;
1766 unsigned int nSampleRate = 0;
1767 unsigned char nGain;
1768 bool bFound = false;
1769 int nResult = 0;
1771 if ((!pTAS2557->mpFirmware->mpPrograms) ||
1772 (!pTAS2557->mpFirmware->mpConfigurations)) {
1773 dev_err(pTAS2557->dev, "Firmware not loaded\n");
1774 nResult = 0;
1775 goto end;
1776 }
1778 if (nProgram >= pTAS2557->mpFirmware->mnPrograms) {
1779 dev_err(pTAS2557->dev, "TAS2557: Program %d doesn't exist\n",
1780 nProgram);
1781 nResult = 0;
1782 goto end;
1783 }
1785 if (nConfig < 0) {
1786 nConfiguration = 0;
1787 nSampleRate = pTAS2557->mnCurrentSampleRate;
1788 while (!bFound && (nConfiguration < pTAS2557->mpFirmware->mnConfigurations)) {
1789 if (pTAS2557->mpFirmware->mpConfigurations[nConfiguration].mnProgram == nProgram) {
1790 if (nSampleRate == 0) {
1791 bFound = true;
1792 dev_info(pTAS2557->dev, "find default configuration %d\n", nConfiguration);
1793 } else if (nSampleRate == pTAS2557->mpFirmware->mpConfigurations[nConfiguration].mnSamplingRate) {
1794 bFound = true;
1795 dev_info(pTAS2557->dev, "find matching configuration %d\n", nConfiguration);
1796 } else {
1797 nConfiguration++;
1798 }
1799 } else {
1800 nConfiguration++;
1801 }
1802 }
1803 if (!bFound) {
1804 dev_err(pTAS2557->dev,
1805 "Program %d, no valid configuration found for sample rate %d, ignore\n",
1806 nProgram, nSampleRate);
1807 nResult = 0;
1808 goto end;
1809 }
1810 } else {
1811 if (pTAS2557->mpFirmware->mpConfigurations[nConfig].mnProgram != nProgram) {
1812 dev_err(pTAS2557->dev, "%s, configuration program doesn't match\n", __func__);
1813 nResult = 0;
1814 goto end;
1815 }
1816 nConfiguration = nConfig;
1817 }
1819 pProgram = &(pTAS2557->mpFirmware->mpPrograms[nProgram]);
1820 if (pTAS2557->mbPowerUp) {
1821 dev_info(pTAS2557->dev,
1822 "device powered up, power down to load program %d (%s)\n",
1823 nProgram, pProgram->mpName);
1824 if (hrtimer_active(&pTAS2557->mtimer))
1825 hrtimer_cancel(&pTAS2557->mtimer);
1827 if (pProgram->mnAppMode == TAS2557_APP_TUNINGMODE)
1828 pTAS2557->enableIRQ(pTAS2557, false, false);
1830 nResult = tas2557_dev_load_data(pTAS2557, p_tas2557_shutdown_data);
1831 if (nResult < 0)
1832 goto end;
1833 }
1835 pTAS2557->hw_reset(pTAS2557);
1836 nResult = pTAS2557->write(pTAS2557, TAS2557_SW_RESET_REG, 0x01);
1837 if (nResult < 0)
1838 goto end;
1839 msleep(1);
1840 nResult = tas2557_load_default(pTAS2557);
1841 if (nResult < 0)
1842 goto end;
1844 dev_info(pTAS2557->dev, "load program %d (%s)\n", nProgram, pProgram->mpName);
1845 nResult = tas2557_load_data(pTAS2557, &(pProgram->mData), TAS2557_BLOCK_PGM_DEV_A);
1846 if (nResult < 0)
1847 goto end;
1848 pTAS2557->mnCurrentProgram = nProgram;
1850 nResult = tas2557_get_DAC_gain(pTAS2557, &nGain);
1851 if (nResult < 0)
1852 goto end;
1853 pTAS2557->mnDevGain = nGain;
1854 pTAS2557->mnDevCurrentGain = nGain;
1856 nResult = tas2557_load_coefficient(pTAS2557, -1, nConfiguration, false);
1857 if (nResult < 0)
1858 goto end;
1860 if (pTAS2557->mbPowerUp) {
1861 pTAS2557->clearIRQ(pTAS2557);
1862 dev_dbg(pTAS2557->dev, "device powered up, load startup\n");
1863 nResult = tas2557_dev_load_data(pTAS2557, p_tas2557_startup_data);
1864 if (nResult < 0)
1865 goto end;
1866 if (pProgram->mnAppMode == TAS2557_APP_TUNINGMODE) {
1867 nResult = tas2557_checkPLL(pTAS2557);
1868 if (nResult < 0) {
1869 nResult = tas2557_dev_load_data(pTAS2557, p_tas2557_shutdown_data);
1870 pTAS2557->mbPowerUp = false;
1871 goto end;
1872 }
1873 }
1874 dev_dbg(pTAS2557->dev, "device powered up, load unmute\n");
1875 nResult = tas2557_dev_load_data(pTAS2557, p_tas2557_unmute_data);
1876 if (nResult < 0)
1877 goto end;
1879 if (pProgram->mnAppMode == TAS2557_APP_TUNINGMODE) {
1880 pTAS2557->enableIRQ(pTAS2557, true, true);
1881 if (!hrtimer_active(&pTAS2557->mtimer)) {
1882 pTAS2557->mnDieTvReadCounter = 0;
1883 hrtimer_start(&pTAS2557->mtimer,
1884 ns_to_ktime((u64)LOW_TEMPERATURE_CHECK_PERIOD * NSEC_PER_MSEC), HRTIMER_MODE_REL);
1885 }
1886 }
1887 }
1889 end:
1891 if (nResult < 0) {
1892 if (pTAS2557->mnErrCode & (ERROR_DEVA_I2C_COMM | ERROR_PRAM_CRCCHK | ERROR_YRAM_CRCCHK))
1893 failsafe(pTAS2557);
1894 }
1895 return nResult;
1896 }
1898 int tas2557_set_calibration(struct tas2557_priv *pTAS2557, int nCalibration)
1899 {
1900 struct TCalibration *pCalibration = NULL;
1901 struct TConfiguration *pConfiguration;
1902 struct TProgram *pProgram;
1903 int nTmax = 0;
1904 bool bFound = false;
1905 int nResult = 0;
1907 if ((!pTAS2557->mpFirmware->mpPrograms)
1908 || (!pTAS2557->mpFirmware->mpConfigurations)) {
1909 dev_err(pTAS2557->dev, "Firmware not loaded\n\r");
1910 nResult = 0;
1911 goto end;
1912 }
1914 if (nCalibration == 0x00FF) {
1915 nResult = tas2557_load_calibration(pTAS2557, TAS2557_CAL_NAME);
1916 if (nResult < 0) {
1917 dev_info(pTAS2557->dev, "load new calibration file %s fail %d\n",
1918 TAS2557_CAL_NAME, nResult);
1919 goto end;
1920 }
1921 nCalibration = 0;
1922 }
1924 if (nCalibration >= pTAS2557->mpCalFirmware->mnCalibrations) {
1925 dev_err(pTAS2557->dev,
1926 "Calibration %d doesn't exist\n", nCalibration);
1927 nResult = 0;
1928 goto end;
1929 }
1931 pTAS2557->mnCurrentCalibration = nCalibration;
1932 if (pTAS2557->mbLoadConfigurationPrePowerUp)
1933 goto end;
1935 pCalibration = &(pTAS2557->mpCalFirmware->mpCalibrations[nCalibration]);
1936 pProgram = &(pTAS2557->mpFirmware->mpPrograms[pTAS2557->mnCurrentProgram]);
1937 pConfiguration = &(pTAS2557->mpFirmware->mpConfigurations[pTAS2557->mnCurrentConfiguration]);
1938 if (pProgram->mnAppMode == TAS2557_APP_TUNINGMODE) {
1939 if (pTAS2557->mbBypassTMax) {
1940 bFound = tas2557_find_Tmax_in_configuration(pTAS2557, pConfiguration, &nTmax);
1941 if (bFound && (nTmax == TAS2557_COEFFICIENT_TMAX)) {
1942 dev_dbg(pTAS2557->dev, "%s, config[%s] bypass load calibration\n",
1943 __func__, pConfiguration->mpName);
1944 goto end;
1945 }
1946 }
1948 dev_dbg(pTAS2557->dev, "%s, load calibration\n", __func__);
1949 nResult = tas2557_load_data(pTAS2557, &(pCalibration->mData), TAS2557_BLOCK_CFG_COEFF_DEV_A);
1950 if (nResult < 0)
1951 goto end;
1952 }
1954 end:
1955 if (nResult < 0) {
1956 tas2557_clear_firmware(pTAS2557->mpCalFirmware);
1957 nResult = tas2557_set_program(pTAS2557, pTAS2557->mnCurrentProgram, pTAS2557->mnCurrentConfiguration);
1958 }
1960 return nResult;
1961 }
1963 bool tas2557_get_Cali_prm_r0(struct tas2557_priv *pTAS2557, int *prm_r0)
1964 {
1965 struct TCalibration *pCalibration;
1966 struct TData *pData;
1967 int nReg;
1968 int nCali_Re;
1969 bool bFound = false;
1970 int nBlockType;
1972 if (!pTAS2557->mpCalFirmware->mnCalibrations) {
1973 dev_err(pTAS2557->dev, "%s, no calibration data\n", __func__);
1974 goto end;
1975 }
1977 if (pTAS2557->mnPGID == TAS2557_PG_VERSION_2P1)
1978 nReg = TAS2557_PG2P1_CALI_R0_REG;
1979 else
1980 nReg = TAS2557_PG1P0_CALI_R0_REG;
1982 nBlockType = TAS2557_BLOCK_CFG_COEFF_DEV_A;
1984 pCalibration = &(pTAS2557->mpCalFirmware->mpCalibrations[pTAS2557->mnCurrentCalibration]);
1985 pData = &(pCalibration->mData);
1987 bFound = tas2557_get_coefficient_in_data(pTAS2557, pData, nBlockType, nReg, &nCali_Re);
1989 end:
1991 if (bFound)
1992 *prm_r0 = nCali_Re;
1994 return bFound;
1995 }
1997 int tas2557_parse_dt(struct device *dev, struct tas2557_priv *pTAS2557)
1998 {
1999 struct device_node *np = dev->of_node;
2000 int rc = 0, ret = 0;
2001 unsigned int value;
2003 pTAS2557->mnResetGPIO = of_get_named_gpio(np, "ti,cdc-reset-gpio", 0);
2004 if (!gpio_is_valid(pTAS2557->mnResetGPIO)) {
2005 dev_err(pTAS2557->dev, "Looking up %s property in node %s failed %d\n",
2006 "ti,cdc-reset-gpio", np->full_name,
2007 pTAS2557->mnResetGPIO);
2008 ret = -EINVAL;
2009 goto end;
2010 } else
2011 dev_dbg(pTAS2557->dev, "ti,cdc-reset-gpio=%d\n", pTAS2557->mnResetGPIO);
2013 pTAS2557->mnGpioINT = of_get_named_gpio(np, "ti,irq-gpio", 0);
2014 if (!gpio_is_valid(pTAS2557->mnGpioINT))
2015 dev_err(pTAS2557->dev, "Looking up %s property in node %s failed %d\n",
2016 "ti,irq-gpio", np->full_name,
2017 pTAS2557->mnGpioINT);
2020 rc = of_property_read_u32(np, "ti,i2s-bits", &value);
2021 if (rc)
2022 dev_err(pTAS2557->dev, "Looking up %s property in node %s failed %d\n",
2023 "ti,i2s-bits", np->full_name, rc);
2024 else
2025 pTAS2557->mnI2SBits = value;
2027 rc = of_property_read_u32(np, "ti,bypass-tmax", &value);
2028 if (rc)
2029 dev_err(pTAS2557->dev, "Looking up %s property in node %s failed %d\n",
2030 "ti,bypass-tmax", np->full_name, rc);
2031 else
2032 pTAS2557->mbBypassTMax = (value > 0);
2034 end:
2036 return ret;
2037 }
2039 MODULE_AUTHOR("Texas Instruments Inc.");
2040 MODULE_DESCRIPTION("TAS2557 common functions for Android Linux");
2041 MODULE_LICENSE("GPL v2");