pure sdk for main

This commit is contained in:
divadiow
2025-08-27 09:51:58 +01:00
parent f0d033f1c9
commit 0571416e7c
3283 changed files with 1577720 additions and 1 deletions
+477
View File
@@ -0,0 +1,477 @@
/**
* @file hgpdm_v0.c
* @author bxd
* @brief pdm
* @version
* TXW80X; TXW81X
* @date 2023-08-02
*
* @copyright Copyright (c) 2023
*
*/
#include "typesdef.h"
#include "list.h"
#include "errno.h"
#include "dev.h"
#include "osal/irq.h"
#include "osal/semaphore.h"
#include "osal/mutex.h"
#include "osal/string.h"
#include "hal/pdm.h"
#include "dev/pdm/hgpdm_v0.h"
#include "hgpdm_v0_hw.h"
/**********************************************************************************/
/* LOW LAYER FUNCTION */
/**********************************************************************************/
static int32 hgpdm_v0_switch_hal_pdm_sample_freq(enum pdm_sample_freq param) {
switch (param) {
#ifdef TXW80X
case (PDM_SAMPLE_FREQ_8K):
return 8000;
break;
#endif
case (PDM_SAMPLE_FREQ_16K):
return 16000;
break;
case (PDM_SAMPLE_FREQ_32K):
return 32000;
break;
case (PDM_SAMPLE_FREQ_48K):
return 48000;
break;
default:
return -1;
break;
}
}
static int32 hgpdm_v0_switch_hal_pdm_channel(enum pdm_channel param) {
switch (param) {
case (PDM_CHANNEL_LEFT):
return 0;
break;
case (PDM_CHANNEL_RIGHT):
return 1;
break;
case (PDM_CHANNEL_STEREO):
return 2;
break;
default:
return -1;
break;
}
}
static void hgpdm_v0_set_mclk(int32 freq) {
uint32 temp;
volatile uint32 div;
sysctrl_unlock();
SYSCTRL->SYS_CON2 |= 1<<18; //choose pll0
#ifdef TXW80X
#ifndef FPGA_SUPPORT
div = (peripheral_clock_get(HG_APB0_PT_PDM)/ (freq*64*8));
#else
float div_f;
div_f = (96000000.0 / (freq*64*8));
div = (uint32_t)(div_f+0.5);
#endif
#endif
#ifdef TXW81X
#ifndef FPGA_SUPPORT
div = (peripheral_clock_get(HG_APB0_PT_PDM)/ (freq*100*4));
#else
float div_f;
div_f = (96000000.0 / (freq*64*8));
div = (uint32_t)(div_f+0.5);
#endif
#endif
temp = SYSCTRL->SYS_CON2;
temp &= ~0x07F00000;
temp |= (div-1)<<20; //select div
SYSCTRL->SYS_CON2 = temp;
sysctrl_lock();
}
static int32 hgpdm_v0_lr_channel_interchange(struct hgpdm_v0_hw *p_pdm, uint32 enable) {
if (enable) {
p_pdm->CON |= LL_PDM_CON_LRSW(1);
} else {
p_pdm->CON &= ~ LL_PDM_CON_LRSW(1);
}
return RET_OK;
}
static void hgpdm_v0_enable(struct hgpdm_v0_hw *p_pdm) {
p_pdm->CON |= LL_PDM_CON_ENABLE(1);
}
static void hgpdm_v0_disable(struct hgpdm_v0_hw *p_pdm) {
p_pdm->CON &= ~ LL_PDM_CON_ENABLE(1);
}
/**********************************************************************************/
/* ATTCH FUNCTION */
/**********************************************************************************/
static int32 hgpdm_v0_open(struct pdm_device *pdm, enum pdm_sample_freq freq, enum pdm_channel channel) {
struct hgpdm_v0 *dev = (struct hgpdm_v0 *)pdm;
struct hgpdm_v0_hw *hw = (struct hgpdm_v0_hw *)dev->hw;
int32 freq_to_reg = 0;
int32 channel_to_reg = 0;
if (dev->opened) {
if (!dev->dsleep) {
return -EBUSY;
}
}
/* hal enum */
freq_to_reg = hgpdm_v0_switch_hal_pdm_sample_freq(freq);
channel_to_reg = hgpdm_v0_switch_hal_pdm_channel(channel);
if ((-1) == freq_to_reg ||
(-1) == channel_to_reg) {
return -EINVAL;
}
/* make sure the clk */
#if 0
if (0 != ((peripheral_clock_get(HG_APB0_PT_PDM)) % (freq_to_reg*512))) {
return RET_ERR;
}
#endif
/* pin config */
if (pin_func(dev->dev.dev.dev_id , 1) != RET_OK) {
return RET_ERR;
}
/*
* open PDM clk
*/
sysctrl_pdm_clk_open();
/*
* clear the regs
*/
hw->CON = 0;
hw->DMACON = 0;
hw->DMALEN = 0;
hw->DMASTADR = 0;
hw->STA = 0xFFFF;
/* reg config */
hgpdm_v0_set_mclk(freq_to_reg);
#ifdef TXW80X
hw->CON = LL_PDM_CON_WORKMODE(channel_to_reg) | LL_PDM_CON_DECIM(0);
#endif
#ifdef TXW81X
hw->CON = LL_PDM_CON_WORKMODE(channel_to_reg) | LL_PDM_CON_DECIM(1);
#endif
hw->STA = 3;
dev->opened = 1;
dev->dsleep = 0;
return RET_OK;
}
static int32 hgpdm_v0_read(struct pdm_device *pdm, void* buf, uint32 len) {
struct hgpdm_v0 *dev = (struct hgpdm_v0 *)pdm;
struct hgpdm_v0_hw *hw = (struct hgpdm_v0_hw *)dev->hw;
if ((!dev->opened) || (dev->dsleep)) {
return RET_ERR;
}
if(!buf || len == 0)
{
return RET_ERR;
}
hw->DMASTADR = (uint32)buf;
hw->DMALEN = len;
hgpdm_v0_enable(hw);
return RET_OK;
}
static int32 hgpdm_v0_close(struct pdm_device *pdm) {
struct hgpdm_v0 *dev = (struct hgpdm_v0 *)pdm;
struct hgpdm_v0_hw *hw = (struct hgpdm_v0_hw *)dev->hw;
if (!dev->opened) {
return RET_OK;
}
/*
* close PDM clk
*/
sysctrl_pdm_clk_close();
hgpdm_v0_disable(hw );
irq_disable(dev->irq_num );
pin_func(dev->dev.dev.dev_id, 0);
dev->opened = 0;
dev->dsleep = 0;
return RET_OK;
}
#ifdef CONFIG_SLEEP
static int32 hgpdm_v0_suspend(struct dev_obj *obj)
{
struct hgpdm_v0 *dev = (struct hgpdm_v0 *)obj;
struct hgpdm_v0_hw *hw = (struct hgpdm_v0_hw *)dev->hw;
if ((!dev->opened) || (dev->dsleep)) {
return RET_OK;
}
if (0 > os_mutex_lock(&dev->bp_suspend_lock, 10000)) {
return RET_ERR;
}
/*!
* Close the PDM
*/
hw->CON &= ~ BIT(0);
pin_func(dev->dev.dev.dev_id, 0);
/*
* close irq
*/
irq_disable(dev->irq_num);
/*
* clear pending
*/
hw->STA = 0xFFFFFFFF;
os_memset((void *)&dev->bp_regs, 0, sizeof(dev->bp_regs));
/*
* save the reglist
*/
dev->bp_regs.con = hw->CON;
dev->bp_regs.dmastadr = hw->DMASTADR;
dev->bp_regs.dmalen = hw->DMALEN;
dev->bp_regs.dmacon = hw->DMACON;
/*
* save the irq_hdl created by user
*/
dev->bp_irq_hdl = dev->irq_hdl;
dev->bp_irq_data = dev->irq_data;
sysctrl_pdm_clk_close();
dev->dsleep = 1;
os_mutex_unlock(&dev->bp_suspend_lock);
return RET_OK;
}
static int32 hgpdm_v0_resume(struct dev_obj *obj)
{
struct hgpdm_v0 *dev = (struct hgpdm_v0 *)obj;
struct hgpdm_v0_hw *hw = (struct hgpdm_v0_hw *)dev->hw;
if ((!dev->opened) || (!dev->dsleep)) {
return RET_OK;
}
if (0 > os_mutex_lock(&dev->bp_resume_lock, 10000)) {
return RET_ERR;
}
/* pin config */
if (pin_func(dev->dev.dev.dev_id , 1) != RET_OK) {
return RET_ERR;
}
/*
* recovery the PDM clk
*/
sysctrl_pdm_clk_open();
/*
* recovery the reglist from sram
*/
hw->DMASTADR = dev->bp_regs.dmastadr;
hw->DMALEN = dev->bp_regs.dmalen;
hw->DMACON = dev->bp_regs.dmacon;
hw->CON = dev->bp_regs.con;
/*
* recovery the irq handle and data
*/
dev->irq_hdl = dev->bp_irq_hdl;
dev->irq_data = dev->bp_irq_data;
os_memset((void *)&dev->bp_regs, 0, sizeof(dev->bp_regs));
/*!
* Open the PDM
*/
hw->CON |= BIT(0);
/*
* open irq
*/
irq_enable(dev->irq_num);
dev->dsleep = 0;
os_mutex_unlock(&dev->bp_resume_lock);
return RET_OK;
}
#endif
static void hgpdm_v0_irq_handler(void *data) {
struct hgpdm_v0 *dev = (struct hgpdm_v0 *)data;
struct hgpdm_v0_hw *hw = (struct hgpdm_v0_hw *)dev->hw;
if ((hw->DMACON & LL_PDM_DMACON_HF_IE_EN(1)) &&
(hw->STA & LL_PDM_STA_HF_PENDING(1))) {
hw->STA |= LL_PDM_STA_HF_PENDING(1);
if (dev->irq_hdl) {
dev->irq_hdl(PDM_IRQ_FLAG_DMA_HF, dev->irq_data);
}
}
if ((hw->DMACON & LL_PDM_DMACON_OV_IE_EN(1)) &&
(hw->STA & LL_PDM_STA_OV_PENDING(1))) {
hw->STA |= LL_PDM_STA_OV_PENDING(1);
if (dev->irq_hdl) {
dev->irq_hdl(PDM_IRQ_FLAG_DMA_OV, dev->irq_data);
}
}
}
static int32 hgpdm_v0_request_irq(struct pdm_device *pdm, enum pdm_irq_flag irq_flag, pdm_irq_hdl irq_hdl, uint32 data) {
struct hgpdm_v0 *dev = (struct hgpdm_v0 *)pdm;
struct hgpdm_v0_hw *hw = (struct hgpdm_v0_hw *)dev->hw;
if ((!dev->opened) || (dev->dsleep)) {
return RET_ERR;
}
dev->irq_hdl = irq_hdl;
dev->irq_data = data;
request_irq(dev->irq_num, hgpdm_v0_irq_handler, dev);
if (irq_flag & PDM_IRQ_FLAG_DMA_HF) {
hw->DMACON |= LL_PDM_DMACON_HF_IE_EN(1);
}
if (irq_flag & PDM_IRQ_FLAG_DMA_OV) {
hw->DMACON |= LL_PDM_DMACON_OV_IE_EN(1);
}
irq_enable(dev->irq_num);
return RET_OK;
}
static int32 hgpdm_v0_release_irq(struct pdm_device *pdm, enum pdm_irq_flag irq_flag) {
struct hgpdm_v0 *dev = (struct hgpdm_v0 *)pdm;
struct hgpdm_v0_hw *hw = (struct hgpdm_v0_hw *)dev->hw;
if ((!dev->opened) || (dev->dsleep)) {
return RET_ERR;
}
if (irq_flag & PDM_IRQ_FLAG_DMA_HF) {
hw->DMACON &= ~ LL_PDM_DMACON_HF_IE_EN(1);
}
if (irq_flag & PDM_IRQ_FLAG_DMA_OV) {
hw->DMACON &= ~ LL_PDM_DMACON_OV_IE_EN(1);
}
return RET_OK;
}
static int32 hgpdm_v0_ioctl(struct pdm_device *pdm, enum pdm_ioctl_cmd ioctl_cmd, uint32 param) {
int32 ret_val = RET_OK;
struct hgpdm_v0 *dev = (struct hgpdm_v0 *)pdm;
struct hgpdm_v0_hw *hw = (struct hgpdm_v0_hw *)dev->hw;
if ((!dev->opened) || (dev->dsleep)) {
return RET_ERR;
}
switch (ioctl_cmd) {
case (PDM_IOCTL_CMD_LR_CHANNEL_INTERCHANGE):
ret_val = hgpdm_v0_lr_channel_interchange(hw, param);
break;
default:
ret_val = -ENOTSUPP;
break;
}
return ret_val;
}
static const struct pdm_hal_ops pdm_ops = {
.open = hgpdm_v0_open,
.read = hgpdm_v0_read,
.close = hgpdm_v0_close,
.ioctl = hgpdm_v0_ioctl,
.request_irq = hgpdm_v0_request_irq,
.release_irq = hgpdm_v0_release_irq,
#ifdef CONFIG_SLEEP
.ops.suspend = hgpdm_v0_suspend,
.ops.resume = hgpdm_v0_resume,
#endif
};
int32 hgpdm_v0_attach(uint32 dev_id, struct hgpdm_v0 *pdm) {
pdm->opened = 0;
pdm->dsleep = 0;
pdm->irq_hdl = NULL;
pdm->irq_data = 0;
pdm->dev.dev.ops =(const struct devobj_ops *)&pdm_ops;
#ifdef CONFIG_SLEEP
os_mutex_init(&pdm->bp_suspend_lock);
os_mutex_init(&pdm->bp_resume_lock);
#endif
irq_disable(pdm->irq_num);
dev_register(dev_id, (struct dev_obj *)pdm);
return RET_OK;
}