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 v5.6 202 lines 5.6 kB view raw
1// SPDX-License-Identifier: GPL-2.0+ 2// 3// soc-io.c -- ASoC register I/O helpers 4// 5// Copyright 2009-2011 Wolfson Microelectronics PLC. 6// 7// Author: Mark Brown <broonie@opensource.wolfsonmicro.com> 8 9#include <linux/i2c.h> 10#include <linux/spi/spi.h> 11#include <linux/regmap.h> 12#include <linux/export.h> 13#include <sound/soc.h> 14 15/** 16 * snd_soc_component_read() - Read register value 17 * @component: Component to read from 18 * @reg: Register to read 19 * @val: Pointer to where the read value is stored 20 * 21 * Return: 0 on success, a negative error code otherwise. 22 */ 23int snd_soc_component_read(struct snd_soc_component *component, 24 unsigned int reg, unsigned int *val) 25{ 26 int ret; 27 28 if (component->regmap) 29 ret = regmap_read(component->regmap, reg, val); 30 else if (component->driver->read) { 31 *val = component->driver->read(component, reg); 32 ret = 0; 33 } 34 else 35 ret = -EIO; 36 37 return ret; 38} 39EXPORT_SYMBOL_GPL(snd_soc_component_read); 40 41unsigned int snd_soc_component_read32(struct snd_soc_component *component, 42 unsigned int reg) 43{ 44 unsigned int val; 45 int ret; 46 47 ret = snd_soc_component_read(component, reg, &val); 48 if (ret < 0) 49 return -1; 50 51 return val; 52} 53EXPORT_SYMBOL_GPL(snd_soc_component_read32); 54 55/** 56 * snd_soc_component_write() - Write register value 57 * @component: Component to write to 58 * @reg: Register to write 59 * @val: Value to write to the register 60 * 61 * Return: 0 on success, a negative error code otherwise. 62 */ 63int snd_soc_component_write(struct snd_soc_component *component, 64 unsigned int reg, unsigned int val) 65{ 66 if (component->regmap) 67 return regmap_write(component->regmap, reg, val); 68 else if (component->driver->write) 69 return component->driver->write(component, reg, val); 70 else 71 return -EIO; 72} 73EXPORT_SYMBOL_GPL(snd_soc_component_write); 74 75static int snd_soc_component_update_bits_legacy( 76 struct snd_soc_component *component, unsigned int reg, 77 unsigned int mask, unsigned int val, bool *change) 78{ 79 unsigned int old, new; 80 int ret; 81 82 mutex_lock(&component->io_mutex); 83 84 ret = snd_soc_component_read(component, reg, &old); 85 if (ret < 0) 86 goto out_unlock; 87 88 new = (old & ~mask) | (val & mask); 89 *change = old != new; 90 if (*change) 91 ret = snd_soc_component_write(component, reg, new); 92out_unlock: 93 mutex_unlock(&component->io_mutex); 94 95 return ret; 96} 97 98/** 99 * snd_soc_component_update_bits() - Perform read/modify/write cycle 100 * @component: Component to update 101 * @reg: Register to update 102 * @mask: Mask that specifies which bits to update 103 * @val: New value for the bits specified by mask 104 * 105 * Return: 1 if the operation was successful and the value of the register 106 * changed, 0 if the operation was successful, but the value did not change. 107 * Returns a negative error code otherwise. 108 */ 109int snd_soc_component_update_bits(struct snd_soc_component *component, 110 unsigned int reg, unsigned int mask, unsigned int val) 111{ 112 bool change; 113 int ret; 114 115 if (component->regmap) 116 ret = regmap_update_bits_check(component->regmap, reg, mask, 117 val, &change); 118 else 119 ret = snd_soc_component_update_bits_legacy(component, reg, 120 mask, val, &change); 121 122 if (ret < 0) 123 return ret; 124 return change; 125} 126EXPORT_SYMBOL_GPL(snd_soc_component_update_bits); 127 128/** 129 * snd_soc_component_update_bits_async() - Perform asynchronous 130 * read/modify/write cycle 131 * @component: Component to update 132 * @reg: Register to update 133 * @mask: Mask that specifies which bits to update 134 * @val: New value for the bits specified by mask 135 * 136 * This function is similar to snd_soc_component_update_bits(), but the update 137 * operation is scheduled asynchronously. This means it may not be completed 138 * when the function returns. To make sure that all scheduled updates have been 139 * completed snd_soc_component_async_complete() must be called. 140 * 141 * Return: 1 if the operation was successful and the value of the register 142 * changed, 0 if the operation was successful, but the value did not change. 143 * Returns a negative error code otherwise. 144 */ 145int snd_soc_component_update_bits_async(struct snd_soc_component *component, 146 unsigned int reg, unsigned int mask, unsigned int val) 147{ 148 bool change; 149 int ret; 150 151 if (component->regmap) 152 ret = regmap_update_bits_check_async(component->regmap, reg, 153 mask, val, &change); 154 else 155 ret = snd_soc_component_update_bits_legacy(component, reg, 156 mask, val, &change); 157 158 if (ret < 0) 159 return ret; 160 return change; 161} 162EXPORT_SYMBOL_GPL(snd_soc_component_update_bits_async); 163 164/** 165 * snd_soc_component_async_complete() - Ensure asynchronous I/O has completed 166 * @component: Component for which to wait 167 * 168 * This function blocks until all asynchronous I/O which has previously been 169 * scheduled using snd_soc_component_update_bits_async() has completed. 170 */ 171void snd_soc_component_async_complete(struct snd_soc_component *component) 172{ 173 if (component->regmap) 174 regmap_async_complete(component->regmap); 175} 176EXPORT_SYMBOL_GPL(snd_soc_component_async_complete); 177 178/** 179 * snd_soc_component_test_bits - Test register for change 180 * @component: component 181 * @reg: Register to test 182 * @mask: Mask that specifies which bits to test 183 * @value: Value to test against 184 * 185 * Tests a register with a new value and checks if the new value is 186 * different from the old value. 187 * 188 * Return: 1 for change, otherwise 0. 189 */ 190int snd_soc_component_test_bits(struct snd_soc_component *component, 191 unsigned int reg, unsigned int mask, unsigned int value) 192{ 193 unsigned int old, new; 194 int ret; 195 196 ret = snd_soc_component_read(component, reg, &old); 197 if (ret < 0) 198 return ret; 199 new = (old & ~mask) | value; 200 return old != new; 201} 202EXPORT_SYMBOL_GPL(snd_soc_component_test_bits);