parent
796620b3ab
commit
a270846325
|
@ -29,17 +29,35 @@
|
||||||
#define SAMPLE_RATE 16000
|
#define SAMPLE_RATE 16000
|
||||||
#define PCM_FORMAT_BITS 16 // SNDRV_PCM_FORMAT_S16_LE
|
#define PCM_FORMAT_BITS 16 // SNDRV_PCM_FORMAT_S16_LE
|
||||||
#define PCM_CHANNEL_NUMBER 1
|
#define PCM_CHANNEL_NUMBER 1
|
||||||
|
#define SOUND_VOLUME (0x000000A2)// TODO:从806获取音量 0~0xFF,default 0xA0
|
||||||
|
|
||||||
struct sunxi_has_mem g_mem;
|
#define HAS_WAIT_WAKEUP_SRC_TIMEOUT 500 // ms
|
||||||
struct sunxi_has_clk g_clk;
|
#define HAS_WAIT_PLAY_END_TIMEOUT 3000 // ms
|
||||||
struct has_pa_config *g_pa_config = NULL;
|
|
||||||
struct platform_device *g_pdev = NULL;
|
#define WAKEUP_SOURCE_NONE 0x00 // 复位就是0
|
||||||
unsigned int g_pa_pin_max = 0;
|
#define WAKEUP_SOURCE_TOUCH 0x01
|
||||||
|
#define WAKEUP_SOURCE_STREAM 0x02
|
||||||
|
#define WAKEUP_SOURCE_DOORBELL 0x03
|
||||||
|
#define WAKEUP_SOURCE_PEEPHOLE 0x04
|
||||||
|
#define WAKEUP_SOURCE_INVALID 0xFF // 无效值,忽略,表示已经获取过唤醒源
|
||||||
|
|
||||||
|
#define DOOLBELL_PARTITION_NAME "doorbell"
|
||||||
|
|
||||||
|
// TODO:可以动态分配管理全局变量,放入device数据中
|
||||||
|
static struct sunxi_has_mem g_mem;
|
||||||
|
static struct sunxi_has_clk g_clk;
|
||||||
|
static struct has_pa_config *g_pa_config = NULL;
|
||||||
|
static struct platform_device *g_pdev = NULL;
|
||||||
|
static unsigned int g_pa_pin_max = 0;
|
||||||
|
|
||||||
struct resource g_res;
|
struct resource g_res;
|
||||||
|
static unsigned int g_reg_val = 0xA0;
|
||||||
|
static atomic_t g_wakeup_src = ATOMIC_INIT(0);
|
||||||
|
// static atomic_t g_wakeup_src;
|
||||||
|
|
||||||
static DECLARE_COMPLETION(doorbell_end);
|
static DECLARE_COMPLETION(kill_doorbell);
|
||||||
static DECLARE_COMPLETION(relase_done);
|
static DECLARE_COMPLETION(relase_done);
|
||||||
|
static DECLARE_COMPLETION(wakeup_get);
|
||||||
|
|
||||||
/* WAV文件格式 */
|
/* WAV文件格式 */
|
||||||
#pragma pack(1)
|
#pragma pack(1)
|
||||||
|
@ -100,6 +118,15 @@ static struct dma_slave_config slave_config = {
|
||||||
.src_maxburst = 4,
|
.src_maxburst = 4,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
void doorbell_control(unsigned char wakeup_src) {
|
||||||
|
if (wakeup_src == WAKEUP_SOURCE_DOORBELL)
|
||||||
|
{
|
||||||
|
atomic_set(&g_wakeup_src, wakeup_src);
|
||||||
|
}
|
||||||
|
complete(&wakeup_get);
|
||||||
|
}
|
||||||
|
EXPORT_SYMBOL(doorbell_control);
|
||||||
|
|
||||||
static void snd_sunxi_has_mem_deinit(struct platform_device *pdev)
|
static void snd_sunxi_has_mem_deinit(struct platform_device *pdev)
|
||||||
{
|
{
|
||||||
devm_iounmap(&pdev->dev, g_mem.membase);
|
devm_iounmap(&pdev->dev, g_mem.membase);
|
||||||
|
@ -140,6 +167,8 @@ static int has_free_own_device(struct platform_device *pdev)
|
||||||
pr_emerg("pdev is NULL\n");
|
pr_emerg("pdev is NULL\n");
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
/* set default volume */
|
||||||
|
regmap_update_bits(g_mem.regmap, SUNXI_DAC_VOL_CTRL, 0x0000FFFF, g_reg_val);
|
||||||
/* clk */
|
/* clk */
|
||||||
snd_sunxi_has_clk_deinit();
|
snd_sunxi_has_clk_deinit();
|
||||||
/* memery io unmap */
|
/* memery io unmap */
|
||||||
|
@ -155,7 +184,7 @@ static void has_dma_complete(void *arg)
|
||||||
{
|
{
|
||||||
// enum dma_status status;
|
// enum dma_status status;
|
||||||
// struct dma_tx_state state;
|
// struct dma_tx_state state;
|
||||||
complete(&doorbell_end);
|
complete(&kill_doorbell);
|
||||||
// status = dmaengine_tx_status(dma_chan, dma_cookie, &state);
|
// status = dmaengine_tx_status(dma_chan, dma_cookie, &state);
|
||||||
// pr_emerg("status:%d residue:%d\n", status, state.residue);
|
// pr_emerg("status:%d residue:%d\n", status, state.residue);
|
||||||
}
|
}
|
||||||
|
@ -166,7 +195,7 @@ static size_t has_decode_WAV_and_getPCM(unsigned char *pcm_data)
|
||||||
size_t retlen = 0;
|
size_t retlen = 0;
|
||||||
struct wav_header_t wav_header;
|
struct wav_header_t wav_header;
|
||||||
|
|
||||||
mtd = get_mtd_device_nm("logo"); // 名称
|
mtd = get_mtd_device_nm(DOOLBELL_PARTITION_NAME); // 名称
|
||||||
if (IS_ERR(mtd))
|
if (IS_ERR(mtd))
|
||||||
{
|
{
|
||||||
pr_emerg("Failed to get MTD device: %ld\n", PTR_ERR(mtd));
|
pr_emerg("Failed to get MTD device: %ld\n", PTR_ERR(mtd));
|
||||||
|
@ -228,6 +257,12 @@ static int snd_has_pcm_playsound(void *param)
|
||||||
dma_addr_t dma_addr = 0;
|
dma_addr_t dma_addr = 0;
|
||||||
unsigned char *dma_area = NULL;
|
unsigned char *dma_area = NULL;
|
||||||
|
|
||||||
|
wait_for_completion_interruptible_timeout(&wakeup_get, msecs_to_jiffies(HAS_WAIT_WAKEUP_SRC_TIMEOUT));
|
||||||
|
if (atomic_read(&g_wakeup_src) != WAKEUP_SOURCE_DOORBELL)
|
||||||
|
{
|
||||||
|
goto skip_doorbell;
|
||||||
|
}
|
||||||
|
|
||||||
dma_area = dma_alloc_coherent(NULL, DMA_ALLOC_SIZE, &dma_addr, GFP_KERNEL); // 申请dma
|
dma_area = dma_alloc_coherent(NULL, DMA_ALLOC_SIZE, &dma_addr, GFP_KERNEL); // 申请dma
|
||||||
// pr_emerg("dma_area:0x%x dma_addr:0x%x\n", (int)dma_area, (int)dma_addr);
|
// pr_emerg("dma_area:0x%x dma_addr:0x%x\n", (int)dma_area, (int)dma_addr);
|
||||||
if ((!dma_area) || (!dma_addr))
|
if ((!dma_area) || (!dma_addr))
|
||||||
|
@ -278,7 +313,7 @@ static int snd_has_pcm_playsound(void *param)
|
||||||
dma_async_issue_pending(dma_chan);
|
dma_async_issue_pending(dma_chan);
|
||||||
// pr_emerg("plad sound start!\n");
|
// pr_emerg("plad sound start!\n");
|
||||||
|
|
||||||
wait_for_completion_interruptible(&doorbell_end);
|
wait_for_completion_interruptible_timeout(&kill_doorbell, msecs_to_jiffies(HAS_WAIT_PLAY_END_TIMEOUT));
|
||||||
// dmaengine_synchronize(dma_chan);
|
// dmaengine_synchronize(dma_chan);
|
||||||
dmaengine_terminate_async(dma_chan);
|
dmaengine_terminate_async(dma_chan);
|
||||||
|
|
||||||
|
@ -298,6 +333,7 @@ err_request_init:
|
||||||
err_read_init:
|
err_read_init:
|
||||||
dma_free_coherent(NULL, DMA_ALLOC_SIZE, dma_area, dma_addr);
|
dma_free_coherent(NULL, DMA_ALLOC_SIZE, dma_area, dma_addr);
|
||||||
err_alloc_init:
|
err_alloc_init:
|
||||||
|
skip_doorbell:
|
||||||
has_free_own_device(g_pdev);
|
has_free_own_device(g_pdev);
|
||||||
g_pdev = NULL;
|
g_pdev = NULL;
|
||||||
complete(&relase_done);
|
complete(&relase_done);
|
||||||
|
@ -868,6 +904,12 @@ static void sunxi_has_codec_init(struct sunxi_has_dts *dts)
|
||||||
|
|
||||||
regmap_update_bits(regmap, SUNXI_DAC_VOL_CTRL, 1 << DAC_VOL_SEL, 1 << DAC_VOL_SEL);
|
regmap_update_bits(regmap, SUNXI_DAC_VOL_CTRL, 1 << DAC_VOL_SEL, 1 << DAC_VOL_SEL);
|
||||||
regmap_update_bits(regmap, SUNXI_ADC_DIG_CTRL, 1 << ADC1_2_VOL_EN, 1 << ADC1_2_VOL_EN);
|
regmap_update_bits(regmap, SUNXI_ADC_DIG_CTRL, 1 << ADC1_2_VOL_EN, 1 << ADC1_2_VOL_EN);
|
||||||
|
regmap_read(regmap, SUNXI_DAC_VOL_CTRL, &g_reg_val);
|
||||||
|
// reg_R_val = (g_reg_val & 0xFF);
|
||||||
|
// reg_L_val = ((g_reg_val >> 8) & 0xFF);
|
||||||
|
// pr_emerg("reg_val:0x%08x, L:0x%02x R:0x%02x\n", reg_val, reg_L_val, reg_R_val);
|
||||||
|
// regmap_update_bits(regmap, SUNXI_DAC_VOL_CTRL, 0x000000FF, SOUND_VOLUME); // R
|
||||||
|
regmap_update_bits(regmap, SUNXI_DAC_VOL_CTRL, 0x0000FFFF, (SOUND_VOLUME << 8 | SOUND_VOLUME)); // L
|
||||||
}
|
}
|
||||||
|
|
||||||
static int doolbell_drv_open(struct inode *node, struct file *file)
|
static int doolbell_drv_open(struct inode *node, struct file *file)
|
||||||
|
@ -892,7 +934,8 @@ static long doolbell_drv_ioctl(struct file *file, unsigned int cmd, unsigned lon
|
||||||
int value;
|
int value;
|
||||||
switch (cmd) {
|
switch (cmd) {
|
||||||
case DOOLBELL_STOP: {
|
case DOOLBELL_STOP: {
|
||||||
complete(&doorbell_end);
|
complete(&kill_doorbell);
|
||||||
|
complete(&wakeup_get);
|
||||||
wait_for_completion_interruptible(&relase_done);
|
wait_for_completion_interruptible(&relase_done);
|
||||||
if (g_pdev != NULL)
|
if (g_pdev != NULL)
|
||||||
{
|
{
|
||||||
|
@ -902,7 +945,7 @@ static long doolbell_drv_ioctl(struct file *file, unsigned int cmd, unsigned lon
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case DOOLBELL_GET_STATUS: {
|
case DOOLBELL_GET_STATUS: {
|
||||||
/* 用户态应该轮询查询状态 */
|
/* 用户态应该轮询查询状态,轮询不用考虑并发读取g_pdev */
|
||||||
if (g_pdev != NULL) // 启动门铃流程未结束
|
if (g_pdev != NULL) // 启动门铃流程未结束
|
||||||
{
|
{
|
||||||
value = DOOLBELL_PLAYING;
|
value = DOOLBELL_PLAYING;
|
||||||
|
@ -946,6 +989,7 @@ static int has_play_sound_dev_probe(struct platform_device *pdev)
|
||||||
g_mem.dev_name = DRV_NAME;
|
g_mem.dev_name = DRV_NAME;
|
||||||
g_mem.res = &g_res;
|
g_mem.res = &g_res;
|
||||||
g_mem.regmap_config = &g_regmap_config;
|
g_mem.regmap_config = &g_regmap_config;
|
||||||
|
// atomic_set(&g_wakeup_src, WAKEUP_SOURCE_NONE);
|
||||||
|
|
||||||
np = of_find_compatible_node(NULL, NULL, "allwinner,sunxi-snd-plat-aaudio");
|
np = of_find_compatible_node(NULL, NULL, "allwinner,sunxi-snd-plat-aaudio");
|
||||||
if (np) {
|
if (np) {
|
||||||
|
|
Loading…
Reference in New Issue