Bryan Huntsman | 3f2bc4d | 2011-08-16 17:27:22 -0700 | [diff] [blame] | 1 | /* Copyright (c) 2010, Code Aurora Forum. All rights reserved. |
| 2 | * |
| 3 | * This program is free software; you can redistribute it and/or modify |
| 4 | * it under the terms of the GNU General Public License version 2 and |
| 5 | * only version 2 as published by the Free Software Foundation. |
| 6 | * |
| 7 | * This program is distributed in the hope that it will be useful, |
| 8 | * but WITHOUT ANY WARRANTY; without even the implied warranty of |
| 9 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
| 10 | * GNU General Public License for more details. |
| 11 | */ |
| 12 | |
| 13 | #include <linux/module.h> |
| 14 | #include <linux/init.h> |
| 15 | #include <linux/kernel.h> |
| 16 | #include <linux/errno.h> |
| 17 | #include <linux/interrupt.h> |
| 18 | #include <linux/platform_device.h> |
| 19 | #include <linux/pmic8058-vibrator.h> |
| 20 | #include <linux/mfd/pmic8058.h> |
| 21 | #include <linux/pm.h> |
| 22 | #include <linux/input.h> |
| 23 | #include <linux/slab.h> |
| 24 | |
| 25 | #define VIB_DRV 0x4A |
| 26 | |
| 27 | #define VIB_DRV_SEL_MASK 0xf8 |
| 28 | #define VIB_DRV_SEL_SHIFT 0x03 |
| 29 | #define VIB_DRV_EN_MANUAL_MASK 0xfc |
| 30 | |
| 31 | #define VIB_MAX_LEVEL_mV (3100) |
| 32 | #define VIB_MIN_LEVEL_mV (1200) |
| 33 | #define VIB_MAX_LEVELS (VIB_MAX_LEVEL_mV - VIB_MIN_LEVEL_mV) |
| 34 | |
| 35 | #define MAX_FF_SPEED 0xff |
| 36 | |
| 37 | struct pmic8058_vib { |
| 38 | struct input_dev *info; |
| 39 | spinlock_t lock; |
| 40 | struct work_struct work; |
| 41 | |
| 42 | bool enabled; |
| 43 | int speed; |
| 44 | struct device *dev; |
| 45 | struct pmic8058_vibrator_pdata *pdata; |
| 46 | int state; |
| 47 | int level; |
| 48 | u8 reg_vib_drv; |
| 49 | |
| 50 | struct pm8058_chip *pm_chip; |
| 51 | }; |
| 52 | |
| 53 | /* REVISIT: just for debugging, will be removed in final working version */ |
| 54 | static void __dump_vib_regs(struct pmic8058_vib *vib, char *msg) |
| 55 | { |
| 56 | u8 temp; |
| 57 | |
| 58 | dev_dbg(vib->dev, "%s\n", msg); |
| 59 | |
| 60 | pm8058_read(vib->pm_chip, VIB_DRV, &temp, 1); |
| 61 | dev_dbg(vib->dev, "VIB_DRV - %X\n", temp); |
| 62 | } |
| 63 | |
| 64 | static int pmic8058_vib_read_u8(struct pmic8058_vib *vib, |
| 65 | u8 *data, u16 reg) |
| 66 | { |
| 67 | int rc; |
| 68 | |
| 69 | rc = pm8058_read(vib->pm_chip, reg, data, 1); |
| 70 | if (rc < 0) |
| 71 | dev_warn(vib->dev, "Error reading pmic8058: %X - ret %X\n", |
| 72 | reg, rc); |
| 73 | |
| 74 | return rc; |
| 75 | } |
| 76 | |
| 77 | static int pmic8058_vib_write_u8(struct pmic8058_vib *vib, |
| 78 | u8 data, u16 reg) |
| 79 | { |
| 80 | int rc; |
| 81 | |
| 82 | rc = pm8058_write(vib->pm_chip, reg, &data, 1); |
| 83 | if (rc < 0) |
| 84 | dev_warn(vib->dev, "Error writing pmic8058: %X - ret %X\n", |
| 85 | reg, rc); |
| 86 | return rc; |
| 87 | } |
| 88 | |
| 89 | static int pmic8058_vib_set(struct pmic8058_vib *vib, int on) |
| 90 | { |
| 91 | int rc; |
| 92 | u8 val; |
| 93 | |
| 94 | if (on) { |
| 95 | val = vib->reg_vib_drv; |
| 96 | val |= ((vib->level << VIB_DRV_SEL_SHIFT) & VIB_DRV_SEL_MASK); |
| 97 | rc = pmic8058_vib_write_u8(vib, val, VIB_DRV); |
| 98 | if (rc < 0) |
| 99 | return rc; |
| 100 | vib->reg_vib_drv = val; |
| 101 | vib->enabled = 1; |
| 102 | |
| 103 | } else { |
| 104 | val = vib->reg_vib_drv; |
| 105 | val &= ~VIB_DRV_SEL_MASK; |
| 106 | rc = pmic8058_vib_write_u8(vib, val, VIB_DRV); |
| 107 | if (rc < 0) |
| 108 | return rc; |
| 109 | vib->reg_vib_drv = val; |
| 110 | vib->enabled = 0; |
| 111 | } |
| 112 | __dump_vib_regs(vib, "vib_set_end"); |
| 113 | |
| 114 | return rc; |
| 115 | } |
| 116 | |
| 117 | static void pmic8058_work_handler(struct work_struct *work) |
| 118 | { |
| 119 | u8 val; |
| 120 | int rc; |
| 121 | struct pmic8058_vib *info; |
| 122 | |
| 123 | info = container_of(work, struct pmic8058_vib, work); |
| 124 | |
| 125 | rc = pmic8058_vib_read_u8(info, &val, VIB_DRV); |
| 126 | if (rc < 0) |
| 127 | return; |
| 128 | |
| 129 | /* |
| 130 | * Vibrator support voltage ranges from 1.2 to 3.1V, so |
| 131 | * scale the FF speed to these range. |
| 132 | */ |
| 133 | if (info->speed) { |
| 134 | info->state = 1; |
| 135 | info->level = ((VIB_MAX_LEVELS * info->speed) / MAX_FF_SPEED) + |
| 136 | VIB_MIN_LEVEL_mV; |
| 137 | info->level /= 100; |
| 138 | } else { |
| 139 | info->state = 0; |
| 140 | info->level = VIB_MIN_LEVEL_mV / 100; |
| 141 | } |
| 142 | pmic8058_vib_set(info, info->state); |
| 143 | } |
| 144 | |
| 145 | static int pmic8058_vib_play_effect(struct input_dev *dev, void *data, |
| 146 | struct ff_effect *effect) |
| 147 | { |
| 148 | struct pmic8058_vib *info = input_get_drvdata(dev); |
| 149 | |
| 150 | info->speed = effect->u.rumble.strong_magnitude >> 8; |
| 151 | if (!info->speed) |
| 152 | info->speed = effect->u.rumble.weak_magnitude >> 9; |
| 153 | schedule_work(&info->work); |
| 154 | return 0; |
| 155 | } |
| 156 | |
| 157 | static int __devinit pmic8058_vib_probe(struct platform_device *pdev) |
| 158 | |
| 159 | { |
| 160 | struct pmic8058_vibrator_pdata *pdata = pdev->dev.platform_data; |
| 161 | struct pmic8058_vib *vib; |
| 162 | u8 val; |
| 163 | int rc; |
| 164 | |
| 165 | struct pm8058_chip *pm_chip; |
| 166 | |
| 167 | pm_chip = dev_get_drvdata(pdev->parent.dev); |
| 168 | if (pm_chip == NULL) { |
| 169 | dev_err(&pdev->dev, "no parent data passed in\n"); |
| 170 | return -EFAULT; |
| 171 | } |
| 172 | |
| 173 | if (!pdata) |
| 174 | return -EINVAL; |
| 175 | |
| 176 | if (pdata->level_mV < VIB_MIN_LEVEL_mV || |
| 177 | pdata->level_mV > VIB_MAX_LEVEL_mV) |
| 178 | return -EINVAL; |
| 179 | |
| 180 | vib = kzalloc(sizeof(*vib), GFP_KERNEL); |
| 181 | if (!vib) |
| 182 | return -ENOMEM; |
| 183 | |
| 184 | vib->pm_chip = pm_chip; |
| 185 | vib->enabled = 0; |
| 186 | vib->pdata = pdata; |
| 187 | vib->level = pdata->level_mV / 100; |
| 188 | vib->dev = &pdev->dev; |
| 189 | |
| 190 | spin_lock_init(&vib->lock); |
| 191 | INIT_WORK(&vib->work, pmic8058_work_handler); |
| 192 | |
| 193 | vib->info = input_allocate_device(); |
| 194 | |
| 195 | if (vib->info == NULL) { |
| 196 | dev_err(&pdev->dev, "couldn't allocate input device\n"); |
| 197 | return -ENOMEM; |
| 198 | } |
| 199 | |
| 200 | input_set_drvdata(vib->info, vib); |
| 201 | |
| 202 | vib->info->name = "pmic8058:vibrator"; |
| 203 | vib->info->id.version = 1; |
| 204 | vib->info->dev.parent = pdev->dev.parent; |
| 205 | |
| 206 | __set_bit(FF_RUMBLE, vib->info->ffbit); |
| 207 | __dump_vib_regs(vib, "boot_vib_default"); |
| 208 | |
| 209 | /* operate in manual mode */ |
| 210 | rc = pmic8058_vib_read_u8(vib, &val, VIB_DRV); |
| 211 | if (rc < 0) |
| 212 | goto err_read_vib; |
| 213 | val &= ~VIB_DRV_EN_MANUAL_MASK; |
| 214 | rc = pmic8058_vib_write_u8(vib, val, VIB_DRV); |
| 215 | if (rc < 0) |
| 216 | goto err_read_vib; |
| 217 | |
| 218 | vib->reg_vib_drv = val; |
| 219 | |
| 220 | rc = input_ff_create_memless(vib->info, NULL, pmic8058_vib_play_effect); |
| 221 | if (rc < 0) { |
| 222 | dev_dbg(&pdev->dev, "couldn't register vibrator to FF\n"); |
| 223 | goto create_memless_err; |
| 224 | } |
| 225 | |
| 226 | platform_set_drvdata(pdev, vib); |
| 227 | |
| 228 | rc = input_register_device(vib->info); |
| 229 | if (rc < 0) { |
| 230 | dev_dbg(&pdev->dev, "couldn't register input device\n"); |
| 231 | goto reg_err; |
| 232 | } |
| 233 | |
| 234 | return 0; |
| 235 | |
| 236 | reg_err: |
| 237 | input_ff_destroy(vib->info); |
| 238 | create_memless_err: |
| 239 | input_free_device(vib->info); |
| 240 | err_read_vib: |
| 241 | kfree(vib); |
| 242 | return rc; |
| 243 | } |
| 244 | |
| 245 | static int __devexit pmic8058_vib_remove(struct platform_device *pdev) |
| 246 | { |
| 247 | struct pmic8058_vib *vib = platform_get_drvdata(pdev); |
| 248 | |
| 249 | cancel_work_sync(&vib->work); |
| 250 | if (vib->enabled) |
| 251 | pmic8058_vib_set(vib, 0); |
| 252 | |
| 253 | input_unregister_device(vib->info); |
| 254 | kfree(vib); |
| 255 | |
| 256 | return 0; |
| 257 | } |
| 258 | |
| 259 | static struct platform_driver pmic8058_vib_driver = { |
| 260 | .probe = pmic8058_vib_probe, |
| 261 | .remove = __devexit_p(pmic8058_vib_remove), |
| 262 | .driver = { |
| 263 | .name = "pm8058-vib", |
| 264 | .owner = THIS_MODULE, |
| 265 | }, |
| 266 | }; |
| 267 | |
| 268 | static int __init pmic8058_vib_init(void) |
| 269 | { |
| 270 | return platform_driver_register(&pmic8058_vib_driver); |
| 271 | } |
| 272 | module_init(pmic8058_vib_init); |
| 273 | |
| 274 | static void __exit pmic8058_vib_exit(void) |
| 275 | { |
| 276 | platform_driver_unregister(&pmic8058_vib_driver); |
| 277 | } |
| 278 | module_exit(pmic8058_vib_exit); |
| 279 | |
| 280 | MODULE_ALIAS("platform:pmic8058_vib"); |
| 281 | MODULE_DESCRIPTION("PMIC8058 vibrator driver memless framework"); |
| 282 | MODULE_LICENSE("GPL v2"); |