Browse Source

Merge pull request #803 from yygg/master

[DeviceDrivers] use data queue in audio device driver and clean up the code.
Bernard Xiong 7 years ago
parent
commit
d6fa9f912d
2 changed files with 484 additions and 785 deletions
  1. 349 655
      components/drivers/audio/audio.c
  2. 135 130
      components/drivers/include/drivers/audio.h

+ 349 - 655
components/drivers/audio/audio.c

@@ -1,8 +1,25 @@
 /*
- * audio.c
+ * File      : audio.c
+ * This file is part of RT-Thread RTOS
+ * COPYRIGHT (C) 2006 - 2017, RT-Thread Development Team
  *
- *  Created on: 2016Äê10ÔÂ19ÈÕ
- *      Author: Urey
+ *  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.
+ *
+ * Change Logs:
+ * Date           Author       Notes
+ * 2017-05-09     Urey      first version
  */
 
 #include <stdio.h>
@@ -19,383 +36,70 @@
 #define AUDIO_DBG(...)
 #endif
 
-
-rt_err_t _audio_queue_init(struct rt_audio_queue *queue, rt_uint16_t size, rt_uint16_t lwm)
+static rt_err_t _audio_send_replay_frame(struct rt_audio_device *audio)
 {
-    RT_ASSERT(queue != RT_NULL);
-
-    queue->count 	= 0;
-    queue->size  	= size;
-    queue->lwm 		= lwm;
-    queue->waiting_lwm 	= RT_FALSE;
-
-    queue->get_index 	= 0;
-    queue->put_index 	= 0;
+    rt_err_t result = RT_EOK;
+    rt_base_t level;
+    struct rt_audio_frame frame;
 
-    rt_list_init(&(queue->suspended_push_list));
-    rt_list_init(&(queue->suspended_pop_list));
+    RT_ASSERT(audio != RT_NULL);
 
-    queue->queue = (struct rt_audio_frame *)rt_malloc(sizeof(struct rt_audio_frame) * size);
-    if (queue->queue == RT_NULL)
+    //check repaly queue is empty
+    if (rt_data_queue_peak(&audio->replay->queue, &frame.data_ptr, &frame.data_size) != RT_EOK)
     {
-        return -RT_ENOMEM;
-    }
-
-    return RT_EOK;
-}
-
-rt_err_t _audio_queue_push(struct rt_audio_queue *queue, struct rt_audio_frame *frame, rt_int32_t timeout)
-{
-    rt_ubase_t  level;
-    rt_thread_t thread;
-    rt_err_t    result;
-
-    RT_ASSERT(queue != RT_NULL);
-
-    result = RT_EOK;
-    thread = rt_thread_self();
-
-    AUDIO_DBG("%s count = %d\n",__func__,queue->count);
-
-    level = rt_hw_interrupt_disable();
-    while(queue->count == queue->size)
-    {// audio queue is full
-        queue->waiting_lwm = RT_TRUE;
-
-        /* queue is full */
-        if (timeout == 0)
-        {
-            result = -RT_ETIMEOUT;
-            goto __exit;
-        }
-
-        /* current context checking */
-        RT_DEBUG_NOT_IN_INTERRUPT;
+        AUDIO_DBG("TX queue is empty\n");
+        result = -RT_EEMPTY;
 
-        /* reset thread error number */
-        thread->error = RT_EOK;
-
-        /* suspend thread on the push list */
-        rt_thread_suspend(thread);
-        rt_list_insert_before(&(queue->suspended_push_list), &(thread->tlist));
-        /* start timer */
-        if (timeout > 0)
-        {
-			/* reset the timeout of thread timer and start it */
-			rt_timer_control(&(thread->thread_timer), RT_TIMER_CTRL_SET_TIME, &timeout);
-			rt_timer_start(&(thread->thread_timer));
-        }
-
-        /* enable interrupt */
-        rt_hw_interrupt_enable(level);
-
-        /* do schedule */
-        rt_schedule();
-
-        /* thread is waked up */
-        result = thread->error;
         level = rt_hw_interrupt_disable();
-        if (result != RT_EOK) goto __exit;
-    }
-
-    queue->queue[queue->put_index].data_ptr  = frame->data_ptr;
-    queue->queue[queue->put_index].data_size = frame->data_size;
-    queue->queue[queue->put_index].data_ofs	 = frame->data_ofs;
-    queue->put_index = (queue->put_index + 1) % queue->size;
-    queue->count ++;
-
-    if (!rt_list_isempty(&(queue->suspended_pop_list)))
-    {
-        /* there is at least one thread in suspended list */
-
-        /* get thread entry */
-        thread = rt_list_entry(queue->suspended_pop_list.next,
-                               struct rt_thread,
-                               tlist);
-
-        /* resume it */
-        rt_thread_resume(thread);
-        rt_hw_interrupt_enable(level);
-
-        /* perform a schedule */
-        rt_schedule();
-
-        return result;
-    }
-__exit:
-	rt_hw_interrupt_enable(level);
-
-	return result;
-}
-
-rt_err_t _audio_queue_pop(struct rt_audio_queue *queue, struct rt_audio_frame *frame, rt_int32_t timeout)
-{
-    rt_ubase_t  level;
-    rt_thread_t thread;
-    rt_err_t    result;
-
-    RT_ASSERT(queue != RT_NULL);
-    RT_ASSERT(frame != RT_NULL);
-
-    result = RT_EOK;
-    thread = rt_thread_self();
-
-    AUDIO_DBG("%s count = %d\n",__func__,queue->count);
-
-    level = rt_hw_interrupt_disable();
-    while (queue->count == 0)
-    {
-        /* queue is empty */
-        if (timeout == 0)
-        {
-            result = -RT_ETIMEOUT;
-            goto __exit;
-        }
-
-        /* current context checking */
-        RT_DEBUG_NOT_IN_INTERRUPT;
-
-        /* reset thread error number */
-        thread->error = RT_EOK;
-
-        /* suspend thread on the pop list */
-        rt_thread_suspend(thread);
-        rt_list_insert_before(&(queue->suspended_pop_list), &(thread->tlist));
-        /* start timer */
-        if (timeout > 0)
-        {
-            /* reset the timeout of thread timer and start it */
-			rt_timer_control(&(thread->thread_timer), RT_TIMER_CTRL_SET_TIME, &timeout);
-            rt_timer_start(&(thread->thread_timer));
-        }
-
-        /* enable interrupt */
+        audio->replay->activated = RT_FALSE;
         rt_hw_interrupt_enable(level);
 
-        /* do schedule */
-        rt_schedule();
-
-        /* thread is waked up */
-        result = thread->error;
-        level  = rt_hw_interrupt_disable();
-        if (result != RT_EOK)
-            goto __exit;
+        goto _exit;
     }
 
-    frame->data_ptr  = queue->queue[queue->get_index].data_ptr;
-    frame->data_size = queue->queue[queue->get_index].data_size;
-    frame->data_ofs  = queue->queue[queue->get_index].data_ofs;
-
-    queue->get_index = (queue->get_index + 1) % queue->size;
-    queue->count --;
-
-    if ((queue->waiting_lwm == RT_TRUE) &&
-        (queue->put_index - queue->get_index) <= queue->lwm)
+    if (audio->ops->transmit != RT_NULL)
     {
-        queue->waiting_lwm = RT_FALSE;
-
-        /*
-         * there is at least one thread in suspended list
-         * and less than low water mark
-         */
-        if (!rt_list_isempty(&(queue->suspended_push_list)))
+        AUDIO_DBG("audio transmit...\n");
+        if (audio->ops->transmit(audio, frame.data_ptr, RT_NULL, frame.data_size) != frame.data_size)
         {
-            /* get thread entry */
-            thread = rt_list_entry(queue->suspended_push_list.next,
-                                   struct rt_thread,
-                                   tlist);
-
-            /* resume it */
-            rt_thread_resume(thread);
-            rt_hw_interrupt_enable(level);
+            result = -RT_EBUSY;
 
-            /* perform a schedule */
-            rt_schedule();
+            goto _exit;
         }
-
-        return result;
-    }
-__exit:
-	rt_hw_interrupt_enable(level);
-	return result;
-}
-
-rt_err_t _audio_queue_peak(struct rt_audio_queue *queue, struct rt_audio_frame *frame)
-{
-    rt_ubase_t  level;
-
-    RT_ASSERT(queue != RT_NULL);
-
-    AUDIO_DBG("%s count = %d\n",__func__,queue->count);
-
-    level = rt_hw_interrupt_disable();
-    if (queue->count == 0)
-    {
-        rt_hw_interrupt_enable(level);
-
-        return -RT_EEMPTY;
     }
 
-    frame->data_ptr  = queue->queue[queue->get_index].data_ptr;
-    frame->data_size = queue->queue[queue->get_index].data_size;
-    frame->data_ofs  = queue->queue[queue->get_index].data_ofs;
-
-    rt_hw_interrupt_enable(level);
+    //pop the head frame...
+    rt_data_queue_pop(&audio->replay->queue, &frame.data_ptr, &frame.data_size, RT_WAITING_FOREVER);
 
-    return RT_EOK;
+    _exit: return result;
 }
 
