#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>
 
        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;
 }
 
        struct device_node *np = dev->of_node;
        struct gpio_rc_dev *gpio_dev;
        struct rc_dev *rcdev;
+       u32 period = 0;
        int rc;
 
        if (!np)
                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,
        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