/* * Copyright (c) 2020-2021 Huawei Device Co., Ltd. * * HDF is dual licensed: you can use it either under the terms of * the GPL, or the BSD license, at your option. * See the LICENSE file in the root of this repository for complete details. */ #include "gpio_if.h" #include "hdf_device_desc.h" #include "hdf_log.h" #include "osal_mem.h" #include "osal_time.h" #include "spi_if.h" #include "ssp_st7789.h" #define WIDTH 240 #define HEIGHT 320 #define FRAME_RATE 50 static struct LcdCmd g_onCmd[] = { { LCD_CMD, 0x11, 120 }, { LCD_CMD, 0x36, 0 }, { LCD_DATA, 0x00, 0 }, { LCD_CMD, 0xb2, 0 }, { LCD_DATA, 0x00, 0 }, { LCD_DATA, 0x00, 0 }, { LCD_DATA, 0x00, 0 }, { LCD_DATA, 0x33, 0 }, { LCD_DATA, 0x33, 0 }, { LCD_CMD, 0xb7, 0 }, { LCD_DATA, 0x35, 0 }, { LCD_CMD, 0xb8, 0 }, { LCD_DATA, 0x2f, 0 }, { LCD_DATA, 0x2b, 0 }, { LCD_DATA, 0x2f, 0 }, { LCD_CMD, 0xbb, 0 }, { LCD_DATA, 0x24, 0 }, { LCD_CMD, 0xc0, 0 }, { LCD_DATA, 0x2c, 0 }, { LCD_CMD, 0xc3, 0 }, { LCD_DATA, 0x20, 0 }, { LCD_CMD, 0xc4, 0 }, { LCD_DATA, 0x03, 0 }, { LCD_CMD, 0xc6, 0 }, { LCD_DATA, 0x11, 0 }, { LCD_CMD, 0xd0, 0 }, { LCD_DATA, 0xa4, 0 }, { LCD_DATA, 0xa1, 0 }, { LCD_CMD, 0xe8, 0 }, { LCD_DATA, 0x03, 0 }, { LCD_CMD, 0xe9, 0 }, { LCD_DATA, 0x0d, 0 }, { LCD_DATA, 0x12, 0 }, { LCD_DATA, 0x00, 0 }, { LCD_CMD, 0x21, 0 }, { LCD_CMD, 0xb0, 0 }, { LCD_DATA, 0x11, 0 }, { LCD_DATA, 0x04, 0 }, { LCD_DATA, 0x00, 0 }, { LCD_CMD, 0xb1, 0 }, { LCD_DATA, 0xc0, 0 }, { LCD_DATA, 0x02, 0 }, { LCD_DATA, 0x14, 0 }, { LCD_CMD, 0x3a, 0 }, { LCD_DATA, 0x66, 0 }, { LCD_CMD, 0x11, 0 }, { LCD_CMD, 0x29, 0 }, { LCD_CMD, 0x2c, 0 }, }; static struct LcdCmd g_offCmd[] = { { LCD_CMD, 0x28, 20 }, { LCD_CMD, 0x10, 120 }, }; static DevHandle g_spiHdl = NULL; static int32_t SpiWrite9Bits(DevHandle spiHandle, uint8_t cmd, uint8_t data) { int32_t ret; uint16_t wbuff[1] = {0}; wbuff[0] = ((cmd << BITS_PER_BYTE) | data); ret = SpiWrite(spiHandle, (uint8_t *)wbuff, SPI_MSG_SIZE); if (ret != HDF_SUCCESS) { HDF_LOGE("SpiWrite failed, ret:%d", ret); return HDF_FAILURE; } return HDF_SUCCESS; } DevHandle GetSpiHandle(void) { int32_t ret; DevHandle spiHandle = NULL; struct SpiDevInfo spiDevinfo; struct SpiCfg cfg; spiDevinfo.busNum = 1; spiDevinfo.csNum = 0; spiHandle = SpiOpen(&spiDevinfo); if (spiHandle == NULL) { HDF_LOGE("SpiOpen failed"); return NULL; } cfg.mode = SPI_CLK_PHASE | SPI_CLK_POLARITY; cfg.bitsPerWord = BITS_PER_WORD; cfg.maxSpeedHz = SPI_MAX_SPEED; ret = SpiSetCfg(spiHandle, &cfg); if (ret != HDF_SUCCESS) { HDF_LOGE("SpiSetCfg failed, ret:%d", ret); SpiClose(spiHandle); return NULL; } HDF_LOGI("Spi init success!"); return spiHandle; } static int32_t LcdResetOn(void) { int32_t ret; ret = GpioSetDir(RESET_GPIO, GPIO_DIR_OUT); if (ret != HDF_SUCCESS) { HDF_LOGE("set lcd reset dir failed, ret:%d", ret); return HDF_FAILURE; } ret = GpioWrite(RESET_GPIO, GPIO_VAL_HIGH); if (ret != HDF_SUCCESS) { HDF_LOGE("set lcd reset hi failed, ret:%d", ret); return HDF_FAILURE; } ret = GpioWrite(RESET_GPIO, GPIO_VAL_LOW); if (ret != HDF_SUCCESS) { HDF_LOGE("set lcd reset how failed, ret:%d", ret); return HDF_FAILURE; } /* delay 10ms */ OsalMSleep(10); ret = GpioWrite(RESET_GPIO, GPIO_VAL_HIGH); if (ret != HDF_SUCCESS) { HDF_LOGE("set lcd reset hi after delay failed, ret:%d", ret); return HDF_FAILURE; } /* delay 120ms */ OsalMSleep(120); return HDF_SUCCESS; } static int32_t LcdResetOff(void) { int32_t ret; ret = GpioSetDir(RESET_GPIO, GPIO_DIR_OUT); if (ret != HDF_SUCCESS) { HDF_LOGE("GpioSetDir failed, ret:%d", ret); return HDF_FAILURE; } ret = GpioWrite(RESET_GPIO, GPIO_VAL_LOW); if (ret != HDF_SUCCESS) { HDF_LOGE("GpioWrite failed, ret:%d", ret); return HDF_FAILURE; } /* delay 20ms */ OsalMSleep(20); return HDF_SUCCESS; } static int32_t St7789Init(void) { g_spiHdl = GetSpiHandle(); if (g_spiHdl == NULL) { HDF_LOGE("GetSpiHandle failed"); return HDF_FAILURE; } return HDF_SUCCESS; } static int32_t St7789On(void) { int32_t ret; int i; /* lcd reset power on */ ret = LcdResetOn(); if (ret != HDF_SUCCESS) { HDF_LOGE("%s: LcdResetOn failed", __func__); return HDF_FAILURE; } if (g_spiHdl == NULL) { HDF_LOGE("%s: g_spiHdl is null", __func__); return HDF_FAILURE; } int32_t count = sizeof(g_onCmd) / sizeof(g_onCmd[0]); for (i = 0; i < count; i++) { ret = SpiWrite9Bits(g_spiHdl, g_onCmd[i].cmd, g_onCmd[i].data); if (ret != HDF_SUCCESS) { HDF_LOGE("SpiWrite failed"); return HDF_FAILURE; } if (g_onCmd[i].delay > 0) { OsalMSleep(g_onCmd[i].delay); } } return HDF_SUCCESS; } static int32_t St7789Off(void) { int32_t ret; int i; if (g_spiHdl == NULL) { HDF_LOGE("%s: g_spiHdl is null", __func__); return HDF_FAILURE; } /* send mipi init code */ int32_t count = sizeof(g_offCmd) / sizeof(g_offCmd[0]); for (i = 0; i < count; i++) { ret = SpiWrite9Bits(g_spiHdl, g_offCmd[i].cmd, g_offCmd[i].data); if (ret != HDF_SUCCESS) { HDF_LOGE("SpiWrite9Bits failed"); return HDF_FAILURE; } if (g_offCmd[i].delay > 0) { OsalMSleep(g_offCmd[i].delay); } } /* lcd reset power off */ ret = LcdResetOff(); if (ret != HDF_SUCCESS) { HDF_LOGE("%s: LcdResetOff failed", __func__); return HDF_FAILURE; } return HDF_SUCCESS; } static int32_t St7789SetBacklight(uint32_t level) { (void)level; return HDF_SUCCESS; } static struct PanelInfo g_panelInfo = { .width = WIDTH, /* width */ .height = HEIGHT, /* height */ .frameRate = FRAME_RATE, /* frame rate */ .intfType = LCD_6BIT, /* panel interface type */ .intfSync = 42, /* Hi3559AV100: For ili9341 at 50 Hz (6bit) */ }; static struct PanelData g_panelData = { .info = &g_panelInfo, .init = St7789Init, .on = St7789On, .off = St7789Off, .setBacklight = St7789SetBacklight, }; int32_t SspSt7789EntryInit(struct HdfDeviceObject *object) { if (object == NULL) { HDF_LOGE("%s: param is null", __func__); return HDF_FAILURE; } if (PanelDataRegister(&g_panelData) != HDF_SUCCESS) { HDF_LOGE("%s: PanelDataRegister failed", __func__); return HDF_FAILURE; } HDF_LOGI("%s: exit succ", __func__); return HDF_SUCCESS; } struct HdfDriverEntry g_st7789DevEntry = { .moduleVersion = 1, .moduleName = "LCD_ST7789", .Init = SspSt7789EntryInit, }; HDF_INIT(g_st7789DevEntry);