linux/sound/soc/soc-io.c
<<
>>
Prefs
   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