Blame view
sound/soc/soc-io.c
5.45 KB
d1aaa2e68 ASoC: soc-io.c: c... |
1 2 3 4 5 6 7 |
// SPDX-License-Identifier: GPL-2.0+ // // soc-io.c -- ASoC register I/O helpers // // Copyright 2009-2011 Wolfson Microelectronics PLC. // // Author: Mark Brown <broonie@opensource.wolfsonmicro.com> |
5bef44f9b ASoC: Move regist... |
8 9 10 |
#include <linux/i2c.h> #include <linux/spi/spi.h> |
be3ea3b9e ASoC: Use new reg... |
11 |
#include <linux/regmap.h> |
d81a6d717 sound: Add export... |
12 |
#include <linux/export.h> |
5bef44f9b ASoC: Move regist... |
13 |
#include <sound/soc.h> |
e2c330b9b ASoC: Move IO abs... |
14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 |
/** * 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); |
d0ff8ba57 ASoC: add Compone... |
29 30 31 32 |
else if (component->driver->read) { *val = component->driver->read(component, reg); ret = 0; } |
e2c330b9b ASoC: Move IO abs... |
33 34 |
else ret = -EIO; |
e2c330b9b ASoC: Move IO abs... |
35 36 37 |
return ret; } EXPORT_SYMBOL_GPL(snd_soc_component_read); |
738b49efe ASoC: add snd_soc... |
38 39 40 41 42 43 44 45 46 47 48 49 50 |
unsigned int snd_soc_component_read32(struct snd_soc_component *component, unsigned int reg) { unsigned int val; int ret; ret = snd_soc_component_read(component, reg, &val); if (ret < 0) return -1; return val; } EXPORT_SYMBOL_GPL(snd_soc_component_read32); |
e2c330b9b ASoC: Move IO abs... |
51 52 53 54 55 56 57 58 59 60 |
/** * 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) |
96241c832 ASoC: Move IO fun... |
61 |
{ |
e2c330b9b ASoC: Move IO abs... |
62 63 |
if (component->regmap) return regmap_write(component->regmap, reg, val); |
d0ff8ba57 ASoC: add Compone... |
64 65 |
else if (component->driver->write) return component->driver->write(component, reg, val); |
e2c330b9b ASoC: Move IO abs... |
66 67 68 69 70 71 72 73 74 75 76 |
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; |
e2c330b9b ASoC: Move IO abs... |
77 |
mutex_lock(&component->io_mutex); |
dead99e85 ASoC: soc-io: Fix... |
78 |
ret = snd_soc_component_read(component, reg, &old); |
e2c330b9b ASoC: Move IO abs... |
79 80 81 82 83 84 |
if (ret < 0) goto out_unlock; new = (old & ~mask) | (val & mask); *change = old != new; if (*change) |
dead99e85 ASoC: soc-io: Fix... |
85 |
ret = snd_soc_component_write(component, reg, new); |
e2c330b9b ASoC: Move IO abs... |
86 87 |
out_unlock: mutex_unlock(&component->io_mutex); |
96241c832 ASoC: Move IO fun... |
88 89 90 |
return ret; } |
e2c330b9b ASoC: Move IO abs... |
91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 |
/** * 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); |