-rt_err_t _audio_queue_unpeak(struct rt_audio_queue *queue, struct rt_audio_frame *frame)
+static rt_err_t _audio_flush_replay_frame(struct rt_audio_device *audio)
 {
-    rt_ubase_t  level;
-
-    RT_ASSERT(queue != RT_NULL);
+    struct rt_audio_frame frame;
 
-    level = rt_hw_interrupt_disable();
-
-    if (queue->count == 0)
+    if (audio->replay == RT_NULL)
+        return -RT_EIO;
+    while (rt_data_queue_peak(&audio->replay->queue, &frame.data_ptr, &frame.data_size) == RT_EOK)
     {
-        rt_hw_interrupt_enable(level);
+        //pop the head frame...
+        rt_data_queue_pop(&audio->replay->queue, &frame.data_ptr, &frame.data_size, RT_WAITING_FOREVER);
 
-        return -RT_EEMPTY;
+        /* notify transmitted complete. */
+        if (audio->parent.tx_complete != RT_NULL)
+            audio->parent.tx_complete(&audio->parent, (void *) frame.data_ptr);
     }
 
-	queue->queue[queue->get_index].data_ptr  = frame->data_ptr;
-	queue->queue[queue->get_index].data_size = frame->data_size;
-	queue->queue[queue->get_index].data_ofs  = frame->data_ofs;
-
-    rt_hw_interrupt_enable(level);
-
     return RT_EOK;
 }
 
