rockchip-leds-gpio.c 注释

3 篇文章 0 订阅
3 篇文章 0 订阅
/*
 * LEDs driver for GPIOs
 *
 * Copyright (C) 2007 8D Technologies inc.
 * Raphael Assenat <raph@8d.com>
 * Copyright (C) 2008 Freescale Semiconductor, Inc.
 *
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License version 2 as
 * published by the Free Software Foundation.
 *
 */
#include <linux/kernel.h>
#include <linux/init.h>
#include <linux/platform_device.h>
#include <linux/gpio.h>
#include <linux/leds.h>
#include <linux/of_platform.h>
#include <linux/of_gpio.h>
#include <linux/rk_fb.h>
#include <linux/slab.h>
#include <linux/workqueue.h>
#include <linux/module.h>
#include <linux/pinctrl/consumer.h>
#include <linux/err.h>

#define TAG "ROCKCHIP_LEDS_GPIO"
#if 0
#define D(fmt, arg...) printk("D>>> %s->%s(%d): " fmt, TAG, __FUNCTION__, __LINE__, ##arg)
#else
#define D(fmt, arg...)
#endif
#define E(fmt, arg...) printk("E>>> %s->%s(%d): " fmt, TAG, __FUNCTION__, __LINE__, ##arg)
#define I(fmt, arg...) printk("I>>> %s->%s(%d): " fmt, TAG, __FUNCTION__, __LINE__, ##arg)

#define GPIO_LOW		0
#define GPIO_HIGH		1

#define LED_ON          0
#define LED_OFF         1

struct rk_gpio_leds_ctl_io {
	unsigned int power_green;
	unsigned int power_red;
	
	unsigned int ir_red;
};

struct rk_gpio_leds_priv {
	struct rk_gpio_leds_ctl_io leds;
	struct timer_list led_timer;
	unsigned int ir_red_status;
	unsigned int ir_red_first_resume;
	unsigned int suspend_state; 
};

struct rk_gpio_leds_priv *g_privdata = NULL;

static ssize_t led_store(struct device *dev, struct device_attribute *attr, const char *cmd, size_t count)
{
	struct platform_device *pdev = to_platform_device(dev);
	struct rk_gpio_leds_priv *priv = platform_get_drvdata(pdev);
	
    // I("led_store(): cmd = %s \n", cmd);
    
    if (true == priv->suspend_state)
    {
        return count;
    }

    if(0 == strcmp("IR_LED_ON", cmd))
    {
        gpio_set_value(priv->leds.ir_red, GPIO_HIGH);
    }
    else if(0 == strcmp("IR_LED_OFF", cmd))
    {
        gpio_set_value(priv->leds.ir_red, GPIO_LOW);
    }
    
    return count;
}
static ssize_t led_show(struct device *dev, struct device_attribute *attr, char *buf)
{   
    return 0; 
}
static DEVICE_ATTR(led_ctl, 0777, led_show, led_store);


static void rk_gpio_led_early_suspend(void)
{
	struct rk_gpio_leds_priv *priv = g_privdata;
	
	if (priv)
	{
    	//POWER_LED_RED
        gpio_set_value(priv->leds.power_green, GPIO_LOW);
        gpio_set_value(priv->leds.power_red, GPIO_HIGH);
	}
	
	return;
}

static void rk_gpio_led_early_resume(void)
{
	struct rk_gpio_leds_priv *priv = g_privdata;
	
	if (priv)
	{
    	//POWER_LED_GREEN	
        gpio_set_value(priv->leds.power_green, GPIO_HIGH);
        gpio_set_value(priv->leds.power_red, GPIO_LOW);
        
        // IR_LED
        if (false == priv->ir_red_first_resume) // 开机时,系统会调用 rk_gpio_led_early_resume ,此时红外灯不应该闪烁。
        {
            mod_timer(&priv->led_timer, jiffies + msecs_to_jiffies(50));
        }
        else
        {
            priv->ir_red_first_resume = false;
        }
    }
        
	return;
}

static int rk_gpio_led_event_notify(struct notifier_block *self,
				      unsigned long action, void *data)
{
	struct fb_event *event = data;
	int blank_mode = *((int *)event->data);

	if (action == FB_EARLY_EVENT_BLANK) {
		switch (blank_mode) {
		case FB_BLANK_UNBLANK:
			break;
		default:
			rk_gpio_led_early_suspend();
			break;
		}
	} else if (action == FB_EVENT_BLANK) {
		switch (blank_mode) {
		case FB_BLANK_UNBLANK:
		    rk_gpio_led_early_resume();
			break;
		default:
			break;
		}
	}

	return NOTIFY_OK;
}

static struct notifier_block rk_gpio_led_notifier = {
	.notifier_call = rk_gpio_led_event_notify,
};

