drv_lcd_mipi.c 7.5 KB
Newer Older
W
Willian Chan 已提交
1
/*
mysterywolf's avatar
mysterywolf 已提交
2
 * Copyright (c) 2006-2021, RT-Thread Development Team
W
Willian Chan 已提交
3 4 5 6 7 8 9
 *
 * SPDX-License-Identifier: Apache-2.0
 *
 * Change Logs:
 * Date           Author         Notes
 * 2019-05-23     WillianChan    first version
 */
mysterywolf's avatar
mysterywolf 已提交
10

W
Willian Chan 已提交
11 12 13 14 15 16 17 18 19 20 21 22 23 24 25
#include <board.h>

#ifdef BSP_USING_LCD_MIPI
#include <lcd_port.h>
#include <string.h>

DSI_HandleTypeDef   hdsi;
DSI_VidCfgTypeDef   hdsi_video;
LTDC_HandleTypeDef  hltdc;

struct stm32_lcd
{
    struct rt_device parent;
    struct rt_device_graphic_info info;
};
mysterywolf's avatar
mysterywolf 已提交
26
static struct stm32_lcd lcd;
W
Willian Chan 已提交
27 28 29 30 31 32 33 34

extern void stm32_mipi_lcd_init(void);
extern void stm32_mipi_lcd_config(rt_uint32_t pixel_format);
extern void stm32_mipi_display_on(void);
extern void stm32_mipi_display_off(void);

