Skip to content

Commit

Permalink
FROMGIT: drm/mipi-dsi: Introduce mipi_dsi_*_write_seq_multi()
Browse files Browse the repository at this point in the history
The current mipi_dsi_*_write_seq() macros are non-intutitive because
they contain a hidden "return" statement that will return out of the
_caller_ of the macro. Let's mark them as deprecated and instead
introduce some new macros that are more intuitive.

These new macros are less optimal when an error occurs but should
behave more optimally when there is no error. Specifically these new
macros cause smaller code to get generated and the code size savings
(less to fetch from RAM, less cache space used, less RAM used) are
important. Since the error case isn't something we need to optimize
for and these new macros are easier to understand and more flexible,
they should be used.

After converting to use these new functions, one example shows some
nice savings while also being easier to understand.

$ scripts/bloat-o-meter \
  ...after/panel-novatek-nt36672e.ko \
  ...ctx/panel-novatek-nt36672e.ko
add/remove: 0/0 grow/shrink: 0/1 up/down: 0/-988 (-988)
Function                                     old     new   delta
nt36672e_1080x2408_60hz_init                6236    5248    -988
Total: Before=10651, After=9663, chg -9.28%

Reviewed-by: Neil Armstrong <[email protected]>
Reviewed-by: Linus Walleij <[email protected]>
Signed-off-by: Douglas Anderson <[email protected]>
Link: https://lore.kernel.org/r/20240514102056.v5.5.Ie94246c30fe95101e0e26dd5f96e976dbeb8f242@changeid
Signed-off-by: Neil Armstrong <[email protected]>
Link: https://patchwork.freedesktop.org/patch/msgid/20240514102056.v5.5.Ie94246c30fe95101e0e26dd5f96e976dbeb8f242@changeid
(cherry picked from commit 966e397)
Signed-off-by: Neil Armstrong <[email protected]>
  • Loading branch information
dianders authored and barni2000 committed Jul 25, 2024
1 parent cc89d56 commit 7c5c096
Show file tree
Hide file tree
Showing 3 changed files with 136 additions and 0 deletions.
18 changes: 18 additions & 0 deletions Documentation/gpu/todo.rst
Original file line number Diff line number Diff line change
Expand Up @@ -507,6 +507,24 @@ Contact: Douglas Anderson <[email protected]>

Level: Starter/Intermediate

Transition away from using mipi_dsi_*_write_seq()
-------------------------------------------------

The macros mipi_dsi_generic_write_seq() and mipi_dsi_dcs_write_seq() are
non-intuitive because, if there are errors, they return out of the *caller's*
function. We should move all callers to use mipi_dsi_generic_write_seq_multi()
and mipi_dsi_dcs_write_seq_multi() macros instead.

Once all callers are transitioned, the macros and the functions that they call,
mipi_dsi_generic_write_chatty() and mipi_dsi_dcs_write_buffer_chatty(), can
probably be removed. Alternatively, if people feel like the _multi() variants
are overkill for some use cases, we could keep the mipi_dsi_*_write_seq()
variants but change them not to return out of the caller.

Contact: Douglas Anderson <[email protected]>

Level: Starter


Core refactorings
=================
Expand Down
56 changes: 56 additions & 0 deletions drivers/gpu/drm/drm_mipi_dsi.c
Original file line number Diff line number Diff line change
Expand Up @@ -792,6 +792,34 @@ int mipi_dsi_generic_write_chatty(struct mipi_dsi_device *dsi,
}
EXPORT_SYMBOL(mipi_dsi_generic_write_chatty);

/**
* mipi_dsi_generic_write_multi() - mipi_dsi_generic_write_chatty() w/ accum_err
* @ctx: Context for multiple DSI transactions
* @payload: buffer containing the payload
* @size: size of payload buffer
*
* Like mipi_dsi_generic_write_chatty() but deals with errors in a way that
* makes it convenient to make several calls in a row.
*/
void mipi_dsi_generic_write_multi(struct mipi_dsi_multi_context *ctx,
const void *payload, size_t size)
{
struct mipi_dsi_device *dsi = ctx->dsi;
struct device *dev = &dsi->dev;
ssize_t ret;

if (ctx->accum_err)
return;

ret = mipi_dsi_generic_write(dsi, payload, size);
if (ret < 0) {
ctx->accum_err = ret;
dev_err(dev, "sending generic data %*ph failed: %d\n",
(int)size, payload, ctx->accum_err);
}
}
EXPORT_SYMBOL(mipi_dsi_generic_write_multi);

/**
* mipi_dsi_generic_read() - receive data using a generic read packet
* @dsi: DSI peripheral device
Expand Down Expand Up @@ -908,6 +936,34 @@ int mipi_dsi_dcs_write_buffer_chatty(struct mipi_dsi_device *dsi,
}
EXPORT_SYMBOL(mipi_dsi_dcs_write_buffer_chatty);

/**
* mipi_dsi_dcs_write_buffer_multi - mipi_dsi_dcs_write_buffer_chatty() w/ accum_err
* @ctx: Context for multiple DSI transactions
* @data: buffer containing data to be transmitted
* @len: size of transmission buffer
*
* Like mipi_dsi_dcs_write_buffer_chatty() but deals with errors in a way that
* makes it convenient to make several calls in a row.
*/
void mipi_dsi_dcs_write_buffer_multi(struct mipi_dsi_multi_context *ctx,
const void *data, size_t len)
{
struct mipi_dsi_device *dsi = ctx->dsi;
struct device *dev = &dsi->dev;
ssize_t ret;

if (ctx->accum_err)
return;

ret = mipi_dsi_dcs_write_buffer(dsi, data, len);
if (ret < 0) {
ctx->accum_err = ret;
dev_err(dev, "sending dcs data %*ph failed: %d\n",
(int)len, data, ctx->accum_err);
}
}
EXPORT_SYMBOL(mipi_dsi_dcs_write_buffer_multi);

