# LCD Development Example Add the device description. ``` /* Description of the display driver */ display :: host { hostName = "display_host"; /* Description of the HDF display driver */ device_hdf_disp :: device { device0 :: deviceNode { policy = 2; priority = 200; permission = 0660; moduleName = "HDF_DISP"; serviceName = "hdf_disp"; } } /* Description of the driver device at the SoC adapter layer */ device_hi35xx_disp :: device { device0 :: deviceNode { policy = 0; priority = 199; moduleName = "HI351XX_DISP"; } } /* Description of the LCD driver */ device_lcd :: device { device0 :: deviceNode { policy = 0; priority = 100; preload = 0; moduleName = "LCD_Sample"; } device1 :: deviceNode { policy = 0; priority = 100; preload = 2; moduleName = "LCD_SampleXX"; } } } ``` The following example shows how to adapt to the MIPI device to the Hi35xx series chips at the SoC adapter layer: ``` static int32_t MipiDsiInit(struct PanelInfo *info) { int32_t ret; struct DevHandle *mipiHandle = NULL; struct MipiCfg cfg; mipiHandle = MipiDsiOpen(0); if (mipiHandle == NULL) { HDF_LOGE("%s: MipiDsiOpen failure", __func__); return HDF_FAILURE; } cfg.lane = info->mipi.lane; cfg.mode = info->mipi.mode; cfg.format = info->mipi.format; cfg.burstMode = info->mipi.burstMode; cfg.timing.xPixels = info->width; cfg.timing.hsaPixels = info->hsw; cfg.timing.hbpPixels = info->hbp; cfg.timing.hlinePixels = info->width + info->hbp + info->hfp + info->hsw; cfg.timing.vsaLines = info->vsw; cfg.timing.vbpLines = info->vbp; cfg.timing.vfpLines = info->vfp; cfg.timing.ylines = info->height; /* 0 : no care */ cfg.timing.edpiCmdSize = 0; cfg.pixelClk = CalcPixelClk(info); cfg.phyDataRate = CalcDataRate(info); /* config mipi device */ ret = MipiDsiSetCfg(mipiHandle, &cfg); if (ret != HDF_SUCCESS) { HDF_LOGE("%s:MipiDsiSetCfg failure", __func__); } MipiDsiClose(mipiHandle); HDF_LOGI("%s:pixelClk = %d, phyDataRate = %d\n", __func__, cfg.pixelClk, cfg.phyDataRate); return ret; } ``` The following example shows code for developing an LCD driver: ``` #define RESET_GPIO 5 #define MIPI_DSI0 0 #define BLK_PWM1 1 #define PWM_MAX_PERIOD 100000 /* backlight setting */ #define MIN_LEVEL 0 #define MAX_LEVEL 255 #define DEFAULT_LEVEL 100 #define WIDTH 480 #define HEIGHT 960 #define HORIZONTAL_BACK_PORCH 20 #define HORIZONTAL_FRONT_PORCH 20 #define HORIZONTAL_SYNC_WIDTH 10 #define VERTIACL_BACK_PORCH 14 #define VERTIACL_FRONT_PORCH 16 #define VERTIACL_SYNC_WIDTH 2 #define FRAME_RATE 60 /* Panel information structure */ struct PanelInfo { uint32_t width; uint32_t height; uint32_t hbp; uint32_t hfp; uint32_t hsw; uint32_t vbp; uint32_t vfp; uint32_t vsw; uint32_t frameRate; enum LcdIntfType intfType; enum IntfSync intfSync; struct MipiDsiDesc mipi; struct BlkDesc blk; struct PwmCfg pwm; }; /* Initialization sequence of the LCD panel */ static uint8_t g_payLoad0[] = { 0xF0, 0x5A, 0x5A }; static uint8_t g_payLoad1[] = { 0xF1, 0xA5, 0xA5 }; static uint8_t g_payLoad2[] = { 0xB3, 0x03, 0x03, 0x03, 0x07, 0x05, 0x0D, 0x0F, 0x11, 0x13, 0x09, 0x0B }; static uint8_t g_payLoad3[] = { 0xB4, 0x03, 0x03, 0x03, 0x06, 0x04, 0x0C, 0x0E, 0x10, 0x12, 0x08, 0x0A }; static uint8_t g_payLoad4[] = { 0xB0, 0x54, 0x32, 0x23, 0x45, 0x44, 0x44, 0x44, 0x44, 0x60, 0x00, 0x60, 0x1C }; static uint8_t g_payLoad5[] = { 0xB1, 0x32, 0x84, 0x02, 0x87, 0x12, 0x00, 0x50, 0x1C }; static uint8_t g_payLoad6[] = { 0xB2, 0x73, 0x09, 0x08 }; static uint8_t g_payLoad7[] = { 0xB6, 0x5C, 0x5C, 0x05 }; static uint8_t g_payLoad8[] = { 0xB8, 0x23, 0x41, 0x32, 0x30, 0x03 }; static uint8_t g_payLoad9[] = { 0xBC, 0xD2, 0x0E, 0x63, 0x63, 0x5A, 0x32, 0x22, 0x14, 0x22, 0x03 }; static uint8_t g_payLoad10[] = { 0xb7, 0x41 }; static uint8_t g_payLoad11[] = { 0xC1, 0x0c, 0x10, 0x04, 0x0c, 0x10, 0x04 }; static uint8_t g_payLoad12[] = { 0xC2, 0x10, 0xE0 }; static uint8_t g_payLoad13[] = { 0xC3, 0x22, 0x11 }; static uint8_t g_payLoad14[] = { 0xD0, 0x07, 0xFF }; static uint8_t g_payLoad15[] = { 0xD2, 0x63, 0x0B, 0x08, 0x88 }; static uint8_t g_payLoad16[] = { 0xC6, 0x08, 0x15, 0xFF, 0x10, 0x16, 0x80, 0x60 }; static uint8_t g_payLoad17[] = { 0xc7, 0x04 }; static uint8_t g_payLoad18[] = { 0xC8, 0x7C, 0x50, 0x3B, 0x2C, 0x25, 0x16, 0x1C, 0x08, 0x27, 0x2B, 0x2F, 0x52, 0x43, 0x4C, 0x40, 0x3D, 0x30, 0x1E, 0x06, 0x7C, 0x50, 0x3B, 0x2C, 0x25, 0x16, 0x1C, 0x08, 0x27, 0x2B, 0x2F, 0x52, 0x43, 0x4C, 0x40, 0x3D, 0x30, 0x1E, 0x06 }; static uint8_t g_payLoad19[] = { 0x11 }; static uint8_t g_payLoad20[] = { 0x29 }; struct DsiCmdDesc g_OnCmd[] = { { 0x29, 0, sizeof(g_payLoad0), g_payLoad0 }, { 0x29, 0, sizeof(g_payLoad1), g_payLoad1 }, { 0x29, 0, sizeof(g_payLoad2), g_payLoad2 }, { 0x29, 0, sizeof(g_payLoad3), g_payLoad3 }, { 0x29, 0, sizeof(g_payLoad4), g_payLoad4 }, { 0x29, 0, sizeof(g_payLoad5), g_payLoad5 }, { 0x29, 0, sizeof(g_payLoad6), g_payLoad6 }, { 0x29, 0, sizeof(g_payLoad7), g_payLoad7 }, { 0x29, 0, sizeof(g_payLoad8), g_payLoad8 }, { 0x29, 0, sizeof(g_payLoad9), g_payLoad9 }, { 0x23, 0, sizeof(g_payLoad10), g_payLoad10 }, { 0x29, 0, sizeof(g_payLoad11), g_payLoad11 }, { 0x29, 0, sizeof(g_payLoad12), g_payLoad12 }, { 0x29, 0, sizeof(g_payLoad13), g_payLoad13 }, { 0x29, 0, sizeof(g_payLoad14), g_payLoad14 }, { 0x29, 0, sizeof(g_payLoad15), g_payLoad15 }, { 0x29, 0, sizeof(g_payLoad16), g_payLoad16 }, { 0x23, 0, sizeof(g_payLoad17), g_payLoad17 }, { 0x29, 1, sizeof(g_payLoad18), g_payLoad18 }, { 0x05, 120, sizeof(g_payLoad19), g_payLoad19 }, { 0x05, 120, sizeof(g_payLoad20), g_payLoad20 }, }; static DevHandle g_mipiHandle = NULL; static DevHandle g_pwmHandle = NULL; /* Set the status of the reset pin. */ static int32_t LcdResetOn(void) { int32_t ret; ret = GpioSetDir(RESET_GPIO, GPIO_DIR_OUT); if (ret != HDF_SUCCESS) { HDF_LOGE("GpioSetDir failure, ret:%d", ret); return HDF_FAILURE; } ret = GpioWrite(RESET_GPIO, GPIO_VAL_HIGH); if (ret != HDF_SUCCESS) { HDF_LOGE("GpioWrite failure, ret:%d", ret); return HDF_FAILURE; } /* delay 20ms */ OsalMSleep(20); return HDF_SUCCESS; } static int32_t SampleInit(void) { /* Obtain the MIPI DSI device handle. */ g_mipiHandle = MipiDsiOpen(MIPI_DSI0); if (g_mipiHandle == NULL) { HDF_LOGE("%s: MipiDsiOpen failure", __func__); return HDF_FAILURE; } return HDF_SUCCESS; } static int32_t SampleOn(void) { int32_t ret; /* Power on the LCD. */ ret = LcdResetOn(); if (ret != HDF_SUCCESS) { HDF_LOGE("%s: LcdResetOn failure", __func__); return HDF_FAILURE; } if (g_mipiHandle == NULL) { HDF_LOGE("%s: g_mipiHandle is null", __func__); return HDF_FAILURE; } /* Send the initialization sequence via MIPI. */ int32_t count = sizeof(g_OnCmd) / sizeof(g_OnCmd[0]); int32_t i; for (i = 0; i < count; i++) { ret = MipiDsiTx(g_mipiHandle, &(g_OnCmd[i])); if (ret != HDF_SUCCESS) { HDF_LOGE("MipiDsiTx failure"); return HDF_FAILURE; } } /* Set MIPI to the high speed (HS) mode. */ MipiDsiSetHsMode(g_mipiHandle); return HDF_SUCCESS; } /* PanelInfo structure variables */ static struct PanelInfo g_panelInfo = { .width = WIDTH, /* width */ .height = HEIGHT, /* height */ .hbp = HORIZONTAL_BACK_PORCH, /* horizontal back porch */ .hfp = HORIZONTAL_FRONT_PORCH, /* horizontal front porch */ .hsw = HORIZONTAL_SYNC_WIDTH, /* horizontal sync width */ .vbp = VERTIACL_BACK_PORCH, /* vertiacl back porch */ .vfp = VERTIACL_FRONT_PORCH, /* vertiacl front porch */ .vsw = VERTIACL_SYNC_WIDTH, /* vertiacl sync width */ .frameRate = FRAME_RATE, /* frame rate */ .intfType = MIPI_DSI, /* panel interface type */ .intfSync = OUTPUT_USER, /* output timming type */ /* mipi config info */ .mipi = { DSI_2_LANES, DSI_VIDEO_MODE, VIDEO_BURST_MODE, FORMAT_RGB_24_BIT }, /* backlight config info */ .blk = { BLK_PWM, MIN_LEVEL, MAX_LEVEL, DEFAULT_LEVEL }, .pwm = { BLK_PWM1, PWM_MAX_PERIOD }, }; /* Basic APIs that need to be adapted for the chip driver */ static struct PanelData g_panelData = { .info = &g_panelInfo, .init = SampleInit, .on = SampleOn, .off = SampleOff, .setBacklight = SampleSetBacklight, }; /* Entry function of the chip driver */ int32_t SampleEntryInit(struct HdfDeviceObject *object) { HDF_LOGI("%s: enter", __func__); if (object == NULL) { HDF_LOGE("%s: param is null!", __func__); return HDF_FAILURE; } /* Register the chip driver APIs with the platform driver. */ if (PanelDataRegister(&g_panelData) != HDF_SUCCESS) { HDF_LOGE("%s: PanelDataRegister error!", __func__); return HDF_FAILURE; } return HDF_SUCCESS; } struct HdfDriverEntry g_sampleDevEntry = { .moduleVersion = 1, .moduleName = "LCD_SAMPLE", .Init = SampleEntryInit, }; HDF_INIT(g_sampleDevEntry); ```