-rt_err_t _audio_queue_reset(struct rt_audio_queue *queue)
-{
-    struct rt_thread *thread;
-    register rt_ubase_t temp;
-
-    rt_enter_critical();
-
-    /* wakeup all suspend threads */
-    /* resume on pop list */
-     while (!rt_list_isempty(&(queue->suspended_pop_list)))
-     {
-         /* disable interrupt */
-         temp = rt_hw_interrupt_disable();
-
-         /* get next suspend thread */
-         thread = rt_list_entry(queue->suspended_pop_list.next,
-                                struct rt_thread,
-                                tlist);
-         /* set error code to RT_ERROR */
-         thread->error = -RT_ERROR;
-
-         /*
-          * resume thread
-          * In rt_thread_resume function, it will remove current thread from
-          * suspend list
-          */
-         rt_thread_resume(thread);
-
-         /* enable interrupt */
-         rt_hw_interrupt_enable(temp);
-     }
-
-     /* resume on push list */
-     while (!rt_list_isempty(&(queue->suspended_push_list)))
-     {
-         /* disable interrupt */
-         temp = rt_hw_interrupt_disable();
-
-         /* get next suspend thread */
-         thread = rt_list_entry(queue->suspended_push_list.next,
-                                struct rt_thread,
-                                tlist);
-         /* set error code to RT_ERROR */
-         thread->error = -RT_ERROR;
-
-         /*
-          * resume thread
-          * In rt_thread_resume function, it will remove current thread from
-          * suspend list
-          */
-         rt_thread_resume(thread);
-
-         /* enable interrupt */
-         rt_hw_interrupt_enable(temp);
-     }
-     rt_exit_critical();
-
-     rt_schedule();
-}
-
-
-static rt_err_t _audio_send_replay_frame(struct rt_audio_device *audio)
-{
-    rt_err_t    result = RT_EOK;
-    rt_base_t	level;
-    struct rt_audio_frame	 frame;
-
-    RT_ASSERT(audio != RT_NULL);
-
-	//check repaly queue is empty
-	if(_audio_queue_peak(&audio->replay->queue,&frame) != RT_EOK)
-	{
-		AUDIO_DBG("TX queue is empty\n");
-		result = -RT_EEMPTY;
-
-		level = rt_hw_interrupt_disable();
-		audio->replay->activated = RT_FALSE;
-		rt_hw_interrupt_enable(level);
-
-		goto _exit;
-	}
-
-	if(audio->ops->transmit != RT_NULL)
-	{
-		AUDIO_DBG("audio transmit...\n");
-		if(audio->ops->transmit(audio,frame.data_ptr,RT_NULL, frame.data_size) != frame.data_size)
-		{
-			result = -RT_EBUSY;
-
-			goto _exit;
-		}
-	}
-
-	//pop the head frame...
-	_audio_queue_pop(&audio->replay->queue,&frame,RT_WAITING_NO);
-
-_exit:
-	return result;
-}
-
-static rt_err_t _audio_flush_replay_frame(struct rt_audio_device *audio)
-{
-    struct rt_audio_frame	 frame;
-
-	if(audio->replay == RT_NULL)
-		return -RT_EIO;
-
-	while(_audio_queue_peak(&audio->replay->queue,&frame) == RT_EOK)
-	{
-		//pop the head frame...
-		_audio_queue_pop(&audio->replay->queue,&frame,RT_WAITING_NO);
-
-		/* notify transmitted complete. */
-		if(audio->parent.tx_complete != RT_NULL)
-			audio->parent.tx_complete(&audio->parent,(void *)frame.data_ptr);
-	}
-
-	return RT_EOK;
-}
-
 static rt_err_t _audio_dev_init(struct rt_device *dev)
 {
     rt_err_t result = RT_EOK;
     struct rt_audio_device *audio;
 
     RT_ASSERT(dev != RT_NULL);
-    audio = (struct rt_audio_device *)dev;
+    audio = (struct rt_audio_device *) dev;
 
     /* initialize replay & record */
     audio->replay = RT_NULL;
@@ -410,12 +114,12 @@ static rt_err_t _audio_dev_init(struct rt_device *dev)
 
 static rt_err_t _audio_dev_open(struct rt_device *dev, rt_uint16_t oflag)
 {
-    rt_err_t    result = RT_EOK;
-    rt_base_t	level;
-    struct rt_audio_device     *audio;
+    rt_err_t result = RT_EOK;
+    rt_base_t level;
+    struct rt_audio_device *audio;
 
     RT_ASSERT(dev != RT_NULL);
-    audio = (struct rt_audio_device *)dev;
+    audio = (struct rt_audio_device *) dev;
 
     /* check device flag with the open flag */
     if ((oflag & RT_DEVICE_OFLAG_RDONLY) && !(dev->flag & RT_DEVICE_FLAG_RDONLY))
@@ -429,64 +133,65 @@ static rt_err_t _audio_dev_open(struct rt_device *dev, rt_uint16_t oflag)
     /* initialize the Rx/Tx structure according to open flag */
     if (oflag & RT_DEVICE_OFLAG_WRONLY)
     {
-    	AUDIO_DBG("open audio device ,oflag = %x\n",oflag);
-    	if(audio->replay == RT_NULL)
-    	{
-    		struct rt_audio_replay	*replay = (struct rt_audio_replay	*)rt_malloc(sizeof(struct rt_audio_replay));
+        AUDIO_DBG("open audio device ,oflag = %x\n",oflag);
+        if (audio->replay == RT_NULL)
+        {
+            struct rt_audio_replay *replay = (struct rt_audio_replay *) rt_malloc(sizeof(struct rt_audio_replay));
 
-    		if(replay == RT_NULL)
-    		{
-    			AUDIO_DBG("request memory for replay error\n");
-    			return -RT_ENOMEM;
-    		}
+            if (replay == RT_NULL)
+            {
+                AUDIO_DBG("request memory for replay error\n");
+                return -RT_ENOMEM;
+            }
 
-    		//init queue for audio replay
-    		_audio_queue_init(&replay->queue,CFG_AUDIO_REPLAY_QUEUE_COUNT,CFG_AUDIO_REPLAY_QUEUE_COUNT / 2);
+            //init queue for audio replay
+            rt_data_queue_init(&replay->queue, CFG_AUDIO_REPLAY_QUEUE_COUNT, CFG_AUDIO_REPLAY_QUEUE_COUNT / 2, RT_NULL);
 
-    		replay->activated = RT_FALSE;
-    		audio->replay = replay;
-    	}
+            replay->activated = RT_FALSE;
+            audio->replay = replay;
+        }
 
         dev->open_flag |= RT_DEVICE_OFLAG_WRONLY;
     }
 
-    if(oflag & RT_DEVICE_OFLAG_RDONLY)
+    if (oflag & RT_DEVICE_OFLAG_RDONLY)
     {
-    	if(audio->record == RT_NULL)
-    	{
-    		struct rt_audio_record	*record = (struct rt_audio_record *)rt_malloc(sizeof(struct rt_audio_record));
-
-    		if(record == RT_NULL)
-    		{
-    			AUDIO_DBG("request memory for record error\n");
-    			return -RT_ENOMEM;
-    		}
-
-    		//init pipe for record
-    		{
-    			rt_size_t size  = CFG_AUDIO_RECORD_PIPE_SIZE;
-    			rt_uint8_t *buf = rt_malloc(CFG_AUDIO_RECORD_PIPE_SIZE);
-
-    			if(buf == RT_NULL)
-    			{
-    				rt_free(record);
-        			AUDIO_DBG("request pipe memory error\n");
-
-    				return -RT_ENOMEM;
-    			}
-
-    			rt_pipe_init(&record->pipe,"recpipe",RT_PIPE_FLAG_FORCE_WR | RT_PIPE_FLAG_BLOCK_RD,buf,CFG_AUDIO_RECORD_PIPE_SIZE);
-    		}
-
-    		record->activated   = RT_FALSE;
-    		audio->record       = record;
-    	}
-
-    	//open record pipe
-    	if(audio->record != RT_NULL)
-    	{
-    		rt_device_open(RT_DEVICE(&audio->record->pipe),RT_DEVICE_OFLAG_RDONLY);
-    	}
+        if (audio->record == RT_NULL)
+        {
+            struct rt_audio_record *record = (struct rt_audio_record *) rt_malloc(sizeof(struct rt_audio_record));
+
+            if (record == RT_NULL)
+            {
+                AUDIO_DBG("request memory for record error\n");
+                return -RT_ENOMEM;
+            }
+
+            //init pipe for record
+            {
+                rt_size_t size = CFG_AUDIO_RECORD_PIPE_SIZE;
+                rt_uint8_t *buf = rt_malloc(CFG_AUDIO_RECORD_PIPE_SIZE);
+
+                if (buf == RT_NULL)
+                {
+                    rt_free(record);
+                    AUDIO_DBG("request pipe memory error\n");
+
+                    return -RT_ENOMEM;
+                }
+
+                rt_pipe_init(&record->pipe, "recpipe", RT_PIPE_FLAG_FORCE_WR | RT_PIPE_FLAG_BLOCK_RD, buf,
+                             CFG_AUDIO_RECORD_PIPE_SIZE);
+            }
+
+            record->activated = RT_FALSE;
+            audio->record = record;
+        }
+
+        //open record pipe
+        if (audio->record != RT_NULL)
+        {
+            rt_device_open(RT_DEVICE(&audio->record->pipe), RT_DEVICE_OFLAG_RDONLY);
+        }
 
         dev->open_flag |= RT_DEVICE_OFLAG_RDONLY;
     }
@@ -496,96 +201,93 @@ static rt_err_t _audio_dev_open(struct rt_device *dev, rt_uint16_t oflag)
 
 static rt_err_t _audio_dev_close(struct rt_device *dev)
 {
-    struct rt_audio_device     *audio;
+    struct rt_audio_device *audio;
     RT_ASSERT(dev != RT_NULL);
-    audio = (struct rt_audio_device *)dev;
+    audio = (struct rt_audio_device *) dev;
 
-	//shutdown the lower device
-    if(audio->ops->shutdown != RT_NULL)
-    	audio->ops->shutdown(audio);
+    //shutdown the lower device
+    if (audio->ops->shutdown != RT_NULL)
+        audio->ops->shutdown(audio);
 
-    if(dev->open_flag & RT_DEVICE_OFLAG_WRONLY)
+    if (dev->open_flag & RT_DEVICE_OFLAG_WRONLY)
     {
-    	struct rt_audio_frame frame;
-    	//stop replay stream
-    	audio->ops->stop(audio,AUDIO_STREAM_REPLAY);
+        struct rt_audio_frame frame;
+        //stop replay stream
+        audio->ops->stop(audio, AUDIO_STREAM_REPLAY);
 
-    	//flush all frame
-    	while(_audio_queue_peak(&audio->replay->queue,&frame) == RT_EOK)
-    	{
-    		_audio_queue_pop(&audio->replay->queue,&frame,RT_WAITING_NO);
+        //flush all frame
+        while (rt_data_queue_peak(&audio->replay->queue, &frame.data_ptr, &frame.data_size) == RT_EOK)
+        {
+            //pop the head frame...
+            rt_data_queue_pop(&audio->replay->queue, &frame.data_ptr, &frame.data_size, RT_WAITING_FOREVER);
 
-    		//indicate this frame complete(maybe upper device need free data)
-    		if(dev->tx_complete != RT_NULL)
-    			dev->tx_complete(dev,(void *)frame.data_ptr);
-    	}
+            /* notify transmitted complete. */
+            if (audio->parent.tx_complete != RT_NULL)
+                audio->parent.tx_complete(&audio->parent, (void *) frame.data_ptr);
+        }
 
-    	dev->open_flag &= ~RT_DEVICE_OFLAG_WRONLY;
+        dev->open_flag &= ~RT_DEVICE_OFLAG_WRONLY;
     }
 
-    if(dev->open_flag & RT_DEVICE_OFLAG_RDONLY)
+    if (dev->open_flag & RT_DEVICE_OFLAG_RDONLY)
     {
-    	//stop record stream
-    	audio->ops->stop(audio,AUDIO_STREAM_RECORD);
+        //stop record stream
+        audio->ops->stop(audio, AUDIO_STREAM_RECORD);
 
-    	//close record pipe
-    	if(audio->record != RT_NULL)
-    		rt_device_close(RT_DEVICE(&audio->record->pipe));
+        //close record pipe
+        if (audio->record != RT_NULL)
+            rt_device_close(RT_DEVICE(&audio->record->pipe));
 
-    	dev->open_flag &= ~RT_DEVICE_OFLAG_RDONLY;
+        dev->open_flag &= ~RT_DEVICE_OFLAG_RDONLY;
     }
 
-	return RT_EOK;
+    return RT_EOK;
 }
 
 static rt_size_t _audio_dev_read(struct rt_device *dev, rt_off_t pos, void *buffer, rt_size_t size)
 {
-    struct rt_audio_device     *audio;
+    struct rt_audio_device *audio;
     RT_ASSERT(dev != RT_NULL);
-    audio = (struct rt_audio_device *)dev;
-    if(!(dev->open_flag & RT_DEVICE_OFLAG_RDONLY) || (audio->record == RT_NULL))
-    	return 0;
+    audio = (struct rt_audio_device *) dev;
+    if (!(dev->open_flag & RT_DEVICE_OFLAG_RDONLY) || (audio->record == RT_NULL))
+        return 0;
 
     return rt_device_read(RT_DEVICE(&audio->record->pipe), pos, buffer, size);
 }
 
 static rt_size_t _audio_dev_write(struct rt_device *dev, rt_off_t pos, const void *buffer, rt_size_t size)
 {
-    rt_err_t    result = RT_EOK;
-    rt_base_t	level;
-    struct rt_audio_device     *audio;
+    rt_err_t result = RT_EOK;
+    rt_base_t level;
+    struct rt_audio_device *audio;
 
     RT_ASSERT(dev != RT_NULL);
-    audio = (struct rt_audio_device *)dev;
+    audio = (struct rt_audio_device *) dev;
 
-    if(!(dev->open_flag & RT_DEVICE_OFLAG_WRONLY) || (audio->replay == RT_NULL))
-    	return 0;
+    if (!(dev->open_flag & RT_DEVICE_OFLAG_WRONLY) || (audio->replay == RT_NULL))
+        return 0;
 
     AUDIO_DBG("audio write : pos = %d,buffer = %x,size = %d\n",pos,(rt_uint32_t)buffer,size);
     //push a new frame to tx queue
     {
-        struct rt_audio_frame		frame;
-        frame.data_ptr  = buffer;
-        frame.data_size = size;
-        frame.data_ofs  = 0;
-
-        result = _audio_queue_push(&audio->replay->queue,&frame,RT_WAITING_FOREVER);
-        if(result != RT_EOK)
+        result = rt_data_queue_push(&audio->replay->queue, buffer, size,
+        RT_WAITING_FOREVER);
+        if (result != RT_EOK)
         {
-    		AUDIO_DBG("TX frame queue push error\n");
-    		rt_set_errno(-RT_EFULL);
+            AUDIO_DBG("TX frame queue push error\n");
+            rt_set_errno(-RT_EFULL);
             return 0;
         }
     }
 
     //check tx state...
     level = rt_hw_interrupt_disable();
-    if(audio->replay->activated != RT_TRUE)
+    if (audio->replay->activated != RT_TRUE)
     {
-    	audio->replay->activated = RT_TRUE;
-    	rt_hw_interrupt_enable(level);
+        audio->replay->activated = RT_TRUE;
+        rt_hw_interrupt_enable(level);
 
-    	_audio_send_replay_frame(audio);
+        _audio_send_replay_frame(audio);
     }
 
     return size;
@@ -593,251 +295,243 @@ static rt_size_t _audio_dev_write(struct rt_device *dev, rt_off_t pos, const voi
 
 static rt_err_t _audio_dev_control(struct rt_device *dev, rt_uint8_t cmd, void *args)
 {
-    rt_err_t    result = RT_EOK;
-    struct rt_audio_device    *audio;
+    rt_err_t result = RT_EOK;
+    struct rt_audio_device *audio;
     RT_ASSERT(dev != RT_NULL);
-    audio = (struct rt_audio_device *)dev;
+    audio = (struct rt_audio_device *) dev;
 
     //dev stat...
-	switch (cmd)
-	{
-	case AUDIO_CTL_GETCAPS:
-	{
-		struct rt_audio_caps *caps = (struct rt_audio_caps *) args;
-
-		AUDIO_DBG("AUDIO_CTL_GETCAPS: main_type = %d,sub_type = %d\n",caps->main_type,caps->sub_type);
-		if (audio->ops->getcaps != RT_NULL)
-		{
-			result = audio->ops->getcaps(audio, caps);
-		}
-	}
-		break;
-	case AUDIO_CTL_CONFIGURE:
-	{
-		struct rt_audio_caps *caps = (struct rt_audio_caps *) args;
-
-		AUDIO_DBG("AUDIO_CTL_CONFIGURE: main_type = %d,sub_type = %d\n",caps->main_type,caps->sub_type);
-		if (audio->ops->configure != RT_NULL)
-		{
-			result = audio->ops->configure(audio, caps);
-		}
-	}
-
-		break;
-	case AUDIO_CTL_SHUTDOWN:
-	{
-		AUDIO_DBG("AUDIO_CTL_SHUTDOWN\n");
-
-		if (audio->ops->shutdown != RT_NULL)
-			result = audio->ops->shutdown(audio);
-
-		//flush replay frame...
-		_audio_flush_replay_frame(audio);
-	}
-		break;
-
-	case AUDIO_CTL_START:
-	{
-		int stream = *(int *) args;
-
-		AUDIO_DBG("AUDIO_CTL_START: stream = %d\n",stream);
-		if (audio->ops->start != RT_NULL)
-			result = audio->ops->start(audio, stream);
-	}
-		break;
-	case AUDIO_CTL_STOP:
-	{
-		int stream = *(int *) args;
-
-		AUDIO_DBG("AUDIO_CTL_STOP: stream = %d\n",stream);
-		if (audio->ops->start != RT_NULL)
-			result = audio->ops->stop(audio, stream);
-
-		if(stream == AUDIO_STREAM_REPLAY)
-		{
-			_audio_flush_replay_frame(audio);
-		}
-	}
-		break;
-	case AUDIO_CTL_PAUSE:
-	{
-		int stream = *(int *) args;
-
-		AUDIO_DBG("AUDIO_CTL_PAUSE: stream = %d\n",stream);
-		if (audio->ops->start != RT_NULL)
-			result = audio->ops->suspend(audio, stream);
-	}
-		break;
-	case AUDIO_CTL_RESUME:
-	{
-		int stream = *(int *) args;
-
-		AUDIO_DBG("AUDIO_CTL_RESUME: stream = %d\n",stream);
-		if (audio->ops->start != RT_NULL)
-			result = audio->ops->resume(audio, stream);
-
-		//resume tx frame...
-		if(stream == AUDIO_STREAM_REPLAY)
-			_audio_send_replay_frame(audio);
-	}
-		break;
-#ifdef AUDIO_DEVICE_USE_PRIVATE_BUFFER
-	case AUDIO_CTL_ALLOCBUFFER:
-	{
-		struct rt_audio_buf_desc *desc = (struct rt_audio_buf_desc *)args;
-
-		if((audio->ops->buffer_alloc != RT_NULL) && (desc != RT_NULL))
-		{
-			result = audio->ops->buffer_alloc(audio,&desc->data_ptr,&desc->data_size);
-			break;
-		}
-
-		result = -RT_EIO;
-	}
-		break;
-	case AUDIO_CTL_FREEBUFFER:
-	{
-		rt_uint8_t *data_ptr = (rt_uint8_t *)args;
-		if((audio->ops->buffer_free != RT_NULL) && (data_ptr != RT_NULL))
-		{
-			audio->ops->buffer_free(audio,data_ptr);
-			break;
-		}
-	}
-		break;
-#endif
-	default:
-		result = audio->ops->control(audio, cmd, args);
-		break;
-	}
+    switch (cmd)
+    {
+        case AUDIO_CTL_GETCAPS:
+        {
+            struct rt_audio_caps *caps = (struct rt_audio_caps *) args;
+
+            AUDIO_DBG("AUDIO_CTL_GETCAPS: main_type = %d,sub_type = %d\n",caps->main_type,caps->sub_type);
+            if (audio->ops->getcaps != RT_NULL)
+            {
+                result = audio->ops->getcaps(audio, caps);
+            }
+        }
+        break;
+        case AUDIO_CTL_CONFIGURE:
+        {
+            struct rt_audio_caps *caps = (struct rt_audio_caps *) args;
+
+            AUDIO_DBG("AUDIO_CTL_CONFIGURE: main_type = %d,sub_type = %d\n",caps->main_type,caps->sub_type);
+            if (audio->ops->configure != RT_NULL)
+            {
+                result = audio->ops->configure(audio, caps);
+            }
+        }
+
+        break;
+        case AUDIO_CTL_SHUTDOWN:
+        {
+            AUDIO_DBG("AUDIO_CTL_SHUTDOWN\n");
+
+            if (audio->ops->shutdown != RT_NULL)
+                result = audio->ops->shutdown(audio);
+
+            //flush replay frame...
+            _audio_flush_replay_frame(audio);
+        }
+        break;
+
+        case AUDIO_CTL_START:
+        {
+            int stream = *(int *) args;
+
+            AUDIO_DBG("AUDIO_CTL_START: stream = %d\n",stream);
+            if (audio->ops->start != RT_NULL)
+                result = audio->ops->start(audio, stream);
+        }
+        break;
+        case AUDIO_CTL_STOP:
+        {
+            int stream = *(int *) args;
+
+            AUDIO_DBG("AUDIO_CTL_STOP: stream = %d\n",stream);
+            if (audio->ops->start != RT_NULL)
+                result = audio->ops->stop(audio, stream);
+
+            if (stream == AUDIO_STREAM_REPLAY)
+            {
+                _audio_flush_replay_frame(audio);
+            }
+        }
+        break;
+        case AUDIO_CTL_PAUSE:
+        {
+            int stream = *(int *) args;
+
+            AUDIO_DBG("AUDIO_CTL_PAUSE: stream = %d\n",stream);
+            if (audio->ops->start != RT_NULL)
+                result = audio->ops->suspend(audio, stream);
+        }
+        break;
+        case AUDIO_CTL_RESUME:
+        {
+            int stream = *(int *) args;
+
+            AUDIO_DBG("AUDIO_CTL_RESUME: stream = %d\n",stream);
+            if (audio->ops->start != RT_NULL)
+                result = audio->ops->resume(audio, stream);
+
+            //resume tx frame...
+            if (stream == AUDIO_STREAM_REPLAY)
+                _audio_send_replay_frame(audio);
+        }
+        break;
+        case AUDIO_CTL_ALLOCBUFFER:
+        {
+            struct rt_audio_buf_desc *desc = (struct rt_audio_buf_desc *) args;
+
+            if (desc)
+            {
+                desc->data_size = AUDIO_DEVICE_DECODE_MP_BLOCK_SZ * 2;
+                desc->data_ptr = rt_mp_alloc(&audio->mp, RT_WAITING_FOREVER);
+
+                result = RT_EOK;
+            }
+            else result = -RT_EIO;
+        }
+        break;
+        case AUDIO_CTL_FREEBUFFER:
+        {
+            rt_uint8_t *data_ptr = (rt_uint8_t *) args;
+            if (data_ptr)
+                rt_mp_free(data_ptr);
+        }
+        break;
+        default:
+            result = audio->ops->control(audio, cmd, args);
+        break;
+    }
 
     return result;
 }
 
-
 rt_err_t rt_audio_register(struct rt_audio_device *audio, const char *name, rt_uint32_t flag, void *data)
 {
     struct rt_device *device;
     RT_ASSERT(audio != RT_NULL);
     device = &(audio->parent);
 
-    device->type        = RT_Device_Class_Sound;
+    device->type = RT_Device_Class_Sound;
     device->rx_indicate = RT_NULL;
     device->tx_complete = RT_NULL;
 
-    device->init        = _audio_dev_init;
-    device->open        = _audio_dev_open;
-    device->close       = _audio_dev_close;
-    device->read        = _audio_dev_read;
-    device->write       = _audio_dev_write;
-    device->control     = _audio_dev_control;
-    device->user_data   = data;
+    device->init = _audio_dev_init;
+    device->open = _audio_dev_open;
+    device->close = _audio_dev_close;
+    device->read = _audio_dev_read;
+    device->write = _audio_dev_write;
+    device->control = _audio_dev_control;
+    device->user_data = data;
+
+    //init memory pool for replay
+    {
+        rt_uint8_t *mempool = rt_malloc(AUDIO_DEVICE_DECODE_MP_SZ);
+        rt_mp_init(&audio->mp, "adu_mp", mempool, AUDIO_DEVICE_DECODE_MP_SZ,
+        AUDIO_DEVICE_DECODE_MP_BLOCK_SZ * 2);
+    }
 
     /* register a character device */
     return rt_device_register(device, name, flag | RT_DEVICE_FLAG_REMOVABLE);
 }
 
-
-
-rt_size_t rt_audio_get_buffer_size(struct rt_audio_device *audio)
-{
-//	return (audio->config.period_count * audio->config.period_size);
-	return 0;
-}
-
 int rt_audio_samplerate_to_speed(rt_uint32_t bitValue)
 {
-	int speed = 0;
-	switch (bitValue)
-	{
-	case AUDIO_SAMP_RATE_8K:
-		speed = 8000;
-		break;
-	case AUDIO_SAMP_RATE_11K:
-		speed = 11052;
-		break;
-	case AUDIO_SAMP_RATE_16K:
-		speed = 16000;
-		break;
-	case AUDIO_SAMP_RATE_22K:
-		speed = 22050;
-		break;
-	case AUDIO_SAMP_RATE_32K:
-		speed = 32000;
-		break;
-	case AUDIO_SAMP_RATE_44K:
-		speed = 44100;
-		break;
-	case AUDIO_SAMP_RATE_48K:
-		speed = 48000;
-		break;
-	case AUDIO_SAMP_RATE_96K:
-		speed = 96000;
-		break;
-	case AUDIO_SAMP_RATE_128K:
-		speed = 128000;
-		break;
-	case AUDIO_SAMP_RATE_160K:
-		speed = 160000;
-		break;
-	case AUDIO_SAMP_RATE_172K:
-		speed = 176400;
-		break;
-	case AUDIO_SAMP_RATE_192K:
-		speed = 192000;
-		break;
-	default:
-
-		break;
-	}
-
-	return speed;
-}
-
+    int speed = 0;
+    switch (bitValue)
+    {
+        case AUDIO_SAMP_RATE_8K:
+            speed = 8000;
+        break;
+        case AUDIO_SAMP_RATE_11K:
+            speed = 11052;
+        break;
+        case AUDIO_SAMP_RATE_16K:
+            speed = 16000;
+        break;
+        case AUDIO_SAMP_RATE_22K:
+            speed = 22050;
+        break;
+        case AUDIO_SAMP_RATE_32K:
+            speed = 32000;
+        break;
+        case AUDIO_SAMP_RATE_44K:
+            speed = 44100;
+        break;
+        case AUDIO_SAMP_RATE_48K:
+            speed = 48000;
+        break;
+        case AUDIO_SAMP_RATE_96K:
+            speed = 96000;
+        break;
+        case AUDIO_SAMP_RATE_128K:
+            speed = 128000;
+        break;
+        case AUDIO_SAMP_RATE_160K:
+            speed = 160000;
+        break;
+        case AUDIO_SAMP_RATE_172K:
+            speed = 176400;
+        break;
+        case AUDIO_SAMP_RATE_192K:
+            speed = 192000;
+        break;
+        default:
+
+        break;
+    }
 
+    return speed;
+}
 
 rt_uint32_t rt_audio_format_to_bits(rt_uint32_t format)
 {
     switch (format)
     {
-    case AUDIO_FMT_PCM_U8:
-    case AUDIO_FMT_PCM_S8:
-        return 8;
-    case AUDIO_FMT_PCM_S16_LE:
-    case AUDIO_FMT_PCM_S16_BE:
-    case AUDIO_FMT_PCM_U16_LE:
-    case AUDIO_FMT_PCM_U16_BE:
-        return 16;
-    default:
-        return 32;
+        case AUDIO_FMT_PCM_U8:
+        case AUDIO_FMT_PCM_S8:
+            return 8;
+        case AUDIO_FMT_PCM_S16_LE:
+        case AUDIO_FMT_PCM_S16_BE:
+        case AUDIO_FMT_PCM_U16_LE:
+        case AUDIO_FMT_PCM_U16_BE:
+            return 16;
+        default:
+            return 32;
     };
 }
 
-void rt_audio_tx_complete(struct rt_audio_device *audio,rt_uint8_t *pbuf)
+void rt_audio_tx_complete(struct rt_audio_device *audio, rt_uint8_t *pbuf)
 {
-	rt_err_t result;
-	AUDIO_DBG("audio tx complete ptr=%x...\n",(rt_uint32_t)pbuf);
-
-	//try to send all frame
-	do
-	{
-		result = _audio_send_replay_frame(audio);
-	}while(result == RT_EOK);
-
-	/* notify transmitted complete. */
-	if(audio->parent.tx_complete != RT_NULL)
-		audio->parent.tx_complete(&audio->parent,(void *)pbuf);
+    rt_err_t result;
+    AUDIO_DBG("audio tx complete ptr=%x...\n",(rt_uint32_t)pbuf);
+
+    //try to send all frame
+    do
+    {
+        result = _audio_send_replay_frame(audio);
+    } while (result == RT_EOK);
+
+    /* notify transmitted complete. */
+    if (audio->parent.tx_complete != RT_NULL)
+        audio->parent.tx_complete(&audio->parent, (void *) pbuf);
 }
 
-void rt_audio_rx_done(struct rt_audio_device *audio,rt_uint8_t *pbuf,rt_size_t len)
+void rt_audio_rx_done(struct rt_audio_device *audio, rt_uint8_t *pbuf, rt_size_t len)
 {
-    rt_err_t    result = RT_EOK;
+    rt_err_t result = RT_EOK;
 
     //save data to record pipe
-    rt_device_write(RT_DEVICE(RT_DEVICE(&audio->record->pipe)),0,pbuf,len);
+    rt_device_write(RT_DEVICE(RT_DEVICE(&audio->record->pipe)), 0, pbuf, len);
 
     /* invoke callback */
-    if(audio->parent.rx_indicate != RT_NULL)
-    	audio->parent.rx_indicate(&audio->parent,len);
+    if (audio->parent.rx_indicate != RT_NULL)
+        audio->parent.rx_indicate(&audio->parent, len);
 }
 

+ 135 - 130
components/drivers/include/drivers/audio.h

@@ -1,98 +1,123 @@
+/*
+ * File      : audio.h
+ * This file is part of RT-Thread RTOS
+ * COPYRIGHT (C) 2006 - 2017, RT-Thread Development Team
+ *
+ *  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.
+ *
+ * Change Logs:
+ * Date           Author       Notes
+ * 2017-05-09     Urey      first version
+ */
+
 #ifndef __AUDIO_H__
 #define __AUDIO_H__
 
-//#define AUDIO_DEVICE_USE_PRIVATE_BUFFER
-
-
 /* AUDIO command */
-#define _AUDIO_CTL(a)   (0x10 + a)
+#define _AUDIO_CTL(a) (0x10 + a)
 
-#define AUDIO_CTL_GETCAPS            _AUDIO_CTL(1)
-#define AUDIO_CTL_CONFIGURE          _AUDIO_CTL(2)
-#define AUDIO_CTL_SHUTDOWN           _AUDIO_CTL(3)
-#define AUDIO_CTL_START              _AUDIO_CTL(4)
-#define AUDIO_CTL_STOP               _AUDIO_CTL(5)
-#define AUDIO_CTL_PAUSE              _AUDIO_CTL(6)
-#define AUDIO_CTL_RESUME             _AUDIO_CTL(7)
-#define AUDIO_CTL_GETBUFFERINFO      _AUDIO_CTL(8)
-#define AUDIO_CTL_ALLOCBUFFER        _AUDIO_CTL(9)
-#define AUDIO_CTL_FREEBUFFER         _AUDIO_CTL(10)
-#define AUDIO_CTL_HWRESET            _AUDIO_CTL(11)
+#define AUDIO_CTL_GETCAPS                   _AUDIO_CTL(1)
+#define AUDIO_CTL_CONFIGURE                 _AUDIO_CTL(2)
+#define AUDIO_CTL_SHUTDOWN                  _AUDIO_CTL(3)
+#define AUDIO_CTL_START                     _AUDIO_CTL(4)
+#define AUDIO_CTL_STOP                      _AUDIO_CTL(5)
+#define AUDIO_CTL_PAUSE                     _AUDIO_CTL(6)
+#define AUDIO_CTL_RESUME                    _AUDIO_CTL(7)
+#define AUDIO_CTL_GETBUFFERINFO             _AUDIO_CTL(8)
+#define AUDIO_CTL_ALLOCBUFFER               _AUDIO_CTL(9)
+#define AUDIO_CTL_FREEBUFFER                _AUDIO_CTL(10)
+#define AUDIO_CTL_HWRESET                   _AUDIO_CTL(11)
 
 
 /* Audio Device Types */
-#define AUDIO_TYPE_QUERY            0x00
-#define AUDIO_TYPE_INPUT            0x01
-#define AUDIO_TYPE_OUTPUT           0x02
-#define AUDIO_TYPE_MIXER            0x04
-#define AUDIO_TYPE_SELECTOR         0x08
-#define AUDIO_TYPE_EFFECT           0x10
+#define AUDIO_TYPE_QUERY                    0x00
+#define AUDIO_TYPE_INPUT                    0x01
+#define AUDIO_TYPE_OUTPUT                   0x02
+#define AUDIO_TYPE_MIXER                    0x04
+#define AUDIO_TYPE_SELECTOR                 0x08
+#define AUDIO_TYPE_EFFECT                   0x10
 
 /* Audio Format Types */
-#define AUDIO_FMT_PCM_U8            0x0001
-#define AUDIO_FMT_PCM_S8            0x0002
-
-#define AUDIO_FMT_PCM_U16_LE        0x0010
-#define AUDIO_FMT_PCM_S16_BE        0x0020
-#define AUDIO_FMT_PCM_S16_LE        0x0040
-#define AUDIO_FMT_PCM_U16_BE        0x0080
-#define AUDIO_FMT_PCM_U24_LE        0x0100
-#define AUDIO_FMT_PCM_S24_BE        0x0200
-#define AUDIO_FMT_PCM_S24_LE        0x0400
-#define AUDIO_FMT_PCM_U24_BE        0x0800
-#define AUDIO_FMT_PCM_U32_LE        0x1000
-#define AUDIO_FMT_PCM_S32_BE        0x2000
-#define AUDIO_FMT_PCM_S32_LE        0x4000
-#define AUDIO_FMT_PCM_U32_BE        0x8000
+#define AUDIO_FMT_PCM_U8                    0x0001
+#define AUDIO_FMT_PCM_S8                    0x0002
+
+#define AUDIO_FMT_PCM_U16_LE                0x0010
+#define AUDIO_FMT_PCM_S16_BE                0x0020
+#define AUDIO_FMT_PCM_S16_LE                0x0040
+#define AUDIO_FMT_PCM_U16_BE                0x0080
+#define AUDIO_FMT_PCM_U24_LE                0x0100
+#define AUDIO_FMT_PCM_S24_BE                0x0200
+#define AUDIO_FMT_PCM_S24_LE                0x0400
+#define AUDIO_FMT_PCM_U24_BE                0x0800
+#define AUDIO_FMT_PCM_U32_LE                0x1000
+#define AUDIO_FMT_PCM_S32_BE                0x2000
+#define AUDIO_FMT_PCM_S32_LE                0x4000
+#define AUDIO_FMT_PCM_U32_BE                0x8000
 
 /* Supported Sampling Rates */
-#define AUDIO_SAMP_RATE_8K          0x0001
-#define AUDIO_SAMP_RATE_11K         0x0002
-#define AUDIO_SAMP_RATE_16K         0x0004
-#define AUDIO_SAMP_RATE_22K         0x0008
-#define AUDIO_SAMP_RATE_32K         0x0010
-#define AUDIO_SAMP_RATE_44K         0x0020
-#define AUDIO_SAMP_RATE_48K         0x0040
-#define AUDIO_SAMP_RATE_96K         0x0080
-#define AUDIO_SAMP_RATE_128K        0x0100
-#define AUDIO_SAMP_RATE_160K        0x0200
-#define AUDIO_SAMP_RATE_172K        0x0400
-#define AUDIO_SAMP_RATE_192K        0x0800
+#define AUDIO_SAMP_RATE_8K                  0x0001
+#define AUDIO_SAMP_RATE_11K                 0x0002
+#define AUDIO_SAMP_RATE_16K                 0x0004
+#define AUDIO_SAMP_RATE_22K                 0x0008
+#define AUDIO_SAMP_RATE_32K                 0x0010
+#define AUDIO_SAMP_RATE_44K                 0x0020
+#define AUDIO_SAMP_RATE_48K                 0x0040
+#define AUDIO_SAMP_RATE_96K                 0x0080
+#define AUDIO_SAMP_RATE_128K                0x0100
+#define AUDIO_SAMP_RATE_160K                0x0200
+#define AUDIO_SAMP_RATE_172K                0x0400
+#define AUDIO_SAMP_RATE_192K                0x0800
 
 /* Supported Bit Rates */
-#define AUDIO_BIT_RATE_22K          0x01
-#define AUDIO_BIT_RATE_44K          0x02
-#define AUDIO_BIT_RATE_48K          0x04
-#define AUDIO_BIT_RATE_96K          0x08
-#define AUDIO_BIT_RATE_128K         0x10
-#define AUDIO_BIT_RATE_160K         0x20
-#define AUDIO_BIT_RATE_172K         0x40
-#define AUDIO_BIT_RATE_192K         0x80
+#define AUDIO_BIT_RATE_22K                  0x01
+#define AUDIO_BIT_RATE_44K                  0x02
+#define AUDIO_BIT_RATE_48K                  0x04
+#define AUDIO_BIT_RATE_96K                  0x08
+#define AUDIO_BIT_RATE_128K                 0x10
+#define AUDIO_BIT_RATE_160K                 0x20
+#define AUDIO_BIT_RATE_172K                 0x40
+#define AUDIO_BIT_RATE_192K                 0x80
 
 
 
 /* Support Dsp(input/output) Units controls */
-#define AUDIO_DSP_PARAM                 0                       /* get/set all params */
-#define AUDIO_DSP_SAMPLERATE            1                       /*  ²ÉÑùƵÂÊ */
-#define AUDIO_DSP_FMT                   2
-#define AUDIO_DSP_CHANNELS              3
+#define AUDIO_DSP_PARAM                     0           /* get/set all params */
+#define AUDIO_DSP_SAMPLERATE                1                       /*  ²ÉÑùƵÂÊ                    */
+#define AUDIO_DSP_FMT                       2
+#define AUDIO_DSP_CHANNELS                  3
 
 /* Supported Mixer Units controls */
-#define AUDIO_MIXER_QUERY              0x0000
-#define AUDIO_MIXER_MUTE               0x0001
-#define AUDIO_MIXER_VOLUME             0x0002
-#define AUDIO_MIXER_BASS               0x0004
-#define AUDIO_MIXER_MID                0x0008
-#define AUDIO_MIXER_TREBLE             0x0010
-#define AUDIO_MIXER_EQUALIZER          0x0020
-#define AUDIO_MIXER_LINE               0x0040
-#define AUDIO_MIXER_DIGITAL            0x0080
-#define AUDIO_MIXER_MIC                0x0100
-
-#define AUDIO_MIXER_EXTEND             0x8000       //extend mixer command
-
-#define CFG_AUDIO_REPLAY_QUEUE_COUNT   4
-#define CFG_AUDIO_RECORD_PIPE_SIZE     (8 * 1024)
+#define AUDIO_MIXER_QUERY                   0x0000
+#define AUDIO_MIXER_MUTE                    0x0001
+#define AUDIO_MIXER_VOLUME                  0x0002
+#define AUDIO_MIXER_BASS                    0x0004
+#define AUDIO_MIXER_MID                     0x0008
+#define AUDIO_MIXER_TREBLE                  0x0010
+#define AUDIO_MIXER_EQUALIZER               0x0020
+#define AUDIO_MIXER_LINE                    0x0040
+#define AUDIO_MIXER_DIGITAL                 0x0080
+#define AUDIO_MIXER_MIC                     0x0100
+
+#define AUDIO_MIXER_EXTEND                  0x8000    //extend mixer command
+
+#define CFG_AUDIO_REPLAY_QUEUE_COUNT        4
+#define CFG_AUDIO_RECORD_PIPE_SIZE          (8 * 1024)
+#define AUDIO_DEVICE_MP_CNT                 (4)
+#define AUDIO_DEVICE_DECODE_MP_BLOCK_SZ     (4352 * 4)
+#define AUDIO_DEVICE_DECODE_MP_SZ           ((AUDIO_DEVICE_DECODE_MP_BLOCK_SZ*2 + 4)*AUDIO_DEVICE_MP_CNT)
+
 
 enum
 {
@@ -104,36 +129,19 @@ enum
 /* the preferred number and size of audio pipeline buffer for the audio device */
 struct rt_audio_buf_info
 {
-    rt_uint32_t buffer_size;                    /* Preferred qty of buffers */
-    rt_uint32_t buffer_count;                   /* Preferred size of the buffers */
+  rt_uint32_t buffer_size;          /* Preferred qty of buffers */
+  rt_uint32_t buffer_count;           /* Preferred size of the buffers */
 };
 struct rt_audio_buf_desc
 {
-    rt_uint8_t *data_ptr;
-    rt_size_t   data_size;
+  rt_uint8_t *data_ptr;
+  rt_size_t data_size;
 };
 
 struct rt_audio_frame
 {
     const void *data_ptr;
     rt_size_t   data_size;
-    rt_size_t   data_ofs;
-};
-
-struct rt_audio_queue
-{
-    rt_uint16_t count;
-    rt_uint16_t size;
-    rt_uint16_t lwm;
-    rt_bool_t   waiting_lwm;
-
-    rt_uint16_t get_index;
-    rt_uint16_t put_index;
-
-    struct rt_audio_frame *queue;
-
-    rt_list_t suspended_push_list;
-    rt_list_t suspended_pop_list;
 };
 
 struct rt_audio_device;
@@ -141,25 +149,21 @@ struct rt_audio_caps;
 struct rt_audio_configure;
 struct rt_audio_ops
 {
-    rt_err_t    (*getcaps)          (struct rt_audio_device *audio,struct rt_audio_caps *caps);
-    rt_err_t    (*configure)        (struct rt_audio_device *audio,struct rt_audio_caps *caps);
+    rt_err_t  (*getcaps)        (struct rt_audio_device *audio,struct rt_audio_caps *caps);
+    rt_err_t  (*configure)      (struct rt_audio_device *audio,struct rt_audio_caps *caps);
 
-    rt_err_t    (*init)             (struct rt_audio_device *audio);
-    rt_err_t    (*shutdown)         (struct rt_audio_device *audio);
-    rt_err_t    (*start)            (struct rt_audio_device *audio,int stream);
-    rt_err_t    (*stop)             (struct rt_audio_device *audio,int stream);
-    rt_err_t    (*suspend)          (struct rt_audio_device *audio,int stream);
-    rt_err_t    (*resume)           (struct rt_audio_device *audio,int stream);
+    rt_err_t    (*init)         (struct rt_audio_device *audio);
+    rt_err_t    (*shutdown)     (struct rt_audio_device *audio);
+    rt_err_t    (*start)        (struct rt_audio_device *audio,int stream);
+    rt_err_t    (*stop)         (struct rt_audio_device *audio,int stream);
+    rt_err_t    (*suspend)      (struct rt_audio_device *audio,int stream);
+    rt_err_t    (*resume)       (struct rt_audio_device *audio,int stream);
 
-    rt_err_t    (*control)          (struct rt_audio_device *audio, rt_uint8_t cmd, void *arg);
-    rt_size_t   (*transmit)         (struct rt_audio_device *audio, const void *writeBuf,void *readBuf, rt_size_t size);
+    rt_err_t    (*control)      (struct rt_audio_device *audio, rt_uint8_t cmd, void *arg);
+    rt_size_t   (*transmit)     (struct rt_audio_device *audio, const void *writeBuf,void *readBuf, rt_size_t size);
 
     //get page size of codec or private buffer's info
-    void        (*buffer_info)      (struct rt_audio_device *audio,struct rt_audio_buf_info *info );
-#ifdef AUDIO_DEVICE_USE_PRIVATE_BUFFER
-    rt_err_t    (*buffer_alloc)     (struct rt_audio_device *audio,rt_uint8_t **data_ptr,rt_size_t *size);
-    void        (*buffer_free)      (struct rt_audio_device *audio,rt_uint8_t *data_ptr);
-#endif
+    void    (*buffer_info)      (struct rt_audio_device *audio,struct rt_audio_buf_info *info );
 };
 
 
@@ -174,42 +178,44 @@ struct rt_audio_configure
 
 struct rt_audio_caps
 {
-    int main_type;
-    int sub_type;
-
-    union
-    {
-        rt_uint32_t mask;
-        int         value;
-        struct rt_audio_configure config;
-    }udata;
+  int main_type;
+  int sub_type;
+
+  union
+  {
+    rt_uint32_t mask;
+    int     value;
+    struct rt_audio_configure config;
+  }udata;
 };
 
 struct rt_audio_replay
 {
     rt_bool_t activated;
-    struct rt_audio_queue       queue;
+    struct rt_data_queue queue;
 };
 
 struct rt_audio_record
 {
     rt_bool_t activated;
-    struct rt_pipe_device       pipe;
+    struct rt_pipe_device   pipe;
 };
 
 struct rt_audio_device
 {
     struct rt_device            parent;
-    struct rt_audio_ops         *ops;
+    struct rt_audio_ops        *ops;
+
+    struct rt_mempool           mp;
 
-    struct rt_audio_replay  *replay;
-    struct rt_audio_record *record;
+    struct rt_audio_replay     *replay;
+    struct rt_audio_record     *record;
 };
 
-rt_err_t rt_audio_register(struct rt_audio_device *audio, const char *name, rt_uint32_t flag, void *data);
-void rt_audio_tx_complete(struct rt_audio_device *audio,rt_uint8_t *pbuf);
-void rt_audio_rx_done(struct rt_audio_device *audio,rt_uint8_t *pbuf,rt_size_t len);
-rt_uint32_t rt_audio_format_to_bits(rt_uint32_t format);
+rt_err_t    rt_audio_register       (struct rt_audio_device *audio, const char *name, rt_uint32_t flag, void *data);
+void        rt_audio_tx_complete    (struct rt_audio_device *audio,rt_uint8_t *pbuf);
+void        rt_audio_rx_done        (struct rt_audio_device *audio,rt_uint8_t *pbuf,rt_size_t len);
+rt_uint32_t rt_audio_format_to_bits (rt_uint32_t format);
 
 
 /* Device Control Commands */
@@ -219,7 +225,6 @@ rt_uint32_t rt_audio_format_to_bits(rt_uint32_t format);
 #define CODEC_CMD_SAMPLERATE        3
 #define CODEC_CMD_EQ                4
 #define CODEC_CMD_3D                5
-#define CODEC_CMD_SWITCH            6
 
 #define CODEC_VOLUME_MAX            (63)