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