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