* 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;
}
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;
}
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;
}
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;
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;
}
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);
}
}
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,
.height = HEIGHT,
.frameRate = FRAME_RATE,
.intfType = LCD_6BIT,
.intfSync = 42,
};
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);