Merge branch 'bugfix/allow_bypass_lcd_cmd_v4.4' into 'release/v4.4'

spi_lcd: panel_io_spi_tx_color without cmd (v4.4)

See merge request espressif/esp-idf!21428
This commit is contained in:
morris
2022-12-05 22:47:22 +08:00
2 changed files with 30 additions and 24 deletions

View File

@@ -47,7 +47,7 @@ typedef struct {
* @brief Transmit LCD command and receive corresponding parameters * @brief Transmit LCD command and receive corresponding parameters
* *
* @note Commands sent by this function are short, so they are sent using polling transactions. * @note Commands sent by this function are short, so they are sent using polling transactions.
* The function does not return before the command tranfer is completed. * The function does not return before the command transfer is completed.
* If any queued transactions sent by `esp_lcd_panel_io_tx_color()` are still pending when this function is called, * If any queued transactions sent by `esp_lcd_panel_io_tx_color()` are still pending when this function is called,
* this function will wait until they are finished and the queue is empty before sending the command(s). * this function will wait until they are finished and the queue is empty before sending the command(s).
* *
@@ -66,7 +66,7 @@ esp_err_t esp_lcd_panel_io_rx_param(esp_lcd_panel_io_handle_t io, int lcd_cmd, v
* @brief Transmit LCD command and corresponding parameters * @brief Transmit LCD command and corresponding parameters
* *
* @note Commands sent by this function are short, so they are sent using polling transactions. * @note Commands sent by this function are short, so they are sent using polling transactions.
* The function does not return before the command tranfer is completed. * The function does not return before the command transfer is completed.
* If any queued transactions sent by `esp_lcd_panel_io_tx_color()` are still pending when this function is called, * If any queued transactions sent by `esp_lcd_panel_io_tx_color()` are still pending when this function is called,
* this function will wait until they are finished and the queue is empty before sending the command(s). * this function will wait until they are finished and the queue is empty before sending the command(s).
* *
@@ -89,7 +89,7 @@ esp_err_t esp_lcd_panel_io_tx_param(esp_lcd_panel_io_handle_t io, int lcd_cmd, c
* Recycling of color buffer should be done in the callback `on_color_trans_done()`. * Recycling of color buffer should be done in the callback `on_color_trans_done()`.
* *
* @param[in] io LCD panel IO handle, which is created by factory API like `esp_lcd_new_panel_io_spi()` * @param[in] io LCD panel IO handle, which is created by factory API like `esp_lcd_new_panel_io_spi()`
* @param[in] lcd_cmd The specific LCD command * @param[in] lcd_cmd The specific LCD command, set to -1 if no command needed
* @param[in] color Buffer that holds the RGB color data * @param[in] color Buffer that holds the RGB color data
* @param[in] color_size Size of `color` in memory, in bytes * @param[in] color_size Size of `color` in memory, in bytes
* @return * @return
@@ -99,7 +99,7 @@ esp_err_t esp_lcd_panel_io_tx_param(esp_lcd_panel_io_handle_t io, int lcd_cmd, c
esp_err_t esp_lcd_panel_io_tx_color(esp_lcd_panel_io_handle_t io, int lcd_cmd, const void *color, size_t color_size); esp_err_t esp_lcd_panel_io_tx_color(esp_lcd_panel_io_handle_t io, int lcd_cmd, const void *color, size_t color_size);
/** /**
* @brief Destory LCD panel IO handle (deinitialize panel and free all corresponding resource) * @brief Destroy LCD panel IO handle (deinitialize panel and free all corresponding resource)
* *
* @param[in] io LCD panel IO handle, which is created by factory API like `esp_lcd_new_panel_io_spi()` * @param[in] io LCD panel IO handle, which is created by factory API like `esp_lcd_new_panel_io_spi()`
* @return * @return
@@ -162,7 +162,7 @@ typedef struct {
uint32_t dev_addr; /*!< I2C device address */ uint32_t dev_addr; /*!< I2C device address */
esp_lcd_panel_io_color_trans_done_cb_t on_color_trans_done; /*!< Callback invoked when color data transfer has finished */ esp_lcd_panel_io_color_trans_done_cb_t on_color_trans_done; /*!< Callback invoked when color data transfer has finished */
void *user_ctx; /*!< User private data, passed directly to on_color_trans_done's user_ctx */ void *user_ctx; /*!< User private data, passed directly to on_color_trans_done's user_ctx */
size_t control_phase_bytes; /*!< I2C LCD panel will encode control information (e.g. D/C seclection) into control phase, in several bytes */ size_t control_phase_bytes; /*!< I2C LCD panel will encode control information (e.g. D/C selection) into control phase, in several bytes */
unsigned int dc_bit_offset; /*!< Offset of the D/C selection bit in control phase */ unsigned int dc_bit_offset; /*!< Offset of the D/C selection bit in control phase */
int lcd_cmd_bits; /*!< Bit-width of LCD command */ int lcd_cmd_bits; /*!< Bit-width of LCD command */
int lcd_param_bits; /*!< Bit-width of LCD parameter */ int lcd_param_bits; /*!< Bit-width of LCD parameter */
@@ -214,7 +214,7 @@ typedef struct {
esp_err_t esp_lcd_new_i80_bus(const esp_lcd_i80_bus_config_t *bus_config, esp_lcd_i80_bus_handle_t *ret_bus); esp_err_t esp_lcd_new_i80_bus(const esp_lcd_i80_bus_config_t *bus_config, esp_lcd_i80_bus_handle_t *ret_bus);
/** /**
* @brief Destory Intel 8080 bus handle * @brief Destroy Intel 8080 bus handle
* *
* @param[in] bus Intel 8080 bus handle, created by `esp_lcd_new_i80_bus()` * @param[in] bus Intel 8080 bus handle, created by `esp_lcd_new_i80_bus()`
* @return * @return
@@ -231,7 +231,7 @@ typedef struct {
int cs_gpio_num; /*!< GPIO used for CS line, set to -1 will declaim exclusively use of I80 bus */ int cs_gpio_num; /*!< GPIO used for CS line, set to -1 will declaim exclusively use of I80 bus */
unsigned int pclk_hz; /*!< Frequency of pixel clock */ unsigned int pclk_hz; /*!< Frequency of pixel clock */
size_t trans_queue_depth; /*!< Transaction queue size, larger queue, higher throughput */ size_t trans_queue_depth; /*!< Transaction queue size, larger queue, higher throughput */
esp_lcd_panel_io_color_trans_done_cb_t on_color_trans_done; /*!< Callback invoked when color data was tranferred done */ esp_lcd_panel_io_color_trans_done_cb_t on_color_trans_done; /*!< Callback invoked when color data was transferred done */
void *user_ctx; /*!< User private data, passed directly to on_color_trans_done's user_ctx */ void *user_ctx; /*!< User private data, passed directly to on_color_trans_done's user_ctx */
int lcd_cmd_bits; /*!< Bit-width of LCD command */ int lcd_cmd_bits; /*!< Bit-width of LCD command */
int lcd_param_bits; /*!< Bit-width of LCD parameter */ int lcd_param_bits; /*!< Bit-width of LCD parameter */

View File

@@ -143,7 +143,7 @@ static esp_err_t panel_io_spi_register_event_callbacks(esp_lcd_panel_io_handle_t
{ {
esp_lcd_panel_io_spi_t *spi_panel_io = __containerof(io, esp_lcd_panel_io_spi_t, base); esp_lcd_panel_io_spi_t *spi_panel_io = __containerof(io, esp_lcd_panel_io_spi_t, base);
if(spi_panel_io->on_color_trans_done != NULL) { if (spi_panel_io->on_color_trans_done != NULL) {
ESP_LOGW(TAG, "Callback on_color_trans_done was already set and now it was owerwritten!"); ESP_LOGW(TAG, "Callback on_color_trans_done was already set and now it was owerwritten!");
} }
@@ -200,7 +200,7 @@ static esp_err_t panel_io_spi_tx_param(esp_lcd_panel_io_t *io, int lcd_cmd, cons
} }
lcd_trans = &spi_panel_io->trans_pool[0]; lcd_trans = &spi_panel_io->trans_pool[0];
memset(lcd_trans, 0, sizeof(lcd_spi_trans_descriptor_t)); memset(lcd_trans, 0, sizeof(lcd_spi_trans_descriptor_t));
spi_lcd_prepare_cmd_buffer(spi_panel_io, &lcd_cmd);
lcd_trans->base.user = spi_panel_io; lcd_trans->base.user = spi_panel_io;
lcd_trans->base.flags |= SPI_TRANS_CS_KEEP_ACTIVE; lcd_trans->base.flags |= SPI_TRANS_CS_KEEP_ACTIVE;
if (spi_panel_io->flags.octal_mode) { if (spi_panel_io->flags.octal_mode) {
@@ -209,6 +209,7 @@ static esp_err_t panel_io_spi_tx_param(esp_lcd_panel_io_t *io, int lcd_cmd, cons
} }
if (send_cmd) { if (send_cmd) {
spi_lcd_prepare_cmd_buffer(spi_panel_io, &lcd_cmd);
lcd_trans->flags.dc_gpio_level = !spi_panel_io->flags.dc_data_level; // set D/C line to command mode lcd_trans->flags.dc_gpio_level = !spi_panel_io->flags.dc_data_level; // set D/C line to command mode
if (spi_panel_io->flags.dc_as_cmd_phase) { // encoding DC value to SPI command phase when necessary if (spi_panel_io->flags.dc_as_cmd_phase) { // encoding DC value to SPI command phase when necessary
lcd_trans->base.cmd = !spi_panel_io->flags.dc_data_level; lcd_trans->base.cmd = !spi_panel_io->flags.dc_data_level;
@@ -259,7 +260,7 @@ static esp_err_t panel_io_spi_rx_param(esp_lcd_panel_io_t *io, int lcd_cmd, void
} }
lcd_trans = &spi_panel_io->trans_pool[0]; lcd_trans = &spi_panel_io->trans_pool[0];
memset(lcd_trans, 0, sizeof(lcd_spi_trans_descriptor_t)); memset(lcd_trans, 0, sizeof(lcd_spi_trans_descriptor_t));
spi_lcd_prepare_cmd_buffer(spi_panel_io, &lcd_cmd);
lcd_trans->base.user = spi_panel_io; lcd_trans->base.user = spi_panel_io;
lcd_trans->base.flags |= SPI_TRANS_CS_KEEP_ACTIVE; lcd_trans->base.flags |= SPI_TRANS_CS_KEEP_ACTIVE;
if (spi_panel_io->flags.octal_mode) { if (spi_panel_io->flags.octal_mode) {
@@ -268,6 +269,7 @@ static esp_err_t panel_io_spi_rx_param(esp_lcd_panel_io_t *io, int lcd_cmd, void
} }
if (send_cmd) { if (send_cmd) {
spi_lcd_prepare_cmd_buffer(spi_panel_io, &lcd_cmd);
lcd_trans->flags.dc_gpio_level = !spi_panel_io->flags.dc_data_level; // set D/C line to command mode lcd_trans->flags.dc_gpio_level = !spi_panel_io->flags.dc_data_level; // set D/C line to command mode
if (spi_panel_io->flags.dc_as_cmd_phase) { // encoding DC value to SPI command phase when necessary if (spi_panel_io->flags.dc_as_cmd_phase) { // encoding DC value to SPI command phase when necessary
lcd_trans->base.cmd = !spi_panel_io->flags.dc_data_level; lcd_trans->base.cmd = !spi_panel_io->flags.dc_data_level;
@@ -306,6 +308,7 @@ static esp_err_t panel_io_spi_tx_color(esp_lcd_panel_io_t *io, int lcd_cmd, cons
spi_transaction_t *spi_trans = NULL; spi_transaction_t *spi_trans = NULL;
lcd_spi_trans_descriptor_t *lcd_trans = NULL; lcd_spi_trans_descriptor_t *lcd_trans = NULL;
esp_lcd_panel_io_spi_t *spi_panel_io = __containerof(io, esp_lcd_panel_io_spi_t, base); esp_lcd_panel_io_spi_t *spi_panel_io = __containerof(io, esp_lcd_panel_io_spi_t, base);
bool send_cmd = (lcd_cmd >= 0);
// before issue a polling transaction, need to wait queued transactions finished // before issue a polling transaction, need to wait queued transactions finished
for (size_t i = 0; i < spi_panel_io->num_trans_inflight; i++) { for (size_t i = 0; i < spi_panel_io->num_trans_inflight; i++) {
@@ -315,21 +318,24 @@ static esp_err_t panel_io_spi_tx_color(esp_lcd_panel_io_t *io, int lcd_cmd, cons
spi_panel_io->num_trans_inflight = 0; spi_panel_io->num_trans_inflight = 0;
lcd_trans = &spi_panel_io->trans_pool[0]; lcd_trans = &spi_panel_io->trans_pool[0];
memset(lcd_trans, 0, sizeof(lcd_spi_trans_descriptor_t)); memset(lcd_trans, 0, sizeof(lcd_spi_trans_descriptor_t));
spi_lcd_prepare_cmd_buffer(spi_panel_io, &lcd_cmd);
lcd_trans->base.user = spi_panel_io; if (send_cmd) {
lcd_trans->flags.dc_gpio_level = !spi_panel_io->flags.dc_data_level; // set D/C line to command mode spi_lcd_prepare_cmd_buffer(spi_panel_io, &lcd_cmd);
lcd_trans->base.length = spi_panel_io->lcd_cmd_bits; lcd_trans->base.user = spi_panel_io;
lcd_trans->base.tx_buffer = &lcd_cmd; lcd_trans->flags.dc_gpio_level = !spi_panel_io->flags.dc_data_level; // set D/C line to command mode
if (spi_panel_io->flags.dc_as_cmd_phase) { // encoding DC value to SPI command phase when necessary lcd_trans->base.length = spi_panel_io->lcd_cmd_bits;
lcd_trans->base.cmd = !spi_panel_io->flags.dc_data_level; lcd_trans->base.tx_buffer = &lcd_cmd;
if (spi_panel_io->flags.dc_as_cmd_phase) { // encoding DC value to SPI command phase when necessary
lcd_trans->base.cmd = !spi_panel_io->flags.dc_data_level;
}
if (spi_panel_io->flags.octal_mode) {
// use 8 lines for transmitting command, address and data
lcd_trans->base.flags |= (SPI_TRANS_MULTILINE_CMD | SPI_TRANS_MULTILINE_ADDR | SPI_TRANS_MODE_OCT);
}
// command is short, using polling mode
ret = spi_device_polling_transmit(spi_panel_io->spi_dev, &lcd_trans->base);
ESP_GOTO_ON_ERROR(ret, err, TAG, "spi transmit (polling) command failed");
} }
if (spi_panel_io->flags.octal_mode) {
// use 8 lines for transmitting command, address and data
lcd_trans->base.flags |= (SPI_TRANS_MULTILINE_CMD | SPI_TRANS_MULTILINE_ADDR | SPI_TRANS_MODE_OCT);
}
// command is short, using polling mode
ret = spi_device_polling_transmit(spi_panel_io->spi_dev, &lcd_trans->base);
ESP_GOTO_ON_ERROR(ret, err, TAG, "spi transmit (polling) command failed");
// split to chunks if required: // split to chunks if required:
// the SPI bus has a maximum transaction size determined by SPI_USR_MOSI_DBITLEN's bit width // the SPI bus has a maximum transaction size determined by SPI_USR_MOSI_DBITLEN's bit width