You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
264 lines
4.2 KiB
264 lines
4.2 KiB
#include <stdio.h>
|
|
#include <stdlib.h>
|
|
#include "stm32f4xx.h"
|
|
#include "cmd.h"
|
|
#include "gpio.h"
|
|
#include "iic.h"
|
|
#include "i2c.h"
|
|
|
|
#define WM8978_ADDR (0x1A)
|
|
#define WADDR (0x34)
|
|
|
|
static union {
|
|
iic_t iic;
|
|
i2c_t i2c;
|
|
void *raw;
|
|
} _i2c;
|
|
static int (*_write)(uint8_t reg, uint8_t val);
|
|
|
|
static uint16_t __regs[58]= {
|
|
0X0000,0X0000,0X0000,0X0000,0X0050,0X0000,0X0140,0X0000,
|
|
0X0000,0X0000,0X0000,0X00FF,0X00FF,0X0000,0X0100,0X00FF,
|
|
0X00FF,0X0000,0X012C,0X002C,0X002C,0X002C,0X002C,0X0000,
|
|
0X0032,0X0000,0X0000,0X0000,0X0000,0X0000,0X0000,0X0000,
|
|
0X0038,0X000B,0X0032,0X0000,0X0008,0X000C,0X0093,0X00E9,
|
|
0X0000,0X0000,0X0000,0X0000,0X0003,0X0010,0X0010,0X0100,
|
|
0X0100,0X0002,0X0001,0X0001,0X0039,0X0039,0X0039,0X0039,
|
|
0X0001,0X0001
|
|
};
|
|
|
|
uint16_t wm8978_read(uint8_t reg)
|
|
{
|
|
return __regs[reg];
|
|
}
|
|
|
|
static int _iic_write(uint8_t regr, uint8_t regv)
|
|
{
|
|
if (iic_start(_i2c.iic)) {
|
|
printf("start\r\n");
|
|
return -1;
|
|
}
|
|
|
|
if (iic_send_slave_address(_i2c.iic, WADDR)) {
|
|
printf("slave\r\n");
|
|
return -2;
|
|
}
|
|
if (iic_send_byte(_i2c.iic, regr)) {
|
|
printf("byte 1\r\n");
|
|
return -3;
|
|
}
|
|
if (iic_send_byte(_i2c.iic, regv)) {
|
|
printf("byte 2\r\n");
|
|
return -4;
|
|
}
|
|
iic_stop(_i2c.raw);
|
|
return 0;
|
|
}
|
|
|
|
static int _i2c_write(uint8_t regr, uint8_t regv)
|
|
{
|
|
if (i2c_start(_i2c.i2c)) {
|
|
printf("start\r\n");
|
|
return -1;
|
|
}
|
|
|
|
i2c_send_byte(_i2c.i2c, WADDR);
|
|
if (i2c_wait_ack(_i2c.i2c)) { /* NACK */
|
|
printf("address not response\r\n");
|
|
return -2;
|
|
}
|
|
|
|
i2c_send_byte(_i2c.i2c, regr);
|
|
i2c_wait_ack(_i2c.i2c);
|
|
|
|
i2c_send_byte(_i2c.i2c, regv);
|
|
i2c_wait_ack(_i2c.i2c);
|
|
|
|
i2c_stop(_i2c.i2c);
|
|
|
|
return 0;
|
|
}
|
|
|
|
int wm8978_write(uint8_t reg, uint16_t val)
|
|
{
|
|
uint8_t regr, regv;
|
|
|
|
if (_write) {
|
|
regr = ((reg << 1) & 0xfe) | ((val >> 8) & 0x01);
|
|
regv = val & 0xff;
|
|
|
|
if (!_write(regr, regv)) {
|
|
__regs[reg] = val;
|
|
return 0;
|
|
}
|
|
}
|
|
return -1;
|
|
}
|
|
|
|
static void aux_gain(uint8_t gain)
|
|
{
|
|
uint16_t regval;
|
|
|
|
gain &=0x07;
|
|
|
|
regval = wm8978_read(47);
|
|
regval &= ~(7<<0);
|
|
wm8978_write(47,regval|gain<<0);
|
|
|
|
regval = wm8978_read(48);
|
|
regval &=~(7<<0);
|
|
|
|
wm8978_write(48, regval|gain<<0);
|
|
}
|
|
|
|
static void linein_gain(uint8_t gain)
|
|
{
|
|
uint16_t regval;
|
|
|
|
gain &= 0x07;
|
|
regval = wm8978_read(47);
|
|
|
|
regval &=~(7<<4);
|
|
wm8978_write(47,regval|gain<<4);
|
|
|
|
regval = wm8978_read(48);
|
|
regval&=~(7<<4);
|
|
wm8978_write(48,regval|gain<<4);
|
|
}
|
|
|
|
static void input_cfg(uint8_t micen,uint8_t lineinen,uint8_t auxen)
|
|
{
|
|
uint16_t regval;
|
|
|
|
regval = wm8978_read(2);
|
|
if(micen)
|
|
regval|=3<<2;
|
|
else
|
|
regval&=~(3<<2);
|
|
|
|
wm8978_write(2,regval);
|
|
regval = wm8978_read(44);
|
|
if(micen)
|
|
regval|=3<<4|3<<0;
|
|
else
|
|
regval&=~(3<<4|3<<0);
|
|
|
|
wm8978_write(44,regval);
|
|
|
|
if(lineinen)
|
|
linein_gain(5);
|
|
else
|
|
linein_gain(0);
|
|
|
|
if (auxen)
|
|
aux_gain(7);
|
|
else
|
|
aux_gain(0);
|
|
}
|
|
|
|
static void enable_ad_da(uint8_t dac, uint8_t adc)
|
|
{
|
|
uint16_t regv;
|
|
|
|
regv = wm8978_read(3);
|
|
if (dac) {
|
|
regv |= 3;
|
|
} else {
|
|
regv &= ~3;
|
|
}
|
|
wm8978_write(3, regv);
|
|
|
|
regv = wm8978_read(2);
|
|
if (adc) {
|
|
regv |= 3;
|
|
} else {
|
|
regv &= ~3;
|
|
}
|
|
wm8978_write(2, regv);
|
|
}
|
|
|
|
static void output_cfg(uint8_t dacen,uint8_t bpsen)
|
|
{
|
|
uint16_t regval=0;
|
|
|
|
if(dacen)
|
|
regval|=1<<0;
|
|
|
|
if(bpsen) {
|
|
regval|=1<<1;
|
|
regval|=5<<2;
|
|
}
|
|
|
|
wm8978_write(50, regval);
|
|
wm8978_write(51, regval);
|
|
}
|
|
|
|
static void hp_vol_set(uint8_t voll,uint8_t volr)
|
|
{
|
|
voll&=0x3F;
|
|
volr&=0x3F;
|
|
|
|
if(voll==0)voll|=1<<6;
|
|
if(volr==0)volr|=1<<6;
|
|
|
|
wm8978_write(52,voll);
|
|
wm8978_write(53,volr|(1<<8));
|
|
}
|
|
|
|
static void spk_vol_set(uint8_t volx)
|
|
{
|
|
volx &= 0x3F;
|
|
if(volx==0)volx|=1<<6;
|
|
|
|
wm8978_write(54, volx);
|
|
wm8978_write(55, volx|(1<<8));
|
|
}
|
|
|
|
static int do_init()
|
|
{
|
|
if (wm8978_write(0, 0)) {
|
|
return -1;
|
|
}
|
|
wm8978_write(1, 0x1b);
|
|
wm8978_write(2, 0x1b0);
|
|
wm8978_write(3, 0x6c);
|
|
wm8978_write(6, 0);
|
|
wm8978_write(43, 1 << 4);
|
|
wm8978_write(47, 1 << 8);
|
|
wm8978_write(48, 1 << 8);
|
|
wm8978_write(49, 1 << 1);
|
|
wm8978_write(10, 1 << 3);
|
|
wm8978_write(14, 1 << 3);
|
|
|
|
/* i2s cfg */
|
|
wm8978_write(4, (0x2 << 3) | (0x00 << 5));
|
|
|
|
/* ad da */
|
|
enable_ad_da(1, 0);
|
|
|
|
input_cfg(0, 0, 0);
|
|
|
|
output_cfg(1, 0);
|
|
|
|
hp_vol_set(63, 63);
|
|
spk_vol_set(63);
|
|
|
|
return 0;
|
|
}
|
|
|
|
int wm8978_init_with_iic(iic_t i2c)
|
|
{
|
|
_i2c.iic = i2c;
|
|
_write = _iic_write;
|
|
|
|
return do_init();
|
|
}
|
|
|
|
int wm8978_init_with_i2c(i2c_t i2c)
|
|
{
|
|
_i2c.i2c = i2c;
|
|
_write = _i2c_write;
|
|
|
|
return do_init();
|
|
}
|
|
|
|
|