drv_lcd.c 7.1 KB
Newer Older
1
/*
2
 * File      : drv_lcd.c
3
 * This file is part of RT-Thread RTOS
4
 * COPYRIGHT (C) 2006-2013, RT-Thread Development Team
5 6 7 8 9 10 11 12
 *
 * The license and distribution terms for this file may be
 * found in the file LICENSE in this distribution or at
 * http://www.rt-thread.org/license/LICENSE
 *
 * Change Logs:
 * Date           Author       Notes
 * 2017-10-30     Tanek        the first version
13
 * 2018-04-05     Liu2guang    export LCD config parameters.
14
 */
15 16

#include "drv_lcd.h"
17 18

#include "fsl_common.h"
19
#include "fsl_iomuxc.h"
20 21
#include "fsl_elcdif.h"

22 23
#if !defined(LCD_WIDTH) || !defined(LCD_HEIGHT)
    #error "Please config lcd pixel parameters."
24 25
#endif

26 27
#if !defined(LCD_HFP) || !defined(LCD_HBP) || !defined(LCD_HSW) || \
    !defined(LCD_VFP) || !defined(LCD_VBP) || !defined(LCD_VSW)
28
    #error "Please config lcd timing parameters."
29
#endif
30

31 32
#if !defined(LCD_BL_PIN) || !defined(LCD_RST_PIN)
    #error "Please config lcd backlight or reset pin."
33
#endif
34

35
struct rt1050_lcd
36
{
37 38 39
    struct rt_device device;
    struct rt_device_graphic_info info;
};
40

41 42
static struct rt1050_lcd lcd;
ALIGN(64) static uint16_t frame_buffer[LCD_HEIGHT][LCD_WIDTH] SECTION("NonCacheable");
43

