parent
796620b3ab
commit
a270846325
|
@ -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) {
|
||||
|
|
Loading…
Reference in New Issue