MIPI DSI

概述

  • DSI(Display Serial Interface)是由移动行业处理器接口联盟(Mobile Industry Processor Interface (MIPI) Alliance)制定的规范,旨在降低移动设备中显示控制器的成本。它以串行的方式发送像素数据或指令给外设(通常是LCD或者类似的显示设备),或从外设中读取状态信息或像素信息;它定义了主机、图像数据源和目标设备之间的串行总线和通信协议。

  • MIPI-DSI具备高速模式和低速模式两种工作模式,全部数据通道都可以用于单向的高速传输,但只有第一个数据通道才可用于低速双向传输,从属端的状态信息、像素等是通过该数据通道返回。时钟通道专用于在高速传输数据的过程中传输同步时钟信号。

  • 图1显示了简化的DSI接口。从概念上看,符合DSI的接口与基于DBI-2和DPI-2标准的接口具有相同的功能。它向外围设备传输像素或命令数据,并且可以从外围设备读取状态或像素信息。主要区别在于,DSI对所有像素数据、命令和事件进行序列化,而在传统接口中,这些像素数据、命令和事件通常需要附加控制信号才能在并行数据总线上传输。

    图 1 DSI发送、接收接口

接口说明

表 1 MIPI-DSI API接口功能介绍

功能分类

接口名

描述

设置/获取当前MIPI-DSI相关配置

MipiDsiSetCfg

设置MIPI-DSI相关配置

MipiDsiGetCfg

获取当前MIPI-DSI相关配置

获取/释放MIPI-DSI操作句柄

MipiDsiOpen

获取MIPI-DSI操作句柄

MipiDsiClose

释放MIPI-DSI操作句柄

设置MIPI-DSI进入Low power模式/High speed模式

MipiDsiSetLpMode

设置MIPI-DSI进入Low power模式

MipiDsiSetHsMode

设置MIPI-DSI进入High speed模式

MIPI-DSI发送/回读指令

MipiDsiTx

MIPI-DSI发送相应指令的接口

MipiDsiRx

MIPI-DSI按期望长度回读的接口

说明: 本文涉及的所有接口,仅限内核态使用,不支持在用户态使用

使用指导

使用流程

使用MIPI-DSI的一般流程如图2所示。

图 2 MIPI-DSI使用流程图

获取MIPI-DSI操作句柄

在进行MIPI-DSI进行通信前,首先要调用MipiDsiOpen获取操作句柄,该函数会返回指定通道ID的操作句柄。

DevHandle MipiDsiOpen(uint8_t id);

表 2 MipiDsiOpen的参数和返回值描述

参数

参数描述

id

MIPI DSI通道ID

返回值

返回值描述

NULL

获取失败

设备句柄

获取到指令通道的操作句柄, 类型为DevHandle

假设系统中的MIPI-DSI通道为0,获取该通道操作句柄的示例如下:

DevHandle mipiDsiHandle = NULL;  /* 设备句柄 */
chnId = 0;      /* MIPI-DSI通道ID */

/* 获取操作句柄 */
mipiDsiHandle = MipiDsiOpen(chnId);
if (mipiDsiHandle == NULL) {
    HDF_LOGE("MipiDsiOpen: failed\n");
    return;
}

MIPI-DSI相应配置

  • 写入MIPI-DSI配置

int32_t MipiDsiSetCfg(DevHandle handle, struct MipiCfg *cfg);

表 3 MipiDsiSetCfg的参数和返回值描述

参数

参数描述

handle

操作句柄

cfg

MIPI-DSI相应配置buf 指针

返回值

返回值描述

0

设置成功

负数

设置失败

int32_t ret;
struct MipiCfg cfg = {0};

/* 当前对接的屏幕配置如下 */
cfg.lane = DSI_4_LANES;
cfg.mode = DSI_CMD_MODE;
cfg.burstMode = VIDEO_NON_BURST_MODE_SYNC_EVENTS;
cfg.format = FORMAT_RGB_24_BIT;
cfg.pixelClk = 174;
cfg.phyDataRate = 384;
cfg.timingInfo.hsaPixels = 50;
cfg.timingInfo.hbpPixels = 55;
cfg.timingInfo.hlinePixels = 1200;
cfg.timingInfo.yResLines = 1800;
cfg.timingInfo.vbpLines = 33;
cfg.timingInfo.vsaLines = 76;
cfg.timingInfo.vfpLines = 120;
cfg.timingInfo.xResPixels = 1342;
/* 写入配置数据 */
ret = MipiDsiSetCfg(g_handle, &cfg);
if (ret != 0) {
    HDF_LOGE("%s: SetMipiCfg fail! ret=%d\n", __func__, ret);
    return -1;
}
  • 获取当前MIPI-DSI的配置

