Linux Audio

Check our new training course

Loading...
Note: File does not exist in v3.1.
  1// SPDX-License-Identifier: GPL-2.0-only
  2/*
  3 * Copyright (C) 2022 Richtek Technology Corp.
  4 * Author: ChiYuan Huang <cy_huang@richtek.com>
  5 */
  6
  7#include <linux/bits.h>
  8#include <linux/input.h>
  9#include <linux/interrupt.h>
 10#include <linux/kernel.h>
 11#include <linux/module.h>
 12#include <linux/mod_devicetable.h>
 13#include <linux/platform_device.h>
 14#include <linux/regmap.h>
 15
 16#define RT5120_REG_INTSTAT	0x1E
 17#define RT5120_PWRKEYSTAT_MASK	BIT(7)
 18
 19struct rt5120_priv {
 20	struct regmap *regmap;
 21	struct input_dev *input;
 22};
 23
 24static irqreturn_t rt5120_pwrkey_handler(int irq, void *devid)
 25{
 26	struct rt5120_priv *priv = devid;
 27	unsigned int stat;
 28	int error;
 29
 30	error = regmap_read(priv->regmap, RT5120_REG_INTSTAT, &stat);
 31	if (error)
 32		return IRQ_NONE;
 33
 34	input_report_key(priv->input, KEY_POWER,
 35			 !(stat & RT5120_PWRKEYSTAT_MASK));
 36	input_sync(priv->input);
 37
 38	return IRQ_HANDLED;
 39}
 40
 41static int rt5120_pwrkey_probe(struct platform_device *pdev)
 42{
 43	struct rt5120_priv *priv;
 44	struct device *dev = &pdev->dev;
 45	int press_irq, release_irq;
 46	int error;
 47
 48	priv = devm_kzalloc(dev, sizeof(*priv), GFP_KERNEL);
 49	if (!priv)
 50		return -ENOMEM;
 51
 52	priv->regmap = dev_get_regmap(dev->parent, NULL);
 53	if (!priv->regmap) {
 54		dev_err(dev, "Failed to init regmap\n");
 55		return -ENODEV;
 56	}
 57
 58	press_irq = platform_get_irq_byname(pdev, "pwrkey-press");
 59	if (press_irq < 0)
 60		return press_irq;
 61
 62	release_irq = platform_get_irq_byname(pdev, "pwrkey-release");
 63	if (release_irq < 0)
 64		return release_irq;
 65
 66	/* Make input device be device resource managed */
 67	priv->input = devm_input_allocate_device(dev);
 68	if (!priv->input)
 69		return -ENOMEM;
 70
 71	priv->input->name = "rt5120_pwrkey";
 72	priv->input->phys = "rt5120_pwrkey/input0";
 73	priv->input->id.bustype = BUS_I2C;
 74	input_set_capability(priv->input, EV_KEY, KEY_POWER);
 75
 76	error = input_register_device(priv->input);
 77	if (error) {
 78		dev_err(dev, "Failed to register input device: %d\n", error);
 79		return error;
 80	}
 81
 82	error = devm_request_threaded_irq(dev, press_irq,
 83					  NULL, rt5120_pwrkey_handler,
 84					  0, "pwrkey-press", priv);
 85	if (error) {
 86		dev_err(dev,
 87			"Failed to register pwrkey press irq: %d\n", error);
 88		return error;
 89	}
 90
 91	error = devm_request_threaded_irq(dev, release_irq,
 92					  NULL, rt5120_pwrkey_handler,
 93					  0, "pwrkey-release", priv);
 94	if (error) {
 95		dev_err(dev,
 96			"Failed to register pwrkey release irq: %d\n", error);
 97		return error;
 98	}
 99
100	return 0;
101}
102
103static const struct of_device_id r5120_pwrkey_match_table[] = {
104	{ .compatible = "richtek,rt5120-pwrkey" },
105	{}
106};
107MODULE_DEVICE_TABLE(of, r5120_pwrkey_match_table);
108
109static struct platform_driver rt5120_pwrkey_driver = {
110	.driver = {
111		.name = "rt5120-pwrkey",
112		.of_match_table = r5120_pwrkey_match_table,
113	},
114	.probe = rt5120_pwrkey_probe,
115};
116module_platform_driver(rt5120_pwrkey_driver);
117
118MODULE_AUTHOR("ChiYuan Huang <cy_huang@richtek.com>");
119MODULE_DESCRIPTION("Richtek RT5120 power key driver");
120MODULE_LICENSE("GPL");