1.添加和唤醒源同步的逻辑

2.添加宏调整音量
This commit is contained in:
张兆鹏 2025-04-24 18:42:26 +08:00
parent 796620b3ab
commit a270846325
1 changed files with 55 additions and 11 deletions

View File

@ -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~0xFFdefault 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) {