Back to home page

OSCL-LXR

 
 

    


0001 // SPDX-License-Identifier: GPL-2.0-or-later
0002 /*
0003  *  Copyright (C) 2010, Lars-Peter Clausen <lars@metafoo.de>
0004  *  PWM beeper driver
0005  */
0006 
0007 #include <linux/input.h>
0008 #include <linux/regulator/consumer.h>
0009 #include <linux/module.h>
0010 #include <linux/kernel.h>
0011 #include <linux/of.h>
0012 #include <linux/platform_device.h>
0013 #include <linux/property.h>
0014 #include <linux/pwm.h>
0015 #include <linux/slab.h>
0016 #include <linux/workqueue.h>
0017 
0018 struct pwm_beeper {
0019     struct input_dev *input;
0020     struct pwm_device *pwm;
0021     struct regulator *amplifier;
0022     struct work_struct work;
0023     unsigned long period;
0024     unsigned int bell_frequency;
0025     bool suspended;
0026     bool amplifier_on;
0027 };
0028 
0029 #define HZ_TO_NANOSECONDS(x) (1000000000UL/(x))
0030 
0031 static int pwm_beeper_on(struct pwm_beeper *beeper, unsigned long period)
0032 {
0033     struct pwm_state state;
0034     int error;
0035 
0036     pwm_get_state(beeper->pwm, &state);
0037 
0038     state.enabled = true;
0039     state.period = period;
0040     pwm_set_relative_duty_cycle(&state, 50, 100);
0041 
0042     error = pwm_apply_state(beeper->pwm, &state);
0043     if (error)
0044         return error;
0045 
0046     if (!beeper->amplifier_on) {
0047         error = regulator_enable(beeper->amplifier);
0048         if (error) {
0049             pwm_disable(beeper->pwm);
0050             return error;
0051         }
0052 
0053         beeper->amplifier_on = true;
0054     }
0055 
0056     return 0;
0057 }
0058 
0059 static void pwm_beeper_off(struct pwm_beeper *beeper)
0060 {
0061     if (beeper->amplifier_on) {
0062         regulator_disable(beeper->amplifier);
0063         beeper->amplifier_on = false;
0064     }
0065 
0066     pwm_disable(beeper->pwm);
0067 }
0068 
0069 static void pwm_beeper_work(struct work_struct *work)
0070 {
0071     struct pwm_beeper *beeper = container_of(work, struct pwm_beeper, work);
0072     unsigned long period = READ_ONCE(beeper->period);
0073 
0074     if (period)
0075         pwm_beeper_on(beeper, period);
0076     else
0077         pwm_beeper_off(beeper);
0078 }
0079 
0080 static int pwm_beeper_event(struct input_dev *input,
0081                 unsigned int type, unsigned int code, int value)
0082 {
0083     struct pwm_beeper *beeper = input_get_drvdata(input);
0084 
0085     if (type != EV_SND || value < 0)
0086         return -EINVAL;
0087 
0088     switch (code) {
0089     case SND_BELL:
0090         value = value ? beeper->bell_frequency : 0;
0091         break;
0092     case SND_TONE:
0093         break;
0094     default:
0095         return -EINVAL;
0096     }
0097 
0098     if (value == 0)
0099         beeper->period = 0;
0100     else
0101         beeper->period = HZ_TO_NANOSECONDS(value);
0102 
0103     if (!beeper->suspended)
0104         schedule_work(&beeper->work);
0105 
0106     return 0;
0107 }
0108 
0109 static void pwm_beeper_stop(struct pwm_beeper *beeper)
0110 {
0111     cancel_work_sync(&beeper->work);
0112     pwm_beeper_off(beeper);
0113 }
0114 
0115 static void pwm_beeper_close(struct input_dev *input)
0116 {
0117     struct pwm_beeper *beeper = input_get_drvdata(input);
0118 
0119     pwm_beeper_stop(beeper);
0120 }
0121 
0122 static int pwm_beeper_probe(struct platform_device *pdev)
0123 {
0124     struct device *dev = &pdev->dev;
0125     struct pwm_beeper *beeper;
0126     struct pwm_state state;
0127     u32 bell_frequency;
0128     int error;
0129 
0130     beeper = devm_kzalloc(dev, sizeof(*beeper), GFP_KERNEL);
0131     if (!beeper)
0132         return -ENOMEM;
0133 
0134     beeper->pwm = devm_pwm_get(dev, NULL);
0135     if (IS_ERR(beeper->pwm)) {
0136         error = PTR_ERR(beeper->pwm);
0137         if (error != -EPROBE_DEFER)
0138             dev_err(dev, "Failed to request PWM device: %d\n",
0139                 error);
0140         return error;
0141     }
0142 
0143     /* Sync up PWM state and ensure it is off. */
0144     pwm_init_state(beeper->pwm, &state);
0145     state.enabled = false;
0146     error = pwm_apply_state(beeper->pwm, &state);
0147     if (error) {
0148         dev_err(dev, "failed to apply initial PWM state: %d\n",
0149             error);
0150         return error;
0151     }
0152 
0153     beeper->amplifier = devm_regulator_get(dev, "amp");
0154     if (IS_ERR(beeper->amplifier)) {
0155         error = PTR_ERR(beeper->amplifier);
0156         if (error != -EPROBE_DEFER)
0157             dev_err(dev, "Failed to get 'amp' regulator: %d\n",
0158                 error);
0159         return error;
0160     }
0161 
0162     INIT_WORK(&beeper->work, pwm_beeper_work);
0163 
0164     error = device_property_read_u32(dev, "beeper-hz", &bell_frequency);
0165     if (error) {
0166         bell_frequency = 1000;
0167         dev_dbg(dev,
0168             "failed to parse 'beeper-hz' property, using default: %uHz\n",
0169             bell_frequency);
0170     }
0171 
0172     beeper->bell_frequency = bell_frequency;
0173 
0174     beeper->input = devm_input_allocate_device(dev);
0175     if (!beeper->input) {
0176         dev_err(dev, "Failed to allocate input device\n");
0177         return -ENOMEM;
0178     }
0179 
0180     beeper->input->name = "pwm-beeper";
0181     beeper->input->phys = "pwm/input0";
0182     beeper->input->id.bustype = BUS_HOST;
0183     beeper->input->id.vendor = 0x001f;
0184     beeper->input->id.product = 0x0001;
0185     beeper->input->id.version = 0x0100;
0186 
0187     input_set_capability(beeper->input, EV_SND, SND_TONE);
0188     input_set_capability(beeper->input, EV_SND, SND_BELL);
0189 
0190     beeper->input->event = pwm_beeper_event;
0191     beeper->input->close = pwm_beeper_close;
0192 
0193     input_set_drvdata(beeper->input, beeper);
0194 
0195     error = input_register_device(beeper->input);
0196     if (error) {
0197         dev_err(dev, "Failed to register input device: %d\n", error);
0198         return error;
0199     }
0200 
0201     platform_set_drvdata(pdev, beeper);
0202 
0203     return 0;
0204 }
0205 
0206 static int __maybe_unused pwm_beeper_suspend(struct device *dev)
0207 {
0208     struct pwm_beeper *beeper = dev_get_drvdata(dev);
0209 
0210     /*
0211      * Spinlock is taken here is not to protect write to
0212      * beeper->suspended, but to ensure that pwm_beeper_event
0213      * does not re-submit work once flag is set.
0214      */
0215     spin_lock_irq(&beeper->input->event_lock);
0216     beeper->suspended = true;
0217     spin_unlock_irq(&beeper->input->event_lock);
0218 
0219     pwm_beeper_stop(beeper);
0220 
0221     return 0;
0222 }
0223 
0224 static int __maybe_unused pwm_beeper_resume(struct device *dev)
0225 {
0226     struct pwm_beeper *beeper = dev_get_drvdata(dev);
0227 
0228     spin_lock_irq(&beeper->input->event_lock);
0229     beeper->suspended = false;
0230     spin_unlock_irq(&beeper->input->event_lock);
0231 
0232     /* Let worker figure out if we should resume beeping */
0233     schedule_work(&beeper->work);
0234 
0235     return 0;
0236 }
0237 
0238 static SIMPLE_DEV_PM_OPS(pwm_beeper_pm_ops,
0239              pwm_beeper_suspend, pwm_beeper_resume);
0240 
0241 #ifdef CONFIG_OF
0242 static const struct of_device_id pwm_beeper_match[] = {
0243     { .compatible = "pwm-beeper", },
0244     { },
0245 };
0246 MODULE_DEVICE_TABLE(of, pwm_beeper_match);
0247 #endif
0248 
0249 static struct platform_driver pwm_beeper_driver = {
0250     .probe  = pwm_beeper_probe,
0251     .driver = {
0252         .name   = "pwm-beeper",
0253         .pm = &pwm_beeper_pm_ops,
0254         .of_match_table = of_match_ptr(pwm_beeper_match),
0255     },
0256 };
0257 module_platform_driver(pwm_beeper_driver);
0258 
0259 MODULE_AUTHOR("Lars-Peter Clausen <lars@metafoo.de>");
0260 MODULE_DESCRIPTION("PWM beeper driver");
0261 MODULE_LICENSE("GPL");
0262 MODULE_ALIAS("platform:pwm-beeper");