drivers: dai: sai: support pm runtime operations
Add support for PM runtime operations. Signed-off-by: Laurentiu Mihalcea <laurentiu.mihalcea@nxp.com>
This commit is contained in:
parent
3fbb7f4403
commit
d3aa170963
1 changed files with 75 additions and 14 deletions
|
|
@ -7,6 +7,8 @@
|
|||
#include <zephyr/drivers/dai.h>
|
||||
#include <zephyr/device.h>
|
||||
#include <zephyr/kernel.h>
|
||||
#include <zephyr/pm/device_runtime.h>
|
||||
#include <zephyr/pm/device.h>
|
||||
|
||||
#include "sai.h"
|
||||
|
||||
|
|
@ -373,6 +375,12 @@ static int sai_config_set(const struct device *dev,
|
|||
tx_config->syncMode = sai_cfg->tx_sync_mode;
|
||||
rx_config->syncMode = sai_cfg->rx_sync_mode;
|
||||
|
||||
ret = pm_device_runtime_get(dev);
|
||||
if (ret < 0) {
|
||||
LOG_ERR("failed to get() SAI device: %d", ret);
|
||||
return ret;
|
||||
}
|
||||
|
||||
/* commit configuration */
|
||||
SAI_RxSetConfig(UINT_TO_I2S(data->regmap), rx_config);
|
||||
SAI_TxSetConfig(UINT_TO_I2S(data->regmap), tx_config);
|
||||
|
|
@ -398,6 +406,7 @@ static int sai_config_set(const struct device *dev,
|
|||
ret = sai_mclk_config(dev, tx_config->bitClock.bclkSource, bespoke);
|
||||
if (ret < 0) {
|
||||
LOG_ERR("failed to set MCLK configuration");
|
||||
pm_device_runtime_put(dev);
|
||||
return ret;
|
||||
}
|
||||
#endif /* CONFIG_SAI_HAS_MCLK_CONFIG_OPTION */
|
||||
|
|
@ -432,7 +441,7 @@ static int sai_config_set(const struct device *dev,
|
|||
|
||||
sai_dump_register_data(data->regmap);
|
||||
|
||||
return 0;
|
||||
return pm_device_runtime_put(dev);
|
||||
}
|
||||
|
||||
/* SOF note: please be very careful with this function as it does
|
||||
|
|
@ -622,7 +631,7 @@ out_dmareq_disable:
|
|||
|
||||
irq_disable(cfg->irq);
|
||||
|
||||
return 0;
|
||||
return pm_device_runtime_put(dev);
|
||||
}
|
||||
|
||||
/* notes:
|
||||
|
|
@ -723,6 +732,12 @@ static int sai_trigger_start(const struct device *dev,
|
|||
|
||||
LOG_DBG("start on direction %d", dir);
|
||||
|
||||
ret = pm_device_runtime_get(dev);
|
||||
if (ret < 0) {
|
||||
LOG_ERR("failed to get() SAI device: %d", ret);
|
||||
return ret;
|
||||
}
|
||||
|
||||
sai_tx_rx_sw_reset(data, cfg, dir);
|
||||
|
||||
irq_enable(cfg->irq);
|
||||
|
|
@ -812,27 +827,71 @@ static const struct dai_driver_api sai_api = {
|
|||
.remove = sai_remove,
|
||||
};
|
||||
|
||||
static int sai_clks_enable_disable(const struct device *dev, bool enable)
|
||||
{
|
||||
int i, ret;
|
||||
const struct sai_config *cfg;
|
||||
void *clk_id;
|
||||
|
||||
cfg = dev->config;
|
||||
|
||||
for (i = 0; i < cfg->clk_data.clock_num; i++) {
|
||||
clk_id = UINT_TO_POINTER(cfg->clk_data.clocks[i]);
|
||||
|
||||
if (enable) {
|
||||
ret = clock_control_on(cfg->clk_data.dev, clk_id);
|
||||
} else {
|
||||
ret = clock_control_off(cfg->clk_data.dev, clk_id);
|
||||
}
|
||||
|
||||
if (ret < 0) {
|
||||
LOG_ERR("failed to gate/ungate clock %u: %d",
|
||||
cfg->clk_data.clocks[i], ret);
|
||||
return ret;
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
__maybe_unused static int sai_pm_action(const struct device *dev,
|
||||
enum pm_device_action action)
|
||||
{
|
||||
bool enable = true;
|
||||
|
||||
switch (action) {
|
||||
case PM_DEVICE_ACTION_RESUME:
|
||||
break;
|
||||
case PM_DEVICE_ACTION_SUSPEND:
|
||||
enable = false;
|
||||
break;
|
||||
case PM_DEVICE_ACTION_TURN_ON:
|
||||
case PM_DEVICE_ACTION_TURN_OFF:
|
||||
return 0;
|
||||
default:
|
||||
return -ENOTSUP;
|
||||
}
|
||||
|
||||
return sai_clks_enable_disable(dev, enable);
|
||||
}
|
||||
|
||||
static int sai_init(const struct device *dev)
|
||||
{
|
||||
const struct sai_config *cfg;
|
||||
struct sai_data *data;
|
||||
int i, ret;
|
||||
int ret;
|
||||
|
||||
cfg = dev->config;
|
||||
data = dev->data;
|
||||
|
||||
device_map(&data->regmap, cfg->regmap_phys, cfg->regmap_size, K_MEM_CACHE_NONE);
|
||||
|
||||
/* enable clocks if any */
|
||||
for (i = 0; i < cfg->clk_data.clock_num; i++) {
|
||||
ret = clock_control_on(cfg->clk_data.dev,
|
||||
UINT_TO_POINTER(cfg->clk_data.clocks[i]));
|
||||
if (ret < 0) {
|
||||
return ret;
|
||||
}
|
||||
|
||||
LOG_DBG("clock %s has been ungated", cfg->clk_data.clock_names[i]);
|
||||
#ifndef CONFIG_PM_DEVICE_RUNTIME
|
||||
ret = sai_clks_enable_disable(dev, true);
|
||||
if (ret < 0) {
|
||||
return ret;
|
||||
}
|
||||
#endif /* CONFIG_PM_DEVICE_RUNTIME */
|
||||
|
||||
/* note: optional operation so -ENOENT is allowed (i.e: we
|
||||
* allow the default state to not be defined)
|
||||
|
|
@ -849,7 +908,7 @@ static int sai_init(const struct device *dev)
|
|||
/* register ISR */
|
||||
cfg->irq_config();
|
||||
|
||||
return 0;
|
||||
return pm_device_runtime_enable(dev);
|
||||
}
|
||||
|
||||
#define SAI_INIT(inst) \
|
||||
|
|
@ -931,7 +990,9 @@ static struct sai_data sai_data_##inst = { \
|
|||
.cfg.dai_index = DT_INST_PROP_OR(inst, dai_index, 0), \
|
||||
}; \
|
||||
\
|
||||
DEVICE_DT_INST_DEFINE(inst, &sai_init, NULL, \
|
||||
PM_DEVICE_DT_INST_DEFINE(inst, sai_pm_action); \
|
||||
\
|
||||
DEVICE_DT_INST_DEFINE(inst, &sai_init, PM_DEVICE_DT_INST_GET(inst), \
|
||||
&sai_data_##inst, &sai_config_##inst, \
|
||||
POST_KERNEL, CONFIG_DAI_INIT_PRIORITY, \
|
||||
&sai_api); \
|
||||
|
|
|
|||
Loading…
Reference in a new issue