int32_t MipiDsiGetCfg(DevHandle handle, struct MipiCfg *cfg);

表 4 MipiDsiGetCfg的参数和返回值描述

参数

参数描述

handle

操作句柄

cfg

MIPI-DSI相应配置buf 指针

返回值

返回值描述

0

获取成功

负数

获取失败

int32_t ret;
struct MipiCfg cfg;
memset(&cfg, 0, sizeof(struct MipiCfg));
ret = MipiDsiGetCfg(g_handle, &cfg);
if (ret != HDF_SUCCESS) {
    HDF_LOGE("%s: GetMipiCfg fail!\n", __func__);
    return HDF_FAILURE;
}

发送/回读控制指令

  • 发送指令

int32_t MipiDsiTx(PalHandle handle, struct DsiCmdDesc *cmd);

表 5 MipiDsiTx的参数和返回值描述

参数

参数描述

handle

操作句柄

cmd

需要发送的指令数据指针

返回值

返回值描述

0

发送成功

负数

发送失败

int32_t ret;
struct DsiCmdDesc *cmd = OsalMemCalloc(sizeof(struct DsiCmdDesc));
if (cmd == NULL) {
    return HDF_FAILURE;
}
cmd->dtype = DTYPE_DCS_WRITE;
cmd->dlen = 1;
cmd->payload = OsalMemCalloc(sizeof(uint8_t));
if (cmd->payload == NULL) {
    HdfFree(cmd);
    return HDF_FAILURE;
}
*(cmd->payload) = DTYPE_GEN_LWRITE;
MipiDsiSetLpMode(mipiHandle);
ret = MipiDsiTx(mipiHandle, cmd);
MipiDsiSetHsMode(mipiHandle);
if (ret != HDF_SUCCESS) {
    HDF_LOGE("%s: PalMipiDsiTx fail! ret=%d\n", __func__, ret);
    HdfFree(cmd->payload);
    HdfFree(cmd);
    return HDF_FAILURE;
}
HdfFree(cmd->payload);
HdfFree(cmd);
  • 回读指令

int32_t MipiDsiRx(DevHandle handle, struct DsiCmdDesc *cmd, uint32_t readLen, uint8_t *out);

表 6 MipiDsiRx的参数和返回值描述

参数

参数描述

handle

操作句柄

cmd

需要回读的指令数据指针

readLen

期望回读的数据长度

out

回读的数据buf指针

返回值

返回值描述

0

获取成功

负数

获取失败

int32_t ret;
uint8_t readVal = 0;

struct DsiCmdDesc *cmdRead = OsalMemCalloc(sizeof(struct DsiCmdDesc));
if (cmdRead == NULL) {
    return HDF_FAILURE;
}
cmdRead->dtype = DTYPE_DCS_READ;
cmdRead->dlen = 1;
cmdRead->payload = OsalMemCalloc(sizeof(uint8_t));
if (cmdRead->payload == NULL) {
    HdfFree(cmdRead);
    return HDF_FAILURE;
}
*(cmdRead->payload) = DDIC_REG_STATUS;
MipiDsiSetLpMode(g_handle);
ret = MipiDsiRx(g_handle, cmdRead, sizeof(readVal), &readVal);
MipiDsiSetHsMode(g_handle);
if (ret != HDF_SUCCESS) {
    HDF_LOGE("%s: MipiDsiRx fail! ret=%d\n", __func__, ret);
    HdfFree(cmdRead->payload);
    HdfFree(cmdRead);
    return HDF_FAILURE;
}
HdfFree(cmdRead->payload);
HdfFree(cmdRead);

释放MIPI-DSI操作句柄

MIPI-DSI使用完成之后,需要释放操作句柄,释放句柄的函数如下所示:

