1 /*
2 * mipi_tx_dev.c
3 *
4 * create vfs node for mipi
5 *
6 * Copyright (c) 2021-2023 Huawei Device Co., Ltd.
7 *
8 * This software is licensed under the terms of the GNU General Public
9 * License version 2, as published by the Free Software Foundation, and
10 * may be copied, distributed, and modified under those terms.
11 *
12 * This program is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 * GNU General Public License for more details.
16 *
17 */
18
19 #include "mipi_tx_dev.h"
20 #include <asm/io.h>
21 #include <asm/uaccess.h>
22 #include <linux/cdev.h>
23 #include <linux/device.h>
24 #include <linux/fs.h>
25 #include <linux/init.h>
26 #include <linux/kdev_t.h>
27 #include <linux/miscdevice.h>
28 #include <linux/module.h>
29 #include <linux/proc_fs.h>
30 #include <linux/semaphore.h>
31 #include <linux/seq_file.h>
32 #include <linux/version.h>
33 #include "hdf_base.h"
34 #include "hdf_log.h"
35 #include "mipi_dsi_core.h"
36 #include "mipi_tx_reg.h"
37 #include "osal_io.h"
38 #include "osal_mem.h"
39 #include "osal_uaccess.h"
40 #include "securec.h"
41
42 #ifdef __cplusplus
43 #if __cplusplus
44 extern "C" {
45 #endif
46 #endif /* End of #ifdef __cplusplus */
47
48 /****************************************************************************
49 * macro definition *
50 ****************************************************************************/
51 #define HDF_LOG_TAG mipi_tx_dev
52 #define MIPI_TX_DEV_NAME "hi_mipi_tx"
53 #define MIPI_TX_PROC_NAME "mipi_tx"
54 #define NAME_LEN 20
55
56 struct MipiDsiVfsPara {
57 struct MipiDsiCntlr *cntlr;
58 struct miscdevice *miscdev;
59 struct semaphore sem;
60 void *priv;
61 };
62
63 static struct MipiDsiVfsPara g_vfsPara[MAX_CNTLR_CNT];
64 static uint8_t g_curId = 0;
RegisterDevice(const char * name,uint8_t id,unsigned short mode,struct file_operations * ops)65 static int32_t RegisterDevice(const char *name, uint8_t id, unsigned short mode, struct file_operations *ops)
66 {
67 int32_t error;
68 struct miscdevice *dev = NULL;
69
70 if ((name == NULL) || (ops == NULL) || (id >= MAX_CNTLR_CNT)) {
71 HDF_LOGE("RegisterDevice: name, ops or id is error!");
72 return HDF_ERR_INVALID_PARAM;
73 }
74 dev = OsalMemCalloc(sizeof(struct miscdevice));
75 if (dev == NULL) {
76 HDF_LOGE("RegisterDevice: [OsalMemCalloc] fail!");
77 return HDF_ERR_MALLOC_FAIL;
78 }
79 dev->fops = ops;
80 dev->name = OsalMemCalloc(NAME_LEN + 1);
81 if (dev->name == NULL) {
82 OsalMemFree(dev);
83 HDF_LOGE("RegisterDevice: [OsalMemCalloc] fail!");
84 return HDF_ERR_MALLOC_FAIL;
85 }
86 if (id != 0) { /* 0 : id */
87 if (snprintf_s((char *)dev->name, NAME_LEN + 1, NAME_LEN, "%s%u", name, id) < 0) {
88 OsalMemFree((char *)dev->name);
89 OsalMemFree(dev);
90 HDF_LOGE("RegisterDevice: [snprintf_s] fail!");
91 return HDF_FAILURE;
92 }
93 } else {
94 if (memcpy_s((char *)dev->name, NAME_LEN, name, strlen(name)) != EOK) {
95 OsalMemFree((char *)dev->name);
96 OsalMemFree(dev);
97 HDF_LOGE("RegisterDevice: [memcpy_s] fail!");
98 return HDF_ERR_IO;
99 }
100 }
101 ops->owner = THIS_MODULE;
102 dev->minor = MISC_DYNAMIC_MINOR;
103 dev->mode = mode;
104 error = misc_register(dev);
105 if (error < 0) {
106 printk("RegisterDevice: id %u cannot register miscdev on minor=%d (err=%d)",
107 id, MISC_DYNAMIC_MINOR, error);
108 OsalMemFree((char *)dev->name);
109 OsalMemFree(dev);
110 return error;
111 }
112
113 g_vfsPara[id].miscdev = dev;
114 g_curId = id;
115 printk("RegisterDevice: create inode ok %s %d", dev->name, dev->minor);
116 HDF_LOGI("RegisterDevice: success!");
117
118 return HDF_SUCCESS;
119 }
120
121 #if LINUX_VERSION_CODE >= KERNEL_VERSION(5, 6, 0)
ProcRegister(const char * name,uint8_t id,unsigned short mode,const struct proc_ops * ops)122 static int32_t ProcRegister(const char *name, uint8_t id, unsigned short mode, const struct proc_ops *ops)
123 #else
124 static int32_t ProcRegister(const char *name, uint8_t id, unsigned short mode, const struct file_operations *ops)
125 #endif
126 {
127 char procName[NAME_LEN + 1];
128 struct proc_dir_entry* entry = NULL;
129 int32_t ret;
130
131 if ((name == NULL) || (ops == NULL) || (id >= MAX_CNTLR_CNT)) {
132 HDF_LOGE("ProcRegister: name, ops or id is error!");
133 return HDF_ERR_INVALID_PARAM;
134 }
135 if (memset_s(procName, NAME_LEN + 1, 0, NAME_LEN + 1) != EOK) {
136 HDF_LOGE("ProcRegister: [memcpy_s] fail!");
137 return HDF_ERR_IO;
138 }
139 if (id != 0) {
140 ret = snprintf_s(procName, NAME_LEN + 1, NAME_LEN, "%s%u", name, id);
141 } else {
142 ret = snprintf_s(procName, NAME_LEN + 1, NAME_LEN, "%s", name);
143 }
144 if (ret < 0) {
145 printk(KERN_ERR "ProcRegister: procName %s snprintf_s fail!", procName);
146 return HDF_FAILURE;
147 }
148 entry = proc_create(procName, mode, NULL, ops);
149 if (entry == NULL) {
150 printk(KERN_ERR "ProcRegister: proc_create name %s fail!", procName);
151 return HDF_FAILURE;
152 }
153 HDF_LOGI("ProcRegister: success!");
154 return HDF_SUCCESS;
155 }
156
UnregisterDevice(uint8_t id)157 static void UnregisterDevice(uint8_t id)
158 {
159 struct miscdevice *dev = NULL;
160
161 if (id >= MAX_CNTLR_CNT) {
162 HDF_LOGE("UnregisterDevice: id error!");
163 return;
164 }
165 dev = g_vfsPara[id].miscdev;
166 if (dev == NULL) {
167 HDF_LOGE("UnregisterDevice: dev is null!");
168 return;
169 }
170
171 misc_deregister(dev);
172 OsalMemFree((void *)dev->name);
173 dev->name = NULL;
174 OsalMemFree(dev);
175 dev = NULL;
176 g_curId = 0;
177 HDF_LOGI("UnregisterDevice: success!");
178 }
179
ProcUnregister(const char * name,uint8_t id)180 static void ProcUnregister(const char *name, uint8_t id)
181 {
182 char procName[NAME_LEN + 1];
183 int32_t ret;
184
185 if (id >= MAX_CNTLR_CNT) {
186 HDF_LOGE("ProcUnregister: id error!");
187 return;
188 }
189 if (memset_s(procName, NAME_LEN + 1, 0, NAME_LEN + 1) != EOK) {
190 HDF_LOGE("ProcUnregister: [memcpy_s] fail!");
191 return;
192 }
193 if (id != 0) {
194 ret = snprintf_s(procName, NAME_LEN + 1, NAME_LEN, "%s%hhu", name, id);
195 } else {
196 ret = snprintf_s(procName, NAME_LEN + 1, NAME_LEN, "%s", name);
197 }
198 if (ret < 0) {
199 printk(KERN_ERR "ProcUnregister: procName format fail!");
200 return;
201 }
202 remove_proc_entry(procName, NULL);
203 HDF_LOGI("ProcUnregister: success!");
204 }
205
SemaInit(struct semaphore * sem,uint16_t val)206 static int32_t SemaInit(struct semaphore *sem, uint16_t val)
207 {
208 if (sem == NULL) {
209 HDF_LOGE("SemaInit: sem is null!");
210 return HDF_ERR_INVALID_OBJECT;
211 }
212 sema_init(sem, val);
213 return HDF_SUCCESS;
214 }
215
SemaDestroy(struct semaphore * sem)216 static void SemaDestroy(struct semaphore *sem)
217 {
218 // don't support sema_destory(sem)!
219 (void)sem;
220 }
221
SemaDownInterruptable(struct semaphore * sem)222 static int32_t SemaDownInterruptable(struct semaphore *sem)
223 {
224 return down_interruptible(sem);
225 }
226
SemaUp(struct semaphore * sem)227 static void SemaUp(struct semaphore *sem)
228 {
229 up(sem);
230 }
231
GetId()232 static uint8_t GetId()
233 {
234 if (g_curId >= MAX_CNTLR_CNT) {
235 HDF_LOGE("GetId: fail g_curId = %hhu!", g_curId);
236 return 0;
237 }
238
239 HDF_LOGI("GetId: success!");
240 return g_curId;
241 }
242
GetIdFromFilep(struct file * filep)243 static uint8_t GetIdFromFilep(struct file *filep)
244 {
245 uint8_t id;
246 if (filep == NULL) {
247 HDF_LOGE("GetIdFromFilep: filep is invalid!");
248 return 0;
249 }
250
251 if (filep->private_data == NULL) {
252 HDF_LOGE("GetIdFromFilep: private_data is null!");
253 return 0;
254 }
255
256 id = (uint8_t)(filep->private_data);
257 if (id >= MAX_CNTLR_CNT) {
258 HDF_LOGE("GetIdFromFilep: id error!");
259 return 0;
260 }
261
262 return id;
263 }
264
GetCntlrFromFilep(struct file * filep)265 static struct MipiDsiCntlr *GetCntlrFromFilep(struct file *filep)
266 {
267 uint8_t id;
268 if (filep == NULL) {
269 HDF_LOGE("GetCntlrFromFilep: filep is invalid!");
270 return NULL;
271 }
272 id = GetId();
273
274 return g_vfsPara[id].cntlr;
275 }
276
GetSemaFromFilep(struct file * filep)277 static struct semaphore *GetSemaFromFilep(struct file *filep)
278 {
279 uint8_t id;
280 if (filep == NULL) {
281 HDF_LOGE("GetSemaFromFilep: filep is invalid!");
282 return NULL;
283 }
284 id = GetId();
285
286 return &g_vfsPara[id].sem;
287 }
288
GetCfgFromFilep(struct file * filep)289 static struct MipiCfg *GetCfgFromFilep(struct file *filep)
290 {
291 uint8_t id;
292 if (filep == NULL) {
293 HDF_LOGE("GetCfgFromFilep: filep is invalid!");
294 return NULL;
295 }
296 id = GetId();
297 if (g_vfsPara[id].cntlr == NULL) {
298 HDF_LOGE("GetCfgFromFilep: g_vfsPara[id].cntlr is null!");
299 return NULL;
300 }
301
302 return &(g_vfsPara[id].cntlr->cfg);
303 }
304
MipiDsiDevSetCfg(struct MipiDsiCntlr * cntlr,struct MipiCfg * arg)305 static int32_t MipiDsiDevSetCfg(struct MipiDsiCntlr *cntlr, struct MipiCfg *arg)
306 {
307 int32_t ret;
308 struct MipiCfg *temp = NULL;
309 uint32_t size;
310
311 if (arg == NULL) {
312 HDF_LOGE("MipiDsiDevSetCfg: arg is invalid!");
313 return HDF_ERR_INVALID_PARAM;
314 }
315
316 if (cntlr == NULL) {
317 HDF_LOGE("MipiDsiDevSetCfg: cntlr is null!");
318 return HDF_ERR_INVALID_PARAM;
319 }
320
321 size = sizeof(struct MipiCfg);
322 temp = (struct MipiCfg *)OsalMemCalloc(size);
323 if (temp == NULL) {
324 HDF_LOGE("MipiDsiDevSetCfg: OsalMemCalloc error!");
325 return HDF_ERR_MALLOC_FAIL;
326 }
327
328 if (access_ok(
329 #if LINUX_VERSION_CODE < KERNEL_VERSION(5, 0, 0)
330 VERIFY_READ,
331 #endif
332 arg, size)) { /* user space */
333 if (CopyFromUser(temp, arg, size) != 0) {
334 OsalMemFree(temp);
335 temp = NULL;
336 HDF_LOGE("MipiDsiDevSetCfg: [CopyFromUser] fail!");
337 return HDF_ERR_IO;
338 }
339 } else {
340 OsalMemFree(temp);
341 temp = NULL;
342 HDF_LOGE("MipiDsiDevSetCfg: illegal user space address!");
343 return HDF_FAILURE;
344 }
345
346 ret = MipiDsiCntlrSetCfg(cntlr, temp);
347 g_curId = cntlr->devNo;
348 OsalMemFree(temp);
349 HDF_LOGI("MipiDsiDevSetCfg: success!");
350
351 return ret;
352 }
353
MipiDsiDevSetCmd(struct MipiDsiCntlr * cntlr,struct DsiCmdDesc * arg)354 static int32_t MipiDsiDevSetCmd(struct MipiDsiCntlr *cntlr, struct DsiCmdDesc *arg)
355 {
356 int32_t ret;
357 struct DsiCmdDesc *temp = NULL;
358 uint32_t size;
359
360 if (arg == NULL) {
361 HDF_LOGE("MipiDsiDevSetCmd: arg is invalid!");
362 return HDF_ERR_INVALID_PARAM;
363 }
364
365 if (cntlr == NULL) {
366 HDF_LOGE("MipiDsiDevSetCmd: cntlr is null!");
367 return HDF_ERR_INVALID_PARAM;
368 }
369
370 if (!access_ok(
371 #if LINUX_VERSION_CODE < KERNEL_VERSION(5, 0, 0)
372 VERIFY_WRITE,
373 #endif
374 arg->payload, arg->dataLen)) {
375 HDF_LOGE("MipiDsiDevSetCmd: payload is illegal user space address!");
376 return HDF_ERR_INVALID_PARAM;
377 }
378
379 size = sizeof(struct DsiCmdDesc);
380 temp = (struct DsiCmdDesc *)OsalMemCalloc(size);
381 if (temp == NULL) {
382 HDF_LOGE("MipiDsiDevSetCmd: [OsalMemCalloc] error!");
383 return HDF_ERR_MALLOC_FAIL;
384 }
385
386 if (access_ok(
387 #if LINUX_VERSION_CODE < KERNEL_VERSION(5, 0, 0)
388 VERIFY_READ,
389 #endif
390 arg, size)) { /* user space */
391 if (CopyFromUser(temp, arg, size) != 0) {
392 OsalMemFree(temp);
393 temp = NULL;
394 HDF_LOGE("MipiDsiDevSetCmd: [CopyFromUser] fail!");
395 return HDF_ERR_IO;
396 }
397 } else {
398 OsalMemFree(temp);
399 temp = NULL;
400 HDF_LOGE("MipiDsiDevSetCmd: illegal user space address!");
401 return HDF_FAILURE;
402 }
403
404 ret = MipiDsiCntlrTx(cntlr, temp);
405 OsalMemFree(temp);
406 HDF_LOGI("MipiDsiDevSetCmd: success!");
407
408 return ret;
409 }
410
MipiDsiDevCmdCopyFromUser(GetDsiCmdDescTag * arg,GetDsiCmdDescTag * temp,uint32_t * size)411 static int32_t MipiDsiDevCmdCopyFromUser(GetDsiCmdDescTag *arg, GetDsiCmdDescTag *temp, uint32_t *size)
412 {
413 if (access_ok(
414 #if LINUX_VERSION_CODE < KERNEL_VERSION(5, 0, 0)
415 VERIFY_READ,
416 #endif
417 arg, *size)) { /* user space */
418 if (CopyFromUser(temp, arg, *size) != 0) {
419 HDF_LOGE("MipiDsiDevCmdCopyFromUser: [CopyFromUser] fail!");
420 return HDF_ERR_IO;
421 }
422 } else {
423 HDF_LOGE("MipiDsiDevCmdCopyFromUser: illegal user space address!");
424 return HDF_FAILURE;
425 }
426 return HDF_SUCCESS;
427 }
428
MipiDsiDevCmdCopyToUser(GetDsiCmdDescTag * arg,GetDsiCmdDescTag * temp,uint32_t * size)429 static int32_t MipiDsiDevCmdCopyToUser(GetDsiCmdDescTag *arg, GetDsiCmdDescTag *temp, uint32_t *size)
430 {
431 if (access_ok(
432 #if LINUX_VERSION_CODE < KERNEL_VERSION(5, 0, 0)
433 VERIFY_WRITE,
434 #endif
435 arg, *size)) { /* user space */
436 if (CopyToUser(arg, temp, *size) != 0) {
437 HDF_LOGE("MipiDsiDevCmdCopyToUser: [CopyToUser] fail!");
438 return HDF_ERR_IO;
439 }
440 } else {
441 HDF_LOGE("MipiDsiDevCmdCopyToUser: illegal user space address!");
442 return HDF_FAILURE;
443 }
444 return HDF_SUCCESS;
445 }
446
MipiDsiDevGetCmd(struct MipiDsiCntlr * cntlr,GetDsiCmdDescTag * arg)447 static int32_t MipiDsiDevGetCmd(struct MipiDsiCntlr *cntlr, GetDsiCmdDescTag *arg)
448 {
449 int32_t ret;
450 GetDsiCmdDescTag *temp = NULL;
451 uint32_t size;
452
453 if ((cntlr == NULL) || (arg == NULL)) {
454 HDF_LOGE("MipiDsiDevGetCmd: cntlr or arg is null!");
455 return HDF_ERR_INVALID_PARAM;
456 }
457
458 if (!access_ok(
459 #if LINUX_VERSION_CODE < KERNEL_VERSION(5, 0, 0)
460 VERIFY_WRITE,
461 #endif
462 arg->out, arg->readLen)) {
463 HDF_LOGE("MipiDsiDevGetCmd: out is illegal user space address!");
464 return HDF_ERR_INVALID_PARAM;
465 }
466
467 size = sizeof(GetDsiCmdDescTag);
468 temp = (GetDsiCmdDescTag *)OsalMemCalloc(size);
469 if (temp == NULL) {
470 HDF_LOGE("MipiDsiDevGetCmd: [OsalMemCalloc] error!");
471 return HDF_ERR_MALLOC_FAIL;
472 }
473 if (MipiDsiDevCmdCopyFromUser(arg, temp, &size) != HDF_SUCCESS) {
474 goto fail0;
475 }
476 ret = MipiDsiCntlrRx(cntlr, &temp->readCmd, temp->readLen, temp->out);
477 if (ret != HDF_SUCCESS) {
478 HDF_LOGE("MipiDsiDevGetCmd: [MipiDsiCntlrRx] fail!");
479 goto fail0;
480 }
481 if (MipiDsiDevCmdCopyToUser(arg, temp, &size) != HDF_SUCCESS) {
482 goto fail0;
483 }
484 OsalMemFree(temp);
485 temp = NULL;
486 HDF_LOGI("MipiDsiDevGetCmd: success!");
487 return HDF_SUCCESS;
488 fail0:
489 OsalMemFree(temp);
490 temp = NULL;
491 return HDF_FAILURE;
492 }
493
MipiDsiDevIoctl(struct file * filep,unsigned int cmd,unsigned long arg)494 static long MipiDsiDevIoctl(struct file *filep, unsigned int cmd, unsigned long arg)
495 {
496 int32_t ret = HDF_SUCCESS;
497 void *pArg = (void *)arg;
498 struct MipiDsiCntlr *cntlr = NULL;
499 struct semaphore *sem = NULL;
500
501 if (filep == NULL || pArg == NULL) {
502 HDF_LOGE("MipiDsiDevIoctl: filep or pArg is null!");
503 return HDF_ERR_INVALID_OBJECT;
504 }
505 cntlr = GetCntlrFromFilep(filep);
506 if (cntlr == NULL) {
507 HDF_LOGE("MipiDsiDevIoctl: cntlr is null.");
508 return HDF_ERR_INVALID_OBJECT;
509 }
510
511 sem = GetSemaFromFilep(filep);
512 if (sem == NULL) {
513 HDF_LOGE("MipiDsiDevIoctl: sem is null.");
514 return HDF_ERR_INVALID_OBJECT;
515 }
516
517 (void)SemaDownInterruptable(sem);
518 switch (cmd) {
519 case HI_MIPI_TX_SET_DEV_CFG:
520 ret = MipiDsiDevSetCfg(cntlr, (struct MipiCfg *)pArg);
521 break;
522 case HI_MIPI_TX_SET_CMD:
523 ret = MipiDsiDevSetCmd(cntlr, (struct DsiCmdDesc *)pArg);
524 break;
525 case HI_MIPI_TX_GET_CMD:
526 ret = MipiDsiDevGetCmd(cntlr, (GetDsiCmdDescTag *)pArg);
527 break;
528 case HI_MIPI_TX_ENABLE:
529 MipiDsiCntlrSetHsMode(cntlr);
530 HDF_LOGI("MipiDsiDevIoctl: [MipiDsiCntlrSetHsMode] done!");
531 break;
532 case HI_MIPI_TX_DISABLE:
533 MipiDsiCntlrSetLpMode(cntlr);
534 HDF_LOGI("MipiDsiDevIoctl: [MipiDsiCntlrSetLpMode] done!");
535 break;
536 default:
537 HDF_LOGE("MipiDsiDevIoctl: [default] fail!");
538 ret = -1;
539 break;
540 }
541 SemaUp(sem);
542
543 return ret;
544 }
545
MipiDsiDevOpen(struct inode * inode,struct file * filep)546 static int MipiDsiDevOpen(struct inode *inode, struct file *filep)
547 {
548 uint8_t id;
549 (void)inode;
550 (void)filep;
551
552 id = GetId();
553 g_vfsPara[id].cntlr = MipiDsiCntlrOpen(id);
554 HDF_LOGI("MipiDsiDevOpen: success!");
555
556 return 0;
557 }
558
MipiDsiDevRelease(struct inode * inode,struct file * filep)559 static int MipiDsiDevRelease(struct inode *inode, struct file *filep)
560 {
561 uint8_t id;
562 (void)inode;
563 (void)filep;
564
565 id = GetId();
566 if (g_vfsPara[id].cntlr != NULL) {
567 MipiDsiCntlrClose(g_vfsPara[id].cntlr);
568 }
569 HDF_LOGI("MipiDsiDevRelease: success!");
570 return 0;
571 }
572
MipiDsiDevProcDevShow(struct seq_file * s)573 static void MipiDsiDevProcDevShow(struct seq_file *s)
574 {
575 struct MipiCfg *cfg = NULL;
576 struct DsiTimingInfo *t = NULL;
577 uint8_t id;
578
579 id = GetId();
580 if (g_vfsPara[id].cntlr == NULL) {
581 HDF_LOGE("MipiDsiDevProcDevShow: g_vfsPara[id].cntlr is null!");
582 return;
583 }
584 cfg = &(g_vfsPara[id].cntlr->cfg);
585 t = &(cfg->timing);
586
587 /* mipi tx device config */
588 seq_printf(s, "MIPI_Tx DEV CONFIG\n");
589 seq_printf(s, "%8s%15s%15s%15s%15s%15s\n",
590 "lane", "output_mode", "phy_data_rate", "pixel_clk(KHz)",
591 "video_mode", "output_fmt");
592 seq_printf(s, "%8d%15d%15d%15d%15d%15d\n",
593 cfg->lane,
594 cfg->mode,
595 cfg->phyDataRate,
596 cfg->pixelClk,
597 cfg->burstMode,
598 cfg->format);
599 seq_printf(s, "\r\n");
600 /* mipi tx device sync config */
601 seq_printf(s, "MIPI_Tx SYNC CONFIG\n");
602 seq_printf(s, "%14s%14s%14s%14s%14s%14s%14s%14s%14s\n",
603 "pkt_size", "hsa_pixels", "hbp_pixels", "hline_pixels", "vsa_lines", "vbp_lines",
604 "vfp_lines", "active_lines", "edpi_cmd_size");
605 seq_printf(s, "%14d%14d%14d%14d%14d%14d%14d%14d%14d\n",
606 t->xPixels,
607 t->hsaPixels,
608 t->hbpPixels,
609 t->hlinePixels,
610 t->vsaLines,
611 t->vbpLines,
612 t->vfpLines,
613 t->ylines,
614 t->edpiCmdSize);
615 seq_printf(s, "\r\n");
616 HDF_LOGI("MipiDsiDevProcDevShow: success!");
617 }
618
MipiDsiDevProcShow(struct seq_file * m,void * v)619 static int MipiDsiDevProcShow(struct seq_file *m, void *v)
620 {
621 seq_printf(m, "\nModule: [MIPI_TX], Build Time["__DATE__", "__TIME__"]\n");
622 MipiDsiDevProcDevShow(m);
623 HDF_LOGI("MipiDsiDevProcShow: success!");
624 return 0;
625 }
626
MipiDsiDevProcOpen(struct inode * inode,struct file * file)627 static int MipiDsiDevProcOpen(struct inode *inode, struct file *file)
628 {
629 (void)inode;
630 HDF_LOGI("MipiDsiDevProcOpen: enter!");
631 return single_open(file, MipiDsiDevProcShow, NULL);
632 }
633
634 #if LINUX_VERSION_CODE >= KERNEL_VERSION(5, 6, 0)
635 static struct proc_ops g_procMipiDsiDevOps = {
636 .proc_open = MipiDsiDevProcOpen,
637 .proc_read = seq_read,
638 };
639 #else
640 static struct file_operations g_procMipiDsiDevOps = {
641 .open = MipiDsiDevProcOpen,
642 .read = seq_read,
643 };
644 #endif
645
646 static struct file_operations g_mipiTxfOps = {
647 .open = MipiDsiDevOpen,
648 .release = MipiDsiDevRelease,
649 .unlocked_ioctl = MipiDsiDevIoctl,
650 };
651
MipiDsiDevModuleInit(uint8_t id)652 int32_t MipiDsiDevModuleInit(uint8_t id)
653 {
654 int32_t ret;
655
656 /* 0660 : node mode */
657 ret = RegisterDevice(MIPI_TX_DEV_NAME, id, 0660, (struct file_operations *)&g_mipiTxfOps);
658 if (ret != HDF_SUCCESS) {
659 HDF_LOGE("MipiDsiDevModuleInit: [RegisterDevice] fail, ret: %d!", ret);
660 return ret;
661 }
662 ret = ProcRegister(MIPI_TX_PROC_NAME, id, 0440, &g_procMipiDsiDevOps); /* 0440 : proc file mode */
663 if (ret != HDF_SUCCESS) {
664 UnregisterDevice(id);
665 HDF_LOGE("MipiDsiDevModuleInit: [ProcRegister] fail, ret: %d!", ret);
666 return ret;
667 }
668
669 ret = SemaInit(&g_vfsPara[id].sem, 1);
670 if (ret != HDF_SUCCESS) {
671 UnregisterDevice(id);
672 ProcUnregister(MIPI_TX_PROC_NAME, id);
673 HDF_LOGE("MipiDsiDevModuleInit: [SemaInit] fail!");
674 return ret;
675 }
676 HDF_LOGI("MipiDsiDevModuleInit: success!");
677 return ret;
678 }
679
MipiDsiDevModuleExit(uint8_t id)680 void MipiDsiDevModuleExit(uint8_t id)
681 {
682 SemaDestroy(&g_vfsPara[id].sem);
683 UnregisterDevice(id);
684 ProcUnregister(MIPI_TX_PROC_NAME, id);
685
686 HDF_LOGI("MipiDsiDevModuleExit: success!");
687 }
688
689 #ifdef __cplusplus
690 #if __cplusplus
691 }
692 #endif
693 #endif /* End of #ifdef __cplusplus */
694