289 lines
6.6 KiB
C
289 lines
6.6 KiB
C
|
/*
|
|||
|
* (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;
|
|||
|
}
|
|||
|
|