您的位置:首页 > 运维架构 > Linux

基于linux switch模块的HDMI检测状态驱动

2014-07-27 03:34 387 查看
/*
* drivers\staging\android\switch\switch_hdmiset.c
*
* Copyright (C) 2008 Google, Inc.
* Author: Johnny <liujun@eken.com>
*
* This software is licensed under the terms of the GNU General Public
* License version 2, as published by the Free Software Foundation, and
* may be copied, distributed, and modified under those terms.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
* GNU General Public License for more details.
*
*/

#include <linux/module.h>
#include <linux/kernel.h>
#include <linux/init.h>
#include <linux/platform_device.h>
#include <linux/slab.h>
#include <linux/workqueue.h>
#include <linux/gpio.h>
#include "switch.h"

#undef SWITCH_DBG
#if (1)
#define SWITCH_DBG(format,args...)  printk("[SWITCH] "format,##args)
#else
#define SWITCH_DBG(...)
#endif

static unsigned int hdmi_status;

static struct gpio_switch_data {
struct switch_dev sdev;
unsigned pio_hdle;
int state;
unsigned long delay_time;
struct delayed_work  hdmi_work;
struct workqueue_struct *mywork_queue;
unsigned char switch_flag;
};

static void hdmi_work_func(struct delayed_work  *hdmi_work)
{
int state = -1;

SWITCH_DBG("enter:%s,line:%d\n", __func__, __LINE__);
struct gpio_switch_data	*switch_data = container_of(hdmi_work, struct gpio_switch_data, hdmi_work);
//state = gpio_get_value(switch_data->pio_hdle);//获取GPIO输入状态值
hdmi_status = gpio_get_value(switch_data->pio_hdle);//获取GPIO输入状态值
//hdmi_status = 1;
//switch_set_state(&switch_data->sdev, state);

queue_delayed_work(switch_data->mywork_queue, &switch_data->hdmi_work, switch_data->delay_time);
}

static ssize_t switch_gpio_print_state(struct switch_dev *sdev, char *buf)
{
SWITCH_DBG("enter:%s,line:%d\n", __func__, __LINE__);
//struct gpio_switch_data	*switch_data =
//	container_of(sdev, struct gpio_switch_data, sdev);
return sprintf(buf, "%d\n", hdmi_status);
}

static int gpio_switch_probe(struct platform_device *pdev)
{
struct gpio_switch_platform_data *pdata = pdev->dev.platform_data;
struct gpio_switch_data *switch_data;
int ret = 0;

SWITCH_DBG("enter:%s,line:%d\n", __func__, __LINE__);
if (!pdata)
return -EBUSY;

switch_data = kzalloc(sizeof(struct gpio_switch_data), GFP_KERNEL);
if (!switch_data)
return -ENOMEM;

switch_data->delay_time = 100;
switch_data->sdev.name = pdata->name;
switch_data->pio_hdle = pdata->gpio;
switch_data->state = 0;
switch_data->switch_flag = 0;
switch_data->sdev.print_state = switch_gpio_print_state;

#if 1
switch_data->pio_hdle = GPIOB(6);
if(0 != gpio_request(switch_data->pio_hdle, NULL)) {
pr_err("ERROR: HDMI request gpio is failed\n");
//goto err_request_gpio;
}

ret = gpio_direction_input(switch_data->pio_hdle);
//if (ret < 0)
//goto err_set_gpio_input;
#endif

ret = switch_dev_register(&switch_data->sdev);
if (ret < 0)
goto err_switch_dev_register;

INIT_DELAYED_WORK(&switch_data->hdmi_work, hdmi_work_func);//初始化工作队列
switch_data->mywork_queue = create_singlethread_workqueue("hdmi_gpio");//创建线程mywork_queue
queue_delayed_work(switch_data->mywork_queue,&switch_data->hdmi_work,switch_data->delay_time);

return 0;

//err_set_gpio_input:
//	gpio_free(switch_data->pio_hdle);
//err_request_gpio:
//	switch_dev_unregister(&switch_data->sdev);
err_switch_dev_register:
kfree(switch_data);

return ret;
}

static int switch_resume(struct platform_device *pdev)
{
struct gpio_switch_data *switch_data;

//switch_data = (struct gpio_switch_data *)platform_get_drvdata(pdev);
//if (switch_data != NULL) {
//	queue_delayed_work(switch_data->mywork_queue,&switch_data->hdmi_work,switch_data->delay_time);
//}
}

static int switch_suspend(struct platform_device *pdev,pm_message_t state)
{
struct gpio_switch_data *switch_data = platform_get_drvdata(pdev);

//cancel_delayed_work_sync(&switch_data->hdmi_work);
//flush_workqueue(switch_data->mywork_queue);

return 0;
}

static int __devexit gpio_switch_remove(struct platform_device *pdev)
{
struct gpio_switch_data *switch_data = platform_get_drvdata(pdev);

//销毁工作队列
cancel_delayed_work_sync(&switch_data->hdmi_work);
destroy_workqueue(switch_data->mywork_queue);
gpio_free(switch_data->pio_hdle);
switch_dev_unregister(&switch_data->sdev);
kfree(switch_data);

return 0;
}

static struct platform_driver gpio_switch_driver = {
.probe		= gpio_switch_probe,
.remove		= __exit_p(gpio_switch_remove),
.driver		= {
.name	= "switch-hdmi",
.owner	= THIS_MODULE,
},
.suspend	= switch_suspend,
.resume		= switch_resume,
};

static struct gpio_switch_platform_data hdmiset_switch_data = {
.name = "hdmi",
};

static struct platform_device gpio_switch_device = {
.name = "switch-hdmi",
.dev = {
.platform_data = &hdmiset_switch_data,
}
};

static int __init gpio_switch_init(void)
{
int ret = 0;

ret = platform_device_register(&gpio_switch_device);
if (ret == 0) {
ret = platform_driver_register(&gpio_switch_driver);
}

return ret;
}

static void __exit gpio_switch_exit(void)
{
platform_driver_unregister(&gpio_switch_driver);
platform_device_unregister(&gpio_switch_device);

}
module_init(gpio_switch_init);
module_exit(gpio_switch_exit);

MODULE_AUTHOR("liujun-style@foxmail.com>");
MODULE_DESCRIPTION("Switch driver");
MODULE_LICENSE("GPL");
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: 
相关文章推荐