123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386 |
- /*
- * This file is part of FH8620 BSP for RT-Thread distribution.
- *
- * Copyright (c) 2016 Shanghai Fullhan Microelectronics Co., Ltd.
- * All rights reserved
- *
- * 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; if not, write to the Free Software Foundation, Inc.,
- * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Visit http://www.fullhan.com to get contact with Fullhan.
- *
- * Change Logs:
- * Date Author Notes
- */
- #include "acw.h"
- #include "fh_def.h"
- #include "fh_dma.h"
- #include "dma.h"
- #ifdef RT_USING_FH_ACW
- #if 1
- typedef struct
- {
- unsigned int base;
- void *vbase;
- unsigned int size;
- unsigned int align;
- }MEM_DESC;
- #define ACW_SELFTEST 0
- int buffer_malloc_withname(MEM_DESC *mem, int size, int align, char* name);
- #endif
- #define NR_DESCS_PER_CHANNEL 64
- #define FIX_SAMPLE_BIT 32
- #define ACW_HW_NUM_RX 0
- #define ACW_HW_NUM_TX 1
- #define ACW_DMA_CAP_CHANNEL 3
- #define ACW_DMA_PAY_CHANNEL 2
- #define ACW_CTRL 0x0
- #define ACW_TXFIFO_CTRL 0x4
- #define ACW_RXFIFO_CTRL 0x8
- #define ACW_STATUS 0x0c
- #define ACW_DIG_IF_CTRL 0x10
- #define ACW_ADC_PATH_CTRL 0x14
- #define ACW_ADC_ALC_CTRL 0x18
- #define ACW_DAC_PATH_CTRL 0x1c
- #define ACW_MISC_CTRL 0x20
- #define ACW_TXFIFO 0xf0a00100
- #define ACW_RXFIFO 0xf0a00200
- typedef char bool;
- #define AUDIO_DMA_PREALLOC_SIZE 128*1024
- #define ACW_INTR_RX_UNDERFLOW 0x10000
- #define ACW_INTR_RX_OVERFLOW 0x20000
- #define ACW_INTR_TX_UNDERFLOW 0x40000
- #define ACW_INTR_TX_OVERFLOW 0x80000
- #define PAGE_SIZE 0x1000
- enum audio_type
- {
- capture = 0,
- playback,
- };
- enum audio_state
- {
- normal = 0,
- xrun,
- stopping,
- running,
- };
- struct infor_record_t
- {
- int record_pid;
- int play_pid;
- }; // infor_record;
- struct audio_config_t {
- int rate;
- int volume;
- enum io_select io_type;
- int frame_bit;
- int channels;
- int buffer_size;
- int period_size;
- int buffer_bytes;
- int period_bytes;
- int start_threshold;
- int stop_threshold;
- };
- struct audio_ptr_t
- {
- struct audio_config_t cfg;
- enum audio_state state;
- long size;
- int hw_ptr;
- int appl_ptr;
- struct rt_mutex lock;
- struct device_acw dev;
- void *area; /*virtual pointer*/
- dma_addr_t addr; /*physical address*/
- unsigned char * mmap_addr;
- };
- struct fh_audio_cfg
- {
- struct rt_dma_device *capture_dma;
- struct rt_dma_device *playback_dma;
- struct dma_transfer *capture_trans;
- struct dma_transfer *plauback_trans;
- struct audio_ptr_t capture;
- struct audio_ptr_t playback;
- wait_queue_head_t readqueue;
- wait_queue_head_t writequeue;
- struct rt_semaphore sem_capture;
- struct rt_semaphore sem_playback;
- };
- typedef int s32;
- typedef s32 dma_cookie_t;
- struct fh_dma_chan
- {
- struct dma_chan *chan;
- void *ch_regs;
- unsigned char mask;
- unsigned char priority;
- bool paused;
- bool initialized;
- struct rt_mutex lock;
- /* these other elements are all protected by lock */
- unsigned long flags;
- dma_cookie_t completed;
- struct list_head active_list;
- struct list_head queue;
- struct list_head free_list;
- struct fh_cyclic_desc *cdesc;
- unsigned int descs_allocated;
- };
- struct fh_acw_dma_transfer
- {
- struct dma_chan *chan;
- struct dma_transfer cfg;
- struct scatterlist sgl;
- struct dma_async_tx_descriptor *desc;
- };
- struct channel_assign
- {
- int capture_channel;
- int playback_channel;
- };
- struct audio_dev_mod
- {
- int reg_base;
- struct channel_assign channel_assign;
- struct fh_audio_cfg *audio_config;
- }audio_dev;
- static struct work_struct playback_wq;
- #define WORK_QUEUE_STACK_SIZE 512
- #if ACW_SELFTEST
- #define WORK_QUEUE_PRIORITY (12)
- #else
- #define WORK_QUEUE_PRIORITY (128+12)
- #endif
- static struct rt_workqueue* playback_queue;
- void audio_prealloc_dma_buffer(int aiaotype,struct fh_audio_cfg *audio_config);
- #if ACW_SELFTEST
- #define BUFF_SIZE 1024*8
- #define TEST_PER_NO 1024
- #endif
- static void audio_callback(){
- rt_kprintf("# \n");
- }
- static void audio_callback_capture(){
- rt_kprintf("$ \n");
- }
- static struct audio_param_store_t
- {
- int input_volume;
- enum io_select input_io_type;
- } audio_param_store;
- void reset_dma_buff(enum audio_type type, struct fh_audio_cfg *audio_config);
- static void fh_acw_tx_dma_done(void *arg);
- static void fh_acw_rx_dma_done(struct fh_audio_cfg *arg);
- static bool fh_acw_dma_chan_filter(struct dma_chan *chan, void *filter_param);
- #define writel(v,a) SET_REG(a,v)
- void fh_acw_stop_playback(struct fh_audio_cfg *audio_config)
- {
- if(audio_config->playback.state == stopping)
- {
- return;
- }
- unsigned int rx_status;
- rx_status = readl( audio_dev.reg_base + ACW_TXFIFO_CTRL);//clear rx fifo
- rx_status = rx_status|(1<<4);
- writel(rx_status,audio_dev.reg_base + ACW_TXFIFO_CTRL);
- audio_config->playback.state = stopping;
- writel(0, audio_dev.reg_base + ACW_TXFIFO_CTRL);//tx fifo disable
- if(audio_config->plauback_trans->channel_number != ACW_PLY_DMA_CHAN)
- goto free_mem;
- if(!audio_config->plauback_trans->first_lli)
- goto free_channel;
- audio_config->playback_dma->ops->control(audio_config->playback_dma,RT_DEVICE_CTRL_DMA_CYCLIC_STOP,audio_config->plauback_trans);
- audio_config->playback_dma->ops->control(audio_config->playback_dma,RT_DEVICE_CTRL_DMA_CYCLIC_FREE,audio_config->plauback_trans);
- free_channel:
- audio_config->playback_dma->ops->control(audio_config->playback_dma,RT_DEVICE_CTRL_DMA_RELEASE_CHANNEL,audio_config->plauback_trans);
- if(&audio_config->sem_playback)
- rt_sem_release(&audio_config->sem_playback);
- if(&audio_config->playback.lock)
- rt_mutex_release(&audio_config->playback.lock);
- if(&playback_wq)
- rt_workqueue_cancel_work(playback_queue,&playback_wq);
- if(playback_queue)
- rt_workqueue_destroy(playback_queue);
- free_mem:
- if(audio_config->playback.area)
- fh_dma_mem_free(audio_config->playback.area);
- }
- void fh_acw_stop_capture(struct fh_audio_cfg *audio_config)
- {
- unsigned int rx_status;
- if(audio_config->capture.state == stopping)
- {
- rt_kprintf(" capture is stopped \n");
- return;
- }
- rx_status = readl( audio_dev.reg_base + ACW_RXFIFO_CTRL);//clear rx fifo
- rx_status = rx_status|(1<<4);
- writel(rx_status,audio_dev.reg_base + ACW_RXFIFO_CTRL);
- audio_config->capture.state = stopping;
- writel(0, audio_dev.reg_base + 8);//rx fifo disable
- if(audio_config->capture_trans->channel_number != ACW_CAP_DMA_CHAN)
- goto free_mem;
- if(!audio_config->capture_trans->first_lli)
- goto free_channel;
- audio_config->capture_dma->ops->control(audio_config->capture_dma,RT_DEVICE_CTRL_DMA_CYCLIC_STOP,audio_config->capture_trans);
- audio_config->capture_dma->ops->control(audio_config->capture_dma,RT_DEVICE_CTRL_DMA_CYCLIC_FREE,audio_config->capture_trans);
- free_channel:
- audio_config->capture_dma->ops->control(audio_config->capture_dma,RT_DEVICE_CTRL_DMA_RELEASE_CHANNEL,audio_config->capture_trans);
- if(&audio_config->sem_capture)
- rt_sem_release(&audio_config->sem_capture);
- if(&audio_config->capture.lock)
- rt_mutex_release(&audio_config->capture.lock);
- free_mem:
- if(audio_config->capture.area)
- fh_dma_mem_free( audio_config->capture.area);
- }
- void switch_io_type(enum audio_type type, enum io_select io_type)
- {
- int reg;
- if (capture == type)
- {
- reg = readl(audio_dev.reg_base + ACW_ADC_PATH_CTRL);
- if (mic_in == io_type)
- {
- rt_kprintf("audio input changed to mic_in\n");
- writel( reg & (~(1<<1)),audio_dev.reg_base + ACW_ADC_PATH_CTRL);
- reg = readl(audio_dev.reg_base + ACW_ADC_PATH_CTRL);
- reg = reg & (~(1<<3));
- reg |=(0x1<<3);
- writel(reg, audio_dev.reg_base + ACW_ADC_PATH_CTRL);
- }
- else if (line_in == io_type)
- {
- rt_kprintf("audio input changed to line_in\n");
- writel(reg | (1<<1), audio_dev.reg_base + ACW_ADC_PATH_CTRL);
- }
- }
- else
- {
- reg = readl(audio_dev.reg_base + ACW_DAC_PATH_CTRL);
- if (speaker_out == io_type)
- {
- rt_kprintf("audio output changed to speaker_out\n");
- reg = reg & (~(3<<21));
- reg = reg & (~(3<<30));
- writel(reg, audio_dev.reg_base + ACW_DAC_PATH_CTRL);
- reg = reg | (1<<21);
- writel(reg,audio_dev.reg_base + ACW_DAC_PATH_CTRL);
- reg = reg | (1<<18);
- writel(reg, audio_dev.reg_base + ACW_DAC_PATH_CTRL);/*unmute speaker*/
- reg = reg | (3<<30);
- writel(reg,audio_dev.reg_base + ACW_DAC_PATH_CTRL);/*mute line out*/
- }
- else if (line_out == io_type)
- {
- rt_kprintf("audio output changed to line_out\n");
- reg = reg & (~(3<<21));
- writel(reg, audio_dev.reg_base + ACW_DAC_PATH_CTRL);/*mute speaker*/
- reg = reg & (~(3<<30));
- writel(reg, audio_dev.reg_base + ACW_DAC_PATH_CTRL);/*unmute line out*/
- }
- }
- }
- int get_factor_from_table(int rate)
- {
- int factor;
- switch(rate)
- {
- case 8000:
- factor = 4;
- break;
- case 16000:
- factor = 1;
- break;
- case 32000:
- factor = 0;
- break;
- case 44100:
- factor = 13;
- break;
- case 48000:
- factor = 6;
- break;
- default:
- factor = -EFAULT;
- break;
- }
- return factor;
- }
- void switch_rate(enum audio_type type, int rate)
- {
- int reg, factor;
- factor = get_factor_from_table(rate);
- if (factor < 0)
- {
- rt_kprintf( "unsupported sample rate\n");
- return;
- }
- reg = readl(audio_dev.reg_base + ACW_DIG_IF_CTRL);
- if (capture == type)
- {
- rt_kprintf("capture rate set to %d\n", rate);
- reg = reg & (~(0xf<<0));
- writel(reg, audio_dev.reg_base + ACW_DIG_IF_CTRL);/*adc and dac sample rate*/
- reg = reg | (factor<<0);
- writel(reg,audio_dev.reg_base + ACW_DIG_IF_CTRL);
- }
- else
- {
- rt_kprintf("playback rate set to %d\n", rate);
- reg = reg & (~(0xf<<8));
- writel(reg, audio_dev.reg_base + ACW_DIG_IF_CTRL);/*adc and dac sample rate*/
- reg = reg | (factor<<8);
- writel(reg, audio_dev.reg_base + ACW_DIG_IF_CTRL);
- }
- }
- int get_param_from_volume(int volume)
- {
- if(volume < 0)
- volume = 0;
- else if(volume > 100)
- volume = 100;
- volume = volume * 63 / 100;
- return volume;
- }
- void switch_input_volume(int volume)
- {
- int reg, param;
- param = get_param_from_volume(volume);
- if (param < 0)
- {
- rt_kprintf("capture volume error\n");
- return;
- }
- reg = readl(audio_dev.reg_base + ACW_ADC_PATH_CTRL);
- reg = reg & (~(0x3f<<8));
- writel(reg, audio_dev.reg_base + ACW_ADC_PATH_CTRL);
- reg = reg | (param<<8);
- writel(reg,audio_dev.reg_base + ACW_ADC_PATH_CTRL);
- }
- void init_audio(enum audio_type type,struct fh_audio_cfg *audio_config)
- {
- int reg;
- reg = readl(audio_dev.reg_base + ACW_CTRL);
- if ((reg & 0x80000000) == 0)
- {
- writel(0x80000000, audio_dev.reg_base + ACW_CTRL);/*enable audio*/
- }
- reg = readl(audio_dev.reg_base + ACW_MISC_CTRL);
- if (0x40400 != reg)
- {
- writel(0x40400,audio_dev.reg_base + ACW_MISC_CTRL);/*misc ctl*/
- }
- if (capture == type)
- {
- writel(0x61141b06,audio_dev.reg_base + ACW_ADC_PATH_CTRL);/*adc cfg*/
- writel(0x167f2307, audio_dev.reg_base + ACW_ADC_ALC_CTRL);/*adc alc*/
- writel(0, audio_dev.reg_base + ACW_RXFIFO_CTRL);/*rx fifo disable*/
- switch_input_volume(audio_config->capture.cfg.volume);
- switch_rate(capture, audio_config->capture.cfg.rate);
- switch_io_type(capture, audio_config->capture.cfg.io_type);
- }
- else
- {
- writel(0x3b403f09, audio_dev.reg_base + ACW_DAC_PATH_CTRL);/*dac cfg*/
- writel(0, audio_dev.reg_base + ACW_TXFIFO_CTRL);/*tx fifo disable*/
- switch_rate(playback, audio_config->playback.cfg.rate);
- switch_io_type(playback, audio_config->playback.cfg.io_type);
- }
- }
- static inline long bytes_to_frames(int frame_bit, int bytes)
- {
- return bytes * 8 /frame_bit;
- }
- static inline long frames_to_bytes(int frame_bit, int frames)
- {
- return frames * frame_bit / 8;
- }
- int avail_data_len(enum audio_type type,struct fh_audio_cfg *stream)
- {
- int delta;
- if (capture == type)
- {
- delta = stream->capture.hw_ptr - stream->capture.appl_ptr;
- if (delta < 0)
- {
- delta += stream->capture.size;
- }
- return delta;
- }
- else
- {
- delta = stream->playback.appl_ptr - stream->playback.hw_ptr;
- if (delta < 0)
- {
- delta += stream->playback.size;
- }
- return stream->playback.size - delta;
- }
- }
- static rt_err_t fh_audio_close(rt_device_t dev)
- {
- struct fh_audio_cfg *audio_config = dev->user_data;
- unsigned int reg;
- //disable interrupts
- reg = readl(audio_dev.reg_base + ACW_CTRL);
- reg &= ~(0x3ff);
- writel(reg, audio_dev.reg_base + ACW_CTRL);
- fh_acw_stop_playback(audio_config);
- fh_acw_stop_capture(audio_config);
- }
- int register_tx_dma(struct fh_audio_cfg *audio_config)
- {
- int ret;
- struct dma_transfer *playback_trans;
- playback_trans = audio_config->plauback_trans;
- struct rt_dma_device *rt_dma_dev;
- rt_dma_dev = audio_config->playback_dma;
- if ((audio_config->playback.cfg.buffer_bytes < audio_config->playback.cfg.period_bytes) ||
- (audio_config->playback.cfg.buffer_bytes <= 0) || (audio_config->playback.cfg.period_bytes <= 0))
- {
- rt_kprintf( "buffer_size and period_size are invalid\n");
- return RT_ERROR;
- }
- if(playback_trans->channel_number == ACW_PLY_DMA_CHAN){
- ret = rt_dma_dev->ops->control(rt_dma_dev,RT_DEVICE_CTRL_DMA_CYCLIC_PREPARE,playback_trans);
- if(ret){
- rt_kprintf("can't playback cyclic prepare \n");
- return RT_ERROR;
- }
- ret = rt_dma_dev->ops->control(rt_dma_dev,RT_DEVICE_CTRL_DMA_CYCLIC_START,playback_trans);
- if(ret){
- rt_kprintf("can't playback cyclic start \n");
- return RT_ERROR;
- }
- }
- else
- return RT_ERROR;
- return 0;
- }
- int register_rx_dma( struct fh_audio_cfg *audio_config)
- {
- int ret;
- struct dma_transfer *capture_slave;
- capture_slave = audio_config->capture_trans;
- struct rt_dma_device *rt_dma_dev;
- rt_dma_dev = audio_config->capture_dma;
- if (!capture_slave)
- {
- return -ENOMEM;
- }
- if ((audio_config->capture.cfg.buffer_bytes < audio_config->capture.cfg.period_bytes) ||
- (audio_config->capture.cfg.buffer_bytes <= 0) ||(audio_config->capture.cfg.period_bytes <= 0) )
- {
- rt_kprintf( "buffer_size and period_size are invalid\n");
- return RT_ERROR;
- }
- if(capture_slave->channel_number==ACW_CAP_DMA_CHAN){
- ret = rt_dma_dev->ops->control(rt_dma_dev,RT_DEVICE_CTRL_DMA_CYCLIC_PREPARE,capture_slave);
- if(ret){
- rt_kprintf("can't capture cyclic prepare \n");
- return RT_ERROR;
- }
- ret = rt_dma_dev->ops->control(rt_dma_dev,RT_DEVICE_CTRL_DMA_CYCLIC_START,capture_slave);
- if(ret){
- rt_kprintf("can't capture cyclic start \n");
- return RT_ERROR;
- }
- }
- else
- return RT_ERROR;
- writel(0x11,audio_dev.reg_base + ACW_RXFIFO_CTRL);//clear rx fifo
- writel(0x30029,audio_dev.reg_base + ACW_RXFIFO_CTRL);/*enable rx fifo*/
- return 0;
- }
- void playback_start_wq_handler(struct work_struct *work)
- {
- int avail;
- unsigned int rx_status;
- while(1)
- {
- if (stopping == audio_dev.audio_config->playback.state)
- {
- return;
- }
- avail = avail_data_len(playback, audio_dev.audio_config);
- if (avail < audio_dev.audio_config->playback.cfg.period_bytes)
- {
- rt_thread_sleep(0);
- }
- else
- {
- rx_status = readl( audio_dev.reg_base + ACW_TXFIFO_CTRL);//clear rx fifo
- rx_status = rx_status|(1<<4);
- writel(rx_status,audio_dev.reg_base + ACW_TXFIFO_CTRL);
- writel(0x30029, audio_dev.reg_base + ACW_TXFIFO_CTRL);
- break;
- }
- }
- }
- int fh_acw_start_playback(struct fh_audio_cfg *audio_config)
- {
- int ret;
- if(audio_config->playback.state == running)
- {
- rt_kprintf("playback is running \n");
- return 0;
- }
- if (audio_config->playback.cfg.buffer_bytes >= AUDIO_DMA_PREALLOC_SIZE)
- {
- rt_kprintf("DMA prealloc buffer is smaller than audio_config->buffer_bytes %x\n",audio_config->playback.cfg.buffer_bytes);
- return -ENOMEM;
- }
- reset_dma_buff(playback,audio_config);
- rt_memset(audio_config->playback.area, 0, audio_config->playback.cfg.buffer_bytes);
- audio_config->playback.size = audio_config->playback.cfg.buffer_bytes;
- audio_config->playback.state = running;
- ret = audio_request_playback_channel(audio_config);
- if(ret){
- rt_kprintf("can't request playback channel\n");
- return ret;
- }
- ret = register_tx_dma(audio_config);
- if (ret < 0)
- {
- rt_kprintf("can't register tx dma\n");
- return ret;
- }
- rt_list_init(&(playback_wq.list));
- playback_wq.work_func = (void *)playback_start_wq_handler;
- playback_wq.work_data = RT_NULL;
- playback_queue = rt_workqueue_create("play_workqueue",WORK_QUEUE_STACK_SIZE,WORK_QUEUE_PRIORITY);
- if(!playback_queue){
- rt_kprintf("init work_queue error....\n");
- return -1;
- }
- rt_workqueue_dowork(playback_queue,&playback_wq);
- return 0;
- }
- int fh_acw_start_capture(struct fh_audio_cfg *audio_config)
- {
- int ret;
- if(audio_config->capture.state == running)
- {
- return 0;
- }
- if (audio_config->capture.cfg.buffer_bytes >= AUDIO_DMA_PREALLOC_SIZE)
- {
- rt_kprintf("DMA prealloc buffer is smaller than audio_config->buffer_bytes %x\n",audio_config->capture.cfg.buffer_bytes);
- return -ENOMEM;
- }
- reset_dma_buff(capture,audio_config);
- rt_memset(audio_config->capture.area, 0, audio_config->capture.cfg.buffer_bytes);
- audio_config->capture.size = audio_config->capture.cfg.buffer_bytes;
- audio_config->capture.state = running;
- ret = audio_request_capture_channel(audio_config);
- if(ret){
- rt_kprintf("can't request capture channel \n");
- return ret;
- }
- return register_rx_dma(audio_config);
- }
- static void fh_acw_rx_dma_done(struct fh_audio_cfg *arg)
- {
- #if 1
- struct fh_audio_cfg *audio_config;
- audio_config = arg;
- audio_config->capture.hw_ptr += audio_config->capture.cfg.period_bytes;
- if (audio_config->capture.hw_ptr > audio_config->capture.size ) // TBD_WAIT ...
- {
- audio_config->capture.hw_ptr = audio_config->capture.hw_ptr - audio_config->capture.size;
- }
- int avail = avail_data_len(capture,audio_config);
- if (avail > audio_config->capture.cfg.period_bytes)
- {
- rt_sem_release(&audio_config->sem_capture);
- }
- #endif
- }
- static void fh_acw_tx_dma_done(void *arg)
- {
- #if 1
- struct fh_audio_cfg *audio_config;
- audio_config = ( struct fh_audio_cfg *)arg;
- audio_config->playback.hw_ptr += audio_config->playback.cfg.period_bytes;
- if (audio_config->playback.hw_ptr > audio_config->playback.size )
- {
- audio_config->playback.hw_ptr = audio_config->playback.hw_ptr - audio_config->playback.size;
- }
- int avail = avail_data_len(playback,audio_config);
- if (avail > audio_config->playback.cfg.period_bytes)
- {
- rt_sem_release(&audio_config->sem_playback);
- }
- #endif
- }
- bool fh_acw_dma_chan_filter(struct dma_chan *chan, void *filter_param)
- {
- }
- int arg_config_support(struct fh_audio_cfg_arg * cfg)
- {
- int ret;
- ret = get_param_from_volume(cfg->volume);
- if (ret < 0) {
- rt_kprintf("invalid volume\n");
- return -EINVAL;
- }
- ret = get_factor_from_table(cfg->rate);
- if (ret < 0) {
- rt_kprintf("invalid rate\n");
- return -EINVAL;
- }
- return 0;
- }
- void reset_dma_buff(enum audio_type type, struct fh_audio_cfg *audio_config)
- {
- if (capture == type)
- {
- audio_config->capture.appl_ptr = 0;
- audio_config->capture.hw_ptr = 0;
- }
- else
- {
- audio_config->playback.appl_ptr = 0;
- audio_config->playback.hw_ptr = 0;
- }
- }
- static rt_err_t fh_audio_ioctl(rt_device_t dev, int cmd, void *arg)
- {
- struct fh_audio_cfg_arg *cfg;
- struct fh_audio_cfg *audio_config = (struct fh_audio_cfg *)dev->user_data;
- int ret;
- int reg;
- int value,pid;
- int *p = (int *)arg;
- int rx_status,tx_status;
- switch (cmd)
- {
- case AC_INIT_CAPTURE_MEM:
- cfg = (struct fh_audio_cfg_arg *)arg;
- if (0 == arg_config_support(cfg))
- {
- audio_config->capture.cfg.io_type = cfg->io_type;
- audio_config->capture.cfg.volume = cfg->volume;
- audio_config->capture.cfg.rate = cfg->rate;
- audio_config->capture.cfg.channels = cfg->channels;
- audio_config->capture.cfg.buffer_size = cfg->buffer_size;
- audio_config->capture.cfg.frame_bit = FIX_SAMPLE_BIT;
- audio_config->capture.cfg.period_size = cfg->period_size;
- audio_config->capture.cfg.buffer_bytes = frames_to_bytes(audio_config->capture.cfg.frame_bit,audio_config->capture.cfg.buffer_size);
- audio_config->capture.cfg.period_bytes = frames_to_bytes(audio_config->capture.cfg.frame_bit,audio_config->capture.cfg.period_size);
- audio_config->capture.cfg.start_threshold =audio_config->capture.cfg.buffer_bytes;
- audio_config->capture.cfg.stop_threshold = audio_config->capture.cfg.buffer_bytes;
- audio_prealloc_dma_buffer((int)cfg->io_type,audio_config);
- reset_dma_buff(capture, audio_config);
- rt_mutex_init(&audio_config->capture.lock, "audio_c", RT_IPC_FLAG_PRIO);
- init_audio(capture, audio_config);
- audio_param_store.input_io_type = audio_config->capture.cfg.io_type;
- audio_param_store.input_volume = audio_config->capture.cfg.volume;
- }
- else
- {
- return -EINVAL;
- }
- break;
- case AC_INIT_PLAYBACK_MEM:
- cfg = arg;
- if (0 == arg_config_support(cfg))
- {
- audio_config->playback.cfg.io_type = cfg->io_type;
- audio_config->playback.cfg.volume = cfg->volume;
- audio_config->playback.cfg.rate = cfg->rate;
- audio_config->playback.cfg.channels = cfg->channels;
- audio_config->playback.cfg.buffer_size = cfg->buffer_size;
- audio_config->playback.cfg.frame_bit = FIX_SAMPLE_BIT;
- audio_config->playback.cfg.period_size = cfg->period_size;
- audio_config->playback.cfg.buffer_bytes = frames_to_bytes(audio_config->playback.cfg.frame_bit,audio_config->playback.cfg.buffer_size);
- audio_config->playback.cfg.period_bytes = frames_to_bytes(audio_config->playback.cfg.frame_bit,audio_config->playback.cfg.period_size);
- audio_config->playback.cfg.start_threshold =audio_config->playback.cfg.buffer_bytes;
- audio_config->playback.cfg.stop_threshold = audio_config->playback.cfg.buffer_bytes;
- audio_prealloc_dma_buffer((int)cfg->io_type,audio_config); // TBD_WAIT ...
- reset_dma_buff(playback, audio_config);
- rt_mutex_init(&audio_config->playback.lock, "audio_p", RT_IPC_FLAG_PRIO);
- init_audio(playback, audio_config);
- }
- else
- {
- return -EINVAL;
- }
- break;
- case AC_AI_EN:
- return fh_acw_start_capture(audio_config);
- case AC_AO_EN:
- rt_kprintf("ao en \n");
- return fh_acw_start_playback(audio_config);
- case AC_SET_VOL:
- value = *(rt_uint32_t *)arg;
- ret = get_param_from_volume(value);
- if (ret < 0) {
- return -EINVAL;
- }
- audio_param_store.input_volume = value;
- switch_input_volume(audio_param_store.input_volume);
- break;
- case AC_SET_INPUT_MODE:
- value = *(rt_uint32_t *)arg;
- if (value != mic_in && value != line_in) {
- return -EINVAL;
- }
- audio_param_store.input_io_type = value;
- switch_io_type(capture, audio_param_store.input_io_type);
- break;
- case AC_SET_OUTPUT_MODE:
- value = *(rt_uint32_t *)arg;
- if (value != speaker_out && value != line_out) {
- return -EINVAL;
- }
- switch_io_type(playback, value);
- break;
- case AC_AI_DISABLE:
- rt_kprintf(" AC_AI_DISABLE\n");
- fh_acw_stop_capture(audio_config);
- if (audio_config->capture_trans != RT_NULL)
- {
- rt_free(audio_config->capture_trans);
- audio_config->capture_trans = NULL;
- }
- break;
- case AC_AO_DISABLE:
- rt_kprintf("[ac_driver]AC_AO_DISABLE\n");
- fh_acw_stop_playback(audio_config);
- if (audio_config->plauback_trans != RT_NULL)
- {
- rt_free(audio_config->plauback_trans);
- audio_config->plauback_trans = NULL;
- }
- rt_kprintf(" AC_AO_DISABLE\n");
- break;
- case AC_AI_PAUSE:
- rt_kprintf( "capture pause\n");
- rx_status = readl(audio_dev.reg_base + ACW_RXFIFO_CTRL);/*rx fifo disable*/
- rx_status = rx_status&(~(1<<0));
- writel(rx_status, audio_dev.reg_base + ACW_RXFIFO_CTRL);/*rx fifo disable*/
- break;
- case AC_AI_RESUME:
- rt_kprintf( "capture resume\n");
- rx_status = readl( audio_dev.reg_base + ACW_RXFIFO_CTRL);//clear rx fifo
- rx_status = rx_status|(1<<4);
- writel(rx_status,audio_dev.reg_base+ ACW_RXFIFO_CTRL);/*enable rx fifo*/
- rx_status = rx_status&(~(1<<4));
- rx_status = rx_status|(1<<0);
- writel(rx_status,audio_dev.reg_base + ACW_RXFIFO_CTRL);/*enable rx fifo*/
- break;
- case AC_AO_PAUSE:
- rt_kprintf( "playback pause\n");
- tx_status = readl(audio_dev.reg_base + ACW_TXFIFO_CTRL);/*rx fifo disable*/
- tx_status = tx_status&(~(1<<0));
- writel(tx_status, audio_dev.reg_base + ACW_TXFIFO_CTRL);/*tx fifo disable*/
- break;
- case AC_AO_RESUME:
- rt_kprintf( "playback resume\n");
- tx_status = readl( audio_dev.reg_base + ACW_TXFIFO_CTRL);//clear rx fifo
- tx_status = tx_status|(1<<0);
- writel(tx_status,audio_dev.reg_base + ACW_TXFIFO_CTRL); //enable tx fifo read enable
- break;
- default:
- return -ENOTTY;
- }
- return 0;
- }
- static rt_err_t fh_audio_open(rt_device_t dev, rt_uint16_t oflag)
- {
- unsigned int reg;
- struct fh_audio_cfg *audio_config = dev->user_data;
- //enable interrupts
- reg = readl(audio_dev.reg_base + ACW_CTRL);
- reg |= 0xa;
- writel(reg, audio_dev.reg_base + ACW_CTRL);
- return 0;
- }
- static rt_err_t fh_audio_tx_poll(rt_device_t dev, void *buffer){
- struct fh_audio_cfg *audio_config = dev->user_data;
- unsigned int mask = 0;
- long avail;
- if (running == audio_config->playback.state)
- {
- rt_sem_take(&audio_config->sem_playback, RT_WAITING_FOREVER);
- avail = avail_data_len(playback, audio_config);
- if (avail > audio_config->playback.cfg.period_bytes)
- {
- mask |= POLLOUT | POLLWRNORM;
- }
- }
- return mask;
- }
- static rt_err_t fh_audio_rx_poll(rt_device_t dev, rt_size_t size){
- struct fh_audio_cfg *audio_config = dev->user_data;
- unsigned int mask = 0;
- long avail;
- if (running == audio_config->capture.state)
- {
- rt_sem_take(&audio_config->sem_capture, RT_WAITING_FOREVER);
- avail = avail_data_len(capture, audio_config);
- if (avail > audio_config->capture.cfg.period_bytes)
- {
- mask |= POLLIN | POLLRDNORM;
- }
- }
- return mask;
- }
- static dma_complete_callback mem_complete(void *p){
- struct rt_completion *completion = (struct rt_completion *)p;
- rt_completion_done(completion);
- }
- static rt_size_t fh_audio_read(rt_device_t dev, rt_off_t pos, void *buffer, rt_size_t size)
- {
- int ret;
- struct fh_audio_cfg *audio_config = dev->user_data;
- int after,left;
- int pid,avail;
- avail = avail_data_len(capture, audio_config);
- if (avail > size)
- {
- avail = size;
- }
- after = avail + audio_config->capture.appl_ptr;
- if(after > audio_config->capture.size)
- {
- left = avail - (audio_config->capture.size - audio_config->capture.appl_ptr);
- rt_memcpy(buffer, audio_config->capture.area+audio_config->capture.appl_ptr, audio_config->capture.size-audio_config->capture.appl_ptr);
- rt_memcpy(buffer+audio_config->capture.size-audio_config->capture.appl_ptr,audio_config->capture.area,left);
- rt_mutex_take(&audio_config->capture.lock, RT_WAITING_FOREVER);
- audio_config->capture.appl_ptr = left;
- rt_mutex_release(&audio_config->capture.lock);
- }
- else
- {
- rt_memcpy(buffer,audio_config->capture.area+audio_config->capture.appl_ptr,avail);
- rt_mutex_take(&audio_config->capture.lock, RT_WAITING_FOREVER);
- audio_config->capture.appl_ptr += avail;
- rt_mutex_release(&audio_config->capture.lock);
- }
- return avail;
- }
- static rt_size_t fh_audio_write(rt_device_t dev, rt_off_t pos, const void *buffer, rt_size_t size)
- {
- struct fh_audio_cfg *audio_config = dev->user_data;
- int ret;
- int after,left;
- int pid,avail;
- avail = avail_data_len(playback,audio_config);
- if (0 == avail)
- {
- return 0;
- }
- if (avail > size)
- {
- avail = size;
- }
- after = avail+audio_config->playback.appl_ptr;
- if(after > audio_config->playback.size)
- {
- left = avail - (audio_config->playback.size-audio_config->playback.appl_ptr);
- rt_memcpy(audio_config->playback.area+audio_config->playback.appl_ptr,buffer,audio_config->playback.size-audio_config->playback.appl_ptr);
- rt_memcpy(audio_config->playback.area,buffer+audio_config->playback.size-audio_config->playback.appl_ptr,left);
- rt_mutex_take(&audio_config->playback.lock, RT_WAITING_FOREVER);
- audio_config->playback.appl_ptr = left;
- rt_mutex_release(&audio_config->playback.lock);
- }
- else
- {
- rt_memcpy(audio_config->playback.area+audio_config->playback.appl_ptr,buffer,avail);
- rt_mutex_take(&audio_config->playback.lock, RT_WAITING_FOREVER);
- audio_config->playback.appl_ptr += avail;
- rt_mutex_release(&audio_config->playback.lock);
- }
- return avail;
- }
- static void fh_audio_interrupt(int irq, void *param)
- {
- unsigned int interrupts, reg;
- struct fh_audio_cfg *audio_config = audio_dev.audio_config;
- interrupts = readl(audio_dev.reg_base + ACW_CTRL);
- writel(interrupts, audio_dev.reg_base + ACW_CTRL);
- if(interrupts & ACW_INTR_RX_UNDERFLOW)
- {
- fh_acw_stop_capture(audio_config);
- fh_acw_start_capture(audio_config);
- rt_kprintf("ACW_INTR_RX_UNDERFLOW\n");
- }
- if(interrupts & ACW_INTR_RX_OVERFLOW)
- {
- fh_acw_stop_capture(audio_config);
- fh_acw_start_capture(audio_config);
- rt_kprintf("ACW_INTR_RX_OVERFLOW\n");
- }
- if(interrupts & ACW_INTR_TX_UNDERFLOW)
- {
- fh_acw_stop_capture(audio_config);
- fh_acw_start_capture(audio_config);
- rt_kprintf("ACW_INTR_TX_UNDERFLOW\n");
- }
- if(interrupts & ACW_INTR_TX_OVERFLOW)
- {
- fh_acw_stop_capture(audio_config);
- fh_acw_start_capture(audio_config);
- rt_kprintf("ACW_INTR_TX_OVERFLOW\n");
- }
- rt_kprintf("interrupts: 0x%x\n", interrupts);
- }
- void audio_prealloc_dma_buffer(int aiaotype,struct fh_audio_cfg *audio_config)
- {
- if(aiaotype == mic_in || aiaotype == line_in){
- audio_config->capture.area = (void *)fh_dma_mem_malloc(audio_config->capture.cfg.buffer_bytes \
- + audio_config->capture.cfg.period_bytes);
- if (!audio_config->capture.area)
- {
- rt_kprintf("no enough mem for capture buffer alloc\n");
- return ;
- }
- }
- if(aiaotype == speaker_out || aiaotype == line_out){
- audio_config->playback.area = (void *)fh_dma_mem_malloc(audio_config->playback.cfg.buffer_bytes \
- + audio_config->playback.cfg.period_bytes);
- if (!audio_config->playback.area)
- {
- rt_kprintf("no enough mem for playback buffer alloc\n");
- return ;
- }}
- }
- void audio_free_prealloc_dma_buffer(struct fh_audio_cfg *audio_config)
- {
- rt_free( audio_config->capture.area);
- rt_free( audio_config->playback.area);
- }
- static void init_audio_mutex(struct fh_audio_cfg *audio_config)
- {
- rt_sem_init(&audio_config->sem_capture, "sem_capture", 0, RT_IPC_FLAG_FIFO);
- rt_sem_init(&audio_config->sem_playback, "sem_playback", 0, RT_IPC_FLAG_FIFO);
- }
- int audio_request_capture_channel(struct fh_audio_cfg *audio_config){
- struct rt_dma_device *rt_dma_dev;
- /*request audio rx dma channel*/
- struct dma_transfer *dma_rx_transfer;
- int ret;
- dma_rx_transfer = rt_malloc(sizeof(struct dma_transfer));
- if (!dma_rx_transfer)
- {
- rt_kprintf("alloc dma_rx_transfer failed\n");
- return RT_ENOMEM;
- }
- rt_memset(dma_rx_transfer, 0, sizeof(struct dma_transfer));
- rt_dma_dev = (struct rt_dma_device *)rt_device_find("fh81_dma");
- if(rt_dma_dev == RT_NULL){
- rt_kprintf("can't find dma dev\n");
- return -1;
- }
- audio_config->capture_dma = rt_dma_dev;
- audio_config->capture_trans = dma_rx_transfer;
- rt_dma_dev->ops->init(rt_dma_dev);
- dma_rx_transfer->channel_number = ACW_CAP_DMA_CHAN;
- dma_rx_transfer->dma_number = 0;
- dma_rx_transfer->dst_add = (rt_uint32_t)audio_config->capture.area;//audio_config->capture.area;//(rt_uint32_t)&tx_buff[0];
- dma_rx_transfer->dst_inc_mode = DW_DMA_SLAVE_INC;
- dma_rx_transfer->dst_msize = DW_DMA_SLAVE_MSIZE_32;
- dma_rx_transfer->dst_width = DW_DMA_SLAVE_WIDTH_32BIT;
- dma_rx_transfer->fc_mode = DMA_P2M;
- dma_rx_transfer->src_add = (rt_uint32_t)ACW_RXFIFO;
- dma_rx_transfer->src_inc_mode = DW_DMA_SLAVE_FIX;
- dma_rx_transfer->src_msize = DW_DMA_SLAVE_MSIZE_32;
- dma_rx_transfer->src_hs = DMA_HW_HANDSHAKING;
- dma_rx_transfer->src_width = DW_DMA_SLAVE_WIDTH_32BIT;
- dma_rx_transfer->trans_len = (audio_config->capture.cfg.buffer_bytes / 4); // DW_DMA_SLAVE_WIDTH_32BIT BUFF_SIZE;
- dma_rx_transfer->src_per =ACODEC_RX;
- dma_rx_transfer->period_len = audio_config->capture.cfg.period_bytes / 4;// (audio_config->capture.cfg.period_bytes / 4); // TEST_PER_NO;
- dma_rx_transfer->complete_callback =(dma_complete_callback)fh_acw_rx_dma_done;
- dma_rx_transfer->complete_para = audio_config;
- rt_dma_dev->ops->control(rt_dma_dev,RT_DEVICE_CTRL_DMA_OPEN,dma_rx_transfer);
- ret = rt_dma_dev->ops->control(rt_dma_dev,RT_DEVICE_CTRL_DMA_REQUEST_CHANNEL,dma_rx_transfer);
- if(ret){
- rt_kprintf("can't request capture channel\n");
- dma_rx_transfer->channel_number =0xff;
- return -ret;
- }
- }
- int audio_request_playback_channel(struct fh_audio_cfg *audio_config)
- {
- struct rt_dma_device *rt_dma_dev;
- int ret;
- struct dma_transfer *dma_tx_transfer;
- dma_tx_transfer = rt_malloc(sizeof(struct dma_transfer));
- if (!dma_tx_transfer)
- {
- rt_kprintf("alloc dma_tx_transfer failed\n");
- return RT_ENOMEM;
- }
- audio_config->plauback_trans = dma_tx_transfer;
- rt_dma_dev = (struct rt_dma_device *)rt_device_find("fh81_dma");
- if(rt_dma_dev == RT_NULL){
- rt_kprintf("can't find dma dev\n");
- return -1;
- }
- rt_dma_dev->ops->init(rt_dma_dev);
- audio_config->playback_dma = rt_dma_dev;
- rt_memset(dma_tx_transfer, 0, sizeof(struct dma_transfer));
- dma_tx_transfer->channel_number = ACW_PLY_DMA_CHAN;
- dma_tx_transfer->dma_number = 0;
- dma_tx_transfer->dst_add = (rt_uint32_t)ACW_TXFIFO;
- dma_tx_transfer->dst_hs = DMA_HW_HANDSHAKING;
- dma_tx_transfer->dst_inc_mode = DW_DMA_SLAVE_FIX;
- dma_tx_transfer->dst_msize = DW_DMA_SLAVE_MSIZE_32;
- dma_tx_transfer->dst_per = ACODEC_TX;
- dma_tx_transfer->dst_width = DW_DMA_SLAVE_WIDTH_32BIT;
- dma_tx_transfer->fc_mode = DMA_M2P;
- dma_tx_transfer->src_add = (rt_uint32_t)audio_config->playback.area;
- dma_tx_transfer->src_inc_mode = DW_DMA_SLAVE_INC;
- dma_tx_transfer->src_msize = DW_DMA_SLAVE_MSIZE_32;
- dma_tx_transfer->src_width = DW_DMA_SLAVE_WIDTH_32BIT;
- dma_tx_transfer->trans_len = (audio_config->playback.cfg.buffer_bytes / 4);// BUFF_SIZE;
- dma_tx_transfer->period_len = (audio_config->playback.cfg.period_bytes / 4); // TEST_PER_NO;
- dma_tx_transfer->complete_callback =(dma_complete_callback)fh_acw_tx_dma_done;
- dma_tx_transfer->complete_para = audio_config;
- rt_dma_dev->ops->control(rt_dma_dev,RT_DEVICE_CTRL_DMA_OPEN,dma_tx_transfer);
- ret = rt_dma_dev->ops->control(rt_dma_dev,RT_DEVICE_CTRL_DMA_REQUEST_CHANNEL,dma_tx_transfer);
- if(ret){
- rt_kprintf("can't request playbak channel\n");
- dma_tx_transfer->channel_number = 0xff;
- return -ret;
- }
- return 0;
- }
- void audio_release_dma_channel(struct fh_audio_cfg *audio_config)
- {
- if (audio_config->plauback_trans != RT_NULL)
- {
- audio_config->playback_dma->ops->control(audio_config->playback_dma,RT_DEVICE_CTRL_DMA_RELEASE_CHANNEL,audio_config->plauback_trans);
- rt_free(audio_config->plauback_trans);
- audio_config->plauback_trans = NULL;
- }
- if (audio_config->capture_trans != RT_NULL)
- {
- audio_config->capture_dma->ops->control(audio_config->capture_dma,RT_DEVICE_CTRL_DMA_RELEASE_CHANNEL,audio_config->capture_trans);
- rt_free(audio_config->capture_trans);
- audio_config->capture_trans = NULL;
- }
- }
- void fh_audio_init(void)
- {
- struct fh_audio_cfg *audio_config;
- audio_config = rt_malloc(sizeof(struct fh_audio_cfg));
- memset(audio_config,0,sizeof(struct fh_audio_cfg)); // new add
- audio_dev.reg_base = 0xf0a00000;
- init_audio_mutex(audio_config);
- rt_device_t audio ;
- audio = rt_malloc(sizeof(struct rt_device));
- if (audio == RT_NULL){
- rt_kprintf("%s no mem \n",__func__);
- }
- audio->user_data = audio_config;
- audio->open =fh_audio_open;
- audio->read = fh_audio_read;
- audio->write = fh_audio_write;
- audio->close = fh_audio_close;
- audio->control = fh_audio_ioctl;
- audio->rx_indicate =fh_audio_rx_poll;
- audio->tx_complete=fh_audio_tx_poll;
- audio_dev.audio_config = audio_config; // TBD_WAIT 2015.09.17 add
- rt_device_register(audio, "audio", RT_DEVICE_FLAG_RDWR);
- }
- #if ACW_SELFTEST
- #define TEST_FN "/audio.dat"
- static rt_uint32_t rx_buff[BUFF_SIZE] __attribute__((aligned(32))) ;
- static const rt_uint32_t tx_buff[BUFF_SIZE*2] __attribute__((aligned(32)))= {
- 0x11,0x22,0x33,0x44,0x55,0x66,0x77,0x88,0x99,0xaa,
- 0x11,0x22,0x33,0x44,0x55,0x66,0x77,0x88,0x99,0xaa,
- 0x11,0x22,0x33,0x44,0x55,0x66,0x77,0x88,0x99,0xaa,
- 0x11,0x22,0x33,0x44,0x55,0x66,0x77,0x88,0x99,0xaa,
- 0x11,0x22,0x33,0x44,0x55,0x66,0x77,0x88,0x99,0xaa,
- };
- struct fh_audio_cfg_arg cfg;
- void fh_acw_test(){
- rt_device_t acw_dev ;
- int i;
- int output=3;
- int select;
- int select_rx_status =0;
- int select_tx_status =0;
- int fd;
- int index, length;
- int mic_boost=1;
- int ret;
- acw_dev = ( rt_device_t )rt_device_find("audio");
- for(i=0;i<BUFF_SIZE;i++)
- rx_buff[i] = i*0x500;
- acw_dev->open(acw_dev,0);
- cfg.buffer_size = BUFF_SIZE;
- cfg.channels =0;
- cfg.frame_bit = 16;
- cfg.io_type = mic_in;
-
- cfg.period_size = BUFF_SIZE/8;
- cfg.rate = 8000;
- cfg.volume = 80;
- // for(i=0;i<100;i++){
- // acw_dev->control(acw_dev,AC_INIT_CAPTURE_MEM,&cfg);
- //
- // acw_dev->control(acw_dev,AC_AI_EN,&cfg);
- // cfg.io_type = line_out;
- // acw_dev->control(acw_dev,AC_INIT_PLAYBACK_MEM,&cfg);
- // acw_dev->control(acw_dev,AC_AO_EN,&cfg);
- // acw_dev->control(acw_dev,AC_SET_OUTPUT_MODE,&output);
- // acw_dev->control(acw_dev,AC_AI_DISABLE,&cfg);
- //
- // acw_dev->control(acw_dev,AC_AO_DISABLE,&cfg);
- // rt_kprintf(" %d \n",i);
- // }
- cfg.io_type = mic_in;
- acw_dev->control(acw_dev,AC_INIT_CAPTURE_MEM,&cfg);
- ret = acw_dev->control(acw_dev,AC_AI_EN,&cfg);
- if(ret)
- acw_dev->control(acw_dev,AC_AI_DISABLE,&cfg);
- cfg.io_type = line_out;
- acw_dev->control(acw_dev,AC_INIT_PLAYBACK_MEM,&cfg);
- ret = acw_dev->control(acw_dev,AC_AO_EN,&cfg);
- if(ret){
- acw_dev->control(acw_dev,AC_AO_DISABLE,&cfg);
- // acw_dev->control(acw_dev,AC_SET_OUTPUT_MODE,&output);
- return ;
- }
- for(i=0;i<100;i++)
- {
- rx:
- select = acw_dev->rx_indicate(acw_dev,RT_NULL);
- if(!select)
- goto rx;
- acw_dev->read(acw_dev,0,&rx_buff[0],1024*8);
- tx:
- select = acw_dev->tx_complete(acw_dev , RT_NULL);
- if(!select)
- goto tx;
- acw_dev->write(acw_dev,0,&rx_buff[0],1024*8);
- }
- acw_dev->close(acw_dev);
- }
- #ifdef RT_USING_FINSH
- #include <finsh.h>
- FINSH_FUNCTION_EXPORT(fh_acw_test, fh_acw_test);
- #endif
- #endif
- #endif
|