diff options
author | Mark Brown <broonie@opensource.wolfsonmicro.com> | 2010-03-05 11:27:15 -0500 |
---|---|---|
committer | Mark Brown <broonie@opensource.wolfsonmicro.com> | 2010-03-05 11:42:06 -0500 |
commit | bc6552f4717e07e7737b5dc17883c2ff99f2a315 (patch) | |
tree | 73bb1869ab320aba08f63d27760dd6231c709f8e | |
parent | 1ca7578043a79d74152774acee0ed6e393134d12 (diff) |
ASoC: Add 16/16 registers to soc-cache
I2C only at the minute.
Signed-off-by: Mark Brown <broonie@opensource.wolfsonmicro.com>
Acked-by: Liam Girdwood <lrg@slimlogic.co.uk>
-rw-r--r-- | sound/soc/soc-cache.c | 83 |
1 files changed, 83 insertions, 0 deletions
diff --git a/sound/soc/soc-cache.c b/sound/soc/soc-cache.c index 5869dc3be781..bf593a834f5a 100644 --- a/sound/soc/soc-cache.c +++ b/sound/soc/soc-cache.c | |||
@@ -366,6 +366,84 @@ static int snd_soc_16_8_spi_write(void *control_data, const char *data, | |||
366 | #define snd_soc_16_8_spi_write NULL | 366 | #define snd_soc_16_8_spi_write NULL |
367 | #endif | 367 | #endif |
368 | 368 | ||
369 | #if defined(CONFIG_I2C) || (defined(CONFIG_I2C_MODULE) && defined(MODULE)) | ||
370 | static unsigned int snd_soc_16_16_read_i2c(struct snd_soc_codec *codec, | ||
371 | unsigned int r) | ||
372 | { | ||
373 | struct i2c_msg xfer[2]; | ||
374 | u16 reg = cpu_to_be16(r); | ||
375 | u16 data; | ||
376 | int ret; | ||
377 | struct i2c_client *client = codec->control_data; | ||
378 | |||
379 | /* Write register */ | ||
380 | xfer[0].addr = client->addr; | ||
381 | xfer[0].flags = 0; | ||
382 | xfer[0].len = 2; | ||
383 | xfer[0].buf = (u8 *)® | ||
384 | |||
385 | /* Read data */ | ||
386 | xfer[1].addr = client->addr; | ||
387 | xfer[1].flags = I2C_M_RD; | ||
388 | xfer[1].len = 2; | ||
389 | xfer[1].buf = (u8 *)&data; | ||
390 | |||
391 | ret = i2c_transfer(client->adapter, xfer, 2); | ||
392 | if (ret != 2) { | ||
393 | dev_err(&client->dev, "i2c_transfer() returned %d\n", ret); | ||
394 | return 0; | ||
395 | } | ||
396 | |||
397 | return be16_to_cpu(data); | ||
398 | } | ||
399 | #else | ||
400 | #define snd_soc_16_16_read_i2c NULL | ||
401 | #endif | ||
402 | |||
403 | static unsigned int snd_soc_16_16_read(struct snd_soc_codec *codec, | ||
404 | unsigned int reg) | ||
405 | { | ||
406 | u16 *cache = codec->reg_cache; | ||
407 | |||
408 | if (reg >= codec->reg_cache_size || | ||
409 | snd_soc_codec_volatile_register(codec, reg)) { | ||
410 | if (codec->cache_only) | ||
411 | return -EINVAL; | ||
412 | |||
413 | return codec->hw_read(codec, reg); | ||
414 | } | ||
415 | |||
416 | return cache[reg]; | ||
417 | } | ||
418 | |||
419 | static int snd_soc_16_16_write(struct snd_soc_codec *codec, unsigned int reg, | ||
420 | unsigned int value) | ||
421 | { | ||
422 | u16 *cache = codec->reg_cache; | ||
423 | u8 data[4]; | ||
424 | int ret; | ||
425 | |||
426 | data[0] = (reg >> 8) & 0xff; | ||
427 | data[1] = reg & 0xff; | ||
428 | data[2] = (value >> 8) & 0xff; | ||
429 | data[3] = value & 0xff; | ||
430 | |||
431 | if (reg < codec->reg_cache_size) | ||
432 | cache[reg] = value; | ||
433 | |||
434 | if (codec->cache_only) { | ||
435 | codec->cache_sync = 1; | ||
436 | return 0; | ||
437 | } | ||
438 | |||
439 | ret = codec->hw_write(codec->control_data, data, 4); | ||
440 | if (ret == 4) | ||
441 | return 0; | ||
442 | if (ret < 0) | ||
443 | return ret; | ||
444 | else | ||
445 | return -EIO; | ||
446 | } | ||
369 | 447 | ||
370 | static struct { | 448 | static struct { |
371 | int addr_bits; | 449 | int addr_bits; |
@@ -400,6 +478,11 @@ static struct { | |||
400 | .i2c_read = snd_soc_16_8_read_i2c, | 478 | .i2c_read = snd_soc_16_8_read_i2c, |
401 | .spi_write = snd_soc_16_8_spi_write, | 479 | .spi_write = snd_soc_16_8_spi_write, |
402 | }, | 480 | }, |
481 | { | ||
482 | .addr_bits = 16, .data_bits = 16, | ||
483 | .write = snd_soc_16_16_write, .read = snd_soc_16_16_read, | ||
484 | .i2c_read = snd_soc_16_16_read_i2c, | ||
485 | }, | ||
403 | }; | 486 | }; |
404 | 487 | ||
405 | /** | 488 | /** |