rt_err_t ltdc_init(void)
{
mysterywolf's avatar
mysterywolf 已提交
35
    uint32_t lcd_clock      = 27429;
W
Willian Chan 已提交
36
    uint32_t lanebyte_clock = 62500;
mysterywolf's avatar
mysterywolf 已提交
37

W
Willian Chan 已提交
38 39 40 41
    uint32_t HSA = LCD_HSYNC, HFP = LCD_HFP, HBP = LCD_HBP, HACT = LCD_WIDTH;
    uint32_t VSA = LCD_VSYNC, VFP = LCD_VFP, VBP = LCD_VBP, VACT = LCD_HEIGHT;

    stm32_mipi_lcd_init();
mysterywolf's avatar
mysterywolf 已提交
42

W
Willian Chan 已提交
43 44 45 46 47 48 49
    __HAL_RCC_LTDC_CLK_ENABLE();
    __HAL_RCC_LTDC_FORCE_RESET();
    __HAL_RCC_LTDC_RELEASE_RESET();

    __HAL_RCC_DSI_CLK_ENABLE();
    __HAL_RCC_DSI_FORCE_RESET();
    __HAL_RCC_DSI_RELEASE_RESET();
mysterywolf's avatar
mysterywolf 已提交
50

W
Willian Chan 已提交
51
    RCC_PeriphCLKInitTypeDef PeriphClkInitStruct;
mysterywolf's avatar
mysterywolf 已提交
52

W
Willian Chan 已提交
53 54 55 56 57
    PeriphClkInitStruct.PeriphClockSelection = RCC_PERIPHCLK_LTDC;
    PeriphClkInitStruct.PLLSAI.PLLSAIN       = 384;
    PeriphClkInitStruct.PLLSAI.PLLSAIR       = 7;
    PeriphClkInitStruct.PLLSAIDivR           = RCC_PLLSAIDIVR_2;
    HAL_RCCEx_PeriphCLKConfig(&PeriphClkInitStruct);
mysterywolf's avatar
mysterywolf 已提交
58

W
Willian Chan 已提交
59 60 61 62 63
    HAL_NVIC_SetPriority(LTDC_IRQn,  3, 0);
    HAL_NVIC_SetPriority(DSI_IRQn,   3, 0);

    HAL_NVIC_EnableIRQ(LTDC_IRQn);
    HAL_NVIC_EnableIRQ(DSI_IRQn);
mysterywolf's avatar
mysterywolf 已提交
64

W
Willian Chan 已提交
65
    DSI_PLLInitTypeDef dsi_pll;
mysterywolf's avatar
mysterywolf 已提交
66 67

    hdsi.Instance = DSI;
W
Willian Chan 已提交
68 69
    hdsi.Init.NumberOfLanes = DSI_TWO_DATA_LANES;
    hdsi.Init.TXEscapeCkdiv = lanebyte_clock / 15620;
mysterywolf's avatar
mysterywolf 已提交
70

W
Willian Chan 已提交
71 72
    dsi_pll.PLLNDIV  = 125;
    dsi_pll.PLLIDF   = DSI_PLL_IN_DIV2;
mysterywolf's avatar
mysterywolf 已提交
73 74
    dsi_pll.PLLODF   = DSI_PLL_OUT_DIV1;

W
Willian Chan 已提交
75
    HAL_DSI_DeInit(&hdsi);
mysterywolf's avatar
mysterywolf 已提交
76 77
    HAL_DSI_Init(&hdsi, &dsi_pll);

W
Willian Chan 已提交
78 79 80 81 82
    hdsi_video.VirtualChannelID             = 0;
    hdsi_video.ColorCoding                  = DSI_RGB888;
    hdsi_video.VSPolarity                   = DSI_VSYNC_ACTIVE_HIGH;
    hdsi_video.HSPolarity                   = DSI_HSYNC_ACTIVE_HIGH;
    hdsi_video.DEPolarity                   = DSI_DATA_ENABLE_ACTIVE_HIGH;
mysterywolf's avatar
mysterywolf 已提交
83
    hdsi_video.Mode                         = DSI_VID_MODE_BURST;
W
Willian Chan 已提交
84 85
    hdsi_video.NullPacketSize               = 0xFFF;
    hdsi_video.NumberOfChunks               = 0;
mysterywolf's avatar
mysterywolf 已提交
86
    hdsi_video.PacketSize                   = HACT;
W
Willian Chan 已提交
87 88
    hdsi_video.HorizontalSyncActive         = (HSA * lanebyte_clock) / lcd_clock;
    hdsi_video.HorizontalBackPorch          = (HBP * lanebyte_clock) / lcd_clock;
mysterywolf's avatar
mysterywolf 已提交
89
    hdsi_video.HorizontalLine               = ((HACT + HSA + HBP + HFP) * lanebyte_clock) / lcd_clock;
W
Willian Chan 已提交
90 91 92
    hdsi_video.VerticalSyncActive           = VSA;
    hdsi_video.VerticalBackPorch            = VBP;
    hdsi_video.VerticalFrontPorch           = VFP;
mysterywolf's avatar
mysterywolf 已提交
93 94
    hdsi_video.VerticalActive               = VACT;
    hdsi_video.LPCommandEnable              = DSI_LP_COMMAND_ENABLE;
W
Willian Chan 已提交
95 96
    hdsi_video.LPLargestPacketSize          = 16;
    hdsi_video.LPVACTLargestPacketSize      = 0;
mysterywolf's avatar
mysterywolf 已提交
97 98 99 100 101 102 103 104
    hdsi_video.LPHorizontalFrontPorchEnable = DSI_LP_HFP_ENABLE;
    hdsi_video.LPHorizontalBackPorchEnable  = DSI_LP_HBP_ENABLE;
    hdsi_video.LPVerticalActiveEnable       = DSI_LP_VACT_ENABLE;
    hdsi_video.LPVerticalFrontPorchEnable   = DSI_LP_VFP_ENABLE;
    hdsi_video.LPVerticalBackPorchEnable    = DSI_LP_VBP_ENABLE;
    hdsi_video.LPVerticalSyncActiveEnable   = DSI_LP_VSYNC_ENABLE;
    HAL_DSI_ConfigVideoMode(&hdsi, &hdsi_video);

W
Willian Chan 已提交
105
    DSI_PHY_TimerTypeDef dsi_phy;
mysterywolf's avatar
mysterywolf 已提交
106

W
Willian Chan 已提交
107 108 109 110 111 112
    dsi_phy.ClockLaneHS2LPTime  = 35;
    dsi_phy.ClockLaneLP2HSTime  = 35;
    dsi_phy.DataLaneHS2LPTime   = 35;
    dsi_phy.DataLaneLP2HSTime   = 35;
    dsi_phy.DataLaneMaxReadTime = 0;
    dsi_phy.StopWaitTime        = 10;
mysterywolf's avatar
mysterywolf 已提交
113 114
    HAL_DSI_ConfigPhyTimer(&hdsi, &dsi_phy);

W
Willian Chan 已提交
115
    hltdc.Instance = LTDC;
mysterywolf's avatar
mysterywolf 已提交
116

W
Willian Chan 已提交
117 118 119 120 121
    hltdc.Init.PCPolarity         = LTDC_PCPOLARITY_IPC;
    hltdc.Init.HorizontalSync     = (HSA - 1);
    hltdc.Init.AccumulatedHBP     = (HSA + HBP - 1);
    hltdc.Init.AccumulatedActiveW = (LCD_WIDTH + HSA + HBP - 1);
    hltdc.Init.TotalWidth         = (LCD_WIDTH + HSA + HBP + HFP - 1);
mysterywolf's avatar
mysterywolf 已提交
122

W
Willian Chan 已提交
123
    hltdc.LayerCfg->ImageWidth    = LCD_WIDTH;
mysterywolf's avatar
mysterywolf 已提交
124
    hltdc.LayerCfg->ImageHeight   = LCD_HEIGHT;
W
Willian Chan 已提交
125 126 127
    hltdc.Init.Backcolor.Blue     = 0x00;
    hltdc.Init.Backcolor.Green    = 0x00;
    hltdc.Init.Backcolor.Red      = 0x00;
mysterywolf's avatar
mysterywolf 已提交
128
    HAL_LTDCEx_StructInitFromVideoConfig(&hltdc, &(hdsi_video));
W
Willian Chan 已提交
129
    HAL_LTDC_Init(&(hltdc));
mysterywolf's avatar
mysterywolf 已提交
130 131

    HAL_DSI_Start(&(hdsi));
W
Willian Chan 已提交
132 133

    stm32_mipi_lcd_config(RTGRAPHIC_PIXEL_FORMAT_ARGB888);
mysterywolf's avatar
mysterywolf 已提交
134 135

    return RT_EOK;
W
Willian Chan 已提交
136 137 138 139 140 141 142
}

