Commit 2958f691 authored by Ioannis Karachalios's avatar Ioannis Karachalios Committed by Anas Nashif
Browse files

drivers: mipi_dbi: smartbond: Optimize driver PM



This commit should optimize the way the device is allowed
to enter the suspended state. Instead of returning a PM
error code to abort the PM process, the standby power state
is constrained as long as the device is not allowed to enter
suspension. With that approach, acquiring PD_SYS is not needed
when in PM device runtime mode.

Signed-off-by: default avatarIoannis Karachalios <ioannis.karachalios.px@renesas.com>
parent 33665348
Loading
Loading
Loading
Loading
+21 −43
Original line number Diff line number Diff line
@@ -14,6 +14,7 @@
#include <zephyr/device.h>
#include <zephyr/pm/device.h>
#include <zephyr/pm/device_runtime.h>
#include <zephyr/pm/policy.h>
#include <DA1469xAB.h>
#include <zephyr/drivers/clock_control.h>
#include <zephyr/drivers/clock_control/smartbond_clock_control.h>
@@ -62,10 +63,6 @@ struct mipi_dbi_smartbond_data {
	struct k_sem sync_sem;
	/* Flag indicating whether or not an underflow took place */
	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 */
	lcdc_smartbond_layer_cfg layer;
};
@@ -82,23 +79,20 @@ struct mipi_dbi_smartbond_config {
};

/* 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 inline void mipi_dbi_smartbond_pm_policy_state_lock_get(void)
{
#ifdef CONFIG_PM_DEVICE
	struct mipi_dbi_smartbond_data *data = dev->data;

	data->is_active = true;
#endif
	/*
	 * Prevent the SoC from etering the normal sleep state as PDC does not support
	 * waking up the application core following LCDC events.
	 */
	pm_policy_state_lock_get(PM_STATE_STANDBY, PM_ALL_SUBSTATES);
}

/* 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 inline void mipi_dbi_smartbond_pm_policy_state_lock_put(void)
{
#ifdef CONFIG_PM_DEVICE
	struct mipi_dbi_smartbond_data *data = dev->data;

	data->is_active = false;
#endif
	/* Allow the SoC to enter the nornmal sleep state once LCDC is inactive */
	pm_policy_state_lock_put(PM_STATE_STANDBY, PM_ALL_SUBSTATES);
}

/* Helper function to trigger the LCDC fetching data from frame buffer to the connected display */
@@ -217,6 +211,8 @@ static int mipi_dbi_smartbond_command_read(const struct device *dev,

	k_sem_take(&data->device_sem, K_FOREVER);

	mipi_dbi_smartbond_pm_policy_state_lock_get();

	/*
	 * Add an arbitrary valid color format to satisfy subroutine. The MIPI DBI command/data
	 * engine should not be affected.
@@ -283,6 +279,8 @@ _mipi_dbi_read_exit:
		LOG_ERR("Could not apply MIPI DBI pins' default state (%d)", ret);
	}

	mipi_dbi_smartbond_pm_policy_state_lock_put();

	k_sem_give(&data->device_sem);

	return ret;
@@ -300,7 +298,7 @@ static int mipi_dbi_smartbond_command_write(const struct device *dev,

	k_sem_take(&data->device_sem, K_FOREVER);

	mipi_dbi_pm_get(dev);
	mipi_dbi_smartbond_pm_policy_state_lock_get();

	/*
	 * Add an arbitrary valid color format to satisfy subroutine. The MIPI DBI command/data
@@ -321,7 +319,7 @@ static int mipi_dbi_smartbond_command_write(const struct device *dev,
		da1469x_lcdc_send_cmd_data(false, data_buf, len);
	}

	mipi_dbi_pm_put(dev);
	mipi_dbi_smartbond_pm_policy_state_lock_put();

	k_sem_give(&data->device_sem);

@@ -349,7 +347,7 @@ static int mipi_dbi_smartbond_write_display(const struct device *dev,

	k_sem_take(&data->device_sem, K_FOREVER);

	mipi_dbi_pm_get(dev);
	mipi_dbi_smartbond_pm_policy_state_lock_get();

	/*
	 * Mainly check if the frame generator is busy with a pending frame update (might happen
@@ -388,7 +386,7 @@ static int mipi_dbi_smartbond_write_display(const struct device *dev,

_mipi_dbi_write_exit:

	mipi_dbi_pm_put(dev);
	mipi_dbi_smartbond_pm_policy_state_lock_put();

	k_sem_give(&data->device_sem);

@@ -488,33 +486,14 @@ 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)
{
	/* Initialize with an error code that should abort sleeping */
	int ret = -EBUSY;
	struct mipi_dbi_smartbond_data *data = dev->data;
	int ret = 0;

	switch (action) {
	case PM_DEVICE_ACTION_SUSPEND:
		/* Sleep is only allowed when there are no active LCDC operations */
		if (!data->is_active) {
		/* A non-zero value should not affect sleep */
		(void)mipi_dbi_smartbond_suspend(dev);
			/*
			 * Once the display block is turned off, its power domain
			 * can be released as well.
			 */
			da1469x_pd_release_nowait(MCU_PD_DOMAIN_SYS);
			ret = 0;
		}
		break;
	case PM_DEVICE_ACTION_RESUME:
		__ASSERT_NO_MSG(!data->is_active);

		/*
		 * Although PD_SYS should already be turned on, make sure LCD controller's
		 * power domain is up and running before accessing the display block.
		 * Acquiring PD_SYS is mandatory when in PM runtime mode.
		 */
		da1469x_pd_acquire(MCU_PD_DOMAIN_SYS);

		/*
		 * The resume error code should not be taken into consideration
		 * by the PM subsystem.
@@ -559,7 +538,6 @@ static int mipi_dbi_smartbond_init(const struct device *dev)

	ret = pm_device_runtime_enable(dev);
#else
	da1469x_pd_acquire(MCU_PD_DOMAIN_SYS);
	/* Resme if either PM is not used at all or if PM without runtime is used. */
	ret = mipi_dbi_smartbond_resume(dev);
#endif