289 lines
6.6 KiB
C
Executable File
289 lines
6.6 KiB
C
Executable File
/*
|
||
* (C) Copyright 2012
|
||
* wangflord@allwinnertech.com
|
||
*
|
||
*
|
||
* This program is free software; you can redistribute it and/or
|
||
* modify it under the terms of the GNU General Public License as
|
||
* published by the Free Software Foundation; either version 2 of
|
||
* the License, or (at your option) any later version.
|
||
*
|
||
* This program is distributed in the hope that it will be useful,
|
||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||
* GNU General Public License for more details.
|
||
*
|
||
* You should have received a copy of the GNU General Public License
|
||
* along with this program;
|
||
*
|
||
*/
|
||
#include <common.h>
|
||
#include <asm/arch/cpu.h>
|
||
#include <asm/arch/clock.h>
|
||
#include <asm/arch/codec.h>
|
||
#include <asm/arch/dma.h>
|
||
|
||
struct sunxi_codec_t *sunxi_codec;
|
||
uint hdma = 0;
|
||
/*
|
||
************************************************************************************************************
|
||
*
|
||
* function
|
||
*
|
||
* name :
|
||
*
|
||
* parmeters :
|
||
*
|
||
* return :
|
||
*
|
||
* note :
|
||
*
|
||
*
|
||
************************************************************************************************************
|
||
*/
|
||
int sunxi_codec_init(void)
|
||
{
|
||
#if 0
|
||
struct sunxi_ccm_reg *ccm_reg = (struct sunxi_ccm_reg *)SUNXI_CCM_BASE;
|
||
sunxi_codec = (struct sunxi_codec_t *)SUNXI_CODEC_BASE;
|
||
|
||
//open codec clock
|
||
ccm_reg->apb0_gate |= 1;
|
||
ccm_reg->audio_codec_clk_cfg |= (1U << 31);
|
||
//open dac
|
||
sunxi_codec->dac_dpc = 0x80800000;
|
||
sunxi_codec->dac_fifoc = 0x10400f11;
|
||
sunxi_codec->adc_actl |= (1 << 4);
|
||
sunxi_codec->dac_actl |= (0x3U<<30)|(0x1<<8)|(0x1<<6)|(0x3c);
|
||
#endif
|
||
return 0;
|
||
}
|
||
/*
|
||
************************************************************************************************************
|
||
*
|
||
* function
|
||
*
|
||
* name :
|
||
*
|
||
* parmeters :
|
||
*
|
||
* return :
|
||
*
|
||
* note :
|
||
*
|
||
*
|
||
************************************************************************************************************
|
||
*/
|
||
int sunxi_codec_config(int samplerate, int samplebit, int channel)
|
||
{
|
||
#if 0
|
||
uint reg_value;
|
||
struct sunxi_ccm_reg *ccm_reg = (struct sunxi_ccm_reg *)SUNXI_CCM_BASE;
|
||
|
||
reg_value = sunxi_codec->dac_fifoc;
|
||
reg_value &= ~((1 << 6) | (1 << 5) | (0x0eU << 29));
|
||
|
||
if(samplebit == 24)
|
||
{
|
||
reg_value |= (1 << 5);
|
||
}
|
||
if(channel != 2)
|
||
{
|
||
reg_value |= (1 << 6);
|
||
}
|
||
|
||
if(samplerate%2000)
|
||
{
|
||
debug("sunxi codec samplerate as 44100\n");
|
||
ccm_reg->pll2_cfg = 0;
|
||
}
|
||
else
|
||
{
|
||
debug("sunxi codec samplerate as 48000\n");
|
||
ccm_reg->pll2_cfg = 0;
|
||
}
|
||
switch(samplerate)
|
||
{
|
||
case 48000:
|
||
case 44100:
|
||
{
|
||
break;
|
||
}
|
||
case 32000:
|
||
{
|
||
reg_value |= (1 << 29);
|
||
break;
|
||
}
|
||
case 24000:
|
||
case 22050:
|
||
{
|
||
reg_value |= (2 << 29);
|
||
break;
|
||
}
|
||
case 16000:
|
||
{
|
||
reg_value |= (3 << 29);
|
||
break;
|
||
}
|
||
case 12000:
|
||
case 11025:
|
||
{
|
||
reg_value |= (4 << 29);
|
||
break;
|
||
}
|
||
case 8000:
|
||
{
|
||
reg_value |= (5 << 29);
|
||
break;
|
||
}
|
||
default:
|
||
{
|
||
printf("sunxi codec config error : audio sample %d not supported\n", samplerate);
|
||
return -1;
|
||
}
|
||
}
|
||
sunxi_codec->dac_fifoc = reg_value;
|
||
#endif
|
||
return 0;
|
||
}
|
||
/*
|
||
************************************************************************************************************
|
||
*
|
||
* function
|
||
*
|
||
* name :
|
||
*
|
||
* parmeters :
|
||
*
|
||
* return :
|
||
*
|
||
* note :
|
||
*
|
||
*
|
||
************************************************************************************************************
|
||
*/
|
||
int sunxi_codec_start(void *buffer, uint length, uint loop_mode)
|
||
{
|
||
#if 0
|
||
sunxi_dma_setting_t dma_cfg;
|
||
|
||
if(!hdma)
|
||
{
|
||
hdma = sunxi_dma_request(0);
|
||
if(!hdma)
|
||
{
|
||
printf("sunxi codec error : request dma failed\n");
|
||
|
||
return -1;
|
||
}
|
||
}
|
||
|
||
dma_cfg.cfg.src_drq_type = DMAC_CFG_DEST_TYPE_DRAM;
|
||
dma_cfg.cfg.src_addr_mode = 0; //Դ<>˵<EFBFBD>ַ<EFBFBD><D6B7><EFBFBD>Ե<EFBFBD><D4B5><EFBFBD>
|
||
dma_cfg.cfg.src_burst_length = 0; //burst = 1
|
||
dma_cfg.cfg.src_data_width = 1; //һ<>δ<EFBFBD><CEB4><EFBFBD>16bit
|
||
dma_cfg.cfg.dst_drq_type = DMAC_CFG_SRC_TYPE_CODEC;
|
||
dma_cfg.cfg.dst_addr_mode = 1; //Ŀ<>Ķ˵<C4B6>ַ<EFBFBD><D6B7><EFBFBD><EFBFBD>
|
||
dma_cfg.cfg.dst_burst_length = 0; //burst = 1
|
||
dma_cfg.cfg.dst_data_width = 1; //һ<>ν<EFBFBD><CEBD><EFBFBD>16bit
|
||
|
||
dma_cfg.loop_mode = loop_mode;
|
||
dma_cfg.wait_cyc = 4;
|
||
dma_cfg.data_block_size = 1 * 16/8;
|
||
|
||
dma_cfg.loop_mode = loop_mode;
|
||
|
||
sunxi_dma_setting(hdma, &dma_cfg);
|
||
flush_cache((uint)buffer, length);
|
||
sunxi_dma_start(hdma, (uint)buffer, (uint)(&sunxi_codec->dac_txdata), length);
|
||
#endif
|
||
return 0;
|
||
}
|
||
/*
|
||
************************************************************************************************************
|
||
*
|
||
* function
|
||
*
|
||
* name :
|
||
*
|
||
* parmeters :
|
||
*
|
||
* return :
|
||
*
|
||
* note :
|
||
*
|
||
*
|
||
************************************************************************************************************
|
||
*/
|
||
int sunxi_codec_stop(void)
|
||
{
|
||
#if 0
|
||
if(!hdma)
|
||
{
|
||
printf("sunxi codec error : cant stop without dma\n");
|
||
|
||
return -1;
|
||
}
|
||
sunxi_dma_stop(hdma);
|
||
#endif
|
||
return 0;
|
||
}
|
||
/*
|
||
************************************************************************************************************
|
||
*
|
||
* function
|
||
*
|
||
* name :
|
||
*
|
||
* parmeters :
|
||
*
|
||
* return :
|
||
*
|
||
* note :
|
||
*
|
||
*
|
||
************************************************************************************************************
|
||
*/
|
||
int sunxi_codec_wink(void *buffer, uint length)
|
||
{
|
||
#if 0
|
||
if(!hdma)
|
||
{
|
||
printf("sunxi codec error : cant stop without dma\n");
|
||
|
||
return -1;
|
||
}
|
||
sunxi_dma_stop(hdma);
|
||
flush_cache((uint)buffer, length);
|
||
sunxi_dma_start(hdma, (uint)buffer, (uint)(&sunxi_codec->dac_txdata), length);
|
||
#endif
|
||
return 0;
|
||
}
|
||
/*
|
||
************************************************************************************************************
|
||
*
|
||
* function
|
||
*
|
||
* name :
|
||
*
|
||
* parmeters :
|
||
*
|
||
* return :
|
||
*
|
||
* note :
|
||
*
|
||
*
|
||
************************************************************************************************************
|
||
*/
|
||
int audio_codec_exit(void)
|
||
{
|
||
#if 0
|
||
struct sunxi_ccm_reg *ccm_reg = (struct sunxi_ccm_reg *)SUNXI_CCM_BASE;
|
||
|
||
ccm_reg->apb0_gate &= ~1;
|
||
ccm_reg->audio_codec_clk_cfg &= ~(1U << 31);
|
||
#endif
|
||
return 0;
|
||
}
|
||
|