GK SDK 源码库: XMIPCLinuxV100R005C00SPC030 (kernel/tools/open_source excluded)
This commit is contained in:
+362
@@ -0,0 +1,362 @@
|
||||
/*
|
||||
* Copyright (c) XMEDIA. All rights reserved.
|
||||
*/
|
||||
#include <linux/version.h>
|
||||
#include <linux/module.h>
|
||||
#include <linux/init.h>
|
||||
#include <linux/dma-mapping.h>
|
||||
#include <linux/err.h>
|
||||
#include <linux/slab.h>
|
||||
#include <linux/device.h>
|
||||
#include <linux/fs.h>
|
||||
#include <linux/errno.h>
|
||||
#include <linux/kernel.h>
|
||||
#include <linux/major.h>
|
||||
#include <linux/stat.h>
|
||||
#include <linux/init.h>
|
||||
#include <linux/kmod.h>
|
||||
|
||||
#include "base.h"
|
||||
|
||||
/*****************************************************************************/
|
||||
/**** media bus ****/
|
||||
/*****************************************************************************/
|
||||
|
||||
static void media_bus_release(struct device *dev)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
struct device media_bus = {
|
||||
// change media_bus name from "media" to "gmp", because bus "media" is used in kenrel
|
||||
.init_name = "gmp",
|
||||
.release = media_bus_release
|
||||
};
|
||||
|
||||
#if LINUX_VERSION_CODE < KERNEL_VERSION(4, 19, 0)
|
||||
/* sysfs modalias store/show */
|
||||
static ssize_t modalias_show(struct device *dev, struct device_attribute *a,
|
||||
char *buf)
|
||||
{
|
||||
struct media_device *pdev = to_media_device(dev);
|
||||
int len = snprintf(buf, PAGE_SIZE, "media:%s\n", pdev->devfs_name);
|
||||
|
||||
return (len >= PAGE_SIZE) ? (PAGE_SIZE - 1) : len;
|
||||
}
|
||||
|
||||
static struct device_attribute media_dev_attrs[] = {
|
||||
__ATTR_RO(modalias),
|
||||
__ATTR_NULL,
|
||||
};
|
||||
#endif
|
||||
|
||||
/* bus match & uevent */
|
||||
static int media_match(struct device *dev, struct device_driver *drv)
|
||||
{
|
||||
struct media_device *pdev = to_media_device(dev);
|
||||
return (strncmp(pdev->devfs_name, drv->name, sizeof(pdev->devfs_name)) == 0);
|
||||
}
|
||||
|
||||
static int media_uevent(struct device *dev, struct kobj_uevent_env *env)
|
||||
{
|
||||
struct media_device *pdev = to_media_device(dev);
|
||||
add_uevent_var(env, "MODALIAS=media:%s", pdev->devfs_name);
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
// pm methods
|
||||
static int media_pm_prepare(struct device *dev)
|
||||
{
|
||||
struct media_device *pdev = to_media_device(dev);
|
||||
struct media_driver *pdrv = to_media_driver(dev->driver);
|
||||
|
||||
if ((pdrv->ops == NULL) || (pdrv->ops->pm_prepare == NULL)) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
return pdrv->ops->pm_prepare(pdev);
|
||||
}
|
||||
|
||||
static void media_pm_complete(struct device *dev)
|
||||
{
|
||||
struct media_device *pdev = to_media_device(dev);
|
||||
struct media_driver *pdrv = to_media_driver(dev->driver);
|
||||
|
||||
if ((pdrv->ops == NULL) || (pdrv->ops->pm_complete == NULL)) {
|
||||
return;
|
||||
}
|
||||
|
||||
pdrv->ops->pm_complete(pdev);
|
||||
}
|
||||
|
||||
static int media_pm_suspend(struct device *dev)
|
||||
{
|
||||
struct media_device *pdev = to_media_device(dev);
|
||||
struct media_driver *pdrv = to_media_driver(dev->driver);
|
||||
|
||||
if ((pdrv->ops == NULL) || (pdrv->ops->pm_suspend == NULL)) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
return pdrv->ops->pm_suspend(pdev);
|
||||
}
|
||||
|
||||
static int media_pm_resume(struct device *dev)
|
||||
{
|
||||
struct media_device *pdev = to_media_device(dev);
|
||||
struct media_driver *pdrv = to_media_driver(dev->driver);
|
||||
|
||||
if ((pdrv->ops == NULL) || (pdrv->ops->pm_resume == NULL)) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
return pdrv->ops->pm_resume(pdev);
|
||||
}
|
||||
|
||||
static int media_pm_freeze(struct device *dev)
|
||||
{
|
||||
struct media_device *pdev = to_media_device(dev);
|
||||
struct media_driver *pdrv = to_media_driver(dev->driver);
|
||||
|
||||
if ((pdrv->ops == NULL) || (pdrv->ops->pm_freeze == NULL)) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
return pdrv->ops->pm_freeze(pdev);
|
||||
}
|
||||
|
||||
static int media_pm_thaw(struct device *dev)
|
||||
{
|
||||
struct media_device *pdev = to_media_device(dev);
|
||||
struct media_driver *pdrv = to_media_driver(dev->driver);
|
||||
|
||||
if ((pdrv->ops == NULL) || (pdrv->ops->pm_thaw == NULL)) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
return pdrv->ops->pm_thaw(pdev);
|
||||
}
|
||||
|
||||
static int media_pm_poweroff(struct device *dev)
|
||||
{
|
||||
struct media_device *pdev = to_media_device(dev);
|
||||
struct media_driver *pdrv = to_media_driver(dev->driver);
|
||||
|
||||
if ((pdrv->ops == NULL) || (pdrv->ops->pm_poweroff == NULL)) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
return pdrv->ops->pm_poweroff(pdev);
|
||||
}
|
||||
|
||||
static int media_pm_restore(struct device *dev)
|
||||
{
|
||||
struct media_device *pdev = to_media_device(dev);
|
||||
struct media_driver *pdrv = to_media_driver(dev->driver);
|
||||
|
||||
if ((pdrv->ops == NULL) || (pdrv->ops->pm_restore == NULL)) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
return pdrv->ops->pm_restore(pdev);
|
||||
}
|
||||
static int media_pm_suspend_noirq(struct device *dev)
|
||||
{
|
||||
struct media_device *pdev = to_media_device(dev);
|
||||
struct media_driver *pdrv = to_media_driver(dev->driver);
|
||||
|
||||
if ((pdrv->ops == NULL) || (pdrv->ops->pm_suspend_noirq == NULL)) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
return pdrv->ops->pm_suspend_noirq(pdev);
|
||||
}
|
||||
|
||||
static int media_pm_resume_noirq(struct device *dev)
|
||||
{
|
||||
struct media_device *pdev = to_media_device(dev);
|
||||
struct media_driver *pdrv = to_media_driver(dev->driver);
|
||||
|
||||
if ((pdrv->ops == NULL) || (pdrv->ops->pm_resume_noirq == NULL)) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
return pdrv->ops->pm_resume_noirq(pdev);
|
||||
}
|
||||
|
||||
static int media_pm_freeze_noirq(struct device *dev)
|
||||
{
|
||||
struct media_device *pdev = to_media_device(dev);
|
||||
struct media_driver *pdrv = to_media_driver(dev->driver);
|
||||
|
||||
if ((pdrv->ops == NULL) || (pdrv->ops->pm_freeze_noirq == NULL)) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
return pdrv->ops->pm_freeze_noirq(pdev);
|
||||
}
|
||||
|
||||
static int media_pm_thaw_noirq(struct device *dev)
|
||||
{
|
||||
struct media_device *pdev = to_media_device(dev);
|
||||
struct media_driver *pdrv = to_media_driver(dev->driver);
|
||||
|
||||
if ((pdrv->ops == NULL) || (pdrv->ops->pm_thaw_noirq == NULL)) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
return pdrv->ops->pm_thaw_noirq(pdev);
|
||||
}
|
||||
|
||||
static int media_pm_poweroff_noirq(struct device *dev)
|
||||
{
|
||||
struct media_device *pdev = to_media_device(dev);
|
||||
struct media_driver *pdrv = to_media_driver(dev->driver);
|
||||
|
||||
if ((pdrv->ops == NULL) || (pdrv->ops->pm_poweroff_noirq == NULL)) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
return pdrv->ops->pm_poweroff_noirq(pdev);
|
||||
}
|
||||
|
||||
static int media_pm_restore_noirq(struct device *dev)
|
||||
{
|
||||
struct media_device *pdev = to_media_device(dev);
|
||||
struct media_driver *pdrv = to_media_driver(dev->driver);
|
||||
|
||||
if ((pdrv->ops == NULL) || (pdrv->ops->pm_restore_noirq == NULL)) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
return pdrv->ops->pm_restore_noirq(pdev);
|
||||
}
|
||||
|
||||
static struct dev_pm_ops media_bus_pm_ops = {
|
||||
.prepare = media_pm_prepare,
|
||||
.complete = media_pm_complete,
|
||||
|
||||
// with irq
|
||||
.suspend = media_pm_suspend,
|
||||
.resume = media_pm_resume,
|
||||
|
||||
.freeze = media_pm_freeze,
|
||||
.thaw = media_pm_thaw,
|
||||
.poweroff = media_pm_poweroff,
|
||||
.restore = media_pm_restore,
|
||||
|
||||
// with noirq
|
||||
.suspend_noirq = media_pm_suspend_noirq,
|
||||
.resume_noirq = media_pm_resume_noirq,
|
||||
.freeze_noirq = media_pm_freeze_noirq,
|
||||
.thaw_noirq = media_pm_thaw_noirq,
|
||||
.poweroff_noirq = media_pm_poweroff_noirq,
|
||||
.restore_noirq = media_pm_restore_noirq,
|
||||
};
|
||||
|
||||
struct bus_type media_bus_type = {
|
||||
// change media_bus name from "media" to "gmp", because bus "media" is used in kenrel
|
||||
.name = "gmp",
|
||||
#if LINUX_VERSION_CODE < KERNEL_VERSION(4, 19, 0)
|
||||
.dev_attrs = media_dev_attrs,
|
||||
#endif
|
||||
.match = media_match,
|
||||
.uevent = media_uevent,
|
||||
.pm = &media_bus_pm_ops,
|
||||
};
|
||||
|
||||
int media_bus_init(void)
|
||||
{
|
||||
int ret;
|
||||
ret = device_register(&media_bus);
|
||||
if (ret) {
|
||||
return ret;
|
||||
}
|
||||
|
||||
ret = bus_register(&media_bus_type);
|
||||
if (ret) {
|
||||
goto error;
|
||||
}
|
||||
|
||||
return 0;
|
||||
error:
|
||||
|
||||
device_unregister(&media_bus);
|
||||
return ret;
|
||||
}
|
||||
|
||||
void media_bus_exit(void)
|
||||
{
|
||||
bus_unregister(&media_bus_type);
|
||||
device_unregister(&media_bus);
|
||||
}
|
||||
|
||||
static void media_device_release(struct device *dev)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
int _media_device_register(struct media_device *pdev)
|
||||
{
|
||||
dev_set_name(&pdev->device, "%s", pdev->devfs_name);
|
||||
|
||||
pdev->device.devt = MKDEV(MEDIA_DEVICE_MAJOR, pdev->minor);
|
||||
pdev->device.release = media_device_release;
|
||||
pdev->device.bus = &media_bus_type;
|
||||
|
||||
return device_register(&pdev->device);
|
||||
}
|
||||
|
||||
void _media_device_unregister(struct media_device *pdev)
|
||||
{
|
||||
device_unregister(&pdev->device);
|
||||
}
|
||||
|
||||
struct media_driver *media_driver_register(const char *name,
|
||||
struct module *owner, struct media_ops *ops)
|
||||
{
|
||||
int ret;
|
||||
struct media_driver *pdrv = NULL;
|
||||
#ifdef MODULE
|
||||
if ((name == NULL) || (owner == NULL)) {
|
||||
#else
|
||||
if (name == NULL){
|
||||
#endif
|
||||
return ERR_PTR(-EINVAL);
|
||||
}
|
||||
|
||||
pdrv = kzalloc(sizeof(struct media_driver) + strnlen(name, MEDIA_MAX_DEV_NAME_LEN), GFP_KERNEL);
|
||||
if (pdrv == NULL) {
|
||||
return ERR_PTR(-ENOMEM);
|
||||
}
|
||||
|
||||
/* init driver object */
|
||||
strncpy(pdrv->name, name, strnlen(name, MEDIA_MAX_DEV_NAME_LEN));
|
||||
|
||||
pdrv->ops = ops;
|
||||
|
||||
pdrv->driver.name = pdrv->name;
|
||||
pdrv->driver.owner = owner;
|
||||
pdrv->driver.bus = &media_bus_type;
|
||||
|
||||
ret = driver_register(&pdrv->driver);
|
||||
if (ret) {
|
||||
kfree(pdrv);
|
||||
return ERR_PTR(ret);
|
||||
}
|
||||
|
||||
return pdrv;
|
||||
}
|
||||
|
||||
void media_driver_unregister(struct media_driver *pdrv)
|
||||
{
|
||||
if (pdrv != NULL) {
|
||||
driver_unregister(&pdrv->driver);
|
||||
kfree(pdrv);
|
||||
}
|
||||
}
|
||||
|
||||
// end!
|
||||
/*****************************************************************************/
|
||||
|
||||
Reference in New Issue
Block a user