[PATCH] drm/mipi-dsi: Introduce macros to create mipi_dsi_*_multi functions

From: Tejas Vipin
Date: Tue Jul 16 2024 - 09:32:12 EST


Introduce 2 new macros, DSI_CTX_NO_OP and MIPI_DSI_ADD_MULTI_VARIANT.

DSI_CTX_NO_OP calls a function only if the context passed to it hasn't
encountered any errors. It is a generic form of what mipi_dsi_msleep
does.

MIPI_DSI_ADD_MULTI_VARIANT defines a multi style function of any
mipi_dsi function that follows a certain style. This allows us to
greatly reduce the amount of redundant code written for each multi
function. It reduces the overhead for a developer introducing new
mipi_dsi_*_multi functions.

Signed-off-by: Tejas Vipin <tejasvipin76@xxxxxxxxx>
---
drivers/gpu/drm/drm_mipi_dsi.c | 286 ++++++++++-----------------------
1 file changed, 83 insertions(+), 203 deletions(-)

diff --git a/drivers/gpu/drm/drm_mipi_dsi.c b/drivers/gpu/drm/drm_mipi_dsi.c
index a471c46f5ca6..53880b486f22 100644
--- a/drivers/gpu/drm/drm_mipi_dsi.c
+++ b/drivers/gpu/drm/drm_mipi_dsi.c
@@ -1430,214 +1430,94 @@ int mipi_dsi_dcs_get_display_brightness_large(struct mipi_dsi_device *dsi,
EXPORT_SYMBOL(mipi_dsi_dcs_get_display_brightness_large);

/**
- * mipi_dsi_picture_parameter_set_multi() - transmit the DSC PPS to the peripheral
- * @ctx: Context for multiple DSI transactions
- * @pps: VESA DSC 1.1 Picture Parameter Set
- *
- * Like mipi_dsi_picture_parameter_set() but deals with errors in a way that
- * makes it convenient to make several calls in a row.
- */
-void mipi_dsi_picture_parameter_set_multi(struct mipi_dsi_multi_context *ctx,
- const struct drm_dsc_picture_parameter_set *pps)
-{
- struct mipi_dsi_device *dsi = ctx->dsi;
- struct device *dev = &dsi->dev;
- ssize_t ret;
-
- if (ctx->accum_err)
- return;
-
- ret = mipi_dsi_picture_parameter_set(dsi, pps);
- if (ret < 0) {
- ctx->accum_err = ret;
- dev_err(dev, "sending PPS failed: %d\n",
- ctx->accum_err);
- }
-}
-EXPORT_SYMBOL(mipi_dsi_picture_parameter_set_multi);
-
-/**
- * mipi_dsi_compression_mode_ext_multi() - enable/disable DSC on the peripheral
- * @ctx: Context for multiple DSI transactions
- * @enable: Whether to enable or disable the DSC
- * @algo: Selected compression algorithm
- * @pps_selector: Select PPS from the table of pre-stored or uploaded PPS entries
- *
- * Like mipi_dsi_compression_mode_ext() but deals with errors in a way that
- * makes it convenient to make several calls in a row.
- */
-void mipi_dsi_compression_mode_ext_multi(struct mipi_dsi_multi_context *ctx,
- bool enable,
- enum mipi_dsi_compression_algo algo,
- unsigned int pps_selector)
-{
- struct mipi_dsi_device *dsi = ctx->dsi;
- struct device *dev = &dsi->dev;
- ssize_t ret;
-
- if (ctx->accum_err)
- return;
-
- ret = mipi_dsi_compression_mode_ext(dsi, enable, algo, pps_selector);
- if (ret < 0) {
- ctx->accum_err = ret;
- dev_err(dev, "sending COMPRESSION_MODE failed: %d\n",
- ctx->accum_err);
- }
-}
-EXPORT_SYMBOL(mipi_dsi_compression_mode_ext_multi);
-
-/**
- * mipi_dsi_dcs_nop_multi() - send DCS NOP packet
- * @ctx: Context for multiple DSI transactions
- *
- * Like mipi_dsi_dcs_nop() but deals with errors in a way that
- * makes it convenient to make several calls in a row.
+ * DSI_CTX_NO_OP() - Calls a function only if no previous errors have
+ * occurred.
+ * @func: The function call that needs to happen.
+ * @ctx: Context whose accum_err is checked to decide if the function
+ * should run.
*/
-void mipi_dsi_dcs_nop_multi(struct mipi_dsi_multi_context *ctx)
-{
- struct mipi_dsi_device *dsi = ctx->dsi;
- struct device *dev = &dsi->dev;
- ssize_t ret;
-
- if (ctx->accum_err)
- return;
-
- ret = mipi_dsi_dcs_nop(dsi);
- if (ret < 0) {
- ctx->accum_err = ret;
- dev_err(dev, "sending DCS NOP failed: %d\n",
- ctx->accum_err);
- }
-}
-EXPORT_SYMBOL(mipi_dsi_dcs_nop_multi);
+#define DSI_CTX_NO_OP(func, ctx) \
+ do { \
+ if (!(ctx)->accum_err) \
+ func; \
+ } while (0)

/**
- * mipi_dsi_dcs_enter_sleep_mode_multi() - send DCS ENTER_SLEEP_MODE packet
- * @ctx: Context for multiple DSI transactions
+ * MIPI_DSI_ADD_MULTI_VARIANT() - Define the multi variant of
+ * an existing MIPI DSI function.
+ * @proto: The prototype of the desired multi variant
+ * @err: The error string used by dev_err on an error occurring.
+ * @inner_func: Identifier of the function being wrapped
+ * @...: Any arguments that need to be passed to inner_func
*
- * Like mipi_dsi_dcs_enter_sleep_mode() but deals with errors in a way that
- * makes it convenient to make several calls in a row.
*/
-void mipi_dsi_dcs_enter_sleep_mode_multi(struct mipi_dsi_multi_context *ctx)
-{
- struct mipi_dsi_device *dsi = ctx->dsi;
- struct device *dev = &dsi->dev;
- ssize_t ret;
-
- if (ctx->accum_err)
- return;
-
- ret = mipi_dsi_dcs_enter_sleep_mode(dsi);
- if (ret < 0) {
- ctx->accum_err = ret;
- dev_err(dev, "sending DCS ENTER_SLEEP_MODE failed: %d\n",
- ctx->accum_err);
- }
-}
-EXPORT_SYMBOL(mipi_dsi_dcs_enter_sleep_mode_multi);
-
-/**
- * mipi_dsi_dcs_exit_sleep_mode_multi() - send DCS EXIT_SLEEP_MODE packet
- * @ctx: Context for multiple DSI transactions
- *
- * Like mipi_dsi_dcs_exit_sleep_mode() but deals with errors in a way that
- * makes it convenient to make several calls in a row.
- */
-void mipi_dsi_dcs_exit_sleep_mode_multi(struct mipi_dsi_multi_context *ctx)
-{
- struct mipi_dsi_device *dsi = ctx->dsi;
- struct device *dev = &dsi->dev;
- ssize_t ret;
-
- if (ctx->accum_err)
- return;
-
- ret = mipi_dsi_dcs_exit_sleep_mode(dsi);
- if (ret < 0) {
- ctx->accum_err = ret;
- dev_err(dev, "sending DCS EXIT_SLEEP_MODE failed: %d\n",
- ctx->accum_err);
- }
-}
-EXPORT_SYMBOL(mipi_dsi_dcs_exit_sleep_mode_multi);
-
-/**
- * mipi_dsi_dcs_set_display_off_multi() - send DCS SET_DISPLAY_OFF packet
- * @ctx: Context for multiple DSI transactions
- *
- * Like mipi_dsi_dcs_set_display_off() but deals with errors in a way that
- * makes it convenient to make several calls in a row.
- */
-void mipi_dsi_dcs_set_display_off_multi(struct mipi_dsi_multi_context *ctx)
-{
- struct mipi_dsi_device *dsi = ctx->dsi;
- struct device *dev = &dsi->dev;
- ssize_t ret;
-
- if (ctx->accum_err)
- return;
-
- ret = mipi_dsi_dcs_set_display_off(dsi);
- if (ret < 0) {
- ctx->accum_err = ret;
- dev_err(dev, "sending DCS SET_DISPLAY_OFF failed: %d\n",
- ctx->accum_err);
- }
-}
-EXPORT_SYMBOL(mipi_dsi_dcs_set_display_off_multi);
-
-/**
- * mipi_dsi_dcs_set_display_on_multi() - send DCS SET_DISPLAY_ON packet
- * @ctx: Context for multiple DSI transactions
- *
- * Like mipi_dsi_dcs_set_display_on() but deals with errors in a way that
- * makes it convenient to make several calls in a row.
- */
-void mipi_dsi_dcs_set_display_on_multi(struct mipi_dsi_multi_context *ctx)
-{
- struct mipi_dsi_device *dsi = ctx->dsi;
- struct device *dev = &dsi->dev;
- ssize_t ret;
-
- if (ctx->accum_err)
- return;
-
- ret = mipi_dsi_dcs_set_display_on(dsi);
- if (ret < 0) {
- ctx->accum_err = ret;
- dev_err(dev, "sending DCS SET_DISPLAY_ON failed: %d\n",
- ctx->accum_err);
- }
-}
-EXPORT_SYMBOL(mipi_dsi_dcs_set_display_on_multi);
-
-/**
- * mipi_dsi_dcs_set_tear_on_multi() - send DCS SET_TEAR_ON packet
- * @ctx: Context for multiple DSI transactions
- * @mode: the Tearing Effect Output Line mode
- *
- * Like mipi_dsi_dcs_set_tear_on() but deals with errors in a way that
- * makes it convenient to make several calls in a row.
- */
-void mipi_dsi_dcs_set_tear_on_multi(struct mipi_dsi_multi_context *ctx,
- enum mipi_dsi_dcs_tear_mode mode)
-{
- struct mipi_dsi_device *dsi = ctx->dsi;
- struct device *dev = &dsi->dev;
- ssize_t ret;
-
- if (ctx->accum_err)
- return;
-
- ret = mipi_dsi_dcs_set_tear_on(dsi, mode);
- if (ret < 0) {
- ctx->accum_err = ret;
- dev_err(dev, "sending DCS SET_TEAR_ON failed: %d\n",
- ctx->accum_err);
- }
-}
-EXPORT_SYMBOL(mipi_dsi_dcs_set_tear_on_multi);
+#define MIPI_DSI_ADD_MULTI_VARIANT(proto, err, inner_func, ...) \
+proto { \
+ struct mipi_dsi_device *dsi = ctx->dsi; \
+ struct device *dev = &dsi->dev; \
+ int ret; \
+ \
+ if (ctx->accum_err) \
+ return; \
+ \
+ ret = inner_func(dsi, ##__VA_ARGS__); \
+ if (ret < 0) { \
+ ctx->accum_err = ret; \
+ dev_err(dev, err, ctx->accum_err); \
+ } \
+} \
+EXPORT_SYMBOL(inner_func##_multi);
+
+MIPI_DSI_ADD_MULTI_VARIANT(
+ void mipi_dsi_picture_parameter_set_multi(
+ struct mipi_dsi_multi_context *ctx,
+ const struct drm_dsc_picture_parameter_set *pps),
+ "sending PPS failed: %d\n",
+ mipi_dsi_picture_parameter_set, pps);
+
+MIPI_DSI_ADD_MULTI_VARIANT(
+ void mipi_dsi_compression_mode_ext_multi(
+ struct mipi_dsi_multi_context *ctx, bool enable,
+ enum mipi_dsi_compression_algo algo, unsigned int pps_selector),
+ "sending COMPRESSION_MODE failed: %d\n",
+ mipi_dsi_compression_mode_ext, enable, algo, pps_selector);
+
+MIPI_DSI_ADD_MULTI_VARIANT(
+ void mipi_dsi_dcs_nop_multi(
+ struct mipi_dsi_multi_context *ctx),
+ "sending DCS NOP failed: %d\n",
+ mipi_dsi_dcs_nop);
+
+MIPI_DSI_ADD_MULTI_VARIANT(
+ void mipi_dsi_dcs_enter_sleep_mode_multi(
+ struct mipi_dsi_multi_context *ctx),
+ "sending DCS ENTER_SLEEP_MODE failed: %d\n",
+ mipi_dsi_dcs_enter_sleep_mode);
+
+MIPI_DSI_ADD_MULTI_VARIANT(
+ void mipi_dsi_dcs_exit_sleep_mode_multi(
+ struct mipi_dsi_multi_context *ctx),
+ "sending DCS EXIT_SLEEP_MODE failed: %d\n",
+ mipi_dsi_dcs_exit_sleep_mode);
+
+MIPI_DSI_ADD_MULTI_VARIANT(
+ void mipi_dsi_dcs_set_display_off_multi(
+ struct mipi_dsi_multi_context *ctx),
+ "sending DCS SET_DISPLAY_OFF failed: %d\n",
+ mipi_dsi_dcs_set_display_off);
+
+MIPI_DSI_ADD_MULTI_VARIANT(
+ void mipi_dsi_dcs_set_display_on_multi(
+ struct mipi_dsi_multi_context *ctx),
+ "sending DCS SET_DISPLAY_ON failed: %d\n",
+ mipi_dsi_dcs_set_display_on);
+
+MIPI_DSI_ADD_MULTI_VARIANT(
+ void mipi_dsi_dcs_set_tear_on_multi(
+ struct mipi_dsi_multi_context *ctx,
+ enum mipi_dsi_dcs_tear_mode mode),
+ "sending DCS SET_TEAR_ON failed: %d\n",
+ mipi_dsi_dcs_set_tear_on, mode);

static int mipi_dsi_drv_probe(struct device *dev)
{
--
2.45.2