1 /*
2 * mipi_tx_dev.c
3 *
4 * create vfs node for mipi
5 *
6 * Copyright (c) 2021 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("%s: name, ops or id is error.", __func__);
72 return HDF_ERR_INVALID_PARAM;
73 }
74 dev = OsalMemCalloc(sizeof(struct miscdevice));
75 if (dev == NULL) {
76 HDF_LOGE("%s: [OsalMemCalloc] failed.", __func__);
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("%s: [OsalMemCalloc] failed.", __func__);
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("%s: [snprintf_s] failed.", __func__);
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("%s: [memcpy_s] failed.", __func__);
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("%s: id %u cannot register miscdev on minor=%d (err=%d)",
107 __func__, 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("mipi_dsi:create inode ok %s %d", dev->name, dev->minor);
116 HDF_LOGI("%s: success.", __func__);
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("%s: name, ops or id is error.", __func__);
133 return HDF_ERR_INVALID_PARAM;
134 }
135 if (memset_s(procName, NAME_LEN + 1, 0, NAME_LEN + 1) != EOK) {
136 HDF_LOGE("%s: [memcpy_s] failed.", __func__);
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 "%s: procName %s snprintf_s fail", __func__, procName);
146 return HDF_FAILURE;
147 }
148 entry = proc_create(procName, mode, NULL, ops);
149 if (entry == NULL) {
150 printk(KERN_ERR "%s: proc_create name %s fail", __func__, procName);
151 return HDF_FAILURE;
152 }
153 HDF_LOGI("%s: success.", __func__);
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("%s: id error.", __func__);
163 return;
164 }
165 dev = g_vfsPara[id].miscdev;
166 if (dev == NULL) {
167 HDF_LOGE("%s: dev is NULL.", __func__);
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("%s: success.", __func__);
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("%s: id error.", __func__);
187 return;
188 }
189 if (memset_s(procName, NAME_LEN + 1, 0, NAME_LEN + 1) != EOK) {
190 HDF_LOGE("%s: [memcpy_s] failed.", __func__);
191 return;
192 }
193 if (id != 0) {
194 ret = snprintf_s(procName, NAME_LEN + 1, NAME_LEN, "%s%u", 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 "%s: procName format fail", __func__);
200 return;
201 }
202 remove_proc_entry(procName, NULL);
203 HDF_LOGI("%s: success.", __func__);
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("%s: sem is NULL", __func__);
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("%s: failed g_curId = %u.", __func__, g_curId);
236 return 0;
237 }
238
239 HDF_LOGI("%s: success.", __func__);
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("%s: filep is invalid.", __func__);
248 return 0;
249 }
250
251 if (filep->private_data == NULL) {
252 HDF_LOGE("%s: private_data is NULL.", __func__);
253 return 0;
254 }
255
256 id = (uint8_t)(filep->private_data);
257 if (id >= MAX_CNTLR_CNT) {
258 HDF_LOGE("%s: id error.", __func__);
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("%s: filep is invalid.", __func__);
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("%s: filep is invalid.", __func__);
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("%s: filep is invalid.", __func__);
294 return NULL;
295 }
296 id = GetId();
297 if (g_vfsPara[id].cntlr == NULL) {
298 HDF_LOGE("%s: g_vfsPara[id].cntlr is NULL.", __func__);
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("%s: arg is invalid.", __func__);
313 return HDF_ERR_INVALID_PARAM;
314 }
315
316 if (cntlr == NULL) {
317 HDF_LOGE("%s: cntlr is NULL.", __func__);
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("%s: OsalMemCalloc error.", __func__);
325 return HDF_ERR_MALLOC_FAIL;
326 }
327
328 if (access_ok(
329 #if LINUX_VERSION_CODE < KERNEL_VERSION(5,6,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("%s: [CopyFromUser] failed.", __func__);
337 return HDF_ERR_IO;
338 }
339 } else {
340 OsalMemFree(temp);
341 temp = NULL;
342 HDF_LOGE("%s: illegal user space address.", __func__);
343 return HDF_FAILURE;
344 }
345
346 ret = MipiDsiCntlrSetCfg(cntlr, temp);
347 g_curId = cntlr->devNo;
348 OsalMemFree(temp);
349 HDF_LOGI("%s: success.", __func__);
350
351 return ret;
352 }
353
MipiDsiDevSetCmd(struct MipiDsiCntlr * cntlr,struct DsiCmdDesc * arg)354 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("%s: arg is invalid.", __func__);
362 return HDF_ERR_INVALID_PARAM;
363 }
364
365 if (cntlr == NULL) {
366 HDF_LOGE("%s: cntlr is NULL.", __func__);
367 return HDF_ERR_INVALID_PARAM;
368 }
369
370 size = sizeof(struct DsiCmdDesc);
371 temp = (struct DsiCmdDesc *)OsalMemCalloc(size);
372 if (temp == NULL) {
373 HDF_LOGE("%s: [OsalMemCalloc] error.", __func__);
374 return HDF_ERR_MALLOC_FAIL;
375 }
376
377 if (access_ok(
378 #if LINUX_VERSION_CODE < KERNEL_VERSION(5,6,0)
379 VERIFY_READ,
380 #endif
381 arg, size)) { /* user space */
382 if (CopyFromUser(temp, arg, size) != 0) {
383 OsalMemFree(temp);
384 temp = NULL;
385 HDF_LOGE("%s: [CopyFromUser] failed.", __func__);
386 return HDF_ERR_IO;
387 }
388 } else {
389 OsalMemFree(temp);
390 temp = NULL;
391 HDF_LOGE("%s: illegal user space address.", __func__);
392 return HDF_FAILURE;
393 }
394
395 ret = MipiDsiCntlrTx(cntlr, temp);
396 OsalMemFree(temp);
397 HDF_LOGI("%s: success.", __func__);
398
399 return ret;
400 }
401
MipiDsiDevCmdCopyFromUser(GetDsiCmdDescTag * arg,GetDsiCmdDescTag * temp,uint32_t * size)402 int32_t MipiDsiDevCmdCopyFromUser(GetDsiCmdDescTag *arg, GetDsiCmdDescTag *temp, uint32_t *size)
403 {
404 if (access_ok(
405 #if LINUX_VERSION_CODE < KERNEL_VERSION(5,6,0)
406 VERIFY_READ,
407 #endif
408 arg, *size)) { /* user space */
409 if (CopyFromUser(temp, arg, *size) != 0) {
410 HDF_LOGE("%s: [CopyFromUser] failed.", __func__);
411 return HDF_ERR_IO;
412 }
413 } else {
414 HDF_LOGE("%s: illegal user space address.", __func__);
415 return HDF_FAILURE;
416 }
417 return HDF_SUCCESS;
418 }
419
MipiDsiDevCmdCopyToUser(GetDsiCmdDescTag * arg,GetDsiCmdDescTag * temp,uint32_t * size)420 int32_t MipiDsiDevCmdCopyToUser(GetDsiCmdDescTag *arg, GetDsiCmdDescTag *temp, uint32_t *size)
421 {
422 if (access_ok(
423 #if LINUX_VERSION_CODE < KERNEL_VERSION(5,6,0)
424 VERIFY_WRITE,
425 #endif
426 arg, *size)) { /* user space */
427 if (CopyToUser(arg, temp, *size) != 0) {
428 HDF_LOGE("%s: [CopyToUser] failed.", __func__);
429 return HDF_ERR_IO;
430 }
431 } else {
432 HDF_LOGE("%s: illegal user space address.", __func__);
433 return HDF_FAILURE;
434 }
435 return HDF_SUCCESS;
436 }
437
MipiDsiDevGetCmd(struct MipiDsiCntlr * cntlr,GetDsiCmdDescTag * arg)438 int32_t MipiDsiDevGetCmd(struct MipiDsiCntlr *cntlr, GetDsiCmdDescTag *arg)
439 {
440 int32_t ret;
441 GetDsiCmdDescTag *temp = NULL;
442 uint32_t size;
443
444 if ((cntlr == NULL) || (arg == NULL)) {
445 HDF_LOGE("%s: cntlr or arg is NULL.", __func__);
446 return HDF_ERR_INVALID_PARAM;
447 }
448
449 size = sizeof(GetDsiCmdDescTag);
450 temp = (GetDsiCmdDescTag *)OsalMemCalloc(size);
451 if (temp == NULL) {
452 HDF_LOGE("%s: [OsalMemCalloc] error.", __func__);
453 return HDF_ERR_MALLOC_FAIL;
454 }
455 if (MipiDsiDevCmdCopyFromUser(arg, temp, &size) != HDF_SUCCESS) {
456 goto fail0;
457 }
458 ret = MipiDsiCntlrRx(cntlr, &temp->readCmd, temp->readLen, temp->out);
459 if (ret != HDF_SUCCESS) {
460 HDF_LOGE("%s: [MipiDsiCntlrRx] failed.", __func__);
461 goto fail0;
462 }
463 if (MipiDsiDevCmdCopyToUser(arg, temp, &size) != HDF_SUCCESS) {
464 goto fail0;
465 }
466 OsalMemFree(temp);
467 temp = NULL;
468 HDF_LOGI("%s: success.", __func__);
469 return HDF_SUCCESS;
470 fail0:
471 OsalMemFree(temp);
472 temp = NULL;
473 return HDF_FAILURE;
474 }
475
MipiDsiDevIoctl(struct file * filep,unsigned int cmd,unsigned long arg)476 static long MipiDsiDevIoctl(struct file *filep, unsigned int cmd, unsigned long arg)
477 {
478 int32_t ret = HDF_SUCCESS;
479 void *pArg = (void *)arg;
480 struct MipiDsiCntlr *cntlr = NULL;
481 struct semaphore *sem = NULL;
482
483 if (filep == NULL || pArg == NULL) {
484 HDF_LOGE("%s: filep or pArg is NULL.", __func__);
485 return HDF_ERR_INVALID_OBJECT;
486 }
487 cntlr = GetCntlrFromFilep(filep);
488 if (cntlr == NULL) {
489 HDF_LOGE("%s: cntlr is NULL.", __func__);
490 return HDF_ERR_INVALID_OBJECT;
491 }
492
493 sem = GetSemaFromFilep(filep);
494 if (sem == NULL) {
495 HDF_LOGE("%s: sem is NULL.", __func__);
496 return HDF_ERR_INVALID_OBJECT;
497 }
498
499 (void)SemaDownInterruptable(sem);
500 switch (cmd) {
501 case HI_MIPI_TX_SET_DEV_CFG:
502 ret = MipiDsiDevSetCfg(cntlr, (struct MipiCfg *)pArg);
503 break;
504 case HI_MIPI_TX_SET_CMD:
505 ret = MipiDsiDevSetCmd(cntlr, (struct DsiCmdDesc *)pArg);
506 break;
507 case HI_MIPI_TX_GET_CMD:
508 ret = MipiDsiDevGetCmd(cntlr, (GetDsiCmdDescTag *)pArg);
509 break;
510 case HI_MIPI_TX_ENABLE:
511 MipiDsiCntlrSetHsMode(cntlr);
512 HDF_LOGI("%s: [MipiDsiCntlrSetHsMode] done.", __func__);
513 break;
514 case HI_MIPI_TX_DISABLE:
515 MipiDsiCntlrSetLpMode(cntlr);
516 HDF_LOGI("%s: [MipiDsiCntlrSetLpMode] done.", __func__);
517 break;
518 default:
519 HDF_LOGE("%s: [default] failed.", __func__);
520 ret = -1;
521 break;
522 }
523 SemaUp(sem);
524
525 return ret;
526 }
527
MipiDsiDevOpen(struct inode * inode,struct file * filep)528 static int MipiDsiDevOpen(struct inode *inode, struct file *filep)
529 {
530 uint8_t id;
531 (void)inode;
532 (void)filep;
533
534 id = GetId();
535 g_vfsPara[id].cntlr = MipiDsiCntlrOpen(id);
536 HDF_LOGI("%s: success.", __func__);
537
538 return 0;
539 }
540
MipiDsiDevRelease(struct inode * inode,struct file * filep)541 static int MipiDsiDevRelease(struct inode *inode, struct file *filep)
542 {
543 uint8_t id;
544 (void)inode;
545 (void)filep;
546
547 id = GetId();
548 if (g_vfsPara[id].cntlr != NULL) {
549 MipiDsiCntlrClose(g_vfsPara[id].cntlr);
550 }
551 HDF_LOGI("%s: success.", __func__);
552 return 0;
553 }
554
MipiDsiDevProcDevShow(struct seq_file * s)555 static void MipiDsiDevProcDevShow(struct seq_file *s)
556 {
557 struct MipiCfg *cfg = NULL;
558 struct DsiTimingInfo *t = NULL;
559 uint8_t id;
560
561 id = GetId();
562 if (g_vfsPara[id].cntlr == NULL) {
563 HDF_LOGE("%s: g_vfsPara[id].cntlr is NULL", __func__);
564 return;
565 }
566 cfg = &(g_vfsPara[id].cntlr->cfg);
567 t = &(cfg->timing);
568
569 /* mipi tx device config */
570 seq_printf(s, "MIPI_Tx DEV CONFIG\n");
571 seq_printf(s, "%8s%15s%15s%15s%15s%15s\n",
572 "lane", "output_mode", "phy_data_rate", "pixel_clk(KHz)",
573 "video_mode", "output_fmt");
574 seq_printf(s, "%8d%15d%15d%15d%15d%15d\n",
575 cfg->lane,
576 cfg->mode,
577 cfg->phyDataRate,
578 cfg->pixelClk,
579 cfg->burstMode,
580 cfg->format);
581 seq_printf(s, "\r\n");
582 /* mipi tx device sync config */
583 seq_printf(s, "MIPI_Tx SYNC CONFIG\n");
584 seq_printf(s, "%14s%14s%14s%14s%14s%14s%14s%14s%14s\n",
585 "pkt_size", "hsa_pixels", "hbp_pixels", "hline_pixels", "vsa_lines", "vbp_lines",
586 "vfp_lines", "active_lines", "edpi_cmd_size");
587 seq_printf(s, "%14d%14d%14d%14d%14d%14d%14d%14d%14d\n",
588 t->xPixels,
589 t->hsaPixels,
590 t->hbpPixels,
591 t->hlinePixels,
592 t->vsaLines,
593 t->vbpLines,
594 t->vfpLines,
595 t->ylines,
596 t->edpiCmdSize);
597 seq_printf(s, "\r\n");
598 HDF_LOGI("%s: success.", __func__);
599 }
600
MipiDsiDevProcShow(struct seq_file * m,void * v)601 static int MipiDsiDevProcShow(struct seq_file *m, void *v)
602 {
603 seq_printf(m, "\nModule: [MIPI_TX], Build Time["__DATE__", "__TIME__"]\n");
604 MipiDsiDevProcDevShow(m);
605 HDF_LOGI("%s: v %p", __func__, v);
606 HDF_LOGI("%s: success.", __func__);
607 return 0;
608 }
609
MipiDsiDevProcOpen(struct inode * inode,struct file * file)610 static int MipiDsiDevProcOpen(struct inode *inode, struct file *file)
611 {
612 (void)inode;
613 HDF_LOGE("%s: enter.", __func__);
614 return single_open(file, MipiDsiDevProcShow, NULL);
615 }
616
617 #if LINUX_VERSION_CODE >= KERNEL_VERSION(5,6,0)
618 static struct proc_ops g_procMipiDsiDevOps = {
619 .proc_open = MipiDsiDevProcOpen,
620 .proc_read = seq_read,
621 };
622 #else
623 static struct file_operations g_procMipiDsiDevOps = {
624 .open = MipiDsiDevProcOpen,
625 .read = seq_read,
626 };
627 #endif
628
629 static struct file_operations g_mipiTxfOps = {
630 .open = MipiDsiDevOpen,
631 .release = MipiDsiDevRelease,
632 .unlocked_ioctl = MipiDsiDevIoctl,
633 };
634
MipiDsiDevModuleInit(uint8_t id)635 int32_t MipiDsiDevModuleInit(uint8_t id)
636 {
637 int32_t ret;
638
639 /* 0660 : node mode */
640 ret = RegisterDevice(MIPI_TX_DEV_NAME, id, 0660, (struct file_operations *)&g_mipiTxfOps);
641 if (ret != HDF_SUCCESS) {
642 HDF_LOGE("%s: [RegisterDevice] fail: %d.", __func__, ret);
643 return ret;
644 }
645 ret = ProcRegister(MIPI_TX_PROC_NAME, id, 0440, &g_procMipiDsiDevOps); /* 0440 : proc file mode */
646 if (ret != HDF_SUCCESS) {
647 UnregisterDevice(id);
648 HDF_LOGE("%s: [ProcRegister] fail: %d.", __func__, ret);
649 return ret;
650 }
651
652 ret = SemaInit(&g_vfsPara[id].sem, 1);
653 if (ret != HDF_SUCCESS) {
654 UnregisterDevice(id);
655 ProcUnregister(MIPI_TX_PROC_NAME, id);
656 HDF_LOGE("%s: [SemaInit] failed.", __func__);
657 return ret;
658 }
659 HDF_LOGI("%s: success!", __func__);
660 return ret;
661 }
662
MipiDsiDevModuleExit(uint8_t id)663 void MipiDsiDevModuleExit(uint8_t id)
664 {
665 SemaDestroy(&g_vfsPara[id].sem);
666 UnregisterDevice(id);
667 ProcUnregister(MIPI_TX_PROC_NAME, id);
668
669 HDF_LOGI("%s: success!", __func__);
670 }
671
672 #ifdef __cplusplus
673 #if __cplusplus
674 }
675 #endif
676 #endif /* End of #ifdef __cplusplus */
677