📄 aud_atom.c
字号:
/*----------------------------------------------------------------------------+| This source code has been made available to you by IBM on an AS-IS| basis. Anyone receiving this source is licensed under IBM| copyrights to use it in any way he or she deems fit, including| copying it, modifying it, compiling it, and redistributing it either| with or without modifications. No license under IBM patents or| patent applications is to be implied by the copyright license.|| Any user of this software should understand that IBM cannot provide| technical support for this software and will not be responsible for| any consequences resulting from the use of this software.|| Any person who transfers this source code or any derivative work| must include the IBM copyright notice, this paragraph, and the| preceding two paragraphs in the transferred software.|| COPYRIGHT I B M CORPORATION 1997, 1999, 2003| LICENSED MATERIAL - PROGRAM PROPERTY OF I B M+----------------------------------------------------------------------------*//*----------------------------------------------------------------------------+| File: aud_atom.c| Purpose: audio driver atom layer PALLAS| Changes:| Date: Comment:| ----- --------| 15-Oct-01 create | 21-Jan-03 Prevent audio pops due to turning on/off clocks to the DAC.| This main cause for this is due to the ADISO bit in CTRL0| being cleared by the reset to clear the rate buffer and| by the loading of microcode. Fixed by using the reset cmd| that will specifically clear the rate buffer instead of the| global audio reset (which also resets the CTRL regs), and| by not clearing the ADISO bit during microcode loading.| 17-Jun-03 Initial implementation to get audio status. MPEG/AC3/UPCM| 17-Jun-03 Added UPCM selection for 8-bit UPCM streams| 20-Jun-03 Change init/stop/start to use halt decoding (pause) instead of | start parsing. This should prevent "losing" stream data between | stop/start and provided a quicker stop (pause). The forcing | on/off of mute was also removed (see aud_osi.c)| 25-Jun-03 Added support for DTS/LPCM coreload and the AC3 decoding coreloads| 25-Jun-03 Force encoded SPDIF output if decoding AC3 not available| 25-Jun-03 Added stream status support for DTS/LPCM coreload| 26-Jun-03 Changed default of _mute var since mute not forced on during open| 22-Jul-03 Fixed LPCM status bit definitions| 23-Jul-03 Fill audio microcode description structure variable| 25-Jul-03 Added check to be sure that the audio physical memory size defined was large enough+----------------------------------------------------------------------------*/#include <os/os-io.h>#include <os/os-interrupt.h>#include <os/drv_debug.h>#include <os/os-sync.h>#include "aud_osi.h"#include "aud_atom.h"#include "aud_atom_hw.h"#include "aud_uc.h"#include "astb_d.h"struct aud_ucode_info stb_info = { "s5amp3", aud_ucode_stb, sizeof(aud_ucode_stb_len), astb_d, sizeof(astb_d),};#ifdef AC3_ENABLE#include "aud_dvd.h"#include "advd_d.h"struct aud_ucode_info dvd_info = { "s5advdr", aud_ucode_dvd, sizeof(aud_ucode_dvd), advd_d, sizeof(advd_d),};#endif#ifdef DTS_ENABLE#include "aud_dts.h"#include "adts_d.h"struct aud_ucode_info dts_info = { "s5adts", aud_ucode_dts, sizeof(aud_ucode_dts), adts_d, sizeof(adts_d),};#endifstruct aud_ucode_info *aud_ucode_info[] = { &stb_info,#if AC3_ENABLE &dvd_info,#endif#if AC3_ENABLE &dts_info,#endif NULL};/*notify channel change done to demux*/extern int aud_cc_done();extern void vid_atom_set_stc(STC_T *pData);void* _seg1_log = NULL;int _mute = 0;/*local definition*/#define DEF_AUD_IRQ_MASK DECOD_AUD_IMR_CCC | \ DECOD_AUD_IMR_CM | \ DECOD_AUD_IMR_CM2 | \ DECOD_AUD_IMR_RTBC | \ DECOD_AUD_IMR_AMSIint aud_atom_load_microcode(const unsigned short *code, int count);INT aud_atom_load_dfile(void *base, const unsigned char *dfile, int df_len, unsigned long rb_off);inline void aud_atom_reset_rb();INT aud_atom_init(ADEC_CON *pAConf){ unsigned long reg; const USHORT *code; const unsigned char *data; int count, dcount; unsigned long control; /*-------------------------------------------------------------------------+ | Disable interrupts during reset. +-------------------------------------------------------------------------*/ // disable_irq(STB_AUD_INT); // YYD disabled /*-------------------------------------------------------------------------+ | Reset the core. +-------------------------------------------------------------------------*/ aud_atom_reset_rb(); /*-------------------------------------------------------------------------+ | After soft reset here must be at least 20 processor cycles before | another read/write to MPEG audio DCR. +-------------------------------------------------------------------------*/ os_cpu_clock_delay(30); // clear all buffer //mpeg_a_buf_blank(pADEC); /*-------------------------------------------------------------------------+ | Write the MPEG audio code segment registers. +-------------------------------------------------------------------------*/ if ((pAConf->seg1 & DECOD_AUD_SEG_ALIGN) != 0) { printk("ERROR: MPEG_A_MEM_START value must be 0x%8.8x byte aligned\n",DECOD_AUD_SEG_ALIGN); return (-1); } if ((pAConf->seg2 & DECOD_AUD_SEG_ALIGN) != 0) { printk("ERROR: Audio segment 2 value must be 0x%8.8x byte aligned\n",DECOD_AUD_SEG_ALIGN); return (-1); } if ((pAConf->rb_base & DECOD_AUD_SEG_ALIGN) != 0) { printk("ERROR: Audio rate buffer base must be 0x%8.8x byte aligned\n",DECOD_AUD_SEG_ALIGN); return (-1); } PDEBUG("MPEG_A_SEGMENT1 = 0x%8.8x and ends at 0x%8.8x\n",MPEG_A_SEGMENT1,MPEG_A_SEGMENT1+MPEG_A_SEGMENT1_SIZE); PDEBUG("MPEG_A_SEGMENT3 = 0x%8.8x and ends at 0x%8.8x\n",MPEG_A_SEGMENT3,MPEG_A_SEGMENT3+MPEG_A_SEGMENT3_SIZE); PDEBUG("MPEG_A_SEGMENT2 = 0x%8.8x and ends at 0x%8.8x\n",MPEG_A_SEGMENT2,MPEG_A_SEGMENT2+MPEG_A_SEGMENT2_SIZE); PDEBUG("MPEG_A_CLIP_BUF_START = 0x%8.8x and ends at 0x%8.8x\n",MPEG_A_CLIP_BUF_START,MPEG_A_CLIP_BUF_START+MPEG_A_CLIP_BUF_LEN); PDEBUG("MPEG_A_MIXER_BUF_START = 0x%8.8x and ends at 0x%8.8x\n",MPEG_A_MIXER_BUF_START,MPEG_A_MIXER_BUF_START+MPEG_A_MIXER_BUF_LEN); /*-------------------------------------------------------------------------+ | Make sure the defined audio size is large enough. +-------------------------------------------------------------------------*/ if(((MPEG_A_MIXER_BUF_START + MPEG_A_MIXER_BUF_LEN)- MPEG_A_SEGMENT1) > MPEG_A_MEM_SIZE) { printk("ERROR: MPEG_A_MEM_SIZE 0x%8.8x is not large enough to cover the audio memory allocations 0x%8.8x\n" ,MPEG_A_MEM_SIZE,(int)((MPEG_A_MIXER_BUF_START + MPEG_A_MIXER_BUF_LEN)- MPEG_A_SEGMENT1) ); return (-1); } PDEBUG("setting audio segment 1 to 0x%8x\n", pAConf->seg1); MT_DCR(AUD_SEG1, pAConf->seg1 >> DECOD_AUD_SEG_SH); PDEBUG("setting audio segment 2 to 0x%8x\n", pAConf->seg2); MT_DCR(AUD_SEG2, pAConf->seg2 >> DECOD_AUD_SEG_SH); /*-------------------------------------------------------------------------+ | 64K rate buffer is configured in following statement. +-------------------------------------------------------------------------*/ PDEBUG("setting audio segment 3 to 0x%8x\n", pAConf->rb_base); MT_DCR(AUD_SEG3, (pAConf->rb_base >> DECOD_AUD_SEG_SH) | (0xF << 28)); // ((pAConf->rb_size & 0xF) << 28)); /*-------------------------------------------------------------------------+ | Initialize offsets for bank1. +-------------------------------------------------------------------------*/ MT_DCR(AUD_OFFSETS, pAConf->rb_off); /*-------------------------------------------------------------------------+ | Check the microcode load type. +-------------------------------------------------------------------------*/ code = (const USHORT*)aud_ucode_stb; /* Set default coreload to mpeg */ count = aud_ucode_stb_len; data = astb_d; dcount = astb_d_len; switch (pAConf->mode) { case AUD_MODE_AC3:#ifdef AC3_ENABLE if (aud_ucode_dvd_len > 0) { code = (const USHORT*)aud_ucode_dvd; count = aud_ucode_dvd_len; data = advd_d; dcount = advd_d_len; control = DECOD_AUD_CTRL2_DM | DECOD_AUD_CTRL2_LL | DECOD_AUD_CTRL2_HL | DECOD_AUD_CTRL2_DN | DECOD_AUD_CTRL2_AC3; } else #endif if (aud_ucode_stb_len > 0) { control = DECOD_AUD_CTRL2_ID | DECOD_AUD_CTRL2_AC3; } else { return (-1); } break; case AUD_MODE_STB_MPEG: if (aud_ucode_stb_len == 1) { return (-1); } control = DECOD_AUD_CTRL2_MPEG; break; case AUD_MODE_STB_PCM: if (aud_ucode_stb_len == 1) { return (-1); } control = DECOD_AUD_CTRL2_PCM; break;#ifdef DTS_ENABLE case AUD_MODE_DTS: if (aud_ucode_dts_len > 0) { code = (const USHORT*)aud_ucode_dts; count = aud_ucode_dts_len; data = adts_d; dcount = adts_d_len; control = DECOD_AUD_CTRL2_ID | DECOD_AUD_CTRL2_DTS; } else { return (-1); } break; case AUD_MODE_LPCM: if (aud_ucode_dts_len > 0) { code = (const USHORT*)aud_ucode_dts; count = aud_ucode_dts_len; data = adts_d; dcount = adts_d_len; control = DECOD_AUD_CTRL2_LPCM; } else { return (-1); } break;#endif default: return (-1); } if(aud_atom_load_microcode(code, count/2) != 0) { PDEBUG("load microcode error\n"); return -1; } PDEBUG("load microcode OK\n"); if(_seg1_log != NULL) { if( aud_atom_load_dfile((void*)_seg1_log, data, dcount, pAConf->rb_off) < 0) { PDEBUG("load data file error\n"); return -1; } } /*-------------------------------------------------------------------------+ | Setup stream ID register. +-------------------------------------------------------------------------*/ if(pAConf->mode == AUD_MODE_STB_MPEG) /* If MPEG, set MPEG pes id's */ { MT_DCR(AUD_STREAM_ID, DECOD_AUD_DEF_ID); } else /* All others use private stream id*/ { MT_DCR(AUD_STREAM_ID, DECOD_AUD_DEF_AC3_ID); } /*-------------------------------------------------------------------------+ | Start DSP. Download end flag must be set. +-------------------------------------------------------------------------*/ MT_DCR(AUD_CTRL0, DECOD_AUD_CTRL0_START_DECODER | DECOD_AUD_CTRL0_DOWNLOAD_END | DECOD_AUD_CTRL0_START_PARSING | DECOD_AUD_CTRL0_ENABLE_INT); /*-------------------------------------------------------------------------+ | Enable DACs +-------------------------------------------------------------------------*/#ifdef CONFIG_OLIVIA // ShaoLin add for Olivia MT_DCR(AUD_CTRL1, MF_DCR(AUD_CTRL1) | DECOD_AUD_CTRL1_DAC_EN | 0x08 | 0x01);#endif reg = MF_DCR(AUD_CTRL1) | DECOD_AUD_CTRL1_DAC_EN; MT_DCR(AUD_CTRL1, reg); /*-------------------------------------------------------------------------+ | Set correct mode. +-------------------------------------------------------------------------*/ MT_DCR(AUD_CTRL2, control); aud_atom_reset_rb(); // YYD, as required by uc 3.01 after set stream format return (0);}void aud_atom_close(){ unsigned long reg; /*-------------------------------------------------------------------------+ | Reset the rate buffers. +-------------------------------------------------------------------------*/ aud_atom_reset_rb(); //stop decoder and disable interrupt reg = MF_DCR(AUD_CTRL0) & (~(DECOD_AUD_CTRL0_START_DECODER | DECOD_AUD_CTRL0_ENABLE_INT)); MT_DCR(AUD_CTRL0, reg);}INT aud_atom_set_stream_type(audStream_t stream){ unsigned long stream_type; unsigned long reg; // unsigned long ctrl2; /*-------------------------------------------------------------------------+ | Reset the core. +-------------------------------------------------------------------------*/ aud_atom_reset_rb(); /*-------------------------------------------------------------------------+ | After soft reset here must be at least 20 processor cycles before | another read/write to MPEG audio DCR. +-------------------------------------------------------------------------*/ os_cpu_clock_delay(30); reg = MF_DCR(AUD_CTRL0) & (~DECOD_AUD_CTRL0_TYPE_MPEG1); // ctrl2 = MF_DCR(AUD_CTRL2) & (~DECOD_AUD_CTRL2_PCM); switch (stream) { case AUD_STREAM_TYPE_MPEG1: stream_type = DECOD_AUD_CTRL0_TYPE_MPEG1; // ctrl2 |= DECOD_AUD_CTRL2_MPEG; break; case AUD_STREAM_TYPE_PES: stream_type = DECOD_AUD_CTRL0_TYPE_PES; // ctrl2 |= DECOD_AUD_CTRL2_MPEG; break; case AUD_STREAM_TYPE_ES: stream_type = DECOD_AUD_CTRL0_TYPE_ES; // ctrl2 |= DECOD_AUD_CTRL2_MPEG; break; case AUD_STREAM_TYPE_PCM: // YYD, add for PCM support stream_type = DECOD_AUD_CTRL0_TYPE_ES; // ctrl2 |= DECOD_AUD_CTRL2_PCM; break; default: return (-1); } PDEBUG("new stream type =%ld\n", stream_type); MT_DCR(AUD_CTRL0, reg | stream_type | DECOD_AUD_CTRL0_START_DECODER); return 0;}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -