/* * Copyright (c) XMEDIA. All rights reserved. */ #include #include #include #include #include #include #include #include #include #include #include #include "media.h" #include "osal.h" #include "osal_devfreq.h" #define DRVAL_DEBUG 0 #define GET_FILE(file) \ do { \ if (__get_file(file) < 0) \ return -1; \ } while (0) #define PUT_FILE(file) \ do { \ if (__put_file(file) < 0) \ return -1; \ } while (0) typedef struct osal_coat_dev { struct osal_dev osal_dev; struct media_device media_dev; } osal_coat_dev_t; struct osal_private_data { struct osal_dev *dev; void *data; struct osal_poll table; int f_ref_cnt; }; spinlock_t f_lock; void osal_device_init(void) { spin_lock_init(&f_lock); } static int __get_file(struct file *file) { struct osal_private_data *pdata = NULL; spin_lock(&f_lock); pdata = file->private_data; if (pdata == NULL) { spin_unlock(&f_lock); return -1; } pdata->f_ref_cnt++; spin_unlock(&f_lock); return 0; } static int __put_file(struct file *file) { struct osal_private_data *pdata = NULL; spin_lock(&f_lock); pdata = file->private_data; if (pdata == NULL) { spin_unlock(&f_lock); return -1; } pdata->f_ref_cnt--; spin_unlock(&f_lock); return 0; } static int osal_open(struct inode *inode, struct file *file) { struct media_device *media = NULL; osal_coat_dev_t *coat_dev = NULL; struct osal_private_data *pdata = NULL; if (!capable(CAP_SYS_RAWIO) || !capable(CAP_SYS_ADMIN)) { return -EPERM; } // media = getmedia(inode); media = (struct media_device *)file->private_data; if (media == NULL) { osal_printk("%s - get media device error!\n", __FUNCTION__); return -1; } coat_dev = osal_container_of(media, struct osal_coat_dev, media_dev); pdata = (struct osal_private_data *)kmalloc(sizeof(struct osal_private_data), GFP_KERNEL); if (pdata == NULL) { osal_printk("%s - kmalloc error!\n", __FUNCTION__); return -1; } if (DRVAL_DEBUG) { osal_printk("%s - file->private_data=%pK!\n", __FUNCTION__, pdata); } memset(pdata, 0, sizeof(struct osal_private_data)); file->private_data = pdata; pdata->dev = &(coat_dev->osal_dev); if (coat_dev->osal_dev.fops->open != NULL) { return coat_dev->osal_dev.fops->open((void *)&(pdata->data)); } return 0; } static ssize_t osal_read(struct file *file, char __user *buf, size_t size, loff_t *offset) { struct osal_private_data *pdata = file->private_data; int ret = 0; GET_FILE(file); if (pdata->dev->fops->read != NULL) { ret = pdata->dev->fops->read(buf, (int)size, (long *)offset, (void *)&(pdata->data)); } PUT_FILE(file); return ret; } static ssize_t osal_write(struct file *file, const char __user *buf, size_t size, loff_t *offset) { struct osal_private_data *pdata = file->private_data; int ret = 0; GET_FILE(file); if (pdata->dev->fops->write != NULL) { ret = pdata->dev->fops->write(buf, (int)size, (long *)offset, (void *)&(pdata->data)); } PUT_FILE(file); return ret; } static loff_t osal_llseek(struct file *file, loff_t offset, int whence) { struct osal_private_data *pdata = file->private_data; int ret = 0; GET_FILE(file); if (DRVAL_DEBUG) { osal_printk("%s - file->private_data=%pK!\n", __FUNCTION__, pdata); } if (whence == SEEK_SET) { if (pdata->dev->fops->llseek != NULL) { ret = pdata->dev->fops->llseek((long)offset, OSAL_SEEK_SET, (void *)&(pdata->data)); } } else if (whence == SEEK_CUR) { if (pdata->dev->fops->llseek != NULL) { ret = pdata->dev->fops->llseek((long)offset, OSAL_SEEK_CUR, (void *)&(pdata->data)); } } else if (whence == SEEK_END) { if (pdata->dev->fops->llseek != NULL) { ret = pdata->dev->fops->llseek((long)offset, OSAL_SEEK_END, (void *)&(pdata->data)); } } PUT_FILE(file); return (loff_t)ret; } static int osal_release(struct inode *inode, struct file *file) { int ret = 0; struct osal_private_data *pdata = file->private_data; GET_FILE(file); if (DRVAL_DEBUG) { osal_printk("%s - file->private_data=%pK!\n", __FUNCTION__, pdata); } if (pdata->dev->fops->release != NULL) { ret = pdata->dev->fops->release((void *)&(pdata->data)); } if (ret != 0) { PUT_FILE(file); osal_printk("%s - release failed!\n", __FUNCTION__); return ret; } PUT_FILE(file); spin_lock(&f_lock); if (pdata->f_ref_cnt != 0) { osal_printk("%s - release failed!\n", __FUNCTION__); spin_unlock(&f_lock); return -1; } kfree(file->private_data); file->private_data = NULL; spin_unlock(&f_lock); return 0; } static long __osal_unlocked_ioctl(struct file *file, unsigned int cmd, unsigned long arg) { int ret = -1; struct osal_private_data *pdata = file->private_data; char *kbuf = NULL; if (DRVAL_DEBUG) { osal_printk("%s - file->private_data=%pK!\n", __FUNCTION__, pdata); } if (((_IOC_SIZE(cmd) == 0) && (_IOC_DIR(cmd) != _IOC_NONE))) { return -1; } if ((_IOC_DIR(cmd) != _IOC_NONE) && (((char *)(uintptr_t)arg) == NULL)) { osal_printk("%s - Input param err,it is null!\n", __FUNCTION__); return -1; } if (_IOC_DIR(cmd) == _IOC_NONE) { if (pdata->dev->fops->unlocked_ioctl == NULL) { return -1; } else { ret = pdata->dev->fops->unlocked_ioctl(cmd, arg, (void *)&(pdata->data)); } } else if (_IOC_DIR(cmd) == _IOC_WRITE) { kbuf = (char *)vmalloc(_IOC_SIZE(cmd)); if (kbuf == NULL) { osal_printk("%s - vmalloc failed!\n", __FUNCTION__); return -1; } if (copy_from_user(kbuf, (char *)(uintptr_t)arg, _IOC_SIZE(cmd))) { vfree(kbuf); return -1; } if (pdata->dev->fops->unlocked_ioctl == NULL) { vfree(kbuf); return -1; } else { ret = pdata->dev->fops->unlocked_ioctl (cmd, (unsigned long)(uintptr_t)kbuf, (void *)&(pdata->data)); } } else if (_IOC_DIR(cmd) == _IOC_READ) { kbuf = vmalloc(_IOC_SIZE(cmd)); if (kbuf == NULL) { osal_printk("%s - vmalloc failed!\n", __FUNCTION__); return -1; } if (pdata->dev->fops->unlocked_ioctl == NULL) { vfree(kbuf); return -1; } else { ret = pdata->dev->fops->unlocked_ioctl (cmd, (unsigned long)(uintptr_t)kbuf, (void *)&(pdata->data)); if (ret == 0) { if (copy_to_user((char *)(uintptr_t)arg, kbuf, _IOC_SIZE(cmd))) { vfree(kbuf); return -1; } } } } else if (_IOC_DIR(cmd) == (_IOC_READ + _IOC_WRITE)) { kbuf = vmalloc(_IOC_SIZE(cmd)); if (kbuf == NULL) { osal_printk("%s - vmalloc failed!\n", __FUNCTION__); return -1; } if (copy_from_user(kbuf, (char *)(uintptr_t)arg, _IOC_SIZE(cmd))) { vfree(kbuf); return -1; } if (pdata->dev->fops->unlocked_ioctl == NULL) { vfree(kbuf); return -1; } else { ret = pdata->dev->fops->unlocked_ioctl (cmd, (unsigned long)(uintptr_t)kbuf, (void *)&(pdata->data)); if (ret == 0) { if (copy_to_user((char *)(uintptr_t)arg, kbuf, _IOC_SIZE(cmd))) { vfree(kbuf); return -1; } } } } if (kbuf != NULL) { vfree(kbuf); } return ret; } static long osal_unlocked_ioctl(struct file *file, unsigned int cmd, unsigned long arg) { long ret = 0; GET_FILE(file); ret = __osal_unlocked_ioctl(file, cmd, arg); PUT_FILE(file); return ret; } #ifdef CONFIG_COMPAT static long __osal_compat_ioctl(struct file *file, unsigned int cmd, unsigned long arg) { int ret = -1; struct osal_private_data *pdata = file->private_data; char *kbuf = NULL; if (DRVAL_DEBUG) { osal_printk("%s - file->private_data=%pK!\n", __FUNCTION__, pdata); } if (((_IOC_SIZE(cmd) == 0) && (_IOC_DIR(cmd) != _IOC_NONE))) { return -1; } if ((_IOC_DIR(cmd) != _IOC_NONE) && (((char *)(uintptr_t)arg) == NULL)) { osal_printk("%s - Input param err,it is null!\n", __FUNCTION__); return -1; } if (_IOC_DIR(cmd) == _IOC_NONE) { if (pdata->dev->fops->compat_ioctl == NULL) { return -1; } else { ret = pdata->dev->fops->compat_ioctl(cmd, arg, (void *)&(pdata->data)); } } else if (_IOC_DIR(cmd) == _IOC_WRITE) { kbuf = (char *)vmalloc(_IOC_SIZE(cmd)); if (kbuf == NULL) { osal_printk("%s - vmalloc failed!\n", __FUNCTION__); return -1; } if (copy_from_user(kbuf, (char *)(uintptr_t)arg, _IOC_SIZE(cmd))) { vfree(kbuf); return -1; } if (pdata->dev->fops->compat_ioctl == NULL) { vfree(kbuf); return -1; } else { ret = pdata->dev->fops->compat_ioctl (cmd, (unsigned long)(uintptr_t)kbuf, (void *)&(pdata->data)); } } else if (_IOC_DIR(cmd) == _IOC_READ) { kbuf = vmalloc(_IOC_SIZE(cmd)); if (kbuf == NULL) { osal_printk("%s - vmalloc failed!\n", __FUNCTION__); return -1; } if (pdata->dev->fops->compat_ioctl == NULL) { vfree(kbuf); return -1; } else { ret = pdata->dev->fops->compat_ioctl (cmd, (unsigned long)(uintptr_t)kbuf, (void *)&(pdata->data)); if (ret == 0) { if (copy_to_user((char *)(uintptr_t)arg, kbuf, _IOC_SIZE(cmd))) { vfree(kbuf); return -1; } } } } else if (_IOC_DIR(cmd) == (_IOC_READ + _IOC_WRITE)) { kbuf = vmalloc(_IOC_SIZE(cmd)); if (kbuf == NULL) { osal_printk("%s - vmalloc failed!\n", __FUNCTION__); return -1; } if (copy_from_user(kbuf, (char *)(uintptr_t)arg, _IOC_SIZE(cmd))) { vfree(kbuf); return -1; } if (pdata->dev->fops->compat_ioctl == NULL) { vfree(kbuf); return -1; } else { ret = pdata->dev->fops->compat_ioctl (cmd, (unsigned long)(uintptr_t)kbuf, (void *)&(pdata->data)); if (ret == 0) { if (copy_to_user((char *)(uintptr_t)arg, kbuf, _IOC_SIZE(cmd))) { vfree(kbuf); return -1; } } } } if (kbuf != NULL) { vfree(kbuf); } return ret; } static long osal_compat_ioctl(struct file *file, unsigned int cmd, unsigned long arg) { long ret = 0; GET_FILE(file); ret = __osal_compat_ioctl(file, cmd, arg); PUT_FILE(file); return ret; } #endif static unsigned int osal_poll(struct file *file, struct poll_table_struct *table) { struct osal_private_data *pdata = file->private_data; struct osal_poll t; unsigned int ret = 0; GET_FILE(file); if (DRVAL_DEBUG) { osal_printk("%s - table=%pK, file=%pK!\n", __FUNCTION__, table, file); } t.poll_table = table; t.data = file; if (pdata->dev->fops->poll != NULL) { ret = pdata->dev->fops->poll(&t, (void *)&(pdata->data)); } PUT_FILE(file); return ret; } static int __osal_valid_mmap_phys_addr_range(unsigned long pfn, size_t size) { /* check physical addr greater than the max addr supported by the system */ if ((pfn + (size >> PAGE_SHIFT)) > (1 + ((~0UL) >> PAGE_SHIFT))) { osal_printk("--%s - %d--!\n", __FUNCTION__, __LINE__); return 0; } /* CMA need to alloc ram region, so annotate the code as follows */ #if 0 /* check physical addr is ram region */ if (pfn_valid(pfn) || pfn_valid(pfn + (size >> PAGE_SHIFT))) { osal_printk("--%s - %d--!\n", __FUNCTION__, __LINE__); return 0; } #endif /* It's necessary for the variable "size" to align 4k(page_size). */ #define PAGE_SIZE_MASK 0xfffffffffffff000ULL if ((unsigned long)size & (~PAGE_SIZE_MASK)) { osal_printk("--%s - %d--!\n", __FUNCTION__, __LINE__); return 0; } #undef PAGE_SIZE_MASK return 1; } static int osal_mmap(struct file *file, struct vm_area_struct *vm) { struct osal_vm osal_vm; struct osal_private_data *pdata = file->private_data; osal_vm.vm = vm; if (!__osal_valid_mmap_phys_addr_range(vm->vm_pgoff, vm->vm_end - vm->vm_start)) { osal_printk("\n%s - invalid argument size=%ld!!!\n", __FUNCTION__, vm->vm_end - vm->vm_start); return -EINVAL; } if (DRVAL_DEBUG) { osal_printk("%s - start=%lx, end=%lx!, off=%lx\n", __FUNCTION__, vm->vm_start, vm->vm_end, vm->vm_pgoff); } if (pdata->dev->fops->mmap != NULL) { return pdata->dev->fops->mmap(&osal_vm, vm->vm_start, vm->vm_end, vm->vm_pgoff, (void *)&(pdata->data)); } return 0; } static struct file_operations s_osal_fops = { .owner = THIS_MODULE, .open = osal_open, .read = osal_read, .write = osal_write, .llseek = osal_llseek, .unlocked_ioctl = osal_unlocked_ioctl, .release = osal_release, .poll = osal_poll, .mmap = osal_mmap, #ifdef CONFIG_COMPAT .compat_ioctl = osal_compat_ioctl, #endif }; static int osal_pm_prepare(struct media_device *media) { osal_coat_dev_t *coat_dev = container_of(media, struct osal_coat_dev, media_dev); if (coat_dev->osal_dev.osal_pmops && coat_dev->osal_dev.osal_pmops->pm_prepare) { return coat_dev->osal_dev.osal_pmops->pm_prepare(&(coat_dev->osal_dev)); } return 0; } static void osal_pm_complete(struct media_device *media) { osal_coat_dev_t *coat_dev = container_of(media, struct osal_coat_dev, media_dev); if (coat_dev->osal_dev.osal_pmops && coat_dev->osal_dev.osal_pmops->pm_complete) { coat_dev->osal_dev.osal_pmops->pm_complete(&(coat_dev->osal_dev)); } } static int osal_pm_suspend(struct media_device *media) { osal_coat_dev_t *coat_dev = container_of(media, struct osal_coat_dev, media_dev); if (coat_dev->osal_dev.osal_pmops && coat_dev->osal_dev.osal_pmops->pm_suspend) { return coat_dev->osal_dev.osal_pmops->pm_suspend(&(coat_dev->osal_dev)); } return 0; } static int osal_pm_resume(struct media_device *media) { osal_coat_dev_t *coat_dev = container_of(media, struct osal_coat_dev, media_dev); if (coat_dev->osal_dev.osal_pmops && coat_dev->osal_dev.osal_pmops->pm_resume) { return coat_dev->osal_dev.osal_pmops->pm_resume(&(coat_dev->osal_dev)); } return 0; } static int osal_pm_freeze(struct media_device *media) { osal_coat_dev_t *coat_dev = container_of(media, struct osal_coat_dev, media_dev); if (coat_dev->osal_dev.osal_pmops && coat_dev->osal_dev.osal_pmops->pm_freeze) { return coat_dev->osal_dev.osal_pmops->pm_freeze(&(coat_dev->osal_dev)); } return 0; } static int osal_pm_thaw(struct media_device *media) { osal_coat_dev_t *coat_dev = container_of(media, struct osal_coat_dev, media_dev); if (coat_dev->osal_dev.osal_pmops && coat_dev->osal_dev.osal_pmops->pm_thaw) { return coat_dev->osal_dev.osal_pmops->pm_thaw(&(coat_dev->osal_dev)); } return 0; } static int osal_pm_poweroff(struct media_device *media) { osal_coat_dev_t *coat_dev = container_of(media, struct osal_coat_dev, media_dev); if (coat_dev->osal_dev.osal_pmops && coat_dev->osal_dev.osal_pmops->pm_poweroff) { return coat_dev->osal_dev.osal_pmops->pm_poweroff(&(coat_dev->osal_dev)); } return 0; } static int osal_pm_restore(struct media_device *media) { osal_coat_dev_t *coat_dev = container_of(media, struct osal_coat_dev, media_dev); if (coat_dev->osal_dev.osal_pmops && coat_dev->osal_dev.osal_pmops->pm_restore) { return coat_dev->osal_dev.osal_pmops->pm_restore(&(coat_dev->osal_dev)); } return 0; } static int osal_pm_suspend_late(struct media_device *media) { osal_coat_dev_t *coat_dev = container_of(media, struct osal_coat_dev, media_dev); if (coat_dev->osal_dev.osal_pmops && coat_dev->osal_dev.osal_pmops->pm_suspend_late) { return coat_dev->osal_dev.osal_pmops->pm_suspend_late(&(coat_dev->osal_dev)); } return 0; } static int osal_pm_resume_early(struct media_device *media) { osal_coat_dev_t *coat_dev = container_of(media, struct osal_coat_dev, media_dev); if (coat_dev->osal_dev.osal_pmops && coat_dev->osal_dev.osal_pmops->pm_resume_early) { return coat_dev->osal_dev.osal_pmops->pm_resume_early(&(coat_dev->osal_dev)); } return 0; } static int osal_pm_freeze_late(struct media_device *media) { osal_coat_dev_t *coat_dev = container_of(media, struct osal_coat_dev, media_dev); if (coat_dev->osal_dev.osal_pmops && coat_dev->osal_dev.osal_pmops->pm_freeze_late) { return coat_dev->osal_dev.osal_pmops->pm_freeze_late(&(coat_dev->osal_dev)); } return 0; } static int osal_pm_thaw_early(struct media_device *media) { osal_coat_dev_t *coat_dev = container_of(media, struct osal_coat_dev, media_dev); if (coat_dev->osal_dev.osal_pmops && coat_dev->osal_dev.osal_pmops->pm_thaw_early) { return coat_dev->osal_dev.osal_pmops->pm_thaw_early(&(coat_dev->osal_dev)); } return 0; } static int osal_pm_poweroff_late(struct media_device *media) { osal_coat_dev_t *coat_dev = container_of(media, struct osal_coat_dev, media_dev); if (coat_dev->osal_dev.osal_pmops && coat_dev->osal_dev.osal_pmops->pm_poweroff_late) { return coat_dev->osal_dev.osal_pmops->pm_poweroff_late(&(coat_dev->osal_dev)); } return 0; } static int osal_pm_restore_early(struct media_device *media) { osal_coat_dev_t *coat_dev = container_of(media, struct osal_coat_dev, media_dev); if (coat_dev->osal_dev.osal_pmops && coat_dev->osal_dev.osal_pmops->pm_restore_early) { return coat_dev->osal_dev.osal_pmops->pm_restore_early(&(coat_dev->osal_dev)); } return 0; } static int osal_pm_suspend_noirq(struct media_device *media) { osal_coat_dev_t *coat_dev = container_of(media, struct osal_coat_dev, media_dev); if (coat_dev->osal_dev.osal_pmops && coat_dev->osal_dev.osal_pmops->pm_suspend_noirq) { return coat_dev->osal_dev.osal_pmops->pm_suspend_noirq(&(coat_dev->osal_dev)); } return 0; } static int osal_pm_resume_noirq(struct media_device *media) { osal_coat_dev_t *coat_dev = container_of(media, struct osal_coat_dev, media_dev); if (coat_dev->osal_dev.osal_pmops && coat_dev->osal_dev.osal_pmops->pm_resume_noirq) { return coat_dev->osal_dev.osal_pmops->pm_resume_noirq(&(coat_dev->osal_dev)); } return 0; } static int osal_pm_freeze_noirq(struct media_device *media) { osal_coat_dev_t *coat_dev = container_of(media, struct osal_coat_dev, media_dev); if (coat_dev->osal_dev.osal_pmops && coat_dev->osal_dev.osal_pmops->pm_freeze_noirq) { return coat_dev->osal_dev.osal_pmops->pm_freeze_noirq(&(coat_dev->osal_dev)); } return 0; } static int osal_pm_thaw_noirq(struct media_device *media) { osal_coat_dev_t *coat_dev = container_of(media, struct osal_coat_dev, media_dev); if (coat_dev->osal_dev.osal_pmops && coat_dev->osal_dev.osal_pmops->pm_thaw_noirq) { return coat_dev->osal_dev.osal_pmops->pm_thaw_noirq(&(coat_dev->osal_dev)); } return 0; } static int osal_pm_poweroff_noirq(struct media_device *media) { osal_coat_dev_t *coat_dev = container_of(media, struct osal_coat_dev, media_dev); if (coat_dev->osal_dev.osal_pmops && coat_dev->osal_dev.osal_pmops->pm_poweroff_noirq) { return coat_dev->osal_dev.osal_pmops->pm_poweroff_noirq(&(coat_dev->osal_dev)); } return 0; } static int osal_pm_restore_noirq(struct media_device *media) { osal_coat_dev_t *coat_dev = container_of(media, struct osal_coat_dev, media_dev); if (coat_dev->osal_dev.osal_pmops && coat_dev->osal_dev.osal_pmops->pm_restore_noirq) { return coat_dev->osal_dev.osal_pmops->pm_restore_noirq(&(coat_dev->osal_dev)); } return 0; } static int osal_devfreq_target(struct media_device *media, unsigned long *freq, unsigned int flags) { osal_coat_dev_t *coat_dev = container_of(media, struct osal_coat_dev, media_dev); if (coat_dev->osal_dev.osal_profile->target) { return coat_dev->osal_dev.osal_profile->target(&(coat_dev->osal_dev), freq, flags); } return 0; } static int osal_devfreq_get_dev_status(struct media_device *media, struct osal_devfreq_dev_status *stat) { osal_coat_dev_t *coat_dev = container_of(media, struct osal_coat_dev, media_dev); if (coat_dev->osal_dev.osal_profile->get_dev_status) { return coat_dev->osal_dev.osal_profile->get_dev_status(&(coat_dev->osal_dev), stat); } return 0; } static int osal_devfreq_get_cur_freq(struct media_device *media, unsigned long *freq) { osal_coat_dev_t *coat_dev = container_of(media, struct osal_coat_dev, media_dev); if (coat_dev->osal_dev.osal_profile->get_cur_freq) { return coat_dev->osal_dev.osal_profile->get_cur_freq(&(coat_dev->osal_dev), freq); } return 0; } static void osal_devfreq_exit(struct media_device *media) { osal_coat_dev_t *coat_dev = container_of(media, struct osal_coat_dev, media_dev); if (coat_dev->osal_dev.osal_profile->exit) { return coat_dev->osal_dev.osal_profile->exit(&(coat_dev->osal_dev)); } } int osal_devfreq_register(osal_dev_t *osal_dev, struct osal_devfreq_dev_profile *osal_profile, const char *governor, void *data) { struct media_device *media = NULL; osal_devfreq_para_t devfreq_para = { 0 }; if ((osal_dev == NULL) || (osal_profile == NULL)) { osal_printk("%s - parameter invalid!\n", __FUNCTION__); return -1; } media = &(((osal_coat_dev_t *)(osal_dev->dev))->media_dev); if ((governor != NULL) && (osal_strcmp(governor, "userspace") == 0)) { osal_printk("Not supported governor\r\n"); return -1; } osal_dev->osal_profile = osal_profile; devfreq_para.initial_freq = osal_dev->osal_profile->initial_freq; devfreq_para.polling_ms = osal_dev->osal_profile->polling_ms; devfreq_para.freq_table = osal_dev->osal_profile->freq_table; devfreq_para.max_state = osal_dev->osal_profile->max_state; return media_devfreq_register(media, &devfreq_para); } EXPORT_SYMBOL(osal_devfreq_register); void osal_devfreq_unregister(osal_dev_t *osal_dev) { struct media_device *media = NULL; if ((osal_dev == NULL) || (osal_dev->osal_profile == NULL)) { osal_printk("%s - parameter invalid!\n", __FUNCTION__); return; } media = &(((osal_coat_dev_t *)(osal_dev->dev))->media_dev); media_devfreq_unregister(media); } EXPORT_SYMBOL(osal_devfreq_unregister); static struct media_ops s_osal_pmops = { .pm_prepare = osal_pm_prepare, .pm_complete = osal_pm_complete, .pm_suspend = osal_pm_suspend, .pm_resume = osal_pm_resume, .pm_freeze = osal_pm_freeze, .pm_thaw = osal_pm_thaw, .pm_poweroff = osal_pm_poweroff, .pm_restore = osal_pm_restore, .pm_suspend_late = osal_pm_suspend_late, .pm_resume_early = osal_pm_resume_early, .pm_freeze_late = osal_pm_freeze_late, .pm_thaw_early = osal_pm_thaw_early, .pm_poweroff_late = osal_pm_poweroff_late, .pm_restore_early = osal_pm_restore_early, .pm_suspend_noirq = osal_pm_suspend_noirq, .pm_resume_noirq = osal_pm_resume_noirq, .pm_freeze_noirq = osal_pm_freeze_noirq, .pm_thaw_noirq = osal_pm_thaw_noirq, .pm_poweroff_noirq = osal_pm_poweroff_noirq, .pm_restore_noirq = osal_pm_restore_noirq, .devfreq_target = osal_devfreq_target, .devfreq_get_dev_status = osal_devfreq_get_dev_status, .devfreq_get_cur_freq = osal_devfreq_get_cur_freq, .devfreq_exit = osal_devfreq_exit, }; osal_dev_t *osal_createdev(const char *name) { osal_coat_dev_t *pdev = NULL; if (name == NULL) { osal_printk("%s - parameter invalid!\n", __FUNCTION__); return NULL; } pdev = (osal_coat_dev_t *)kmalloc(sizeof(osal_coat_dev_t), GFP_KERNEL); if (pdev == NULL) { osal_printk("%s - kmalloc error!\n", __FUNCTION__); return NULL; } memset(pdev, 0, sizeof(osal_coat_dev_t)); osal_strncpy(pdev->osal_dev.name, name, sizeof(pdev->osal_dev.name) - 1); pdev->osal_dev.dev = pdev; return &(pdev->osal_dev); } EXPORT_SYMBOL(osal_createdev); int osal_destroydev(osal_dev_t *osal_dev) { osal_coat_dev_t *pdev = NULL; if (osal_dev == NULL) { osal_printk("%s - parameter invalid!\n", __FUNCTION__); return -1; } pdev = osal_dev->dev; if (pdev == NULL) { osal_printk("%s - parameter invalid!\n", __FUNCTION__); return -1; } kfree(pdev); return 0; } EXPORT_SYMBOL(osal_destroydev); int osal_registerdevice(osal_dev_t *osal_dev) { struct media_device *media = NULL; if ((osal_dev == NULL) || (osal_dev->fops == NULL)) { osal_printk("%s - parameter invalid!\n", __FUNCTION__); return -1; } media = &(((osal_coat_dev_t *)(osal_dev->dev))->media_dev); if (osal_dev->minor != 0) { media->minor = osal_dev->minor; } else { media->minor = MEDIA_DYNAMIC_MINOR; } media->owner = THIS_MODULE; media->fops = &s_osal_fops; media->drvops = &s_osal_pmops; osal_strncpy(media->devfs_name, osal_dev->name, sizeof(media->devfs_name) - 1); return media_register(media); } EXPORT_SYMBOL(osal_registerdevice); void osal_deregisterdevice(osal_dev_t *pdev) { if (pdev == NULL) { osal_printk("%s - parameter invalid!\n", __FUNCTION__); return; } media_unregister((struct media_device *)&(((osal_coat_dev_t *)(pdev->dev))->media_dev)); } EXPORT_SYMBOL(osal_deregisterdevice); void osal_poll_wait(osal_poll_t *table, osal_wait_t *wait) { if (DRVAL_DEBUG) { osal_printk("%s - call poll_wait +!, table=%pK, file=%pK\n", __FUNCTION__, table->poll_table, table->data); } poll_wait ((struct file *)table->data, (wait_queue_head_t *)(wait->wait), table->poll_table); if (DRVAL_DEBUG) { osal_printk("%s - call poll_wait -!\n", __FUNCTION__); } } EXPORT_SYMBOL(osal_poll_wait); #if 0 void osal_pgprot_noncached(osal_vm_t *vm) { struct vm_area_struct *v = (struct vm_area_struct *)(vm->vm); v->vm_page_prot = pgprot_noncached(v->vm_page_prot); } #else void osal_pgprot_noncached(osal_vm_t *vm) { struct vm_area_struct *v = (struct vm_area_struct *)(vm->vm); v->vm_page_prot = pgprot_writecombine(v->vm_page_prot); } #endif EXPORT_SYMBOL(osal_pgprot_noncached); void osal_pgprot_cached(osal_vm_t *vm) { struct vm_area_struct *v = (struct vm_area_struct *)(vm->vm); #ifdef CONFIG_64BIT v->vm_page_prot = __pgprot(pgprot_val(v->vm_page_prot) | PTE_VALID | PTE_DIRTY | PTE_AF); #else v->vm_page_prot = __pgprot(pgprot_val(v->vm_page_prot) | L_PTE_PRESENT | L_PTE_YOUNG | L_PTE_DIRTY | L_PTE_MT_DEV_CACHED); #endif } EXPORT_SYMBOL(osal_pgprot_cached); void osal_pgprot_writecombine(osal_vm_t *vm) { struct vm_area_struct *v = (struct vm_area_struct *)(vm->vm); v->vm_page_prot = pgprot_writecombine(v->vm_page_prot); } EXPORT_SYMBOL(osal_pgprot_writecombine); void osal_pgprot_stronglyordered(osal_vm_t *vm) { struct vm_area_struct *v = (struct vm_area_struct *)(vm->vm); #ifdef CONFIG_64BIT v->vm_page_prot = pgprot_device(v->vm_page_prot); #else v->vm_page_prot = pgprot_stronglyordered(v->vm_page_prot); #endif } EXPORT_SYMBOL(osal_pgprot_stronglyordered); int osal_remap_pfn_range(osal_vm_t *vm, unsigned long addr, unsigned long pfn, unsigned long size) { struct vm_area_struct *v = (struct vm_area_struct *)(vm->vm); if (size == 0) { return -EPERM; } return remap_pfn_range(v, addr, pfn, size, v->vm_page_prot); } EXPORT_SYMBOL(osal_remap_pfn_range); int osal_io_remap_pfn_range(osal_vm_t *vm, unsigned long addr, unsigned long pfn, unsigned long size) { struct vm_area_struct *v = (struct vm_area_struct *)(vm->vm); v->vm_flags |= VM_IO; if (size == 0) { return -EPERM; } return io_remap_pfn_range(v, addr, pfn, size, v->vm_page_prot); } EXPORT_SYMBOL(osal_io_remap_pfn_range); #ifdef CONFIG_SNAPSHOT_BOOT int osal_call_usermodehelper_force(char *path, char **argv, char **envp, int wait) { return call_usermodehelper_force(path, argv, envp, wait); } EXPORT_SYMBOL(osal_call_usermodehelper_force); #endif