From a270846325c94861b7c128e4fbaedd72e57f3c67 Mon Sep 17 00:00:00 2001 From: zhangzhaopeng Date: Thu, 24 Apr 2025 18:42:26 +0800 Subject: [PATCH] =?UTF-8?q?1.=E6=B7=BB=E5=8A=A0=E5=92=8C=E5=94=A4=E9=86=92?= =?UTF-8?q?=E6=BA=90=E5=90=8C=E6=AD=A5=E7=9A=84=E9=80=BB=E8=BE=91=202.?= =?UTF-8?q?=E6=B7=BB=E5=8A=A0=E5=AE=8F=E8=B0=83=E6=95=B4=E9=9F=B3=E9=87=8F?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../char/hichs-has/snd_has_play_sound.c | 66 +++++++++++++++---- 1 file changed, 55 insertions(+), 11 deletions(-) diff --git a/lichee/linux-4.9/drivers/char/hichs-has/snd_has_play_sound.c b/lichee/linux-4.9/drivers/char/hichs-has/snd_has_play_sound.c index a1f4c4571..b6f5c075f 100755 --- a/lichee/linux-4.9/drivers/char/hichs-has/snd_has_play_sound.c +++ b/lichee/linux-4.9/drivers/char/hichs-has/snd_has_play_sound.c @@ -29,17 +29,35 @@ #define SAMPLE_RATE 16000 #define PCM_FORMAT_BITS 16 // SNDRV_PCM_FORMAT_S16_LE #define PCM_CHANNEL_NUMBER 1 +#define SOUND_VOLUME (0x000000A2)// TODO:从806获取音量 0~0xFF,default 0xA0 -struct sunxi_has_mem g_mem; -struct sunxi_has_clk g_clk; -struct has_pa_config *g_pa_config = NULL; -struct platform_device *g_pdev = NULL; -unsigned int g_pa_pin_max = 0; +#define HAS_WAIT_WAKEUP_SRC_TIMEOUT 500 // ms +#define HAS_WAIT_PLAY_END_TIMEOUT 3000 // ms + +#define WAKEUP_SOURCE_NONE 0x00 // 复位就是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; +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(wakeup_get); /* WAV文件格式 */ #pragma pack(1) @@ -100,6 +118,15 @@ static struct dma_slave_config slave_config = { .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) { 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"); return -1; } + /* set default volume */ + regmap_update_bits(g_mem.regmap, SUNXI_DAC_VOL_CTRL, 0x0000FFFF, g_reg_val); /* clk */ snd_sunxi_has_clk_deinit(); /* memery io unmap */ @@ -155,7 +184,7 @@ static void has_dma_complete(void *arg) { // enum dma_status status; // struct dma_tx_state state; - complete(&doorbell_end); + complete(&kill_doorbell); // status = dmaengine_tx_status(dma_chan, dma_cookie, &state); // 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; struct wav_header_t wav_header; - mtd = get_mtd_device_nm("logo"); // 名称 + mtd = get_mtd_device_nm(DOOLBELL_PARTITION_NAME); // 名称 if (IS_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; 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 // pr_emerg("dma_area:0x%x dma_addr:0x%x\n", (int)dma_area, (int)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); // 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_terminate_async(dma_chan); @@ -298,6 +333,7 @@ err_request_init: err_read_init: dma_free_coherent(NULL, DMA_ALLOC_SIZE, dma_area, dma_addr); err_alloc_init: +skip_doorbell: has_free_own_device(g_pdev); g_pdev = NULL; 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_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) @@ -892,7 +934,8 @@ static long doolbell_drv_ioctl(struct file *file, unsigned int cmd, unsigned lon int value; switch (cmd) { case DOOLBELL_STOP: { - complete(&doorbell_end); + complete(&kill_doorbell); + complete(&wakeup_get); wait_for_completion_interruptible(&relase_done); if (g_pdev != NULL) { @@ -902,7 +945,7 @@ static long doolbell_drv_ioctl(struct file *file, unsigned int cmd, unsigned lon break; } case DOOLBELL_GET_STATUS: { - /* 用户态应该轮询查询状态 */ + /* 用户态应该轮询查询状态,轮询不用考虑并发读取g_pdev */ if (g_pdev != NULL) // 启动门铃流程未结束 { 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.res = &g_res; 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"); if (np) {