1 /*
2 * Copyright 2019 NXP
3 * All rights reserved.
4 * SPDX-License-Identifier: BSD-3-Clause
5 */
6 #include <stdint.h>
7 #include <stdlib.h>
8 #include <math.h>
9 #include <stdio.h>
10 #include <string.h>
11 #include <assert.h>
12 #include "fsl_tfa9896.h"
13 #include "fsl_common.h"
14 /*******************************************************************************
15 * Definitions
16 ******************************************************************************/
17 #define TFA_SWAP_UINT16_BYTE_SEQUENCE(x) (__REV16(x))
18
19 /*******************************************************************************
20 * Prototypes
21 ******************************************************************************/
22
23 /*******************************************************************************
24 * Code
25 ******************************************************************************/
TFA9896_ReadRegister(tfa9896_handle_t * handle,uint8_t subaddress,unsigned short * value)26 status_t TFA9896_ReadRegister(tfa9896_handle_t *handle, uint8_t subaddress, unsigned short *value)
27 {
28 assert(handle->config != NULL);
29 assert(handle->config->slaveAddress != 0U);
30
31 uint16_t readValue = 0U;
32 #if defined(DEMO_VERBOSE)
33 int i;
34 #endif
35
36 if (CODEC_I2C_Receive(handle->i2cHandle, handle->config->slaveAddress, subaddress, 1U, (uint8_t *)&readValue, 2U) !=
37 kStatus_HAL_I2cSuccess)
38 {
39 return kStatus_TFA9896_I2C_Fatal;
40 }
41
42 *value = TFA_SWAP_UINT16_BYTE_SEQUENCE(readValue);
43 #if defined(DEMO_VERBOSE)
44 TFA9896_Printf("R(0x%02x):", subaddress);
45 for (i = 0; i < transfer.dataSize; i++)
46 {
47 TFA9896_Printf("[0x%02x]", (unsigned char)((unsigned char *)transfer.data + i));
48 }
49 TFA9896_Printf("\r\n");
50 #endif
51
52 return kStatus_TFA9896_Ok;
53 }
54
tfa_read_reg(tfa9896_handle_t * handle,const uint16_t bf)55 int tfa_read_reg(tfa9896_handle_t *handle, const uint16_t bf)
56 {
57 status_t err = kStatus_TFA9896_Ok;
58 uint16_t regvalue;
59
60 /* bitfield enum - 8..15 : address */
61 uint8_t address = (bf >> 8) & 0xff;
62
63 err = TFA9896_ReadRegister(handle, address, ®value);
64 if (err)
65 {
66 return -err;
67 }
68
69 return regvalue;
70 }
71
TFA9896_WriteRegister(tfa9896_handle_t * handle,uint8_t subaddress,uint16_t value)72 status_t TFA9896_WriteRegister(tfa9896_handle_t *handle, uint8_t subaddress, uint16_t value)
73 {
74 assert(handle->config != NULL);
75 assert(handle->config->slaveAddress != 0U);
76
77 #if defined(DEMO_VERBOSE)
78 int i;
79 #endif
80
81 uint16_t writeValue = TFA_SWAP_UINT16_BYTE_SEQUENCE(value);
82
83 if (kStatus_HAL_I2cSuccess !=
84 CODEC_I2C_Send(handle->i2cHandle, handle->config->slaveAddress, subaddress, 1U, (uint8_t *)&writeValue, 2U))
85 {
86 return kStatus_TFA9896_I2C_Fatal;
87 }
88
89 #if defined(DEMO_VERBOSE)
90 TFA9896_Printf("W(0x%02x):", subaddress);
91 for (i = 0; i < transfer.dataSize; i++)
92 {
93 TFA9896_Printf("[0x%02x]", (unsigned char)((unsigned char *)transfer.data + i));
94 }
95 TFA9896_Printf("\r\n");
96 #endif
97
98 return kStatus_TFA9896_Ok;
99 }
100
TFA9896_GetBits(tfa9896_handle_t * handle,const uint16_t bf)101 uint16_t TFA9896_GetBits(tfa9896_handle_t *handle, const uint16_t bf)
102 {
103 uint16_t regvalue, msk;
104 status_t err = kStatus_TFA9896_Ok;
105 uint16_t value;
106 uint8_t len = bf & 0x0f;
107 uint8_t pos = (bf >> 4) & 0x0f;
108 uint8_t address = (bf >> 8) & 0xff;
109 err = TFA9896_ReadRegister(handle, address, ®value);
110 if (err != kStatus_TFA9896_Ok)
111 {
112 return 0U;
113 }
114 msk = ((1 << (len + 1)) - 1) << pos;
115 regvalue &= msk;
116 value = regvalue >> pos;
117
118 return value;
119 }
120
TFA9896_isFactory(tfa9896_handle_t * handle)121 uint16_t TFA9896_isFactory(tfa9896_handle_t *handle)
122 {
123 return (TFA9896_GetBits(handle, TFA1_BF_MTPEX) == 1);
124 }
125
TFA9896_SetBits(tfa9896_handle_t * handle,const uint16_t bf,const uint16_t value)126 status_t TFA9896_SetBits(tfa9896_handle_t *handle, const uint16_t bf, const uint16_t value)
127 {
128 status_t err = kStatus_TFA9896_Ok;
129 uint16_t regvalue, msk, oldvalue;
130 uint8_t len = (bf & 0x0f) + 1;
131 uint8_t pos = (bf >> 4) & 0x0f;
132 uint8_t address = (bf >> 8) & 0xff;
133 err = TFA9896_ReadRegister(handle, address, ®value);
134 oldvalue = regvalue;
135 msk = ((1 << len) - 1) << pos;
136 regvalue &= ~msk;
137 regvalue |= value << pos;
138
139 if (oldvalue != regvalue)
140 {
141 err = TFA9896_WriteRegister(handle, (bf >> 8) & 0xff, regvalue);
142 }
143
144 return err;
145 }
146
TFA9896_ReadData(tfa9896_handle_t * handle,unsigned char subaddress,int num_bytes,unsigned char data[])147 status_t TFA9896_ReadData(tfa9896_handle_t *handle, unsigned char subaddress, int num_bytes, unsigned char data[])
148 {
149 status_t err = kStatus_TFA9896_Ok;
150 #if defined(DEMO_VERBOSE)
151 int i;
152 #endif
153
154 err =
155 CODEC_I2C_Receive(handle->i2cHandle, handle->config->slaveAddress, subaddress, 1U, (uint8_t *)data, num_bytes);
156
157 #if defined(DEMO_VERBOSE)
158 TFA9896_Printf("R(0x%02x):", subaddress);
159 for (i = 0; i < transfer.dataSize; i++)
160 TFA9896_Printf("[0x%02x]", (unsigned char)((unsigned char *)transfer.data + i));
161 TFA9896_Printf("\r\n");
162 #endif
163
164 return err;
165 }
166
TFA9896_WriteData(tfa9896_handle_t * handle,unsigned char subaddress,int num_bytes,const unsigned char data[])167 status_t TFA9896_WriteData(tfa9896_handle_t *handle,
168 unsigned char subaddress,
169 int num_bytes,
170 const unsigned char data[])
171 {
172 status_t err = kStatus_TFA9896_Ok;
173 #if defined(DEMO_VERBOSE)
174 int i;
175 #endif
176
177 err = CODEC_I2C_Send(handle->i2cHandle, handle->config->slaveAddress, subaddress, 1U, (uint8_t *)data, num_bytes);
178
179 #if defined(DEMO_VERBOSE)
180 TFA9896_Printf("W(0x%02x):", subaddress);
181 for (i = 0; i < transfer.dataSize; i++)
182 {
183 TFA9896_Printf("[0x%02x]", (unsigned char)((unsigned char *)transfer.data + i));
184 }
185 TFA9896_Printf("\r\n");
186 #endif
187
188 return err;
189 }
190
191 /* read the return code for the RPC call */
checkRpcStatus(tfa9896_handle_t * handle,int * pRpcStatus)192 status_t checkRpcStatus(tfa9896_handle_t *handle, int *pRpcStatus)
193 {
194 status_t error = kStatus_TFA9896_Ok;
195 unsigned short cf_ctrl = 0x0002; /* the value to sent to the CF_CONTROLS register: cf_req=00000000, cf_int=0,
196 cf_aif=0, cf_dmem=XMEM=01, cf_rst_dsp=0 */
197 unsigned short cf_mad = 0x0000; /* memory address to be accessed (0 : Status, 1 : ID, 2 : parameters) */
198 unsigned char mem[3]; /* will be filled with the status read from DSP memory */
199 if (pRpcStatus == 0)
200 return kStatus_TFA9896_Bad_Parameter;
201 #ifdef OPTIMIZED_RPC
202 {
203 /* minimize the number of I2C transactions by making use of the autoincrement in I2C */
204 unsigned char buffer[4];
205 /* first the data for CF_CONTROLS */
206 buffer[0] = (unsigned char)((cf_ctrl >> 8) & 0xFF);
207 buffer[1] = (unsigned char)(cf_ctrl & 0xFF);
208 /* write the contents of CF_MAD which is the subaddress following CF_CONTROLS */
209 buffer[2] = (unsigned char)((cf_mad >> 8) & 0xFF);
210 buffer[3] = (unsigned char)(cf_mad & 0xFF);
211 error = TFA9896_WriteData(handle, 0x70, sizeof(buffer), buffer);
212 }
213 #else
214 /* 1) write DMEM=XMEM to the DSP XMEM */
215 if (error == kStatus_TFA9896_Ok)
216 {
217 error = TFA9896_WriteRegister(handle, 0x70, cf_ctrl);
218 }
219 if (error == kStatus_TFA9896_Ok)
220 {
221 /* write the address in XMEM where to read */
222 TFA9896_WriteRegister(handle, 0x71, cf_mad);
223 }
224 #endif
225 if (error == kStatus_TFA9896_Ok)
226 {
227 /* read 1 word (24 bit) from XMEM */
228 error = TFA9896_ReadData(handle, 0x72, 3 /*sizeof(mem) */, mem);
229 }
230 if (error == kStatus_TFA9896_Ok)
231 {
232 *pRpcStatus = (mem[0] << 16) | (mem[1] << 8) | mem[2];
233 }
234 return error;
235 }
236
237 /* check that num_byte matches the memory type selected */
check_size(tfa9896_DMEM_t which_mem,int num_bytes)238 status_t check_size(tfa9896_DMEM_t which_mem, int num_bytes)
239 {
240 status_t error = kStatus_TFA9896_Ok;
241 int modulo_size = 1;
242 switch (which_mem)
243 {
244 case DMEM_PMEM:
245 /* 32 bit PMEM */
246 modulo_size = 4;
247 break;
248 case DMEM_XMEM:
249 case DMEM_YMEM:
250 case DMEM_IOMEM:
251 /* 24 bit MEM */
252 modulo_size = 3;
253 break;
254 default:
255 error = kStatus_TFA9896_Bad_Parameter;
256 }
257 if (error == kStatus_TFA9896_Ok)
258 {
259 if ((num_bytes % modulo_size) != 0)
260 {
261 error = kStatus_TFA9896_Bad_Parameter;
262 }
263 }
264 return error;
265 }
266
writeParameter(tfa9896_handle_t * handle,unsigned char module_id,unsigned char param_id,int num_bytes,const unsigned char data[])267 status_t writeParameter(tfa9896_handle_t *handle,
268 unsigned char module_id,
269 unsigned char param_id,
270 int num_bytes,
271 const unsigned char data[])
272 {
273 status_t error;
274 unsigned short cf_ctrl = 0x0002; /* the value to be sent to the CF_CONTROLS register: cf_req=00000000, cf_int=0,
275 cf_aif=0, cf_dmem=XMEM=01, cf_rst_dsp=0 */
276 unsigned short cf_mad = 0x0001; /* memory address to be accessed (0 : Status, 1 : ID, 2 : parameters) */
277 error = check_size(DMEM_XMEM, num_bytes);
278 if (error == kStatus_TFA9896_Ok)
279 {
280 if ((num_bytes <= 0) || (num_bytes > MAX_PARAM_SIZE))
281 {
282 return kStatus_TFA9896_Bad_Parameter;
283 }
284 }
285 #ifdef OPTIMIZED_RPC
286 {
287 /* minimize the number of I2C transactions by making use of the autoincrement in I2C */
288 unsigned char buffer[7];
289 /* first the data for CF_CONTROLS */
290 buffer[0] = (unsigned char)((cf_ctrl >> 8) & 0xFF);
291 buffer[1] = (unsigned char)(cf_ctrl & 0xFF);
292 /* write the contents of CF_MAD which is the subaddress following CF_CONTROLS */
293 buffer[2] = (unsigned char)((cf_mad >> 8) & 0xFF);
294 buffer[3] = (unsigned char)(cf_mad & 0xFF);
295 /* write the module and RPC id into CF_MEM, which follows CF_MAD */
296 buffer[4] = 0;
297 buffer[5] = module_id + 128;
298 buffer[6] = param_id;
299 /* TFA9896_Printf("calling TFA9896_WriteData\n");*/
300 error = TFA9896_WriteData(handle, 0x70, sizeof(buffer), buffer);
301 }
302 #else
303 if (error == kStatus_TFA9896_Ok)
304 {
305 error = TFA9896_WriteRegister(handle, 0x70, cf_ctrl);
306 }
307 if (error == kStatus_TFA9896_Ok)
308 {
309 TFA9896_WriteRegister(handle, 0x71, cf_mad);
310 }
311 if (error == kStatus_TFA9896_Ok)
312 {
313 unsigned char id[3];
314 id[0] = 0;
315 id[1] = module_id + 128;
316 id[2] = param_id;
317 error = TFA9896_WriteData(handle, 0x72, 3, id);
318 }
319 #endif /* OPTIMIZED_RPC */
320 if (error == kStatus_TFA9896_Ok)
321 {
322 int offset = 0;
323 int chunk_size = ROUND_DOWN(NXP_I2C_MAX_SIZE, 3 /* XMEM word size */);
324 int remaining_bytes = num_bytes;
325 /* due to autoincrement in cf_ctrl, next write will happen at the next address */
326 while ((error == kStatus_TFA9896_Ok) && (remaining_bytes > 0))
327 {
328 if (remaining_bytes < chunk_size)
329 {
330 chunk_size = remaining_bytes;
331 }
332 /* else chunk_size remains at initialize value above*/
333 error = TFA9896_WriteData(handle, 0x72, chunk_size, data + offset);
334 if (error != kStatus_TFA9896_Ok)
335 {
336 break;
337 }
338 remaining_bytes -= chunk_size;
339 offset += chunk_size;
340 }
341 }
342 return error;
343 }
344
executeParam(tfa9896_handle_t * handle)345 status_t executeParam(tfa9896_handle_t *handle)
346 {
347 status_t error;
348 unsigned short cf_ctrl = 0x0002; /* the value to be sent to the CF_CONTROLS register: cf_req=00000000, cf_int=0,
349 cf_aif=0, cf_dmem=XMEM=01, cf_rst_dsp=0 */
350 cf_ctrl |= (1 << 8) | (1 << 4); /* set the cf_req1 and cf_int bit */
351 error = TFA9896_WriteRegister(handle, 0x70, (uint16_t)cf_ctrl);
352 return error;
353 }
354
waitResult(tfa9896_handle_t * handle)355 status_t waitResult(tfa9896_handle_t *handle)
356 {
357 status_t error;
358 unsigned short cf_status; /* the contents of the CF_STATUS register */
359 int tries = 0;
360 do
361 {
362 error = TFA9896_ReadRegister(handle, 0x73, &cf_status);
363 tries++;
364 } while ((error == kStatus_TFA9896_Ok) && ((cf_status & 0x0100) == 0) &&
365 (tries < TFA9896_API_WAITRESULT_NTRIES)); /* don't wait forever, DSP is pretty quick to respond (< 1ms) */
366 if (tries >= TFA9896_API_WAITRESULT_NTRIES)
367 {
368 /* something wrong with communication with DSP */
369 error = kStatus_TFA9896_DSP_not_running;
370 }
371 return error;
372 }
373
TFA9896_DspSetParam(tfa9896_handle_t * handle,unsigned char module_id,unsigned char param_id,int num_bytes,const unsigned char data[])374 status_t TFA9896_DspSetParam(tfa9896_handle_t *handle,
375 unsigned char module_id,
376 unsigned char param_id,
377 int num_bytes,
378 const unsigned char data[])
379 {
380 status_t error;
381 int rpcStatus = STATUS_OK;
382 /* 1) write the id and data to the DSP XMEM */
383 error = writeParameter(handle, module_id, param_id, num_bytes, data);
384 /* 2) wake up the DSP and let it process the data */
385 if (error == kStatus_TFA9896_Ok)
386 {
387 error = executeParam(handle);
388 }
389 /* check the result when addressed an IC uniquely */
390 if (handle->config->slaveAddress != 0x1C)
391 {
392 /* 3) wait for the ack */
393 if (error == kStatus_TFA9896_Ok)
394 {
395 error = waitResult(handle);
396 }
397 /* 4) check the RPC return value */
398 if (error == kStatus_TFA9896_Ok)
399 {
400 error = checkRpcStatus(handle, &rpcStatus);
401 TFA9896_Printf("rpcStatus:%d\n", rpcStatus);
402 }
403 if (error == kStatus_TFA9896_Ok)
404 {
405 if (rpcStatus != STATUS_OK)
406 {
407 /* DSP RPC call returned an error */
408 error = (status_t)(rpcStatus + kStatus_TFA9896_RpcBase);
409 }
410 }
411 }
412 return error;
413 }
414
tfa9896_convert_data2bytes(int num_data,const int data[],unsigned char bytes[])415 void tfa9896_convert_data2bytes(int num_data, const int data[], unsigned char bytes[])
416 {
417 int i; /* index for data */
418 int k; /* index for bytes */
419 int d;
420 /* note: cannot just take the lowest 3 bytes from the 32 bit
421 * integer, because also need to take care of clipping any
422 * value > 2&23 */
423 for (i = 0, k = 0; i < num_data; ++i, k += 3)
424 {
425 if (data[i] >= 0)
426 {
427 d = MIN(data[i], (1 << 23) - 1);
428 }
429 else
430 {
431 /* 2's complement */
432 d = (1 << 24) - MIN(-data[i], 1 << 23);
433 }
434 bytes[k] = (d >> 16) & 0xFF; /* MSB */
435 bytes[k + 1] = (d >> 8) & 0xFF;
436 bytes[k + 2] = (d)&0xFF; /* LSB */
437 }
438 }
439
tfa9896_convert_bytes2data(int num_bytes,const unsigned char bytes[],int data[])440 void tfa9896_convert_bytes2data(int num_bytes, const unsigned char bytes[], int data[])
441 {
442 int i; /* index for data */
443 int k; /* index for bytes */
444 int d;
445 int num_data = num_bytes / 3;
446
447 for (i = 0, k = 0; i < num_data; ++i, k += 3)
448 {
449 d = (bytes[k] << 16) | (bytes[k + 1] << 8) | (bytes[k + 2]);
450 if (bytes[k] & 0x80) /* sign bit was set */
451 {
452 d = -((1 << 24) - d);
453 }
454
455 data[i] = d;
456 }
457 }
458
TFA9896_DspBiquad_Disable(tfa9896_handle_t * handle,int biquad_index)459 status_t TFA9896_DspBiquad_Disable(tfa9896_handle_t *handle, int biquad_index)
460 {
461 int coeff_buffer[6];
462 unsigned char bytes[6 * 3];
463 status_t error = kStatus_TFA9896_Ok;
464 /* set in correct order and format for the DSP */
465 coeff_buffer[0] = (int)-8388608; /* -1.0f */
466 coeff_buffer[1] = 0;
467 coeff_buffer[2] = 0;
468 coeff_buffer[3] = 0;
469 coeff_buffer[4] = 0;
470 coeff_buffer[5] = 0;
471 /* convert float to fixed point and then bytes suitable for transmaission over I2C */
472 tfa9896_convert_data2bytes(6, coeff_buffer, bytes);
473 error = TFA9896_DspSetParam(handle, 2, (unsigned char)biquad_index, (unsigned char)6 * 3, bytes);
474
475 return error;
476 }
477
478 #ifdef TFA9896_DEBUG_DATA
printArray(char * ptr,size_t size)479 void printArray(char *ptr, size_t size)
480 {
481 char *const end = ptr + size;
482 while (ptr < end)
483 {
484 TFA9896_Printf("[%x]-", *ptr++);
485 }
486 }
487 #endif
488
TFA9896_Write_FilterBank(tfa9896_handle_t * handle,tfa9896FilterM_t * filter)489 status_t TFA9896_Write_FilterBank(tfa9896_handle_t *handle, tfa9896FilterM_t *filter)
490 {
491 unsigned char biquad_index;
492 status_t error = kStatus_TFA9896_Ok;
493 for (biquad_index = 0; biquad_index < 10; biquad_index++)
494 {
495 if (filter[biquad_index].enabled)
496 {
497 TFA9896_Printf("TFA9896_Write_FilterBank inside if block\n");
498 error = TFA9896_DspSetParam(handle, 2, biquad_index + 1, sizeof(filter[biquad_index].biquad.bytes),
499 filter[biquad_index].biquad.bytes);
500 }
501 else
502 {
503 TFA9896_Printf("TFA9896_Write_FilterBank inside else block\n");
504 error = TFA9896_DspBiquad_Disable(handle, biquad_index + 1);
505 }
506 }
507 return error;
508 }
509
510 unsigned char vsfwdelay_table[] = {
511 0, 0, 2, /*Index 0 - Current/Volt Fractional Delay for 8KHz */
512 0, 0, 0, /*Index 1 - Current/Volt Fractional Delay for 11KHz */
513 0, 0, 0, /*Index 2 - Current/Volt Fractional Delay for 12KHz */
514 0, 0, 2, /*Index 3 - Current/Volt Fractional Delay for 16KHz */
515 0, 0, 2, /*Index 4 - Current/Volt Fractional Delay for 22KHz */
516 0, 0, 2, /*Index 5 - Current/Volt Fractional Delay for 24KHz */
517 0, 0, 2, /*Index 6 - Current/Volt Fractional Delay for 32KHz */
518 0, 0, 2, /*Index 7 - Current/Volt Fractional Delay for 44KHz */
519 0, 0, 3 /*Index 8 - Current/Volt Fractional Delay for 48KHz */
520 };
521 unsigned char cvfracdelay_table[] = {
522 0, 0, 51, /*Index 0 - Current/Volt Fractional Delay for 8KHz */
523 0, 0, 0, /*Index 1 - Current/Volt Fractional Delay for 11KHz */
524 0, 0, 0, /*Index 2 - Current/Volt Fractional Delay for 12KHz */
525 0, 0, 38, /*Index 3 - Current/Volt Fractional Delay for 16KHz */
526 0, 0, 34, /*Index 4 - Current/Volt Fractional Delay for 22KHz */
527 0, 0, 33, /*Index 5 - Current/Volt Fractional Delay for 24KHz */
528 0, 0, 11, /*Index 6 - Current/Volt Fractional Delay for 32KHz */
529 0, 0, 2, /*Index 7 - Current/Volt Fractional Delay for 44KHz */
530 0, 0, 62 /*Index 8 - Current/Volt Fractional Delay for 48KHz */
531 };
532
tfa_dsp_write_cvfracdelay_table(tfa9896_handle_t * handle)533 status_t tfa_dsp_write_cvfracdelay_table(tfa9896_handle_t *handle)
534 {
535 TFA9896_Printf("Bytes cvfracdelay_table_96 to be written:%d\n", sizeof(cvfracdelay_table));
536 return TFA9896_DspSetParam(handle, MODULE_FRAMEWORK, 0x06, sizeof(cvfracdelay_table), cvfracdelay_table);
537 }
538
tfa_dsp_write_vsfwdelay_table(tfa9896_handle_t * handle)539 status_t tfa_dsp_write_vsfwdelay_table(tfa9896_handle_t *handle)
540 {
541 TFA9896_Printf("Bytes vsfwdelay_table_96 to be written:%d\n", sizeof(vsfwdelay_table));
542 return TFA9896_DspSetParam(handle, MODULE_FRAMEWORK, 0x03, sizeof(vsfwdelay_table), vsfwdelay_table);
543 }
544
TFA9896_DSPWriteTables(tfa9896_handle_t * handle)545 status_t TFA9896_DSPWriteTables(tfa9896_handle_t *handle)
546 {
547 status_t error = kStatus_TFA9896_Ok;
548
549 error = tfa_dsp_write_vsfwdelay_table(handle);
550 if (error == kStatus_TFA9896_Ok)
551 {
552 error = tfa_dsp_write_cvfracdelay_table(handle);
553 assert(error == kStatus_TFA9896_Ok);
554 }
555
556 TFA9896_SetBits(handle, TFA1_BF_RST, 1);
557 assert(error == kStatus_TFA9896_Ok);
558 TFA9896_SetBits(handle, TFA1_BF_RST, 0);
559 assert(error == kStatus_TFA9896_Ok);
560 return error;
561 }
562
TFA9896_ProcessPatchFile(tfa9896_handle_t * handle,int length,const unsigned char * bytes)563 status_t TFA9896_ProcessPatchFile(tfa9896_handle_t *handle, int length, const unsigned char *bytes)
564 {
565 unsigned short size;
566 int index;
567
568 status_t err = kStatus_TFA9896_Ok;
569 #if defined(DEMO_VERBOSE)
570 int i;
571 #endif
572
573 /* expect following format in patchBytes:
574 * 2 bytes length of I2C transaction in little endian, then the bytes, excluding the slave address which is added
575 * from the handle This repeats for the whole file
576 */
577 index = 0;
578
579 while (index < length)
580 {
581 /* extract little endian length */
582 size = bytes[index] + bytes[index + 1] * 256;
583 index += 2;
584 if ((index + size) > length)
585 {
586 /* too big, outside the buffer, error in the input data */
587 return kStatus_TFA9896_Bad_Parameter;
588 }
589 if ((size + 1) > MAX_I2C_LENGTH)
590 {
591 /* too big, must fit buffer */
592 return kStatus_TFA9896_Bad_Parameter;
593 }
594
595 #ifdef TFA9896_PRINT_DEBUG
596 /* TFA9896_Printf("Bytes to be written_patch:%d (index = %d bytes[index] = %d bytes[index+1] = %d\r\n",size,
597 index, bytes[index], bytes[index+1]);*/
598 #endif
599
600 err = CODEC_I2C_Send(handle->i2cHandle, handle->config->slaveAddress, 0U, 0U, (void *)(bytes + index), size);
601
602 if (err != kStatus_Success)
603 {
604 #ifdef TFA9896_PRINT_DEBUG
605 TFA9896_Printf("I2C write error at %d\r\n", size);
606 #endif
607 err = kStatus_TFA9896_I2C_Fatal;
608 break;
609 }
610 #if defined(DEMO_VERBOSE)
611 for (i = 0; i < transfer.dataSize; i++)
612 TFA9896_Printf("[%02x]-", (unsigned char)((unsigned char *)transfer.data + i));
613 TFA9896_Printf("\r\n");
614 #endif
615 index += size;
616 }
617
618 return err;
619 }
620
TFA9896_DspWritePreset(tfa9896_handle_t * handle,int length,const unsigned char * pPresetBytes)621 status_t TFA9896_DspWritePreset(tfa9896_handle_t *handle, int length, const unsigned char *pPresetBytes)
622 {
623 status_t error = kStatus_TFA9896_Ok;
624 if (pPresetBytes != 0)
625 {
626 TFA9896_Printf("Bytes to be written_preset_end:%d\n", length);
627 /* by design: keep the data opaque and no interpreting/calculation */
628 error = TFA9896_DspSetParam(handle, MODULE_SPEAKERBOOST, SB_PARAM_SET_PRESET, length, pPresetBytes);
629 TFA9896_Printf("Bytes written_preset_end:%d\n", length);
630 }
631 else
632 {
633 error = kStatus_TFA9896_Bad_Parameter;
634 }
635 return error;
636 }
637
TFA9896_DspWriteConfig(tfa9896_handle_t * handle,int length,const unsigned char * pConfigBytes)638 status_t TFA9896_DspWriteConfig(tfa9896_handle_t *handle, int length, const unsigned char *pConfigBytes)
639 {
640 status_t error = kStatus_TFA9896_Ok;
641 TFA9896_Printf("Bytes to be written_config:%d\n", length);
642 error = TFA9896_DspSetParam(handle, MODULE_SPEAKERBOOST, SB_PARAM_SET_CONFIG, length, pConfigBytes);
643 TFA9896_Printf("Bytes to written_config_end:%d\n", length);
644 return error;
645 }
646
TFA9896_DspWriteSpeakerParameters(tfa9896_handle_t * handle,int length,const unsigned char * pSpeakerBytes)647 status_t TFA9896_DspWriteSpeakerParameters(tfa9896_handle_t *handle, int length, const unsigned char *pSpeakerBytes)
648 {
649 status_t error;
650 if (pSpeakerBytes != 0)
651 {
652 TFA9896_Printf("Bytes to be written_speaker:%d\n", length);
653 /* by design: keep the data opaque and no interpreting/calculation */
654 error = TFA9896_DspSetParam(handle, MODULE_SPEAKERBOOST, SB_PARAM_SET_LSMODEL, length, pSpeakerBytes);
655
656 TFA9896_Printf("Bytes to written_speaker_end:%d\n", length);
657 }
658 else
659 {
660 error = kStatus_TFA9896_Bad_Parameter;
661 }
662
663 return error;
664 }
665
tfa_get_bf_value(const uint16_t bf,const uint16_t reg_value)666 uint16_t tfa_get_bf_value(const uint16_t bf, const uint16_t reg_value)
667 {
668 uint16_t msk, value;
669
670 /*
671 * bitfield enum:
672 * - 0..3 : len
673 * - 4..7 : pos
674 * - 8..15 : address
675 */
676 uint8_t len = bf & 0x0f;
677 uint8_t pos = (bf >> 4) & 0x0f;
678
679 msk = ((1 << (len + 1)) - 1) << pos;
680 value = (reg_value & msk) >> pos;
681
682 return value;
683 }
684
685 #ifdef TFA9890_DEVICE
tfa9890_dsp_system_stable(tfa9896_handle_t * handle,int * ready)686 static uint16_t tfa9890_dsp_system_stable(tfa9896_handle_t *handle, int *ready)
687 {
688 char error;
689 unsigned short status, mtp0;
690 int result;
691 uint8_t tries;
692 /************************/
693 result = tfa_read_reg(handle, TFA1_BF_AREFS);
694 if (result < 0)
695 {
696 error = -result;
697 goto errorExit;
698 }
699 status = (unsigned short)result;
700
701 /* if AMPS is set then we were already configured and running
702 * no need to check further
703 */
704 *ready = (tfa_get_bf_value(TFA1_BF_AMPS, status) == 1);
705 if (*ready) /* if ready go back */
706 {
707 return 0; /* will be kStatus_TFA9896_Ok */
708 }
709
710 /* check AREFS and CLKS: not ready if either is clear */
711 *ready = !((tfa_get_bf_value(TFA1_BF_AREFS, status) == 0) || (tfa_get_bf_value(TFA1_BF_CLKS, status) == 0));
712 if (!*ready) /* if not ready go back */
713 {
714 return 0; /* will be kStatus_TFA9896_Ok */
715 }
716
717 /* check MTPB
718 * mtpbusy will be active when the subsys copies MTP to I2C
719 * 2 times retry avoids catching this short mtpbusy active period
720 */
721 for (tries = 2; tries > 0; tries--)
722 {
723 result = TFA9896_GetBits(handle, TFA1_BF_MTPB);
724 if (result < 0)
725 {
726 error = -result;
727 goto errorExit;
728 }
729 status = (unsigned short)result;
730
731 /* check the contents of the STATUS register */
732 *ready = (status == 0);
733 if (*ready) /* if ready go on */
734 {
735 break;
736 }
737 }
738 if (tries == 0) /* ready will be 0 if retries exausted */
739 {
740 return 0;
741 }
742 /* check the contents of MTP register for non-zero,
743 * this indicates that the subsys is ready */
744
745 error = TFA9896_ReadRegister(handle, 0x84, &mtp0);
746 if (error)
747 {
748 goto errorExit;
749 }
750
751 *ready = (mtp0 != 0); /* The MTP register written? */
752
753 return error;
754
755 errorExit:
756 *ready = 0;
757 return error;
758 }
759 #endif
760
setOtc(tfa9896_handle_t * handle,int otcOn)761 status_t setOtc(tfa9896_handle_t *handle, int otcOn)
762 {
763 unsigned short mtp;
764 status_t err;
765 unsigned short status;
766 int mtpChanged = 0;
767 int i;
768
769 TFA9896_Printf("Inside setOtc\n");
770 err = TFA9896_ReadRegister(handle, 0x80, &mtp);
771 if (err != kStatus_TFA9896_Ok)
772 {
773 return err;
774 }
775 TFA9896_Printf("mtp:%d--mtp & 0x01:%d--otcOn:%d\n", mtp, (mtp & 0x01), otcOn);
776 /* set reset MTPEX bit if needed */
777 if ((mtp & 0x01) != otcOn)
778 {
779 TFA9896_Printf("writing into 0x5A and setting OTC\n");
780 /* need to change the OTC bit, set MTPEX=0 in any case */
781 err = TFA9896_WriteRegister(handle, 0x0B, (uint16_t)0x5A);
782 if (err != kStatus_TFA9896_Ok)
783 {
784 return err;
785 }
786 err = TFA9896_WriteRegister(handle, 0x80, (uint16_t)otcOn);
787 if (err != kStatus_TFA9896_Ok)
788 {
789 return err;
790 }
791 err = TFA9896_WriteRegister(handle, 0x62, 1 << 11);
792 if (err != kStatus_TFA9896_Ok)
793 {
794 return err;
795 }
796 mtpChanged = 1;
797 }
798 do
799 {
800 for (i = 0; i < 0xfff; i++)
801 ;
802 err = TFA9896_ReadRegister(handle, 0x00, &status);
803 if (err != kStatus_TFA9896_Ok)
804 {
805 return err;
806 }
807
808 } while ((status & 0x100) == 0x100);
809 assert((status & 0x100) == 0);
810 if (mtpChanged)
811 {
812 TFA9896_Printf("writing 0x01 into 0x70\n");
813 err = TFA9896_WriteRegister(handle, 0x70, (uint16_t)0x1);
814 if (err != kStatus_TFA9896_Ok)
815 {
816 return err;
817 }
818 }
819
820 return kStatus_TFA9896_Ok;
821 }
822
TFA9896_SetConfigured(tfa9896_handle_t * handle)823 status_t TFA9896_SetConfigured(tfa9896_handle_t *handle)
824 {
825 status_t error;
826 unsigned short value;
827 /* read the SystemControl register, modify the bit and write again */
828 error = TFA9896_ReadRegister(handle, 0x09, &value);
829 if (error != kStatus_TFA9896_Ok)
830 {
831 return error;
832 }
833 value |= 0x20;
834 error = TFA9896_WriteRegister(handle, 0x09, value);
835 return error;
836 }
837
TFA9896_DspReadMem(tfa9896_handle_t * handle,unsigned short start_offset,int num_words,int * pValues)838 status_t TFA9896_DspReadMem(tfa9896_handle_t *handle, unsigned short start_offset, int num_words, int *pValues)
839 {
840 status_t error = kStatus_TFA9896_Ok;
841 unsigned short cf_ctrl; /* the value to sent to the CF_CONTROLS register */
842 unsigned char bytes[MAX_PARAM_SIZE /*MAX_I2C_LENGTH*/];
843 int burst_size; /* number of words per burst size */
844 int bytes_per_word = 3;
845 int num_bytes;
846 int *p;
847 /* first set DMEM and AIF, leaving other bits intact */
848 error = TFA9896_ReadRegister(handle, 0x70, &cf_ctrl);
849 if (error != kStatus_TFA9896_Ok)
850 {
851 return error;
852 }
853 cf_ctrl &= ~0x000E; /* clear AIF & DMEM */
854 cf_ctrl |= (DMEM_XMEM << 1); /* set DMEM, leave AIF cleared for autoincrement */
855 error = TFA9896_WriteRegister(handle, 0x70, cf_ctrl);
856 if (error != kStatus_TFA9896_Ok)
857 {
858 return error;
859 }
860 error = TFA9896_WriteRegister(handle, 0x71, start_offset);
861 if (error != kStatus_TFA9896_Ok)
862 {
863 return error;
864 }
865 num_bytes = num_words * bytes_per_word;
866 p = pValues;
867 for (; num_bytes > 0;)
868 {
869 burst_size = ROUND_DOWN(MAX_I2C_LENGTH, bytes_per_word);
870 if (num_bytes < burst_size)
871 {
872 burst_size = num_bytes;
873 }
874 assert(burst_size <= sizeof(bytes));
875 error = TFA9896_ReadData(handle, 0x72, burst_size, bytes);
876 if (error != kStatus_TFA9896_Ok)
877 {
878 return error;
879 }
880 tfa9896_convert_bytes2data(burst_size, bytes, p);
881 num_bytes -= burst_size;
882 p += burst_size / bytes_per_word;
883 }
884 return kStatus_TFA9896_Ok;
885 }
886
TFA9896_DspExecuteRpc(tfa9896_handle_t * handle,unsigned char module_id,unsigned char param_id,int num_inbytes,unsigned char indata[],int num_outbytes,unsigned char outdata[])887 status_t TFA9896_DspExecuteRpc(tfa9896_handle_t *handle,
888 unsigned char module_id,
889 unsigned char param_id,
890 int num_inbytes,
891 unsigned char indata[],
892 int num_outbytes,
893 unsigned char outdata[])
894 {
895 status_t error;
896 int rpcStatus = STATUS_OK;
897 int i;
898
899 /* 1) write the id and data to the DSP XMEM */
900 error = writeParameter(handle, module_id, param_id, num_inbytes, indata);
901
902 /* 2) wake up the DSP and let it process the data */
903 if (error == kStatus_TFA9896_Ok)
904 {
905 error = executeParam(handle);
906 }
907
908 /* 3) wait for the ack */
909 if (error == kStatus_TFA9896_Ok)
910 {
911 error = waitResult(handle);
912 }
913
914 /* 4) check the RPC return value */
915 if (error == kStatus_TFA9896_Ok)
916 {
917 error = checkRpcStatus(handle, &rpcStatus);
918 }
919 if (error == kStatus_TFA9896_Ok)
920 {
921 if (rpcStatus != STATUS_OK)
922 {
923 /* DSP RPC call returned an error */
924 error = (status_t)(rpcStatus + kStatus_TFA9896_RpcBase);
925 }
926 }
927
928 if (error == kStatus_TFA9896_Ok)
929 {
930 /* 5) read the resulting data */
931 error = TFA9896_WriteRegister(handle, 0x71, 2 /*start_offset*/);
932 if (error != kStatus_TFA9896_Ok)
933 {
934 return error;
935 }
936 /* read in chunks, limited by max I2C length */
937 for (i = 0; i < num_outbytes;)
938 {
939 int burst_size = ROUND_DOWN(MAX_I2C_LENGTH, 3 /*bytes_per_word*/);
940 if ((num_outbytes - i) < burst_size)
941 {
942 burst_size = num_outbytes - i;
943 }
944 error = TFA9896_ReadData(handle, 0x72, burst_size, outdata + i);
945 if (error != kStatus_TFA9896_Ok)
946 {
947 return error;
948 }
949 i += burst_size;
950 }
951 }
952
953 return error;
954 }
955
TFA9896_CheckICROMversion(tfa9896_handle_t * handle,const unsigned char patchheader[])956 status_t TFA9896_CheckICROMversion(tfa9896_handle_t *handle, const unsigned char patchheader[])
957 {
958 status_t error = kStatus_TFA9896_Ok;
959 unsigned short checkrev;
960 unsigned short checkaddress;
961 int checkvalue;
962 int value = 0;
963 unsigned short status;
964 checkrev = patchheader[0];
965 if ((checkrev != 0xFF) && (checkrev != 0x96))
966 {
967 return kStatus_TFA9896_Not_Supported;
968 }
969 checkaddress = (patchheader[1] << 8) + patchheader[2];
970 checkvalue = (patchheader[3] << 16) + (patchheader[4] << 8) + patchheader[5];
971 if (checkaddress != 0xFFFF)
972 {
973 /* before reading XMEM, check if we can access the DSP */
974 error = TFA9896_ReadRegister(handle, 0x00, &status);
975 if (error == kStatus_TFA9896_Ok)
976 {
977 if ((status & 0x8000) != 0x8000)
978 {
979 /* one of Vddd, PLL and clocks not ok */
980 error = kStatus_TFA9896_DSP_not_running;
981 }
982 }
983 /* read some address register that allows checking the correct ROM version */
984 if (error == kStatus_TFA9896_Ok)
985 {
986 error = TFA9896_DspReadMem(handle, checkaddress, 1, &value);
987 }
988 if (error == kStatus_TFA9896_Ok)
989 {
990 if (value != checkvalue)
991 {
992 error = kStatus_TFA9896_Not_Supported;
993 }
994 }
995 }
996 return error;
997 }
998
tfa_write_reg(tfa9896_handle_t * handle,const uint16_t bf,const uint16_t reg_value)999 int tfa_write_reg(tfa9896_handle_t *handle, const uint16_t bf, const uint16_t reg_value)
1000 {
1001 status_t err;
1002
1003 /* bitfield enum - 8..15 : address */
1004 uint8_t address = (bf >> 8) & 0xff;
1005
1006 err = TFA9896_WriteRegister(handle, address, reg_value);
1007 if (err)
1008 return -err;
1009
1010 return 0;
1011 }
1012
TFA9896_DSP_System_Stable(tfa9896_handle_t * handle,int * ready)1013 status_t TFA9896_DSP_System_Stable(tfa9896_handle_t *handle, int *ready)
1014 {
1015 #ifndef TFA9890_DEVICE
1016 status_t error = kStatus_TFA9896_Ok;
1017 unsigned short status;
1018 int value;
1019
1020 /* check the contents of the STATUS register */
1021 value = tfa_read_reg(handle, TFA1_BF_AREFS);
1022 if (value < 0)
1023 {
1024 error = -value;
1025 *ready = 0;
1026 /* an error here can be fatal */
1027 TFA9896_Printf("FATAL ERROR#######\n");
1028 return error;
1029 }
1030 status = (unsigned short)value;
1031
1032 /* check AREFS and CLKS: not ready if either is clear */
1033 *ready = !((tfa_get_bf_value(TFA1_BF_AREFS, status) == 0) || (tfa_get_bf_value(TFA1_BF_CLKS, status) == 0) ||
1034 (tfa_get_bf_value(TFA1_BF_MTPB, status) == 1));
1035
1036 return error;
1037 #else
1038 return tfa9890_dsp_system_stable(handle, ready);
1039 #endif
1040 }
1041
1042 #ifdef TFA9896_DEBUG
stateFlagsStr(int stateFlags)1043 static char *stateFlagsStr(int stateFlags)
1044 {
1045 static char flags[10];
1046
1047 flags[0] = (stateFlags & (0x1 << tfa9896_SpeakerBoost_ActivityLive)) ? 'A' : 'a';
1048 flags[1] = (stateFlags & (0x1 << tfa9896_SpeakerBoost_S_CtrlLive)) ? 'S' : 's';
1049 flags[2] = (stateFlags & (0x1 << tfa9896_SpeakerBoost_MutedLive)) ? 'M' : 'm';
1050 flags[3] = (stateFlags & (0x1 << tfa9896_SpeakerBoost_X_CtrlLive)) ? 'X' : 'x';
1051 flags[4] = (stateFlags & (0x1 << tfa9896_SpeakerBoost_T_CtrlLive)) ? 'T' : 't';
1052 flags[5] = (stateFlags & (0x1 << tfa9896_SpeakerBoost_NewModelLive)) ? 'L' : 'l';
1053 flags[6] = (stateFlags & (0x1 << tfa9896_SpeakerBoost_VolumeRdyLive)) ? 'V' : 'v';
1054 flags[7] = (stateFlags & (0x1 << tfa9896_SpeakerBoost_DamagedLive)) ? 'D' : 'd';
1055 flags[8] = (stateFlags & (0x1 << tfa9896_SpeakerBoost_SignalClippingLive)) ? 'C' : 'c';
1056
1057 flags[9] = 0;
1058 return flags;
1059 }
1060 #endif
1061
1062 /* Execute RPC protocol to read something from the DSP */
TFA9896_DspGetParam(tfa9896_handle_t * handle,unsigned char module_id,unsigned char param_id,int num_bytes,unsigned char data[])1063 status_t TFA9896_DspGetParam(
1064 tfa9896_handle_t *handle, unsigned char module_id, unsigned char param_id, int num_bytes, unsigned char data[])
1065 {
1066 status_t error;
1067 unsigned short cf_ctrl = 0x0002; /* the value to be sent to the CF_CONTROLS register: cf_req=00000000, cf_int=0,
1068 cf_aif=0, cf_dmem=XMEM=01, cf_rst_dsp=0 */
1069 unsigned short cf_mad = 0x0001; /* memory address to be accessed (0 : Status, 1 : ID, 2 : parameters) */
1070 unsigned short cf_status; /* the contents of the CF_STATUS register */
1071 int rpcStatus = STATUS_OK;
1072
1073 if (handle->config->slaveAddress == 0x1C)
1074 {
1075 /* cannot read */
1076 return kStatus_TFA9896_Bad_Parameter;
1077 }
1078 error = check_size(DMEM_XMEM, num_bytes);
1079
1080 if (error == kStatus_TFA9896_Ok)
1081 {
1082 if ((num_bytes <= 0) || (num_bytes > MAX_PARAM_SIZE))
1083 {
1084 return kStatus_TFA9896_Bad_Parameter;
1085 }
1086 }
1087 #ifdef OPTIMIZED_RPC
1088 {
1089 /* minimize the number of I2C transactions by making use of the autoincrement in I2C */
1090 unsigned char buffer[7];
1091 /* first the data for CF_CONTROLS */
1092 buffer[0] = (unsigned char)((cf_ctrl >> 8) & 0xFF);
1093 buffer[1] = (unsigned char)(cf_ctrl & 0xFF);
1094 /* write the contents of CF_MAD which is the subaddress following CF_CONTROLS */
1095 buffer[2] = (unsigned char)((cf_mad >> 8) & 0xFF);
1096 buffer[3] = (unsigned char)(cf_mad & 0xFF);
1097 /* write the module and RPC id into CF_MEM, which follows CF_MAD */
1098 buffer[4] = 0;
1099 buffer[5] = module_id + 128;
1100 buffer[6] = param_id;
1101 error = TFA9896_WriteData(handle, 0x70, sizeof(buffer), buffer);
1102 }
1103 #else
1104 /* 1) write the id and data to the DSP XMEM */
1105 if (error == kStatus_TFA9896_Ok)
1106 {
1107 error = TFA9896_WriteRegister(handle, 0x70, cf_ctrl);
1108 }
1109 if (error == kStatus_TFA9896_Ok)
1110 {
1111 error = TFA9896_WriteRegister(handle, 0x71, cf_mad);
1112 }
1113 if (error == kStatus_TFA9896_Ok)
1114 {
1115 unsigned char id[3];
1116 id[0] = 0;
1117 id[1] = module_id + 128;
1118 id[2] = param_id;
1119 /* only try MEM once, if error, need to resend mad as well */
1120 error = TFA9896_WriteData(handle, 0x72, 3, id);
1121 }
1122 #endif
1123 /* 2) wake up the DSP and let it process the data */
1124 if (error == kStatus_TFA9896_Ok)
1125 {
1126 cf_ctrl |= (1 << 8) | (1 << 4); /* set the cf_req1 and cf_int bit */
1127
1128 error = TFA9896_WriteRegister(handle, 0x70, (uint16_t)cf_ctrl);
1129 }
1130 /* 3) wait for the ack */
1131 if (error == kStatus_TFA9896_Ok)
1132 {
1133 int tries = 0;
1134 do
1135 {
1136 error = TFA9896_ReadRegister(handle, 0x73, &cf_status);
1137 tries++;
1138 } while (
1139 (error == kStatus_TFA9896_Ok) && ((cf_status & 0x0100) == 0) &&
1140 (tries < TFA9896_API_WAITRESULT_NTRIES)); /* don't wait forever, DSP is pretty quick to respond (< 1ms) */
1141 if (tries >= TFA9896_API_WAITRESULT_NTRIES)
1142 {
1143 /* something wrong with communication with DSP */
1144 return kStatus_TFA9896_DSP_not_running;
1145 }
1146 }
1147 /* 4) check the RPC return value */
1148 if (error == kStatus_TFA9896_Ok)
1149 {
1150 error = checkRpcStatus(handle, &rpcStatus);
1151 }
1152 if (error == kStatus_TFA9896_Ok)
1153 {
1154 if (rpcStatus != STATUS_OK)
1155 {
1156 /* DSP RPC call returned an error */
1157 error = (status_t)(rpcStatus + kStatus_TFA9896_RpcBase);
1158 }
1159 }
1160 /* 5) read the resulting data */
1161 if (error == kStatus_TFA9896_Ok)
1162 {
1163 cf_mad = 0x0002; /* memory address to be accessed (0 : Status, 1 : ID, 2 : parameters) */
1164 error = TFA9896_WriteRegister(handle, 0x71, (uint16_t)cf_mad);
1165 }
1166 if (error == kStatus_TFA9896_Ok)
1167 {
1168 int offset = 0;
1169 int chunk_size = ROUND_DOWN(NXP_I2C_MAX_SIZE, 3 /* XMEM word size */);
1170 int remaining_bytes = num_bytes;
1171 /* due to autoincrement in cf_ctrl, next write will happen at the next address */
1172 while ((error == kStatus_TFA9896_Ok) && (remaining_bytes > 0))
1173 {
1174 if (remaining_bytes < 252)
1175 {
1176 chunk_size = remaining_bytes;
1177 }
1178 /* else chunk_size remains at initialize value above*/
1179 error = TFA9896_ReadData(handle, 0x72, chunk_size, data + offset);
1180 remaining_bytes -= chunk_size;
1181 offset += chunk_size;
1182 }
1183 }
1184 return error;
1185 }
1186
1187 #ifdef TFA9896_LIVEDATA_CAPTURE
TFA9896_DspGetStateInfo(tfa9896_handle_t * handle,tfa9896_StateInfoLive_t * pInfo)1188 status_t TFA9896_DspGetStateInfo(tfa9896_handle_t *handle, tfa9896_StateInfoLive_t *pInfo)
1189 {
1190 status_t error = kStatus_TFA9896_Ok;
1191 int24 data[FW_STATE_MAX_SIZE]; /* allocate worst case */
1192 unsigned char bytes[FW_STATE_MAX_SIZE * 3];
1193 int stateSize =
1194 FW_STATE_SIZE; /* contains the actual amount of parameters transferred, depends on IC and ROM code version */
1195 int i;
1196
1197 assert(pInfo != 0);
1198
1199 /* init to default value to have sane values even when some features aren't supported */
1200 for (i = 0; i < FW_STATE_MAX_SIZE; i++)
1201 {
1202 data[i] = 0;
1203 }
1204
1205 error = TFA9896_DspGetParam(handle, MODULE_FRAMEWORK, FW_PARAM_GET_STATE, 3 * stateSize, bytes);
1206 if (error != kStatus_TFA9896_Ok)
1207 {
1208 if (error == kStatus_TFA9896_RpcParamId)
1209 {
1210 /* old ROM code, ask SpeakerBoost and only do first portion */
1211 stateSize = 8;
1212 error = TFA9896_DspGetParam(handle, MODULE_SPEAKERBOOST, SB_PARAM_GET_STATE, 3 * stateSize, bytes);
1213 }
1214 else
1215 {
1216 return error;
1217 }
1218 }
1219 tfa9896_convert_bytes2data(3 * stateSize, bytes, data);
1220 pInfo->agcGain = (float)data[0] / (1 << (23 - SPKRBST_AGCGAIN_EXP)); /* /2^23*2^(SPKRBST_AGCGAIN_EXP) */
1221 pInfo->limGain = (float)data[1] / (1 << (23 - SPKRBST_LIMGAIN_EXP)); /* /2^23*2^(SPKRBST_LIMGAIN_EXP) */
1222 pInfo->sMax = (float)data[2] / (1 << (23 - SPKRBST_HEADROOM)); /* /2^23*2^(SPKRBST_HEADROOM) */
1223 pInfo->T = data[3] / (1 << (23 - SPKRBST_TEMPERATURE_EXP)); /* /2^23*2^(def.SPKRBST_TEMPERATURE_EXP) */
1224 pInfo->statusFlag = data[4];
1225 pInfo->X1 = (float)data[5] / (1 << (23 - SPKRBST_HEADROOM)); /* /2^23*2^(SPKRBST_HEADROOM) */
1226
1227 pInfo->X2 = 0; /* /2^23*2^(SPKRBST_HEADROOM) */
1228 pInfo->Re = (float)data[6] / (1 << (23 - SPKRBST_TEMPERATURE_EXP)); /* /2^23*2^(SPKRBST_TEMPERATURE_EXP) */
1229 pInfo->shortOnMips = data[7];
1230 return error;
1231 }
1232
dump_state_infoLive(tfa9896_StateInfoLive_t * pState)1233 void dump_state_infoLive(tfa9896_StateInfoLive_t *pState)
1234 {
1235 #ifdef TFA9896_DEBUG
1236 TFA9896_Printf(
1237 "state: flags %s, agcGain %2.1f\tlimGain %2.1f\tsMax %2.1f\tT %d\tX1 %2.1f\tX2 %2.1f\tRe %2.2f\tshortOnMips "
1238 "%d\n",
1239 stateFlagsStr(pState->statusFlag), pState->agcGain, pState->limGain, pState->sMax, pState->T, pState->X1,
1240 pState->X2, pState->Re, pState->shortOnMips);
1241 #endif
1242 }
1243 #endif
1244
TFA9896_WaitCalibrateDone(tfa9896_handle_t * handle,int * calibrateDone)1245 status_t TFA9896_WaitCalibrateDone(tfa9896_handle_t *handle, int *calibrateDone)
1246 {
1247 status_t err;
1248 int tries = 0;
1249 unsigned short mtp;
1250 #define WAIT_TRIES 30000
1251
1252 err = TFA9896_ReadRegister(handle, 0x80, &mtp);
1253
1254 /* in case of calibrate once wait for MTPEX */
1255 if (mtp & 0x1)
1256 {
1257 while ((*calibrateDone == 0) && (tries < TFA9896_API_WAITRESULT_NTRIES))
1258 { /* TODO optimise with wait estimation */
1259 err = TFA9896_ReadRegister(handle, 0x80, &mtp);
1260 *calibrateDone = (mtp & 0x2); /* check MTP bit1 (MTPEX) */
1261 tries++;
1262 }
1263 }
1264 else /* poll xmem for calibrate always */
1265 {
1266 while ((*calibrateDone == 0) && (tries < WAIT_TRIES))
1267 { /* TODO optimise with wait estimation*/
1268 err = TFA9896_DspReadMem(handle, 231, 1, calibrateDone);
1269 tries++;
1270 }
1271 if (tries == WAIT_TRIES)
1272 {
1273 TFA9896_Printf("calibrateDone 231 timedout\n");
1274 }
1275 }
1276 return err;
1277 }
1278
TFA9896_DspGetCalibrationImpedance(tfa9896_handle_t * handle,float * pRe25)1279 status_t TFA9896_DspGetCalibrationImpedance(tfa9896_handle_t *handle, float *pRe25)
1280 {
1281 status_t error = kStatus_TFA9896_Ok;
1282 unsigned char bytes[3];
1283 int24 data[1];
1284 int calibrateDone;
1285
1286 assert(pRe25 != 0);
1287 *pRe25 = 0.0f; /* default 0.0 */
1288 {
1289 error = TFA9896_DspReadMem(handle, 231, 1, &calibrateDone);
1290 if (error == kStatus_TFA9896_Ok)
1291 {
1292 if (!calibrateDone)
1293 {
1294 /* return the default */
1295 return error;
1296 }
1297 error = TFA9896_DspGetParam(handle, MODULE_SPEAKERBOOST, 0x85, 3, bytes);
1298 }
1299 if (error == kStatus_TFA9896_Ok)
1300 {
1301 tfa9896_convert_bytes2data(3, bytes, data);
1302 *pRe25 = ((float)data[0] / (1 << (23 - SPKRBST_TEMPERATURE_EXP)) * 1024) /
1303 1000; /* /2^23*2^(def.SPKRBST_TEMPERATURE_EXP) */
1304 }
1305 }
1306 return error;
1307 }
1308
TFA9896_DSP_Write_Mem_Word(tfa9896_handle_t * handle,unsigned short address,int value,int memtype)1309 status_t TFA9896_DSP_Write_Mem_Word(tfa9896_handle_t *handle, unsigned short address, int value, int memtype)
1310 {
1311 status_t error = kStatus_TFA9896_Ok;
1312 unsigned char bytes[3];
1313
1314 TFA9896_SetBits(handle, TFA1_BF_DMEM, (uint16_t)memtype);
1315 error = -tfa_write_reg(handle, TFA1_BF_MADD, address);
1316 if (error != kStatus_TFA9896_Ok)
1317 {
1318 return error;
1319 }
1320 tfa9896_convert_data2bytes(1, &value, bytes);
1321 error = TFA9896_WriteData(handle, 0x720f >> 8, 3, bytes);
1322
1323 return error;
1324 }
1325
1326 /*************************/
1327 #ifdef TFA9896_LIVEDATA_CAPTURE
tfa9896GetSpeakerModel(tfa9896_handle_t * handle,int xmodel,tfa9896SPKRBST_SpkrModel_t * record)1328 status_t tfa9896GetSpeakerModel(tfa9896_handle_t *handle, int xmodel, tfa9896SPKRBST_SpkrModel_t *record)
1329 {
1330 status_t error = kStatus_TFA9896_Ok;
1331 unsigned char bytes[3 * 141];
1332 int24 data[141];
1333 int i = 0;
1334
1335 memset(bytes, 0, 423);
1336
1337 /*PARAM_GET_LSMODELW*/
1338 error = TFA9896_DspGetParam(handle, 1, PARAM_GET_LSMODEL, 423, bytes);
1339 if (error != kStatus_TFA9896_Ok)
1340 {
1341 return error;
1342 }
1343
1344 tfa9896_convert_bytes2data(sizeof(bytes), bytes, data);
1345
1346 for (i = 0; i < 128; i++)
1347 {
1348 /*record->pFIR[i] = (double)data[i] / ((1 << 23) * 2);*/
1349 record->pFIR[i] = (double)data[i] / (1 << 22);
1350 }
1351
1352 record->Shift_FIR = data[i++]; /* Exponent of HX data*/
1353 record->leakageFactor = (float)data[i++] / (1 << (23)); /* Excursion model integration leakage*/
1354 record->ReCorrection = (float)data[i++] / (1 << (23)); /* Correction factor for Re*/
1355 record->xInitMargin = (float)data[i++] / (1 << (23 - 2)); /* (can change) Margin on excursion model during startup*/
1356 record->xDamageMargin =
1357 (float)data[i++] / (1 << (23 - 2)); /* Margin on excursion modelwhen damage has been detected*/
1358 record->xMargin = (float)data[i++] / (1 << (23 - 2)); /* Margin on excursion model activated when LookaHead is 0*/
1359 record->Bl = (float)data[i++] / (1 << (23 - 2)); /* Loudspeaker force factor*/
1360 record->fRes = data[i++]; /* (can change) Estimated Speaker Resonance Compensation Filter cutoff frequency*/
1361 record->fResInit = data[i++]; /* Initial Speaker Resonance Compensation Filter cutoff frequency*/
1362 record->Qt = (float)data[i++] / (1 << (23 - 6)); /* Speaker Resonance Compensation Filter Q-factor*/
1363 record->xMax = (float)data[i++] / (1 << (23 - 7)); /* Maximum excursion of the speaker membrane*/
1364 record->tMax = (float)data[i++] / (1 << (23 - 9)); /* Maximum Temperature of the speaker coil*/
1365 record->tCoefA = (float)data[i++] / (1 << 23); /* (can change) Temperature coefficient*/
1366
1367 return error;
1368 }
1369
dump_speaker_model(tfa9896SPKRBST_SpkrModel_t * pState,tfa9896_handle_t * handle)1370 void dump_speaker_model(tfa9896SPKRBST_SpkrModel_t *pState, tfa9896_handle_t *handle)
1371 {
1372 TFA9896_Printf("FRes:%d--SPKS:%d\n", pState->fRes, TFA9896_GetBits(handle, TFA1_BF_SPKS));
1373 }
1374 #endif
1375
TFA9896_PrintCalibration(tfa9896_handle_t * handle)1376 status_t TFA9896_PrintCalibration(tfa9896_handle_t *handle)
1377 {
1378 status_t err = kStatus_TFA9896_Ok;
1379 #ifdef TFA9896_DEBUG
1380 unsigned char bytes[6] = {0};
1381 int24 data[2];
1382 float mohm;
1383
1384 err = TFA9896_DspGetParam(handle, MODULE_SPEAKERBOOST, SB_PARAM_GET_RE0, 3, bytes);
1385 if (err != kStatus_TFA9896_Ok)
1386 {
1387 return err;
1388 }
1389
1390 tfa9896_convert_bytes2data(3, bytes, data);
1391 mohm = ((float)data[0] * 1024) / TFA1_FW_ReZ_SCALE;
1392
1393 TFA9896_Printf(" Calibrated value :%1.2f mOhms :\n", (mohm * 1024) / 1000);
1394 #endif
1395
1396 return err;
1397 }
1398
TFA9896_SetOneTimeCalibration(tfa9896_handle_t * handle)1399 status_t TFA9896_SetOneTimeCalibration(tfa9896_handle_t *handle)
1400 {
1401 unsigned short mtp = 0;
1402 status_t err = kStatus_TFA9896_Ok;
1403 int tries = 0, mtpBusy = 0;
1404 int i;
1405 /* Read MTP register*/
1406 TFA9896_Printf("totest\n");
1407 /* Set MTPOTC=1*/
1408 mtp |= 0x01;
1409 err = TFA9896_WriteRegister(handle, 0x40, (uint16_t)0x5A6B);
1410 if (err != kStatus_TFA9896_Ok)
1411 {
1412 return err;
1413 }
1414 err = TFA9896_WriteRegister(handle, 0x0B, (uint16_t)0x005A);
1415 if (err != kStatus_TFA9896_Ok)
1416 {
1417 return err;
1418 }
1419 err = TFA9896_WriteRegister(handle, 0x40, (uint16_t)0);
1420 if (err != kStatus_TFA9896_Ok)
1421 {
1422 return err;
1423 }
1424 /* Update contents of MTP register*/
1425 err = TFA9896_WriteRegister(handle, 0x80, mtp);
1426 if (err != kStatus_TFA9896_Ok)
1427 {
1428 return err;
1429 }
1430 err = TFA9896_SetBits(handle, TFA1_BF_CIMTP, 0x01);
1431 if (err != kStatus_TFA9896_Ok)
1432 {
1433 return err;
1434 }
1435 err = TFA9896_WriteRegister(handle, 0x40, (uint16_t)0x5A6B);
1436 if (err != kStatus_TFA9896_Ok)
1437 {
1438 return err;
1439 }
1440 err = TFA9896_WriteRegister(handle, 0x0B, (uint16_t)0);
1441 if (err != kStatus_TFA9896_Ok)
1442 {
1443 return err;
1444 }
1445 err = TFA9896_WriteRegister(handle, 0x40, (uint16_t)0);
1446 if (err != kStatus_TFA9896_Ok)
1447 {
1448 return err;
1449 }
1450 tries = 0;
1451 do
1452 {
1453 tries++;
1454 for (i = 0; i < 0xfff; i++)
1455 ;
1456 mtpBusy = TFA9896_GetBits(handle, TFA1_BF_MTPB);
1457 } while ((mtpBusy == 0x01) && (tries < TFA9896_API_WAITRESULT_NTRIES));
1458
1459 if (tries == TFA9896_API_WAITRESULT_NTRIES)
1460 {
1461 TFA9896_Printf("MTP Busy timedout\n");
1462 err = kStatus_TFA9896_StateTimedOut;
1463 }
1464
1465 return err;
1466 }
1467
TFA9896_SetFactoryValues(tfa9896_handle_t * handle)1468 status_t TFA9896_SetFactoryValues(tfa9896_handle_t *handle)
1469 {
1470 unsigned short mtp = 0, ron, regRead, xor;
1471 status_t err = kStatus_TFA9896_Ok;
1472 int tries = 0, mtpBusy = 0;
1473 int i;
1474
1475 TFA9896_Printf("totest\n");
1476 /*********Hardcoding MTPEX and MTPOTC***************************/
1477 mtp |= 0x03;
1478 /*********Hardcoding Ron in MTP to 8 ohm***************************/
1479 ron = 0x1F40;
1480 err = TFA9896_ReadRegister(handle, 0x8B, ®Read);
1481 if (err != kStatus_TFA9896_Ok)
1482 {
1483 return err;
1484 }
1485 xor = regRead ^ 0x005A;
1486 err = TFA9896_WriteRegister(handle, 0x40, (uint16_t)0x5A6B);
1487 if (err != kStatus_TFA9896_Ok)
1488 {
1489 return err;
1490 }
1491 err = TFA9896_WriteRegister(handle, 0x0B, (uint16_t)0x005A);
1492 if (err != kStatus_TFA9896_Ok)
1493 {
1494 return err;
1495 }
1496 err = TFA9896_WriteRegister(handle, 0x60, (uint16_t) xor);
1497 if (err != kStatus_TFA9896_Ok)
1498 {
1499 return err;
1500 }
1501 err = TFA9896_WriteRegister(handle, 0x40, (uint16_t)0);
1502 if (err != kStatus_TFA9896_Ok)
1503 {
1504 return err;
1505 }
1506 err = TFA9896_ReadRegister(handle, 0x32, ®Read);
1507 if (err != kStatus_TFA9896_Ok)
1508 {
1509 return err;
1510 }
1511 /*Update contents of MTP register*/
1512 err = TFA9896_WriteRegister(handle, 0x83, ron);
1513 if (err != kStatus_TFA9896_Ok)
1514 {
1515 return err;
1516 }
1517 err = TFA9896_WriteRegister(handle, 0x80, mtp);
1518 if (err != kStatus_TFA9896_Ok)
1519 {
1520 return err;
1521 }
1522 err = TFA9896_SetBits(handle, TFA1_BF_CIMTP, 0x01);
1523 if (err != kStatus_TFA9896_Ok)
1524 {
1525 return err;
1526 }
1527 err = TFA9896_WriteRegister(handle, 0x40, (uint16_t)0x5A6B);
1528 if (err != kStatus_TFA9896_Ok)
1529 {
1530 return err;
1531 }
1532 err = TFA9896_WriteRegister(handle, 0x0B, (uint16_t)0);
1533 if (err != kStatus_TFA9896_Ok)
1534 {
1535 return err;
1536 }
1537 err = TFA9896_WriteRegister(handle, 0x40, (uint16_t)0);
1538 if (err != kStatus_TFA9896_Ok)
1539 {
1540 return err;
1541 }
1542 tries = 0;
1543 do
1544 {
1545 tries++;
1546 for (i = 0; i < 0xfff; i++)
1547 ;
1548 mtpBusy = TFA9896_GetBits(handle, TFA1_BF_MTPB);
1549 } while ((mtpBusy == 0x01) && (tries < TFA9896_API_WAITRESULT_NTRIES));
1550
1551 if (tries == TFA9896_API_WAITRESULT_NTRIES)
1552 {
1553 TFA9896_Printf("MTP Busy timedout\n");
1554 err = kStatus_TFA9896_StateTimedOut;
1555 }
1556
1557 return err;
1558 }
1559
TFA9896_ClearOneTimeCalibration(tfa9896_handle_t * handle)1560 status_t TFA9896_ClearOneTimeCalibration(tfa9896_handle_t *handle)
1561 {
1562 status_t err = kStatus_TFA9896_Ok;
1563 unsigned short mtp;
1564 int tries = 0, mtpBusy = 0;
1565 int i;
1566
1567 /* Read MTP register */
1568 err = TFA9896_ReadRegister(handle, 0x80, &mtp);
1569 if (err != kStatus_TFA9896_Ok)
1570 {
1571 return err;
1572 }
1573 /* Set MTPEX=0 and MTPOTC=0 to clear current calibration status*/
1574 mtp &= ~(0x03);
1575 err = TFA9896_WriteRegister(handle, 0x40, (uint16_t)0x5A6B);
1576 if (err != kStatus_TFA9896_Ok)
1577 {
1578 return err;
1579 }
1580 err = TFA9896_WriteRegister(handle, 0x0B, (uint16_t)0x005A);
1581 if (err != kStatus_TFA9896_Ok)
1582 {
1583 return err;
1584 }
1585 err = TFA9896_WriteRegister(handle, 0x40, (uint16_t)0);
1586 if (err != kStatus_TFA9896_Ok)
1587 {
1588 return err;
1589 }
1590 /* Update contents of MTP register*/
1591 err = TFA9896_WriteRegister(handle, 0x80, mtp);
1592 if (err != kStatus_TFA9896_Ok)
1593 {
1594 return err;
1595 }
1596 err = TFA9896_SetBits(handle, TFA1_BF_CIMTP, 0x01);
1597 if (err != kStatus_TFA9896_Ok)
1598 {
1599 return err;
1600 }
1601
1602 tries = 0;
1603 do
1604 {
1605 tries++;
1606 for (i = 0; i < 0xfff; i++)
1607 ;
1608 mtpBusy = TFA9896_GetBits(handle, TFA1_BF_MTPB);
1609 } while ((mtpBusy == 0x01) && (tries < TFA9896_API_WAITRESULT_NTRIES));
1610
1611 if (tries == TFA9896_API_WAITRESULT_NTRIES)
1612 {
1613 TFA9896_Printf("MTP Busy timedout\n");
1614 err = kStatus_TFA9896_StateTimedOut;
1615 }
1616
1617 return err;
1618 }
1619
TFA9896_SetOVPBypass(tfa9896_handle_t * handle)1620 status_t TFA9896_SetOVPBypass(tfa9896_handle_t *handle)
1621 {
1622 status_t err;
1623
1624 unsigned short value, xor;
1625
1626 /* read the SystemControl register, modify the bit and write again */
1627 err = TFA9896_WriteRegister(handle, 0x40, 0x5A6B);
1628 if (err != kStatus_TFA9896_Ok)
1629 {
1630 return err;
1631 }
1632
1633 err = TFA9896_ReadRegister(handle, 0x8B, &value);
1634 if (err != kStatus_TFA9896_Ok)
1635 {
1636 return err;
1637 }
1638
1639 xor = value ^ 0x005A;
1640 err = TFA9896_WriteRegister(handle, 0x60, xor);
1641 if (err != kStatus_TFA9896_Ok)
1642 {
1643 return err;
1644 }
1645
1646 err = TFA9896_ReadRegister(handle, 0x45, &value);
1647 if (err != kStatus_TFA9896_Ok)
1648 {
1649 return err;
1650 }
1651 TFA9896_Printf("before 0x45 regsiter is:%d\n", value);
1652 value |= (0x01 << 9);
1653
1654 err = TFA9896_WriteRegister(handle, 0x45, value);
1655 if (err != kStatus_TFA9896_Ok)
1656 {
1657 return err;
1658 }
1659
1660 err = TFA9896_ReadRegister(handle, 0x45, &value);
1661 if (err != kStatus_TFA9896_Ok)
1662 {
1663 return err;
1664 }
1665
1666 TFA9896_Printf("after 0x45 regsiter is:%d\n", value);
1667
1668 return err;
1669 }
1670
TFA9896_SetMute(tfa9896_handle_t * handle,tfa9896_mute_t mute)1671 status_t TFA9896_SetMute(tfa9896_handle_t *handle, tfa9896_mute_t mute)
1672 {
1673 status_t error;
1674 unsigned short audioctrl_value;
1675 unsigned short sysctrl_value;
1676 error = TFA9896_ReadRegister(handle, TFA9896_AUDIO_CTR, &audioctrl_value);
1677 if (error != kStatus_TFA9896_Ok)
1678 {
1679 return error;
1680 }
1681 error = TFA9896_ReadRegister(handle, TFA9896_SYS_CTRL, &sysctrl_value);
1682
1683 if (error != kStatus_TFA9896_Ok)
1684 {
1685 return error;
1686 }
1687 switch (mute)
1688 {
1689 case Mute_Off:
1690 /* previous state can be digital or amplifier mute,
1691 * clear the cf_mute and set the enbl_amplifier bits
1692 *
1693 * To reduce PLOP at power on it is needed to switch the
1694 * amplifier on with the DCDC in follower mode (enbl_boost = 0 ?).
1695 * This workaround is also needed when toggling the powerdown bit!
1696 */
1697 audioctrl_value &= ~(TFA9896_AUDIO_CTR_CFSM_MSK);
1698 sysctrl_value |= TFA9896_SYS_CTRL_AMPE_MSK;
1699 sysctrl_value |= TFA9896_SYS_CTRL_DCA_MSK;
1700 break;
1701 case Mute_Digital:
1702 /* expect the amplifier to run */
1703 /* set the cf_mute bit */
1704 audioctrl_value |= TFA9896_AUDIO_CTR_CFSM_MSK;
1705 /* set the enbl_amplifier bit */
1706 sysctrl_value |= (TFA9896_SYS_CTRL_AMPE_MSK);
1707 /* clear active mode */
1708 sysctrl_value &= ~(TFA9896_SYS_CTRL_DCA_MSK);
1709 break;
1710 case Mute_Amplifier:
1711 /* clear the cf_mute bit */
1712 audioctrl_value &= ~TFA9896_AUDIO_CTR_CFSM_MSK;
1713 /* clear the enbl_amplifier bit and active mode */
1714 sysctrl_value &= ~(TFA9896_SYS_CTRL_AMPE_MSK | TFA9896_SYS_CTRL_DCA_MSK);
1715 break;
1716 default:
1717 error = kStatus_TFA9896_Bad_Parameter;
1718 }
1719 if (error != kStatus_TFA9896_Ok)
1720 {
1721 return error;
1722 }
1723 error = TFA9896_WriteRegister(handle, TFA9896_AUDIO_CTR, audioctrl_value);
1724 if (error != kStatus_TFA9896_Ok)
1725 {
1726 return error;
1727 }
1728 error = TFA9896_WriteRegister(handle, TFA9896_SYS_CTRL, sysctrl_value);
1729
1730 return error;
1731 }
1732