/**
* mipi_dsi_dcs_write() - send DCS write command
* @dsi: DSI peripheral device
Expand Down
62 changes: 62 additions & 0 deletions include/drm/drm_mipi_dsi.h
Original file line number Diff line number Diff line change
Expand Up @@ -197,6 +197,27 @@ struct mipi_dsi_device {
struct drm_dsc_config *dsc;
};

/**
* struct mipi_dsi_multi_context - Context to call multiple MIPI DSI funcs in a row
*/
struct mipi_dsi_multi_context {
/**
* @dsi: Pointer to the MIPI DSI device
*/
struct mipi_dsi_device *dsi;

/**
* @accum_err: Storage for the accumulated error over the multiple calls
*
* Init to 0. If a function encounters an error then the error code
* will be stored here. If you call a function and this points to a
* non-zero value then the function will be a noop. This allows calling
* a function many times in a row and just checking the error at the
* end to see if any of them failed.
*/
int accum_err;
};

#define MIPI_DSI_MODULE_PREFIX "mipi-dsi:"

#define to_mipi_dsi_device(__dev) container_of_const(__dev, struct mipi_dsi_device, dev)
Expand Down Expand Up @@ -258,6 +279,8 @@ ssize_t mipi_dsi_generic_write(struct mipi_dsi_device *dsi, const void *payload,
size_t size);
int mipi_dsi_generic_write_chatty(struct mipi_dsi_device *dsi,
const void *payload, size_t size);
void mipi_dsi_generic_write_multi(struct mipi_dsi_multi_context *ctx,
const void *payload, size_t size);
ssize_t mipi_dsi_generic_read(struct mipi_dsi_device *dsi, const void *params,
size_t num_params, void *data, size_t size);

Expand All @@ -283,6 +306,8 @@ ssize_t mipi_dsi_dcs_write_buffer(struct mipi_dsi_device *dsi,
const void *data, size_t len);
int mipi_dsi_dcs_write_buffer_chatty(struct mipi_dsi_device *dsi,
const void *data, size_t len);
void mipi_dsi_dcs_write_buffer_multi(struct mipi_dsi_multi_context *ctx,
const void *data, size_t len);
ssize_t mipi_dsi_dcs_write(struct mipi_dsi_device *dsi, u8 cmd,
const void *data, size_t len);
ssize_t mipi_dsi_dcs_read(struct mipi_dsi_device *dsi, u8 cmd, void *data,
Expand Down Expand Up @@ -319,6 +344,9 @@ int mipi_dsi_dcs_get_display_brightness_large(struct mipi_dsi_device *dsi,
* This macro will print errors for you and will RETURN FROM THE CALLING
* FUNCTION (yes this is non-intuitive) upon error.
*
* Because of the non-intuitive return behavior, THIS MACRO IS DEPRECATED.
* Please replace calls of it with mipi_dsi_generic_write_seq_multi().
*
* @dsi: DSI peripheral device
* @seq: buffer containing the payload
*/
Expand All @@ -331,12 +359,30 @@ int mipi_dsi_dcs_get_display_brightness_large(struct mipi_dsi_device *dsi,
return ret; \
} while (0)

/**
* mipi_dsi_generic_write_seq_multi - transmit data using a generic write packet
*
* This macro will print errors for you and error handling is optimized for
* callers that call this multiple times in a row.
*
* @ctx: Context for multiple DSI transactions
* @seq: buffer containing the payload
*/
#define mipi_dsi_generic_write_seq_multi(ctx, seq...) \
do { \
static const u8 d[] = { seq }; \
mipi_dsi_generic_write_multi(ctx, d, ARRAY_SIZE(d)); \
} while (0)

/**
* mipi_dsi_dcs_write_seq - transmit a DCS command with payload
*
* This macro will print errors for you and will RETURN FROM THE CALLING
* FUNCTION (yes this is non-intuitive) upon error.
*
* Because of the non-intuitive return behavior, THIS MACRO IS DEPRECATED.
* Please replace calls of it with mipi_dsi_dcs_write_seq_multi().
*
* @dsi: DSI peripheral device
* @cmd: Command
* @seq: buffer containing data to be transmitted
Expand All @@ -350,6 +396,22 @@ int mipi_dsi_dcs_get_display_brightness_large(struct mipi_dsi_device *dsi,
return ret; \
} while (0)

/**
* mipi_dsi_dcs_write_seq_multi - transmit a DCS command with payload
*
* This macro will print errors for you and error handling is optimized for
* callers that call this multiple times in a row.
*
* @ctx: Context for multiple DSI transactions
* @cmd: Command
* @seq: buffer containing data to be transmitted
*/
#define mipi_dsi_dcs_write_seq_multi(ctx, cmd, seq...) \
do { \
static const u8 d[] = { cmd, seq }; \
mipi_dsi_dcs_write_buffer_multi(ctx, d, ARRAY_SIZE(d)); \
} while (0)

/**
* struct mipi_dsi_driver - DSI driver
* @driver: device driver model driver
Expand Down

0 comments on commit 7c5c096

Please sign in to comment.