Back to home page

OSCL-LXR

 
 

    


0001 // SPDX-License-Identifier: GPL-2.0-only
0002 /*
0003  * twl4030-vibra.c - TWL4030 Vibrator driver
0004  *
0005  * Copyright (C) 2008-2010 Nokia Corporation
0006  *
0007  * Written by Henrik Saari <henrik.saari@nokia.com>
0008  * Updates by Felipe Balbi <felipe.balbi@nokia.com>
0009  * Input by Jari Vanhala <ext-jari.vanhala@nokia.com>
0010  */
0011 
0012 #include <linux/module.h>
0013 #include <linux/jiffies.h>
0014 #include <linux/platform_device.h>
0015 #include <linux/of.h>
0016 #include <linux/workqueue.h>
0017 #include <linux/mfd/twl.h>
0018 #include <linux/mfd/twl4030-audio.h>
0019 #include <linux/input.h>
0020 #include <linux/slab.h>
0021 
0022 /* MODULE ID2 */
0023 #define LEDEN       0x00
0024 
0025 /* ForceFeedback */
0026 #define EFFECT_DIR_180_DEG  0x8000 /* range is 0 - 0xFFFF */
0027 
0028 struct vibra_info {
0029     struct device       *dev;
0030     struct input_dev    *input_dev;
0031 
0032     struct work_struct  play_work;
0033 
0034     bool            enabled;
0035     int         speed;
0036     int         direction;
0037 
0038     bool            coexist;
0039 };
0040 
0041 static void vibra_disable_leds(void)
0042 {
0043     u8 reg;
0044 
0045     /* Disable LEDA & LEDB, cannot be used with vibra (PWM) */
0046     twl_i2c_read_u8(TWL4030_MODULE_LED, &reg, LEDEN);
0047     reg &= ~0x03;
0048     twl_i2c_write_u8(TWL4030_MODULE_LED, LEDEN, reg);
0049 }
0050 
0051 /* Powers H-Bridge and enables audio clk */
0052 static void vibra_enable(struct vibra_info *info)
0053 {
0054     u8 reg;
0055 
0056     twl4030_audio_enable_resource(TWL4030_AUDIO_RES_POWER);
0057 
0058     /* turn H-Bridge on */
0059     twl_i2c_read_u8(TWL4030_MODULE_AUDIO_VOICE,
0060             &reg, TWL4030_REG_VIBRA_CTL);
0061     twl_i2c_write_u8(TWL4030_MODULE_AUDIO_VOICE,
0062              (reg | TWL4030_VIBRA_EN), TWL4030_REG_VIBRA_CTL);
0063 
0064     twl4030_audio_enable_resource(TWL4030_AUDIO_RES_APLL);
0065 
0066     info->enabled = true;
0067 }
0068 
0069 static void vibra_disable(struct vibra_info *info)
0070 {
0071     u8 reg;
0072 
0073     /* Power down H-Bridge */
0074     twl_i2c_read_u8(TWL4030_MODULE_AUDIO_VOICE,
0075             &reg, TWL4030_REG_VIBRA_CTL);
0076     twl_i2c_write_u8(TWL4030_MODULE_AUDIO_VOICE,
0077              (reg & ~TWL4030_VIBRA_EN), TWL4030_REG_VIBRA_CTL);
0078 
0079     twl4030_audio_disable_resource(TWL4030_AUDIO_RES_APLL);
0080     twl4030_audio_disable_resource(TWL4030_AUDIO_RES_POWER);
0081 
0082     info->enabled = false;
0083 }
0084 
0085 static void vibra_play_work(struct work_struct *work)
0086 {
0087     struct vibra_info *info = container_of(work,
0088             struct vibra_info, play_work);
0089     int dir;
0090     int pwm;
0091     u8 reg;
0092 
0093     dir = info->direction;
0094     pwm = info->speed;
0095 
0096     twl_i2c_read_u8(TWL4030_MODULE_AUDIO_VOICE,
0097             &reg, TWL4030_REG_VIBRA_CTL);
0098     if (pwm && (!info->coexist || !(reg & TWL4030_VIBRA_SEL))) {
0099 
0100         if (!info->enabled)
0101             vibra_enable(info);
0102 
0103         /* set vibra rotation direction */
0104         twl_i2c_read_u8(TWL4030_MODULE_AUDIO_VOICE,
0105                 &reg, TWL4030_REG_VIBRA_CTL);
0106         reg = (dir) ? (reg | TWL4030_VIBRA_DIR) :
0107             (reg & ~TWL4030_VIBRA_DIR);
0108         twl_i2c_write_u8(TWL4030_MODULE_AUDIO_VOICE,
0109                  reg, TWL4030_REG_VIBRA_CTL);
0110 
0111         /* set PWM, 1 = max, 255 = min */
0112         twl_i2c_write_u8(TWL4030_MODULE_AUDIO_VOICE,
0113                  256 - pwm, TWL4030_REG_VIBRA_SET);
0114     } else {
0115         if (info->enabled)
0116             vibra_disable(info);
0117     }
0118 }
0119 
0120 /*** Input/ForceFeedback ***/
0121 
0122 static int vibra_play(struct input_dev *input, void *data,
0123               struct ff_effect *effect)
0124 {
0125     struct vibra_info *info = input_get_drvdata(input);
0126 
0127     info->speed = effect->u.rumble.strong_magnitude >> 8;
0128     if (!info->speed)
0129         info->speed = effect->u.rumble.weak_magnitude >> 9;
0130     info->direction = effect->direction < EFFECT_DIR_180_DEG ? 0 : 1;
0131     schedule_work(&info->play_work);
0132     return 0;
0133 }
0134 
0135 static void twl4030_vibra_close(struct input_dev *input)
0136 {
0137     struct vibra_info *info = input_get_drvdata(input);
0138 
0139     cancel_work_sync(&info->play_work);
0140 
0141     if (info->enabled)
0142         vibra_disable(info);
0143 }
0144 
0145 /*** Module ***/
0146 static int __maybe_unused twl4030_vibra_suspend(struct device *dev)
0147 {
0148     struct platform_device *pdev = to_platform_device(dev);
0149     struct vibra_info *info = platform_get_drvdata(pdev);
0150 
0151     if (info->enabled)
0152         vibra_disable(info);
0153 
0154     return 0;
0155 }
0156 
0157 static int __maybe_unused twl4030_vibra_resume(struct device *dev)
0158 {
0159     vibra_disable_leds();
0160     return 0;
0161 }
0162 
0163 static SIMPLE_DEV_PM_OPS(twl4030_vibra_pm_ops,
0164              twl4030_vibra_suspend, twl4030_vibra_resume);
0165 
0166 static bool twl4030_vibra_check_coexist(struct twl4030_vibra_data *pdata,
0167                   struct device_node *parent)
0168 {
0169     struct device_node *node;
0170 
0171     if (pdata && pdata->coexist)
0172         return true;
0173 
0174     node = of_get_child_by_name(parent, "codec");
0175     if (node) {
0176         of_node_put(node);
0177         return true;
0178     }
0179 
0180     return false;
0181 }
0182 
0183 static int twl4030_vibra_probe(struct platform_device *pdev)
0184 {
0185     struct twl4030_vibra_data *pdata = dev_get_platdata(&pdev->dev);
0186     struct device_node *twl4030_core_node = pdev->dev.parent->of_node;
0187     struct vibra_info *info;
0188     int ret;
0189 
0190     if (!pdata && !twl4030_core_node) {
0191         dev_dbg(&pdev->dev, "platform_data not available\n");
0192         return -EINVAL;
0193     }
0194 
0195     info = devm_kzalloc(&pdev->dev, sizeof(*info), GFP_KERNEL);
0196     if (!info)
0197         return -ENOMEM;
0198 
0199     info->dev = &pdev->dev;
0200     info->coexist = twl4030_vibra_check_coexist(pdata, twl4030_core_node);
0201     INIT_WORK(&info->play_work, vibra_play_work);
0202 
0203     info->input_dev = devm_input_allocate_device(&pdev->dev);
0204     if (info->input_dev == NULL) {
0205         dev_err(&pdev->dev, "couldn't allocate input device\n");
0206         return -ENOMEM;
0207     }
0208 
0209     input_set_drvdata(info->input_dev, info);
0210 
0211     info->input_dev->name = "twl4030:vibrator";
0212     info->input_dev->id.version = 1;
0213     info->input_dev->close = twl4030_vibra_close;
0214     __set_bit(FF_RUMBLE, info->input_dev->ffbit);
0215 
0216     ret = input_ff_create_memless(info->input_dev, NULL, vibra_play);
0217     if (ret < 0) {
0218         dev_dbg(&pdev->dev, "couldn't register vibrator to FF\n");
0219         return ret;
0220     }
0221 
0222     ret = input_register_device(info->input_dev);
0223     if (ret < 0) {
0224         dev_dbg(&pdev->dev, "couldn't register input device\n");
0225         goto err_iff;
0226     }
0227 
0228     vibra_disable_leds();
0229 
0230     platform_set_drvdata(pdev, info);
0231     return 0;
0232 
0233 err_iff:
0234     input_ff_destroy(info->input_dev);
0235     return ret;
0236 }
0237 
0238 static struct platform_driver twl4030_vibra_driver = {
0239     .probe      = twl4030_vibra_probe,
0240     .driver     = {
0241         .name   = "twl4030-vibra",
0242         .pm = &twl4030_vibra_pm_ops,
0243     },
0244 };
0245 module_platform_driver(twl4030_vibra_driver);
0246 
0247 MODULE_ALIAS("platform:twl4030-vibra");
0248 MODULE_DESCRIPTION("TWL4030 Vibra driver");
0249 MODULE_LICENSE("GPL");
0250 MODULE_AUTHOR("Nokia Corporation");