void MipiDsiClose(DevHandle handle);

该函数会释放掉由MipiDsiOpen申请的资源。

表 7 MipiDsiClose的参数和返回值描述

参数

参数描述

handle

MIPI-DSI操作句柄

MipiDsiClose(mipiHandle); /* 释放掉MIPI-DSI操作句柄 */

使用实例

MIPI-DSI完整的使用示例如下所示:

#include "hdf.h"
#include "mipi_dsi_if.h"

void PalMipiDsiTestSample(void)
{
    uint8_t chnId;
    int32_t ret;  
    DevHandle handle = NULL;
    
    /* 设备通道编号 */
    chnId = 0; 
    /* 获取操作句柄 */
    handle = MipiDsiOpen(chnId);
    if (handle == NULL) {
        HDF_LOGE("MipiDsiOpen: failed!\n");
        return;
    }
    /* 配置相应参数 */
    struct MipiCfg cfg = {0};
    cfg.lane = DSI_4_LANES;
    cfg.mode = DSI_CMD_MODE;
    cfg.burstMode = VIDEO_NON_BURST_MODE_SYNC_EVENTS;
    cfg.format = FORMAT_RGB_24_BIT;
    cfg.pixelClk = 174;                      
    cfg.phyDataRate = 384;                 
    cfg.timingInfo.hsaPixels = 50;
    cfg.timingInfo.hbpPixels = 55;
    cfg.timingInfo.hlinePixels = 1200;
    cfg.timingInfo.yResLines = 1800;
    cfg.timingInfo.vbpLines = 33;
    cfg.timingInfo.vsaLines = 76;
    cfg.timingInfo.vfpLines = 120;
    cfg.timingInfo.xResPixels = 1342;
    /* 写入配置数据 */
    ret = MipiDsiSetCfg(g_handle, &cfg);
    if (ret != 0) {
        HDF_LOGE("%s: SetMipiCfg fail! ret=%d\n", __func__, ret);
        return;
    }
    /* 发送PANEL初始化指令 */
    struct DsiCmdDesc *cmd = OsalMemCalloc(sizeof(struct DsiCmdDesc));
    if (cmd == NULL) {
        return;
    }
    cmd->dtype = DTYPE_DCS_WRITE;
    cmd->dlen = 1;
    cmd->payload = OsalMemCalloc(sizeof(uint8_t));
    if (cmd->payload == NULL) {
        HdfFree(cmd);
        return;
    }
    *(cmd->payload) = DTYPE_GEN_LWRITE;
    MipiDsiSetLpMode(mipiHandle);
    ret = MipiDsiTx(mipiHandle, cmd);
    MipiDsiSetHsMode(mipiHandle);
    if (ret != HDF_SUCCESS) {
        HDF_LOGE("%s: MipiDsiTx fail! ret=%d\n", __func__, ret);
        HdfFree(cmd->payload);
        HdfFree(cmd);
        return;
    }
    HdfFree(cmd->payload);
    HdfFree(cmd);
    /* 回读panel状态寄存器 */
    uint8_t readVal = 0;
    struct DsiCmdDesc *cmdRead = OsalMemCalloc(sizeof(struct DsiCmdDesc));
    if (cmdRead == NULL) {
        return;
    }
    cmdRead->dtype = DTYPE_DCS_READ;
    cmdRead->dlen = 1;
    cmdRead->payload = OsalMemCalloc(sizeof(uint8_t));
    if (cmdRead->payload == NULL) {
        HdfFree(cmdRead);
        return;
    }
    *(cmdRead->payload) = DDIC_REG_STATUS;
    MipiDsiSetLpMode(g_handle);
    ret = MipiDsiRx(g_handle, cmdRead, sizeof(readVal), &readVal);
    MipiDsiSetHsMode(g_handle);
    if (ret != HDF_SUCCESS) {
        HDF_LOGE("%s: MipiDsiRx fail! ret=%d\n", __func__, ret);
        HdfFree(cmdRead->payload);
        HdfFree(cmdRead);
        return;
    }
    HdfFree(cmdRead->payload);
    HdfFree(cmdRead);
    /* 释放MIPI DSI设备句柄 */
    MipiDsiClose(handle); 
}