void ltdc_layer_init(uint16_t index, uint32_t framebuffer)
{
    LTDC_LayerCfgTypeDef layer_cfg;

    layer_cfg.WindowX0        = 0;
mysterywolf's avatar
mysterywolf 已提交
143
    layer_cfg.WindowX1        = LCD_WIDTH;
W
Willian Chan 已提交
144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163
    layer_cfg.WindowY0        = 0;
    layer_cfg.WindowY1        = LCD_HEIGHT;
    layer_cfg.PixelFormat     = LTDC_PIXEL_FORMAT_ARGB8888;
    layer_cfg.BlendingFactor1 = LTDC_BLENDING_FACTOR1_PAxCA;
    layer_cfg.BlendingFactor2 = LTDC_BLENDING_FACTOR2_PAxCA;
    layer_cfg.Alpha           = 255;
    layer_cfg.Alpha0          = 0;
    layer_cfg.ImageWidth      = LCD_WIDTH;
    layer_cfg.ImageHeight     = LCD_HEIGHT;
    layer_cfg.Backcolor.Blue  = 0;
    layer_cfg.Backcolor.Green = 0;
    layer_cfg.Backcolor.Red   = 0;
    layer_cfg.FBStartAdress   = framebuffer;

    HAL_LTDC_ConfigLayer(&hltdc, &layer_cfg, index);
}

