1 /*
2 * Copyright (c) 2015 Travis Geiselbrecht
3 *
4 * Use of this source code is governed by a MIT-style
5 * license that can be found in the LICENSE file or at
6 * https://opensource.org/licenses/MIT
7 */
8 /*
9 * COPYRIGHT(c) 2015 STMicroelectronics
10 *
11 * Redistribution and use in source and binary forms, with or without modification,
12 * are permitted provided that the following conditions are met:
13 * 1. Redistributions of source code must retain the above copyright notice,
14 * this list of conditions and the following disclaimer.
15 * 2. Redistributions in binary form must reproduce the above copyright notice,
16 * this list of conditions and the following disclaimer in the documentation
17 * and/or other materials provided with the distribution.
18 * 3. Neither the name of STMicroelectronics nor the names of its contributors
19 * may be used to endorse or promote products derived from this software
20 * without specific prior written permission.
21 *
22 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
23 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
24 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
25 * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
26 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
27 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
28 * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
29 * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
30 * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
31 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
32 *
33 ******************************************************************************
34 */
35
36 #include <assert.h>
37 #include <lk/err.h>
38 #include <lk/debug.h>
39 #include <lk/trace.h>
40 #include <target.h>
41 #include <lk/compiler.h>
42 #include <string.h>
43 #include <dev/gpio.h>
44 #include <dev/display.h>
45 #include <arch/ops.h>
46 #include <platform/stm32.h>
47
48 /*
49 * lcd initialization sequence, taken from
50 * STM32Cube_FW_F7_V1.1.0/Drivers/BSP/STM32756G_EVAL/stm32756g_eval_lcd.[ch]
51 */
52
53 /**
54 * @brief AMPIRE640480 Size
55 */
56 #define AMPIRE640480_WIDTH ((uint16_t)640) /* LCD PIXEL WIDTH */
57 #define AMPIRE640480_HEIGHT ((uint16_t)480) /* LCD PIXEL HEIGHT */
58
59 /**
60 * @brief AMPIRE640480 Timing
61 */
62 #define AMPIRE640480_HSYNC ((uint16_t)30) /* Horizontal synchronization */
63 #define AMPIRE640480_HBP ((uint16_t)114) /* Horizontal back porch */
64 #define AMPIRE640480_HFP ((uint16_t)16) /* Horizontal front porch */
65 #define AMPIRE640480_VSYNC ((uint16_t)3) /* Vertical synchronization */
66 #define AMPIRE640480_VBP ((uint16_t)32) /* Vertical back porch */
67 #define AMPIRE640480_VFP ((uint16_t)10) /* Vertical front porch */
68
69 /**
70 * @brief AMPIRE640480 frequency divider
71 */
72 #define AMPIRE640480_FREQUENCY_DIVIDER 3 /* LCD Frequency divider */
73
74 /** @defgroup STM32756G_EVAL_LCD_Exported_Constants
75 * @{
76 */
77 #define MAX_LAYER_NUMBER ((uint32_t)2)
78
79 #define LCD_LayerCfgTypeDef LTDC_LayerCfgTypeDef
80
81 #define LTDC_ACTIVE_LAYER ((uint32_t)1) /* Layer 1 */
82 /**
83 * @brief LCD status structure definition
84 */
85 #define LCD_OK ((uint8_t)0x00)
86 #define LCD_ERROR ((uint8_t)0x01)
87 #define LCD_TIMEOUT ((uint8_t)0x02)
88
89 /**
90 * @brief LCD FB_StartAddress
91 */
92 #define LCD_FB_START_ADDRESS ((uint32_t)SDRAM_BASE)
93 //#define LCD_FB_START_ADDRESS ((uint32_t)EXT_SRAM_BASE)
94
95 //#define LCD_PIXEL_FORMAT LTDC_PIXEL_FORMAT_ARGB888
96 #define LCD_PIXEL_FORMAT LTDC_PIXEL_FORMAT_RGB565
97
98 static LTDC_HandleTypeDef hLtdcEval;
99
100 /* Default LCD configuration with LCD Layer 1 */
101 static uint32_t ActiveLayer = 0;
102
103 /**
104 * @brief Gets the LCD X size.
105 * @retval Used LCD X size
106 */
BSP_LCD_GetXSize(void)107 uint32_t BSP_LCD_GetXSize(void) {
108 return hLtdcEval.LayerCfg[ActiveLayer].ImageWidth;
109 }
110
111 /**
112 * @brief Gets the LCD Y size.
113 * @retval Used LCD Y size
114 */
BSP_LCD_GetYSize(void)115 uint32_t BSP_LCD_GetYSize(void) {
116 return hLtdcEval.LayerCfg[ActiveLayer].ImageHeight;
117 }
118
119 /**
120 * @brief Set the LCD X size.
121 * @param imageWidthPixels : image width in pixels unit
122 * @retval None
123 */
BSP_LCD_SetXSize(uint32_t imageWidthPixels)124 void BSP_LCD_SetXSize(uint32_t imageWidthPixels) {
125 hLtdcEval.LayerCfg[ActiveLayer].ImageWidth = imageWidthPixels;
126 }
127
128 /**
129 * @brief Set the LCD Y size.
130 * @param imageHeightPixels : image height in lines unit
131 * @retval None
132 */
BSP_LCD_SetYSize(uint32_t imageHeightPixels)133 void BSP_LCD_SetYSize(uint32_t imageHeightPixels) {
134 hLtdcEval.LayerCfg[ActiveLayer].ImageHeight = imageHeightPixels;
135 }
136
BSP_LCD_PixelSize(void)137 static size_t BSP_LCD_PixelSize(void) {
138 return (hLtdcEval.LayerCfg[ActiveLayer].PixelFormat == LTDC_PIXEL_FORMAT_ARGB8888) ? 4 : 2;
139 }
140
141 /**
142 * @brief Initializes the LCD layers.
143 * @param LayerIndex: Layer foreground or background
144 * @param FB_Address: Layer frame buffer
145 * @retval None
146 */
BSP_LCD_LayerDefaultInit(uint16_t LayerIndex,uint32_t FB_Address)147 void BSP_LCD_LayerDefaultInit(uint16_t LayerIndex, uint32_t FB_Address) {
148 LCD_LayerCfgTypeDef layer_cfg;
149
150 /* Layer Init */
151 layer_cfg.WindowX0 = 0;
152 layer_cfg.WindowX1 = BSP_LCD_GetXSize();
153 layer_cfg.WindowY0 = 0;
154 layer_cfg.WindowY1 = BSP_LCD_GetYSize();
155 layer_cfg.PixelFormat = LCD_PIXEL_FORMAT;
156 layer_cfg.FBStartAdress = FB_Address;
157 layer_cfg.Alpha = 255;
158 layer_cfg.Alpha0 = 0;
159 layer_cfg.Backcolor.Blue = 0;
160 layer_cfg.Backcolor.Green = 0;
161 layer_cfg.Backcolor.Red = 0;
162 layer_cfg.BlendingFactor1 = LTDC_BLENDING_FACTOR1_PAxCA;
163 layer_cfg.BlendingFactor2 = LTDC_BLENDING_FACTOR2_PAxCA;
164 layer_cfg.ImageWidth = BSP_LCD_GetXSize();
165 layer_cfg.ImageHeight = BSP_LCD_GetYSize();
166
167 HAL_LTDC_ConfigLayer(&hLtdcEval, &layer_cfg, LayerIndex);
168 }
169
170
171 /**
172 * @brief Selects the LCD Layer.
173 * @param LayerIndex: Layer foreground or background
174 * @retval None
175 */
BSP_LCD_SelectLayer(uint32_t LayerIndex)176 void BSP_LCD_SelectLayer(uint32_t LayerIndex) {
177 ActiveLayer = LayerIndex;
178 }
179
180 /**
181 * @brief Sets an LCD Layer visible
182 * @param LayerIndex: Visible Layer
183 * @param State: New state of the specified layer
184 * This parameter can be one of the following values:
185 * @arg ENABLE
186 * @arg DISABLE
187 * @retval None
188 */
BSP_LCD_SetLayerVisible(uint32_t LayerIndex,FunctionalState State)189 void BSP_LCD_SetLayerVisible(uint32_t LayerIndex, FunctionalState State) {
190 if (State == ENABLE) {
191 __HAL_LTDC_LAYER_ENABLE(&hLtdcEval, LayerIndex);
192 } else {
193 __HAL_LTDC_LAYER_DISABLE(&hLtdcEval, LayerIndex);
194 }
195 __HAL_LTDC_RELOAD_CONFIG(&hLtdcEval);
196 }
197
198 /**
199 * @brief Configures the transparency.
200 * @param LayerIndex: Layer foreground or background.
201 * @param Transparency: Transparency
202 * This parameter must be a number between Min_Data = 0x00 and Max_Data = 0xFF
203 * @retval None
204 */
BSP_LCD_SetTransparency(uint32_t LayerIndex,uint8_t Transparency)205 void BSP_LCD_SetTransparency(uint32_t LayerIndex, uint8_t Transparency) {
206 HAL_LTDC_SetAlpha(&hLtdcEval, Transparency, LayerIndex);
207 }
208
209 /**
210 * @brief Sets an LCD layer frame buffer address.
211 * @param LayerIndex: Layer foreground or background
212 * @param Address: New LCD frame buffer value
213 * @retval None
214 */
BSP_LCD_SetLayerAddress(uint32_t LayerIndex,uint32_t Address)215 void BSP_LCD_SetLayerAddress(uint32_t LayerIndex, uint32_t Address) {
216 HAL_LTDC_SetAddress(&hLtdcEval, Address, LayerIndex);
217 }
218
219 /**
220 * @brief Enables the display.
221 * @retval None
222 */
BSP_LCD_DisplayOn(void)223 void BSP_LCD_DisplayOn(void) {
224 /* Display On */
225 __HAL_LTDC_ENABLE(&hLtdcEval);
226 }
227
228 /**
229 * @brief Disables the display.
230 * @retval None
231 */
BSP_LCD_DisplayOff(void)232 void BSP_LCD_DisplayOff(void) {
233 /* Display Off */
234 __HAL_LTDC_DISABLE(&hLtdcEval);
235 }
236
237 /**
238 * @brief Initializes the LTDC MSP.
239 * @param hltdc: LTDC handle
240 * @retval None
241 */
BSP_LCD_MspInit(LTDC_HandleTypeDef * hltdc,void * Params)242 static void BSP_LCD_MspInit(LTDC_HandleTypeDef *hltdc, void *Params) {
243 GPIO_InitTypeDef gpio_init_structure;
244
245 /* Enable the LTDC and DMA2D clocks */
246 __HAL_RCC_LTDC_CLK_ENABLE();
247 __HAL_RCC_DMA2D_CLK_ENABLE();
248
249 /* Enable GPIOs clock */
250 __HAL_RCC_GPIOI_CLK_ENABLE();
251 __HAL_RCC_GPIOJ_CLK_ENABLE();
252 __HAL_RCC_GPIOK_CLK_ENABLE();
253
254 /*** LTDC Pins configuration ***/
255 /* GPIOI configuration */
256 gpio_init_structure.Pin = GPIO_PIN_12 | GPIO_PIN_13 | GPIO_PIN_14 | GPIO_PIN_15;
257 gpio_init_structure.Mode = GPIO_MODE_AF_PP;
258 gpio_init_structure.Pull = GPIO_NOPULL;
259 gpio_init_structure.Speed = GPIO_SPEED_FAST;
260 gpio_init_structure.Alternate = GPIO_AF14_LTDC;
261 HAL_GPIO_Init(GPIOI, &gpio_init_structure);
262
263 /* GPIOJ configuration */
264 gpio_init_structure.Pin = GPIO_PIN_0 | GPIO_PIN_1 | GPIO_PIN_2 | GPIO_PIN_3 | \
265 GPIO_PIN_4 | GPIO_PIN_5 | GPIO_PIN_6 | GPIO_PIN_7 | \
266 GPIO_PIN_8 | GPIO_PIN_9 | GPIO_PIN_10 | GPIO_PIN_11 | \
267 GPIO_PIN_12 | GPIO_PIN_13 | GPIO_PIN_14 | GPIO_PIN_15;
268 gpio_init_structure.Mode = GPIO_MODE_AF_PP;
269 gpio_init_structure.Pull = GPIO_NOPULL;
270 gpio_init_structure.Speed = GPIO_SPEED_FAST;
271 gpio_init_structure.Alternate = GPIO_AF14_LTDC;
272 HAL_GPIO_Init(GPIOJ, &gpio_init_structure);
273
274 /* GPIOK configuration */
275 gpio_init_structure.Pin = GPIO_PIN_0 | GPIO_PIN_1 | GPIO_PIN_2 | GPIO_PIN_3 | \
276 GPIO_PIN_4 | GPIO_PIN_5 | GPIO_PIN_6 | GPIO_PIN_7;
277 gpio_init_structure.Mode = GPIO_MODE_AF_PP;
278 gpio_init_structure.Pull = GPIO_NOPULL;
279 gpio_init_structure.Speed = GPIO_SPEED_FAST;
280 gpio_init_structure.Alternate = GPIO_AF14_LTDC;
281 HAL_GPIO_Init(GPIOK, &gpio_init_structure);
282 }
283
284 /**
285 * @brief Clock Config.
286 * @param hltdc: LTDC handle
287 * @note This API is called by BSP_LCD_Init()
288 * Being __weak it can be overwritten by the application
289 * @retval None
290 */
BSP_LCD_ClockConfig(LTDC_HandleTypeDef * hltdc,void * Params)291 static void BSP_LCD_ClockConfig(LTDC_HandleTypeDef *hltdc, void *Params) {
292 static RCC_PeriphCLKInitTypeDef periph_clk_init_struct;
293
294 /* AMPIRE640480 LCD clock configuration */
295 /* PLLSAI_VCO Input = HSE_VALUE/PLL_M = 1 Mhz */
296 /* PLLSAI_VCO Output = PLLSAI_VCO Input * PLLSAIN = 151 Mhz */
297 /* PLLLCDCLK = PLLSAI_VCO Output/PLLSAIR = 151/3 = 50.3 Mhz */
298 /* LTDC clock frequency = PLLLCDCLK / LTDC_PLLSAI_DIVR_2 = 50.3/2 = 25.1 Mhz */
299 periph_clk_init_struct.PeriphClockSelection = RCC_PERIPHCLK_LTDC;
300 periph_clk_init_struct.PLLSAI.PLLSAIN = 151;
301 periph_clk_init_struct.PLLSAI.PLLSAIR = AMPIRE640480_FREQUENCY_DIVIDER;
302 periph_clk_init_struct.PLLSAIDivR = RCC_PLLSAIDIVR_2;
303 HAL_RCCEx_PeriphCLKConfig(&periph_clk_init_struct);
304 }
305
306 /**
307 * @brief Initializes the LCD.
308 * @retval LCD state
309 */
BSP_LCD_Init(void)310 uint8_t BSP_LCD_Init(void) {
311 /* Select the used LCD */
312 /* The LCD AMPIRE 640x480 is selected */
313 /* Timing configuration */
314 hLtdcEval.Init.HorizontalSync = (AMPIRE640480_HSYNC - 1);
315 hLtdcEval.Init.VerticalSync = (AMPIRE640480_VSYNC - 1);
316 hLtdcEval.Init.AccumulatedHBP = (AMPIRE640480_HSYNC + AMPIRE640480_HBP - 1);
317 hLtdcEval.Init.AccumulatedVBP = (AMPIRE640480_VSYNC + AMPIRE640480_VBP - 1);
318 hLtdcEval.Init.AccumulatedActiveH = (AMPIRE640480_HEIGHT + AMPIRE640480_VSYNC + AMPIRE640480_VBP - 1);
319 hLtdcEval.Init.AccumulatedActiveW = (AMPIRE640480_WIDTH + AMPIRE640480_HSYNC + AMPIRE640480_HBP - 1);
320 hLtdcEval.Init.TotalHeigh = (AMPIRE640480_HEIGHT + AMPIRE640480_VSYNC + AMPIRE640480_VBP + AMPIRE640480_VFP - 1);
321 hLtdcEval.Init.TotalWidth = (AMPIRE640480_WIDTH + AMPIRE640480_HSYNC + AMPIRE640480_HBP + AMPIRE640480_HFP - 1);
322
323 /* LCD clock configuration */
324 BSP_LCD_ClockConfig(&hLtdcEval, NULL);
325
326 /* Initialize the LCD pixel width and pixel height */
327 hLtdcEval.LayerCfg->ImageWidth = AMPIRE640480_WIDTH;
328 hLtdcEval.LayerCfg->ImageHeight = AMPIRE640480_HEIGHT;
329
330 /* Background value */
331 hLtdcEval.Init.Backcolor.Blue = 0;
332 hLtdcEval.Init.Backcolor.Green = 0;
333 hLtdcEval.Init.Backcolor.Red = 0;
334
335 /* Polarity */
336 hLtdcEval.Init.HSPolarity = LTDC_HSPOLARITY_AL;
337 hLtdcEval.Init.VSPolarity = LTDC_VSPOLARITY_AL;
338 hLtdcEval.Init.DEPolarity = LTDC_DEPOLARITY_AL;
339 hLtdcEval.Init.PCPolarity = LTDC_PCPOLARITY_IPC;
340 hLtdcEval.Instance = LTDC;
341
342 if (HAL_LTDC_GetState(&hLtdcEval) == HAL_LTDC_STATE_RESET) {
343 /* Initialize the LCD Msp: this __weak function can be rewritten by the application */
344 BSP_LCD_MspInit(&hLtdcEval, NULL);
345 }
346 HAL_LTDC_Init(&hLtdcEval);
347
348 /* set a default layer to the base of sdram */
349 BSP_LCD_LayerDefaultInit(0, LCD_FB_START_ADDRESS);
350 BSP_LCD_SelectLayer(0);
351
352 /* clear it out */
353 memset((void *)hLtdcEval.LayerCfg[ActiveLayer].FBStartAdress, 0, BSP_LCD_GetXSize() * BSP_LCD_GetYSize() * BSP_LCD_PixelSize());
354
355 /* turn the display on */
356 BSP_LCD_DisplayOn();
357
358 return LCD_OK;
359 }
360
361 /* LK display api here */
display_get_framebuffer(struct display_framebuffer * fb)362 status_t display_get_framebuffer(struct display_framebuffer *fb) {
363 fb->image.pixels = (void *)hLtdcEval.LayerCfg[ActiveLayer].FBStartAdress;
364
365 if (hLtdcEval.LayerCfg[ActiveLayer].PixelFormat == LTDC_PIXEL_FORMAT_ARGB8888) {
366 fb->format = DISPLAY_FORMAT_ARGB_8888;
367 fb->image.format = IMAGE_FORMAT_ARGB_8888;
368 fb->image.rowbytes = BSP_LCD_GetXSize() * 4;
369 } else if (hLtdcEval.LayerCfg[ActiveLayer].PixelFormat == LTDC_PIXEL_FORMAT_RGB565) {
370 fb->format = DISPLAY_FORMAT_RGB_565;
371 fb->image.format = IMAGE_FORMAT_RGB_565;
372 fb->image.rowbytes = BSP_LCD_GetXSize() * 2;
373 } else {
374 panic("unhandled pixel format\n");
375 return ERR_NOT_FOUND;
376 }
377
378 fb->image.width = BSP_LCD_GetXSize();
379 fb->image.height = BSP_LCD_GetYSize();
380 fb->image.stride = BSP_LCD_GetXSize();
381 fb->flush = NULL;
382
383 return NO_ERROR;
384 }
385
display_get_info(struct display_info * info)386 status_t display_get_info(struct display_info *info) {
387 if (hLtdcEval.LayerCfg[ActiveLayer].PixelFormat == LTDC_PIXEL_FORMAT_ARGB8888) {
388 info->format = DISPLAY_FORMAT_ARGB_8888;
389 } else if (hLtdcEval.LayerCfg[ActiveLayer].PixelFormat == LTDC_PIXEL_FORMAT_RGB565) {
390 info->format = DISPLAY_FORMAT_RGB_565;
391 } else {
392 panic("unhandled pixel format\n");
393 return ERR_NOT_FOUND;
394 }
395
396 info->width = BSP_LCD_GetXSize();
397 info->height = BSP_LCD_GetYSize();
398
399 return NO_ERROR;
400 }
401
display_present(struct display_image * image,uint starty,uint endy)402 status_t display_present(struct display_image *image, uint starty, uint endy) {
403 TRACEF("display_present - not implemented");
404 DEBUG_ASSERT(false);
405 return NO_ERROR;
406 }
407