4d93ecd26ae23072a9b37991173619dc779ab19a
[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(uint8_t book, uint8_t page, uint8_t reg)
121         unsigned char pPageZero[] = {0x00, 0x00};
122         unsigned char pBook[] = {0x7F, book};
123         unsigned char pPage[] = {0x00, page};
124         unsigned char pData[] = {reg, 0x00, 0x00, 0x00, 0x00};
126         tas2557_check_node();
128         write(gTILoad, pPageZero, 2);
129         write(gTILoad, pBook, 2);
130         write(gTILoad, pPage, 2);
131         read(gTILoad, pData, 4);
133         return ((pData[0] << 24) | (pData[1] << 16) | (pData[2] << 8) | (pData[3]));
136 void tas2557_coeff_write(uint8_t book, uint8_t page, uint8_t reg, uint32_t data)
138         unsigned int nByte;
140         if (gBinFile) {
141                 /* if the bin file is open, write the coefficients to the bin file */
142                 unsigned int index = gnDevABlockIndex*4;
143                 gpDevABlock[index] = 0;
144                 gpDevABlock[index + 1] = 4;
145                 gpDevABlock[index + 2] = 0x85;
146                 gpDevABlock[index + 4] = book;
147                 gpDevABlock[index + 5] = page;
148                 gpDevABlock[index + 6] = reg;
150                 for (nByte = 0; nByte < 4; nByte++)
151                         gpDevABlock[index + 7 + nByte] = (data >> ((3 - nByte) * 8)) & 0xFF;
153                 gnDevABlockIndex += 3;
154         } else {
155                 unsigned char pPageZero[] = {0x00, 0x00};
156                 unsigned char pBook[] = {0x7F, book};
157                 unsigned char pPage[] = {0x00, page};
158                 unsigned char pData[] = {reg, (data & 0xFF000000) >> 24, (data & 0x00FF0000) >> 16, (data & 0x0000FF00) >> 8, data & 0x000000FF};
160                 tas2557_check_node();
162                 write(gTILoad, pPageZero, 2);
163                 write(gTILoad, pBook, 2);
164                 write(gTILoad, pPage, 2);
165                 write(gTILoad, pData, 5);
167                 pBook[1] = 0x8C;
168                 pPage[1] = 0x19;
170                 pData[0] = 0x7C;
171                 pData[1] = 0x00;
172                 pData[2] = 0x00;
173                 pData[3] = 0x00;
174                 pData[4] = 0x01;
176                 write(gTILoad, pPageZero, 2);
177                 write(gTILoad, pBook, 2);
178                 write(gTILoad, pPage, 2);
179                 write(gTILoad, pData, 5);
181                 pBook[1] = 0x00;
182                 pPage[1] = 0x35;
184                 pData[0] = 0x2c;
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);
194         }
197 void tas2557_save_cal(struct TFTCConfiguration *pFTCC, 
198         double dev_a_re, uint32_t dev_a_rms_pow, uint32_t dev_a_t_limit, 
199         double t_cal,  uint32_t nResult, char * pFileName)
201         printf("TAS2557 calibration values:\n\r");
202         printf("    DevA Re = %1.2f Ohm\n\r", dev_a_re);
203         printf("    DevA rms_pow       = 0x%08X\n\r", dev_a_rms_pow);
204         printf("    DevA t_limit       = 0x%08X\n\r", dev_a_t_limit);
206         if((nResult & RE1_CHK_MSK) == RESULT_PASS)
207                 printf(" SPK A calibration success! \n\r");
208         else {
209                 if(nResult & RE1_FAIL_HI)
210                         printf(" SPK A Calibration fail : Re is too high (limit: %1.2f).\n\r", pFTCC->nTSpkCharDevA.nReHi);
211                 else
212                         printf(" SPK A Calibration fail : Re is too low (limit: %1.2f).\n\r", pFTCC->nTSpkCharDevA.nReLo);
213         }
215         FILE *pFile = fopen(pFileName, "w+");
217         fprintf(pFile, "DevA Re = %1.2f\n\r", dev_a_re);
218         fprintf(pFile, "DevA rms_pow       = 0x%08X\n\r", dev_a_rms_pow);
219         fprintf(pFile, "DevA t_limit       = 0x%08X\n\r", dev_a_t_limit);
220         fprintf(pFile, "Ambient temperature = %2.2f\n\r\n\r", t_cal);
221         fprintf(pFile, "Result = 0x%x\n\r\n\r", nResult);
223         fclose(pFile);
226 #define DDC_DESCRIPTION "Calibration Data File for TAS2557 Mono"
227 #define CALIBRATION_DESCRIPTION "Calibration snapshot for TAS2557 Mono"
228 #define DATA_DESCRIPTION "data blocks for TAS2557 Mono FTC"
230 void tas2557_open_bin(char * pFileName)
232         time_t timestamp; 
234         gBinFile = open(pFileName, O_RDWR | O_CREAT, S_IRUSR | S_IWUSR | S_IROTH | S_IWOTH);
236         gnBinIndex = 0;
237         memset(gpBin, 0, MAX_BIN_SIZE);
238         memset(gpDevABlock, 0, MAX_BIN_SIZE/2);
239         gnDevABlockIndex = 0;
241         //magic number
242         gpBin[gnBinIndex++] = '5';
243         gpBin[gnBinIndex++] = '5';
244         gpBin[gnBinIndex++] = '5';
245         gpBin[gnBinIndex++] = '2';
247         gnBinIndex += 4;        /* bypass size int */
248         gnBinIndex += 4;        /* bypass checksum int */
249         gnBinIndex += 4;        /* bypass PPC3 version int */
250         gnBinIndex += 4;        /* bypass DSP version int */
252         gpBin[gnBinIndex++] = 0;
253         gpBin[gnBinIndex++] = 0;
254         gpBin[gnBinIndex++] = 1;
255         gpBin[gnBinIndex++] = 0; /* driver version 0x00000100 */
257         time(&timestamp);
258         gpBin[gnBinIndex++] = (unsigned char)((timestamp&0xff000000)>>24);
259         gpBin[gnBinIndex++] = (unsigned char)((timestamp&0x00ff0000)>>16);;
260         gpBin[gnBinIndex++] = (unsigned char)((timestamp&0x0000ff00)>>8);;
261         gpBin[gnBinIndex++] = (unsigned char)((timestamp&0x000000ff));;
263         strcpy(&gpBin[gnBinIndex], "Calibration Data File");    /* DDC name */
264         gnBinIndex += 64;
266         strcpy(&gpBin[gnBinIndex], DDC_DESCRIPTION);
267         gnBinIndex += strlen(DDC_DESCRIPTION) + 1;
269         gnBinIndex += 4; /* device family index */
271         gpBin[gnBinIndex++] = 0; /* device index */
272         gpBin[gnBinIndex++] = 0; /* device index */
273         gpBin[gnBinIndex++] = 0; /* device index */
274         gpBin[gnBinIndex++] = 2; /* device index, TAS2557 Mono */
276         gnBinIndex +=
277                 2 +     /* num PLL index */
278                 0 +     /* array PLL index */
279                 2 +     /* num programs index */
280                 0 +     /* array programs index */
281                 2 +     /* num configurations index */
282                 0;      /* array configurations index */
284         gpBin[gnBinIndex++] = 0x00;
285         gpBin[gnBinIndex++] = 0x01; /* one calibration data block */
287         strcpy(&gpBin[gnBinIndex], "Calibration snapshot");
288         gnBinIndex += 64;
289         strcpy(&gpBin[gnBinIndex], CALIBRATION_DESCRIPTION);
290         gnBinIndex += strlen(CALIBRATION_DESCRIPTION) + 1;
292         gpBin[gnBinIndex++] = 0x00; /* compatible program = smart amp (index 0) */
293         gpBin[gnBinIndex++] = 0x00; /* compatible configuration */
295         strcpy(&gpBin[gnBinIndex], "Calibration Data");
296         gnBinIndex += 64;
297         strcpy(&gpBin[gnBinIndex], DATA_DESCRIPTION);
298         gnBinIndex += strlen(DATA_DESCRIPTION) + 1;
300         gpBin[gnBinIndex++] = 0x00; 
301         gpBin[gnBinIndex++] = 1;        /* one blocks */
303         gpDevABlock[0] = 0;
304         gpDevABlock[1] = 0;
305         gpDevABlock[2] = 0;
306         gpDevABlock[3] = 0x03;  /* COEFF_DEVICE_A – 0x03 */
307         gnDevABlockIndex = 2;
310 void tas2557_close_bin(void)
312         unsigned int nCommands;
313         unsigned char pCommit[] = {
314                 0x00, 0x04, 0x85, 0x00,
315                 0x8C, 0x19, 0x7C, 0x00,
316                 0x00, 0x00, 0x01, 0x00,
317                 0x00, 0x04, 0x85, 0x00,
318                 0x00, 0x35, 0x2c, 0x00,
319                 0x00, 0x00, 0x01, 0x00
320         };
322         /* write the commit sequence */
323         memcpy(&gpDevABlock[gnDevABlockIndex*4], pCommit, 24);
324         gnDevABlockIndex += 6;
326         /* write number of commands for calibration block */
327         gpDevABlock[4] = ((gnDevABlockIndex-2) & 0xFF000000) >> 24;
328         gpDevABlock[5] = ((gnDevABlockIndex-2) & 0x00FF0000) >> 16;
329         gpDevABlock[6] = ((gnDevABlockIndex-2) & 0x0000FF00) >> 8;
330         gpDevABlock[7] = ((gnDevABlockIndex-2) & 0x000000FF);
332         memcpy(&gpBin[gnBinIndex], gpDevABlock, gnDevABlockIndex*4);
333         gnBinIndex += (gnDevABlockIndex*4);
335         /* write bin file size */
336         gpBin[4] = (gnBinIndex & 0xFF000000) >> 24;
337         gpBin[5] = (gnBinIndex & 0x00FF0000) >> 16;
338         gpBin[6] = (gnBinIndex & 0x0000FF00) >> 8;
339         gpBin[7] = (gnBinIndex & 0x000000FF);
341         write(gBinFile, gpBin, gnBinIndex);
342         close(gBinFile);
344         gBinFile = 0;
347 // ----------------------------------------------------------------------------- 
348 // check_spk_bounds 
349 // ----------------------------------------------------------------------------- 
350 // Description: 
351 //      Checks if speaker paramters are within bounds. 
352 // ----------------------------------------------------------------------------- 
353 uint32_t check_spk_bounds(struct TFTCConfiguration *pFTCC, double re1) 
354
355         uint32_t result = RESULT_PASS; 
357         if(re1>pFTCC->nTSpkCharDevA.nReHi) 
358                 result |= RE1_FAIL_HI; 
359         if(re1<pFTCC->nTSpkCharDevA.nReLo) 
360                 result |= RE1_FAIL_LO; 
362         return result; 
363
365 void tas2557_ftc_release(void)
367         if (gTILoad > 0) {
368                 close(gTILoad);
369                 gTILoad = 0;
370         }