ASoC: Use new register map API for ASoC generic physical I/O
[deliverable/linux.git] / sound / soc / soc-io.c
CommitLineData
5bef44f9
MB
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>
be3ea3b9 16#include <linux/regmap.h>
5bef44f9
MB
17#include <sound/soc.h>
18
19#include <trace/events/asoc.h>
20
be3ea3b9
MB
21static int hw_write(struct snd_soc_codec *codec, unsigned int reg,
22 unsigned int value)
5bef44f9
MB
23{
24 int ret;
25
26 if (!snd_soc_codec_volatile_register(codec, reg) &&
27 reg < codec->driver->reg_cache_size &&
28 !codec->cache_bypass) {
29 ret = snd_soc_cache_write(codec, reg, value);
30 if (ret < 0)
31 return -1;
32 }
33
34 if (codec->cache_only) {
35 codec->cache_sync = 1;
36 return 0;
37 }
38
be3ea3b9 39 return regmap_write(codec->control_data, reg, value);
5bef44f9
MB
40}
41
42static unsigned int hw_read(struct snd_soc_codec *codec, unsigned int reg)
43{
44 int ret;
45 unsigned int val;
46
47 if (reg >= codec->driver->reg_cache_size ||
48 snd_soc_codec_volatile_register(codec, reg) ||
49 codec->cache_bypass) {
50 if (codec->cache_only)
51 return -1;
52
be3ea3b9
MB
53 ret = regmap_read(codec->control_data, reg, &val);
54 if (ret == 0)
55 return val;
56 else
57 return ret;
5bef44f9
MB
58 }
59
60 ret = snd_soc_cache_read(codec, reg, &val);
61 if (ret < 0)
62 return -1;
63 return val;
64}
65
5bef44f9 66/* Primitive bulk write support for soc-cache. The data pointed to by
be3ea3b9
MB
67 * `data' needs to already be in the form the hardware expects. Any
68 * data written through this function will not go through the cache as
69 * it only handles writing to volatile or out of bounds registers.
70 *
71 * This is currently only supported for devices using the regmap API
72 * wrappers.
5bef44f9 73 */
be3ea3b9
MB
74static int snd_soc_hw_bulk_write_raw(struct snd_soc_codec *codec,
75 unsigned int reg,
5bef44f9
MB
76 const void *data, size_t len)
77{
5bef44f9
MB
78 /* To ensure that we don't get out of sync with the cache, check
79 * whether the base register is volatile or if we've directly asked
80 * to bypass the cache. Out of bounds registers are considered
81 * volatile.
82 */
83 if (!codec->cache_bypass
84 && !snd_soc_codec_volatile_register(codec, reg)
85 && reg < codec->driver->reg_cache_size)
86 return -EINVAL;
87
be3ea3b9 88 return regmap_raw_write(codec->control_data, reg, data, len);
5bef44f9
MB
89}
90
5bef44f9
MB
91/**
92 * snd_soc_codec_set_cache_io: Set up standard I/O functions.
93 *
94 * @codec: CODEC to configure.
95 * @addr_bits: Number of bits of register address data.
96 * @data_bits: Number of bits of data per register.
97 * @control: Control bus used.
98 *
99 * Register formats are frequently shared between many I2C and SPI
100 * devices. In order to promote code reuse the ASoC core provides
101 * some standard implementations of CODEC read and write operations
102 * which can be set up using this function.
103 *
104 * The caller is responsible for allocating and initialising the
105 * actual cache.
106 *
107 * Note that at present this code cannot be used by CODECs with
108 * volatile registers.
109 */
110int snd_soc_codec_set_cache_io(struct snd_soc_codec *codec,
111 int addr_bits, int data_bits,
112 enum snd_soc_control_type control)
113{
be3ea3b9 114 struct regmap_config config;
5bef44f9 115
be3ea3b9
MB
116 memset(&config, 0, sizeof(config));
117 codec->write = hw_write;
5bef44f9
MB
118 codec->read = hw_read;
119 codec->bulk_write_raw = snd_soc_hw_bulk_write_raw;
120
be3ea3b9
MB
121 config.reg_bits = addr_bits;
122 config.val_bits = data_bits;
123
5bef44f9 124 switch (control) {
5bef44f9 125 case SND_SOC_I2C:
be3ea3b9
MB
126 codec->control_data = regmap_init_i2c(to_i2c_client(codec->dev),
127 &config);
5bef44f9
MB
128 break;
129
130 case SND_SOC_SPI:
be3ea3b9
MB
131 codec->control_data = regmap_init_spi(to_spi_device(codec->dev),
132 &config);
5bef44f9 133 break;
be3ea3b9
MB
134
135 default:
136 return -EINVAL;
5bef44f9
MB
137 }
138
be3ea3b9
MB
139 if (IS_ERR(codec->control_data))
140 return PTR_ERR(codec->control_data);
141
5bef44f9
MB
142 return 0;
143}
144EXPORT_SYMBOL_GPL(snd_soc_codec_set_cache_io);
145
This page took 0.038861 seconds and 5 git commands to generate.