⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 wm8750.c.svn-base

📁 我们自己开发的一个OSEK操作系统!不知道可不可以?
💻 SVN-BASE
📖 第 1 页 / 共 2 页
字号:
/* * WM8750 audio CODEC. * * Copyright (c) 2006 Openedhand Ltd. * Written by Andrzej Zaborowski <balrog@zabor.org> * * This file is licensed under GNU GPL. */#include "hw.h"#include "i2c.h"#include "audio/audio.h"#define IN_PORT_N	3#define OUT_PORT_N	3#define CODEC		"wm8750"struct wm_rate_s;struct wm8750_s {    i2c_slave i2c;    uint8_t i2c_data[2];    int i2c_len;    QEMUSoundCard card;    SWVoiceIn *adc_voice[IN_PORT_N];    SWVoiceOut *dac_voice[OUT_PORT_N];    int enable;    void (*data_req)(void *, int, int);    void *opaque;    uint8_t data_in[4096];    uint8_t data_out[4096];    int idx_in, req_in;    int idx_out, req_out;    SWVoiceOut **out[2];    uint8_t outvol[7], outmute[2];    SWVoiceIn **in[2];    uint8_t invol[4], inmute[2];    uint8_t diff[2], pol, ds, monomix[2], alc, mute;    uint8_t path[4], mpath[2], power, format;    uint32_t inmask, outmask;    const struct wm_rate_s *rate;};static inline void wm8750_in_load(struct wm8750_s *s){    int acquired;    if (s->idx_in + s->req_in <= sizeof(s->data_in))        return;    s->idx_in = audio_MAX(0, (int) sizeof(s->data_in) - s->req_in);    acquired = AUD_read(*s->in[0], s->data_in + s->idx_in,                    sizeof(s->data_in) - s->idx_in);}static inline void wm8750_out_flush(struct wm8750_s *s){    int sent;    if (!s->idx_out)        return;    sent = AUD_write(*s->out[0], s->data_out, s->idx_out);    s->idx_out = 0;}static void wm8750_audio_in_cb(void *opaque, int avail_b){    struct wm8750_s *s = (struct wm8750_s *) opaque;    s->req_in = avail_b;    s->data_req(s->opaque, s->req_out >> 2, avail_b >> 2);#if 0    wm8750_in_load(s);#endif}static void wm8750_audio_out_cb(void *opaque, int free_b){    struct wm8750_s *s = (struct wm8750_s *) opaque;    wm8750_out_flush(s);    s->req_out = free_b;    s->data_req(s->opaque, free_b >> 2, s->req_in >> 2);}struct wm_rate_s {    int adc;    int adc_hz;    int dac;    int dac_hz;};static const struct wm_rate_s wm_rate_table[] = {    {  256, 48000,  256, 48000 },	/* SR: 00000 */    {  384, 48000,  384, 48000 },	/* SR: 00001 */    {  256, 48000, 1536,  8000 },	/* SR: 00010 */    {  384, 48000, 2304,  8000 },	/* SR: 00011 */    { 1536,  8000,  256, 48000 },	/* SR: 00100 */    { 2304,  8000,  384, 48000 },	/* SR: 00101 */    { 1536,  8000, 1536,  8000 },	/* SR: 00110 */    { 2304,  8000, 2304,  8000 },	/* SR: 00111 */    { 1024, 12000, 1024, 12000 },	/* SR: 01000 */    { 1526, 12000, 1536, 12000 },	/* SR: 01001 */    {  768, 16000,  768, 16000 },	/* SR: 01010 */    { 1152, 16000, 1152, 16000 },	/* SR: 01011 */    {  384, 32000,  384, 32000 },	/* SR: 01100 */    {  576, 32000,  576, 32000 },	/* SR: 01101 */    {  128, 96000,  128, 96000 },	/* SR: 01110 */    {  192, 96000,  192, 96000 },	/* SR: 01111 */    {  256, 44100,  256, 44100 },	/* SR: 10000 */    {  384, 44100,  384, 44100 },	/* SR: 10001 */    {  256, 44100, 1408,  8018 },	/* SR: 10010 */    {  384, 44100, 2112,  8018 },	/* SR: 10011 */    { 1408,  8018,  256, 44100 },	/* SR: 10100 */    { 2112,  8018,  384, 44100 },	/* SR: 10101 */    { 1408,  8018, 1408,  8018 },	/* SR: 10110 */    { 2112,  8018, 2112,  8018 },	/* SR: 10111 */    { 1024, 11025, 1024, 11025 },	/* SR: 11000 */    { 1536, 11025, 1536, 11025 },	/* SR: 11001 */    {  512, 22050,  512, 22050 },	/* SR: 11010 */    {  768, 22050,  768, 22050 },	/* SR: 11011 */    {  512, 24000,  512, 24000 },	/* SR: 11100 */    {  768, 24000,  768, 24000 },	/* SR: 11101 */    {  128, 88200,  128, 88200 },	/* SR: 11110 */    {  192, 88200,  128, 88200 },	/* SR: 11111 */};static void wm8750_set_format(struct wm8750_s *s){    int i;    audsettings_t in_fmt;    audsettings_t out_fmt;    audsettings_t monoout_fmt;    wm8750_out_flush(s);    if (s->in[0] && *s->in[0])        AUD_set_active_in(*s->in[0], 0);    if (s->out[0] && *s->out[0])        AUD_set_active_out(*s->out[0], 0);    for (i = 0; i < IN_PORT_N; i ++)        if (s->adc_voice[i]) {            AUD_close_in(&s->card, s->adc_voice[i]);            s->adc_voice[i] = 0;        }    for (i = 0; i < OUT_PORT_N; i ++)        if (s->dac_voice[i]) {            AUD_close_out(&s->card, s->dac_voice[i]);            s->dac_voice[i] = 0;        }    if (!s->enable)        return;    /* Setup input */    in_fmt.endianness = 0;    in_fmt.nchannels = 2;    in_fmt.freq = s->rate->adc_hz;    in_fmt.fmt = AUD_FMT_S16;    s->adc_voice[0] = AUD_open_in(&s->card, s->adc_voice[0],                    CODEC ".input1", s, wm8750_audio_in_cb, &in_fmt);    s->adc_voice[1] = AUD_open_in(&s->card, s->adc_voice[1],                    CODEC ".input2", s, wm8750_audio_in_cb, &in_fmt);    s->adc_voice[2] = AUD_open_in(&s->card, s->adc_voice[2],                    CODEC ".input3", s, wm8750_audio_in_cb, &in_fmt);    /* Setup output */    out_fmt.endianness = 0;    out_fmt.nchannels = 2;    out_fmt.freq = s->rate->dac_hz;    out_fmt.fmt = AUD_FMT_S16;    monoout_fmt.endianness = 0;    monoout_fmt.nchannels = 1;    monoout_fmt.freq = s->rate->dac_hz;    monoout_fmt.fmt = AUD_FMT_S16;    s->dac_voice[0] = AUD_open_out(&s->card, s->dac_voice[0],                    CODEC ".speaker", s, wm8750_audio_out_cb, &out_fmt);    s->dac_voice[1] = AUD_open_out(&s->card, s->dac_voice[1],                    CODEC ".headphone", s, wm8750_audio_out_cb, &out_fmt);    /* MONOMIX is also in stereo for simplicity */    s->dac_voice[2] = AUD_open_out(&s->card, s->dac_voice[2],                    CODEC ".monomix", s, wm8750_audio_out_cb, &out_fmt);    /* no sense emulating OUT3 which is a mix of other outputs */    /* We should connect the left and right channels to their     * respective inputs/outputs but we have completely no need     * for mixing or combining paths to different ports, so we     * connect both channels to where the left channel is routed.  */    if (s->in[0] && *s->in[0])        AUD_set_active_in(*s->in[0], 1);    if (s->out[0] && *s->out[0])        AUD_set_active_out(*s->out[0], 1);}static void inline wm8750_mask_update(struct wm8750_s *s){#define R_ONLY	0x0000ffff#define L_ONLY	0xffff0000#define BOTH	(R_ONLY | L_ONLY)#define NONE	(R_ONLY & L_ONLY)    s->inmask =            (s->inmute[0] ? R_ONLY : BOTH) &            (s->inmute[1] ? L_ONLY : BOTH) &            (s->mute ? NONE : BOTH);    s->outmask =            (s->outmute[0] ? R_ONLY : BOTH) &            (s->outmute[1] ? L_ONLY : BOTH) &            (s->mute ? NONE : BOTH);}void wm8750_reset(i2c_slave *i2c){    struct wm8750_s *s = (struct wm8750_s *) i2c;    s->enable = 0;    wm8750_set_format(s);    s->diff[0] = 0;    s->diff[1] = 0;    s->ds = 0;    s->alc = 0;    s->in[0] = &s->adc_voice[0];    s->invol[0] = 0x17;    s->invol[1] = 0x17;    s->invol[2] = 0xc3;    s->invol[3] = 0xc3;    s->out[0] = &s->dac_voice[0];    s->outvol[0] = 0xff;    s->outvol[1] = 0xff;    s->outvol[2] = 0x79;    s->outvol[3] = 0x79;    s->outvol[4] = 0x79;    s->outvol[5] = 0x79;    s->inmute[0] = 0;    s->inmute[1] = 0;    s->outmute[0] = 0;    s->outmute[1] = 0;    s->mute = 1;    s->path[0] = 0;    s->path[1] = 0;    s->path[2] = 0;    s->path[3] = 0;    s->mpath[0] = 0;    s->mpath[1] = 0;    s->format = 0x0a;    s->idx_in = sizeof(s->data_in);    s->req_in = 0;    s->idx_out = 0;    s->req_out = 0;    wm8750_mask_update(s);    s->i2c_len = 0;}static void wm8750_event(i2c_slave *i2c, enum i2c_event event){    struct wm8750_s *s = (struct wm8750_s *) i2c;    switch (event) {    case I2C_START_SEND:        s->i2c_len = 0;        break;    case I2C_FINISH:#ifdef VERBOSE        if (s->i2c_len < 2)            printf("%s: message too short (%i bytes)\n",                            __FUNCTION__, s->i2c_len);#endif        break;    default:        break;    }}#define WM8750_LINVOL	0x00#define WM8750_RINVOL	0x01#define WM8750_LOUT1V	0x02#define WM8750_ROUT1V	0x03#define WM8750_ADCDAC	0x05#define WM8750_IFACE	0x07#define WM8750_SRATE	0x08#define WM8750_LDAC	0x0a#define WM8750_RDAC	0x0b#define WM8750_BASS	0x0c#define WM8750_TREBLE	0x0d#define WM8750_RESET	0x0f#define WM8750_3D	0x10#define WM8750_ALC1	0x11#define WM8750_ALC2	0x12#define WM8750_ALC3	0x13#define WM8750_NGATE	0x14#define WM8750_LADC	0x15#define WM8750_RADC	0x16#define WM8750_ADCTL1	0x17#define WM8750_ADCTL2	0x18#define WM8750_PWR1	0x19#define WM8750_PWR2	0x1a#define WM8750_ADCTL3	0x1b#define WM8750_ADCIN	0x1f#define WM8750_LADCIN	0x20#define WM8750_RADCIN	0x21#define WM8750_LOUTM1	0x22#define WM8750_LOUTM2	0x23#define WM8750_ROUTM1	0x24#define WM8750_ROUTM2	0x25#define WM8750_MOUTM1	0x26#define WM8750_MOUTM2	0x27#define WM8750_LOUT2V	0x28#define WM8750_ROUT2V	0x29#define WM8750_MOUTV	0x2astatic int wm8750_tx(i2c_slave *i2c, uint8_t data){    struct wm8750_s *s = (struct wm8750_s *) i2c;    uint8_t cmd;    uint16_t value;    if (s->i2c_len >= 2) {        printf("%s: long message (%i bytes)\n", __FUNCTION__, s->i2c_len);#ifdef VERBOSE

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -