123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274 |
- /*
- * soc-io.c -- ASoC register I/O helpers
- *
- * Copyright 2009-2011 Wolfson Microelectronics PLC.
- *
- * Author: Mark Brown <broonie@opensource.wolfsonmicro.com>
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License as published by the
- * Free Software Foundation; either version 2 of the License, or (at your
- * option) any later version.
- */
- #include <linux/i2c.h>
- #include <linux/spi/spi.h>
- #include <linux/regmap.h>
- #include <linux/export.h>
- #include <sound/soc.h>
- /**
- * snd_soc_component_read() - Read register value
- * @component: Component to read from
- * @reg: Register to read
- * @val: Pointer to where the read value is stored
- *
- * Return: 0 on success, a negative error code otherwise.
- */
- int snd_soc_component_read(struct snd_soc_component *component,
- unsigned int reg, unsigned int *val)
- {
- int ret;
- if (component->regmap)
- ret = regmap_read(component->regmap, reg, val);
- else if (component->read)
- ret = component->read(component, reg, val);
- else
- ret = -EIO;
- return ret;
- }
- EXPORT_SYMBOL_GPL(snd_soc_component_read);
- /**
- * snd_soc_component_write() - Write register value
- * @component: Component to write to
- * @reg: Register to write
- * @val: Value to write to the register
- *
- * Return: 0 on success, a negative error code otherwise.
- */
- int snd_soc_component_write(struct snd_soc_component *component,
- unsigned int reg, unsigned int val)
- {
- if (component->regmap)
- return regmap_write(component->regmap, reg, val);
- else if (component->write)
- return component->write(component, reg, val);
- else
- return -EIO;
- }
- EXPORT_SYMBOL_GPL(snd_soc_component_write);
- static int snd_soc_component_update_bits_legacy(
- struct snd_soc_component *component, unsigned int reg,
- unsigned int mask, unsigned int val, bool *change)
- {
- unsigned int old, new;
- int ret;
- if (!component->read || !component->write)
- return -EIO;
- mutex_lock(&component->io_mutex);
- ret = component->read(component, reg, &old);
- if (ret < 0)
- goto out_unlock;
- new = (old & ~mask) | (val & mask);
- *change = old != new;
- if (*change)
- ret = component->write(component, reg, new);
- out_unlock:
- mutex_unlock(&component->io_mutex);
- return ret;
- }
- /**
- * snd_soc_component_update_bits() - Perform read/modify/write cycle
- * @component: Component to update
- * @reg: Register to update
- * @mask: Mask that specifies which bits to update
- * @val: New value for the bits specified by mask
- *
- * Return: 1 if the operation was successful and the value of the register
- * changed, 0 if the operation was successful, but the value did not change.
- * Returns a negative error code otherwise.
- */
- int snd_soc_component_update_bits(struct snd_soc_component *component,
- unsigned int reg, unsigned int mask, unsigned int val)
- {
- bool change;
- int ret;
- if (component->regmap)
- ret = regmap_update_bits_check(component->regmap, reg, mask,
- val, &change);
- else
- ret = snd_soc_component_update_bits_legacy(component, reg,
- mask, val, &change);
- if (ret < 0)
- return ret;
- return change;
- }
- EXPORT_SYMBOL_GPL(snd_soc_component_update_bits);
- /**
- * snd_soc_component_update_bits_async() - Perform asynchronous
- * read/modify/write cycle
- * @component: Component to update
- * @reg: Register to update
- * @mask: Mask that specifies which bits to update
- * @val: New value for the bits specified by mask
- *
- * This function is similar to snd_soc_component_update_bits(), but the update
- * operation is scheduled asynchronously. This means it may not be completed
- * when the function returns. To make sure that all scheduled updates have been
- * completed snd_soc_component_async_complete() must be called.
- *
- * Return: 1 if the operation was successful and the value of the register
- * changed, 0 if the operation was successful, but the value did not change.
- * Returns a negative error code otherwise.
- */
- int snd_soc_component_update_bits_async(struct snd_soc_component *component,
- unsigned int reg, unsigned int mask, unsigned int val)
- {
- bool change;
- int ret;
- if (component->regmap)
- ret = regmap_update_bits_check_async(component->regmap, reg,
- mask, val, &change);
- else
- ret = snd_soc_component_update_bits_legacy(component, reg,
- mask, val, &change);
- if (ret < 0)
- return ret;
- return change;
- }
- EXPORT_SYMBOL_GPL(snd_soc_component_update_bits_async);
- /**
- * snd_soc_component_async_complete() - Ensure asynchronous I/O has completed
- * @component: Component for which to wait
- *
- * This function blocks until all asynchronous I/O which has previously been
- * scheduled using snd_soc_component_update_bits_async() has completed.
- */
- void snd_soc_component_async_complete(struct snd_soc_component *component)
- {
- if (component->regmap)
- regmap_async_complete(component->regmap);
- }
- EXPORT_SYMBOL_GPL(snd_soc_component_async_complete);
- /**
- * snd_soc_component_test_bits - Test register for change
- * @component: component
- * @reg: Register to test
- * @mask: Mask that specifies which bits to test
- * @value: Value to test against
- *
- * Tests a register with a new value and checks if the new value is
- * different from the old value.
- *
- * Return: 1 for change, otherwise 0.
- */
- int snd_soc_component_test_bits(struct snd_soc_component *component,
- unsigned int reg, unsigned int mask, unsigned int value)
- {
- unsigned int old, new;
- int ret;
- ret = snd_soc_component_read(component, reg, &old);
- if (ret < 0)
- return ret;
- new = (old & ~mask) | value;
- return old != new;
- }
- EXPORT_SYMBOL_GPL(snd_soc_component_test_bits);
- unsigned int snd_soc_read(struct snd_soc_codec *codec, unsigned int reg)
- {
- unsigned int val;
- int ret;
- ret = snd_soc_component_read(&codec->component, reg, &val);
- if (ret < 0)
- return -1;
- return val;
- }
- EXPORT_SYMBOL_GPL(snd_soc_read);
- int snd_soc_write(struct snd_soc_codec *codec, unsigned int reg,
- unsigned int val)
- {
- return snd_soc_component_write(&codec->component, reg, val);
- }
- EXPORT_SYMBOL_GPL(snd_soc_write);
- /**
- * snd_soc_update_bits - update codec register bits
- * @codec: audio codec
- * @reg: codec register
- * @mask: register mask
- * @value: new value
- *
- * Writes new register value.
- *
- * Returns 1 for change, 0 for no change, or negative error code.
- */
- int snd_soc_update_bits(struct snd_soc_codec *codec, unsigned int reg,
- unsigned int mask, unsigned int value)
- {
- return snd_soc_component_update_bits(&codec->component, reg, mask,
- value);
- }
- EXPORT_SYMBOL_GPL(snd_soc_update_bits);
- /**
- * snd_soc_test_bits - test register for change
- * @codec: audio codec
- * @reg: codec register
- * @mask: register mask
- * @value: new value
- *
- * Tests a register with a new value and checks if the new value is
- * different from the old value.
- *
- * Returns 1 for change else 0.
- */
- int snd_soc_test_bits(struct snd_soc_codec *codec, unsigned int reg,
- unsigned int mask, unsigned int value)
- {
- return snd_soc_component_test_bits(&codec->component, reg, mask, value);
- }
- EXPORT_SYMBOL_GPL(snd_soc_test_bits);
- int snd_soc_platform_read(struct snd_soc_platform *platform,
- unsigned int reg)
- {
- unsigned int val;
- int ret;
- ret = snd_soc_component_read(&platform->component, reg, &val);
- if (ret < 0)
- return -1;
- return val;
- }
- EXPORT_SYMBOL_GPL(snd_soc_platform_read);
- int snd_soc_platform_write(struct snd_soc_platform *platform,
- unsigned int reg, unsigned int val)
- {
- return snd_soc_component_write(&platform->component, reg, val);
- }
- EXPORT_SYMBOL_GPL(snd_soc_platform_write);
|