http://blog.csdn.net/wangjianzhongfj/article/details/42764437
http://www.docin.com/p-970537368.html
rk3128原生安卓代码里。按红外遥控器的时候,灯是不闪的。在这里,我把如何进行灯闪的问题解决一下。哈!
在\kernel\src\arch\arm\boot\dts\rk3128-box-rk88.dts增加gpio控制led的节点
rockchip_leds_gpio {
compatible = "rockchip-leds-gpio";
led-gpios = <&gpio0 GPIO_D2 GPIO_ACTIVE_LOW>, <&gpio0 GPIO_B0 GPIO_ACTIVE_LOW>;
status = "okay";
};
gpio_poweroff {
compatible = "gpio-poweroff";
gpios = <&gpio1 GPIO_A2 GPIO_ACTIVE_LOW>;
};
在\kernel\src\arch\arm\configs\rockchip_defconfig里,配置leds。
CONFIG_LEDS_TRIGGERS=y
CONFIG_LEDS_TRIGGER_BACKLIGHT=y
CONFIG_LEDS_TRIGGER_DEFAULT_ON=y
然后增加代码目录路径
\kernel\src\drivers\leds\rockchip-leds-gpio.c
- /*
- * 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");
# LED Triggers
obj-$(CONFIG_LEDS_TRIGGERS) += trigger/
obj-$(CONFIG_LEDS_TRIGGERS) += trigger/
在\kernel\src\drivers\leds\Kconfig里增加
- config LEDS_GPIO_REGISTER
- bool
- help
- This option provides the function gpio_led_register_device.
- As this function is used by arch code it must not be compiled as a
- module.
- menuconfig NEW_LEDS
- bool "LED Support"
- help
- Say Y to enable Linux LED support. This allows control of supported
- LEDs from both userspace and optionally, by kernel events (triggers).
- This is not related to standard keyboard LEDs which are controlled
- via the input system.
- if NEW_LEDS
- config LEDS_CLASS
- tristate "LED Class Support"
- help
- This option enables the led sysfs class in /sys/class/leds. You'll
- need this to do anything useful with LEDs. If unsure, say N.
- comment "LED drivers"
这样linux层配置好。我们需要通过安卓层来调用。
在/policy/src/com/android/internal/policy/impl/PhoneWindowManager.java,直接去控制底层的gpio的leds。
- static final int FREQUENCY = 10;
- private int mKeyDownCount = 0;
- private long mKeyDownTime = 0;
- +
- + private void updateLEDState(String cmd) {
- + File f = new File("/sys/devices/rockchip_leds_gpio.17/led_ctl");
- + OutputStream output = null;
- + OutputStreamWriter outputWrite = null;
- + PrintWriter print = null;
- + StringBuffer strbuf = new StringBuffer("");
- + strbuf.append(cmd);
- + try {
- + output = new FileOutputStream(f);
- + outputWrite = new OutputStreamWriter(output);
- + print = new PrintWriter(outputWrite);
- + print.print(strbuf.toString());
- + print.flush();
- + output.close();
- + }catch (FileNotFoundException e){
- + e.printStackTrace();
- + }catch (IOException e){
- + e.printStackTrace();
- + }
- + }
- +
- //$_rbox_$_modify_$_end
- @Override
- public long interceptKeyBeforeDispatching(WindowState win, KeyEvent event, int policyFlags) {
- @@ -4267,6 +4289,16 @@ public class PhoneWindowManager implements WindowManagerPolicy {
- final boolean down = event.getAction() == KeyEvent.ACTION_DOWN;
- final boolean canceled = event.isCanceled();
- final int keyCode = event.getKeyCode();
- +
- + if (down)
- + {
- + updateLEDState ("IR_LED_ON");
- + }
- + else
- + {
- + updateLEDState ("IR_LED_OFF");
- + }
- +
- //<!-- $_rbox_$_modify_$_huangjc -->
- if("true".equals(SystemProperties.get("persist.sys.realsleep"))){
- if((SystemProperties.getInt("persist.sys.poweroff", 0) == 1)&&!(keyCode == KeyEvent.KEYCODE_POWER)){