drivers: mipi dbi: smartbond: Add support for PM
This commit should add all the functionality needed for the MIPI DBI driver to work when PM is enabled. Signed-off-by: Ioannis Karachalios <ioannis.karachalios.px@renesas.com>
This commit is contained in:
parent
8742e24760
commit
58b9facbd1
2 changed files with 39 additions and 61 deletions
|
@ -34,4 +34,13 @@ config LV_Z_POINTER_INPUT_MSGQ_COUNT
|
||||||
|
|
||||||
endif # INPUT
|
endif # INPUT
|
||||||
|
|
||||||
|
#if PM || PM_DEVICE
|
||||||
|
|
||||||
|
# Increase stack size to avoid raising usage-fault
|
||||||
|
# exceptions due to stack overflow.
|
||||||
|
config IDLE_STACK_SIZE
|
||||||
|
default 2048
|
||||||
|
|
||||||
|
#endif # PM || PM_DEVICE
|
||||||
|
|
||||||
endif # BOARD_DA1469X_DK_PRO
|
endif # BOARD_DA1469X_DK_PRO
|
||||||
|
|
|
@ -62,6 +62,10 @@ struct mipi_dbi_smartbond_data {
|
||||||
struct k_sem sync_sem;
|
struct k_sem sync_sem;
|
||||||
/* Flag indicating whether or not an underflow took place */
|
/* Flag indicating whether or not an underflow took place */
|
||||||
volatile bool underflow_flag;
|
volatile bool underflow_flag;
|
||||||
|
#if defined(CONFIG_PM_DEVICE) || defined(CONFIG_PM_DEVICE_RUNTIME)
|
||||||
|
/* Flag to designate whether or not a frame update is in progress */
|
||||||
|
bool is_active;
|
||||||
|
#endif
|
||||||
/* Layer settings */
|
/* Layer settings */
|
||||||
lcdc_smartbond_layer_cfg layer;
|
lcdc_smartbond_layer_cfg layer;
|
||||||
};
|
};
|
||||||
|
@ -80,44 +84,20 @@ struct mipi_dbi_smartbond_config {
|
||||||
/* Mark the device is is progress and so it's not allowed to enter the sleep state. */
|
/* Mark the device is is progress and so it's not allowed to enter the sleep state. */
|
||||||
static void mipi_dbi_pm_get(const struct device *dev)
|
static void mipi_dbi_pm_get(const struct device *dev)
|
||||||
{
|
{
|
||||||
#if CONFIG_PM_DEVICE
|
#ifdef CONFIG_PM_DEVICE
|
||||||
/*
|
struct mipi_dbi_smartbond_data *data = dev->data;
|
||||||
* By marking the device as busy, PM will not communicate PM events
|
|
||||||
* to the device via mipi_dbi_smartbond_pm_action. It's OK if PM is
|
data->is_active = true;
|
||||||
* not used at all. Executing a single frame requires waiting for
|
|
||||||
* the frame to be completed. As such, the system might enter the idle
|
|
||||||
* state if no other tasks are pending and for as long as the frame is
|
|
||||||
* being sent.
|
|
||||||
*
|
|
||||||
* XXX: Another option would be to use a flag and mark when the controller
|
|
||||||
* is in progress so a negative value other than -ENOSYS, -ENOTSUP or
|
|
||||||
* -EALREADY is returned in mipi_dbi_smartbond_pm_action. Sideffect
|
|
||||||
* of this approach is that the sleep state will be aborted at all,
|
|
||||||
* though the system could enter a low-power state, instead (see comment
|
|
||||||
* below on how to achieve a low-power state).
|
|
||||||
*/
|
|
||||||
pm_device_busy_set(dev);
|
|
||||||
#endif
|
|
||||||
#if CONFIG_PM
|
|
||||||
/*
|
|
||||||
* LCDC controller resides in PD_SYS which is turned off when the system enters
|
|
||||||
* the extended sleep state. By calling this API, a reference counter is
|
|
||||||
* incremented, designating that the specific power domain should not be turned off.
|
|
||||||
* As a result, a low-power state (i.e. ARM WFI) will be selected, instead (when the
|
|
||||||
* system is idle).
|
|
||||||
*/
|
|
||||||
(void)da1469x_pd_acquire_noconf(MCU_PD_DOMAIN_SYS);
|
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Mark that device is inactive and so it's allowed to enter the sleep state */
|
/* Mark that device is inactive and so it's allowed to enter the sleep state */
|
||||||
static void mipi_dbi_pm_put(const struct device *dev)
|
static void mipi_dbi_pm_put(const struct device *dev)
|
||||||
{
|
{
|
||||||
#if CONFIG_PM_DEVICE
|
#ifdef CONFIG_PM_DEVICE
|
||||||
(void)pm_device_busy_clear(dev);
|
struct mipi_dbi_smartbond_data *data = dev->data;
|
||||||
#endif
|
|
||||||
#if CONFIG_PM
|
data->is_active = false;
|
||||||
(void)da1469x_pd_release_nowait(MCU_PD_DOMAIN_SYS);
|
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -488,7 +468,7 @@ static int mipi_dbi_smartbond_resume(const struct device *dev)
|
||||||
return mipi_dbi_smartbond_configure(dev);
|
return mipi_dbi_smartbond_configure(dev);
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifdef CONFIG_PM_DEVICE
|
#if defined(CONFIG_PM_DEVICE) || defined(CONFIG_PM_DEVICE_RUNTIME)
|
||||||
static int mipi_dbi_smartbond_suspend(const struct device *dev)
|
static int mipi_dbi_smartbond_suspend(const struct device *dev)
|
||||||
{
|
{
|
||||||
const struct mipi_dbi_smartbond_config *config = dev->config;
|
const struct mipi_dbi_smartbond_config *config = dev->config;
|
||||||
|
@ -508,31 +488,26 @@ static int mipi_dbi_smartbond_suspend(const struct device *dev)
|
||||||
|
|
||||||
static int mipi_dbi_smartbond_pm_action(const struct device *dev, enum pm_device_action action)
|
static int mipi_dbi_smartbond_pm_action(const struct device *dev, enum pm_device_action action)
|
||||||
{
|
{
|
||||||
int ret = 0;
|
/* Initialize with an error code that should abort sleeping */
|
||||||
|
int ret = -EBUSY;
|
||||||
|
struct mipi_dbi_smartbond_data *data = dev->data;
|
||||||
|
|
||||||
switch (action) {
|
switch (action) {
|
||||||
case PM_DEVICE_ACTION_SUSPEND:
|
case PM_DEVICE_ACTION_SUSPEND:
|
||||||
(void)mipi_dbi_smartbond_suspend(dev);
|
/* Sleep is only allowed when there are no active LCDC operations */
|
||||||
|
if (!data->is_active) {
|
||||||
#if CONFIG_PM_DEVICE_RUNTIME && CONFIG_PM
|
(void)mipi_dbi_smartbond_suspend(dev);
|
||||||
da1469x_pd_release_nowait(MCU_PD_DOMAIN_SYS);
|
ret = 0;
|
||||||
#endif
|
|
||||||
break;
|
|
||||||
case PM_DEVICE_ACTION_RESUME:
|
|
||||||
ret = mipi_dbi_smartbond_resume(dev);
|
|
||||||
|
|
||||||
#if CONFIG_PM_DEVICE_RUNTIME && CONFIG_PM
|
|
||||||
/*
|
|
||||||
* If resume succeeded, prevent the system from entering the
|
|
||||||
* extended sleep state (Instead, use __WFI). If not, do not
|
|
||||||
* as users should not suspend the device and thus releasing
|
|
||||||
* PD_SYS.
|
|
||||||
*/
|
|
||||||
if (ret == 0) {
|
|
||||||
da1469x_pd_acquire_noconf(MCU_PD_DOMAIN_SYS);
|
|
||||||
}
|
}
|
||||||
#endif
|
break;
|
||||||
break;
|
case PM_DEVICE_ACTION_RESUME:
|
||||||
|
__ASSERT_NO_MSG(!data->is_active);
|
||||||
|
/*
|
||||||
|
* The resume error code should not be taken into consideration
|
||||||
|
* by the PM subsystem.
|
||||||
|
*/
|
||||||
|
ret = mipi_dbi_smartbond_resume(dev);
|
||||||
|
break;
|
||||||
default:
|
default:
|
||||||
return -ENOTSUP;
|
return -ENOTSUP;
|
||||||
}
|
}
|
||||||
|
@ -570,18 +545,12 @@ static int mipi_dbi_smartbond_init(const struct device *dev)
|
||||||
pm_device_init_suspended(dev);
|
pm_device_init_suspended(dev);
|
||||||
|
|
||||||
ret = pm_device_runtime_enable(dev);
|
ret = pm_device_runtime_enable(dev);
|
||||||
if ((ret < 0) && (ret != -ENOSYS)) {
|
|
||||||
return ret;
|
|
||||||
}
|
|
||||||
#else
|
#else
|
||||||
/* Resme if either PM is not used at all or if PM without runtime is used. */
|
/* Resme if either PM is not used at all or if PM without runtime is used. */
|
||||||
ret = mipi_dbi_smartbond_resume(dev);
|
ret = mipi_dbi_smartbond_resume(dev);
|
||||||
if (ret < 0) {
|
|
||||||
return ret;
|
|
||||||
}
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
return 0;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
static struct mipi_dbi_driver_api mipi_dbi_smartbond_driver_api = {
|
static struct mipi_dbi_driver_api mipi_dbi_smartbond_driver_api = {
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue