/*
* drivers\staging\android\switch\switch_hdmiset.c
*
* Copyright (C) 2008 Google, Inc.
* Author: Johnny <[email protected]>
*
* 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("[email protected]>");
MODULE_DESCRIPTION("Switch driver");
MODULE_LICENSE("GPL");
基於linux switch模塊的HDMI檢測狀態驅動
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.