embox
269 строк · 6.3 Кб
1/**
2* @file
3* @brief
4*
5* @date 16.07.15
6* @author
7*/
8
9#include <errno.h>10#include <assert.h>11#include <stdint.h>12#include <string.h>13#include <sys/mman.h>14
15#include <drivers/video/fb.h>16#include <mem/page.h>17#include <util/binalign.h>18#include <util/log.h>19#include <kernel/irq.h>20
21#if defined STM32F746xx22#include "stm32746g_discovery_lcd.h"23#elif defined STM32F769xx24#include "stm32f769i_discovery_lcd.h"25#elif defined STM32H745xx26#include "stm32h745i_discovery_lcd.h"27#else28#error Unsupported platform29#endif30
31/* Initialize layer 0 as active for all F7 boards. */
32#undef LTDC_ACTIVE_LAYER33#define LTDC_ACTIVE_LAYER 034
35#include <embox/unit.h>36EMBOX_UNIT_INIT(stm32cube_lcd_init);37
38#define LTDC_IRQ OPTION_GET(NUMBER,ltdc_irq)39static_assert(LTDC_IRQ == LTDC_IRQn, "");40
41#define USE_FB_SECTION OPTION_GET(BOOLEAN,use_fb_section)42
43#if USE_FB_SECTION44#define STM32_FB_SECTION_START OPTION_GET(STRING,fb_section_start)45extern char STM32_FB_SECTION_START;46#else47#define STM32_FB_START OPTION_GET(NUMBER, fb_base)48#endif49
50#define STM32_LCD_HEIGHT OPTION_GET(NUMBER, height)51#define STM32_LCD_WIDTH OPTION_GET(NUMBER, width)52#define STM32_LCD_BPP OPTION_GET(NUMBER, bpp)53
54#if defined STM32F746xx55extern LTDC_HandleTypeDef hLtdcHandler;56#define hltdc_handler hLtdcHandler57#elif defined STM32F769xx58extern LTDC_HandleTypeDef hltdc_discovery;59#define hltdc_handler hltdc_discovery60#elif defined STM32H745xx61extern LTDC_HandleTypeDef hlcd_ltdc;62#define hltdc_handler hlcd_ltdc63#else64#error Unsupported platform65#endif66
67static int stm32cube_lcd_set_var(struct fb_info *info,68struct fb_var_screeninfo const *var) {69return 0;70}
71
72static int stm32cube_lcd_get_var(struct fb_info *info,73struct fb_var_screeninfo *var) {74memset(var, 0, sizeof(*var));75
76#if defined STM32H745xx77BSP_LCD_GetXSize(0, &var->xres);78BSP_LCD_GetYSize(0, &var->yres);79#else80var->xres = BSP_LCD_GetXSize();81var->yres = BSP_LCD_GetYSize();82#endif83var->xres_virtual = var->xres;84var->yres_virtual = var->yres;85var->bits_per_pixel = STM32_LCD_BPP;86
87switch (STM32_LCD_BPP) {88case 16:89var->fmt = BGR565;90break;91case 32:92var->fmt = BGRA8888;93break;94default:95log_error("unknown BPP = %d\n", STM32_LCD_BPP);96return -1;97}98
99return 0;100}
101
102static void stm32cube_lcd_fillrect(struct fb_info *info,103const struct fb_fillrect *rect) {104#if defined STM32H745xx105BSP_LCD_FillRect(0, rect->dx, rect->dy, rect->width, rect->height,106rect->color | 0xff000000);107#else108BSP_LCD_SetTextColor(rect->color | 0xff000000);109BSP_LCD_FillRect(rect->dx, rect->dy, rect->width, rect->height);110#endif111}
112
113static uint32_t stm32cube_get_image_color(const struct fb_image *image, int num) {114switch (image->depth) {115case 1:116if (image->data[num / 8] & (1 << (8 - num % 8))) {117return image->fg_color;118} else {119return image->bg_color;120}121case 16:122return ((uint16_t *) image->data)[num];123case 32:124return ((uint32_t *) image->data)[num];125default:126log_error("Unsupported color depth: %d\n", image->depth);127return image->bg_color;128}129}
130
131static void stm32cube_lcd_imageblit(struct fb_info *info,132const struct fb_image *image) {133int dy = image->dy, dx = image->dx;134int height = image->height, width = image->width;135int n = 0;136
137for (int j = dy; j < dy + height; j++) {138for (int i = dx; i < dx + width; i++) {139#if defined STM32H745xx140BSP_LCD_WritePixel(0, i, j, stm32cube_get_image_color(image, n));141#else142BSP_LCD_DrawPixel(i, j, stm32cube_get_image_color(image, n));143#endif144}145}146}
147
148static void ltdc_layer_init(uint16_t LayerIndex, uint32_t FB_Address, int bpp) {149#if defined STM32H745xx150#else151LCD_LayerCfgTypeDef Layercfg;152
153switch (bpp) {154case 16:155Layercfg.PixelFormat = LTDC_PIXEL_FORMAT_RGB565;156break;157case 32:158Layercfg.PixelFormat = LTDC_PIXEL_FORMAT_ARGB8888;159break;160default:161return;162}163
164/* Layer Init */165Layercfg.WindowX0 = 0;166Layercfg.WindowX1 = BSP_LCD_GetXSize();167Layercfg.WindowY0 = 0;168Layercfg.WindowY1 = BSP_LCD_GetYSize();169Layercfg.FBStartAdress = FB_Address;170Layercfg.Alpha = 255;171Layercfg.Alpha0 = 0;172Layercfg.Backcolor.Blue = 0;173Layercfg.Backcolor.Green = 0;174Layercfg.Backcolor.Red = 0;175Layercfg.BlendingFactor1 = LTDC_BLENDING_FACTOR1_PAxCA;176Layercfg.BlendingFactor2 = LTDC_BLENDING_FACTOR2_PAxCA;177Layercfg.ImageWidth = BSP_LCD_GetXSize();178Layercfg.ImageHeight = BSP_LCD_GetYSize();179
180HAL_LTDC_ConfigLayer(&hltdc_handler, &Layercfg, LayerIndex);181#endif182}
183
184static irq_return_t ltdc_irq_handler(unsigned int irq_num, void *dev_id) {185HAL_LTDC_IRQHandler(&hltdc_handler);186
187return IRQ_HANDLED;188}
189
190STATIC_IRQ_ATTACH(LTDC_IRQ, ltdc_irq_handler, NULL);191
192static struct fb_ops stm32cube_lcd_ops = {193.fb_set_var = stm32cube_lcd_set_var,194.fb_get_var = stm32cube_lcd_get_var,195.fb_fillrect = stm32cube_lcd_fillrect,196.fb_imageblit = stm32cube_lcd_imageblit,197};198
199static int stm32cube_lcd_init(void) {200char *mmap_base;201
202#if defined STM32H745xx203#if STM32_LCD_BPP == 16204/* Initialize the LCD */205BSP_LCD_InitEx(0, LCD_ORIENTATION_LANDSCAPE, LTDC_PIXEL_FORMAT_RGB565, STM32_LCD_WIDTH, STM32_LCD_HEIGHT);206#else207BSP_LCD_InitEx(0, LCD_ORIENTATION_LANDSCAPE, LTDC_PIXEL_FORMAT_ARGB8888, STM32_LCD_WIDTH, STM32_LCD_HEIGHT);208#endif209
210#else211if (BSP_LCD_Init() != LCD_OK) {212log_error("Failed to init LCD!");213return -1;214}215
216#endif217
218#if USE_FB_SECTION219mmap_base = (char *) &STM32_FB_SECTION_START;220#else221mmap_base = (char *) STM32_FB_START;222#endif223
224#if STM32_LCD_BPP == 16225ltdc_layer_init(LTDC_ACTIVE_LAYER, (unsigned int) mmap_base, 16);226#elif STM32_LCD_BPP == 32227ltdc_layer_init(LTDC_ACTIVE_LAYER, (unsigned int) mmap_base, 32);228#else229#error Unsupported STM32_LCD_BPP value230#endif231
232#if defined STM32H745xx233BSP_LCD_SetBrightness(0, 100);234BSP_LCD_DisplayOn(0);235
236BSP_LCD_SetLayerVisible(0, 1, DISABLE);237BSP_LCD_SetLayerVisible(0, LTDC_ACTIVE_LAYER, ENABLE);238
239memset(mmap_base, 0, STM32_LCD_WIDTH * STM32_LCD_HEIGHT * 4);240#else241BSP_LCD_SetXSize(STM32_LCD_WIDTH);242BSP_LCD_SetYSize(STM32_LCD_HEIGHT);243
244BSP_LCD_SetBackColor(LCD_COLOR_WHITE);245BSP_LCD_SetTextColor(LCD_COLOR_BLACK);246
247BSP_LCD_SelectLayer(LTDC_ACTIVE_LAYER);248
249#ifdef STM32F769xx250/* STM32746 doesn't support brightness change */251BSP_LCD_SetBrightness(100);252#endif253
254BSP_LCD_Clear(LCD_COLOR_BLACK);255#endif256
257if (0 > irq_attach(LTDC_IRQ, ltdc_irq_handler, 0, NULL, "LTDC")) {258log_error("irq_attach failed");259return -1;260}261
262fb_create(&stm32cube_lcd_ops,263mmap_base,264STM32_LCD_WIDTH *265STM32_LCD_HEIGHT /2668 * STM32_LCD_BPP);267
268return 0;269}
270