44
static rt_err_t rt1050_lcd_init(rt_device_t device)
45
{
46 47 48 49
    RT_ASSERT(device != RT_NULL);

    rt_memset(frame_buffer, 0x00, sizeof(frame_buffer));

50 51
    /* DeInit Video PLL. */
    CLOCK_DeinitVideoPll();
52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145

    /*
     * Initialize the Video PLL.
     * Video PLL output clock is OSC24M * (loopDivider + (denominator / numerator)) / postDivider = 93MHz.
     */
    clock_video_pll_config_t config =
    {
        .loopDivider = 31, .postDivider = 8, .numerator = 0, .denominator = 1,
    };

    CLOCK_InitVideoPll(&config);

    /*
     * 000 derive clock from PLL2
     * 001 derive clock from PLL3 PFD3
     * 010 derive clock from PLL5
     * 011 derive clock from PLL2 PFD0
     * 100 derive clock from PLL2 PFD1
     * 101 derive clock from PLL3 PFD1
     */
    CLOCK_SetMux(kCLOCK_LcdifPreMux, 2);

    CLOCK_SetDiv(kCLOCK_LcdifPreDiv, 4);

    CLOCK_SetDiv(kCLOCK_LcdifDiv, 1);

    /* GPIO */
    CLOCK_EnableClock(kCLOCK_Iomuxc);

    IOMUXC_SetPinMux(IOMUXC_GPIO_B0_04_LCD_DATA00, 0U);
    IOMUXC_SetPinConfig(IOMUXC_GPIO_B0_04_LCD_DATA00, 0x01B0B0U); /* LCD_B3 */
    IOMUXC_SetPinMux(IOMUXC_GPIO_B0_05_LCD_DATA01, 0U);
    IOMUXC_SetPinConfig(IOMUXC_GPIO_B0_05_LCD_DATA01, 0x01B0B0U); /* LCD_B4 */
    IOMUXC_SetPinMux(IOMUXC_GPIO_B0_06_LCD_DATA02, 0U);
    IOMUXC_SetPinConfig(IOMUXC_GPIO_B0_06_LCD_DATA02, 0x01B0B0U); /* LCD_B5 */
    IOMUXC_SetPinMux(IOMUXC_GPIO_B0_07_LCD_DATA03, 0U);
    IOMUXC_SetPinConfig(IOMUXC_GPIO_B0_07_LCD_DATA03, 0x01B0B0U); /* LCD_B6 */
    IOMUXC_SetPinMux(IOMUXC_GPIO_B0_08_LCD_DATA04, 0U);
    IOMUXC_SetPinConfig(IOMUXC_GPIO_B0_08_LCD_DATA04, 0x01B0B0U); /* LCD_B7 */

    IOMUXC_SetPinMux(IOMUXC_GPIO_B0_09_LCD_DATA05, 0U);
    IOMUXC_SetPinConfig(IOMUXC_GPIO_B0_09_LCD_DATA05, 0x01B0B0U); /* LCD_G2 */
    IOMUXC_SetPinMux(IOMUXC_GPIO_B0_10_LCD_DATA06, 0U);
    IOMUXC_SetPinConfig(IOMUXC_GPIO_B0_10_LCD_DATA06, 0x01B0B0U); /* LCD_G3 */
    IOMUXC_SetPinMux(IOMUXC_GPIO_B0_11_LCD_DATA07, 0U);
    IOMUXC_SetPinConfig(IOMUXC_GPIO_B0_11_LCD_DATA07, 0x01B0B0U); /* LCD_G4 */
    IOMUXC_SetPinMux(IOMUXC_GPIO_B0_12_LCD_DATA08, 0U);
    IOMUXC_SetPinConfig(IOMUXC_GPIO_B0_12_LCD_DATA08, 0x01B0B0U); /* LCD_G5 */
    IOMUXC_SetPinMux(IOMUXC_GPIO_B0_13_LCD_DATA09, 0U);
    IOMUXC_SetPinConfig(IOMUXC_GPIO_B0_13_LCD_DATA09, 0x01B0B0U); /* LCD_G6 */
    IOMUXC_SetPinMux(IOMUXC_GPIO_B0_14_LCD_DATA10, 0U);
    IOMUXC_SetPinConfig(IOMUXC_GPIO_B0_14_LCD_DATA10, 0x01B0B0U); /* LCD_G7 */

    IOMUXC_SetPinMux(IOMUXC_GPIO_B0_15_LCD_DATA11, 0U);
    IOMUXC_SetPinConfig(IOMUXC_GPIO_B0_15_LCD_DATA11, 0x01B0B0U); /* LCD_R3 */
    IOMUXC_SetPinMux(IOMUXC_GPIO_B1_00_LCD_DATA12, 0U);
    IOMUXC_SetPinConfig(IOMUXC_GPIO_B1_00_LCD_DATA12, 0x01B0B0U); /* LCD_R4 */
    IOMUXC_SetPinMux(IOMUXC_GPIO_B1_01_LCD_DATA13, 0U);
    IOMUXC_SetPinConfig(IOMUXC_GPIO_B1_01_LCD_DATA13, 0x01B0B0U); /* LCD_R5 */
    IOMUXC_SetPinMux(IOMUXC_GPIO_B1_02_LCD_DATA14, 0U);
    IOMUXC_SetPinConfig(IOMUXC_GPIO_B1_02_LCD_DATA14, 0x01B0B0U); /* LCD_R6 */
    IOMUXC_SetPinMux(IOMUXC_GPIO_B1_03_LCD_DATA15, 0U);
    IOMUXC_SetPinConfig(IOMUXC_GPIO_B1_03_LCD_DATA15, 0x01B0B0U); /* LCD_R7 */

    IOMUXC_SetPinMux(IOMUXC_GPIO_B0_00_LCD_CLK,    0U);
    IOMUXC_SetPinConfig(IOMUXC_GPIO_B0_00_LCD_CLK,    0x01B0B0u); /* LCD_CLK */
    IOMUXC_SetPinMux(IOMUXC_GPIO_B0_02_LCD_HSYNC,  0U);
    IOMUXC_SetPinConfig(IOMUXC_GPIO_B0_02_LCD_HSYNC,  0x01B0B0u); /* LCD_HSYNC */
    IOMUXC_SetPinMux(IOMUXC_GPIO_B0_03_LCD_VSYNC,  0U);
    IOMUXC_SetPinConfig(IOMUXC_GPIO_B0_03_LCD_VSYNC,  0x01B0B0u); /* LCD_VSYNC */
    IOMUXC_SetPinMux(IOMUXC_GPIO_B0_01_LCD_ENABLE, 0U);
    IOMUXC_SetPinConfig(IOMUXC_GPIO_B0_01_LCD_ENABLE, 0x01B0B0u); /* LCD_ENABLE */

    rt_pin_mode(LCD_RST_PIN, PIN_MODE_OUTPUT); /* LCD_RESET */
    rt_pin_write(LCD_RST_PIN, PIN_LOW);
    rt_thread_delay(RT_TICK_PER_SECOND / 100);
    rt_pin_write(LCD_RST_PIN, PIN_HIGH);

    rt_pin_mode(LCD_BL_PIN, PIN_MODE_OUTPUT);   /* LCD_BL */
    rt_pin_write(LCD_BL_PIN, PIN_HIGH);

    /* LCD */
    elcdif_rgb_mode_config_t lcd_config;

    lcd_config.hfp           = LCD_HFP;
    lcd_config.vfp           = LCD_VFP;
    lcd_config.hbp           = LCD_HBP;
    lcd_config.vbp           = LCD_VBP;
    lcd_config.hsw           = LCD_HSW;
    lcd_config.vsw           = LCD_VSW;

    lcd_config.polarityFlags = kELCDIF_DataEnableActiveHigh |
                               kELCDIF_VsyncActiveHigh      |
                               kELCDIF_HsyncActiveLow       |
146
                               kELCDIF_DriveDataOnRisingClkEdge;
147 148 149 150 151 152 153 154 155 156

    lcd_config.panelWidth    = LCD_WIDTH;
    lcd_config.panelHeight   = LCD_HEIGHT;
    lcd_config.pixelFormat   = kELCDIF_PixelFormatRGB565;
    lcd_config.dataBus       = kELCDIF_DataBus16Bit;
    lcd_config.bufferAddr    = (uint32_t)frame_buffer;

    ELCDIF_RgbModeInit(LCDIF, &lcd_config);
    ELCDIF_RgbModeStart(LCDIF);

157 158 159 160
    /* LCD DEVICE */
    lcd.info.width          = LCD_WIDTH;
    lcd.info.height         = LCD_HEIGHT;
    lcd.info.pixel_format   = RTGRAPHIC_PIXEL_FORMAT_RGB565;
161
    lcd.info.bits_per_pixel = 16;
162 163
    lcd.info.framebuffer    = (void *)frame_buffer;

164
    return RT_EOK;
165 166
}

