update FTC to v1.0.0.2, add ftc-stop
[tas2557sw-android/tas2557-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 unsigned char gnDevA;
51 static unsigned char gnDev;
53 static void tas2557_check_node(void);
55 void tas2557_mixer_command(char *pCommand, int nData)
56 {
57         char *pMixer[] = {AUDIO_MIXER, pCommand, "0", NULL};
58         char *pEnv[] = {NULL};
60         char pData[16];
62         printf("TAS2557 mixer command %s = %d.\n\r", pCommand, nData);
64         sprintf(pData, "%d", nData);
65         pMixer[2] = pData;
66         
67         if (0 == (fork()))
68         {
69                 if (execve(AUDIO_MIXER, pMixer, pEnv) == -1)
70                 {
71                         printf("factorytest: Can't find mixer. Please install %s. \n\r", AUDIO_MIXER);
72                         exit(-1);
73                 }
74         }
76         sys_delay(500);
77 }
79 void tas2557_load_calibration(int nCalibration)
80 {
81         tas2557_check_node();
82         
83         ioctl(gTILoad, TILOAD_IOCTL_SET_CALIBRATION, &nCalibration);
84         sys_delay(500);
85 }
87 static void tas2557_check_node(void)
88 {
89         if (gTILoad) return;
91         gTILoad = open(TILOAD_NODE, O_RDWR);
93         if (gTILoad < 0)
94         {
95                 printf("factorytest: Can't find tiload. Please create %s. \n\r", TILOAD_NODE);
96                 exit(-1);
97         }
99         printf("factorytest: %s handle = %d\n\r", TILOAD_NODE, gTILoad);
102 uint8_t tas2557_get_PGID(void)
104         unsigned char pPageZero[] = {0x00, 0x00};
105         unsigned char pBook[] = {0x7F, 0x00};
106         unsigned char pPage[] = {0x00, 0x00};
107         unsigned char pData[] = {0x03, 0x00, 0x00, 0x00, 0x00};
109         tas2557_check_node();
111         write(gTILoad, pPageZero, 2);
112         write(gTILoad, pBook, 2);
113         write(gTILoad, pPage, 2);
114         read(gTILoad, pData, 1);
116         return pData[0];
119 uint32_t tas2557_coeff_read(uint32_t reg)
121         uint8_t nbook = TAS2557_BOOK_ID(reg);
122         uint8_t npage = TAS2557_PAGE_ID(reg);
123         uint8_t nreg = TAS2557_PAGE_REG(reg);
124         unsigned char pPageZero[] = {0x00, 0x00};
125         unsigned char pBook[] = {0x7F, nbook};
126         unsigned char pPage[] = {0x00, npage};
127         unsigned char pData[] = {nreg, 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]));
140 #define TAS2557_mCDSP_SWAP_REG  TAS2557_REG(0x8c, 0x19, 0x7c)
141 #define TAS2557_uCDSP_SWAP_REG  TAS2557_REG(0x00, 0x35, 0x2c)
143 void tas2557_coeff_write(uint32_t reg, uint32_t data)
145         unsigned int nByte;
146         uint8_t nbook, npage, nreg;
148         nbook = TAS2557_BOOK_ID(reg);
149         npage = TAS2557_PAGE_ID(reg);
150         nreg = TAS2557_PAGE_REG(reg);
152         // if the bin file is open, write the coefficients to the bin file
153         if (gBinFile) {
154                 /* if the bin file is open, write the coefficients to the bin file */
155                         unsigned int index = gnDevABlockIndex*4;
157                         gpDevABlock[index] = 0;
158                         gpDevABlock[index + 1] = 4;
159                         gpDevABlock[index + 2] = 0x85;
160                         gpDevABlock[index + 4] = nbook;
161                         gpDevABlock[index + 5] = npage;
162                         gpDevABlock[index + 6] = nreg;
164                         for (nByte = 0; nByte < 4; nByte++)
165                                 gpDevABlock[index + 7 + nByte] = (data >> ((3 - nByte) * 8)) & 0xFF;
167                         gnDevABlockIndex += 3;
168         } else {
169                 unsigned char pPageZero[] = {0x00, 0x00};
170                 unsigned char pBook[] = {0x7F, nbook};
171                 unsigned char pPage[] = {0x00, npage};
172                 unsigned char pData[] = {nreg, (data & 0xFF000000) >> 24, (data & 0x00FF0000) >> 16, (data & 0x0000FF00) >> 8, data & 0x000000FF};
174                 tas2557_check_node();
176                 write(gTILoad, pPageZero, 2);
177                 write(gTILoad, pBook, 2);
178                 write(gTILoad, pPage, 2);
179                 write(gTILoad, pData, 5);
181                 pBook[1] = TAS2557_BOOK_ID(TAS2557_mCDSP_SWAP_REG);
182                 pPage[1] = TAS2557_PAGE_ID(TAS2557_mCDSP_SWAP_REG);
184                 pData[0] = TAS2557_PAGE_REG(TAS2557_mCDSP_SWAP_REG);
185                 pData[1] = 0x00;
186                 pData[2] = 0x00;
187                 pData[3] = 0x00;
188                 pData[4] = 0x01;
190                 write(gTILoad, pPageZero, 2);
191                 write(gTILoad, pBook, 2);
192                 write(gTILoad, pPage, 2);
193                 write(gTILoad, pData, 5);
195                 pBook[1] = TAS2557_BOOK_ID(TAS2557_uCDSP_SWAP_REG);;
196                 pPage[1] = TAS2557_PAGE_ID(TAS2557_uCDSP_SWAP_REG);
198                 pData[0] = TAS2557_PAGE_REG(TAS2557_uCDSP_SWAP_REG);
199                 pData[1] = 0x00;
200                 pData[2] = 0x00;
201                 pData[3] = 0x00;
202                 pData[4] = 0x01;
204                 write(gTILoad, pPageZero, 2);
205                 write(gTILoad, pBook, 2);
206                 write(gTILoad, pPage, 2);
207                 write(gTILoad, pData, 5);
208         }
211 void tas2557_save_cal(struct TFTCConfiguration *pFTCC, 
212         double dev_a_re, uint32_t dev_a_rms_pow, uint32_t dev_a_t_limit, 
213         double t_cal,  uint32_t nResult, char * pFileName)
215         printf("TAS2557 calibration values:\n\r");
216         printf("    DevA Re = %1.2f Ohm\n\r", dev_a_re);
217         printf("    DevA rms_pow       = 0x%08X\n\r", dev_a_rms_pow);
218         printf("    DevA t_limit       = 0x%08X\n\r", dev_a_t_limit);
220         if((nResult & RE1_CHK_MSK) == RESULT_PASS)
221                 printf(" SPK A calibration success! \n\r");
222         else {
223                 if(nResult & RE1_FAIL_HI)
224                         printf(" SPK A Calibration fail : Re is too high (limit: %1.2f).\n\r", pFTCC->nTSpkCharDevA.nReHi);
225                 else
226                         printf(" SPK A Calibration fail : Re is too low (limit: %1.2f).\n\r", pFTCC->nTSpkCharDevA.nReLo);
227         }
229         FILE *pFile = fopen(pFileName, "w+");
231         fprintf(pFile, "DevA Re = %1.2f\n\r", dev_a_re);
232         fprintf(pFile, "DevA rms_pow       = 0x%08X\n\r", dev_a_rms_pow);
233         fprintf(pFile, "DevA t_limit       = 0x%08X\n\r", dev_a_t_limit);
234         fprintf(pFile, "Ambient temperature = %2.2f\n\r\n\r", t_cal);
235         fprintf(pFile, "Result = 0x%x\n\r\n\r", nResult);
237         fclose(pFile);
240 #define DDC_DESCRIPTION "Calibration Data File for TAS2557 Mono"
241 #define CALIBRATION_DESCRIPTION "Calibration snapshot for TAS2557 Mono"
242 #define DATA_DESCRIPTION "data blocks for TAS2557 Mono FTC"
244 void tas2557_open_bin(char * pFileName)
246         time_t timestamp; 
248         gBinFile = open(pFileName, O_RDWR | O_CREAT, S_IRUSR | S_IWUSR | S_IROTH | S_IWOTH);
250         gnBinIndex = 0;
251         memset(gpBin, 0, MAX_BIN_SIZE);
252         memset(gpDevABlock, 0, MAX_BIN_SIZE/2);
253         gnDevABlockIndex = 0;
255         //magic number
256         gpBin[gnBinIndex++] = '5';
257         gpBin[gnBinIndex++] = '5';
258         gpBin[gnBinIndex++] = '5';
259         gpBin[gnBinIndex++] = '2';
261         gnBinIndex += 4;        /* bypass size int */
262         gnBinIndex += 4;        /* bypass checksum int */
263         gnBinIndex += 4;        /* bypass PPC3 version int */
264         gnBinIndex += 4;        /* bypass DSP version int */
266         gpBin[gnBinIndex++] = 0;
267         gpBin[gnBinIndex++] = 0;
268         gpBin[gnBinIndex++] = 1;
269         gpBin[gnBinIndex++] = 0; /* driver version 0x00000100 */
271         time(&timestamp);
272         gpBin[gnBinIndex++] = (unsigned char)((timestamp&0xff000000)>>24);
273         gpBin[gnBinIndex++] = (unsigned char)((timestamp&0x00ff0000)>>16);;
274         gpBin[gnBinIndex++] = (unsigned char)((timestamp&0x0000ff00)>>8);;
275         gpBin[gnBinIndex++] = (unsigned char)((timestamp&0x000000ff));;
277         strcpy(&gpBin[gnBinIndex], "Calibration Data File");    /* DDC name */
278         gnBinIndex += 64;
280         strcpy(&gpBin[gnBinIndex], DDC_DESCRIPTION);
281         gnBinIndex += strlen(DDC_DESCRIPTION) + 1;
283         gnBinIndex += 4; /* device family index */
285         gpBin[gnBinIndex++] = 0; /* device index */
286         gpBin[gnBinIndex++] = 0; /* device index */
287         gpBin[gnBinIndex++] = 0; /* device index */
288         gpBin[gnBinIndex++] = 2; /* device index, TAS2557 Mono */
290         gnBinIndex +=
291                 2 +     /* num PLL index */
292                 0 +     /* array PLL index */
293                 2 +     /* num programs index */
294                 0 +     /* array programs index */
295                 2 +     /* num configurations index */
296                 0;      /* array configurations index */
298         gpBin[gnBinIndex++] = 0x00;
299         gpBin[gnBinIndex++] = 0x01; /* one calibration data block */
301         strcpy(&gpBin[gnBinIndex], "Calibration snapshot");
302         gnBinIndex += 64;
303         strcpy(&gpBin[gnBinIndex], CALIBRATION_DESCRIPTION);
304         gnBinIndex += strlen(CALIBRATION_DESCRIPTION) + 1;
306         gpBin[gnBinIndex++] = 0x00; /* compatible program = smart amp (index 0) */
307         gpBin[gnBinIndex++] = 0x00; /* compatible configuration */
309         strcpy(&gpBin[gnBinIndex], "Calibration Data");
310         gnBinIndex += 64;
311         strcpy(&gpBin[gnBinIndex], DATA_DESCRIPTION);
312         gnBinIndex += strlen(DATA_DESCRIPTION) + 1;
314         gpBin[gnBinIndex++] = 0x00; 
315         gpBin[gnBinIndex++] = 1;        /* one blocks */
317         gpDevABlock[0] = 0;
318         gpDevABlock[1] = 0;
319         gpDevABlock[2] = 0;
320         gpDevABlock[3] = 0x03;  /* COEFF_DEVICE_A – 0x03 */
321         gnDevABlockIndex = 2;
324 void tas2557_close_bin(void)
326         unsigned int nCommands;
327         unsigned char pCommit[] = {
328                 0x00, 0x04, 0x85, 0x00,
329                 TAS2557_BOOK_ID(TAS2557_mCDSP_SWAP_REG), TAS2557_PAGE_ID(TAS2557_mCDSP_SWAP_REG), TAS2557_PAGE_REG(TAS2557_mCDSP_SWAP_REG), 0x00,
330                 0x00, 0x00, 0x01, 0x00,
331                 0x00, 0x04, 0x85, 0x00,
332                 TAS2557_BOOK_ID(TAS2557_uCDSP_SWAP_REG), TAS2557_PAGE_ID(TAS2557_uCDSP_SWAP_REG), TAS2557_PAGE_REG(TAS2557_uCDSP_SWAP_REG), 0x00,
333                 0x00, 0x00, 0x01, 0x00
334         };
336         /* write the commit sequence */
337         memcpy(&gpDevABlock[gnDevABlockIndex*4], pCommit, 24);
338         gnDevABlockIndex += 6;
340         /* write number of commands for calibration block */
341         gpDevABlock[4] = ((gnDevABlockIndex-2) & 0xFF000000) >> 24;
342         gpDevABlock[5] = ((gnDevABlockIndex-2) & 0x00FF0000) >> 16;
343         gpDevABlock[6] = ((gnDevABlockIndex-2) & 0x0000FF00) >> 8;
344         gpDevABlock[7] = ((gnDevABlockIndex-2) & 0x000000FF);
346         memcpy(&gpBin[gnBinIndex], gpDevABlock, gnDevABlockIndex*4);
347         gnBinIndex += (gnDevABlockIndex*4);
349         /* write bin file size */
350         gpBin[4] = (gnBinIndex & 0xFF000000) >> 24;
351         gpBin[5] = (gnBinIndex & 0x00FF0000) >> 16;
352         gpBin[6] = (gnBinIndex & 0x0000FF00) >> 8;
353         gpBin[7] = (gnBinIndex & 0x000000FF);
355         write(gBinFile, gpBin, gnBinIndex);
356         close(gBinFile);
358         gBinFile = 0;
361 // ----------------------------------------------------------------------------- 
362 // check_spk_bounds 
363 // ----------------------------------------------------------------------------- 
364 // Description: 
365 //      Checks if speaker paramters are within bounds. 
366 // ----------------------------------------------------------------------------- 
367 uint32_t check_spk_bounds(struct TFTCConfiguration *pFTCC, double re1) 
368
369         uint32_t result = RESULT_PASS; 
371         if(re1>pFTCC->nTSpkCharDevA.nReHi) 
372                 result |= RE1_FAIL_HI; 
373         if(re1<pFTCC->nTSpkCharDevA.nReLo) 
374                 result |= RE1_FAIL_LO; 
376         return result; 
377
379 void tas2557_ftc_release(void)
381         if (gTILoad > 0) {
382                 close(gTILoad);
383                 gTILoad = 0;
384         }