Merge branch 'topic/core-cleanup' into for-linus
[safe/jmp/linux-2.6] / sound / soc / soc-cache.c
1 /*
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
14 #include <linux/i2c.h>
15 #include <linux/spi/spi.h>
16 #include <sound/soc.h>
17
18 static unsigned int snd_soc_4_12_read(struct snd_soc_codec *codec,
19                                      unsigned int reg)
20 {
21         u16 *cache = codec->reg_cache;
22         if (reg >= codec->reg_cache_size)
23                 return -1;
24         return cache[reg];
25 }
26
27 static int snd_soc_4_12_write(struct snd_soc_codec *codec, unsigned int reg,
28                              unsigned int value)
29 {
30         u16 *cache = codec->reg_cache;
31         u8 data[2];
32         int ret;
33
34         BUG_ON(codec->volatile_register);
35
36         data[0] = (reg << 4) | ((value >> 8) & 0x000f);
37         data[1] = value & 0x00ff;
38
39         if (reg < codec->reg_cache_size)
40                 cache[reg] = value;
41
42         if (codec->cache_only) {
43                 codec->cache_sync = 1;
44                 return 0;
45         }
46
47         ret = codec->hw_write(codec->control_data, data, 2);
48         if (ret == 2)
49                 return 0;
50         if (ret < 0)
51                 return ret;
52         else
53                 return -EIO;
54 }
55
56 #if defined(CONFIG_SPI_MASTER)
57 static int snd_soc_4_12_spi_write(void *control_data, const char *data,
58                                  int len)
59 {
60         struct spi_device *spi = control_data;
61         struct spi_transfer t;
62         struct spi_message m;
63         u8 msg[2];
64
65         if (len <= 0)
66                 return 0;
67
68         msg[0] = data[1];
69         msg[1] = data[0];
70
71         spi_message_init(&m);
72         memset(&t, 0, (sizeof t));
73
74         t.tx_buf = &msg[0];
75         t.len = len;
76
77         spi_message_add_tail(&t, &m);
78         spi_sync(spi, &m);
79
80         return len;
81 }
82 #else
83 #define snd_soc_4_12_spi_write NULL
84 #endif
85
86 static unsigned int snd_soc_7_9_read(struct snd_soc_codec *codec,
87                                      unsigned int reg)
88 {
89         u16 *cache = codec->reg_cache;
90         if (reg >= codec->reg_cache_size)
91                 return -1;
92         return cache[reg];
93 }
94
95 static int snd_soc_7_9_write(struct snd_soc_codec *codec, unsigned int reg,
96                              unsigned int value)
97 {
98         u16 *cache = codec->reg_cache;
99         u8 data[2];
100         int ret;
101
102         BUG_ON(codec->volatile_register);
103
104         data[0] = (reg << 1) | ((value >> 8) & 0x0001);
105         data[1] = value & 0x00ff;
106
107         if (reg < codec->reg_cache_size)
108                 cache[reg] = value;
109
110         if (codec->cache_only) {
111                 codec->cache_sync = 1;
112                 return 0;
113         }
114
115         ret = codec->hw_write(codec->control_data, data, 2);
116         if (ret == 2)
117                 return 0;
118         if (ret < 0)
119                 return ret;
120         else
121                 return -EIO;
122 }
123
124 #if defined(CONFIG_SPI_MASTER)
125 static int snd_soc_7_9_spi_write(void *control_data, const char *data,
126                                  int len)
127 {
128         struct spi_device *spi = control_data;
129         struct spi_transfer t;
130         struct spi_message m;
131         u8 msg[2];
132
133         if (len <= 0)
134                 return 0;
135
136         msg[0] = data[0];
137         msg[1] = data[1];
138
139         spi_message_init(&m);
140         memset(&t, 0, (sizeof t));
141
142         t.tx_buf = &msg[0];
143         t.len = len;
144
145         spi_message_add_tail(&t, &m);
146         spi_sync(spi, &m);
147
148         return len;
149 }
150 #else
151 #define snd_soc_7_9_spi_write NULL
152 #endif
153
154 static int snd_soc_8_8_write(struct snd_soc_codec *codec, unsigned int reg,
155                              unsigned int value)
156 {
157         u8 *cache = codec->reg_cache;
158         u8 data[2];
159
160         BUG_ON(codec->volatile_register);
161
162         data[0] = reg & 0xff;
163         data[1] = value & 0xff;
164
165         if (reg < codec->reg_cache_size)
166                 cache[reg] = value;
167
168         if (codec->cache_only) {
169                 codec->cache_sync = 1;
170                 return 0;
171         }
172
173         if (codec->hw_write(codec->control_data, data, 2) == 2)
174                 return 0;
175         else
176                 return -EIO;
177 }
178
179 static unsigned int snd_soc_8_8_read(struct snd_soc_codec *codec,
180                                      unsigned int reg)
181 {
182         u8 *cache = codec->reg_cache;
183         if (reg >= codec->reg_cache_size)
184                 return -1;
185         return cache[reg];
186 }
187
188 static int snd_soc_8_16_write(struct snd_soc_codec *codec, unsigned int reg,
189                               unsigned int value)
190 {
191         u16 *reg_cache = codec->reg_cache;
192         u8 data[3];
193
194         data[0] = reg;
195         data[1] = (value >> 8) & 0xff;
196         data[2] = value & 0xff;
197
198         if (!snd_soc_codec_volatile_register(codec, reg))
199                 reg_cache[reg] = value;
200
201         if (codec->cache_only) {
202                 codec->cache_sync = 1;
203                 return 0;
204         }
205
206         if (codec->hw_write(codec->control_data, data, 3) == 3)
207                 return 0;
208         else
209                 return -EIO;
210 }
211
212 static unsigned int snd_soc_8_16_read(struct snd_soc_codec *codec,
213                                       unsigned int reg)
214 {
215         u16 *cache = codec->reg_cache;
216
217         if (reg >= codec->reg_cache_size ||
218             snd_soc_codec_volatile_register(codec, reg)) {
219                 if (codec->cache_only)
220                         return -EINVAL;
221
222                 return codec->hw_read(codec, reg);
223         } else {
224                 return cache[reg];
225         }
226 }
227
228 #if defined(CONFIG_I2C) || (defined(CONFIG_I2C_MODULE) && defined(MODULE))
229 static unsigned int snd_soc_8_16_read_i2c(struct snd_soc_codec *codec,
230                                           unsigned int r)
231 {
232         struct i2c_msg xfer[2];
233         u8 reg = r;
234         u16 data;
235         int ret;
236         struct i2c_client *client = codec->control_data;
237
238         /* Write register */
239         xfer[0].addr = client->addr;
240         xfer[0].flags = 0;
241         xfer[0].len = 1;
242         xfer[0].buf = &reg;
243
244         /* Read data */
245         xfer[1].addr = client->addr;
246         xfer[1].flags = I2C_M_RD;
247         xfer[1].len = 2;
248         xfer[1].buf = (u8 *)&data;
249
250         ret = i2c_transfer(client->adapter, xfer, 2);
251         if (ret != 2) {
252                 dev_err(&client->dev, "i2c_transfer() returned %d\n", ret);
253                 return 0;
254         }
255
256         return (data >> 8) | ((data & 0xff) << 8);
257 }
258 #else
259 #define snd_soc_8_16_read_i2c NULL
260 #endif
261
262 #if defined(CONFIG_I2C) || (defined(CONFIG_I2C_MODULE) && defined(MODULE))
263 static unsigned int snd_soc_16_8_read_i2c(struct snd_soc_codec *codec,
264                                           unsigned int r)
265 {
266         struct i2c_msg xfer[2];
267         u16 reg = r;
268         u8 data;
269         int ret;
270         struct i2c_client *client = codec->control_data;
271
272         /* Write register */
273         xfer[0].addr = client->addr;
274         xfer[0].flags = 0;
275         xfer[0].len = 2;
276         xfer[0].buf = (u8 *)&reg;
277
278         /* Read data */
279         xfer[1].addr = client->addr;
280         xfer[1].flags = I2C_M_RD;
281         xfer[1].len = 1;
282         xfer[1].buf = &data;
283
284         ret = i2c_transfer(client->adapter, xfer, 2);
285         if (ret != 2) {
286                 dev_err(&client->dev, "i2c_transfer() returned %d\n", ret);
287                 return 0;
288         }
289
290         return data;
291 }
292 #else
293 #define snd_soc_16_8_read_i2c NULL
294 #endif
295
296 static unsigned int snd_soc_16_8_read(struct snd_soc_codec *codec,
297                                      unsigned int reg)
298 {
299         u16 *cache = codec->reg_cache;
300
301         reg &= 0xff;
302         if (reg >= codec->reg_cache_size)
303                 return -1;
304         return cache[reg];
305 }
306
307 static int snd_soc_16_8_write(struct snd_soc_codec *codec, unsigned int reg,
308                              unsigned int value)
309 {
310         u16 *cache = codec->reg_cache;
311         u8 data[3];
312         int ret;
313
314         BUG_ON(codec->volatile_register);
315
316         data[0] = (reg >> 8) & 0xff;
317         data[1] = reg & 0xff;
318         data[2] = value;
319
320         reg &= 0xff;
321         if (reg < codec->reg_cache_size)
322                 cache[reg] = value;
323
324         if (codec->cache_only) {
325                 codec->cache_sync = 1;
326                 return 0;
327         }
328
329         ret = codec->hw_write(codec->control_data, data, 3);
330         if (ret == 3)
331                 return 0;
332         if (ret < 0)
333                 return ret;
334         else
335                 return -EIO;
336 }
337
338 #if defined(CONFIG_SPI_MASTER)
339 static int snd_soc_16_8_spi_write(void *control_data, const char *data,
340                                  int len)
341 {
342         struct spi_device *spi = control_data;
343         struct spi_transfer t;
344         struct spi_message m;
345         u8 msg[3];
346
347         if (len <= 0)
348                 return 0;
349
350         msg[0] = data[0];
351         msg[1] = data[1];
352         msg[2] = data[2];
353
354         spi_message_init(&m);
355         memset(&t, 0, (sizeof t));
356
357         t.tx_buf = &msg[0];
358         t.len = len;
359
360         spi_message_add_tail(&t, &m);
361         spi_sync(spi, &m);
362
363         return len;
364 }
365 #else
366 #define snd_soc_16_8_spi_write NULL
367 #endif
368
369
370 static struct {
371         int addr_bits;
372         int data_bits;
373         int (*write)(struct snd_soc_codec *codec, unsigned int, unsigned int);
374         int (*spi_write)(void *, const char *, int);
375         unsigned int (*read)(struct snd_soc_codec *, unsigned int);
376         unsigned int (*i2c_read)(struct snd_soc_codec *, unsigned int);
377 } io_types[] = {
378         {
379                 .addr_bits = 4, .data_bits = 12,
380                 .write = snd_soc_4_12_write, .read = snd_soc_4_12_read,
381                 .spi_write = snd_soc_4_12_spi_write,
382         },
383         {
384                 .addr_bits = 7, .data_bits = 9,
385                 .write = snd_soc_7_9_write, .read = snd_soc_7_9_read,
386                 .spi_write = snd_soc_7_9_spi_write,
387         },
388         {
389                 .addr_bits = 8, .data_bits = 8,
390                 .write = snd_soc_8_8_write, .read = snd_soc_8_8_read,
391         },
392         {
393                 .addr_bits = 8, .data_bits = 16,
394                 .write = snd_soc_8_16_write, .read = snd_soc_8_16_read,
395                 .i2c_read = snd_soc_8_16_read_i2c,
396         },
397         {
398                 .addr_bits = 16, .data_bits = 8,
399                 .write = snd_soc_16_8_write, .read = snd_soc_16_8_read,
400                 .i2c_read = snd_soc_16_8_read_i2c,
401                 .spi_write = snd_soc_16_8_spi_write,
402         },
403 };
404
405 /**
406  * snd_soc_codec_set_cache_io: Set up standard I/O functions.
407  *
408  * @codec: CODEC to configure.
409  * @type: Type of cache.
410  * @addr_bits: Number of bits of register address data.
411  * @data_bits: Number of bits of data per register.
412  * @control: Control bus used.
413  *
414  * Register formats are frequently shared between many I2C and SPI
415  * devices.  In order to promote code reuse the ASoC core provides
416  * some standard implementations of CODEC read and write operations
417  * which can be set up using this function.
418  *
419  * The caller is responsible for allocating and initialising the
420  * actual cache.
421  *
422  * Note that at present this code cannot be used by CODECs with
423  * volatile registers.
424  */
425 int snd_soc_codec_set_cache_io(struct snd_soc_codec *codec,
426                                int addr_bits, int data_bits,
427                                enum snd_soc_control_type control)
428 {
429         int i;
430
431         for (i = 0; i < ARRAY_SIZE(io_types); i++)
432                 if (io_types[i].addr_bits == addr_bits &&
433                     io_types[i].data_bits == data_bits)
434                         break;
435         if (i == ARRAY_SIZE(io_types)) {
436                 printk(KERN_ERR
437                        "No I/O functions for %d bit address %d bit data\n",
438                        addr_bits, data_bits);
439                 return -EINVAL;
440         }
441
442         codec->write = io_types[i].write;
443         codec->read = io_types[i].read;
444
445         switch (control) {
446         case SND_SOC_CUSTOM:
447                 break;
448
449         case SND_SOC_I2C:
450 #if defined(CONFIG_I2C) || (defined(CONFIG_I2C_MODULE) && defined(MODULE))
451                 codec->hw_write = (hw_write_t)i2c_master_send;
452 #endif
453                 if (io_types[i].i2c_read)
454                         codec->hw_read = io_types[i].i2c_read;
455                 break;
456
457         case SND_SOC_SPI:
458                 if (io_types[i].spi_write)
459                         codec->hw_write = io_types[i].spi_write;
460                 break;
461         }
462
463         return 0;
464 }
465 EXPORT_SYMBOL_GPL(snd_soc_codec_set_cache_io);