void LTDC_IRQHandler(void)
{
    rt_interrupt_enter();
mysterywolf's avatar
mysterywolf 已提交
164
    HAL_LTDC_IRQHandler(&hltdc);
W
Willian Chan 已提交
165 166 167 168 169 170 171 172 173
    rt_interrupt_leave();
}

static rt_err_t stm32_lcd_init(rt_device_t device)
{
    lcd.info.width          = LCD_WIDTH;
    lcd.info.height         = LCD_HEIGHT;
    lcd.info.pixel_format   = RTGRAPHIC_PIXEL_FORMAT_ARGB888;
    lcd.info.bits_per_pixel = 32;
mysterywolf's avatar
mysterywolf 已提交
174
    lcd.info.framebuffer    = (void *)rt_malloc_align(LCD_WIDTH * LCD_HEIGHT * (lcd.info.bits_per_pixel / 8), 32);
W
Willian Chan 已提交
175 176
    memset(lcd.info.framebuffer, 0, LCD_WIDTH * LCD_HEIGHT * (lcd.info.bits_per_pixel / 8));
    ltdc_init();
mysterywolf's avatar
mysterywolf 已提交
177 178
    ltdc_layer_init(0, (uint32_t)lcd.info.framebuffer);

W
Willian Chan 已提交
179 180 181 182 183 184 185 186 187 188
    return RT_EOK;
}

static rt_err_t stm32_lcd_control(rt_device_t device, int cmd, void *args)
{
    switch(cmd)
    {
    case RTGRAPHIC_CTRL_RECT_UPDATE:
        break;

mysterywolf's avatar
mysterywolf 已提交
189 190
    case RTGRAPHIC_CTRL_POWERON:
        stm32_mipi_display_on();
W
Willian Chan 已提交
191 192
        break;

mysterywolf's avatar
mysterywolf 已提交
193 194
    case RTGRAPHIC_CTRL_POWEROFF:
        stm32_mipi_display_off();
W
Willian Chan 已提交
195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212
        break;

    case RTGRAPHIC_CTRL_GET_INFO:
        rt_memcpy(args, &lcd.info, sizeof(lcd.info));
        break;

    case RTGRAPHIC_CTRL_SET_MODE:
        break;

    case RTGRAPHIC_CTRL_GET_EXT:
        break;
    }

    return RT_EOK;
}

int rt_hw_lcd_init(void)
{
mysterywolf's avatar
mysterywolf 已提交
213 214 215
    rt_err_t ret;

    rt_memset(&lcd, 0x00, sizeof(lcd));
W
Willian Chan 已提交
216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254

    lcd.parent.type    = RT_Device_Class_Graphic;
    lcd.parent.init    = stm32_lcd_init;
    lcd.parent.open    = RT_NULL;
    lcd.parent.close   = RT_NULL;
    lcd.parent.read    = RT_NULL;
    lcd.parent.write   = RT_NULL;
    lcd.parent.control = stm32_lcd_control;

    lcd.parent.user_data = (void *)&lcd.info;

    ret = rt_device_register(&lcd.parent, "lcd", RT_DEVICE_FLAG_RDWR);

    return ret;
}
INIT_DEVICE_EXPORT(rt_hw_lcd_init);


RT_WEAK void stm32_mipi_lcd_init(void)
{
    rt_kprintf("please Implementation function %s\n", __func__);
}

RT_WEAK void stm32_mipi_lcd_config(rt_uint32_t pixel_format)
{
    rt_kprintf("please Implementation function %s\n", __func__);
}

RT_WEAK void stm32_mipi_display_on(void)
{
    rt_kprintf("please Implementation function %s\n", __func__);
}

RT_WEAK void stm32_mipi_display_off(void)
{
    rt_kprintf("please Implementation function %s\n", __func__);
}

#endif /* BSP_USING_LCD_MIPI */