2 /*
3 Copyright (c) 2016, Texas Instruments Incorporated - http://www.ti.com/
4 All rights reserved.
6 * Redistribution and use in source and binary forms, with or without
7 * modification, are permitted provided that the following conditions
8 * are met:
9 *
10 * Redistributions of source code must retain the above copyright
11 * notice, this list of conditions and the following disclaimer.
12 *
13 * Redistributions in binary form must reproduce the above copyright
14 * notice, this list of conditions and the following disclaimer in the
15 * documentation and/or other materials provided with the
16 * distribution.
17 *
18 * Neither the name of Texas Instruments Incorporated nor the names of
19 * its contributors may be used to endorse or promote products derived
20 * from this software without specific prior written permission.
21 *
22 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
23 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
24 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
25 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
26 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
27 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
28 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
29 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
30 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
31 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
32 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
33 *
34 */
36 /**
37 * \file audio_dc_config.c
38 *
39 * \brief Configures Audio daughter card HW modules
40 *
41 */
43 #include "audio_dc_cfg.h"
44 #include "vproccmds_a.h"
45 #include <stdarg.h>
46 #include "string.h"
48 Platform_STATUS audioHDMIConfig(void);
50 #define HSR4_I2C_ADDR 0x5D
51 #define HSR4_I2C_PORT_NUM I2C_PORT_1
53 /* ------------------------------------------------------------------------ *
54 * Prototypes *
55 * ------------------------------------------------------------------------ */
57 /**
58 * \brief Initializes ADC module
59 *
60 * This function initializes and configures the ADC modules
61 * on audio daughter card
62 *
63 * \param devId [IN] ADC Device Id
64 * \param config [IN] ADC configuration parameters
65 *
66 * \return Platform_EOK on Success or error code
67 */
68 Platform_STATUS audioAdcConfig(AdcDevId devId, AdcConfig *config)
69 {
70 Platform_STATUS status;
72 if(config == NULL)
73 {
74 IFPRINT(platform_write("Invalid Inputs\n"));
75 return (Platform_EINVALID);
76 }
78 /* Initialize all the HW instances of ADC */
79 status = platformAudioAdcInit(devId);
80 if(status != Platform_EOK)
81 {
82 IFPRINT(platform_write("audioAdcConfig : platformaudioAdcConfig Failed\n"));
83 return (status);
84 }
86 /* Set ADC channel gain */
87 status = platformAudioAdcSetGain(devId, ADC_CH_ALL, config->gain);
88 if(status != Platform_EOK)
89 {
90 IFPRINT(platform_write("audioAdcConfig : platformAudioAdcSetGain Failed\n"));
91 return (status);
92 }
94 /* Configure Left input mux for ADC1L */
95 status = platformAudioAdcSetLeftInputMux(devId, ADC_CH1_LEFT,
96 config->adc1LMux);
97 if(status != Platform_EOK)
98 {
99 IFPRINT(platform_write("audioAdcConfig : platformAudioAdcSetLeftInputMux Failed\n"));
100 return (status);
101 }
103 /* Configure Left input mux for ADC2L*/
104 status = platformAudioAdcSetLeftInputMux(devId, ADC_CH2_LEFT,
105 config->adc2LMux);
106 if(status != Platform_EOK)
107 {
108 IFPRINT(platform_write("audioAdcConfig : platformAudioAdcSetLeftInputMux Failed\n"));
109 return (status);
110 }
112 /* Configure Right input mux for ADC1R */
113 status = platformAudioAdcSetRightInputMux(devId, ADC_CH1_RIGHT,
114 config->adc1RMux);
115 if(status != Platform_EOK)
116 {
117 IFPRINT(platform_write("audioAdcConfig : platformAudioAdcSetRightInputMux Failed\n"));
118 return (status);
119 }
121 /* Configure Right input mux for ADC2R */
122 status = platformAudioAdcSetRightInputMux(devId, ADC_CH2_RIGHT,
123 config->adc2RMux);
124 if(status != Platform_EOK)
125 {
126 IFPRINT(platform_write("audioAdcConfig : platformAudioAdcSetRightInputMux Failed\n"));
127 return (status);
128 }
130 /* Configure audio data format */
131 status = platformAudioAdcDataConfig(devId, config->wlen, config->format);
132 if(status != Platform_EOK)
133 {
134 IFPRINT(platform_write("audioAdcConfig : platformAudioAdcDataConfig Failed\n"));
135 return (status);
136 }
138 /* Configure all the interrupts */
139 status = platformAudioAdcConfigIntr(devId, ADC_INTR_ALL,
140 config->intEnable);
141 if(status != Platform_EOK)
142 {
143 IFPRINT(platform_write("audioAdcConfig : platformAudioAdcConfigIntr Failed\n"));
144 return (status);
145 }
147 return (status);
148 }
150 /**
151 * \brief Initializes DAC module
152 *
153 * This function initializes and configures the DAC modules
154 * on audio daughter card
155 *
156 * \param devId [IN] DAC Device Id
157 * \param config [IN] DAC configuration parameters
158 *
159 * \return Platform_EOK on Success or error code
160 */
161 Platform_STATUS audioDacConfig(DacDevId devId, DacConfig *config)
162 {
163 Platform_STATUS status;
165 if(config == NULL)
166 {
167 IFPRINT(platform_write("Invalid Inputs\n"));
168 return (Platform_EINVALID);
169 }
171 /* Initialize Audio DAC */
172 status = platformAudioDacInit(devId);
173 if(status != Platform_EOK)
174 {
175 IFPRINT(platform_write("audioDacConfig : platformaudioDacConfig Failed\n"));
176 return (status);
177 }
179 /* Configure AMUTE control event */
180 status = platformAudioDacAmuteCtrl(devId, config->amuteCtrl,
181 config->amuteEnable);
182 if(status != Platform_EOK)
183 {
184 IFPRINT(platform_write("audioDacConfig : platformAudioDacAmuteCtrl Failed\n"));
185 return (status);
186 }
188 /* Set sampling mode */
189 status = platformAudioDacSetSamplingMode(devId, config->samplingMode);
190 if(status != Platform_EOK)
191 {
192 IFPRINT(platform_write("audioDacConfig : platformAudioDacSetSamplingMode Failed\n"));
193 return (status);
194 }
196 /* Set data format */
197 status = platformAudioDacSetDataFormat(devId, config->dataFormat);
198 if(status != Platform_EOK)
199 {
200 IFPRINT(platform_write("audioDacConfig : platformAudioDacSetDataFormat Failed\n"));
201 return (status);
202 }
204 /* Enable soft mute control */
205 status = platformAudioDacSoftMuteCtrl(devId, DAC_CHAN_ALL,
206 config->softMuteEnable);
207 if(status != Platform_EOK)
208 {
209 IFPRINT(platform_write("audioDacConfig : platformAudioDacSoftMuteCtrl Failed\n"));
210 return (status);
211 }
213 /* Set attenuation mode */
214 status = platformAudioDacSetAttnMode(devId, config->attnMode);
215 if(status != Platform_EOK)
216 {
217 IFPRINT(platform_write("audioDacConfig : platformAudioDacSetAttnMode Failed\n"));
218 return (status);
219 }
221 /* Set De-emphasis control */
222 status = platformAudioDacDeempCtrl(devId, config->deempCtrl);
223 if(status != Platform_EOK)
224 {
225 IFPRINT(platform_write("audioDacConfig : platformAudioDacDeempCtrl Failed\n"));
226 return (status);
227 }
229 /* Set DAC volume */
230 status = platformAudioDacSetVolume(devId, DAC_CHAN_ALL, config->volume);
231 if(status != Platform_EOK)
232 {
233 IFPRINT(platform_write("audioDacConfig : platformAudioDacSetVolume Failed\n"));
234 return (status);
235 }
237 return (status);
238 }
240 /**
241 * \brief Initializes DIR module
242 *
243 * This function initializes and configures the DIR modules
244 * on audio daughter card
245 *
246 * \return Platform_EOK on Success or error code
247 */
248 Platform_STATUS audioDirConfig(void)
249 {
250 Platform_STATUS status;
251 int8_t fsout;
252 #ifdef CHECK_ERROR_STATUS
253 uint32_t timeout;
254 #endif
256 status = platformAudioDirInit();
257 if(status != Platform_EOK)
258 {
259 IFPRINT(platform_write("audioDirConfig : Audio DIR Configuration Failed!\n"));
260 return (status);
261 }
263 #ifdef CHECK_ERROR_STATUS
264 /* DIR should be in PLL mode.
265 Wait for ERROR signal to be low as DIR is configured for
266 AUTO mode */
267 timeout = ERROR_STATUS_WAIT_TIMEOUT;
268 while (timeout)
269 {
270 if(!platformAudioDirGetErrStatus())
271 {
272 IFPRINT(platform_write("audioDirConfig : DIR in PLL Mode\n"));
273 break;
274 }
276 IFPRINT(platform_write("audioDirConfig : Waiting for DIR to Enter PLL Mode...\n"));
277 platform_delay(1000);
278 timeout--;
279 }
281 if(!timeout)
282 {
283 IFPRINT(platform_write("audioDirConfig : DIR is not in PLL Mode!!\n"));
284 return (Platform_EFAIL);
285 }
286 #endif
288 fsout = platformAudioDirGetFsOut();
289 if(fsout == 2)
290 {
291 IFPRINT(platform_write("audioDirConfig : Out of Range Sampling Frequency\n"));
292 }
293 else if(fsout == 0)
294 {
295 IFPRINT(platform_write("audioDirConfig : Calculated Sampling Frequency Output is 43 kHz\9645.2 kHz\n"));
296 }
297 else if(fsout == 1)
298 {
299 IFPRINT(platform_write("audioDirConfig : Calculated Sampling Frequency Output is 46.8 kHz\9649.2 kHz\n"));
300 }
301 else if(fsout == 3)
302 {
303 IFPRINT(platform_write("audioDirConfig : Calculated Sampling Frequency Output is 31.2 kHz\9632.8 kHz\n"));
304 }
305 else
306 {
307 IFPRINT(platform_write("audioDirConfig : Error in Reading FSOUT status \n"));
308 status = Platform_EFAIL;
309 }
311 return (status);
312 }
314 int alpha_i2c_write(unsigned short, ...);
315 void set_audio_desc(unsigned char ,unsigned char ,unsigned char ,unsigned char ,unsigned char );
316 void hrptredid();
317 void hdmi128();
320 int gret_val=0;
321 int alpha_i2c_write(unsigned short var1, ...)
322 {
323 unsigned short alpha_type,length,temp_var;
324 int i,offset,ret_val;
325 unsigned char cmd[50];
326 char *s;
327 va_list argp;
328 va_start(argp, var1);
330 alpha_type = var1>> 8;
331 switch(alpha_type)
332 {
333 case 0xca:
334 case 0xc2:
335 case 0xc3:
336 case 0xc4:
337 length = 4;
338 break;
339 case 0xcb:
340 length = 6;
341 break;
342 case 0xcc:
343 length = 8;
344 break;
345 case 0xcd:
346 case 0xc5:
347 length= 8; // temporary - data starts after 8 bytes
348 break;
349 }
351 cmd[0]=length;
352 temp_var=var1;
353 for(i=0;i<length-2;i+=2) // convert to bytes as per protocol
354 {
355 cmd[i+1]= temp_var & 0xff;
356 cmd[i+2]= temp_var >> 8;
357 temp_var=va_arg(argp, short);
358 }
359 cmd[i+1]= temp_var & 0xff;
360 cmd[i+2]= temp_var >> 8;
363 if(alpha_type == 0xcd) // special processing for variable length
364 {
365 offset=9;
366 s = va_arg(argp, char *); // remaining data is in form of string
367 length = temp_var; // last short indicates data length
368 cmd[0]+=length;
369 for(i=offset;i<offset+length;i++)
370 cmd[i]=s[i-offset];
371 }
372 va_end(argp);
375 ret_val = i2cWrite(HSR4_I2C_PORT_NUM, HSR4_I2C_ADDR, cmd, cmd[0]+1, I2C_RELEASE_BUS);
376 if(ret_val !=I2C_RET_OK)
377 gret_val++;
380 return ret_val;
381 }
383 void set_audio_desc(unsigned char var1,unsigned char var2,unsigned char var3,unsigned char var4,unsigned char var5)
384 {
385 int ret_val=I2C_RET_OK;
387 platform_delay(1000);do{ret_val=alpha_i2c_write(HSDIO_EDID_AUDIO_DESC_FORMAT(var1, var2));}while (ret_val !=I2C_RET_OK);
388 platform_delay(1000);do{ret_val=alpha_i2c_write(HSDIO_EDID_AUDIO_DESC_NUM_CHANNELS(var1, var3));}while (ret_val !=I2C_RET_OK);
389 platform_delay(1000);do{ret_val=alpha_i2c_write(HSDIO_EDID_AUDIO_DESC_SAMPLE_RATES(var1, var4));}while (ret_val !=I2C_RET_OK);
390 platform_delay(1000);do{ret_val=alpha_i2c_write(HSDIO_EDID_AUDIO_DESC_MISC(var1, var5));}while (ret_val !=I2C_RET_OK);
391 }
394 // Program HDMI CEA / EDID values, as necessary.
395 void hrptredid()
396 {
397 int ret_val=I2C_RET_OK;
399 do{
400 platform_delay(1000);
401 ret_val=alpha_i2c_write(HSDIO_EDID_SPEAKER_ALLOCATION_BLOCK(0xFF));
402 if (ret_val !=I2C_RET_OK)
403 i2cConfig(HSR4_I2C_PORT_NUM);
405 }while (ret_val !=I2C_RET_OK);
407 platform_delay(1000);
408 do{ret_val=alpha_i2c_write(HSDIO_EDID_SPEAKER_ALLOCATION_BLOCK_2(0x7));}while (ret_val !=I2C_RET_OK);
410 set_audio_desc(0,1,2,0x7f,7); // PCM 2 channel, 32kHz, 44.1kHz, 48kHz, 88.2kHz, 96kHz, 176.4 KHz, 192 KHz, 16bit, 20bit, 24bit
411 set_audio_desc(1,1,8,0x7f,7); // PCM 8 channel, 32kHz, 44.1kHz, 48kHz, 88.2kHz, 96kHz, 176.4 KHz, 192 KHz, 16bit, 20bit, 24bit
412 set_audio_desc(2,2,6,0x7,80); // AC3 6 channel, 32kHz, 44.1kHz, 48kHz, 640kHz max bit rate
413 set_audio_desc(3,10,8,0x07,1); // Dolby Digital Plus, 8 channel, 32kHz, 44.1kHz, 48kHz, codec specific:1
414 set_audio_desc(4,12,8,0x7F,1); // MAT(MPL)(Dolby TrueHD), 8 channel, 32kHz, 44.1kHz, 48kHz, 88.2kHz, 96kHz,
415 // 176.4kHz, 192kHz, codec specific:1
416 set_audio_desc(5,7,6,0x1E,192); // DTS 6 channel, 44.1kHz, 48kHz, 88.2kHz, 96kHz, 1,536kHz max bit rate
417 set_audio_desc(6,7,8,0x6,192); // DTS 8 channel, 44.1kHz, 48kHz, 1,536kHz max bit rate
418 set_audio_desc(7,11,8,0x7F,3); // DTS-HD, 8 channel, 32kHz, 44.1kHz, 48kHz, 88.2kHz, 96kHz, 176.4kHz, 192kHz,
419 // last byte is 3 for DTS:X, 1 otherwise.
420 set_audio_desc(8,11,8,0x7F,1); // DTS-HD, 8 channel - same as above, but last byte = 1
421 set_audio_desc(9,0,0,0,0);
422 set_audio_desc(10,0,0,0,0);
423 set_audio_desc(11,0,0,0,0); //AAC LC (5,6,6,0x1f,192);
424 set_audio_desc(12,0,0,0,0);
425 set_audio_desc(13,0,0,0,0);
426 set_audio_desc(14,0,0,0,0);
427 set_audio_desc(15,0,0,0,0);
428 set_audio_desc(16,0,0,0,0);
429 set_audio_desc(17,0,0,0,0);
430 set_audio_desc(18,0,0,0,0);
431 set_audio_desc(19,0,0,0,0);
432 platform_delay(1000);
433 do{ret_val=alpha_i2c_write(HSDIO_EDID_GO);}while (ret_val !=I2C_RET_OK);
434 }
436 // Configure the HOST port of HSR41 for EXTRACT mode of operation.
437 // Note: HDMI Tx/Out Port's state is not cared for, at all.
438 void hdmi128()
439 {
440 int ret_val=I2C_RET_OK;
442 platform_delay(1000);do{ret_val=alpha_i2c_write(HSDIO_ALERT(HSDIO_ALERT_INPUT_AUDIO_CHANGE_msk));}while (ret_val !=I2C_RET_OK);
443 platform_delay(1000);do{ret_val=alpha_i2c_write(HSDIO_ALERT(HSDIO_ALERT_INPUT_AUDIO_MUTE_msk));}while (ret_val !=I2C_RET_OK);
444 platform_delay(1000);do{ret_val=alpha_i2c_write(HSDIO_AUDIO_MCLK_TO_HOST(HSDIO_AudioMClk_128X));}while (ret_val !=I2C_RET_OK);
445 platform_delay(1000);do{ret_val=alpha_i2c_write(HSDIO_AUDIO_UNMUTE_DELAY_TO_HOST(HSDIO_AudioUnMuteDelay_NO_DELAY));}while (ret_val !=I2C_RET_OK);
446 platform_delay(1000);do{ret_val=alpha_i2c_write(HSDIO_AUDIO_FORMAT_TO_HOST(HSDIO_AudioFmt_I2S));}while (ret_val !=I2C_RET_OK);
447 platform_delay(1000);do{ret_val=alpha_i2c_write(HSDIO_IMPLEMENT_AUDIO_TO_HOST_CMDS);}while (ret_val !=I2C_RET_OK);
448 platform_delay(1000);do{ret_val=alpha_i2c_write(HSDIO_AUDIO_ROUTING(HSDIO_AudioRouting_HSDIOIN_NOOUT));}while (ret_val !=I2C_RET_OK);
449 platform_delay(1000);do{ret_val=alpha_i2c_write(HSDIO_SYS_CFG_GO);}while (ret_val !=I2C_RET_OK);
450 }
452 //
453 // Fetch Video Sync Status from HSR41
454 unsigned int read_hdmi_videosyncstatus()
455 {
456 unsigned char data[50];
457 Uint8 length;
458 int ret_val=0;
460 ret_val=alpha_i2c_write(HSDIO_INPUT_SYNC_STS);
461 if(!ret_val) i2cRead(HSR4_I2C_PORT_NUM, HSR4_I2C_ADDR,&length,0,1,1);
462 if(!ret_val) i2cRead(HSR4_I2C_PORT_NUM, HSR4_I2C_ADDR,&data[0],0,1,length);
463 if(!ret_val) ret_val= data[3]; // 1-byte / indicates error status
465 return ret_val;
466 }
468 //
469 // Fetch Audio Present Status from HSR41
470 unsigned int read_hdmi_audiostatus()
471 {
472 unsigned char data[50];
473 Uint8 length;
474 int ret_val=0;
476 ret_val=alpha_i2c_write(HSDIO_AUDIO_INPUT_PRESENT_STS);
477 if(!ret_val) i2cRead(HSR4_I2C_PORT_NUM, HSR4_I2C_ADDR,&length,0,1,1);
478 if(!ret_val) i2cRead(HSR4_I2C_PORT_NUM, HSR4_I2C_ADDR,&data[0],0,1,length);
479 if(!ret_val) ret_val= data[3]; // 1-byte / indicates error status
481 return ret_val;
482 }
484 // Fetch Clock Status from HSR41
485 unsigned int read_hdmi_clockstatus()
486 {
487 unsigned char data[50];
488 Uint8 length;
489 int ret_val=0;
491 ret_val=alpha_i2c_write(HSDIO_GET_AUDIO_MCLK_TO_HOST);
492 if(!ret_val) i2cRead(HSR4_I2C_PORT_NUM, HSR4_I2C_ADDR,&length,0,1,1);
493 if(!ret_val) i2cRead(HSR4_I2C_PORT_NUM, HSR4_I2C_ADDR,&data[0],0,1,length);
494 if(!ret_val) ret_val= data[3]; // 1-byte / indicates clock status
496 return ret_val;
497 }
499 // Fetch Error Status from HSR41
500 unsigned int read_hdmi_errstatus()
501 {
502 unsigned char data[50];
503 Uint8 length;
504 int ret_val=0;
506 ret_val=alpha_i2c_write(HSDIO_AUDIO_INPUT_ERROR_STS);
507 if(!ret_val) i2cRead(HSR4_I2C_PORT_NUM, HSR4_I2C_ADDR,&length,0,1,1);
508 if(!ret_val) i2cRead(HSR4_I2C_PORT_NUM, HSR4_I2C_ADDR,&data[0],0,1,length);
509 if(!ret_val) ret_val= data[3]; // 1-byte / indicates error status
511 return ret_val;
512 }
514 void clear_hdmi_hmint()
515 {
516 int ret_val=0;
518 ret_val=alpha_i2c_write(HSDIO_ALERT_STS); //clear the interrupt on ~HMINT by reading the Alert Status register
520 if(ret_val)
521 while(1); // Control shouldn't be here
523 return;
524 }
526 unsigned int read_hdmi_samprate()
527 {
528 unsigned char data[50];
529 Uint8 length;
530 int ret_val=7;
532 ret_val=alpha_i2c_write(HSDIO_AUDIO_INPUT_FREQ_STS);
534 if(!ret_val) i2cRead(HSR4_I2C_PORT_NUM, HSR4_I2C_ADDR,&length,0,1,1);
535 if(!ret_val) i2cRead(HSR4_I2C_PORT_NUM, HSR4_I2C_ADDR,&data[0],0,1,length);
536 if(!ret_val) ret_val= data[3]; // indicates sample rate
537 else
538 ret_val = 0;
540 return ret_val;
541 }
544 Platform_STATUS audioHDMIConfig(void)
545 {
546 Platform_STATUS status = Platform_EOK;
548 hrptredid();
550 hdmi128();
552 //while((HSDIO_InSync_SYNC_DETECTED != read_hdmi_videosyncstatus()) || (HSDIO_AudioMClk_128X != read_hdmi_clockstatus()));// || (HSDIO_AudioPresent_HAS_AUDIO != read_hdmi_audiostatus()));
553 while((HSDIO_InSync_SYNC_DETECTED != read_hdmi_videosyncstatus()));
554 //while((HSDIO_AudioMClk_128X != read_hdmi_clockstatus()) || (HSDIO_AudioErr_NO_ERROR != read_hdmi_errstatus()));
556 return (status);
557 }
561 /* Nothing past this point */