static void rk_gpio_led_timer(unsigned long _data)
{
    struct rk_gpio_leds_priv *priv;
	
	priv =  (struct rk_gpio_leds_priv *)_data;
	
	if (LED_OFF == priv->ir_red_status)   // turn on
	{
	    priv->ir_red_status = LED_ON;
	    gpio_set_value(priv->leds.ir_red, GPIO_HIGH);
	    
	    mod_timer(&priv->led_timer, jiffies + msecs_to_jiffies(300));
	}
	else    // turn off
	{
	    priv->ir_red_status = LED_OFF;
	    gpio_set_value(priv->leds.ir_red, GPIO_LOW);
	}
}

static int rk_gpio_led_probe(struct platform_device *pdev)
{
	struct rk_gpio_leds_priv *priv;
	struct device_node *np = pdev->dev.of_node;
	int ret;
	
	I ("rk_gpio_led v1.0 init");

	priv = devm_kzalloc(&pdev->dev, sizeof(struct rk_gpio_leds_priv),
			     GFP_KERNEL);
	if (!priv) {
		dev_err(&pdev->dev, "failed to allocate memory\n");
		return -ENOMEM;
	}
	
	g_privdata = priv;
	
	priv->leds.power_green = of_get_named_gpio(np,"led-gpios", 0);
	priv->leds.power_red   = of_get_named_gpio(np,"led-gpios", 1);
//	priv->leds.ir_red      = of_get_named_gpio(np,"led-gpios", 2);
	
    if(priv->leds.power_green)
    {
        ret = gpio_request(priv->leds.power_green, "power_green");
        if (!ret)
        {
            gpio_direction_output(priv->leds.power_green, GPIO_HIGH);
        }
        else
        {
            I("power_green request gpio fail!");
        }
    }

    if(priv->leds.power_red)
    {
        ret = gpio_request(priv->leds.power_red, "power_red");
        if (!ret)
        {
            gpio_direction_output(priv->leds.power_red, GPIO_LOW);
        }
        else
        {
            I("power_red request gpio fail!");
        }
    }
    
    if(priv->leds.ir_red)
    {
        ret = gpio_request(priv->leds.ir_red, "ir_red");
        if (!ret)
        {
            gpio_direction_output(priv->leds.ir_red, GPIO_LOW);
        }
        else
        {
            I("ir_red request gpio fail!");
        }
    }
    priv->ir_red_status = LED_OFF;
    priv->ir_red_first_resume = true;
    priv->suspend_state = false;
    setup_timer(&priv->led_timer, rk_gpio_led_timer, (unsigned long)priv);
    
	ret = device_create_file(&pdev->dev, &dev_attr_led_ctl);
	if (ret) {
		return ret;
	}
	
    fb_register_client(&rk_gpio_led_notifier);
	
	platform_set_drvdata(pdev, priv);

	return 0;
}

static int rk_gpio_led_remove(struct platform_device *pdev)
{
	D("Enter function! \n");

	platform_set_drvdata(pdev, NULL);

	return 0;
}

#ifdef CONFIG_PM
static int rk_gpio_led_suspend(struct device *dev)
{
	struct platform_device *pdev = to_platform_device(dev);
	struct rk_gpio_leds_priv *priv = platform_get_drvdata(pdev);
	
	priv->suspend_state = true;
	
	return 0;
}


static int rk_gpio_led_resume(struct device *dev)
{
	struct platform_device *pdev = to_platform_device(dev);
	struct rk_gpio_leds_priv *priv = platform_get_drvdata(pdev);
	
    priv->suspend_state = false;
	
	return 0;
}

static const struct dev_pm_ops rk_gpio_led_pm_ops = {
	.suspend_late = rk_gpio_led_suspend,
	.resume_early = rk_gpio_led_resume,
};
#endif

static const struct of_device_id of_gpio_leds_match[] = {
	{ .compatible = "rockchip-leds-gpio", },
	{},
};
MODULE_DEVICE_TABLE(of, of_gpio_leds_match);

static struct platform_driver gpio_led_driver = {
	.probe		= rk_gpio_led_probe,
	.remove		= rk_gpio_led_remove,
	.driver		= {
		.name	= "rockchip-leds-gpio",
		.owner	= THIS_MODULE,
		.of_match_table = of_match_ptr(of_gpio_leds_match),
#ifdef CONFIG_PM
		.pm = &rk_gpio_led_pm_ops,
#endif
	},
};

module_platform_driver(gpio_led_driver);

MODULE_AUTHOR("Fengminxi <fmx@rock-chips.com>");
MODULE_DESCRIPTION("Rockchip GPIO LED driver");
MODULE_LICENSE("GPL");
MODULE_ALIAS("platform:rockchip-leds-gpio");
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值