From cde9070d9970eef1f7ec2360586c802a16230ad8 Mon Sep 17 00:00:00 2001 From: hc <hc@nodka.com> Date: Fri, 10 May 2024 07:43:50 +0000 Subject: [PATCH] rtl88x2CE_WiFi_linux driver --- kernel/drivers/media/rc/gpio-ir-recv.c | 83 +++++++++++++++++++++++++++++++++++++---- 1 files changed, 74 insertions(+), 9 deletions(-) diff --git a/kernel/drivers/media/rc/gpio-ir-recv.c b/kernel/drivers/media/rc/gpio-ir-recv.c index 3d99b51..16795e0 100644 --- a/kernel/drivers/media/rc/gpio-ir-recv.c +++ b/kernel/drivers/media/rc/gpio-ir-recv.c @@ -1,13 +1,5 @@ +// SPDX-License-Identifier: GPL-2.0-only /* Copyright (c) 2012, Code Aurora Forum. All rights reserved. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 and - * only version 2 as published by the Free Software Foundation. - * - * 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/kernel.h> @@ -19,6 +11,8 @@ #include <linux/of.h> #include <linux/of_gpio.h> #include <linux/platform_device.h> +#include <linux/pm_runtime.h> +#include <linux/pm_qos.h> #include <linux/irq.h> #include <media/rc-core.h> @@ -28,16 +22,37 @@ struct rc_dev *rcdev; struct gpio_desc *gpiod; int irq; + struct device *pmdev; + struct pm_qos_request qos; }; static irqreturn_t gpio_ir_recv_irq(int irq, void *dev_id) { int val; struct gpio_rc_dev *gpio_dev = dev_id; + struct device *pmdev = gpio_dev->pmdev; + + /* + * For some cpuidle systems, not all: + * Respond to interrupt taking more latency when cpu in idle. + * Invoke asynchronous pm runtime get from interrupt context, + * this may introduce a millisecond delay to call resume callback, + * where to disable cpuilde. + * + * Two issues lead to fail to decode first frame, one is latency to + * respond to interrupt, another is delay introduced by async api. + */ + if (pmdev) + pm_runtime_get(pmdev); val = gpiod_get_value(gpio_dev->gpiod); if (val >= 0) ir_raw_event_store_edge(gpio_dev->rcdev, val == 1); + + if (pmdev) { + pm_runtime_mark_last_busy(pmdev); + pm_runtime_put_autosuspend(pmdev); + } return IRQ_HANDLED; } @@ -48,6 +63,7 @@ struct device_node *np = dev->of_node; struct gpio_rc_dev *gpio_dev; struct rc_dev *rcdev; + u32 period = 0; int rc; if (!np) @@ -91,6 +107,8 @@ rcdev->map_name = RC_MAP_EMPTY; gpio_dev->rcdev = rcdev; + if (of_property_read_bool(np, "wakeup-source")) + device_init_wakeup(dev, true); rc = devm_rc_register_device(dev, rcdev); if (rc < 0) { @@ -98,11 +116,37 @@ return rc; } + of_property_read_u32(np, "linux,autosuspend-period", &period); + if (period) { + gpio_dev->pmdev = dev; + pm_runtime_set_autosuspend_delay(dev, period); + pm_runtime_use_autosuspend(dev); + pm_runtime_set_suspended(dev); + pm_runtime_enable(dev); + } + platform_set_drvdata(pdev, gpio_dev); return devm_request_irq(dev, gpio_dev->irq, gpio_ir_recv_irq, IRQF_TRIGGER_FALLING | IRQF_TRIGGER_RISING, "gpio-ir-recv-irq", gpio_dev); +} + +static int gpio_ir_recv_remove(struct platform_device *pdev) +{ + struct gpio_rc_dev *gpio_dev = platform_get_drvdata(pdev); + struct device *pmdev = gpio_dev->pmdev; + + if (pmdev) { + pm_runtime_get_sync(pmdev); + cpu_latency_qos_remove_request(&gpio_dev->qos); + + pm_runtime_disable(pmdev); + pm_runtime_put_noidle(pmdev); + pm_runtime_set_suspended(pmdev); + } + + return 0; } #ifdef CONFIG_PM @@ -130,9 +174,29 @@ return 0; } +static int gpio_ir_recv_runtime_suspend(struct device *dev) +{ + struct gpio_rc_dev *gpio_dev = dev_get_drvdata(dev); + + cpu_latency_qos_remove_request(&gpio_dev->qos); + + return 0; +} + +static int gpio_ir_recv_runtime_resume(struct device *dev) +{ + struct gpio_rc_dev *gpio_dev = dev_get_drvdata(dev); + + cpu_latency_qos_add_request(&gpio_dev->qos, 0); + + return 0; +} + static const struct dev_pm_ops gpio_ir_recv_pm_ops = { .suspend = gpio_ir_recv_suspend, .resume = gpio_ir_recv_resume, + .runtime_suspend = gpio_ir_recv_runtime_suspend, + .runtime_resume = gpio_ir_recv_runtime_resume, }; #endif @@ -144,6 +208,7 @@ static struct platform_driver gpio_ir_recv_driver = { .probe = gpio_ir_recv_probe, + .remove = gpio_ir_recv_remove, .driver = { .name = KBUILD_MODNAME, .of_match_table = of_match_ptr(gpio_ir_recv_of_match), -- Gitblit v1.6.2