1779380caa08eecfb2c7eb99905e6358ae89e860
[tas2557sw-android/tas2557dm-ftc.git] / tas2557.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 ** 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("TAS2557 mixer command %s = %d.\n\r", pCommand, nData);
67         sprintf(pData, "%d", nData);
68         pMixer[2] = pData;
69         
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_calibration(int nCalibration)
83 {
84         tas2557_check_node();
85         
86         ioctl(gTILoad, TILOAD_IOCTL_SET_CALIBRATION, &nCalibration);
87         sys_delay(500);
88 }
90 static void tas2557_check_node(void)
91 {
92         if (gTILoad) return;
94         gTILoad = open(TILOAD_NODE, O_RDWR);
96         if (gTILoad < 0)
97         {
98                 printf("factorytest: Can't find tiload. Please create %s. \n\r", TILOAD_NODE);
99                 exit(-1);
100         }
102         printf("factorytest: %s handle = %d\n\r", TILOAD_NODE, gTILoad);
105 uint8_t tas2557_get_PGID(void)
107         unsigned char pPageZero[] = {0x00, 0x00};
108         unsigned char pBook[] = {0x7F, 0x00};
109         unsigned char pPage[] = {0x00, 0x00};
110         unsigned char pData[] = {0x03, 0x00, 0x00, 0x00, 0x00};
112         tas2557_check_node();
114         write(gTILoad, pPageZero, 2);
115         write(gTILoad, pBook, 2);
116         write(gTILoad, pPage, 2);
117         read(gTILoad, pData, 1);
119         return pData[0];
122 uint32_t tas2557_coeff_read(uint8_t book, uint8_t page, uint8_t reg)
124         unsigned char pPageZero[] = {0x00, 0x00};
125         unsigned char pBook[] = {0x7F, book};
126         unsigned char pPage[] = {0x00, page};
127         unsigned char pData[] = {reg, 0x00, 0x00, 0x00, 0x00};
129         tas2557_check_node();
131         write(gTILoad, pPageZero, 2);
132         write(gTILoad, pBook, 2);
133         write(gTILoad, pPage, 2);
134         read(gTILoad, pData, 4);
136         return ((pData[0] << 24) | (pData[1] << 16) | (pData[2] << 8) | (pData[3]));
139 uint32_t tas2557_switch_device(uint8_t i2cslave)
141         int addr = i2cslave;
142         
143         tas2557_check_node();
145         gnDev = i2cslave;
146         
147         ioctl(gTILoad, TILOAD_IOCTL_SET_CHL, &addr);
148         
149         return 0;
152 void tas2557_coeff_write(uint8_t book, uint8_t page, uint8_t reg, uint32_t data)
154         unsigned int nByte;
156         if (gBinFile) // if the bin file is open, write the coefficients to the bin file
157         {
158                 if(gnDev == gnDevA){
159                         unsigned int index = gnDevABlockIndex*4;
160                         gpDevABlock[index] = 0;
161                         gpDevABlock[index + 1] = 4;
162                         gpDevABlock[index + 2] = 0x85;
163                         gpDevABlock[index + 4] = book;
164                         gpDevABlock[index + 5] = page;
165                         gpDevABlock[index + 6] = reg;
166                         
167                         for (nByte = 0; nByte < 4; nByte++)
168                         {
169                                 gpDevABlock[index + 7 + nByte] = (data >> ((3 - nByte) * 8)) & 0xFF;
170                         }
171                         
172                         gnDevABlockIndex += 3;                  
173                 }
174                 else if(gnDev == gnDevB)
175                 {
176                         unsigned int index = gnDevBBlockIndex*4;
177                         gpDevBBlock[index] = 0;
178                         gpDevBBlock[index + 1] = 4;
179                         gpDevBBlock[index + 2] = 0x85;
180                         gpDevBBlock[index + 4] = book;
181                         gpDevBBlock[index + 5] = page;
182                         gpDevBBlock[index + 6] = reg;
183                         
184                         for (nByte = 0; nByte < 4; nByte++)
185                         {
186                                 gpDevBBlock[index + 7 + nByte] = (data >> ((3 - nByte) * 8)) & 0xFF;
187                         }
188                         
189                         gnDevBBlockIndex += 3;  
190                 }               
191         }
192         else
193         {
194                 unsigned char pPageZero[] = {0x00, 0x00};
195                 unsigned char pBook[] = {0x7F, book};
196                 unsigned char pPage[] = {0x00, page};
197                 unsigned char pData[] = {reg, (data & 0xFF000000) >> 24, (data & 0x00FF0000) >> 16, (data & 0x0000FF00) >> 8, data & 0x000000FF};
199                 tas2557_check_node();
201                 write(gTILoad, pPageZero, 2);
202                 write(gTILoad, pBook, 2);
203                 write(gTILoad, pPage, 2);
204                 write(gTILoad, pData, 5);
206                 pBook[1] = 0x8C;
207                 pPage[1] = 0x19;
209                 pData[0] = 0x7C;
210                 pData[1] = 0x00;
211                 pData[2] = 0x00;
212                 pData[3] = 0x00;
213                 pData[4] = 0x01;
215                 write(gTILoad, pPageZero, 2);
216                 write(gTILoad, pBook, 2);
217                 write(gTILoad, pPage, 2);
218                 write(gTILoad, pData, 5);
220                 pBook[1] = 0x00;
221                 pPage[1] = 0x35;
223                 pData[0] = 0x2c;
224                 pData[1] = 0x00;
225                 pData[2] = 0x00;
226                 pData[3] = 0x00;
227                 pData[4] = 0x01;
229                 write(gTILoad, pPageZero, 2);
230                 write(gTILoad, pBook, 2);
231                 write(gTILoad, pPage, 2);
232                 write(gTILoad, pData, 5);
233         }
236 void tas2557_save_cal(struct TFTCConfiguration *pFTCC, 
237         double dev_a_re, uint32_t dev_a_rms_pow, uint32_t dev_a_t_limit, 
238         double dev_b_re, uint32_t dev_b_rms_pow, uint32_t dev_b_t_limit, 
239         double t_cal,  uint32_t nResult, char * pFileName)
241         printf("TAS2557 calibration values:\n\r");
242         printf("    DevA Re = %1.2f Ohm\n\r", dev_a_re);
243         printf("    DevA rms_pow       = 0x%08X\n\r", dev_a_rms_pow);
244         printf("    DevA t_limit       = 0x%08X\n\r", dev_a_t_limit);
245         printf("    DevB Re = %1.2f Ohm\n\r", dev_b_re);
246         printf("    DevB rms_pow       = 0x%08X\n\r", dev_b_rms_pow);
247         printf("    DevB t_limit       = 0x%08X\n\r", dev_b_t_limit);
249         if((nResult & RE1_CHK_MSK) == RESULT_PASS)
250                 printf(" SPK A calibration success! \n\r");
251         else {
252                 if(nResult & RE1_FAIL_HI)
253                         printf(" SPK A Calibration fail : Re is too high (limit: %1.2f).\n\r", pFTCC->nTSpkCharDevA.nReHi);
254                 else
255                         printf(" SPK A Calibration fail : Re is too low (limit: %1.2f).\n\r", pFTCC->nTSpkCharDevA.nReLo);
256         }
257         
258         if((nResult & RE2_CHK_MSK) == RESULT_PASS){
259                 printf(" SPK B calibration success! \n\r");
260         }else {
261                 if(nResult & RE2_FAIL_HI)
262                         printf(" SPK B Calibration fail : Re is too high (limit: %1.2f).\n\r", pFTCC->nTSpkCharDevB.nReHi);
263                 else
264                         printf(" SPK B Calibration fail : Re is too low (limit: %1.2f).\n\r", pFTCC->nTSpkCharDevB.nReLo);
265         }
266         
267         FILE *pFile = fopen(pFileName, "w+");
268         
269         fprintf(pFile, "DevA Re = %1.2f\n\r", dev_a_re);
270         fprintf(pFile, "DevA rms_pow       = 0x%08X\n\r", dev_a_rms_pow);
271         fprintf(pFile, "DevA t_limit       = 0x%08X\n\r", dev_a_t_limit);
272         fprintf(pFile, "DevB Re = %1.2f\n\r", dev_b_re);
273         fprintf(pFile, "DevB rms_pow       = 0x%08X\n\r", dev_b_rms_pow);
274         fprintf(pFile, "DevB t_limit       = 0x%08X\n\r", dev_b_t_limit);       
275         fprintf(pFile, "Ambient temperature = %2.2f\n\r\n\r", t_cal);
276         fprintf(pFile, "Result = 0x%x\n\r\n\r", nResult);
278         fclose(pFile);
281 #define DDC_DESCRIPTION "Calibration Data File for TAS2557 Dual Mono"
282 #define CALIBRATION_DESCRIPTION "Calibration snapshot for TAS2557 Dual Mono"
283 #define DATA_DESCRIPTION "data blocks for TAS2557 Dual Mono FTCc"
285 void tas2557_open_bin(char * pFileName, unsigned char dev_a, unsigned char dev_b)
287         time_t timestamp; 
288         
289         gnDevA = dev_a;
290         gnDevB = dev_b;
291         
292         gBinFile = open(pFileName, O_RDWR | O_CREAT, S_IRUSR | S_IWUSR | S_IROTH | S_IWOTH);
294         gnBinIndex = 0;
295         memset(gpBin, 0, MAX_BIN_SIZE);
296         memset(gpDevABlock, 0, MAX_BIN_SIZE/2);
297         gnDevABlockIndex = 0;
298         memset(gpDevBBlock, 0, MAX_BIN_SIZE/2);
299         gnDevBBlockIndex = 0;
301         //magic number
302         gpBin[gnBinIndex++] = '5';
303         gpBin[gnBinIndex++] = '5';
304         gpBin[gnBinIndex++] = '5';
305         gpBin[gnBinIndex++] = '2';
307         gnBinIndex += 4;        /* bypass size int */
308         gnBinIndex += 4;        /* bypass checksum int */
309         gnBinIndex += 4;        /* bypass PPC3 version int */
310         gnBinIndex += 4;        /* bypass DSP version int */
312         gpBin[gnBinIndex++] = 0;
313         gpBin[gnBinIndex++] = 0;
314         gpBin[gnBinIndex++] = 1;
315         gpBin[gnBinIndex++] = 0; /* driver version 0x00000100 */
317         time(&timestamp);
318         gpBin[gnBinIndex++] = (unsigned char)((timestamp&0xff000000)>>24);
319         gpBin[gnBinIndex++] = (unsigned char)((timestamp&0x00ff0000)>>16);;
320         gpBin[gnBinIndex++] = (unsigned char)((timestamp&0x0000ff00)>>8);;
321         gpBin[gnBinIndex++] = (unsigned char)((timestamp&0x000000ff));;
323         strcpy(&gpBin[gnBinIndex], "Calibration Data File");    /* DDC name */
324         gnBinIndex += 64;
326         strcpy(&gpBin[gnBinIndex], DDC_DESCRIPTION);
327         gnBinIndex += strlen(DDC_DESCRIPTION) + 1;
329         gnBinIndex += 4; /* device family index */
331         gpBin[gnBinIndex++] = 0; /* device index */
332         gpBin[gnBinIndex++] = 0; /* device index */
333         gpBin[gnBinIndex++] = 0; /* device index */
334         gpBin[gnBinIndex++] = 3; //device index, TAS2557 Dual Mono
336         gnBinIndex +=
337                 2 +     /* num PLL index */
338                 0 +     /* array PLL index */
339                 2 +     /* num programs index */
340                 0 +     /* array programs index */
341                 2 +     /* num configurations index */
342                 0;      /* array configurations index */
344         gpBin[gnBinIndex++] = 0x00;
345         gpBin[gnBinIndex++] = 0x01; /* one calibration data block */
347         strcpy(&gpBin[gnBinIndex], "Calibration snapshot");
348         gnBinIndex += 64;
349         strcpy(&gpBin[gnBinIndex], CALIBRATION_DESCRIPTION);
350         gnBinIndex += strlen(CALIBRATION_DESCRIPTION) + 1;
352         gpBin[gnBinIndex++] = 0x00; /* compatible program = smart amp (index 0) */
353         gpBin[gnBinIndex++] = 0x00; /* compatible configuration */
355         strcpy(&gpBin[gnBinIndex], "Calibration Data");
356         gnBinIndex += 64;
357         strcpy(&gpBin[gnBinIndex], DATA_DESCRIPTION);
358         gnBinIndex += strlen(DATA_DESCRIPTION) + 1;
360         gpBin[gnBinIndex++] = 0x00; 
361         gpBin[gnBinIndex++] = 2;        // two blocks
363         gpDevABlock[0] = 0;
364         gpDevABlock[1] = 0;
365         gpDevABlock[2] = 0;
366         gpDevABlock[3] = 0x03;  /* COEFF_DEVICE_A – 0x03 */
367         gnDevABlockIndex = 2;
368         
369         gpDevBBlock[0] = 0;
370         gpDevBBlock[1] = 0;
371         gpDevBBlock[2] = 0;
372         gpDevBBlock[3] = 0x0a;  //o     COEFF_DEVICE_B – 0x0a
373         gnDevBBlockIndex = 2;
376 void tas2557_close_bin(void)
378         unsigned int nCommands;
379         unsigned char pCommit[] = {
380                 0x00, 0x04, 0x85, 0x00,
381                 0x8C, 0x19, 0x7C, 0x00,
382                 0x00, 0x00, 0x01, 0x00,
383                 0x00, 0x04, 0x85, 0x00,
384                 0x00, 0x35, 0x2c, 0x00,
385                 0x00, 0x00, 0x01, 0x00
386         };
388         /* write the commit sequence */
389         memcpy(&gpDevABlock[gnDevABlockIndex*4], pCommit, 24);
390         gnDevABlockIndex += 6;
391         
392         memcpy(&gpDevBBlock[gnDevBBlockIndex*4], pCommit, 24);
393         gnDevBBlockIndex += 6;
394         
395         /* write number of commands for calibration block */
396         gpDevABlock[4] = ((gnDevABlockIndex-2) & 0xFF000000) >> 24;
397         gpDevABlock[5] = ((gnDevABlockIndex-2) & 0x00FF0000) >> 16;
398         gpDevABlock[6] = ((gnDevABlockIndex-2) & 0x0000FF00) >> 8;
399         gpDevABlock[7] = ((gnDevABlockIndex-2) & 0x000000FF);
400                 
401         gpDevBBlock[4] = ((gnDevBBlockIndex-2) & 0xFF000000) >> 24;
402         gpDevBBlock[5] = ((gnDevBBlockIndex-2) & 0x00FF0000) >> 16;
403         gpDevBBlock[6] = ((gnDevBBlockIndex-2) & 0x0000FF00) >> 8;
404         gpDevBBlock[7] = ((gnDevBBlockIndex-2) & 0x000000FF);
405         
406         memcpy(&gpBin[gnBinIndex], gpDevABlock, gnDevABlockIndex*4);
407         gnBinIndex += (gnDevABlockIndex*4);
408         
409         memcpy(&gpBin[gnBinIndex], gpDevBBlock, gnDevBBlockIndex*4);
410         gnBinIndex += (gnDevBBlockIndex*4);
411         
412         /* write bin file size */
413         gpBin[4] = (gnBinIndex & 0xFF000000) >> 24;
414         gpBin[5] = (gnBinIndex & 0x00FF0000) >> 16;
415         gpBin[6] = (gnBinIndex & 0x0000FF00) >> 8;
416         gpBin[7] = (gnBinIndex & 0x000000FF);
418         write(gBinFile, gpBin, gnBinIndex);
419         close(gBinFile);
421         gBinFile = 0;
424 // ----------------------------------------------------------------------------- 
425 // check_spk_bounds 
426 // ----------------------------------------------------------------------------- 
427 // Description: 
428 //      Checks if speaker paramters are within bounds. 
429 // ----------------------------------------------------------------------------- 
430 uint32_t check_spk_bounds(struct TFTCConfiguration *pFTCC, double re1, double re2) 
431
432         uint32_t result = RESULT_PASS; 
434         if(re1>pFTCC->nTSpkCharDevA.nReHi) 
435                 result |= RE1_FAIL_HI; 
436         if(re1<pFTCC->nTSpkCharDevA.nReLo) 
437                 result |= RE1_FAIL_LO; 
438    
439     if(re2>pFTCC->nTSpkCharDevB.nReHi) 
440         result |= RE2_FAIL_HI; 
441     if(re2<pFTCC->nTSpkCharDevB.nReLo) 
442         result |= RE2_FAIL_LO; 
444         return result; 
445
447 void tas2557_ftc_release(void)
449         if (gTILoad > 0) {
450                 close(gTILoad);
451                 gTILoad = 0;
452         }