diff options
author | Stefan Richter <stefanr@s5r6.in-berlin.de> | 2011-05-10 14:52:07 -0400 |
---|---|---|
committer | Stefan Richter <stefanr@s5r6.in-berlin.de> | 2011-05-10 16:50:41 -0400 |
commit | 020abf03cd659388f94cb328e1e1df0656e0d7ff (patch) | |
tree | 40d05011708ad1b4a05928d167eb120420581aa6 /drivers/mfd/wm8994-core.c | |
parent | 0ff8fbc61727c926883eec381fbd3d32d1fab504 (diff) | |
parent | 693d92a1bbc9e42681c42ed190bd42b636ca876f (diff) |
Merge tag 'v2.6.39-rc7'
in order to pull in changes in drivers/media/dvb/firewire/ and
sound/firewire/.
Diffstat (limited to 'drivers/mfd/wm8994-core.c')
-rw-r--r-- | drivers/mfd/wm8994-core.c | 232 |
1 files changed, 170 insertions, 62 deletions
diff --git a/drivers/mfd/wm8994-core.c b/drivers/mfd/wm8994-core.c index b3b2aaf89dbe..e198d40292e7 100644 --- a/drivers/mfd/wm8994-core.c +++ b/drivers/mfd/wm8994-core.c | |||
@@ -18,6 +18,7 @@ | |||
18 | #include <linux/i2c.h> | 18 | #include <linux/i2c.h> |
19 | #include <linux/delay.h> | 19 | #include <linux/delay.h> |
20 | #include <linux/mfd/core.h> | 20 | #include <linux/mfd/core.h> |
21 | #include <linux/pm_runtime.h> | ||
21 | #include <linux/regulator/consumer.h> | 22 | #include <linux/regulator/consumer.h> |
22 | #include <linux/regulator/machine.h> | 23 | #include <linux/regulator/machine.h> |
23 | 24 | ||
@@ -39,10 +40,8 @@ static int wm8994_read(struct wm8994 *wm8994, unsigned short reg, | |||
39 | return ret; | 40 | return ret; |
40 | 41 | ||
41 | for (i = 0; i < bytes / 2; i++) { | 42 | for (i = 0; i < bytes / 2; i++) { |
42 | buf[i] = be16_to_cpu(buf[i]); | ||
43 | |||
44 | dev_vdbg(wm8994->dev, "Read %04x from R%d(0x%x)\n", | 43 | dev_vdbg(wm8994->dev, "Read %04x from R%d(0x%x)\n", |
45 | buf[i], reg + i, reg + i); | 44 | be16_to_cpu(buf[i]), reg + i, reg + i); |
46 | } | 45 | } |
47 | 46 | ||
48 | return 0; | 47 | return 0; |
@@ -68,7 +67,7 @@ int wm8994_reg_read(struct wm8994 *wm8994, unsigned short reg) | |||
68 | if (ret < 0) | 67 | if (ret < 0) |
69 | return ret; | 68 | return ret; |
70 | else | 69 | else |
71 | return val; | 70 | return be16_to_cpu(val); |
72 | } | 71 | } |
73 | EXPORT_SYMBOL_GPL(wm8994_reg_read); | 72 | EXPORT_SYMBOL_GPL(wm8994_reg_read); |
74 | 73 | ||
@@ -78,7 +77,7 @@ EXPORT_SYMBOL_GPL(wm8994_reg_read); | |||
78 | * @wm8994: Device to read from | 77 | * @wm8994: Device to read from |
79 | * @reg: First register | 78 | * @reg: First register |
80 | * @count: Number of registers | 79 | * @count: Number of registers |
81 | * @buf: Buffer to fill. | 80 | * @buf: Buffer to fill. The data will be returned big endian. |
82 | */ | 81 | */ |
83 | int wm8994_bulk_read(struct wm8994 *wm8994, unsigned short reg, | 82 | int wm8994_bulk_read(struct wm8994 *wm8994, unsigned short reg, |
84 | int count, u16 *buf) | 83 | int count, u16 *buf) |
@@ -96,9 +95,9 @@ int wm8994_bulk_read(struct wm8994 *wm8994, unsigned short reg, | |||
96 | EXPORT_SYMBOL_GPL(wm8994_bulk_read); | 95 | EXPORT_SYMBOL_GPL(wm8994_bulk_read); |
97 | 96 | ||
98 | static int wm8994_write(struct wm8994 *wm8994, unsigned short reg, | 97 | static int wm8994_write(struct wm8994 *wm8994, unsigned short reg, |
99 | int bytes, void *src) | 98 | int bytes, const void *src) |
100 | { | 99 | { |
101 | u16 *buf = src; | 100 | const u16 *buf = src; |
102 | int i; | 101 | int i; |
103 | 102 | ||
104 | BUG_ON(bytes % 2); | 103 | BUG_ON(bytes % 2); |
@@ -106,9 +105,7 @@ static int wm8994_write(struct wm8994 *wm8994, unsigned short reg, | |||
106 | 105 | ||
107 | for (i = 0; i < bytes / 2; i++) { | 106 | for (i = 0; i < bytes / 2; i++) { |
108 | dev_vdbg(wm8994->dev, "Write %04x to R%d(0x%x)\n", | 107 | dev_vdbg(wm8994->dev, "Write %04x to R%d(0x%x)\n", |
109 | buf[i], reg + i, reg + i); | 108 | be16_to_cpu(buf[i]), reg + i, reg + i); |
110 | |||
111 | buf[i] = cpu_to_be16(buf[i]); | ||
112 | } | 109 | } |
113 | 110 | ||
114 | return wm8994->write_dev(wm8994, reg, bytes, src); | 111 | return wm8994->write_dev(wm8994, reg, bytes, src); |
@@ -126,6 +123,8 @@ int wm8994_reg_write(struct wm8994 *wm8994, unsigned short reg, | |||
126 | { | 123 | { |
127 | int ret; | 124 | int ret; |
128 | 125 | ||
126 | val = cpu_to_be16(val); | ||
127 | |||
129 | mutex_lock(&wm8994->io_lock); | 128 | mutex_lock(&wm8994->io_lock); |
130 | 129 | ||
131 | ret = wm8994_write(wm8994, reg, 2, &val); | 130 | ret = wm8994_write(wm8994, reg, 2, &val); |
@@ -137,6 +136,29 @@ int wm8994_reg_write(struct wm8994 *wm8994, unsigned short reg, | |||
137 | EXPORT_SYMBOL_GPL(wm8994_reg_write); | 136 | EXPORT_SYMBOL_GPL(wm8994_reg_write); |
138 | 137 | ||
139 | /** | 138 | /** |
139 | * wm8994_bulk_write: Write multiple WM8994 registers | ||
140 | * | ||
141 | * @wm8994: Device to write to | ||
142 | * @reg: First register | ||
143 | * @count: Number of registers | ||
144 | * @buf: Buffer to write from. Data must be big-endian formatted. | ||
145 | */ | ||
146 | int wm8994_bulk_write(struct wm8994 *wm8994, unsigned short reg, | ||
147 | int count, const u16 *buf) | ||
148 | { | ||
149 | int ret; | ||
150 | |||
151 | mutex_lock(&wm8994->io_lock); | ||
152 | |||
153 | ret = wm8994_write(wm8994, reg, count * 2, buf); | ||
154 | |||
155 | mutex_unlock(&wm8994->io_lock); | ||
156 | |||
157 | return ret; | ||
158 | } | ||
159 | EXPORT_SYMBOL_GPL(wm8994_bulk_write); | ||
160 | |||
161 | /** | ||
140 | * wm8994_set_bits: Set the value of a bitfield in a WM8994 register | 162 | * wm8994_set_bits: Set the value of a bitfield in a WM8994 register |
141 | * | 163 | * |
142 | * @wm8994: Device to write to. | 164 | * @wm8994: Device to write to. |
@@ -156,9 +178,13 @@ int wm8994_set_bits(struct wm8994 *wm8994, unsigned short reg, | |||
156 | if (ret < 0) | 178 | if (ret < 0) |
157 | goto out; | 179 | goto out; |
158 | 180 | ||
181 | r = be16_to_cpu(r); | ||
182 | |||
159 | r &= ~mask; | 183 | r &= ~mask; |
160 | r |= val; | 184 | r |= val; |
161 | 185 | ||
186 | r = cpu_to_be16(r); | ||
187 | |||
162 | ret = wm8994_write(wm8994, reg, 2, &r); | 188 | ret = wm8994_write(wm8994, reg, 2, &r); |
163 | 189 | ||
164 | out: | 190 | out: |
@@ -169,8 +195,16 @@ out: | |||
169 | EXPORT_SYMBOL_GPL(wm8994_set_bits); | 195 | EXPORT_SYMBOL_GPL(wm8994_set_bits); |
170 | 196 | ||
171 | static struct mfd_cell wm8994_regulator_devs[] = { | 197 | static struct mfd_cell wm8994_regulator_devs[] = { |
172 | { .name = "wm8994-ldo", .id = 1 }, | 198 | { |
173 | { .name = "wm8994-ldo", .id = 2 }, | 199 | .name = "wm8994-ldo", |
200 | .id = 1, | ||
201 | .pm_runtime_no_callbacks = true, | ||
202 | }, | ||
203 | { | ||
204 | .name = "wm8994-ldo", | ||
205 | .id = 2, | ||
206 | .pm_runtime_no_callbacks = true, | ||
207 | }, | ||
174 | }; | 208 | }; |
175 | 209 | ||
176 | static struct resource wm8994_codec_resources[] = { | 210 | static struct resource wm8994_codec_resources[] = { |
@@ -200,6 +234,7 @@ static struct mfd_cell wm8994_devs[] = { | |||
200 | .name = "wm8994-gpio", | 234 | .name = "wm8994-gpio", |
201 | .num_resources = ARRAY_SIZE(wm8994_gpio_resources), | 235 | .num_resources = ARRAY_SIZE(wm8994_gpio_resources), |
202 | .resources = wm8994_gpio_resources, | 236 | .resources = wm8994_gpio_resources, |
237 | .pm_runtime_no_callbacks = true, | ||
203 | }, | 238 | }, |
204 | }; | 239 | }; |
205 | 240 | ||
@@ -218,12 +253,34 @@ static const char *wm8994_main_supplies[] = { | |||
218 | "SPKVDD2", | 253 | "SPKVDD2", |
219 | }; | 254 | }; |
220 | 255 | ||
256 | static const char *wm8958_main_supplies[] = { | ||
257 | "DBVDD1", | ||
258 | "DBVDD2", | ||
259 | "DBVDD3", | ||
260 | "DCVDD", | ||
261 | "AVDD1", | ||
262 | "AVDD2", | ||
263 | "CPVDD", | ||
264 | "SPKVDD1", | ||
265 | "SPKVDD2", | ||
266 | }; | ||
267 | |||
221 | #ifdef CONFIG_PM | 268 | #ifdef CONFIG_PM |
222 | static int wm8994_device_suspend(struct device *dev) | 269 | static int wm8994_suspend(struct device *dev) |
223 | { | 270 | { |
224 | struct wm8994 *wm8994 = dev_get_drvdata(dev); | 271 | struct wm8994 *wm8994 = dev_get_drvdata(dev); |
225 | int ret; | 272 | int ret; |
226 | 273 | ||
274 | /* Don't actually go through with the suspend if the CODEC is | ||
275 | * still active (eg, for audio passthrough from CP. */ | ||
276 | ret = wm8994_reg_read(wm8994, WM8994_POWER_MANAGEMENT_1); | ||
277 | if (ret < 0) { | ||
278 | dev_err(dev, "Failed to read power status: %d\n", ret); | ||
279 | } else if (ret & WM8994_VMID_SEL_MASK) { | ||
280 | dev_dbg(dev, "CODEC still active, ignoring suspend\n"); | ||
281 | return 0; | ||
282 | } | ||
283 | |||
227 | /* GPIO configuration state is saved here since we may be configuring | 284 | /* GPIO configuration state is saved here since we may be configuring |
228 | * the GPIO alternate functions even if we're not using the gpiolib | 285 | * the GPIO alternate functions even if we're not using the gpiolib |
229 | * driver for them. | 286 | * driver for them. |
@@ -239,7 +296,14 @@ static int wm8994_device_suspend(struct device *dev) | |||
239 | if (ret < 0) | 296 | if (ret < 0) |
240 | dev_err(dev, "Failed to save LDO registers: %d\n", ret); | 297 | dev_err(dev, "Failed to save LDO registers: %d\n", ret); |
241 | 298 | ||
242 | ret = regulator_bulk_disable(ARRAY_SIZE(wm8994_main_supplies), | 299 | /* Explicitly put the device into reset in case regulators |
300 | * don't get disabled in order to ensure consistent restart. | ||
301 | */ | ||
302 | wm8994_reg_write(wm8994, WM8994_SOFTWARE_RESET, 0x8994); | ||
303 | |||
304 | wm8994->suspended = true; | ||
305 | |||
306 | ret = regulator_bulk_disable(wm8994->num_supplies, | ||
243 | wm8994->supplies); | 307 | wm8994->supplies); |
244 | if (ret != 0) { | 308 | if (ret != 0) { |
245 | dev_err(dev, "Failed to disable supplies: %d\n", ret); | 309 | dev_err(dev, "Failed to disable supplies: %d\n", ret); |
@@ -249,12 +313,16 @@ static int wm8994_device_suspend(struct device *dev) | |||
249 | return 0; | 313 | return 0; |
250 | } | 314 | } |
251 | 315 | ||
252 | static int wm8994_device_resume(struct device *dev) | 316 | static int wm8994_resume(struct device *dev) |
253 | { | 317 | { |
254 | struct wm8994 *wm8994 = dev_get_drvdata(dev); | 318 | struct wm8994 *wm8994 = dev_get_drvdata(dev); |
255 | int ret; | 319 | int ret; |
256 | 320 | ||
257 | ret = regulator_bulk_enable(ARRAY_SIZE(wm8994_main_supplies), | 321 | /* We may have lied to the PM core about suspending */ |
322 | if (!wm8994->suspended) | ||
323 | return 0; | ||
324 | |||
325 | ret = regulator_bulk_enable(wm8994->num_supplies, | ||
258 | wm8994->supplies); | 326 | wm8994->supplies); |
259 | if (ret != 0) { | 327 | if (ret != 0) { |
260 | dev_err(dev, "Failed to enable supplies: %d\n", ret); | 328 | dev_err(dev, "Failed to enable supplies: %d\n", ret); |
@@ -276,6 +344,8 @@ static int wm8994_device_resume(struct device *dev) | |||
276 | if (ret < 0) | 344 | if (ret < 0) |
277 | dev_err(dev, "Failed to restore GPIO registers: %d\n", ret); | 345 | dev_err(dev, "Failed to restore GPIO registers: %d\n", ret); |
278 | 346 | ||
347 | wm8994->suspended = false; | ||
348 | |||
279 | return 0; | 349 | return 0; |
280 | } | 350 | } |
281 | #endif | 351 | #endif |
@@ -305,9 +375,10 @@ static int wm8994_ldo_in_use(struct wm8994_pdata *pdata, int ldo) | |||
305 | /* | 375 | /* |
306 | * Instantiate the generic non-control parts of the device. | 376 | * Instantiate the generic non-control parts of the device. |
307 | */ | 377 | */ |
308 | static int wm8994_device_init(struct wm8994 *wm8994, unsigned long id, int irq) | 378 | static int wm8994_device_init(struct wm8994 *wm8994, int irq) |
309 | { | 379 | { |
310 | struct wm8994_pdata *pdata = wm8994->dev->platform_data; | 380 | struct wm8994_pdata *pdata = wm8994->dev->platform_data; |
381 | const char *devname; | ||
311 | int ret, i; | 382 | int ret, i; |
312 | 383 | ||
313 | mutex_init(&wm8994->io_lock); | 384 | mutex_init(&wm8994->io_lock); |
@@ -323,25 +394,48 @@ static int wm8994_device_init(struct wm8994 *wm8994, unsigned long id, int irq) | |||
323 | goto err; | 394 | goto err; |
324 | } | 395 | } |
325 | 396 | ||
397 | switch (wm8994->type) { | ||
398 | case WM8994: | ||
399 | wm8994->num_supplies = ARRAY_SIZE(wm8994_main_supplies); | ||
400 | break; | ||
401 | case WM8958: | ||
402 | wm8994->num_supplies = ARRAY_SIZE(wm8958_main_supplies); | ||
403 | break; | ||
404 | default: | ||
405 | BUG(); | ||
406 | return -EINVAL; | ||
407 | } | ||
408 | |||
326 | wm8994->supplies = kzalloc(sizeof(struct regulator_bulk_data) * | 409 | wm8994->supplies = kzalloc(sizeof(struct regulator_bulk_data) * |
327 | ARRAY_SIZE(wm8994_main_supplies), | 410 | wm8994->num_supplies, |
328 | GFP_KERNEL); | 411 | GFP_KERNEL); |
329 | if (!wm8994->supplies) { | 412 | if (!wm8994->supplies) { |
330 | ret = -ENOMEM; | 413 | ret = -ENOMEM; |
331 | goto err; | 414 | goto err; |
332 | } | 415 | } |
333 | 416 | ||
334 | for (i = 0; i < ARRAY_SIZE(wm8994_main_supplies); i++) | 417 | switch (wm8994->type) { |
335 | wm8994->supplies[i].supply = wm8994_main_supplies[i]; | 418 | case WM8994: |
336 | 419 | for (i = 0; i < ARRAY_SIZE(wm8994_main_supplies); i++) | |
337 | ret = regulator_bulk_get(wm8994->dev, ARRAY_SIZE(wm8994_main_supplies), | 420 | wm8994->supplies[i].supply = wm8994_main_supplies[i]; |
421 | break; | ||
422 | case WM8958: | ||
423 | for (i = 0; i < ARRAY_SIZE(wm8958_main_supplies); i++) | ||
424 | wm8994->supplies[i].supply = wm8958_main_supplies[i]; | ||
425 | break; | ||
426 | default: | ||
427 | BUG(); | ||
428 | return -EINVAL; | ||
429 | } | ||
430 | |||
431 | ret = regulator_bulk_get(wm8994->dev, wm8994->num_supplies, | ||
338 | wm8994->supplies); | 432 | wm8994->supplies); |
339 | if (ret != 0) { | 433 | if (ret != 0) { |
340 | dev_err(wm8994->dev, "Failed to get supplies: %d\n", ret); | 434 | dev_err(wm8994->dev, "Failed to get supplies: %d\n", ret); |
341 | goto err_supplies; | 435 | goto err_supplies; |
342 | } | 436 | } |
343 | 437 | ||
344 | ret = regulator_bulk_enable(ARRAY_SIZE(wm8994_main_supplies), | 438 | ret = regulator_bulk_enable(wm8994->num_supplies, |
345 | wm8994->supplies); | 439 | wm8994->supplies); |
346 | if (ret != 0) { | 440 | if (ret != 0) { |
347 | dev_err(wm8994->dev, "Failed to enable supplies: %d\n", ret); | 441 | dev_err(wm8994->dev, "Failed to enable supplies: %d\n", ret); |
@@ -353,7 +447,22 @@ static int wm8994_device_init(struct wm8994 *wm8994, unsigned long id, int irq) | |||
353 | dev_err(wm8994->dev, "Failed to read ID register\n"); | 447 | dev_err(wm8994->dev, "Failed to read ID register\n"); |
354 | goto err_enable; | 448 | goto err_enable; |
355 | } | 449 | } |
356 | if (ret != 0x8994) { | 450 | switch (ret) { |
451 | case 0x8994: | ||
452 | devname = "WM8994"; | ||
453 | if (wm8994->type != WM8994) | ||
454 | dev_warn(wm8994->dev, "Device registered as type %d\n", | ||
455 | wm8994->type); | ||
456 | wm8994->type = WM8994; | ||
457 | break; | ||
458 | case 0x8958: | ||
459 | devname = "WM8958"; | ||
460 | if (wm8994->type != WM8958) | ||
461 | dev_warn(wm8994->dev, "Device registered as type %d\n", | ||
462 | wm8994->type); | ||
463 | wm8994->type = WM8958; | ||
464 | break; | ||
465 | default: | ||
357 | dev_err(wm8994->dev, "Device is not a WM8994, ID is %x\n", | 466 | dev_err(wm8994->dev, "Device is not a WM8994, ID is %x\n", |
358 | ret); | 467 | ret); |
359 | ret = -EINVAL; | 468 | ret = -EINVAL; |
@@ -370,14 +479,16 @@ static int wm8994_device_init(struct wm8994 *wm8994, unsigned long id, int irq) | |||
370 | switch (ret) { | 479 | switch (ret) { |
371 | case 0: | 480 | case 0: |
372 | case 1: | 481 | case 1: |
373 | dev_warn(wm8994->dev, "revision %c not fully supported\n", | 482 | if (wm8994->type == WM8994) |
374 | 'A' + ret); | 483 | dev_warn(wm8994->dev, |
484 | "revision %c not fully supported\n", | ||
485 | 'A' + ret); | ||
375 | break; | 486 | break; |
376 | default: | 487 | default: |
377 | dev_info(wm8994->dev, "revision %c\n", 'A' + ret); | ||
378 | break; | 488 | break; |
379 | } | 489 | } |
380 | 490 | ||
491 | dev_info(wm8994->dev, "%s revision %c\n", devname, 'A' + ret); | ||
381 | 492 | ||
382 | if (pdata) { | 493 | if (pdata) { |
383 | wm8994->irq_base = pdata->irq_base; | 494 | wm8994->irq_base = pdata->irq_base; |
@@ -418,15 +529,18 @@ static int wm8994_device_init(struct wm8994 *wm8994, unsigned long id, int irq) | |||
418 | goto err_irq; | 529 | goto err_irq; |
419 | } | 530 | } |
420 | 531 | ||
532 | pm_runtime_enable(wm8994->dev); | ||
533 | pm_runtime_resume(wm8994->dev); | ||
534 | |||
421 | return 0; | 535 | return 0; |
422 | 536 | ||
423 | err_irq: | 537 | err_irq: |
424 | wm8994_irq_exit(wm8994); | 538 | wm8994_irq_exit(wm8994); |
425 | err_enable: | 539 | err_enable: |
426 | regulator_bulk_disable(ARRAY_SIZE(wm8994_main_supplies), | 540 | regulator_bulk_disable(wm8994->num_supplies, |
427 | wm8994->supplies); | 541 | wm8994->supplies); |
428 | err_get: | 542 | err_get: |
429 | regulator_bulk_free(ARRAY_SIZE(wm8994_main_supplies), wm8994->supplies); | 543 | regulator_bulk_free(wm8994->num_supplies, wm8994->supplies); |
430 | err_supplies: | 544 | err_supplies: |
431 | kfree(wm8994->supplies); | 545 | kfree(wm8994->supplies); |
432 | err: | 546 | err: |
@@ -437,11 +551,12 @@ err: | |||
437 | 551 | ||
438 | static void wm8994_device_exit(struct wm8994 *wm8994) | 552 | static void wm8994_device_exit(struct wm8994 *wm8994) |
439 | { | 553 | { |
554 | pm_runtime_disable(wm8994->dev); | ||
440 | mfd_remove_devices(wm8994->dev); | 555 | mfd_remove_devices(wm8994->dev); |
441 | wm8994_irq_exit(wm8994); | 556 | wm8994_irq_exit(wm8994); |
442 | regulator_bulk_disable(ARRAY_SIZE(wm8994_main_supplies), | 557 | regulator_bulk_disable(wm8994->num_supplies, |
443 | wm8994->supplies); | 558 | wm8994->supplies); |
444 | regulator_bulk_free(ARRAY_SIZE(wm8994_main_supplies), wm8994->supplies); | 559 | regulator_bulk_free(wm8994->num_supplies, wm8994->supplies); |
445 | kfree(wm8994->supplies); | 560 | kfree(wm8994->supplies); |
446 | kfree(wm8994); | 561 | kfree(wm8994); |
447 | } | 562 | } |
@@ -467,25 +582,29 @@ static int wm8994_i2c_read_device(struct wm8994 *wm8994, unsigned short reg, | |||
467 | return 0; | 582 | return 0; |
468 | } | 583 | } |
469 | 584 | ||
470 | /* Currently we allocate the write buffer on the stack; this is OK for | ||
471 | * small writes - if we need to do large writes this will need to be | ||
472 | * revised. | ||
473 | */ | ||
474 | static int wm8994_i2c_write_device(struct wm8994 *wm8994, unsigned short reg, | 585 | static int wm8994_i2c_write_device(struct wm8994 *wm8994, unsigned short reg, |
475 | int bytes, void *src) | 586 | int bytes, const void *src) |
476 | { | 587 | { |
477 | struct i2c_client *i2c = wm8994->control_data; | 588 | struct i2c_client *i2c = wm8994->control_data; |
478 | unsigned char msg[bytes + 2]; | 589 | struct i2c_msg xfer[2]; |
479 | int ret; | 590 | int ret; |
480 | 591 | ||
481 | reg = cpu_to_be16(reg); | 592 | reg = cpu_to_be16(reg); |
482 | memcpy(&msg[0], ®, 2); | ||
483 | memcpy(&msg[2], src, bytes); | ||
484 | 593 | ||
485 | ret = i2c_master_send(i2c, msg, bytes + 2); | 594 | xfer[0].addr = i2c->addr; |
595 | xfer[0].flags = 0; | ||
596 | xfer[0].len = 2; | ||
597 | xfer[0].buf = (char *)® | ||
598 | |||
599 | xfer[1].addr = i2c->addr; | ||
600 | xfer[1].flags = I2C_M_NOSTART; | ||
601 | xfer[1].len = bytes; | ||
602 | xfer[1].buf = (char *)src; | ||
603 | |||
604 | ret = i2c_transfer(i2c->adapter, xfer, 2); | ||
486 | if (ret < 0) | 605 | if (ret < 0) |
487 | return ret; | 606 | return ret; |
488 | if (ret < bytes + 2) | 607 | if (ret != 2) |
489 | return -EIO; | 608 | return -EIO; |
490 | 609 | ||
491 | return 0; | 610 | return 0; |
@@ -506,8 +625,9 @@ static int wm8994_i2c_probe(struct i2c_client *i2c, | |||
506 | wm8994->read_dev = wm8994_i2c_read_device; | 625 | wm8994->read_dev = wm8994_i2c_read_device; |
507 | wm8994->write_dev = wm8994_i2c_write_device; | 626 | wm8994->write_dev = wm8994_i2c_write_device; |
508 | wm8994->irq = i2c->irq; | 627 | wm8994->irq = i2c->irq; |
628 | wm8994->type = id->driver_data; | ||
509 | 629 | ||
510 | return wm8994_device_init(wm8994, id->driver_data, i2c->irq); | 630 | return wm8994_device_init(wm8994, i2c->irq); |
511 | } | 631 | } |
512 | 632 | ||
513 | static int wm8994_i2c_remove(struct i2c_client *i2c) | 633 | static int wm8994_i2c_remove(struct i2c_client *i2c) |
@@ -519,36 +639,24 @@ static int wm8994_i2c_remove(struct i2c_client *i2c) | |||
519 | return 0; | 639 | return 0; |
520 | } | 640 | } |
521 | 641 | ||
522 | #ifdef CONFIG_PM | ||
523 | static int wm8994_i2c_suspend(struct i2c_client *i2c, pm_message_t state) | ||
524 | { | ||
525 | return wm8994_device_suspend(&i2c->dev); | ||
526 | } | ||
527 | |||
528 | static int wm8994_i2c_resume(struct i2c_client *i2c) | ||
529 | { | ||
530 | return wm8994_device_resume(&i2c->dev); | ||
531 | } | ||
532 | #else | ||
533 | #define wm8994_i2c_suspend NULL | ||
534 | #define wm8994_i2c_resume NULL | ||
535 | #endif | ||
536 | |||
537 | static const struct i2c_device_id wm8994_i2c_id[] = { | 642 | static const struct i2c_device_id wm8994_i2c_id[] = { |
538 | { "wm8994", 0 }, | 643 | { "wm8994", WM8994 }, |
644 | { "wm8958", WM8958 }, | ||
539 | { } | 645 | { } |
540 | }; | 646 | }; |
541 | MODULE_DEVICE_TABLE(i2c, wm8994_i2c_id); | 647 | MODULE_DEVICE_TABLE(i2c, wm8994_i2c_id); |
542 | 648 | ||
649 | static UNIVERSAL_DEV_PM_OPS(wm8994_pm_ops, wm8994_suspend, wm8994_resume, | ||
650 | NULL); | ||
651 | |||
543 | static struct i2c_driver wm8994_i2c_driver = { | 652 | static struct i2c_driver wm8994_i2c_driver = { |
544 | .driver = { | 653 | .driver = { |
545 | .name = "wm8994", | 654 | .name = "wm8994", |
546 | .owner = THIS_MODULE, | 655 | .owner = THIS_MODULE, |
656 | .pm = &wm8994_pm_ops, | ||
547 | }, | 657 | }, |
548 | .probe = wm8994_i2c_probe, | 658 | .probe = wm8994_i2c_probe, |
549 | .remove = wm8994_i2c_remove, | 659 | .remove = wm8994_i2c_remove, |
550 | .suspend = wm8994_i2c_suspend, | ||
551 | .resume = wm8994_i2c_resume, | ||
552 | .id_table = wm8994_i2c_id, | 660 | .id_table = wm8994_i2c_id, |
553 | }; | 661 | }; |
554 | 662 | ||