1 /*
2  * Copyright (c) 2020-2023 Huawei Device Co., Ltd.
3  *
4  * HDF is dual licensed: you can use it either under the terms of
5  * the GPL, or the BSD license, at your option.
6  * See the LICENSE file in the root of this repository for complete details.
7  */
8 
9 #include "mipi_dsi_test.h"
10 #include "hdf_log.h"
11 
12 #define HDF_LOG_TAG mipi_dsi_test
13 
MipiDsiTestMallocBuf(struct MipiDsiTest * test)14 static int32_t MipiDsiTestMallocBuf(struct MipiDsiTest *test)
15 {
16     static uint8_t buf = 0x29;
17 
18     test->msgs.dataType = 0x05;    /* 0x05: data type */
19     test->msgs.dataLen  = 1;       /* 1: data len */
20     test->msgs.delay = 0;
21     test->msgs.payload = &buf;
22 
23     return HDF_SUCCESS;
24 }
25 
MipiDsiTestSetUp(struct MipiDsiTest * test)26 static int32_t MipiDsiTestSetUp(struct MipiDsiTest *test)
27 {
28     if (test == NULL) {
29         HDF_LOGE("MipiDsiTestSetUp: test is null!");
30         return HDF_ERR_INVALID_OBJECT;
31     }
32 
33     if (test->handle == NULL) {
34         test->handle = MipiDsiOpen(test->devNo);
35     }
36     if (test->handle == NULL) {
37         HDF_LOGE("MipiDsiTestSetUp: fail!");
38         return HDF_FAILURE;
39     }
40 #ifdef CONFIG_DRIVERS_HDF_PLATFORM_IMX8MM_MIPI_DSI
41     MipiDsiAttach(test->handle, "toshiba,panel-tc358775");
42 #endif
43     test->fails = 0;
44     HDF_LOGD("MipiDsiTestSetUp: devNo:0x%x", test->devNo);
45     return MipiDsiTestMallocBuf(test);
46 }
47 
MipiDsiTestTearDown(struct MipiDsiTest * test)48 static void MipiDsiTestTearDown(struct MipiDsiTest *test)
49 {
50     if (test == NULL) {
51         HDF_LOGE("MipiDsiTestTearDown: test is null!");
52         return;
53     }
54     if (test->handle != NULL) {
55         MipiDsiClose(test->handle);
56         test->handle = NULL;
57     }
58 }
59 
CmpStVal(struct MipiCfg * a,struct MipiCfg * b)60 static int32_t CmpStVal(struct MipiCfg *a, struct MipiCfg *b)
61 {
62     if (a->lane == b->lane &&
63         a->mode == b->mode &&
64         a->format == b->format &&
65         a->burstMode == b->burstMode &&
66         a->pixelClk == b->pixelClk &&
67         a->phyDataRate == b->phyDataRate &&
68         a->timing.xPixels == b->timing.xPixels &&
69         a->timing.hsaPixels == b->timing.hsaPixels &&
70         a->timing.hbpPixels == b->timing.hbpPixels &&
71         a->timing.hlinePixels == b->timing.hlinePixels &&
72         a->timing.vsaLines == b->timing.vsaLines &&
73         a->timing.vbpLines == b->timing.vbpLines &&
74         a->timing.vfpLines == b->timing.vfpLines &&
75         a->timing.ylines == b->timing.ylines &&
76         a->timing.edpiCmdSize == b->timing.edpiCmdSize) {
77             return true;
78     }
79     return false;
80 }
81 
MipiDsiGetCfgTest(struct MipiDsiTest * test)82 static int32_t MipiDsiGetCfgTest(struct MipiDsiTest *test)
83 {
84     int32_t ret;
85     struct MipiCfg cfg;
86 
87     ret = MipiDsiGetCfg(test->handle, &cfg);
88     if (ret == HDF_SUCCESS) {
89         if (CmpStVal(&cfg, &test->cfg)) {
90             return HDF_SUCCESS;
91         }
92     }
93     return HDF_FAILURE;
94 }
95 
MipiDsiTxRxTest(struct MipiDsiTest * test)96 static int32_t MipiDsiTxRxTest(struct MipiDsiTest *test)
97 {
98     int32_t ret;
99     uint8_t data = 0x0A;   /* 0x0A: lcd status reg */
100     struct DsiCmdDesc cmd = {
101         .dataType = 0x06,     /* 0x06: read data type */
102         .dataLen = 1,         /* 1: data len */
103         .delay = 0,
104         .payload = &data,
105     };
106     uint8_t buf = 0;
107 
108     ret = MipiDsiTx(test->handle, &test->msgs);
109     if (ret == HDF_SUCCESS) {
110         ret = MipiDsiRx(test->handle, &cmd, 1, &buf); /* 1: read len */
111         if (ret == HDF_SUCCESS || ret == HDF_ERR_NOT_SUPPORT) {
112             return HDF_SUCCESS;
113         }
114     } else if (ret == HDF_ERR_NOT_SUPPORT) {
115         return HDF_SUCCESS;
116     }
117     HDF_LOGE("MipiDsiTxRxTest: fail!");
118     return HDF_FAILURE;
119 }
120 
MipiDsiToLpToHsTest(struct MipiDsiTest * test)121 static int32_t MipiDsiToLpToHsTest(struct MipiDsiTest *test)
122 {
123     MipiDsiSetHsMode(test->handle);
124     MipiDsiSetLpMode(test->handle);
125     return HDF_SUCCESS;
126 }
127 
MipiDsiTestByCmd(struct MipiDsiTest * test,int32_t cmd)128 static int32_t MipiDsiTestByCmd(struct MipiDsiTest *test, int32_t cmd)
129 {
130     int32_t ret = HDF_FAILURE;
131 
132     switch (cmd) {
133         case MIPI_DSI_TEST_SET_CFG:
134             ret = MipiDsiSetCfg(test->handle, &test->cfg);
135             break;
136         case MIPI_DSI_TEST_GET_CFG:
137             ret = MipiDsiGetCfgTest(test);
138             break;
139         case MIPI_DSI_TEST_TX_RX:
140             ret = MipiDsiTxRxTest(test);
141             break;
142         case MIPI_DSI_TEST_TO_LP_TO_HS:
143             ret = MipiDsiToLpToHsTest(test);
144             break;
145         default:
146             HDF_LOGE("MipiDsiTestByCmd: not support!");
147             break;
148     }
149     HDF_LOGI("MipiDsiTestByCmd: test cmd %d, ret: %d!", cmd, ret);
150     return ret;
151 }
152 
MipiDsiTestDoTest(struct MipiDsiTest * test,int32_t cmd)153 static int32_t MipiDsiTestDoTest(struct MipiDsiTest *test, int32_t cmd)
154 {
155     int32_t ret;
156 
157     if (test == NULL) {
158         HDF_LOGE("MipiDsiTestDoTest: test is null!");
159         return HDF_ERR_INVALID_OBJECT;
160     }
161     ret = MipiDsiTestSetUp(test);
162     if (ret != HDF_SUCCESS) {
163         HDF_LOGE("MipiDsiTestDoTest: setup fail, ret: %d!", ret);
164         return ret;
165     }
166 #ifdef MIPI_DSI_TEST_ON_INIT
167     int32_t i;
168     for (i = 0; i < test->total; i++) {
169         if (MipiDsiTestByCmd(test, i) != HDF_SUCCESS) {
170             test->fails++;
171         }
172     }
173     HDF_LOGI("\n\nMipiDsiTestDoTest: **********PASS:%u  FAIL:%u**************\n\n",
174         test->total - test->fails, test->fails);
175     ret = (test->fails > 0) ? HDF_FAILURE : HDF_SUCCESS;
176 #else
177     ret = MipiDsiTestByCmd(test, cmd);
178 #endif
179     MipiDsiTestTearDown(test);
180     return ret;
181 }
182 
MipiDsiTestBind(struct HdfDeviceObject * device)183 static int32_t MipiDsiTestBind(struct HdfDeviceObject *device)
184 {
185     static struct MipiDsiTest test;
186 
187     test.cfg.lane = DSI_2_LANES;
188     test.cfg.mode = DSI_VIDEO_MODE;
189     test.cfg.format = FORMAT_RGB_24_BIT;
190     test.cfg.burstMode = VIDEO_BURST_MODE;
191     test.cfg.timing.xPixels = 480;       /* 480: width */
192     test.cfg.timing.hsaPixels = 10;      /* 10: horizontal sync porch */
193     test.cfg.timing.hbpPixels = 20;      /* 20: horizontal back porch */
194     test.cfg.timing.hlinePixels = 530;   /* 530: horizontal total width */
195     test.cfg.timing.vsaLines = 2;        /* 2: vertiacl sync width */
196     test.cfg.timing.vbpLines = 14;       /* 14: vertiacl back porch */
197     test.cfg.timing.vfpLines = 16;       /* 16: vertiacl front porch */
198     test.cfg.timing.ylines = 960;        /* 960: height */
199     /* 0 : no care */
200     test.cfg.timing.edpiCmdSize = 0;
201     /*
202      * pixel clk(kHZ):
203      * calculate: (width + hbp + hfp + hsw) * (height + vbp + vfp + vsw) * frameRate / 1000
204      */
205     test.cfg.pixelClk = 31546;           /* 31546: pixel clk */
206     /*
207      * phy data rate(Mbps):
208      * calculate: (pixelClk / 1000) * 24 / laneNum
209      */
210     test.cfg.phyDataRate = 379;          /* 379: mipi clk */
211     test.devNo = 0;
212     test.total = MIPI_DSI_TEST_MAX;
213     test.doTest = MipiDsiTestDoTest;
214     device->service = &test.service;
215 #ifdef MIPI_DSI_TEST_ON_INIT
216     HDF_LOGI("MipiDsiTestBind: test on init!");
217     test.doTest(&test, -1);
218 #endif
219     return HDF_SUCCESS;
220 }
221 
MipiDsiTestInit(struct HdfDeviceObject * device)222 static int32_t MipiDsiTestInit(struct HdfDeviceObject *device)
223 {
224     (void)device;
225     return HDF_SUCCESS;
226 }
227 
228 struct HdfDriverEntry g_mipiDsiTestEntry = {
229     .moduleVersion = 1,
230     .Bind = MipiDsiTestBind,
231     .Init = MipiDsiTestInit,
232     .moduleName = "PLATFORM_MIPI_DSI_TEST",
233 };
234 HDF_INIT(g_mipiDsiTestEntry);
235