1 /*
2 * Copyright (C) 2021 HiSilicon (Shanghai) Technologies CO., LIMITED.
3 *
4 * This program is free software; you can redistribute it and/or
5 * modify it under the terms of the GNU General Public License
6 * as published by the Free Software Foundation; either version 2
7 * of the License, or (at your option) any later version.
8 *
9 * This program is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 * GNU General Public License for more details.
13 *
14 * You should have received a copy of the GNU General Public License
15 * along with this program; if not, write to the Free Software
16 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
17 */
18
19 #include <linux/module.h>
20 #include <linux/kernel.h>
21 #include <linux/printk.h>
22 #include <linux/fs.h>
23 #include <linux/poll.h>
24 #include <linux/slab.h>
25 #include <linux/vmalloc.h>
26 #include <linux/mm_types.h>
27 #include <linux/mm.h>
28 #include <linux/kmod.h>
29 #include "himedia.h"
30 #include "securec.h"
31 #include "hi_osal.h"
32
33 #define DRVAL_DEBUG 0
34
35 #define GET_FILE(file) \
36 do { \
37 if (__get_file(file) < 0) \
38 return -1; \
39 } while (0)
40
41 #define PUT_FILE(file) \
42 do { \
43 if (__put_file(file) < 0) \
44 return -1; \
45 } while (0)
46
47 typedef struct osal_coat_dev {
48 struct osal_dev osal_dev;
49 struct himedia_device himedia_dev;
50 } osal_coat_dev_t;
51
52 struct osal_private_data {
53 struct osal_dev *dev;
54 void *data;
55 struct osal_poll table;
56 int f_ref_cnt;
57 };
58
59 spinlock_t g_f_lock;
60
osal_device_init(void)61 void osal_device_init(void)
62 {
63 spin_lock_init(&g_f_lock);
64 }
65
__get_file(struct file * file)66 static int __get_file(struct file *file)
67 {
68 struct osal_private_data *pdata = NULL;
69
70 spin_lock(&g_f_lock);
71 pdata = file->private_data;
72 if (pdata == NULL) {
73 spin_unlock(&g_f_lock);
74 return -1;
75 }
76
77 pdata->f_ref_cnt++;
78 spin_unlock(&g_f_lock);
79
80 return 0;
81 }
82
__put_file(struct file * file)83 static int __put_file(struct file *file)
84 {
85 struct osal_private_data *pdata = NULL;
86
87 spin_lock(&g_f_lock);
88 pdata = file->private_data;
89 if (pdata == NULL) {
90 spin_unlock(&g_f_lock);
91 return -1;
92 }
93
94 pdata->f_ref_cnt--;
95 spin_unlock(&g_f_lock);
96
97 return 0;
98 }
99
osal_open(struct inode * inode,struct file * file)100 static int osal_open(struct inode *inode, struct file *file)
101 {
102 struct himedia_device *himedia = NULL;
103 osal_coat_dev_t *coat_dev = NULL;
104 struct osal_private_data *pdata = NULL;
105
106 osal_unused(inode);
107
108 himedia = (struct himedia_device *)file->private_data;
109 if (himedia == NULL) {
110 osal_trace("%s - get himedia device error!\n", __FUNCTION__);
111 return -1;
112 }
113 coat_dev = osal_container_of(himedia, struct osal_coat_dev, himedia_dev);
114 pdata = (struct osal_private_data *)kmalloc(sizeof(struct osal_private_data), GFP_KERNEL);
115 if (pdata == NULL) {
116 osal_trace("%s - kmalloc error!\n", __FUNCTION__);
117 return -1;
118 }
119 if (DRVAL_DEBUG) {
120 osal_trace("%s - file->private_data=%pK!\n", __FUNCTION__, pdata);
121 }
122
123 (void)memset_s(pdata, sizeof(struct osal_private_data), 0, sizeof(struct osal_private_data));
124
125 file->private_data = pdata;
126 pdata->dev = &(coat_dev->osal_dev);
127 if (coat_dev->osal_dev.fops->open != NULL) {
128 return coat_dev->osal_dev.fops->open((void *)&(pdata->data));
129 }
130 return 0;
131 }
132
osal_read(struct file * file,char __user * buf,size_t size,loff_t * offset)133 static ssize_t osal_read(struct file *file, char __user *buf, size_t size, loff_t *offset)
134 {
135 struct osal_private_data *pdata = file->private_data;
136 int ret = 0;
137
138 GET_FILE(file);
139
140 if (pdata->dev->fops->read != NULL) {
141 ret = pdata->dev->fops->read(buf, (int)size, (long *)offset, (void *)&(pdata->data));
142 }
143
144 PUT_FILE(file);
145 return ret;
146 }
147
osal_write(struct file * file,const char __user * buf,size_t size,loff_t * offset)148 static ssize_t osal_write(struct file *file, const char __user *buf, size_t size, loff_t *offset)
149 {
150 struct osal_private_data *pdata = file->private_data;
151 int ret = -1;
152
153 GET_FILE(file);
154 if (pdata->dev->fops->write != NULL) {
155 ret = pdata->dev->fops->write(buf, (int)size, (long *)offset, (void *)&(pdata->data));
156 }
157 PUT_FILE(file);
158 return ret;
159 }
160
osal_llseek(struct file * file,loff_t offset,int whence)161 static loff_t osal_llseek(struct file *file, loff_t offset, int whence)
162 {
163 struct osal_private_data *pdata = file->private_data;
164 int ret = 0;
165
166 GET_FILE(file);
167 if (DRVAL_DEBUG) {
168 osal_trace("%s - file->private_data=%pK!\n", __FUNCTION__, pdata);
169 }
170
171 if (whence == SEEK_SET) {
172 if (pdata->dev->fops->llseek != NULL) {
173 ret = pdata->dev->fops->llseek((long)offset, OSAL_SEEK_SET, (void *)&(pdata->data));
174 }
175 } else if (whence == SEEK_CUR) {
176 if (pdata->dev->fops->llseek != NULL) {
177 ret = pdata->dev->fops->llseek((long)offset, OSAL_SEEK_CUR, (void *)&(pdata->data));
178 }
179 } else if (whence == SEEK_END) {
180 if (pdata->dev->fops->llseek != NULL) {
181 ret = pdata->dev->fops->llseek((long)offset, OSAL_SEEK_END, (void *)&(pdata->data));
182 }
183 }
184
185 PUT_FILE(file);
186 return (loff_t)ret;
187 }
188
osal_release(struct inode * inode,struct file * file)189 static int osal_release(struct inode *inode, struct file *file)
190 {
191 int ret = 0;
192 struct osal_private_data *pdata = file->private_data;
193
194 osal_unused(inode);
195 GET_FILE(file);
196
197 if (DRVAL_DEBUG) {
198 osal_trace("%s - file->private_data=%pK!\n", __FUNCTION__, pdata);
199 }
200
201 if (pdata->dev->fops->release != NULL) {
202 ret = pdata->dev->fops->release((void *)&(pdata->data));
203 }
204 PUT_FILE(file);
205 if (ret != 0) {
206 osal_trace("%s - release failed!\n", __FUNCTION__);
207 return ret;
208 }
209
210 spin_lock(&g_f_lock);
211 if (pdata->f_ref_cnt != 0) {
212 osal_trace("%s - release failed!\n", __FUNCTION__);
213 spin_unlock(&g_f_lock);
214 return -1;
215 }
216 kfree(file->private_data);
217 file->private_data = NULL;
218 spin_unlock(&g_f_lock);
219
220 return 0;
221 }
222
__osal_unlocked_ioctl(struct file * file,unsigned int cmd,unsigned long arg)223 static long __osal_unlocked_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
224 {
225 int ret = -1;
226 struct osal_private_data *pdata = file->private_data;
227 char *kbuf = NULL;
228
229 if (DRVAL_DEBUG) {
230 osal_trace("%s - file->private_data=%pK!\n", __FUNCTION__, pdata);
231 }
232
233 if (((_IOC_SIZE(cmd) == 0) && (_IOC_DIR(cmd) != _IOC_NONE))) {
234 return -1;
235 }
236
237 if ((_IOC_DIR(cmd) != _IOC_NONE) && (((char *)(uintptr_t)arg) == NULL)) {
238 osal_trace("%s - Input param err,it is null!\n", __FUNCTION__);
239 return -1;
240 }
241
242 if (_IOC_DIR(cmd) == _IOC_NONE) {
243 if (pdata->dev->fops->unlocked_ioctl == NULL) {
244 return -1;
245 } else {
246 ret = pdata->dev->fops->unlocked_ioctl(cmd, (unsigned long)NULL, (void *)&(pdata->data));
247 }
248 } else if (_IOC_DIR(cmd) == _IOC_WRITE) {
249 kbuf = (char *)vmalloc(_IOC_SIZE(cmd));
250 if (kbuf == NULL) {
251 osal_trace("%s - vmalloc failed!\n", __FUNCTION__);
252 return -1;
253 }
254
255 if (copy_from_user(kbuf, (char *)(uintptr_t)arg, _IOC_SIZE(cmd))) {
256 vfree(kbuf);
257 kbuf = NULL;
258 return -1;
259 }
260
261 if (pdata->dev->fops->unlocked_ioctl == NULL) {
262 vfree(kbuf);
263 kbuf = NULL;
264 return -1;
265 } else {
266 ret = pdata->dev->fops->unlocked_ioctl (cmd, (unsigned long)(uintptr_t)kbuf, (void *)&(pdata->data));
267 }
268 } else if (_IOC_DIR(cmd) == _IOC_READ) {
269 if (pdata->dev->fops->unlocked_ioctl == NULL) {
270 return -1;
271 }
272
273 kbuf = vmalloc(_IOC_SIZE(cmd));
274 if (kbuf == NULL) {
275 osal_trace("%s - vmalloc failed!\n", __FUNCTION__);
276 return -1;
277 }
278
279 ret = pdata->dev->fops->unlocked_ioctl (cmd, (unsigned long)(uintptr_t)kbuf, (void *)&(pdata->data));
280 if (ret == 0) {
281 if (copy_to_user((char *)(uintptr_t)arg, kbuf, _IOC_SIZE(cmd))) {
282 vfree(kbuf);
283 return -1;
284 }
285 }
286 } else if (_IOC_DIR(cmd) == (_IOC_READ + _IOC_WRITE)) {
287 kbuf = vmalloc(_IOC_SIZE(cmd));
288 if (kbuf == NULL) {
289 osal_trace("%s - vmalloc failed!\n", __FUNCTION__);
290 return -1;
291 }
292
293 if (copy_from_user(kbuf, (char *)(uintptr_t)arg, _IOC_SIZE(cmd))) {
294 vfree(kbuf);
295 kbuf = NULL;
296 return -1;
297 }
298
299 if (pdata->dev->fops->unlocked_ioctl == NULL) {
300 vfree(kbuf);
301 kbuf = NULL;
302 return -1;
303 } else {
304 ret = pdata->dev->fops->unlocked_ioctl (cmd, (unsigned long)(uintptr_t)kbuf, (void *)&(pdata->data));
305 if (ret == 0) {
306 if (copy_to_user((char *)(uintptr_t)arg, kbuf, _IOC_SIZE(cmd))) {
307 vfree(kbuf);
308 kbuf = NULL;
309 return -1;
310 }
311 }
312 }
313 }
314
315 if (kbuf != NULL) {
316 vfree(kbuf);
317 kbuf = NULL;
318 }
319
320 return ret;
321 }
322
osal_unlocked_ioctl(struct file * file,unsigned int cmd,unsigned long arg)323 static long osal_unlocked_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
324 {
325 long ret;
326
327 GET_FILE(file);
328
329 ret = __osal_unlocked_ioctl(file, cmd, arg);
330 PUT_FILE(file);
331
332 return ret;
333 }
334
335 #ifdef CONFIG_COMPAT
__osal_compat_ioctl(struct file * file,unsigned int cmd,unsigned long arg)336 static long __osal_compat_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
337 {
338 int ret = -1;
339 struct osal_private_data *pdata = file->private_data;
340 char *kbuf = NULL;
341
342 if (DRVAL_DEBUG) {
343 osal_trace("%s - file->private_data=%pK!\n", __FUNCTION__, pdata);
344 }
345
346 if ((_IOC_SIZE(cmd) == 0) && (_IOC_DIR(cmd) != _IOC_NONE)) {
347 return -1;
348 }
349
350 if ((_IOC_DIR(cmd) != _IOC_NONE) && (((char *)(uintptr_t)arg) == NULL)) {
351 osal_trace("%s - Input param err,it is null!\n", __FUNCTION__);
352 return -1;
353 }
354
355 if (_IOC_DIR(cmd) == _IOC_NONE) {
356 if (pdata->dev->fops->compat_ioctl == NULL) {
357 return -1;
358 } else {
359 ret = pdata->dev->fops->compat_ioctl(cmd, arg, (void *)&(pdata->data));
360 }
361 } else if (_IOC_DIR(cmd) == _IOC_WRITE) {
362 kbuf = (char *)vmalloc(_IOC_SIZE(cmd));
363 if (kbuf == NULL) {
364 osal_trace("%s - vmalloc failed!\n", __FUNCTION__);
365 return -1;
366 }
367
368 if (copy_from_user(kbuf, (char *)(uintptr_t)arg, _IOC_SIZE(cmd))) {
369 vfree(kbuf);
370 return -1;
371 }
372
373 if (pdata->dev->fops->compat_ioctl == NULL) {
374 vfree(kbuf);
375 return -1;
376 } else {
377 ret = pdata->dev->fops->compat_ioctl (cmd, (unsigned long)(uintptr_t)kbuf, (void *)&(pdata->data));
378 }
379 } else if (_IOC_DIR(cmd) == _IOC_READ) {
380 kbuf = vmalloc(_IOC_SIZE(cmd));
381 if (kbuf == NULL) {
382 osal_trace("%s - vmalloc failed!\n", __FUNCTION__);
383 return -1;
384 }
385 if (pdata->dev->fops->compat_ioctl == NULL) {
386 vfree(kbuf);
387 return -1;
388 } else {
389 ret = pdata->dev->fops->compat_ioctl (cmd, (unsigned long)(uintptr_t)kbuf, (void *)&(pdata->data));
390 if (ret == 0) {
391 if (copy_to_user((char *)(uintptr_t)arg, kbuf, _IOC_SIZE(cmd))) {
392 vfree(kbuf);
393 return -1;
394 }
395 }
396 }
397 } else if (_IOC_DIR(cmd) == (_IOC_READ + _IOC_WRITE)) {
398 kbuf = vmalloc(_IOC_SIZE(cmd));
399 if (kbuf == NULL) {
400 osal_trace("%s - vmalloc failed!\n", __FUNCTION__);
401 return -1;
402 }
403
404 if (copy_from_user(kbuf, (char *)(uintptr_t)arg, _IOC_SIZE(cmd))) {
405 vfree(kbuf);
406 return -1;
407 }
408
409 if (pdata->dev->fops->compat_ioctl == NULL) {
410 vfree(kbuf);
411 return -1;
412 } else {
413 ret = pdata->dev->fops->compat_ioctl (cmd, (unsigned long)(uintptr_t)kbuf, (void *)&(pdata->data));
414 if (ret == 0) {
415 if (copy_to_user((char *)(uintptr_t)arg, kbuf, _IOC_SIZE(cmd))) {
416 vfree(kbuf);
417 return -1;
418 }
419 }
420 }
421 }
422
423 if (kbuf != NULL) {
424 vfree(kbuf);
425 }
426
427 return ret;
428 }
429
osal_compat_ioctl(struct file * file,unsigned int cmd,unsigned long arg)430 static long osal_compat_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
431 {
432 long ret;
433
434 GET_FILE(file);
435
436 ret = __osal_compat_ioctl(file, cmd, arg);
437 PUT_FILE(file);
438
439 return ret;
440 }
441
442 #endif
443
osal_poll(struct file * file,struct poll_table_struct * table)444 static unsigned int osal_poll(struct file *file, struct poll_table_struct *table)
445 {
446 struct osal_private_data *pdata = file->private_data;
447 struct osal_poll t;
448 unsigned int ret = 0;
449
450 GET_FILE(file);
451
452 if (DRVAL_DEBUG) {
453 osal_trace("%s - table=%pK, file=%pK!\n", __FUNCTION__, table, file);
454 }
455 t.poll_table = table;
456 t.data = file;
457 if (pdata->dev->fops->poll != NULL) {
458 ret = pdata->dev->fops->poll(&t, (void *)&(pdata->data));
459 }
460
461 PUT_FILE(file);
462 return ret;
463 }
464
valid_mmap_phys_addr_range(unsigned long pfn,size_t size)465 int valid_mmap_phys_addr_range(unsigned long pfn, size_t size)
466 {
467 /* check physical addr greater than the max addr supported by the system */
468 if ((pfn + (size >> PAGE_SHIFT)) > (1 + ((~0UL) >> PAGE_SHIFT))) {
469 osal_trace("--%s - %d--!\n", __FUNCTION__, __LINE__);
470 return 0;
471 }
472
473 /* It's necessary for the variable "size" to align 4k(page_size). */
474 #define PAGE_SIZE_MASK 0xfffffffffffff000ULL
475 if ((unsigned long)size & (~PAGE_SIZE_MASK)) {
476 osal_trace("--%s - %d--!\n", __FUNCTION__, __LINE__);
477 return 0;
478 }
479 #undef PAGE_SIZE_MASK
480
481 return 1;
482 }
483
osal_mmap(struct file * file,struct vm_area_struct * vm)484 static int osal_mmap(struct file *file, struct vm_area_struct *vm)
485 {
486 struct osal_vm osal_vm;
487 struct osal_private_data *pdata = file->private_data;
488 osal_vm.vm = vm;
489
490 if (!valid_mmap_phys_addr_range(vm->vm_pgoff, vm->vm_end - vm->vm_start)) {
491 osal_trace("\n%s - invalid argument size=%ld!!!\n", __FUNCTION__, vm->vm_end - vm->vm_start);
492 return -EINVAL;
493 }
494
495 if (DRVAL_DEBUG) {
496 osal_trace("%s - start=%lx, end=%lx!, off=%lx\n", __FUNCTION__, vm->vm_start, vm->vm_end, vm->vm_pgoff);
497 }
498 if (pdata->dev->fops->mmap != NULL) {
499 return pdata->dev->fops->mmap(&osal_vm, vm->vm_start, vm->vm_end, vm->vm_pgoff, (void *)&(pdata->data));
500 }
501 return 0;
502 }
503
504 static struct file_operations g_osal_fops = {
505 .owner = THIS_MODULE,
506 .open = osal_open,
507 .read = osal_read,
508 .write = osal_write,
509 .llseek = osal_llseek,
510 .unlocked_ioctl = osal_unlocked_ioctl,
511 .release = osal_release,
512 .poll = osal_poll,
513 .mmap = osal_mmap,
514 #ifdef CONFIG_COMPAT
515 .compat_ioctl = osal_compat_ioctl,
516 #endif
517 };
518
osal_pm_prepare(struct himedia_device * himedia)519 static int osal_pm_prepare(struct himedia_device *himedia)
520 {
521 osal_coat_dev_t *coat_dev = container_of(himedia, struct osal_coat_dev, himedia_dev);
522 if (coat_dev != NULL) {
523 if (coat_dev->osal_dev.osal_pmops && coat_dev->osal_dev.osal_pmops->pm_prepare) {
524 return coat_dev->osal_dev.osal_pmops->pm_prepare(&(coat_dev->osal_dev));
525 }
526 }
527 return 0;
528 }
529
osal_pm_complete(struct himedia_device * himedia)530 static void osal_pm_complete(struct himedia_device *himedia)
531 {
532 osal_coat_dev_t *coat_dev = container_of(himedia, struct osal_coat_dev, himedia_dev);
533 if (coat_dev != NULL) {
534 if (coat_dev->osal_dev.osal_pmops && coat_dev->osal_dev.osal_pmops->pm_complete) {
535 coat_dev->osal_dev.osal_pmops->pm_complete(&(coat_dev->osal_dev));
536 }
537 }
538 }
539
osal_pm_suspend(struct himedia_device * himedia)540 static int osal_pm_suspend(struct himedia_device *himedia)
541 {
542 osal_coat_dev_t *coat_dev = container_of(himedia, struct osal_coat_dev, himedia_dev);
543 if (coat_dev != NULL) {
544 if (coat_dev->osal_dev.osal_pmops && coat_dev->osal_dev.osal_pmops->pm_suspend) {
545 return coat_dev->osal_dev.osal_pmops->pm_suspend(&(coat_dev->osal_dev));
546 }
547 }
548 return 0;
549 }
550
osal_pm_resume(struct himedia_device * himedia)551 static int osal_pm_resume(struct himedia_device *himedia)
552 {
553 osal_coat_dev_t *coat_dev = container_of(himedia, struct osal_coat_dev, himedia_dev);
554 if (coat_dev != NULL) {
555 if (coat_dev->osal_dev.osal_pmops && coat_dev->osal_dev.osal_pmops->pm_resume) {
556 return coat_dev->osal_dev.osal_pmops->pm_resume(&(coat_dev->osal_dev));
557 }
558 }
559 return 0;
560 }
561
osal_pm_freeze(struct himedia_device * himedia)562 static int osal_pm_freeze(struct himedia_device *himedia)
563 {
564 osal_coat_dev_t *coat_dev = container_of(himedia, struct osal_coat_dev, himedia_dev);
565 if (coat_dev != NULL) {
566 if (coat_dev->osal_dev.osal_pmops && coat_dev->osal_dev.osal_pmops->pm_freeze) {
567 return coat_dev->osal_dev.osal_pmops->pm_freeze(&(coat_dev->osal_dev));
568 }
569 }
570 return 0;
571 }
572
osal_pm_thaw(struct himedia_device * himedia)573 static int osal_pm_thaw(struct himedia_device *himedia)
574 {
575 osal_coat_dev_t *coat_dev = container_of(himedia, struct osal_coat_dev, himedia_dev);
576 if (coat_dev != NULL) {
577 if (coat_dev->osal_dev.osal_pmops && coat_dev->osal_dev.osal_pmops->pm_thaw) {
578 return coat_dev->osal_dev.osal_pmops->pm_thaw(&(coat_dev->osal_dev));
579 }
580 }
581 return 0;
582 }
583
osal_pm_poweroff(struct himedia_device * himedia)584 static int osal_pm_poweroff(struct himedia_device *himedia)
585 {
586 osal_coat_dev_t *coat_dev = container_of(himedia, struct osal_coat_dev, himedia_dev);
587 if (coat_dev != NULL) {
588 if (coat_dev->osal_dev.osal_pmops && coat_dev->osal_dev.osal_pmops->pm_poweroff) {
589 return coat_dev->osal_dev.osal_pmops->pm_poweroff(&(coat_dev->osal_dev));
590 }
591 }
592 return 0;
593 }
594
osal_pm_restore(struct himedia_device * himedia)595 static int osal_pm_restore(struct himedia_device *himedia)
596 {
597 osal_coat_dev_t *coat_dev = container_of(himedia, struct osal_coat_dev, himedia_dev);
598 if (coat_dev != NULL) {
599 if (coat_dev->osal_dev.osal_pmops && coat_dev->osal_dev.osal_pmops->pm_restore) {
600 return coat_dev->osal_dev.osal_pmops->pm_restore(&(coat_dev->osal_dev));
601 }
602 }
603 return 0;
604 }
605
osal_pm_suspend_late(struct himedia_device * himedia)606 static int osal_pm_suspend_late(struct himedia_device *himedia)
607 {
608 osal_coat_dev_t *coat_dev = container_of(himedia, struct osal_coat_dev, himedia_dev);
609 if (coat_dev != NULL) {
610 if (coat_dev->osal_dev.osal_pmops && coat_dev->osal_dev.osal_pmops->pm_suspend_late) {
611 return coat_dev->osal_dev.osal_pmops->pm_suspend_late(&(coat_dev->osal_dev));
612 }
613 }
614 return 0;
615 }
616
osal_pm_resume_early(struct himedia_device * himedia)617 static int osal_pm_resume_early(struct himedia_device *himedia)
618 {
619 osal_coat_dev_t *coat_dev = container_of(himedia, struct osal_coat_dev, himedia_dev);
620 if (coat_dev != NULL) {
621 if (coat_dev->osal_dev.osal_pmops && coat_dev->osal_dev.osal_pmops->pm_resume_early) {
622 return coat_dev->osal_dev.osal_pmops->pm_resume_early(&(coat_dev->osal_dev));
623 }
624 }
625 return 0;
626 }
627
osal_pm_freeze_late(struct himedia_device * himedia)628 static int osal_pm_freeze_late(struct himedia_device *himedia)
629 {
630 osal_coat_dev_t *coat_dev = container_of(himedia, struct osal_coat_dev, himedia_dev);
631 if (coat_dev != NULL) {
632 if (coat_dev->osal_dev.osal_pmops && coat_dev->osal_dev.osal_pmops->pm_freeze_late) {
633 return coat_dev->osal_dev.osal_pmops->pm_freeze_late(&(coat_dev->osal_dev));
634 }
635 }
636 return 0;
637 }
638
osal_pm_thaw_early(struct himedia_device * himedia)639 static int osal_pm_thaw_early(struct himedia_device *himedia)
640 {
641 osal_coat_dev_t *coat_dev = container_of(himedia, struct osal_coat_dev, himedia_dev);
642 if (coat_dev != NULL) {
643 if (coat_dev->osal_dev.osal_pmops && coat_dev->osal_dev.osal_pmops->pm_thaw_early) {
644 return coat_dev->osal_dev.osal_pmops->pm_thaw_early(&(coat_dev->osal_dev));
645 }
646 }
647 return 0;
648 }
649
osal_pm_poweroff_late(struct himedia_device * himedia)650 static int osal_pm_poweroff_late(struct himedia_device *himedia)
651 {
652 osal_coat_dev_t *coat_dev = container_of(himedia, struct osal_coat_dev, himedia_dev);
653 if (coat_dev != NULL) {
654 if (coat_dev->osal_dev.osal_pmops && coat_dev->osal_dev.osal_pmops->pm_poweroff_late) {
655 return coat_dev->osal_dev.osal_pmops->pm_poweroff_late(&(coat_dev->osal_dev));
656 }
657 }
658 return 0;
659 }
660
osal_pm_restore_early(struct himedia_device * himedia)661 static int osal_pm_restore_early(struct himedia_device *himedia)
662 {
663 osal_coat_dev_t *coat_dev = container_of(himedia, struct osal_coat_dev, himedia_dev);
664 if (coat_dev != NULL) {
665 if (coat_dev->osal_dev.osal_pmops && coat_dev->osal_dev.osal_pmops->pm_restore_early) {
666 return coat_dev->osal_dev.osal_pmops->pm_restore_early(&(coat_dev->osal_dev));
667 }
668 }
669 return 0;
670 }
671
osal_pm_suspend_noirq(struct himedia_device * himedia)672 static int osal_pm_suspend_noirq(struct himedia_device *himedia)
673 {
674 osal_coat_dev_t *coat_dev = container_of(himedia, struct osal_coat_dev, himedia_dev);
675 if (coat_dev != NULL) {
676 if (coat_dev->osal_dev.osal_pmops && coat_dev->osal_dev.osal_pmops->pm_suspend_noirq) {
677 return coat_dev->osal_dev.osal_pmops->pm_suspend_noirq(&(coat_dev->osal_dev));
678 }
679 }
680 return 0;
681 }
682
osal_pm_resume_noirq(struct himedia_device * himedia)683 static int osal_pm_resume_noirq(struct himedia_device *himedia)
684 {
685 osal_coat_dev_t *coat_dev = container_of(himedia, struct osal_coat_dev, himedia_dev);
686 if (coat_dev != NULL) {
687 if (coat_dev->osal_dev.osal_pmops && coat_dev->osal_dev.osal_pmops->pm_resume_noirq) {
688 return coat_dev->osal_dev.osal_pmops->pm_resume_noirq(&(coat_dev->osal_dev));
689 }
690 }
691 return 0;
692 }
693
osal_pm_freeze_noirq(struct himedia_device * himedia)694 static int osal_pm_freeze_noirq(struct himedia_device *himedia)
695 {
696 osal_coat_dev_t *coat_dev = container_of(himedia, struct osal_coat_dev, himedia_dev);
697 if (coat_dev != NULL) {
698 if (coat_dev->osal_dev.osal_pmops && coat_dev->osal_dev.osal_pmops->pm_freeze_noirq) {
699 return coat_dev->osal_dev.osal_pmops->pm_freeze_noirq(&(coat_dev->osal_dev));
700 }
701 }
702 return 0;
703 }
704
osal_pm_thaw_noirq(struct himedia_device * himedia)705 static int osal_pm_thaw_noirq(struct himedia_device *himedia)
706 {
707 osal_coat_dev_t *coat_dev = container_of(himedia, struct osal_coat_dev, himedia_dev);
708 if (coat_dev != NULL) {
709 if (coat_dev->osal_dev.osal_pmops && coat_dev->osal_dev.osal_pmops->pm_thaw_noirq) {
710 return coat_dev->osal_dev.osal_pmops->pm_thaw_noirq(&(coat_dev->osal_dev));
711 }
712 }
713 return 0;
714 }
715
osal_pm_poweroff_noirq(struct himedia_device * himedia)716 static int osal_pm_poweroff_noirq(struct himedia_device *himedia)
717 {
718 osal_coat_dev_t *coat_dev = container_of(himedia, struct osal_coat_dev, himedia_dev);
719 if (coat_dev != NULL) {
720 if (coat_dev->osal_dev.osal_pmops && coat_dev->osal_dev.osal_pmops->pm_poweroff_noirq) {
721 return coat_dev->osal_dev.osal_pmops->pm_poweroff_noirq(&(coat_dev->osal_dev));
722 }
723 }
724 return 0;
725 }
726
osal_pm_restore_noirq(struct himedia_device * himedia)727 static int osal_pm_restore_noirq(struct himedia_device *himedia)
728 {
729 osal_coat_dev_t *coat_dev = container_of(himedia, struct osal_coat_dev, himedia_dev);
730 if (coat_dev != NULL) {
731 if (coat_dev->osal_dev.osal_pmops && coat_dev->osal_dev.osal_pmops->pm_restore_noirq) {
732 return coat_dev->osal_dev.osal_pmops->pm_restore_noirq(&(coat_dev->osal_dev));
733 }
734 }
735 return 0;
736 }
737
738 static struct himedia_ops g_osal_pmops = {
739 .pm_prepare = osal_pm_prepare,
740 .pm_complete = osal_pm_complete,
741 .pm_suspend = osal_pm_suspend,
742 .pm_resume = osal_pm_resume,
743 .pm_freeze = osal_pm_freeze,
744 .pm_thaw = osal_pm_thaw,
745 .pm_poweroff = osal_pm_poweroff,
746 .pm_restore = osal_pm_restore,
747 .pm_suspend_late = osal_pm_suspend_late,
748 .pm_resume_early = osal_pm_resume_early,
749 .pm_freeze_late = osal_pm_freeze_late,
750 .pm_thaw_early = osal_pm_thaw_early,
751 .pm_poweroff_late = osal_pm_poweroff_late,
752 .pm_restore_early = osal_pm_restore_early,
753 .pm_suspend_noirq = osal_pm_suspend_noirq,
754 .pm_resume_noirq = osal_pm_resume_noirq,
755 .pm_freeze_noirq = osal_pm_freeze_noirq,
756 .pm_thaw_noirq = osal_pm_thaw_noirq,
757 .pm_poweroff_noirq = osal_pm_poweroff_noirq,
758 .pm_restore_noirq = osal_pm_restore_noirq,
759 };
760
osal_createdev(const char * name)761 osal_dev_t *osal_createdev(const char *name)
762 {
763 osal_coat_dev_t *pdev = NULL;
764 errno_t err_value;
765
766 if (name == NULL) {
767 osal_trace("%s - parameter invalid!\n", __FUNCTION__);
768 return NULL;
769 }
770 pdev = (osal_coat_dev_t *)kmalloc(sizeof(osal_coat_dev_t), GFP_KERNEL);
771 if (pdev == NULL) {
772 osal_trace("%s - kmalloc error!\n", __FUNCTION__);
773 return NULL;
774 }
775 (void)memset_s(pdev, sizeof(osal_coat_dev_t), 0, sizeof(osal_coat_dev_t));
776 err_value = strncpy_s(pdev->osal_dev.name, OSAL_MAX_DEV_NAME_LEN, name, sizeof(pdev->osal_dev.name) - 1);
777 if (err_value != EOK) {
778 kfree(pdev);
779 osal_trace("%s - strncpy_s failed!\n", __FUNCTION__);
780 return NULL;
781 }
782 pdev->osal_dev.dev = pdev;
783 return &(pdev->osal_dev);
784 }
785 EXPORT_SYMBOL(osal_createdev);
786
osal_destroydev(osal_dev_t * osal_dev)787 int osal_destroydev(osal_dev_t *osal_dev)
788 {
789 osal_coat_dev_t *pdev = NULL;
790 if (osal_dev == NULL) {
791 osal_trace("%s - parameter invalid!\n", __FUNCTION__);
792 return -1;
793 }
794 pdev = osal_dev->dev;
795 if (pdev == NULL) {
796 osal_trace("%s - parameter invalid!\n", __FUNCTION__);
797 return -1;
798 }
799 kfree(pdev);
800 return 0;
801 }
802 EXPORT_SYMBOL(osal_destroydev);
803
osal_registerdevice(osal_dev_t * osal_dev)804 int osal_registerdevice(osal_dev_t *osal_dev)
805 {
806 struct himedia_device *himedia = NULL;
807 errno_t err_value;
808
809 if ((osal_dev == NULL) || (osal_dev->fops == NULL)) {
810 osal_trace("%s - parameter invalid!\n", __FUNCTION__);
811 return -1;
812 }
813 himedia = &(((osal_coat_dev_t *)(osal_dev->dev))->himedia_dev);
814 if (osal_dev->minor != 0) {
815 himedia->minor = osal_dev->minor;
816 } else {
817 himedia->minor = HIMEDIA_DYNAMIC_MINOR;
818 }
819 himedia->owner = THIS_MODULE;
820 himedia->fops = &g_osal_fops;
821 himedia->drvops = &g_osal_pmops;
822 err_value = strncpy_s(himedia->devfs_name, HIMIDIA_MAX_DEV_NAME_LEN, osal_dev->name,
823 sizeof(himedia->devfs_name) - 1);
824 if (err_value != EOK) {
825 osal_trace("%s - strncpy_s failed!\n", __FUNCTION__);
826 return -1;
827 }
828 return himedia_register(himedia);
829 }
830 EXPORT_SYMBOL(osal_registerdevice);
831
osal_deregisterdevice(osal_dev_t * pdev)832 void osal_deregisterdevice(osal_dev_t *pdev)
833 {
834 if (pdev == NULL) {
835 osal_trace("%s - parameter invalid!\n", __FUNCTION__);
836 return;
837 }
838 himedia_unregister((struct himedia_device *)&(((osal_coat_dev_t *)(pdev->dev))->himedia_dev));
839 }
840 EXPORT_SYMBOL(osal_deregisterdevice);
841
osal_poll_wait(osal_poll_t * table,osal_wait_t * wait)842 void osal_poll_wait(osal_poll_t *table, osal_wait_t *wait)
843 {
844 if ((table != NULL) && (wait != NULL)) {
845 if (DRVAL_DEBUG) {
846 osal_trace("%s - call poll_wait +!, table=%pK, file=%pK\n", __FUNCTION__, table->poll_table, table->data);
847 }
848
849 poll_wait ((struct file *)table->data, (wait_queue_head_t *)(wait->wait), table->poll_table);
850
851 if (DRVAL_DEBUG) {
852 osal_trace("%s - call poll_wait -!\n", __FUNCTION__);
853 }
854 }
855 }
856 EXPORT_SYMBOL(osal_poll_wait);
857
osal_pgprot_noncached(osal_vm_t * vm)858 void osal_pgprot_noncached(osal_vm_t *vm)
859 {
860 if (vm != NULL) {
861 struct vm_area_struct *v = (struct vm_area_struct *)(vm->vm);
862 v->vm_page_prot = pgprot_writecombine(v->vm_page_prot);
863 }
864 }
865 EXPORT_SYMBOL(osal_pgprot_noncached);
866
osal_pgprot_cached(osal_vm_t * vm)867 void osal_pgprot_cached(osal_vm_t *vm)
868 {
869 if (vm != NULL) {
870 struct vm_area_struct *v = (struct vm_area_struct *)(vm->vm);
871
872 #ifdef CONFIG_64BIT
873 v->vm_page_prot = __pgprot(pgprot_val(v->vm_page_prot) |
874 PTE_VALID | PTE_DIRTY | PTE_AF);
875 #else
876
877 v->vm_page_prot = __pgprot(pgprot_val(v->vm_page_prot) | L_PTE_PRESENT |
878 L_PTE_YOUNG | L_PTE_DIRTY | L_PTE_MT_DEV_CACHED);
879 #endif
880 }
881 }
882 EXPORT_SYMBOL(osal_pgprot_cached);
883
osal_pgprot_writecombine(osal_vm_t * vm)884 void osal_pgprot_writecombine(osal_vm_t *vm)
885 {
886 if (vm != NULL) {
887 struct vm_area_struct *v = (struct vm_area_struct *)(vm->vm);
888 v->vm_page_prot = pgprot_writecombine(v->vm_page_prot);
889 }
890 }
891 EXPORT_SYMBOL(osal_pgprot_writecombine);
892
osal_remap_pfn_range(osal_vm_t * vm,unsigned long addr,unsigned long pfn,unsigned long size)893 int osal_remap_pfn_range(osal_vm_t *vm, unsigned long addr, unsigned long pfn, unsigned long size)
894 {
895 struct vm_area_struct *v = NULL;
896 if (vm == NULL) {
897 return -EINVAL;
898 }
899 v = (struct vm_area_struct *)(vm->vm);
900 if (size == 0) {
901 return -EPERM;
902 }
903 return remap_pfn_range(v, addr, pfn, size, v->vm_page_prot);
904 }
905 EXPORT_SYMBOL(osal_remap_pfn_range);
906
907