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#include <trace/events/asoc.h>
  21
  22#ifdef CONFIG_REGMAP
  23static int hw_write(struct snd_soc_codec *codec, unsigned int reg,
  24                    unsigned int value)
  25{
  26        int ret;
  27
  28        if (!snd_soc_codec_volatile_register(codec, reg) &&
  29            reg < codec->driver->reg_cache_size &&
  30            !codec->cache_bypass) {
  31                ret = snd_soc_cache_write(codec, reg, value);
  32                if (ret < 0)
  33                        return -1;
  34        }
  35
  36        if (codec->cache_only) {
  37                codec->cache_sync = 1;
  38                return 0;
  39        }
  40
  41        return regmap_write(codec->control_data, reg, value);
  42}
  43
  44static unsigned int hw_read(struct snd_soc_codec *codec, unsigned int reg)
  45{
  46        int ret;
  47        unsigned int val;
  48
  49        if (reg >= codec->driver->reg_cache_size ||
  50            snd_soc_codec_volatile_register(codec, reg) ||
  51            codec->cache_bypass) {
  52                if (codec->cache_only)
  53                        return -1;
  54
  55                ret = regmap_read(codec->control_data, reg, &val);
  56                if (ret == 0)
  57                        return val;
  58                else
  59                        return -1;
  60        }
  61
  62        ret = snd_soc_cache_read(codec, reg, &val);
  63        if (ret < 0)
  64                return -1;
  65        return val;
  66}
  67
  68/* Primitive bulk write support for soc-cache.  The data pointed to by
  69 * `data' needs to already be in the form the hardware expects.  Any
  70 * data written through this function will not go through the cache as
  71 * it only handles writing to volatile or out of bounds registers.
  72 *
  73 * This is currently only supported for devices using the regmap API
  74 * wrappers.
  75 */
  76static int snd_soc_hw_bulk_write_raw(struct snd_soc_codec *codec,
  77                                     unsigned int reg,
  78                                     const void *data, size_t len)
  79{
  80        /* To ensure that we don't get out of sync with the cache, check
  81         * whether the base register is volatile or if we've directly asked
  82         * to bypass the cache.  Out of bounds registers are considered
  83         * volatile.
  84         */
  85        if (!codec->cache_bypass
  86            && !snd_soc_codec_volatile_register(codec, reg)
  87            && reg < codec->driver->reg_cache_size)
  88                return -EINVAL;
  89
  90        return regmap_raw_write(codec->control_data, reg, data, len);
  91}
  92
  93/**
  94 * snd_soc_codec_set_cache_io: Set up standard I/O functions.
  95 *
  96 * @codec: CODEC to configure.
  97 * @addr_bits: Number of bits of register address data.
  98 * @data_bits: Number of bits of data per register.
  99 * @control: Control bus used.
 100 *
 101 * Register formats are frequently shared between many I2C and SPI
 102 * devices.  In order to promote code reuse the ASoC core provides
 103 * some standard implementations of CODEC read and write operations
 104 * which can be set up using this function.
 105 *
 106 * The caller is responsible for allocating and initialising the
 107 * actual cache.
 108 *
 109 * Note that at present this code cannot be used by CODECs with
 110 * volatile registers.
 111 */
 112int snd_soc_codec_set_cache_io(struct snd_soc_codec *codec,
 113                               int addr_bits, int data_bits,
 114                               enum snd_soc_control_type control)
 115{
 116        struct regmap_config config;
 117        int ret;
 118
 119        memset(&config, 0, sizeof(config));
 120        codec->write = hw_write;
 121        codec->read = hw_read;
 122        codec->bulk_write_raw = snd_soc_hw_bulk_write_raw;
 123
 124        config.reg_bits = addr_bits;
 125        config.val_bits = data_bits;
 126
 127        switch (control) {
 128#if defined(CONFIG_REGMAP_I2C) || defined(CONFIG_REGMAP_I2C_MODULE)
 129        case SND_SOC_I2C:
 130                codec->control_data = regmap_init_i2c(to_i2c_client(codec->dev),
 131                                                      &config);
 132                break;
 133#endif
 134
 135#if defined(CONFIG_REGMAP_SPI) || defined(CONFIG_REGMAP_SPI_MODULE)
 136        case SND_SOC_SPI:
 137                codec->control_data = regmap_init_spi(to_spi_device(codec->dev),
 138                                                      &config);
 139                break;
 140#endif
 141
 142        case SND_SOC_REGMAP:
 143                /* Device has made its own regmap arrangements */
 144                codec->using_regmap = true;
 145                if (!codec->control_data)
 146                        codec->control_data = dev_get_regmap(codec->dev, NULL);
 147
 148                if (codec->control_data) {
 149                        ret = regmap_get_val_bytes(codec->control_data);
 150                        /* Errors are legitimate for non-integer byte
 151                         * multiples */
 152                        if (ret > 0)
 153                                codec->val_bytes = ret;
 154                }
 155                break;
 156
 157        default:
 158                return -EINVAL;
 159        }
 160
 161        if (IS_ERR(codec->control_data))
 162                return PTR_ERR(codec->control_data);
 163
 164        return 0;
 165}
 166EXPORT_SYMBOL_GPL(snd_soc_codec_set_cache_io);
 167#else
 168int snd_soc_codec_set_cache_io(struct snd_soc_codec *codec,
 169                               int addr_bits, int data_bits,
 170                               enum snd_soc_control_type control)
 171{
 172        return -ENOTSUPP;
 173}
 174EXPORT_SYMBOL_GPL(snd_soc_codec_set_cache_io);
 175#endif
 176
lxr.linux.no kindly hosted by Redpill Linpro AS, provider of Linux consulting and operations services since 1995.