167
static rt_err_t rt1050_lcd_control(rt_device_t device, int cmd, void *args)
168
{
169
    switch (cmd)
170
    {
171
    case RTGRAPHIC_CTRL_RECT_UPDATE:
172
        break;
173 174 175

    case RTGRAPHIC_CTRL_POWERON:
        rt_pin_write(LCD_BL_PIN, PIN_HIGH);
176
        break;
177 178 179

    case RTGRAPHIC_CTRL_POWEROFF:
        rt_pin_write(LCD_BL_PIN, PIN_LOW);
180
        break;
181

182
    case RTGRAPHIC_CTRL_GET_INFO:
183
        rt_memcpy(args, &lcd.info, sizeof(lcd.info));
184
        break;
185

186 187 188 189 190 191 192
    case RTGRAPHIC_CTRL_SET_MODE:
        break;
    }

    return RT_EOK;
}

193
int rt_hw_lcd_init(void)
194
{
195
    rt_err_t ret;
196

197 198
    lcd.device.type    = RT_Device_Class_Graphic;
    lcd.device.init    = rt1050_lcd_init;
199 200 201 202
    lcd.device.open    = RT_NULL;
    lcd.device.close   = RT_NULL;
    lcd.device.read    = RT_NULL;
    lcd.device.write   = RT_NULL;
203 204 205 206 207 208 209
    lcd.device.control = rt1050_lcd_control;

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

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

    return ret;
210
}
211
INIT_DEVICE_EXPORT(rt_hw_lcd_init);