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