1/* 2 * soc-io.c -- ASoC register I/O helpers 3 * 4 * Copyright 2009-2011 Wolfson Microelectronics PLC. 5 * 6 * Author: Mark Brown <broonie@opensource.wolfsonmicro.com> 7 * 8 * This program is free software; you can redistribute it and/or modify it 9 * under the terms of the GNU General Public License as published by the 10 * Free Software Foundation; either version 2 of the License, or (at your 11 * option) any later version. 12 */ 13 14#include <linux/i2c.h> 15#include <linux/spi/spi.h> 16#include <linux/regmap.h> 17#include <linux/export.h> 18#include <sound/soc.h> 19 20/** 21 * snd_soc_component_read() - Read register value 22 * @component: Component to read from 23 * @reg: Register to read 24 * @val: Pointer to where the read value is stored 25 * 26 * Return: 0 on success, a negative error code otherwise. 27 */ 28int snd_soc_component_read(struct snd_soc_component *component, 29 unsigned int reg, unsigned int *val) 30{ 31 int ret; 32 33 if (component->regmap) 34 ret = regmap_read(component->regmap, reg, val); 35 else if (component->read) 36 ret = component->read(component, reg, val); 37 else 38 ret = -EIO; 39 40 return ret; 41} 42EXPORT_SYMBOL_GPL(snd_soc_component_read); 43 44/** 45 * snd_soc_component_write() - Write register value 46 * @component: Component to write to 47 * @reg: Register to write 48 * @val: Value to write to the register 49 * 50 * Return: 0 on success, a negative error code otherwise. 51 */ 52int snd_soc_component_write(struct snd_soc_component *component, 53 unsigned int reg, unsigned int val) 54{ 55 if (component->regmap) 56 return regmap_write(component->regmap, reg, val); 57 else if (component->write) 58 return component->write(component, reg, val); 59 else 60 return -EIO; 61} 62EXPORT_SYMBOL_GPL(snd_soc_component_write); 63 64static int snd_soc_component_update_bits_legacy( 65 struct snd_soc_component *component, unsigned int reg, 66 unsigned int mask, unsigned int val, bool *change) 67{ 68 unsigned int old, new; 69 int ret; 70 71 if (!component->read || !component->write) 72 return -EIO; 73 74 mutex_lock(&component->io_mutex); 75 76 ret = component->read(component, reg, &old); 77 if (ret < 0) 78 goto out_unlock; 79 80 new = (old & ~mask) | (val & mask); 81 *change = old != new; 82 if (*change) 83 ret = component->write(component, reg, new); 84out_unlock: 85 mutex_unlock(&component->io_mutex); 86 87 return ret; 88} 89 90/** 91 * snd_soc_component_update_bits() - Perform read/modify/write cycle 92 * @component: Component to update 93 * @reg: Register to update 94 * @mask: Mask that specifies which bits to update 95 * @val: New value for the bits specified by mask 96 * 97 * Return: 1 if the operation was successful and the value of the register 98 * changed, 0 if the operation was successful, but the value did not change. 99 * Returns a negative error code otherwise. 100 */ 101int snd_soc_component_update_bits(struct snd_soc_component *component, 102 unsigned int reg, unsigned int mask, unsigned int val) 103{ 104 bool change; 105 int ret; 106 107 if (component->regmap) 108 ret = regmap_update_bits_check(component->regmap, reg, mask, 109 val, &change); 110 else 111 ret = snd_soc_component_update_bits_legacy(component, reg, 112 mask, val, &change); 113 114 if (ret < 0) 115 return ret; 116 return change; 117} 118EXPORT_SYMBOL_GPL(snd_soc_component_update_bits); 119 120/** 121 * snd_soc_component_update_bits_async() - Perform asynchronous 122 * read/modify/write cycle 123 * @component: Component to update 124 * @reg: Register to update 125 * @mask: Mask that specifies which bits to update 126 * @val: New value for the bits specified by mask 127 * 128 * This function is similar to snd_soc_component_update_bits(), but the update 129 * operation is scheduled asynchronously. This means it may not be completed 130 * when the function returns. To make sure that all scheduled updates have been 131 * completed snd_soc_component_async_complete() must be called. 132 * 133 * Return: 1 if the operation was successful and the value of the register 134 * changed, 0 if the operation was successful, but the value did not change. 135 * Returns a negative error code otherwise. 136 */ 137int snd_soc_component_update_bits_async(struct snd_soc_component *component, 138 unsigned int reg, unsigned int mask, unsigned int val) 139{ 140 bool change; 141 int ret; 142 143 if (component->regmap) 144 ret = regmap_update_bits_check_async(component->regmap, reg, 145 mask, val, &change); 146 else 147 ret = snd_soc_component_update_bits_legacy(component, reg, 148 mask, val, &change); 149 150 if (ret < 0) 151 return ret; 152 return change; 153} 154EXPORT_SYMBOL_GPL(snd_soc_component_update_bits_async); 155 156/** 157 * snd_soc_component_async_complete() - Ensure asynchronous I/O has completed 158 * @component: Component for which to wait 159 * 160 * This function blocks until all asynchronous I/O which has previously been 161 * scheduled using snd_soc_component_update_bits_async() has completed. 162 */ 163void snd_soc_component_async_complete(struct snd_soc_component *component) 164{ 165 if (component->regmap) 166 regmap_async_complete(component->regmap); 167} 168EXPORT_SYMBOL_GPL(snd_soc_component_async_complete); 169 170/** 171 * snd_soc_component_test_bits - Test register for change 172 * @component: component 173 * @reg: Register to test 174 * @mask: Mask that specifies which bits to test 175 * @value: Value to test against 176 * 177 * Tests a register with a new value and checks if the new value is 178 * different from the old value. 179 * 180 * Return: 1 for change, otherwise 0. 181 */ 182int snd_soc_component_test_bits(struct snd_soc_component *component, 183 unsigned int reg, unsigned int mask, unsigned int value) 184{ 185 unsigned int old, new; 186 int ret; 187 188 ret = snd_soc_component_read(component, reg, &old); 189 if (ret < 0) 190 return ret; 191 new = (old & ~mask) | value; 192 return old != new; 193} 194EXPORT_SYMBOL_GPL(snd_soc_component_test_bits); 195 196unsigned int snd_soc_read(struct snd_soc_codec *codec, unsigned int reg) 197{ 198 unsigned int val; 199 int ret; 200 201 ret = snd_soc_component_read(&codec->component, reg, &val); 202 if (ret < 0) 203 return -1; 204 205 return val; 206} 207EXPORT_SYMBOL_GPL(snd_soc_read); 208 209int snd_soc_write(struct snd_soc_codec *codec, unsigned int reg, 210 unsigned int val) 211{ 212 return snd_soc_component_write(&codec->component, reg, val); 213} 214EXPORT_SYMBOL_GPL(snd_soc_write); 215 216/** 217 * snd_soc_update_bits - update codec register bits 218 * @codec: audio codec 219 * @reg: codec register 220 * @mask: register mask 221 * @value: new value 222 * 223 * Writes new register value. 224 * 225 * Returns 1 for change, 0 for no change, or negative error code. 226 */ 227int snd_soc_update_bits(struct snd_soc_codec *codec, unsigned int reg, 228 unsigned int mask, unsigned int value) 229{ 230 return snd_soc_component_update_bits(&codec->component, reg, mask, 231 value); 232} 233EXPORT_SYMBOL_GPL(snd_soc_update_bits); 234 235/** 236 * snd_soc_test_bits - test register for change 237 * @codec: audio codec 238 * @reg: codec register 239 * @mask: register mask 240 * @value: new value 241 * 242 * Tests a register with a new value and checks if the new value is 243 * different from the old value. 244 * 245 * Returns 1 for change else 0. 246 */ 247int snd_soc_test_bits(struct snd_soc_codec *codec, unsigned int reg, 248 unsigned int mask, unsigned int value) 249{ 250 return snd_soc_component_test_bits(&codec->component, reg, mask, value); 251} 252EXPORT_SYMBOL_GPL(snd_soc_test_bits); 253 254int snd_soc_platform_read(struct snd_soc_platform *platform, 255 unsigned int reg) 256{ 257 unsigned int val; 258 int ret; 259 260 ret = snd_soc_component_read(&platform->component, reg, &val); 261 if (ret < 0) 262 return -1; 263 264 return val; 265} 266EXPORT_SYMBOL_GPL(snd_soc_platform_read); 267 268int snd_soc_platform_write(struct snd_soc_platform *platform, 269 unsigned int reg, unsigned int val) 270{ 271 return snd_soc_component_write(&platform->component, reg, val); 272} 273EXPORT_SYMBOL_GPL(snd_soc_platform_write); 274