Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

at v4.16 293 lines 7.9 kB view raw
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 if (component->driver->read) { 38 *val = component->driver->read(component, reg); 39 ret = 0; 40 } 41 else 42 ret = -EIO; 43 44 return ret; 45} 46EXPORT_SYMBOL_GPL(snd_soc_component_read); 47 48unsigned int snd_soc_component_read32(struct snd_soc_component *component, 49 unsigned int reg) 50{ 51 unsigned int val; 52 int ret; 53 54 ret = snd_soc_component_read(component, reg, &val); 55 if (ret < 0) 56 return -1; 57 58 return val; 59} 60EXPORT_SYMBOL_GPL(snd_soc_component_read32); 61 62/** 63 * snd_soc_component_write() - Write register value 64 * @component: Component to write to 65 * @reg: Register to write 66 * @val: Value to write to the register 67 * 68 * Return: 0 on success, a negative error code otherwise. 69 */ 70int snd_soc_component_write(struct snd_soc_component *component, 71 unsigned int reg, unsigned int val) 72{ 73 if (component->regmap) 74 return regmap_write(component->regmap, reg, val); 75 else if (component->write) 76 return component->write(component, reg, val); 77 else if (component->driver->write) 78 return component->driver->write(component, reg, val); 79 else 80 return -EIO; 81} 82EXPORT_SYMBOL_GPL(snd_soc_component_write); 83 84static int snd_soc_component_update_bits_legacy( 85 struct snd_soc_component *component, unsigned int reg, 86 unsigned int mask, unsigned int val, bool *change) 87{ 88 unsigned int old, new; 89 int ret; 90 91 if (!component->read || !component->write) 92 return -EIO; 93 94 mutex_lock(&component->io_mutex); 95 96 ret = component->read(component, reg, &old); 97 if (ret < 0) 98 goto out_unlock; 99 100 new = (old & ~mask) | (val & mask); 101 *change = old != new; 102 if (*change) 103 ret = component->write(component, reg, new); 104out_unlock: 105 mutex_unlock(&component->io_mutex); 106 107 return ret; 108} 109 110/** 111 * snd_soc_component_update_bits() - Perform read/modify/write cycle 112 * @component: Component to update 113 * @reg: Register to update 114 * @mask: Mask that specifies which bits to update 115 * @val: New value for the bits specified by mask 116 * 117 * Return: 1 if the operation was successful and the value of the register 118 * changed, 0 if the operation was successful, but the value did not change. 119 * Returns a negative error code otherwise. 120 */ 121int snd_soc_component_update_bits(struct snd_soc_component *component, 122 unsigned int reg, unsigned int mask, unsigned int val) 123{ 124 bool change; 125 int ret; 126 127 if (component->regmap) 128 ret = regmap_update_bits_check(component->regmap, reg, mask, 129 val, &change); 130 else 131 ret = snd_soc_component_update_bits_legacy(component, reg, 132 mask, val, &change); 133 134 if (ret < 0) 135 return ret; 136 return change; 137} 138EXPORT_SYMBOL_GPL(snd_soc_component_update_bits); 139 140/** 141 * snd_soc_component_update_bits_async() - Perform asynchronous 142 * read/modify/write cycle 143 * @component: Component to update 144 * @reg: Register to update 145 * @mask: Mask that specifies which bits to update 146 * @val: New value for the bits specified by mask 147 * 148 * This function is similar to snd_soc_component_update_bits(), but the update 149 * operation is scheduled asynchronously. This means it may not be completed 150 * when the function returns. To make sure that all scheduled updates have been 151 * completed snd_soc_component_async_complete() must be called. 152 * 153 * Return: 1 if the operation was successful and the value of the register 154 * changed, 0 if the operation was successful, but the value did not change. 155 * Returns a negative error code otherwise. 156 */ 157int snd_soc_component_update_bits_async(struct snd_soc_component *component, 158 unsigned int reg, unsigned int mask, unsigned int val) 159{ 160 bool change; 161 int ret; 162 163 if (component->regmap) 164 ret = regmap_update_bits_check_async(component->regmap, reg, 165 mask, val, &change); 166 else 167 ret = snd_soc_component_update_bits_legacy(component, reg, 168 mask, val, &change); 169 170 if (ret < 0) 171 return ret; 172 return change; 173} 174EXPORT_SYMBOL_GPL(snd_soc_component_update_bits_async); 175 176/** 177 * snd_soc_component_async_complete() - Ensure asynchronous I/O has completed 178 * @component: Component for which to wait 179 * 180 * This function blocks until all asynchronous I/O which has previously been 181 * scheduled using snd_soc_component_update_bits_async() has completed. 182 */ 183void snd_soc_component_async_complete(struct snd_soc_component *component) 184{ 185 if (component->regmap) 186 regmap_async_complete(component->regmap); 187} 188EXPORT_SYMBOL_GPL(snd_soc_component_async_complete); 189 190/** 191 * snd_soc_component_test_bits - Test register for change 192 * @component: component 193 * @reg: Register to test 194 * @mask: Mask that specifies which bits to test 195 * @value: Value to test against 196 * 197 * Tests a register with a new value and checks if the new value is 198 * different from the old value. 199 * 200 * Return: 1 for change, otherwise 0. 201 */ 202int snd_soc_component_test_bits(struct snd_soc_component *component, 203 unsigned int reg, unsigned int mask, unsigned int value) 204{ 205 unsigned int old, new; 206 int ret; 207 208 ret = snd_soc_component_read(component, reg, &old); 209 if (ret < 0) 210 return ret; 211 new = (old & ~mask) | value; 212 return old != new; 213} 214EXPORT_SYMBOL_GPL(snd_soc_component_test_bits); 215 216unsigned int snd_soc_read(struct snd_soc_codec *codec, unsigned int reg) 217{ 218 unsigned int val; 219 int ret; 220 221 ret = snd_soc_component_read(&codec->component, reg, &val); 222 if (ret < 0) 223 return -1; 224 225 return val; 226} 227EXPORT_SYMBOL_GPL(snd_soc_read); 228 229int snd_soc_write(struct snd_soc_codec *codec, unsigned int reg, 230 unsigned int val) 231{ 232 return snd_soc_component_write(&codec->component, reg, val); 233} 234EXPORT_SYMBOL_GPL(snd_soc_write); 235 236/** 237 * snd_soc_update_bits - update codec register bits 238 * @codec: audio codec 239 * @reg: codec register 240 * @mask: register mask 241 * @value: new value 242 * 243 * Writes new register value. 244 * 245 * Returns 1 for change, 0 for no change, or negative error code. 246 */ 247int snd_soc_update_bits(struct snd_soc_codec *codec, unsigned int reg, 248 unsigned int mask, unsigned int value) 249{ 250 return snd_soc_component_update_bits(&codec->component, reg, mask, 251 value); 252} 253EXPORT_SYMBOL_GPL(snd_soc_update_bits); 254 255/** 256 * snd_soc_test_bits - test register for change 257 * @codec: audio codec 258 * @reg: codec register 259 * @mask: register mask 260 * @value: new value 261 * 262 * Tests a register with a new value and checks if the new value is 263 * different from the old value. 264 * 265 * Returns 1 for change else 0. 266 */ 267int snd_soc_test_bits(struct snd_soc_codec *codec, unsigned int reg, 268 unsigned int mask, unsigned int value) 269{ 270 return snd_soc_component_test_bits(&codec->component, reg, mask, value); 271} 272EXPORT_SYMBOL_GPL(snd_soc_test_bits); 273 274int snd_soc_platform_read(struct snd_soc_platform *platform, 275 unsigned int reg) 276{ 277 unsigned int val; 278 int ret; 279 280 ret = snd_soc_component_read(&platform->component, reg, &val); 281 if (ret < 0) 282 return -1; 283 284 return val; 285} 286EXPORT_SYMBOL_GPL(snd_soc_platform_read); 287 288int snd_soc_platform_write(struct snd_soc_platform *platform, 289 unsigned int reg, unsigned int val) 290{ 291 return snd_soc_component_write(&platform->component, reg, val); 292} 293EXPORT_SYMBOL_GPL(snd_soc_platform_write);