mirror of
https://github.com/RT-Thread/rt-thread.git
synced 2026-11-09 20:45:41 +08:00
[bsp][qemu-vexpress-a9]update qemu-vexpress-a9 audio device drivers.
This commit is contained in:
1 parent
87267b41bc
commit
559e297e4b
9 files changed
+355
-745
No files matched your search
@@ -1,191 +0,0 @@
|
||||
/*
|
||||
* File : audio_device.c
|
||||
* This file is part of RT-Thread RTOS
|
||||
* COPYRIGHT (C) 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
|
||||
* 2018-05-26 RT-Thread the first version
|
||||
*/
|
||||
|
||||
#include <rtthread.h>
|
||||
#include <rthw.h>
|
||||
#include <rtdevice.h>
|
||||
#include <string.h>
|
||||
#include "drv_pl041.h"
|
||||
#include "drv_ac97.h"
|
||||
#include "audio_device.h"
|
||||
|
||||
struct audio_device
|
||||
{
|
||||
struct rt_device *snd;
|
||||
struct rt_mempool mp;
|
||||
|
||||
int state;
|
||||
|
||||
void (*evt_handler)(void *parameter, int state);
|
||||
void *parameter;
|
||||
};
|
||||
|
||||
static struct audio_device *_audio_device = NULL;
|
||||
|
||||
void *audio_device_get_buffer(int *bufsz)
|
||||
{
|
||||
if (bufsz)
|
||||
{
|
||||
*bufsz = AUDIO_DEVICE_DECODE_MP_BLOCK_SZ * 2;
|
||||
}
|
||||
|
||||
return rt_mp_alloc(&(_audio_device->mp), RT_WAITING_FOREVER);
|
||||
}
|
||||
|
||||
void audio_device_put_buffer(void *ptr)
|
||||
{
|
||||
if (ptr) rt_mp_free(ptr);
|
||||
return ;
|
||||
}
|
||||
|
||||
static rt_err_t audio_device_write_done(struct rt_device *device, void *ptr)
|
||||
{
|
||||
if (!ptr)
|
||||
{
|
||||
rt_kprintf("device buf_release NULL\n");
|
||||
return -RT_ERROR;
|
||||
}
|
||||
|
||||
rt_mp_free(ptr);
|
||||
return RT_EOK;
|
||||
}
|
||||
|
||||
void audio_device_write(void *buffer, int size)
|
||||
{
|
||||
if (_audio_device->snd && size != 0)
|
||||
{
|
||||
if (_audio_device->state == AUDIO_DEVICE_IDLE)
|
||||
{
|
||||
if (_audio_device->evt_handler)
|
||||
_audio_device->evt_handler(_audio_device->parameter, AUDIO_DEVICE_PLAYBACK);
|
||||
|
||||
/* change audio device state */
|
||||
_audio_device->state = AUDIO_DEVICE_PLAYBACK;
|
||||
}
|
||||
|
||||
rt_device_write(_audio_device->snd, 0, buffer, size);
|
||||
}
|
||||
else
|
||||
{
|
||||
/* release buffer directly */
|
||||
rt_mp_free(buffer);
|
||||
}
|
||||
|
||||
return ;
|
||||
}
|
||||
|
||||
int audio_device_init(void)
|
||||
{
|
||||
uint8_t *mempool_ptr;
|
||||
|
||||
if (!_audio_device)
|
||||
{
|
||||
_audio_device = (struct audio_device *) rt_malloc(sizeof(struct audio_device) + AUDIO_DEVICE_DECODE_MP_SZ);
|
||||
if (_audio_device == NULL)
|
||||
{
|
||||
rt_kprintf("malloc memeory for _audio_device failed! \n");
|
||||
return -RT_ERROR;
|
||||
}
|
||||
|
||||
_audio_device->evt_handler = NULL;
|
||||
_audio_device->parameter = NULL;
|
||||
|
||||
mempool_ptr = (uint8_t *)(_audio_device + 1);
|
||||
rt_mp_init(&(_audio_device->mp), "adbuf", mempool_ptr, AUDIO_DEVICE_DECODE_MP_SZ, AUDIO_DEVICE_DECODE_MP_BLOCK_SZ * 2);
|
||||
|
||||
/* find snd device */
|
||||
_audio_device->snd = rt_device_find("sound");
|
||||
if (_audio_device->snd == NULL)
|
||||
{
|
||||
rt_kprintf("sound device not found \n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
/* set tx complete call back function */
|
||||
rt_device_set_tx_complete(_audio_device->snd, audio_device_write_done);
|
||||
}
|
||||
|
||||
return RT_EOK;
|
||||
}
|
||||
|
||||
int audio_device_set_evt_handler(void (*handler)(void *parameter, int state), void *parameter)
|
||||
{
|
||||
if (_audio_device)
|
||||
{
|
||||
_audio_device->evt_handler = handler;
|
||||
_audio_device->parameter = parameter;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
void audio_device_set_rate(int sample_rate)
|
||||
{
|
||||
if (_audio_device->snd)
|
||||
{
|
||||
int rate = sample_rate;
|
||||
|
||||
rt_device_control(_audio_device->snd, CODEC_CMD_SAMPLERATE, &rate);
|
||||
}
|
||||
}
|
||||
|
||||
void audio_device_set_volume(int value)
|
||||
{
|
||||
if (_audio_device->snd)
|
||||
{
|
||||
rt_device_control(_audio_device->snd, CODEC_CMD_SET_VOLUME, &value);
|
||||
}
|
||||
}
|
||||
|
||||
int audio_device_get_volume(void)
|
||||
{
|
||||
int value = 0;
|
||||
|
||||
if (_audio_device->snd)
|
||||
{
|
||||
rt_device_control(_audio_device->snd, CODEC_CMD_GET_VOLUME, &value);
|
||||
}
|
||||
|
||||
return value;
|
||||
}
|
||||
|
||||
void audio_device_open(void)
|
||||
{
|
||||
_audio_device->state = AUDIO_DEVICE_IDLE;
|
||||
rt_device_open(_audio_device->snd, RT_DEVICE_OFLAG_WRONLY);
|
||||
}
|
||||
|
||||
void audio_device_close(void)
|
||||
{
|
||||
rt_device_close(_audio_device->snd);
|
||||
|
||||
if (_audio_device->state == AUDIO_DEVICE_PLAYBACK)
|
||||
{
|
||||
if (_audio_device->evt_handler)
|
||||
_audio_device->evt_handler(_audio_device->parameter, AUDIO_DEVICE_CLOSE);
|
||||
}
|
||||
|
||||
/* set to idle */
|
||||
_audio_device->state = AUDIO_DEVICE_CLOSE;
|
||||
}
|
||||
@@ -1,51 +0,0 @@
|
||||
/*
|
||||
* File : audio_device.h
|
||||
* This file is part of RT-Thread RTOS
|
||||
* COPYRIGHT (C) 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
|
||||
* 2018-05-26 RT-Thread the first version
|
||||
*/
|
||||
|
||||
#ifndef AUDIO_DEVICE_H__
|
||||
#define AUDIO_DEVICE_H__
|
||||
|
||||
enum AUDIO_DEVICE_STATE
|
||||
{
|
||||
AUDIO_DEVICE_IDLE,
|
||||
AUDIO_DEVICE_PLAYBACK,
|
||||
AUDIO_DEVICE_CLOSE,
|
||||
};
|
||||
|
||||
void *audio_device_get_buffer(int *bufsz);
|
||||
void audio_device_put_buffer(void *ptr);
|
||||
|
||||
void audio_device_write(void *buffer, int size);
|
||||
|
||||
int audio_device_init(void);
|
||||
void audio_device_close(void);
|
||||
|
||||
void audio_device_open(void);
|
||||
|
||||
int audio_device_set_evt_handler(void (*handler)(void *parameter, int state), void *parameter);
|
||||
|
||||
void audio_device_set_rate(int sample_rate);
|
||||
void audio_device_set_volume(int volume);
|
||||
void audio_device_wait_free(void);
|
||||
|
||||
#endif
|
||||
File diff suppressed because it is too large.
Load diff
@@ -1,29 +0,0 @@
|
||||
/*
|
||||
* File : drv_audio.h
|
||||
* This file is part of RT-Thread RTOS
|
||||
* COPYRIGHT (C) 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
|
||||
* 2018-05-26 RT-Thread the first version
|
||||
*/
|
||||
|
||||
#ifndef __DRV_AUDIO_H__
|
||||
#define __DRV_AUDIO_H__
|
||||
|
||||
|
||||
#endif
|
||||
@@ -302,7 +302,7 @@ static void aaci_pl041_irq_handle(int irqno, void *param)
|
||||
void *p_status;
|
||||
|
||||
mask = PL041_READ(&PL041->allints);
|
||||
PL041_WRITE(PL041->intclr, mask);
|
||||
PL041_WRITE(&PL041->intclr, mask);
|
||||
|
||||
for (channle = 0; (channle < PL041_CHANNLE_NUM) && (mask); channle++)
|
||||
{
|
||||
|
||||
@@ -225,7 +225,7 @@ typedef void (*pl041_irq_fun_t)(rt_uint32_t status, void * user_data);
|
||||
rt_err_t aaci_pl041_init(void);
|
||||
void aaci_ac97_write(rt_uint16_t reg, rt_uint16_t val);
|
||||
rt_uint16_t aaci_ac97_read(rt_uint16_t reg);
|
||||
int aaci_pl041_channle_cfg(int channle, pl041_cfg_t cgf);
|
||||
int aaci_pl041_channle_cfg(int channle, pl041_cfg_t cfg);
|
||||
int aaci_pl041_channle_write(int channle, rt_uint16_t *buff, int count);
|
||||
int aaci_pl041_channle_read(int channle, rt_uint16_t *buff, int count);
|
||||
int aaci_pl041_channle_enable(int channle);
|
||||
|
||||
File diff suppressed because it is too large.
Load diff
@@ -0,0 +1,13 @@
|
||||
/*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*
|
||||
* Date Author Notes
|
||||
* 2019-07-23 Zero-Free first implementation
|
||||
*/
|
||||
|
||||
#ifndef __DRV_SOUND_H__
|
||||
#define __DRV_SOUND_H__
|
||||
|
||||
int rt_hw_audio_init(void);
|
||||
|
||||
#endif
|
||||
@@ -1,144 +0,0 @@
|
||||
#include <rtthread.h>
|
||||
#include <rtdevice.h>
|
||||
#include <finsh.h>
|
||||
|
||||
#include <string.h>
|
||||
#include <stdlib.h>
|
||||
#include <stdio.h>
|
||||
|
||||
#include "audio_device.h"
|
||||
|
||||
#define BUFSZ 2048
|
||||
|
||||
struct RIFF_HEADER_DEF
|
||||
{
|
||||
char riff_id[4]; // 'R','I','F','F'
|
||||
uint32_t riff_size;
|
||||
char riff_format[4]; // 'W','A','V','E'
|
||||
};
|
||||
|
||||
struct WAVE_FORMAT_DEF
|
||||
{
|
||||
uint16_t FormatTag;
|
||||
uint16_t Channels;
|
||||
uint32_t SamplesPerSec;
|
||||
uint32_t AvgBytesPerSec;
|
||||
uint16_t BlockAlign;
|
||||
uint16_t BitsPerSample;
|
||||
};
|
||||
|
||||
struct FMT_BLOCK_DEF
|
||||
{
|
||||
char fmt_id[4]; // 'f','m','t',' '
|
||||
uint32_t fmt_size;
|
||||
struct WAVE_FORMAT_DEF wav_format;
|
||||
};
|
||||
|
||||
struct DATA_BLOCK_DEF
|
||||
{
|
||||
char data_id[4]; // 'R','I','F','F'
|
||||
uint32_t data_size;
|
||||
};
|
||||
|
||||
struct wav_info
|
||||
{
|
||||
struct RIFF_HEADER_DEF header;
|
||||
struct FMT_BLOCK_DEF fmt_block;
|
||||
struct DATA_BLOCK_DEF data_block;
|
||||
};
|
||||
|
||||
static char file_name[32];
|
||||
|
||||
void wavplay_thread_entry(void *parameter)
|
||||
{
|
||||
FILE *fp = NULL;
|
||||
uint16_t *buffer = NULL;
|
||||
struct wav_info *info = NULL;
|
||||
|
||||
fp = fopen(file_name, "rb");
|
||||
if (!fp)
|
||||
{
|
||||
printf("open file failed!\n");
|
||||
goto __exit;
|
||||
}
|
||||
|
||||
info = (struct wav_info *) malloc(sizeof(*info));
|
||||
if (!info) goto __exit;
|
||||
|
||||
if (fread(&(info->header), sizeof(struct RIFF_HEADER_DEF), 1, fp) != 1) goto __exit;
|
||||
if (fread(&(info->fmt_block), sizeof(struct FMT_BLOCK_DEF), 1, fp) != 1) goto __exit;
|
||||
if (fread(&(info->data_block), sizeof(struct DATA_BLOCK_DEF), 1, fp) != 1) goto __exit;
|
||||
|
||||
printf("wav information:\n");
|
||||
printf("samplerate %u\n", info->fmt_block.wav_format.SamplesPerSec);
|
||||
printf("channel %u\n", info->fmt_block.wav_format.Channels);
|
||||
|
||||
audio_device_init();
|
||||
audio_device_open();
|
||||
audio_device_set_rate(info->fmt_block.wav_format.SamplesPerSec);
|
||||
|
||||
while (!feof(fp))
|
||||
{
|
||||
int length;
|
||||
|
||||
buffer = (uint16_t *)audio_device_get_buffer(RT_NULL);
|
||||
|
||||
length = fread(buffer, 1, BUFSZ, fp);
|
||||
if (length)
|
||||
{
|
||||
if (info->fmt_block.wav_format.Channels == 1)
|
||||
{
|
||||
/* extend to stereo channels */
|
||||
int index;
|
||||
uint16_t *ptr;
|
||||
|
||||
ptr = (uint16_t *)((uint8_t *)buffer + BUFSZ * 2);
|
||||
for (index = 1; index < BUFSZ / 2; index ++)
|
||||
{
|
||||
*ptr = *(ptr - 1) = buffer[BUFSZ / 2 - index];
|
||||
ptr -= 2;
|
||||
}
|
||||
|
||||
length = length * 2;
|
||||
}
|
||||
|
||||
audio_device_write((uint8_t *)buffer, length);
|
||||
}
|
||||
else
|
||||
{
|
||||
audio_device_put_buffer((uint8_t *)buffer);
|
||||
break;
|
||||
}
|
||||
}
|
||||
audio_device_close();
|
||||
|
||||
__exit:
|
||||
if (fp) fclose(fp);
|
||||
if (info) free(info);
|
||||
}
|
||||
|
||||
int wavplay(int argc, char **argv)
|
||||
{
|
||||
rt_thread_t tid = RT_NULL;
|
||||
|
||||
if (argc != 2)
|
||||
{
|
||||
printf("Usage:\n");
|
||||
printf("wavplay song.wav\n");
|
||||
return 0;
|
||||
}
|
||||
|
||||
memset(file_name, 0, sizeof(file_name));
|
||||
memcpy(file_name, argv[1], strlen(argv[1]));
|
||||
|
||||
tid = rt_thread_create("wayplay",
|
||||
wavplay_thread_entry,
|
||||
RT_NULL,
|
||||
1024 * 8,
|
||||
22,
|
||||
10);
|
||||
if (tid != RT_NULL)
|
||||
rt_thread_startup(tid);
|
||||
}
|
||||
|
||||
MSH_CMD_EXPORT(wavplay, wavplay song.wav);
|
||||
Reference in new issue
Block a user