esp_lcd_common.c 3.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106
  1. /*
  2. * SPDX-FileCopyrightText: 2021-2022 Espressif Systems (Shanghai) CO LTD
  3. *
  4. * SPDX-License-Identifier: Apache-2.0
  5. */
  6. #include "freertos/FreeRTOS.h"
  7. #include "soc/soc_caps.h"
  8. #include "esp_lcd_common.h"
  9. #if SOC_LCDCAM_SUPPORTED
  10. #include "hal/lcd_ll.h"
  11. #include "hal/lcd_hal.h"
  12. typedef struct esp_lcd_platform_t {
  13. portMUX_TYPE spinlock; // spinlock used to protect platform level resources
  14. union {
  15. void *panels[SOC_LCD_RGB_PANELS]; // array of RGB LCD panel instances
  16. void *buses[SOC_LCD_I80_BUSES]; // array of i80 bus instances
  17. }; // LCD peripheral can only work under either RGB mode or intel 8080 mode
  18. } esp_lcd_platform_t;
  19. esp_lcd_platform_t s_lcd_platform = {
  20. .spinlock = (portMUX_TYPE)portMUX_INITIALIZER_UNLOCKED,
  21. .buses = {} // initially the bus slots and panel slots are empty
  22. };
  23. int lcd_com_register_device(lcd_com_device_type_t device_type, void *device_obj)
  24. {
  25. int member_id = -1;
  26. switch (device_type) {
  27. case LCD_COM_DEVICE_TYPE_I80:
  28. // search for a bus slot then register to platform
  29. for (int i = 0; (i < SOC_LCD_I80_BUSES) && (member_id == -1); i++) {
  30. portENTER_CRITICAL(&s_lcd_platform.spinlock);
  31. if (!s_lcd_platform.buses[i]) {
  32. s_lcd_platform.buses[i] = device_obj;
  33. member_id = i;
  34. }
  35. portEXIT_CRITICAL(&s_lcd_platform.spinlock);
  36. }
  37. break;
  38. case LCD_COM_DEVICE_TYPE_RGB:
  39. // search for a panel slot then register to platform
  40. for (int i = 0; (i < SOC_LCD_RGB_PANELS) && (member_id == -1); i++) {
  41. portENTER_CRITICAL(&s_lcd_platform.spinlock);
  42. if (!s_lcd_platform.panels[i]) {
  43. s_lcd_platform.panels[i] = device_obj;
  44. member_id = i;
  45. }
  46. portEXIT_CRITICAL(&s_lcd_platform.spinlock);
  47. }
  48. break;
  49. default:
  50. break;
  51. }
  52. return member_id;
  53. }
  54. void lcd_com_remove_device(lcd_com_device_type_t device_type, int member_id)
  55. {
  56. switch (device_type) {
  57. case LCD_COM_DEVICE_TYPE_I80:
  58. portENTER_CRITICAL(&s_lcd_platform.spinlock);
  59. if (s_lcd_platform.buses[member_id]) {
  60. s_lcd_platform.buses[member_id] = NULL;
  61. }
  62. portEXIT_CRITICAL(&s_lcd_platform.spinlock);
  63. break;
  64. case LCD_COM_DEVICE_TYPE_RGB:
  65. portENTER_CRITICAL(&s_lcd_platform.spinlock);
  66. if (s_lcd_platform.panels[member_id]) {
  67. s_lcd_platform.panels[member_id] = NULL;
  68. }
  69. portEXIT_CRITICAL(&s_lcd_platform.spinlock);
  70. break;
  71. default:
  72. break;
  73. }
  74. }
  75. #endif // SOC_LCDCAM_SUPPORTED
  76. void lcd_com_mount_dma_data(dma_descriptor_t *desc_head, const void *buffer, size_t len)
  77. {
  78. size_t prepared_length = 0;
  79. uint8_t *data = (uint8_t *)buffer;
  80. dma_descriptor_t *desc = desc_head;
  81. while (len > DMA_DESCRIPTOR_BUFFER_MAX_SIZE) {
  82. desc->dw0.suc_eof = 0; // not the end of the transaction
  83. desc->dw0.size = DMA_DESCRIPTOR_BUFFER_MAX_SIZE;
  84. desc->dw0.length = DMA_DESCRIPTOR_BUFFER_MAX_SIZE;
  85. desc->dw0.owner = DMA_DESCRIPTOR_BUFFER_OWNER_DMA;
  86. desc->buffer = &data[prepared_length];
  87. desc = desc->next; // move to next descriptor
  88. prepared_length += DMA_DESCRIPTOR_BUFFER_MAX_SIZE;
  89. len -= DMA_DESCRIPTOR_BUFFER_MAX_SIZE;
  90. }
  91. if (len) {
  92. desc->dw0.suc_eof = 1; // end of the transaction
  93. desc->dw0.size = len;
  94. desc->dw0.length = len;
  95. desc->dw0.owner = DMA_DESCRIPTOR_BUFFER_OWNER_DMA;
  96. desc->buffer = &data[prepared_length];
  97. desc = desc->next; // move to next descriptor
  98. prepared_length += len;
  99. }
  100. }