blob: ab058b81163304ce599c4c1b5c1664db24dc0c8e [file] [log] [blame]
Mark Brown17a52fd2009-07-05 17:24:50 +01001/*
2 * soc-cache.c -- ASoC register cache helpers
3 *
4 * Copyright 2009 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
Mark Brown7084a422009-07-10 22:24:27 +010014#include <linux/i2c.h>
Mark Brown17a52fd2009-07-05 17:24:50 +010015#include <sound/soc.h>
16
17static unsigned int snd_soc_7_9_read(struct snd_soc_codec *codec,
18 unsigned int reg)
19{
20 u16 *cache = codec->reg_cache;
21 if (reg >= codec->reg_cache_size)
22 return -1;
23 return cache[reg];
24}
25
26static int snd_soc_7_9_write(struct snd_soc_codec *codec, unsigned int reg,
27 unsigned int value)
28{
29 u16 *cache = codec->reg_cache;
30 u8 data[2];
31 int ret;
32
33 BUG_ON(codec->volatile_register);
34
35 data[0] = (reg << 1) | ((value >> 8) & 0x0001);
36 data[1] = value & 0x00ff;
37
38 if (reg < codec->reg_cache_size)
39 cache[reg] = value;
40 ret = codec->hw_write(codec->control_data, data, 2);
41 if (ret == 2)
42 return 0;
43 if (ret < 0)
44 return ret;
45 else
46 return -EIO;
47}
48
Mark Brownafa2f102009-07-10 23:11:24 +010049static int snd_soc_8_16_write(struct snd_soc_codec *codec, unsigned int reg,
50 unsigned int value)
51{
52 u16 *reg_cache = codec->reg_cache;
53 u8 data[3];
54
55 data[0] = reg;
56 data[1] = (value >> 8) & 0xff;
57 data[2] = value & 0xff;
58
59 if (!snd_soc_codec_volatile_register(codec, reg))
60 reg_cache[reg] = value;
61
62 if (codec->hw_write(codec->control_data, data, 3) == 3)
63 return 0;
64 else
65 return -EIO;
66}
67
68static unsigned int snd_soc_8_16_read(struct snd_soc_codec *codec,
69 unsigned int reg)
70{
71 u16 *cache = codec->reg_cache;
72
73 if (reg >= codec->reg_cache_size ||
74 snd_soc_codec_volatile_register(codec, reg))
75 return codec->hw_read(codec, reg);
76 else
77 return cache[reg];
78}
79
80#if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE)
81static unsigned int snd_soc_8_16_read_i2c(struct snd_soc_codec *codec,
82 unsigned int r)
83{
84 struct i2c_msg xfer[2];
85 u8 reg = r;
86 u16 data;
87 int ret;
88 struct i2c_client *client = codec->control_data;
89
90 /* Write register */
91 xfer[0].addr = client->addr;
92 xfer[0].flags = 0;
93 xfer[0].len = 1;
94 xfer[0].buf = &reg;
95
96 /* Read data */
97 xfer[1].addr = client->addr;
98 xfer[1].flags = I2C_M_RD;
99 xfer[1].len = 2;
100 xfer[1].buf = (u8 *)&data;
101
102 ret = i2c_transfer(client->adapter, xfer, 2);
103 if (ret != 2) {
104 dev_err(&client->dev, "i2c_transfer() returned %d\n", ret);
105 return 0;
106 }
107
108 return (data >> 8) | ((data & 0xff) << 8);
109}
110#else
111#define snd_soc_8_16_read_i2c NULL
112#endif
Mark Brown17a52fd2009-07-05 17:24:50 +0100113
114static struct {
115 int addr_bits;
116 int data_bits;
Mark Brownafa2f102009-07-10 23:11:24 +0100117 int (*write)(struct snd_soc_codec *codec, unsigned int, unsigned int);
Mark Brown17a52fd2009-07-05 17:24:50 +0100118 unsigned int (*read)(struct snd_soc_codec *, unsigned int);
Mark Brownafa2f102009-07-10 23:11:24 +0100119 unsigned int (*i2c_read)(struct snd_soc_codec *, unsigned int);
Mark Brown17a52fd2009-07-05 17:24:50 +0100120} io_types[] = {
121 { 7, 9, snd_soc_7_9_write, snd_soc_7_9_read },
Mark Brownafa2f102009-07-10 23:11:24 +0100122 { 8, 16,
123 snd_soc_8_16_write, snd_soc_8_16_read,
124 snd_soc_8_16_read_i2c },
Mark Brown17a52fd2009-07-05 17:24:50 +0100125};
126
127/**
128 * snd_soc_codec_set_cache_io: Set up standard I/O functions.
129 *
130 * @codec: CODEC to configure.
131 * @type: Type of cache.
132 * @addr_bits: Number of bits of register address data.
133 * @data_bits: Number of bits of data per register.
Mark Brown7084a422009-07-10 22:24:27 +0100134 * @control: Control bus used.
Mark Brown17a52fd2009-07-05 17:24:50 +0100135 *
136 * Register formats are frequently shared between many I2C and SPI
137 * devices. In order to promote code reuse the ASoC core provides
138 * some standard implementations of CODEC read and write operations
139 * which can be set up using this function.
140 *
141 * The caller is responsible for allocating and initialising the
142 * actual cache.
143 *
144 * Note that at present this code cannot be used by CODECs with
145 * volatile registers.
146 */
147int snd_soc_codec_set_cache_io(struct snd_soc_codec *codec,
Mark Brown7084a422009-07-10 22:24:27 +0100148 int addr_bits, int data_bits,
149 enum snd_soc_control_type control)
Mark Brown17a52fd2009-07-05 17:24:50 +0100150{
151 int i;
152
Mark Brown17a52fd2009-07-05 17:24:50 +0100153 for (i = 0; i < ARRAY_SIZE(io_types); i++)
154 if (io_types[i].addr_bits == addr_bits &&
155 io_types[i].data_bits == data_bits)
156 break;
157 if (i == ARRAY_SIZE(io_types)) {
158 printk(KERN_ERR
159 "No I/O functions for %d bit address %d bit data\n",
160 addr_bits, data_bits);
161 return -EINVAL;
162 }
163
164 codec->write = io_types[i].write;
165 codec->read = io_types[i].read;
166
Mark Brown7084a422009-07-10 22:24:27 +0100167 switch (control) {
168 case SND_SOC_CUSTOM:
169 break;
170
171 case SND_SOC_I2C:
172#if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE)
173 codec->hw_write = (hw_write_t)i2c_master_send;
174#endif
Mark Brownafa2f102009-07-10 23:11:24 +0100175 if (io_types[i].i2c_read)
176 codec->hw_read = io_types[i].i2c_read;
Mark Brown7084a422009-07-10 22:24:27 +0100177 break;
178
179 case SND_SOC_SPI:
180 break;
181 }
182
Mark Brown17a52fd2009-07-05 17:24:50 +0100183 return 0;
184}
185EXPORT_SYMBOL_GPL(snd_soc_codec_set_cache_io);