1e674083efca086db07cf7e288bda8318fe6ff49
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 ** You should have received a copy of the GNU General Public License along with
14 ** this program; if not, write to the Free Software Foundation, Inc., 51 Franklin
15 ** Street, Fifth Floor, Boston, MA 02110-1301, USA.
16 **
17 ** File:
18 ** tas2555.c
19 **
20 ** Description:
21 ** functions for configurating TAS2555 Android device
22 **
23 ** =============================================================================
24 */
26 #include "tas2557.h"
27 #include "system.h"
29 #include <sys/types.h>
30 #include <stdio.h>
31 #include <time.h>
32 #include <unistd.h>
33 #include <stdlib.h>
34 #include <sys/stat.h>
35 #include <fcntl.h>
36 #include <sys/ioctl.h>
37 #include <string.h>
39 #define TILOAD_NODE "/dev/tiload_node"
41 static int gTILoad = 0;
42 static int gBinFile = 0;
44 #define MAX_BIN_SIZE 2048
45 static char gpBin[MAX_BIN_SIZE];
46 static unsigned int gnBinIndex = 0;
47 static unsigned int gnBinBlockIndex = 0;
48 static char gpDevABlock[MAX_BIN_SIZE/2];
49 static unsigned int gnDevABlockIndex = 0;
50 static char gpDevBBlock[MAX_BIN_SIZE/2];
51 static unsigned int gnDevBBlockIndex = 0;
52 static unsigned char gnDevA;
53 static unsigned char gnDevB;
54 static unsigned char gnDev;
56 static void tas2557_check_node(void);
58 void tas2557_mixer_command(char *pCommand, int nData)
59 {
60 char *pMixer[] = {AUDIO_MIXER, pCommand, "0", NULL};
61 char *pEnv[] = {NULL};
63 char pData[16];
65 printf("TAS2555 mixer command %s = %d.\n\r", pCommand, nData);
67 sprintf(pData, "%d", nData);
68 pMixer[2] = pData;
70 if (0 == (fork()))
71 {
72 if (execve(AUDIO_MIXER, pMixer, pEnv) == -1)
73 {
74 printf("factorytest: Can't find mixer. Please install %s. \n\r", AUDIO_MIXER);
75 exit(-1);
76 }
77 }
79 sys_delay(500);
80 }
82 void tas2557_load_configuration(int nConfiguration)
83 {
84 tas2557_check_node();
86 ioctl(gTILoad, TILOAD_IOCTL_SET_CONFIG, &nConfiguration);
87 sys_delay(500);
88 }
90 void tas2557_load_calibration(int nCalibration)
91 {
92 tas2557_check_node();
94 ioctl(gTILoad, TILOAD_IOCTL_SET_CALIBRATION, &nCalibration);
95 sys_delay(500);
96 }
98 static void tas2557_check_node(void)
99 {
100 if (gTILoad) return;
102 gTILoad = open(TILOAD_NODE, O_RDWR);
104 if (gTILoad < 0)
105 {
106 printf("factorytest: Can't find tiload. Please create %s. \n\r", TILOAD_NODE);
107 exit(-1);
108 }
110 printf("factorytest: %s handle = %d\n\r", TILOAD_NODE, gTILoad);
111 }
113 uint8_t tas2557_get_PGID(void)
114 {
115 unsigned char pPageZero[] = {0x00, 0x00};
116 unsigned char pBook[] = {0x7F, 0x00};
117 unsigned char pPage[] = {0x00, 0x00};
118 unsigned char pData[] = {0x03, 0x00, 0x00, 0x00, 0x00};
120 tas2557_check_node();
122 write(gTILoad, pPageZero, 2);
123 write(gTILoad, pBook, 2);
124 write(gTILoad, pPage, 2);
125 read(gTILoad, pData, 1);
127 return pData[0];
128 }
130 uint32_t tas2557_coeff_read(uint8_t book, uint8_t page, uint8_t reg)
131 {
132 unsigned char pPageZero[] = {0x00, 0x00};
133 unsigned char pBook[] = {0x7F, book};
134 unsigned char pPage[] = {0x00, page};
135 unsigned char pData[] = {reg, 0x00, 0x00, 0x00, 0x00};
137 tas2557_check_node();
139 write(gTILoad, pPageZero, 2);
140 write(gTILoad, pBook, 2);
141 write(gTILoad, pPage, 2);
142 read(gTILoad, pData, 4);
144 return ((pData[0] << 24) | (pData[1] << 16) | (pData[2] << 8) | (pData[3]));
145 }
147 uint32_t tas2557_switch_device(uint8_t i2cslave)
148 {
149 int addr = i2cslave;
151 tas2557_check_node();
153 gnDev = i2cslave;
155 ioctl(gTILoad, TILOAD_IOCTL_SET_CHL, &addr);
157 return 0;
158 }
160 void tas2557_coeff_write(uint8_t book, uint8_t page, uint8_t reg, uint32_t data)
161 {
162 unsigned int nByte;
164 if (gBinFile) // if the bin file is open, write the coefficients to the bin file
165 {
166 if(gnDev == gnDevA){
167 unsigned int index = gnDevABlockIndex*4;
168 gpDevABlock[index] = 0;
169 gpDevABlock[index + 1] = 4;
170 gpDevABlock[index + 2] = 0x85;
171 gpDevABlock[index + 4] = book;
172 gpDevABlock[index + 5] = page;
173 gpDevABlock[index + 6] = reg;
175 for (nByte = 0; nByte < 4; nByte++)
176 {
177 gpDevABlock[index + 7 + nByte] = (data >> ((3 - nByte) * 8)) & 0xFF;
178 }
180 gnDevABlockIndex += 3;
181 }
182 else if(gnDev == gnDevB)
183 {
184 unsigned int index = gnDevBBlockIndex*4;
185 gpDevBBlock[index] = 0;
186 gpDevBBlock[index + 1] = 4;
187 gpDevBBlock[index + 2] = 0x85;
188 gpDevBBlock[index + 4] = book;
189 gpDevBBlock[index + 5] = page;
190 gpDevBBlock[index + 6] = reg;
192 for (nByte = 0; nByte < 4; nByte++)
193 {
194 gpDevBBlock[index + 7 + nByte] = (data >> ((3 - nByte) * 8)) & 0xFF;
195 }
197 gnDevBBlockIndex += 3;
198 }
199 }
200 else
201 {
202 unsigned char pPageZero[] = {0x00, 0x00};
203 unsigned char pBook[] = {0x7F, book};
204 unsigned char pPage[] = {0x00, page};
205 unsigned char pData[] = {reg, (data & 0xFF000000) >> 24, (data & 0x00FF0000) >> 16, (data & 0x0000FF00) >> 8, data & 0x000000FF};
207 tas2557_check_node();
209 write(gTILoad, pPageZero, 2);
210 write(gTILoad, pBook, 2);
211 write(gTILoad, pPage, 2);
212 write(gTILoad, pData, 5);
214 pBook[1] = 0x8C;
215 pPage[1] = 0x19;
217 pData[0] = 0x7C;
218 pData[1] = 0x00;
219 pData[2] = 0x00;
220 pData[3] = 0x00;
221 pData[4] = 0x01;
223 write(gTILoad, pPageZero, 2);
224 write(gTILoad, pBook, 2);
225 write(gTILoad, pPage, 2);
226 write(gTILoad, pData, 5);
228 pBook[1] = 0x00;
229 pPage[1] = 0x35;
231 pData[0] = 0x2c;
232 pData[1] = 0x00;
233 pData[2] = 0x00;
234 pData[3] = 0x00;
235 pData[4] = 0x01;
237 write(gTILoad, pPageZero, 2);
238 write(gTILoad, pBook, 2);
239 write(gTILoad, pPage, 2);
240 write(gTILoad, pData, 5);
241 }
242 }
244 void tas2557_save_cal(TFTCConfiguration *pFTCC,
245 double dev_a_re, uint32_t dev_a_rms_pow, uint32_t dev_a_t_limit,
246 double dev_b_re, uint32_t dev_b_rms_pow, uint32_t dev_b_t_limit,
247 double t_cal, uint32_t nResult, char * pFileName)
248 {
249 printf("TAS2557 calibration values:\n\r");
250 printf(" DevA Re = %1.2f Ohm\n\r", dev_a_re);
251 printf(" DevA rms_pow = 0x%08X\n\r", dev_a_rms_pow);
252 printf(" DevA t_limit = 0x%08X\n\r", dev_a_t_limit);
253 printf(" DevB Re = %1.2f Ohm\n\r", dev_b_re);
254 printf(" DevB rms_pow = 0x%08X\n\r", dev_b_rms_pow);
255 printf(" DevB t_limit = 0x%08X\n\r", dev_b_t_limit);
257 if((nResult & RE1_CHK_MSK) == RESULT_PASS){
258 printf(" SPK A calibration success! \n\r");
259 }else {
260 if(nResult & RE1_FAIL_HI)
261 printf(" SPK A Calibration fail : Re is too high (limit: %1.2f).\n\r", pFTCC->nTSpkCharDevA.nReHi);
262 else
263 printf(" SPK A Calibration fail : Re is too low (limit: %1.2f).\n\r", pFTCC->nTSpkCharDevA.nReLo);
264 }
266 if((nResult & RE2_CHK_MSK) == RESULT_PASS){
267 printf(" SPK B calibration success! \n\r");
268 }else {
269 if(nResult & RE2_FAIL_HI)
270 printf(" SPK B Calibration fail : Re is too high (limit: %1.2f).\n\r", pFTCC->nTSpkCharDevB.nReHi);
271 else
272 printf(" SPK B Calibration fail : Re is too low (limit: %1.2f).\n\r", pFTCC->nTSpkCharDevB.nReLo);
273 }
275 FILE *pFile = fopen(pFileName, "w+");
277 fprintf(pFile, "DevA Re = %1.2f\n\r", dev_a_re);
278 fprintf(pFile, "DevA rms_pow = 0x%08X\n\r", dev_a_rms_pow);
279 fprintf(pFile, "DevA t_limit = 0x%08X\n\r", dev_a_t_limit);
280 fprintf(pFile, "DevB Re = %1.2f\n\r", dev_b_re);
281 fprintf(pFile, "DevB rms_pow = 0x%08X\n\r", dev_b_rms_pow);
282 fprintf(pFile, "DevB t_limit = 0x%08X\n\r", dev_b_t_limit);
283 fprintf(pFile, "Ambient temperature = %2.2f\n\r\n\r", t_cal);
284 fprintf(pFile, "Result = 0x%x\n\r\n\r", nResult);
286 fclose(pFile);
287 }
289 #define DDC_DESCRIPTION "Calibration Data File for TAS2557 Dual Mono"
290 #define CALIBRATION_DESCRIPTION "Calibration snapshot for TAS2557 Dual Mono"
291 #define DATA_DESCRIPTION "data blocks for TAS2557 Dual Mono FTCc"
293 void tas2557_open_bin(char * pFileName, unsigned char dev_a, unsigned char dev_b)
294 {
295 time_t timestamp;
297 gnDevA = dev_a;
298 gnDevB = dev_b;
300 gBinFile = open(pFileName, O_RDWR | O_CREAT, S_IRUSR | S_IWUSR | S_IROTH | S_IWOTH);
302 gnBinIndex = 0;
303 memset(gpBin, 0, MAX_BIN_SIZE);
304 memset(gpDevABlock, 0, MAX_BIN_SIZE/2);
305 gnDevABlockIndex = 0;
306 memset(gpDevBBlock, 0, MAX_BIN_SIZE/2);
307 gnDevBBlockIndex = 0;
309 //magic number
310 gpBin[gnBinIndex++] = '5';
311 gpBin[gnBinIndex++] = '5';
312 gpBin[gnBinIndex++] = '5';
313 gpBin[gnBinIndex++] = '2';
315 gnBinIndex += 4; //bypass size int
316 gnBinIndex += 4; //bypass checksum int
317 gnBinIndex += 4; //bypass PPC3 version int
318 gnBinIndex += 4; //bypass DSP version int
320 gpBin[gnBinIndex++] = 0;
321 gpBin[gnBinIndex++] = 0;
322 gpBin[gnBinIndex++] = 1;
323 gpBin[gnBinIndex++] = 0; //driver version 0x00000100
325 time(×tamp);
326 gpBin[gnBinIndex++] = (unsigned char)((timestamp&0xff000000)>>24);
327 gpBin[gnBinIndex++] = (unsigned char)((timestamp&0x00ff0000)>>16);;
328 gpBin[gnBinIndex++] = (unsigned char)((timestamp&0x0000ff00)>>8);;
329 gpBin[gnBinIndex++] = (unsigned char)((timestamp&0x000000ff));;
331 strcpy(&gpBin[gnBinIndex], "Calibration Data File"); //DDC name
332 gnBinIndex += 64;
334 strcpy(&gpBin[gnBinIndex], DDC_DESCRIPTION);
335 gnBinIndex += strlen(DDC_DESCRIPTION) + 1;
337 gnBinIndex += 4; //device family index
339 gpBin[gnBinIndex++] = 0; //device index
340 gpBin[gnBinIndex++] = 0; //device index
341 gpBin[gnBinIndex++] = 0; //device index
342 gpBin[gnBinIndex++] = 3; //device index, TAS2557 Dual Mono
344 gnBinIndex +=
345 2 + //num PLL index
346 0 + //array PLL index
347 2 + //num programs index
348 0 + //array programs index
349 2 + //num configurations index
350 0; //array configurations index
352 gpBin[gnBinIndex++] = 0x00;
353 gpBin[gnBinIndex++] = 0x01; // one calibration data block
355 strcpy(&gpBin[gnBinIndex], "Calibration snapshot");
356 gnBinIndex += 64;
357 strcpy(&gpBin[gnBinIndex], CALIBRATION_DESCRIPTION);
358 gnBinIndex += strlen(CALIBRATION_DESCRIPTION) + 1;
360 gpBin[gnBinIndex++] = 0x00; // compatible program = smart amp (index 0)
361 gpBin[gnBinIndex++] = 0x00; // compatible configuration
363 strcpy(&gpBin[gnBinIndex], "Calibration Data");
364 gnBinIndex += 64;
365 strcpy(&gpBin[gnBinIndex], DATA_DESCRIPTION);
366 gnBinIndex += strlen(DATA_DESCRIPTION) + 1;
368 gpBin[gnBinIndex++] = 0x00; //
369 gpBin[gnBinIndex++] = 2; // two blocks
371 gpDevABlock[0] = 0;
372 gpDevABlock[1] = 0;
373 gpDevABlock[2] = 0;
374 gpDevABlock[3] = 0x03; //o COEFF_DEVICE_A – 0x03
375 gnDevABlockIndex = 2;
377 gpDevBBlock[0] = 0;
378 gpDevBBlock[1] = 0;
379 gpDevBBlock[2] = 0;
380 gpDevBBlock[3] = 0x0a; //o COEFF_DEVICE_B – 0x0a
381 gnDevBBlockIndex = 2;
382 }
384 void tas2557_close_bin(void)
385 {
386 unsigned int nCommands;
387 unsigned char pCommit[] =
388 {
389 0x00, 0x04, 0x85, 0x00,
390 0x8C, 0x19, 0x7C, 0x00,
391 0x00, 0x00, 0x01, 0x00,
392 0x00, 0x04, 0x85, 0x00,
393 0x00, 0x35, 0x2c, 0x00,
394 0x00, 0x00, 0x01, 0x00
395 };
397 // write the commit sequence
398 memcpy(&gpDevABlock[gnDevABlockIndex*4], pCommit, 24);
399 gnDevABlockIndex += 6;
401 memcpy(&gpDevBBlock[gnDevBBlockIndex*4], pCommit, 24);
402 gnDevBBlockIndex += 6;
404 // write number of commands for calibration block
405 gpDevABlock[4] = ((gnDevABlockIndex-2) & 0xFF000000) >> 24;
406 gpDevABlock[5] = ((gnDevABlockIndex-2) & 0x00FF0000) >> 16;
407 gpDevABlock[6] = ((gnDevABlockIndex-2) & 0x0000FF00) >> 8;
408 gpDevABlock[7] = ((gnDevABlockIndex-2) & 0x000000FF);
410 gpDevBBlock[4] = ((gnDevBBlockIndex-2) & 0xFF000000) >> 24;
411 gpDevBBlock[5] = ((gnDevBBlockIndex-2) & 0x00FF0000) >> 16;
412 gpDevBBlock[6] = ((gnDevBBlockIndex-2) & 0x0000FF00) >> 8;
413 gpDevBBlock[7] = ((gnDevBBlockIndex-2) & 0x000000FF);
415 memcpy(&gpBin[gnBinIndex], gpDevABlock, gnDevABlockIndex*4);
416 gnBinIndex += (gnDevABlockIndex*4);
418 memcpy(&gpBin[gnBinIndex], gpDevBBlock, gnDevBBlockIndex*4);
419 gnBinIndex += (gnDevBBlockIndex*4);
421 // write bin file size
422 gpBin[4] = (gnBinIndex & 0xFF000000) >> 24;
423 gpBin[5] = (gnBinIndex & 0x00FF0000) >> 16;
424 gpBin[6] = (gnBinIndex & 0x0000FF00) >> 8;
425 gpBin[7] = (gnBinIndex & 0x000000FF);
427 write(gBinFile, gpBin, gnBinIndex);
428 close(gBinFile);
430 gBinFile = 0;
431 }
433 // -----------------------------------------------------------------------------
434 // check_spk_bounds
435 // -----------------------------------------------------------------------------
436 // Description:
437 // Checks if speaker paramters are within bounds.
438 // -----------------------------------------------------------------------------
439 uint32_t check_spk_bounds(TFTCConfiguration *pFTCC, double re1, double re2)
440 {
441 uint32_t result = RESULT_PASS;
443 if(re1>pFTCC->nTSpkCharDevA.nReHi)
444 result |= RE1_FAIL_HI;
445 if(re1<pFTCC->nTSpkCharDevA.nReLo)
446 result |= RE1_FAIL_LO;
448 if(re2>pFTCC->nTSpkCharDevB.nReHi)
449 result |= RE2_FAIL_HI;
450 if(re2<pFTCC->nTSpkCharDevB.nReLo)
451 result |= RE2_FAIL_LO;
453 return result;
454 }
456 void tas2557_ftc_release(void)
457 {
458 if (gTILoad > 0) {
459 close(gTILoad);
460 gTILoad = 0;
461 }
462 }