21
21
#include "esp_log.h"
22
22
#include "esp_check.h"
23
23
#include "esp_lcd_common.h"
24
-
25
- #define LCD_SPI_MAX_DATA_SIZE (SPI_LL_DATA_MAX_BIT_LEN / 8)
24
+ #include "esp_private/spi_common_internal.h"
26
25
27
26
static const char * TAG = "lcd_panel.io.spi" ;
28
27
@@ -45,6 +44,7 @@ typedef struct {
45
44
typedef struct {
46
45
esp_lcd_panel_io_t base ; // Base class of generic lcd panel io
47
46
spi_device_handle_t spi_dev ; // SPI device handle
47
+ size_t spi_trans_max_bytes ; // Maximum bytes that can be transmitted in one spi transaction
48
48
int dc_gpio_num ; // D/C line GPIO number
49
49
esp_lcd_panel_io_color_trans_done_cb_t on_color_trans_done ; // User register's callback, invoked when color data trans done
50
50
void * user_ctx ; // User's private data, passed directly to callback on_color_trans_done
@@ -107,6 +107,7 @@ esp_err_t esp_lcd_new_panel_io_spi(esp_lcd_spi_bus_handle_t bus, const esp_lcd_p
107
107
spi_panel_io -> base .tx_color = panel_io_spi_tx_color ;
108
108
spi_panel_io -> base .del = panel_io_spi_del ;
109
109
spi_panel_io -> base .register_event_callbacks = panel_io_spi_register_event_callbacks ;
110
+ spi_panel_io -> spi_trans_max_bytes = spi_bus_get_attr ((spi_host_device_t )bus )-> max_transfer_sz ;
110
111
* ret_io = & (spi_panel_io -> base );
111
112
ESP_LOGD (TAG , "new spi lcd panel io @%p" , spi_panel_io );
112
113
@@ -305,19 +306,21 @@ static esp_err_t panel_io_spi_tx_color(esp_lcd_panel_io_t *io, int lcd_cmd, cons
305
306
spi_transaction_t * spi_trans = NULL ;
306
307
lcd_spi_trans_descriptor_t * lcd_trans = NULL ;
307
308
esp_lcd_panel_io_spi_t * spi_panel_io = __containerof (io , esp_lcd_panel_io_spi_t , base );
308
- bool send_cmd = (lcd_cmd >= 0 );
309
309
310
- // before issue a polling transaction, need to wait queued transactions finished
311
- size_t num_trans_inflight = spi_panel_io -> num_trans_inflight ;
312
- for (size_t i = 0 ; i < num_trans_inflight ; i ++ ) {
313
- ret = spi_device_get_trans_result (spi_panel_io -> spi_dev , & spi_trans , portMAX_DELAY );
314
- ESP_GOTO_ON_ERROR (ret , err , TAG , "recycle spi transactions failed" );
315
- spi_panel_io -> num_trans_inflight -- ;
316
- }
317
- lcd_trans = & spi_panel_io -> trans_pool [0 ];
318
- memset (lcd_trans , 0 , sizeof (lcd_spi_trans_descriptor_t ));
310
+ ESP_RETURN_ON_ERROR (spi_device_acquire_bus (spi_panel_io -> spi_dev , portMAX_DELAY ), TAG , "acquire spi bus failed" );
319
311
312
+ bool send_cmd = (lcd_cmd >= 0 );
320
313
if (send_cmd ) {
314
+ // before issue a polling transaction, need to wait queued transactions finished
315
+ size_t num_trans_inflight = spi_panel_io -> num_trans_inflight ;
316
+ for (size_t i = 0 ; i < num_trans_inflight ; i ++ ) {
317
+ ret = spi_device_get_trans_result (spi_panel_io -> spi_dev , & spi_trans , portMAX_DELAY );
318
+ ESP_GOTO_ON_ERROR (ret , err , TAG , "recycle spi transactions failed" );
319
+ spi_panel_io -> num_trans_inflight -- ;
320
+ }
321
+ lcd_trans = & spi_panel_io -> trans_pool [0 ];
322
+ memset (lcd_trans , 0 , sizeof (lcd_spi_trans_descriptor_t ));
323
+
321
324
spi_lcd_prepare_cmd_buffer (spi_panel_io , & lcd_cmd );
322
325
lcd_trans -> base .user = spi_panel_io ;
323
326
lcd_trans -> flags .dc_gpio_level = !spi_panel_io -> flags .dc_data_level ; // set D/C line to command mode
@@ -332,8 +335,7 @@ static esp_err_t panel_io_spi_tx_color(esp_lcd_panel_io_t *io, int lcd_cmd, cons
332
335
ESP_GOTO_ON_ERROR (ret , err , TAG , "spi transmit (polling) command failed" );
333
336
}
334
337
335
- // split to chunks if required:
336
- // the SPI bus has a maximum transaction size determined by SPI_LL_DATA_MAX_BIT_LEN
338
+ // if the color buffer is big, we want to split it into chunks, and queue the chunks one by one
337
339
do {
338
340
size_t chunk_size = color_size ;
339
341
@@ -349,13 +351,15 @@ static esp_err_t panel_io_spi_tx_color(esp_lcd_panel_io_t *io, int lcd_cmd, cons
349
351
}
350
352
memset (lcd_trans , 0 , sizeof (lcd_spi_trans_descriptor_t ));
351
353
352
- // SPI per-transfer size has its limitation, if the color buffer is too big, we need to split it into multiple trunks
353
- if (chunk_size > LCD_SPI_MAX_DATA_SIZE ) {
354
+ // SPI per-transfer size has its limitation, if the color buffer is too big, we need to split it into multiple chunks
355
+ if (chunk_size > spi_panel_io -> spi_trans_max_bytes ) {
354
356
// cap the transfer size to the maximum supported by the bus
355
- chunk_size = LCD_SPI_MAX_DATA_SIZE ;
357
+ chunk_size = spi_panel_io -> spi_trans_max_bytes ;
358
+ lcd_trans -> base .flags |= SPI_TRANS_CS_KEEP_ACTIVE ;
356
359
} else {
357
360
// mark en_trans_done_cb only at the last round to avoid premature completion callback
358
361
lcd_trans -> flags .en_trans_done_cb = 1 ;
362
+ lcd_trans -> base .flags &= ~SPI_TRANS_CS_KEEP_ACTIVE ;
359
363
}
360
364
361
365
lcd_trans -> base .user = spi_panel_io ;
@@ -378,6 +382,7 @@ static esp_err_t panel_io_spi_tx_color(esp_lcd_panel_io_t *io, int lcd_cmd, cons
378
382
} while (color_size > 0 ); // continue while we have remaining data to transmit
379
383
380
384
err :
385
+ spi_device_release_bus (spi_panel_io -> spi_dev );
381
386
return ret ;
382
387
}
383
388
0 commit comments