add respeaker 4mic audio card driver
This commit is contained in:
parent
0785cfd9f7
commit
5b49bfb4ec
21 changed files with 4365 additions and 22 deletions
11
Makefile
11
Makefile
|
@ -1,4 +1,10 @@
|
|||
obj-m := wm8960.o
|
||||
snd-soc-wm8960-objs := wm8960.o
|
||||
snd-soc-ac108-objs := ac108.o
|
||||
|
||||
|
||||
obj-m += snd-soc-wm8960.o
|
||||
obj-m += snd-soc-ac108.o
|
||||
|
||||
|
||||
all:
|
||||
make -C /lib/modules/$(shell uname -r)/build M=$(PWD) modules
|
||||
|
@ -7,5 +13,6 @@ clean:
|
|||
make -C /lib/modules/$(shell uname -r)/build M=$(PWD) clean
|
||||
|
||||
install:
|
||||
sudo cp wm8960.ko /lib/modules/$(shell uname -r)
|
||||
sudo cp snd-soc-ac108.ko /lib/modules/$(shell uname -r)/sound/soc/codecs/
|
||||
sudo cp snd-soc-wm8960.ko /lib/modules/$(shell uname -r)/sound/soc/codecs/
|
||||
sudo depmod -a
|
||||
|
|
774
ac108.h
Executable file
774
ac108.h
Executable file
|
@ -0,0 +1,774 @@
|
|||
/*
|
||||
* ac108.h -- ac108 ALSA Soc Audio driver
|
||||
*
|
||||
* Author: panjunwen
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License version 2 as
|
||||
* published by the Free Software Foundation.
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef _AC108_H
|
||||
#define _AC108_H
|
||||
|
||||
|
||||
/*** AC108 Codec Register Define***/
|
||||
|
||||
//Chip Reset
|
||||
#define CHIP_RST 0x00
|
||||
#define CHIP_RST_VAL 0x12
|
||||
|
||||
//Power Control
|
||||
#define PWR_CTRL1 0x01
|
||||
#define PWR_CTRL2 0x02
|
||||
#define PWR_CTRL3 0x03
|
||||
#define PWR_CTRL4 0x04
|
||||
#define PWR_CTRL5 0x05
|
||||
#define PWR_CTRL6 0x06
|
||||
#define PWR_CTRL7 0x07
|
||||
#define PWR_CTRL8 0x08
|
||||
#define PWR_CTRL9 0x09
|
||||
|
||||
//PLL Configure Control
|
||||
#define PLL_CTRL1 0x10
|
||||
#define PLL_CTRL2 0x11
|
||||
#define PLL_CTRL3 0x12
|
||||
#define PLL_CTRL4 0x13
|
||||
#define PLL_CTRL5 0x14
|
||||
#define PLL_CTRL6 0x16
|
||||
#define PLL_CTRL7 0x17
|
||||
#define PLL_LOCK_CTRL 0x18
|
||||
|
||||
//System Clock Control
|
||||
#define SYSCLK_CTRL 0x20
|
||||
#define MOD_CLK_EN 0x21
|
||||
#define MOD_RST_CTRL 0x22
|
||||
#define DSM_CLK_CTRL 0x25
|
||||
|
||||
//I2S Common Control
|
||||
#define I2S_CTRL 0x30
|
||||
#define I2S_BCLK_CTRL 0x31
|
||||
#define I2S_LRCK_CTRL1 0x32
|
||||
#define I2S_LRCK_CTRL2 0x33
|
||||
#define I2S_FMT_CTRL1 0x34
|
||||
#define I2S_FMT_CTRL2 0x35
|
||||
#define I2S_FMT_CTRL3 0x36
|
||||
|
||||
//I2S TX1 Control
|
||||
#define I2S_TX1_CTRL1 0x38
|
||||
#define I2S_TX1_CTRL2 0x39
|
||||
#define I2S_TX1_CTRL3 0x3A
|
||||
#define I2S_TX1_CHMP_CTRL1 0x3C
|
||||
#define I2S_TX1_CHMP_CTRL2 0x3D
|
||||
#define I2S_TX1_CHMP_CTRL3 0x3E
|
||||
#define I2S_TX1_CHMP_CTRL4 0x3F
|
||||
|
||||
//I2S TX2 Control
|
||||
#define I2S_TX2_CTRL1 0x40
|
||||
#define I2S_TX2_CTRL2 0x41
|
||||
#define I2S_TX2_CTRL3 0x42
|
||||
#define I2S_TX2_CHMP_CTRL1 0x44
|
||||
#define I2S_TX2_CHMP_CTRL2 0x45
|
||||
#define I2S_TX2_CHMP_CTRL3 0x46
|
||||
#define I2S_TX2_CHMP_CTRL4 0x47
|
||||
|
||||
//I2S RX1 Control
|
||||
#define I2S_RX1_CTRL1 0x50
|
||||
#define I2S_RX1_CHMP_CTRL1 0x54
|
||||
#define I2S_RX1_CHMP_CTRL2 0x55
|
||||
#define I2S_RX1_CHMP_CTRL3 0x56
|
||||
#define I2S_RX1_CHMP_CTRL4 0x57
|
||||
|
||||
//I2S Loopback Debug
|
||||
#define I2S_LPB_DEBUG 0x58
|
||||
|
||||
//ADC Common Control
|
||||
#define ADC_SPRC 0x60
|
||||
#define ADC_DIG_EN 0x61
|
||||
#define DMIC_EN 0x62
|
||||
#define ADC_DSR 0x63
|
||||
#define ADC_FIR 0x64
|
||||
#define ADC_DDT_CTRL 0x65
|
||||
|
||||
//HPF Control
|
||||
#define HPF_EN 0x66
|
||||
#define HPF_COEF_REGH1 0x67
|
||||
#define HPF_COEF_REGH2 0x68
|
||||
#define HPF_COEF_REGL1 0x69
|
||||
#define HPF_COEF_REGL2 0x6A
|
||||
#define HPF_GAIN_REGH1 0x6B
|
||||
#define HPF_GAIN_REGH2 0x6C
|
||||
#define HPF_GAIN_REGL1 0x6D
|
||||
#define HPF_GAIN_REGL2 0x6E
|
||||
|
||||
//ADC Digital Channel Volume Control
|
||||
#define ADC1_DVOL_CTRL 0x70
|
||||
#define ADC2_DVOL_CTRL 0x71
|
||||
#define ADC3_DVOL_CTRL 0x72
|
||||
#define ADC4_DVOL_CTRL 0x73
|
||||
|
||||
//ADC Digital Mixer Source and Gain Control
|
||||
#define ADC1_DMIX_SRC 0x76
|
||||
#define ADC2_DMIX_SRC 0x77
|
||||
#define ADC3_DMIX_SRC 0x78
|
||||
#define ADC4_DMIX_SRC 0x79
|
||||
|
||||
//ADC Digital Debug Control
|
||||
#define ADC_DIG_DEBUG 0x7F
|
||||
|
||||
//I2S Pad Drive Control
|
||||
#define I2S_DAT_PADDRV_CTRL 0x80
|
||||
#define I2S_CLK_PADDRV_CTRL 0x81
|
||||
|
||||
//Analog PGA Control
|
||||
#define ANA_PGA1_CTRL 0x90
|
||||
#define ANA_PGA2_CTRL 0x91
|
||||
#define ANA_PGA3_CTRL 0x92
|
||||
#define ANA_PGA4_CTRL 0x93
|
||||
|
||||
//MIC Offset Control
|
||||
#define MIC_OFFSET_CTRL1 0x96
|
||||
#define MIC_OFFSET_CTRL2 0x97
|
||||
#define MIC1_OFFSET_STATU1 0x98
|
||||
#define MIC1_OFFSET_STATU2 0x99
|
||||
#define MIC2_OFFSET_STATU1 0x9A
|
||||
#define MIC2_OFFSET_STATU2 0x9B
|
||||
#define MIC3_OFFSET_STATU1 0x9C
|
||||
#define MIC3_OFFSET_STATU2 0x9D
|
||||
#define MIC4_OFFSET_STATU1 0x9E
|
||||
#define MIC4_OFFSET_STATU2 0x9F
|
||||
|
||||
//ADC1 Analog Control
|
||||
#define ANA_ADC1_CTRL1 0xA0
|
||||
#define ANA_ADC1_CTRL2 0xA1
|
||||
#define ANA_ADC1_CTRL3 0xA2
|
||||
#define ANA_ADC1_CTRL4 0xA3
|
||||
#define ANA_ADC1_CTRL5 0xA4
|
||||
#define ANA_ADC1_CTRL6 0xA5
|
||||
#define ANA_ADC1_CTRL7 0xA6
|
||||
|
||||
//ADC2 Analog Control
|
||||
#define ANA_ADC2_CTRL1 0xA7
|
||||
#define ANA_ADC2_CTRL2 0xA8
|
||||
#define ANA_ADC2_CTRL3 0xA9
|
||||
#define ANA_ADC2_CTRL4 0xAA
|
||||
#define ANA_ADC2_CTRL5 0xAB
|
||||
#define ANA_ADC2_CTRL6 0xAC
|
||||
#define ANA_ADC2_CTRL7 0xAD
|
||||
|
||||
//ADC3 Analog Control
|
||||
#define ANA_ADC3_CTRL1 0xAE
|
||||
#define ANA_ADC3_CTRL2 0xAF
|
||||
#define ANA_ADC3_CTRL3 0xB0
|
||||
#define ANA_ADC3_CTRL4 0xB1
|
||||
#define ANA_ADC3_CTRL5 0xB2
|
||||
#define ANA_ADC3_CTRL6 0xB3
|
||||
#define ANA_ADC3_CTRL7 0xB4
|
||||
|
||||
//ADC4 Analog Control
|
||||
#define ANA_ADC4_CTRL1 0xB5
|
||||
#define ANA_ADC4_CTRL2 0xB6
|
||||
#define ANA_ADC4_CTRL3 0xB7
|
||||
#define ANA_ADC4_CTRL4 0xB8
|
||||
#define ANA_ADC4_CTRL5 0xB9
|
||||
#define ANA_ADC4_CTRL6 0xBA
|
||||
#define ANA_ADC4_CTRL7 0xBB
|
||||
|
||||
//GPIO Configure
|
||||
#define GPIO_CFG1 0xC0
|
||||
#define GPIO_CFG2 0xC1
|
||||
#define GPIO_DAT 0xC2
|
||||
#define GPIO_DRV 0xC3
|
||||
#define GPIO_PULL 0xC4
|
||||
#define GPIO_INT_CFG 0xC5
|
||||
#define GPIO_INT_EN 0xC6
|
||||
#define GPIO_INT_STATUS 0xC7
|
||||
|
||||
//Misc
|
||||
#define BGTC_DAT 0xD1
|
||||
#define BGVC_DAT 0xD2
|
||||
#define PRNG_CLK_CTRL 0xDF
|
||||
|
||||
|
||||
|
||||
/*** AC108 Codec Register Bit Define***/
|
||||
|
||||
/*PWR_CTRL1*/
|
||||
#define CP12_CTRL 4
|
||||
#define CP12_SENSE_SELECT 3
|
||||
|
||||
/*PWR_CTRL2*/
|
||||
#define CP12_SENSE_FILT 6
|
||||
#define CP12_COMP_FF_EN 3
|
||||
#define CP12_FORCE_ENABLE 2
|
||||
#define CP12_FORCE_RSTB 1
|
||||
|
||||
/*PWR_CTRL3*/
|
||||
#define LDO33DIG_CTRL 0
|
||||
|
||||
/*PWR_CTRL6*/
|
||||
#define LDO33ANA_2XHDRM 2
|
||||
#define LDO33ANA_ENABLE 0
|
||||
|
||||
/*PWR_CTRL7*/
|
||||
#define VREF_SEL 3
|
||||
#define VREF_FASTSTART_ENABLE 1
|
||||
#define VREF_ENABLE 0
|
||||
|
||||
/*PWR_CTRL9*/
|
||||
#define VREFP_FASTSTART_ENABLE 7
|
||||
#define VREFP_RESCTRL 5
|
||||
#define VREFP_LPMODE 4
|
||||
#define IGEN_TRIM 1
|
||||
#define VREFP_ENABLE 0
|
||||
|
||||
|
||||
/*PLL_CTRL1*/
|
||||
#define PLL_IBIAS 4
|
||||
#define PLL_NDET 3
|
||||
#define PLL_LOCKED_STATUS 2
|
||||
#define PLL_COM_EN 1
|
||||
#define PLL_EN 0
|
||||
|
||||
/*PLL_CTRL2*/
|
||||
#define PLL_PREDIV2 5
|
||||
#define PLL_PREDIV1 0
|
||||
|
||||
/*PLL_CTRL3*/
|
||||
#define PLL_LOOPDIV_MSB 0
|
||||
|
||||
/*PLL_CTRL4*/
|
||||
#define PLL_LOOPDIV_LSB 0
|
||||
|
||||
/*PLL_CTRL5*/
|
||||
#define PLL_POSTDIV2 5
|
||||
#define PLL_POSTDIV1 0
|
||||
|
||||
/*PLL_CTRL6*/
|
||||
#define PLL_LDO 6
|
||||
#define PLL_CP 0
|
||||
|
||||
/*PLL_CTRL7*/
|
||||
#define PLL_CAP 6
|
||||
#define PLL_RES 4
|
||||
#define PLL_TEST_EN 0
|
||||
|
||||
/*PLL_LOCK_CTRL*/
|
||||
#define LOCK_LEVEL1 2
|
||||
#define LOCK_LEVEL2 1
|
||||
#define PLL_LOCK_EN 0
|
||||
|
||||
|
||||
/*SYSCLK_CTRL*/
|
||||
#define PLLCLK_EN 7
|
||||
#define PLLCLK_SRC 4
|
||||
#define SYSCLK_SRC 3
|
||||
#define SYSCLK_EN 0
|
||||
|
||||
/*MOD_CLK_EN & MOD_RST_CTRL*/
|
||||
#define I2S 7
|
||||
#define ADC_DIGITAL 4
|
||||
#define MIC_OFFSET_CALIBRATION 1
|
||||
#define ADC_ANALOG 0
|
||||
|
||||
/*DSM_CLK_CTRL*/
|
||||
#define MIC_OFFSET_DIV 4
|
||||
#define DSM_CLK_SEL 0
|
||||
|
||||
|
||||
/*I2S_CTRL*/
|
||||
#define BCLK_IOEN 7
|
||||
#define LRCK_IOEN 6
|
||||
#define SDO2_EN 5
|
||||
#define SDO1_EN 4
|
||||
#define TXEN 2
|
||||
#define RXEN 1
|
||||
#define GEN 0
|
||||
|
||||
/*I2S_BCLK_CTRL*/
|
||||
#define EDGE_TRANSFER 5
|
||||
#define BCLK_POLARITY 4
|
||||
#define BCLKDIV 0
|
||||
|
||||
/*I2S_LRCK_CTRL1*/
|
||||
#define LRCK_POLARITY 4
|
||||
#define LRCK_PERIODH 0
|
||||
|
||||
/*I2S_LRCK_CTRL2*/
|
||||
#define LRCK_PERIODL 0
|
||||
|
||||
/*I2S_FMT_CTRL1*/
|
||||
#define ENCD_SEL 6
|
||||
#define MODE_SEL 4
|
||||
#define TX2_OFFSET 3
|
||||
#define TX1_OFFSET 2
|
||||
#define TX_SLOT_HIZ 1
|
||||
#define TX_STATE 0
|
||||
|
||||
/*I2S_FMT_CTRL2*/
|
||||
#define SLOT_WIDTH_SEL 4
|
||||
#define SAMPLE_RESOLUTION 0
|
||||
|
||||
/*I2S_FMT_CTRL3*/
|
||||
#define TX_MLS 7
|
||||
#define SEXT 5
|
||||
#define OUT2_MUTE 4
|
||||
#define OUT1_MUTE 3
|
||||
#define LRCK_WIDTH 2
|
||||
#define TX_PDM 0
|
||||
|
||||
|
||||
/*I2S_TX1_CTRL1*/
|
||||
#define TX1_CHSEL 0
|
||||
|
||||
/*I2S_TX1_CTRL2*/
|
||||
#define TX1_CH8_EN 7
|
||||
#define TX1_CH7_EN 6
|
||||
#define TX1_CH6_EN 5
|
||||
#define TX1_CH5_EN 4
|
||||
#define TX1_CH4_EN 3
|
||||
#define TX1_CH3_EN 2
|
||||
#define TX1_CH2_EN 1
|
||||
#define TX1_CH1_EN 0
|
||||
|
||||
/*I2S_TX1_CTRL3*/
|
||||
#define TX1_CH16_EN 7
|
||||
#define TX1_CH15_EN 6
|
||||
#define TX1_CH14_EN 5
|
||||
#define TX1_CH13_EN 4
|
||||
#define TX1_CH12_EN 3
|
||||
#define TX1_CH11_EN 2
|
||||
#define TX1_CH10_EN 1
|
||||
#define TX1_CH9_EN 0
|
||||
|
||||
/*I2S_TX1_CHMP_CTRL1*/
|
||||
#define TX1_CH4_MAP 6
|
||||
#define TX1_CH3_MAP 4
|
||||
#define TX1_CH2_MAP 2
|
||||
#define TX1_CH1_MAP 0
|
||||
|
||||
/*I2S_TX1_CHMP_CTRL2*/
|
||||
#define TX1_CH8_MAP 6
|
||||
#define TX1_CH7_MAP 4
|
||||
#define TX1_CH6_MAP 2
|
||||
#define TX1_CH5_MAP 0
|
||||
|
||||
/*I2S_TX1_CHMP_CTRL3*/
|
||||
#define TX1_CH12_MAP 6
|
||||
#define TX1_CH11_MAP 4
|
||||
#define TX1_CH10_MAP 2
|
||||
#define TX1_CH9_MAP 0
|
||||
|
||||
/*I2S_TX1_CHMP_CTRL4*/
|
||||
#define TX1_CH16_MAP 6
|
||||
#define TX1_CH15_MAP 4
|
||||
#define TX1_CH14_MAP 2
|
||||
#define TX1_CH13_MAP 0
|
||||
|
||||
|
||||
/*I2S_TX2_CTRL1*/
|
||||
#define TX2_CHSEL 0
|
||||
|
||||
/*I2S_TX2_CHMP_CTRL1*/
|
||||
#define TX2_CH4_MAP 6
|
||||
#define TX2_CH3_MAP 4
|
||||
#define TX2_CH2_MAP 2
|
||||
#define TX2_CH1_MAP 0
|
||||
|
||||
/*I2S_TX2_CHMP_CTRL2*/
|
||||
#define TX2_CH8_MAP 6
|
||||
#define TX2_CH7_MAP 4
|
||||
#define TX2_CH6_MAP 2
|
||||
#define TX2_CH5_MAP 0
|
||||
|
||||
/*I2S_TX2_CHMP_CTRL3*/
|
||||
#define TX2_CH12_MAP 6
|
||||
#define TX2_CH11_MAP 4
|
||||
#define TX2_CH10_MAP 2
|
||||
#define TX2_CH9_MAP 0
|
||||
|
||||
/*I2S_TX2_CHMP_CTRL4*/
|
||||
#define TX2_CH16_MAP 6
|
||||
#define TX2_CH15_MAP 4
|
||||
#define TX2_CH14_MAP 2
|
||||
#define TX2_CH13_MAP 0
|
||||
|
||||
|
||||
/*I2S_RX1_CTRL1*/
|
||||
#define RX1_CHSEL 0
|
||||
|
||||
/*I2S_RX1_CHMP_CTRL1*/
|
||||
#define RX1_CH4_MAP 6
|
||||
#define RX1_CH3_MAP 4
|
||||
#define RX1_CH2_MAP 2
|
||||
#define RX1_CH1_MAP 0
|
||||
|
||||
/*I2S_RX1_CHMP_CTRL2*/
|
||||
#define RX1_CH8_MAP 6
|
||||
#define RX1_CH7_MAP 4
|
||||
#define RX1_CH6_MAP 2
|
||||
#define RX1_CH5_MAP 0
|
||||
|
||||
/*I2S_RX1_CHMP_CTRL3*/
|
||||
#define RX1_CH12_MAP 6
|
||||
#define RX1_CH11_MAP 4
|
||||
#define RX1_CH10_MAP 2
|
||||
#define RX1_CH9_MAP 0
|
||||
|
||||
/*I2S_RX1_CHMP_CTRL4*/
|
||||
#define RX1_CH16_MAP 6
|
||||
#define RX1_CH15_MAP 4
|
||||
#define RX1_CH14_MAP 2
|
||||
#define RX1_CH13_MAP 0
|
||||
|
||||
|
||||
/*I2S_LPB_DEBUG*/
|
||||
#define I2S_LPB_DEBUG_EN 0
|
||||
|
||||
|
||||
/*ADC_SPRC*/
|
||||
#define ADC_FS_I2S1 0
|
||||
|
||||
/*ADC_DIG_EN*/
|
||||
#define DG_EN 4
|
||||
#define ENAD4 3
|
||||
#define ENAD3 2
|
||||
#define ENAD2 1
|
||||
#define ENAD1 0
|
||||
|
||||
/*DMIC_EN*/
|
||||
#define DMIC2_EN 1
|
||||
#define DMIC1_EN 0
|
||||
|
||||
/*ADC_DSR*/
|
||||
#define DIG_ADC4_SRS 6
|
||||
#define DIG_ADC3_SRS 4
|
||||
#define DIG_ADC2_SRS 2
|
||||
#define DIG_ADC1_SRS 0
|
||||
|
||||
/*ADC_DDT_CTRL*/
|
||||
#define ADOUT_DLY_EN 2
|
||||
#define ADOUT_DTS 0
|
||||
|
||||
|
||||
/*HPF_EN*/
|
||||
#define DIG_ADC4_HPF_EN 3
|
||||
#define DIG_ADC3_HPF_EN 2
|
||||
#define DIG_ADC2_HPF_EN 1
|
||||
#define DIG_ADC1_HPF_EN 0
|
||||
|
||||
|
||||
/*ADC1_DMIX_SRC*/
|
||||
#define ADC1_ADC4_DMXL_GC 7
|
||||
#define ADC1_ADC3_DMXL_GC 6
|
||||
#define ADC1_ADC2_DMXL_GC 5
|
||||
#define ADC1_ADC1_DMXL_GC 4
|
||||
#define ADC1_ADC4_DMXL_SRC 3
|
||||
#define ADC1_ADC3_DMXL_SRC 2
|
||||
#define ADC1_ADC2_DMXL_SRC 1
|
||||
#define ADC1_ADC1_DMXL_SRC 0
|
||||
|
||||
/*ADC2_DMIX_SRC*/
|
||||
#define ADC2_ADC4_DMXL_GC 7
|
||||
#define ADC2_ADC3_DMXL_GC 6
|
||||
#define ADC2_ADC2_DMXL_GC 5
|
||||
#define ADC2_ADC1_DMXL_GC 4
|
||||
#define ADC2_ADC4_DMXL_SRC 3
|
||||
#define ADC2_ADC3_DMXL_SRC 2
|
||||
#define ADC2_ADC2_DMXL_SRC 1
|
||||
#define ADC2_ADC1_DMXL_SRC 0
|
||||
|
||||
/*ADC3_DMIX_SRC*/
|
||||
#define ADC3_ADC4_DMXL_GC 7
|
||||
#define ADC3_ADC3_DMXL_GC 6
|
||||
#define ADC3_ADC2_DMXL_GC 5
|
||||
#define ADC3_ADC1_DMXL_GC 4
|
||||
#define ADC3_ADC4_DMXL_SRC 3
|
||||
#define ADC3_ADC3_DMXL_SRC 2
|
||||
#define ADC3_ADC2_DMXL_SRC 1
|
||||
#define ADC3_ADC1_DMXL_SRC 0
|
||||
|
||||
/*ADC4_DMIX_SRC*/
|
||||
#define ADC4_ADC4_DMXL_GC 7
|
||||
#define ADC4_ADC3_DMXL_GC 6
|
||||
#define ADC4_ADC2_DMXL_GC 5
|
||||
#define ADC4_ADC1_DMXL_GC 4
|
||||
#define ADC4_ADC4_DMXL_SRC 3
|
||||
#define ADC4_ADC3_DMXL_SRC 2
|
||||
#define ADC4_ADC2_DMXL_SRC 1
|
||||
#define ADC4_ADC1_DMXL_SRC 0
|
||||
|
||||
|
||||
/*ADC_DIG_DEBUG*/
|
||||
#define ADC_PTN_SEL 0
|
||||
|
||||
|
||||
/*I2S_DAT_PADDRV_CTRL*/
|
||||
#define TX2_DAT_DRV 4
|
||||
#define TX1_DAT_DRV 0
|
||||
|
||||
/*I2S_CLK_PADDRV_CTRL*/
|
||||
#define LRCK_DRV 4
|
||||
#define BCLK_DRV 0
|
||||
|
||||
|
||||
/*ANA_PGA1_CTRL*/
|
||||
#define ADC1_ANALOG_PGA 1
|
||||
#define ADC1_ANALOG_PGA_STEP 0
|
||||
|
||||
/*ANA_PGA2_CTRL*/
|
||||
#define ADC2_ANALOG_PGA 1
|
||||
#define ADC2_ANALOG_PGA_STEP 0
|
||||
|
||||
/*ANA_PGA3_CTRL*/
|
||||
#define ADC3_ANALOG_PGA 1
|
||||
#define ADC3_ANALOG_PGA_STEP 0
|
||||
|
||||
/*ANA_PGA4_CTRL*/
|
||||
#define ADC4_ANALOG_PGA 1
|
||||
#define ADC4_ANALOG_PGA_STEP 0
|
||||
|
||||
|
||||
/*MIC_OFFSET_CTRL1*/
|
||||
#define MIC_OFFSET_CAL_EN4 3
|
||||
#define MIC_OFFSET_CAL_EN3 2
|
||||
#define MIC_OFFSET_CAL_EN2 1
|
||||
#define MIC_OFFSET_CAL_EN1 0
|
||||
|
||||
/*MIC_OFFSET_CTRL2*/
|
||||
#define MIC_OFFSET_CAL_GAIN 3
|
||||
#define MIC_OFFSET_CAL_CHANNEL 1
|
||||
#define MIC_OFFSET_CAL_EN_ONCE 0
|
||||
|
||||
/*MIC1_OFFSET_STATU1*/
|
||||
#define MIC1_OFFSET_CAL_DONE 7
|
||||
#define MIC1_OFFSET_CAL_RUN_STA 6
|
||||
#define MIC1_OFFSET_MSB 0
|
||||
|
||||
/*MIC1_OFFSET_STATU2*/
|
||||
#define MIC1_OFFSET_LSB 0
|
||||
|
||||
/*MIC2_OFFSET_STATU1*/
|
||||
#define MIC2_OFFSET_CAL_DONE 7
|
||||
#define MIC2_OFFSET_CAL_RUN_STA 6
|
||||
#define MIC2_OFFSET_MSB 0
|
||||
|
||||
/*MIC2_OFFSET_STATU2*/
|
||||
#define MIC2_OFFSET_LSB 0
|
||||
|
||||
/*MIC3_OFFSET_STATU1*/
|
||||
#define MIC3_OFFSET_CAL_DONE 7
|
||||
#define MIC3_OFFSET_CAL_RUN_STA 6
|
||||
#define MIC3_OFFSET_MSB 0
|
||||
|
||||
/*MIC3_OFFSET_STATU2*/
|
||||
#define MIC3_OFFSET_LSB 0
|
||||
|
||||
/*MIC4_OFFSET_STATU1*/
|
||||
#define MIC4_OFFSET_CAL_DONE 7
|
||||
#define MIC4_OFFSET_CAL_RUN_STA 6
|
||||
#define MIC4_OFFSET_MSB 0
|
||||
|
||||
/*MIC4_OFFSET_STATU2*/
|
||||
#define MIC4_OFFSET_LSB 0
|
||||
|
||||
|
||||
/*ANA_ADC1_CTRL1*/
|
||||
#define ADC1_PGA_BYPASS 7
|
||||
#define ADC1_PGA_BYP_RCM 6
|
||||
#define ADC1_PGA_CTRL_RCM 4
|
||||
#define ADC1_PGA_MUTE 3
|
||||
#define ADC1_DSM_ENABLE 2
|
||||
#define ADC1_PGA_ENABLE 1
|
||||
#define ADC1_MICBIAS_EN 0
|
||||
|
||||
/*ANA_ADC1_CTRL3*/
|
||||
#define ADC1_ANA_CAL_EN 5
|
||||
#define ADC1_SEL_OUT_EDGE 3
|
||||
#define ADC1_DSM_DISABLE 2
|
||||
#define ADC1_VREFP_DISABLE 1
|
||||
#define ADC1_AAF_DISABLE 0
|
||||
|
||||
/*ANA_ADC1_CTRL6*/
|
||||
#define PGA_CTRL_TC 6
|
||||
#define PGA_CTRL_RC 4
|
||||
#define PGA_CTRL_I_LIN 2
|
||||
#define PGA_CTRL_I_IN 0
|
||||
|
||||
/*ANA_ADC1_CTRL7*/
|
||||
#define PGA_CTRL_HI_Z 7
|
||||
#define PGA_CTRL_SHORT_RF 6
|
||||
#define PGA_CTRL_VCM_VG 4
|
||||
#define PGA_CTRL_VCM_IN 0
|
||||
|
||||
|
||||
/*ANA_ADC2_CTRL1*/
|
||||
#define ADC2_PGA_BYPASS 7
|
||||
#define ADC2_PGA_BYP_RCM 6
|
||||
#define ADC2_PGA_CTRL_RCM 4
|
||||
#define ADC2_PGA_MUTE 3
|
||||
#define ADC2_DSM_ENABLE 2
|
||||
#define ADC2_PGA_ENABLE 1
|
||||
#define ADC2_MICBIAS_EN 0
|
||||
|
||||
/*ANA_ADC2_CTRL3*/
|
||||
#define ADC2_ANA_CAL_EN 5
|
||||
#define ADC2_SEL_OUT_EDGE 3
|
||||
#define ADC2_DSM_DISABLE 2
|
||||
#define ADC2_VREFP_DISABLE 1
|
||||
#define ADC2_AAF_DISABLE 0
|
||||
|
||||
/*ANA_ADC2_CTRL6*/
|
||||
#define PGA_CTRL_IBOOST 7
|
||||
#define PGA_CTRL_IQCTRL 6
|
||||
#define PGA_CTRL_OABIAS 4
|
||||
#define PGA_CTRL_CMLP_DIS 3
|
||||
#define PGA_CTRL_PDB_RIN 2
|
||||
#define PGA_CTRL_PEAKDET 0
|
||||
|
||||
/*ANA_ADC2_CTRL7*/
|
||||
#define AAF_LPMODE_EN 7
|
||||
#define AAF_STG2_IB_SEL 4
|
||||
#define AAFDSM_IB_DIV2 3
|
||||
#define AAF_STG1_IB_SEL 0
|
||||
|
||||
|
||||
/*ANA_ADC3_CTRL1*/
|
||||
#define ADC3_PGA_BYPASS 7
|
||||
#define ADC3_PGA_BYP_RCM 6
|
||||
#define ADC3_PGA_CTRL_RCM 4
|
||||
#define ADC3_PGA_MUTE 3
|
||||
#define ADC3_DSM_ENABLE 2
|
||||
#define ADC3_PGA_ENABLE 1
|
||||
#define ADC3_MICBIAS_EN 0
|
||||
|
||||
/*ANA_ADC3_CTRL3*/
|
||||
#define ADC3_ANA_CAL_EN 5
|
||||
#define ADC3_INVERT_CLK 4
|
||||
#define ADC3_SEL_OUT_EDGE 3
|
||||
#define ADC3_DSM_DISABLE 2
|
||||
#define ADC3_VREFP_DISABLE 1
|
||||
#define ADC3_AAF_DISABLE 0
|
||||
|
||||
/*ANA_ADC3_CTRL7*/
|
||||
#define DSM_COMP_IB_SEL 6
|
||||
#define DSM_OTA_CTRL 4
|
||||
#define DSM_LPMODE 3
|
||||
#define DSM_OTA_IB_SEL 0
|
||||
|
||||
|
||||
/*ANA_ADC4_CTRL1*/
|
||||
#define ADC4_PGA_BYPASS 7
|
||||
#define ADC4_PGA_BYP_RCM 6
|
||||
#define ADC4_PGA_CTRL_RCM 4
|
||||
#define ADC4_PGA_MUTE 3
|
||||
#define ADC4_DSM_ENABLE 2
|
||||
#define ADC4_PGA_ENABLE 1
|
||||
#define ADC4_MICBIAS_EN 0
|
||||
|
||||
/*ANA_ADC4_CTRL3*/
|
||||
#define ADC4_ANA_CAL_EN 5
|
||||
#define ADC4_SEL_OUT_EDGE 3
|
||||
#define ADC4_DSM_DISABLE 2
|
||||
#define ADC4_VREFP_DISABLE 1
|
||||
#define ADC4_AAF_DISABLE 0
|
||||
|
||||
/*ANA_ADC4_CTRL6*/
|
||||
#define DSM_DEMOFF 5
|
||||
#define DSM_EN_DITHER 4
|
||||
#define DSM_VREFP_LPMODE 2
|
||||
#define DSM_VREFP_OUTCTRL 0
|
||||
|
||||
/*ANA_ADC4_CTRL7*/
|
||||
#define CK8M_EN 5
|
||||
#define OSC_EN 4
|
||||
#define ADC4_CLK_GATING 3
|
||||
#define ADC3_CLK_GATING 2
|
||||
#define ADC2_CLK_GATING 1
|
||||
#define ADC1_CLK_GATING 0
|
||||
|
||||
|
||||
/*GPIO_CFG1*/
|
||||
#define GPIO2_SELECT 4
|
||||
#define GPIO1_SELECT 0
|
||||
|
||||
/*GPIO_CFG2*/
|
||||
#define GPIO4_SELECT 4
|
||||
#define GPIO3_SELECT 0
|
||||
|
||||
/*GPIO_DAT*///order???
|
||||
#define GPIO4_DAT 3
|
||||
#define GPIO3_DAT 2
|
||||
#define GPIO2_DAT 1
|
||||
#define GPIO1_DAT 0
|
||||
|
||||
/*GPIO_DRV*/
|
||||
#define GPIO4_DRV 6
|
||||
#define GPIO3_DRV 4
|
||||
#define GPIO2_DRV 2
|
||||
#define GPIO1_DRV 0
|
||||
|
||||
/*GPIO_PULL*/
|
||||
#define GPIO4_PULL 6
|
||||
#define GPIO3_PULL 4
|
||||
#define GPIO2_PULL 2
|
||||
#define GPIO1_PULL 0
|
||||
|
||||
/*GPIO_INT_CFG*/
|
||||
#define GPIO4_EINT_CFG 6
|
||||
#define GPIO3_EINT_CFG 4
|
||||
#define GPIO2_EINT_CFG 2
|
||||
#define GPIO1_EINT_CFG 0
|
||||
|
||||
/*GPIO_INT_EN*///order???
|
||||
#define GPIO4_EINT_EN 3
|
||||
#define GPIO3_EINT_EN 2
|
||||
#define GPIO2_EINT_EN 1
|
||||
#define GPIO1_EINT_EN 0
|
||||
|
||||
/*GPIO_INT_STATUS*///order???
|
||||
#define GPIO4_EINT_STA 3
|
||||
#define GPIO3_EINT_STA 2
|
||||
#define GPIO2_EINT_STA 1
|
||||
#define GPIO1_EINT_STA 0
|
||||
|
||||
|
||||
/*PRNG_CLK_CTRL*/
|
||||
#define PRNG_CLK_EN 1
|
||||
#define PRNG_CLK_POS 0
|
||||
|
||||
|
||||
|
||||
/*** Some Config Value ***/
|
||||
|
||||
//[SYSCLK_CTRL]: PLLCLK_SRC
|
||||
#define PLLCLK_SRC_MCLK 0
|
||||
#define PLLCLK_SRC_BCLK 1
|
||||
#define PLLCLK_SRC_GPIO2 2
|
||||
#define PLLCLK_SRC_GPIO3 3
|
||||
|
||||
//[SYSCLK_CTRL]: SYSCLK_SRC
|
||||
#define SYSCLK_SRC_MCLK 0
|
||||
#define SYSCLK_SRC_PLL 1
|
||||
|
||||
//I2S BCLK POLARITY Control
|
||||
#define BCLK_NORMAL_DRIVE_N_SAMPLE_P 0
|
||||
#define BCLK_INVERT_DRIVE_P_SAMPLE_N 1
|
||||
|
||||
//I2S LRCK POLARITY Control
|
||||
#define LRCK_LEFT_LOW_RIGHT_HIGH 0
|
||||
#define LRCK_LEFT_HIGH_RIGHT_LOW 1
|
||||
|
||||
//I2S Format Selection
|
||||
#define PCM_FORMAT 0
|
||||
#define LEFT_JUSTIFIED_FORMAT 1
|
||||
#define RIGHT_JUSTIFIED_FORMAT 2
|
||||
|
||||
|
||||
//I2S data protocol types
|
||||
|
||||
#define IS_ENCODING_MODE 0
|
||||
|
||||
#endif
|
||||
|
12
ac108_asound.conf
Normal file
12
ac108_asound.conf
Normal file
|
@ -0,0 +1,12 @@
|
|||
pcm.!default {
|
||||
type ac108
|
||||
slavepcm "hw:1,0"
|
||||
channels 4
|
||||
}
|
||||
|
||||
|
||||
pcm.ac108 {
|
||||
type ac108
|
||||
slavepcm "hw:1,0"
|
||||
channels 4
|
||||
}
|
1644
ac108_asound.state
Normal file
1644
ac108_asound.state
Normal file
File diff suppressed because it is too large
Load diff
58
ac108_plugin/Makefile
Normal file
58
ac108_plugin/Makefile
Normal file
|
@ -0,0 +1,58 @@
|
|||
|
||||
# Quiet (set to @ for a quite compile)
|
||||
Q ?= @
|
||||
#Q ?=
|
||||
|
||||
# Build Tools
|
||||
CC := gcc
|
||||
CFLAGS += -I. -Wall -funroll-loops -ffast-math -fPIC -DPIC -O0 -g
|
||||
LD := gcc
|
||||
LDFLAGS += -Wall -shared -lasound
|
||||
|
||||
SND_PCM_OBJECTS = pcm_ac108.o
|
||||
SND_PCM_LIBS =
|
||||
SND_PCM_BIN = libasound_module_pcm_ac108.so
|
||||
|
||||
#SND_CTL_OBJECTS = ctl_ac108.o ladspa_utils.o
|
||||
#SND_CTL_LIBS =
|
||||
#SND_CTL_BIN = libasound_module_ctl_ac108.so
|
||||
|
||||
MULTIARCH:=$(shell gcc --print-multiarch)
|
||||
LIBDIR = lib/$(MULTIARCH)
|
||||
|
||||
.PHONY: all clean dep load_default
|
||||
|
||||
all: Makefile $(SND_PCM_BIN) $(SND_CTL_BIN)
|
||||
|
||||
dep:
|
||||
@echo DEP $@
|
||||
$(Q)for i in *.c; do $(CC) -MM $(CFLAGS) "$${i}" ; done > makefile.dep
|
||||
|
||||
-include makefile.dep
|
||||
|
||||
$(SND_PCM_BIN): $(SND_PCM_OBJECTS)
|
||||
@echo LD $@
|
||||
$(Q)$(LD) $(LDFLAGS) $(SND_PCM_LIBS) $(SND_PCM_OBJECTS) -o $(SND_PCM_BIN)
|
||||
|
||||
#$(SND_CTL_BIN): $(SND_CTL_OBJECTS)
|
||||
# @echo LD $@
|
||||
# $(Q)$(LD) $(LDFLAGS) $(SND_CTL_LIBS) $(SND_CTL_OBJECTS) -o $(SND_CTL_BIN)
|
||||
|
||||
%.o: %.c
|
||||
@echo GCC $<
|
||||
$(Q)$(CC) -c $(CFLAGS) $(CPPFLAGS) $<
|
||||
|
||||
clean:
|
||||
@echo Cleaning...
|
||||
$(Q)rm -vf *.o *.so
|
||||
|
||||
install: all
|
||||
@echo Installing...
|
||||
$(Q)mkdir -p ${DESTDIR}/usr/$(LIBDIR)/alsa-lib/
|
||||
$(Q)install -m 644 $(SND_PCM_BIN) ${DESTDIR}/usr/$(LIBDIR)/alsa-lib/
|
||||
#$(Q)install -m 644 $(SND_CTL_BIN) ${DESTDIR}/usr/$(LIBDIR)/alsa-lib/
|
||||
|
||||
uninstall:
|
||||
@echo Un-installing...
|
||||
$(Q)rm ${DESTDIR}/usr/lib/alsa-lib/$(SND_PCM_BIN)
|
||||
#$(Q)rm ${DESTDIR}/usr/lib/alsa-lib/$(SND_CTL_BIN)
|
5
ac108_plugin/README.md
Normal file
5
ac108_plugin/README.md
Normal file
|
@ -0,0 +1,5 @@
|
|||
#seeed-4mic-voicecard alsa plugin
|
||||
```
|
||||
sudo apt install libasound2-dev
|
||||
make && sudo make install
|
||||
```
|
BIN
ac108_plugin/libasound_module_pcm_ac108.so
Executable file
BIN
ac108_plugin/libasound_module_pcm_ac108.so
Executable file
Binary file not shown.
479
ac108_plugin/pcm_ac108.c
Normal file
479
ac108_plugin/pcm_ac108.c
Normal file
|
@ -0,0 +1,479 @@
|
|||
//https://github.com/HazouPH/android_device_motorola_smi-plus/blob/48029b4afc307c73181b108a5b0155b9f20856ca/smi-modules/alsa-lib_module_voice/pcm_voice.c
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include <unistd.h>
|
||||
#include <alsa/asoundlib.h>
|
||||
#include <alsa/pcm_external.h>
|
||||
#include <alsa/pcm_plugin.h>
|
||||
|
||||
#include <math.h>
|
||||
|
||||
#define ARRAY_SIZE(ary) (sizeof(ary)/sizeof(ary[0]))
|
||||
#define AC108_FRAME_SIZE 4096
|
||||
struct ac108_t {
|
||||
snd_pcm_ioplug_t io;
|
||||
snd_pcm_t *slave;
|
||||
snd_pcm_hw_params_t *hw_params;
|
||||
unsigned int last_size;
|
||||
unsigned int ptr;
|
||||
void *buf;
|
||||
unsigned int latency; // Delay in usec
|
||||
unsigned int bufferSize; // Size of sample buffer
|
||||
};
|
||||
|
||||
/* set up the fixed parameters of slave PCM hw_parmas */
|
||||
static int ac108_slave_hw_params_half(struct ac108_t *rec, unsigned int rate,snd_pcm_format_t format) {
|
||||
int err;
|
||||
snd_pcm_uframes_t bufferSize = rec->bufferSize;
|
||||
unsigned int latency = rec->latency;
|
||||
|
||||
unsigned int buffer_time = 0;
|
||||
unsigned int period_time = 0;
|
||||
if ((err = snd_pcm_hw_params_malloc(&rec->hw_params)) < 0) return err;
|
||||
|
||||
if ((err = snd_pcm_hw_params_any(rec->slave, rec->hw_params)) < 0) {
|
||||
SNDERR("Cannot get slave hw_params");
|
||||
goto out;
|
||||
}
|
||||
if ((err = snd_pcm_hw_params_set_access(rec->slave, rec->hw_params,
|
||||
SND_PCM_ACCESS_RW_INTERLEAVED)) < 0) {
|
||||
SNDERR("Cannot set slave access RW_INTERLEAVED");
|
||||
goto out;
|
||||
}
|
||||
if ((err = snd_pcm_hw_params_set_channels(rec->slave, rec->hw_params, 2)) < 0) {
|
||||
SNDERR("Cannot set slave channels 2");
|
||||
goto out;
|
||||
}
|
||||
if ((err = snd_pcm_hw_params_set_format(rec->slave, rec->hw_params,
|
||||
format)) < 0) {
|
||||
SNDERR("Cannot set slave format");
|
||||
goto out;
|
||||
}
|
||||
if ((err = snd_pcm_hw_params_set_rate(rec->slave, rec->hw_params, rate, 0)) < 0) {
|
||||
SNDERR("Cannot set slave rate %d", rate);
|
||||
goto out;
|
||||
}
|
||||
|
||||
err = snd_pcm_hw_params_get_buffer_time_max(rec->hw_params,
|
||||
&buffer_time, 0);
|
||||
if (buffer_time > 80000)
|
||||
buffer_time = 80000;
|
||||
period_time = buffer_time / 4;
|
||||
|
||||
err = snd_pcm_hw_params_set_period_time_near(rec->slave, rec->hw_params,
|
||||
&period_time, 0);
|
||||
if (err < 0) {
|
||||
fprintf(stderr,"Unable to set_period_time_near");
|
||||
goto out;
|
||||
}
|
||||
err = snd_pcm_hw_params_set_buffer_time_near(rec->slave, rec->hw_params,
|
||||
&buffer_time, 0);
|
||||
if (err < 0) {
|
||||
fprintf(stderr,"Unable to set_buffer_time_near");
|
||||
goto out;
|
||||
}
|
||||
|
||||
rec->bufferSize = bufferSize;
|
||||
rec->latency = latency;
|
||||
|
||||
return 0;
|
||||
|
||||
out:
|
||||
free(rec->hw_params);
|
||||
rec->hw_params = NULL;
|
||||
return err;
|
||||
}
|
||||
|
||||
/*
|
||||
* start and stop callbacks - just trigger slave PCM
|
||||
*/
|
||||
static int ac108_start(snd_pcm_ioplug_t *io) {
|
||||
struct ac108_t *rec = io->private_data;
|
||||
|
||||
if(!rec->slave) {
|
||||
fprintf(stderr, "slave is lost\n");
|
||||
}
|
||||
|
||||
return snd_pcm_start(rec->slave);
|
||||
}
|
||||
|
||||
static int ac108_stop(snd_pcm_ioplug_t *io) {
|
||||
struct ac108_t *rec = io->private_data;
|
||||
|
||||
return snd_pcm_drop(rec->slave);
|
||||
}
|
||||
/*
|
||||
* pointer callback
|
||||
*
|
||||
* Calculate the current position from the delay of slave PCM
|
||||
*/
|
||||
static snd_pcm_sframes_t ac108_pointer(snd_pcm_ioplug_t *io) {
|
||||
struct ac108_t *rec = io->private_data;
|
||||
int err, size;
|
||||
|
||||
assert(rec);
|
||||
|
||||
|
||||
size = snd_pcm_avail(rec->slave);
|
||||
if (size < 0) return size;
|
||||
size = size /2;
|
||||
if (size > rec->last_size) {
|
||||
rec->ptr += size - rec->last_size;
|
||||
rec->ptr %= io->buffer_size;
|
||||
}
|
||||
|
||||
rec->last_size = size;
|
||||
|
||||
//fprintf(stderr, "%s :%d %d %d %d\n", __func__, rec->ptr,size, io->appl_ptr, io->hw_ptr);
|
||||
return rec->ptr;
|
||||
}
|
||||
|
||||
/*
|
||||
* transfer callback
|
||||
*/
|
||||
static snd_pcm_sframes_t ac108_transfer(snd_pcm_ioplug_t *io,
|
||||
const snd_pcm_channel_area_t *areas,
|
||||
snd_pcm_uframes_t offset,
|
||||
snd_pcm_uframes_t size) {
|
||||
struct ac108_t *rec = io->private_data;
|
||||
char *buf;
|
||||
ssize_t result;
|
||||
int err;
|
||||
|
||||
|
||||
/* we handle only an interleaved buffer */
|
||||
buf = (char *)areas->addr + (areas->first + areas->step * offset) / 8;
|
||||
result = snd_pcm_readi(rec->slave, buf, size*2);
|
||||
if (result <= 0) {
|
||||
fprintf(stderr, "%s out error:%d %d\n", __func__, result);
|
||||
return result;
|
||||
}
|
||||
rec->last_size -= size;
|
||||
|
||||
|
||||
return size;
|
||||
|
||||
}
|
||||
|
||||
/*
|
||||
* poll-related callbacks - just pass to slave PCM
|
||||
*/
|
||||
static int ac108_poll_descriptors_count(snd_pcm_ioplug_t *io) {
|
||||
struct ac108_t *rec = io->private_data;
|
||||
|
||||
//fprintf(stderr, "%s\n", __FUNCTION__);
|
||||
return snd_pcm_poll_descriptors_count(rec->slave);
|
||||
}
|
||||
|
||||
static int ac108_poll_descriptors(snd_pcm_ioplug_t *io, struct pollfd *pfd,
|
||||
unsigned int space) {
|
||||
struct ac108_t *rec = io->private_data;
|
||||
|
||||
//fprintf(stderr, "%s\n", __FUNCTION__);
|
||||
return snd_pcm_poll_descriptors(rec->slave, pfd, space);
|
||||
}
|
||||
|
||||
static int ac108_poll_revents(snd_pcm_ioplug_t *io, struct pollfd *pfd,
|
||||
unsigned int nfds, unsigned short *revents) {
|
||||
struct ac108_t *rec = io->private_data;
|
||||
|
||||
//fprintf(stderr, "%s\n", __FUNCTION__);
|
||||
return snd_pcm_poll_descriptors_revents(rec->slave, pfd, nfds, revents);
|
||||
}
|
||||
|
||||
/*
|
||||
* close callback
|
||||
*/
|
||||
static int ac108_close(snd_pcm_ioplug_t *io) {
|
||||
struct ac108_t *rec = io->private_data;
|
||||
|
||||
if (rec->slave) return snd_pcm_close(rec->slave);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int setSoftwareParams(struct ac108_t *rec) {
|
||||
snd_pcm_sw_params_t *softwareParams;
|
||||
int err;
|
||||
|
||||
snd_pcm_uframes_t bufferSize = 0;
|
||||
snd_pcm_uframes_t periodSize = 0;
|
||||
snd_pcm_uframes_t startThreshold, stopThreshold;
|
||||
snd_pcm_sw_params_alloca(&softwareParams);
|
||||
|
||||
// Get the current software parameters
|
||||
err = snd_pcm_sw_params_current(rec->slave, softwareParams);
|
||||
if (err < 0) {
|
||||
fprintf(stderr, "Unable to get software parameters: %s", snd_strerror(err));
|
||||
goto done;
|
||||
}
|
||||
|
||||
// Configure ALSA to start the transfer when the buffer is almost full.
|
||||
snd_pcm_get_params(rec->slave, &bufferSize, &periodSize);
|
||||
|
||||
|
||||
startThreshold = 1;
|
||||
stopThreshold = bufferSize;
|
||||
|
||||
|
||||
err = snd_pcm_sw_params_set_start_threshold(rec->slave, softwareParams,
|
||||
startThreshold);
|
||||
if (err < 0) {
|
||||
fprintf(stderr, "Unable to set start threshold to %lu frames: %s",
|
||||
startThreshold, snd_strerror(err));
|
||||
goto done;
|
||||
}
|
||||
|
||||
err = snd_pcm_sw_params_set_stop_threshold(rec->slave, softwareParams,
|
||||
stopThreshold);
|
||||
if (err < 0) {
|
||||
fprintf(stderr, "Unable to set stop threshold to %lu frames: %s",
|
||||
stopThreshold, snd_strerror(err));
|
||||
goto done;
|
||||
}
|
||||
// Allow the transfer to start when at least periodSize samples can be
|
||||
// processed.
|
||||
err = snd_pcm_sw_params_set_avail_min(rec->slave, softwareParams,
|
||||
periodSize);
|
||||
if (err < 0) {
|
||||
fprintf(stderr, "Unable to configure available minimum to %lu: %s",
|
||||
periodSize, snd_strerror(err));
|
||||
goto done;
|
||||
}
|
||||
|
||||
// Commit the software parameters back to the device.
|
||||
err = snd_pcm_sw_params(rec->slave, softwareParams);
|
||||
if (err < 0) fprintf(stderr, "Unable to configure software parameters: %s",
|
||||
snd_strerror(err));
|
||||
|
||||
|
||||
|
||||
return 0;
|
||||
done:
|
||||
snd_pcm_sw_params_free(softwareParams);
|
||||
|
||||
return err;
|
||||
}
|
||||
/*
|
||||
* hw_params callback
|
||||
*
|
||||
* Set up slave PCM according to the current parameters
|
||||
*/
|
||||
//static int ac108_hw_params(snd_pcm_ioplug_t *io,
|
||||
// snd_pcm_hw_params_t *params ATTRIBUTE_UNUSED) {
|
||||
static int ac108_hw_params(snd_pcm_ioplug_t *io) {
|
||||
struct ac108_t *rec = io->private_data;
|
||||
snd_pcm_sw_params_t *sparams;
|
||||
snd_pcm_uframes_t period_size;
|
||||
snd_pcm_uframes_t buffer_size;
|
||||
int err;
|
||||
if (!rec->hw_params) {
|
||||
err = ac108_slave_hw_params_half(rec, io->rate*2,io->format);
|
||||
if (err < 0) {
|
||||
fprintf(stderr, "ac108_slave_hw_params_half error\n");
|
||||
return err;
|
||||
}
|
||||
}
|
||||
period_size = io->period_size;
|
||||
if ((err = snd_pcm_hw_params_set_period_size_near(rec->slave, rec->hw_params,
|
||||
&period_size, NULL)) < 0) {
|
||||
SNDERR("Cannot set slave period size %ld", period_size);
|
||||
return err;
|
||||
}
|
||||
buffer_size = io->buffer_size;
|
||||
if ((err = snd_pcm_hw_params_set_buffer_size_near(rec->slave, rec->hw_params,
|
||||
&buffer_size)) < 0) {
|
||||
SNDERR("Cannot set slave buffer size %ld", buffer_size);
|
||||
return err;
|
||||
}
|
||||
if ((err = snd_pcm_hw_params(rec->slave, rec->hw_params)) < 0) {
|
||||
SNDERR("Cannot set slave hw_params");
|
||||
return err;
|
||||
}
|
||||
|
||||
setSoftwareParams(rec);
|
||||
|
||||
return 0;
|
||||
}
|
||||
/*
|
||||
* hw_free callback
|
||||
*/
|
||||
static int ac108_hw_free(snd_pcm_ioplug_t *io) {
|
||||
struct ac108_t *rec = io->private_data;
|
||||
free(rec->hw_params);
|
||||
if (rec->buf != NULL) {
|
||||
free(rec->buf);
|
||||
rec->buf = NULL;
|
||||
}
|
||||
rec->hw_params = NULL;
|
||||
|
||||
return snd_pcm_hw_free(rec->slave);
|
||||
|
||||
}
|
||||
|
||||
|
||||
static int ac108_prepare(snd_pcm_ioplug_t *io) {
|
||||
struct ac108_t *rec = io->private_data;
|
||||
rec->ptr = 0;
|
||||
rec->last_size =0;
|
||||
if (rec->buf == NULL) {
|
||||
rec->buf = malloc(io->buffer_size);
|
||||
}
|
||||
|
||||
return snd_pcm_prepare(rec->slave);
|
||||
}
|
||||
static int ac108_drain(snd_pcm_ioplug_t *io) {
|
||||
struct ac108_t *rec = io->private_data;
|
||||
return snd_pcm_drain(rec->slave);
|
||||
}
|
||||
static int ac108_sw_params(snd_pcm_ioplug_t *io, snd_pcm_sw_params_t *params) {
|
||||
struct ac108_t *rec = io->private_data;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int ac108_delay(snd_pcm_ioplug_t * io, snd_pcm_sframes_t * delayp){
|
||||
|
||||
return 0;
|
||||
}
|
||||
/*
|
||||
* callback table
|
||||
*/
|
||||
static snd_pcm_ioplug_callback_t a108_ops = {
|
||||
.start = ac108_start,
|
||||
.stop = ac108_stop,
|
||||
.pointer = ac108_pointer,
|
||||
.transfer = ac108_transfer,
|
||||
.poll_descriptors_count = ac108_poll_descriptors_count,
|
||||
.poll_descriptors = ac108_poll_descriptors,
|
||||
.poll_revents = ac108_poll_revents,
|
||||
.close = ac108_close,
|
||||
.hw_params = ac108_hw_params,
|
||||
.hw_free = ac108_hw_free,
|
||||
// .sw_params = ac108_sw_params,
|
||||
.prepare = ac108_prepare,
|
||||
.drain = ac108_drain,
|
||||
.delay = ac108_delay,
|
||||
};
|
||||
|
||||
|
||||
static int ac108_set_hw_constraint(struct ac108_t *rec) {
|
||||
static unsigned int accesses[] = {
|
||||
SND_PCM_ACCESS_RW_INTERLEAVED,
|
||||
SND_PCM_ACCESS_RW_NONINTERLEAVED
|
||||
};
|
||||
unsigned int formats[] = { SND_PCM_FORMAT_S32,
|
||||
SND_PCM_FORMAT_S16 };
|
||||
int err;
|
||||
snd_pcm_uframes_t buffer_max;
|
||||
unsigned int period_bytes, max_periods;
|
||||
|
||||
|
||||
err = snd_pcm_ioplug_set_param_list(&rec->io,
|
||||
SND_PCM_IOPLUG_HW_ACCESS,
|
||||
ARRAY_SIZE(accesses),
|
||||
accesses);
|
||||
if (err < 0) return err;
|
||||
|
||||
if ((err = snd_pcm_ioplug_set_param_list(&rec->io, SND_PCM_IOPLUG_HW_FORMAT,
|
||||
ARRAY_SIZE(formats), formats)) < 0 ||
|
||||
(err = snd_pcm_ioplug_set_param_minmax(&rec->io, SND_PCM_IOPLUG_HW_CHANNELS,
|
||||
1, 4)) < 0 ||
|
||||
(err = snd_pcm_ioplug_set_param_minmax(&rec->io, SND_PCM_IOPLUG_HW_RATE,
|
||||
8000, 96000)) < 0) return err;
|
||||
err = snd_pcm_ioplug_set_param_minmax(&rec->io,
|
||||
SND_PCM_IOPLUG_HW_BUFFER_BYTES,
|
||||
1, 4 * 1024 * 1024);
|
||||
if (err < 0) return err;
|
||||
|
||||
err = snd_pcm_ioplug_set_param_minmax(&rec->io,
|
||||
SND_PCM_IOPLUG_HW_PERIOD_BYTES,
|
||||
128, 2 * 1024 * 1024);
|
||||
if (err < 0) return err;
|
||||
|
||||
err = snd_pcm_ioplug_set_param_minmax(&rec->io, SND_PCM_IOPLUG_HW_PERIODS,
|
||||
3, 1024);
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
/*
|
||||
* Main entry point
|
||||
*/
|
||||
SND_PCM_PLUGIN_DEFINE_FUNC(ac108) {
|
||||
snd_config_iterator_t i, next;
|
||||
int err;
|
||||
const char *card = NULL;
|
||||
const char *pcm_string = NULL;
|
||||
snd_pcm_format_t format = SND_PCM_FORMAT_S32_LE;
|
||||
char devstr[128], tmpcard[8];
|
||||
struct ac108_t *rec;
|
||||
int channels;
|
||||
struct pollfd fds;
|
||||
if (stream != SND_PCM_STREAM_CAPTURE) {
|
||||
SNDERR("a108 is only for capture");
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
snd_config_for_each(i, next, conf) {
|
||||
snd_config_t *n = snd_config_iterator_entry(i);
|
||||
const char *id;
|
||||
if (snd_config_get_id(n, &id) < 0) continue;
|
||||
if (strcmp(id, "comment") == 0 || strcmp(id, "type") == 0 || strcmp(id, "hint") == 0) continue;
|
||||
|
||||
if (strcmp(id, "slavepcm") == 0) {
|
||||
if (snd_config_get_string(n, &pcm_string) < 0) {
|
||||
SNDERR("ac108 slavepcm must be a string");
|
||||
return -EINVAL;
|
||||
}
|
||||
continue;
|
||||
}
|
||||
|
||||
if (strcmp(id, "channels") == 0) {
|
||||
long val;
|
||||
if (snd_config_get_integer(n, &val) < 0) {
|
||||
SNDERR("Invalid type for %s", id);
|
||||
return -EINVAL;
|
||||
}
|
||||
channels = val;
|
||||
if (channels != 2 && channels != 4 && channels != 6) {
|
||||
SNDERR("channels must be 2, 4 or 6");
|
||||
return -EINVAL;
|
||||
}
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
rec = calloc(1, sizeof(*rec));
|
||||
if (!rec) {
|
||||
SNDERR("cannot allocate");
|
||||
return -ENOMEM;
|
||||
}
|
||||
err = snd_pcm_open(&rec->slave, pcm_string, stream, mode);
|
||||
if (err < 0) goto error;
|
||||
|
||||
|
||||
|
||||
//SND_PCM_NONBLOCK
|
||||
rec->io.version = SND_PCM_IOPLUG_VERSION;
|
||||
rec->io.name = "AC108 decode Plugin";
|
||||
rec->io.mmap_rw = 0;
|
||||
rec->io.callback = &a108_ops;
|
||||
rec->io.private_data = rec;
|
||||
|
||||
err = snd_pcm_ioplug_create(&rec->io, name, stream, mode);
|
||||
if (err < 0) goto error;
|
||||
|
||||
if ((err = ac108_set_hw_constraint(rec)) < 0) {
|
||||
snd_pcm_ioplug_delete(&rec->io);
|
||||
return err;
|
||||
}
|
||||
*pcmp = rec->io.pcm;
|
||||
return 0;
|
||||
|
||||
error:
|
||||
if (rec->slave) snd_pcm_close(rec->slave);
|
||||
free(rec);
|
||||
return err;
|
||||
}
|
||||
|
||||
SND_PCM_PLUGIN_SYMBOL(ac108);
|
BIN
ac108_plugin/pcm_ac108.o
Normal file
BIN
ac108_plugin/pcm_ac108.o
Normal file
Binary file not shown.
11
builddtbo.sh
11
builddtbo.sh
|
@ -1,4 +1,7 @@
|
|||
dtoverlay -r seeed-voicecard
|
||||
dtc -@ -I dts -O dtb -o seeed-voicecard.dtbo seeed-voicecard-overlay.dts
|
||||
cp seeed-voicecard.dtbo /boot/overlays
|
||||
dtoverlay seeed-voicecard
|
||||
#dtoverlay -r seeed-2mic-voicecard
|
||||
|
||||
dtc -@ -I dts -O dtb -o seeed-2mic-voicecard.dtbo seeed-2mic-voicecard-overlay.dts
|
||||
dtc -@ -I dts -O dtb -o seeed-4mic-voicecard.dtbo seeed-4mic-voicecard-overlay.dts
|
||||
|
||||
# cp *.dtbo /boot/overlays
|
||||
# dtoverlay seeed-2mic-voicecard
|
||||
|
|
|
@ -1,5 +1,7 @@
|
|||
PACKAGE_NAME="seeed-voicecard"
|
||||
PACKAGE_VERSION="0.1"
|
||||
BUILT_MODULE_NAME[0]="wm8960"
|
||||
PACKAGE_VERSION="0.2"
|
||||
BUILT_MODULE_NAME[0]="snd-soc-wm8960"
|
||||
BUILT_MODULE_NAME[1]="snd-soc-ac108"
|
||||
DEST_MODULE_LOCATION[0]="/kernel/sound/soc/codecs"
|
||||
DEST_MODULE_LOCATION[1]="/kernel/sound/soc/codecs"
|
||||
AUTOINSTALL="yes"
|
||||
|
|
20
install.sh
20
install.sh
|
@ -5,8 +5,7 @@ if [[ $EUID -ne 0 ]]; then
|
|||
exit 1
|
||||
fi
|
||||
|
||||
|
||||
ver="0.1"
|
||||
ver="0.2"
|
||||
|
||||
# we create a dir with this version to ensure that 'dkms remove' won't delete
|
||||
# the sources during kernel updates
|
||||
|
@ -42,22 +41,19 @@ function install_module {
|
|||
|
||||
install_module "./" "seeed-voicecard"
|
||||
|
||||
|
||||
(
|
||||
cp seeed-voicecard.dtbo /boot/overlays
|
||||
cp asound.state /var/lib/alsa/asound.state
|
||||
cp seeed-2mic-voicecard.dtbo /boot/overlays
|
||||
cp seeed-4mic-voicecard.dtbo /boot/overlays
|
||||
)
|
||||
|
||||
echo 'wm8960' | sudo tee --append /etc/modules > /dev/null
|
||||
echo 'snd-soc-ac108' | sudo tee --append /etc/modules > /dev/null
|
||||
echo 'snd-soc-wm8960' | sudo tee --append /etc/modules > /dev/null
|
||||
|
||||
|
||||
sed -i \
|
||||
-e "s/^dtparam=audio=on/#\0/" \
|
||||
-e "s/^#\(dtparam=i2s=on\)/\1/" \
|
||||
/boot/config.txt
|
||||
grep -q "dtoverlay=i2s-mmap" /boot/config.txt || \
|
||||
echo "dtoverlay=i2s-mmap" >> /boot/config.txt
|
||||
grep -q "dtoverlay=seeed-voicecard" /boot/config.txt || \
|
||||
echo "dtoverlay=seeed-voicecard" >> /boot/config.txt
|
||||
|
||||
|
||||
grep -q "dtparam=i2s=on" /boot/config.txt || \
|
||||
echo "dtparam=i2s=on" >> /boot/config.txt
|
||||
|
||||
|
|
|
@ -43,7 +43,7 @@
|
|||
master_overlay: __dormant__ {
|
||||
compatible = "simple-audio-card";
|
||||
simple-audio-card,format = "i2s";
|
||||
simple-audio-card,name = "seeed-voicecard";
|
||||
simple-audio-card,name = "seeed-2mic-voicecard";
|
||||
simple-audio-card,bitclock-master = <&dailink0_master>;
|
||||
simple-audio-card,frame-master = <&dailink0_master>;
|
||||
status = "okay";
|
||||
|
@ -80,7 +80,7 @@
|
|||
slave_overlay: __overlay__ {
|
||||
compatible = "simple-audio-card";
|
||||
simple-audio-card,format = "i2s";
|
||||
simple-audio-card,name = "seeed-voicecard";
|
||||
simple-audio-card,name = "seeed-2mic-voicecard";
|
||||
status = "okay";
|
||||
simple-audio-card,widgets =
|
||||
"Microphone", "Mic Jack",
|
BIN
seeed-2mic-voicecard.dtbo
Normal file
BIN
seeed-2mic-voicecard.dtbo
Normal file
Binary file not shown.
66
seeed-4mic-voicecard-overlay.dts
Normal file
66
seeed-4mic-voicecard-overlay.dts
Normal file
|
@ -0,0 +1,66 @@
|
|||
/dts-v1/;
|
||||
/plugin/;
|
||||
|
||||
/ {
|
||||
compatible = "brcm,bcm2708";
|
||||
fragment@0 {
|
||||
target = <&i2s>;
|
||||
__overlay__ {
|
||||
#sound-dai-cells = <0>;
|
||||
status = "okay";
|
||||
};
|
||||
};
|
||||
fragment@1 {
|
||||
target-path = "/clocks";
|
||||
__overlay__ {
|
||||
ac108_mclk: codec-mclk {
|
||||
compatible = "fixed-clock";
|
||||
#clock-cells = <0>;
|
||||
clock-frequency = <24000000>;
|
||||
};
|
||||
};
|
||||
};
|
||||
fragment@2 {
|
||||
target = <&i2c1>;
|
||||
__overlay__ {
|
||||
#address-cells = <1>;
|
||||
#size-cells = <0>;
|
||||
status = "okay";
|
||||
|
||||
ac108_a: ac108@3b{
|
||||
compatible = "x-power,ac108_0";
|
||||
reg = <0x3b>;
|
||||
#sound-dai-cells = <0>;
|
||||
data-protocol = <1>;
|
||||
};
|
||||
};
|
||||
};
|
||||
|
||||
|
||||
|
||||
fragment@3 {
|
||||
target = <&sound>;
|
||||
sound_overlay: __overlay__ {
|
||||
compatible = "simple-audio-card";
|
||||
simple-audio-card,format = "i2s";
|
||||
simple-audio-card,name = "seeed-4mic-voicecard";
|
||||
status = "okay";
|
||||
|
||||
simple-audio-card,bitclock-master = <&dailink0_slave>;
|
||||
simple-audio-card,frame-slave = <&dailink0_slave>;
|
||||
dailink0_slave: simple-audio-card,cpu {
|
||||
sound-dai = <&i2s>;
|
||||
};
|
||||
codec_dai: simple-audio-card,codec {
|
||||
sound-dai = <&ac108_a>;
|
||||
clocks = <&ac108_mclk>;
|
||||
};
|
||||
};
|
||||
};
|
||||
__overrides__ {
|
||||
card-name = <&sound_overlay>,"seeed-voicecard,name";
|
||||
};
|
||||
|
||||
|
||||
};
|
||||
|
BIN
seeed-4mic-voicecard.dtbo
Normal file
BIN
seeed-4mic-voicecard.dtbo
Normal file
Binary file not shown.
Binary file not shown.
BIN
wm8960.ko
BIN
wm8960.ko
Binary file not shown.
Loading…
Reference in a new issue