blob: 73907e5f078fb685d8e8af4e52837d54d42a7e08 [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 Brown27ded042009-07-10 23:28:16 +010015#include <linux/spi/spi.h>
Mark Brown17a52fd2009-07-05 17:24:50 +010016#include <sound/soc.h>
Dimitris Papastamoscc28fb82010-11-11 10:04:58 +000017#include <linux/lzo.h>
18#include <linux/bitmap.h>
Dimitris Papastamosa7f387d2010-11-11 10:04:59 +000019#include <linux/rbtree.h>
Mark Brown17a52fd2009-07-05 17:24:50 +010020
Dimitris Papastamosc358e642011-01-21 15:29:02 +000021#include <trace/events/asoc.h>
22
Dimitris Papastamos30539a182011-03-22 10:37:00 +000023#if defined(CONFIG_SPI_MASTER)
24static int do_spi_write(void *control_data, const void *msg,
25 int len)
26{
27 struct spi_device *spi = control_data;
28 struct spi_transfer t;
29 struct spi_message m;
30
31 if (len <= 0)
32 return 0;
33
34 spi_message_init(&m);
35 memset(&t, 0, sizeof t);
36
37 t.tx_buf = msg;
38 t.len = len;
39
40 spi_message_add_tail(&t, &m);
41 spi_sync(spi, &m);
42
43 return len;
44}
45#endif
46
Dimitris Papastamos26e99842011-03-22 10:36:58 +000047static int do_hw_write(struct snd_soc_codec *codec, unsigned int reg,
48 unsigned int value, const void *data, int len)
49{
50 int ret;
51
52 if (!snd_soc_codec_volatile_register(codec, reg) &&
53 reg < codec->driver->reg_cache_size &&
54 !codec->cache_bypass) {
55 ret = snd_soc_cache_write(codec, reg, value);
56 if (ret < 0)
57 return -1;
58 }
59
60 if (codec->cache_only) {
61 codec->cache_sync = 1;
62 return 0;
63 }
64
65 ret = codec->hw_write(codec->control_data, data, len);
66 if (ret == len)
67 return 0;
68 if (ret < 0)
69 return ret;
70 else
71 return -EIO;
72}
73
Dimitris Papastamosb8cbc192011-03-22 10:36:59 +000074static unsigned int do_hw_read(struct snd_soc_codec *codec, unsigned int reg)
Barry Song63b62ab2010-01-27 11:46:17 +080075{
Dimitris Papastamos7a30a3d2010-11-11 10:04:57 +000076 int ret;
77 unsigned int val;
Dimitris Papastamosdb49c142010-09-22 13:25:47 +010078
79 if (reg >= codec->driver->reg_cache_size ||
Dimitris Papastamosb8cbc192011-03-22 10:36:59 +000080 snd_soc_codec_volatile_register(codec, reg) ||
81 codec->cache_bypass) {
82 if (codec->cache_only)
83 return -1;
Dimitris Papastamosdb49c142010-09-22 13:25:47 +010084
Dimitris Papastamosb8cbc192011-03-22 10:36:59 +000085 BUG_ON(!codec->hw_read);
86 return codec->hw_read(codec, reg);
Dimitris Papastamosdb49c142010-09-22 13:25:47 +010087 }
88
Dimitris Papastamos7a30a3d2010-11-11 10:04:57 +000089 ret = snd_soc_cache_read(codec, reg, &val);
90 if (ret < 0)
91 return -1;
92 return val;
Barry Song63b62ab2010-01-27 11:46:17 +080093}
94
Dimitris Papastamosb8cbc192011-03-22 10:36:59 +000095static unsigned int snd_soc_4_12_read(struct snd_soc_codec *codec,
Dimitris Papastamosfbda1822011-03-28 11:39:14 +010096 unsigned int reg)
Dimitris Papastamosb8cbc192011-03-22 10:36:59 +000097{
98 return do_hw_read(codec, reg);
99}
100
Barry Song63b62ab2010-01-27 11:46:17 +0800101static int snd_soc_4_12_write(struct snd_soc_codec *codec, unsigned int reg,
Dimitris Papastamosfbda1822011-03-28 11:39:14 +0100102 unsigned int value)
Barry Song63b62ab2010-01-27 11:46:17 +0800103{
Mark Brown063b7cc2011-05-10 23:55:21 +0200104 u16 data;
Barry Song63b62ab2010-01-27 11:46:17 +0800105
Mark Brown063b7cc2011-05-10 23:55:21 +0200106 data = cpu_to_be16((reg << 12) | (value & 0xffffff));
Barry Song63b62ab2010-01-27 11:46:17 +0800107
Mark Brown063b7cc2011-05-10 23:55:21 +0200108 return do_hw_write(codec, reg, value, &data, 2);
Barry Song63b62ab2010-01-27 11:46:17 +0800109}
110
111#if defined(CONFIG_SPI_MASTER)
112static int snd_soc_4_12_spi_write(void *control_data, const char *data,
Dimitris Papastamosfbda1822011-03-28 11:39:14 +0100113 int len)
Barry Song63b62ab2010-01-27 11:46:17 +0800114{
Barry Song63b62ab2010-01-27 11:46:17 +0800115 u8 msg[2];
116
Mark Brown063b7cc2011-05-10 23:55:21 +0200117 msg[0] = data[0];
118 msg[1] = data[1];
Barry Song63b62ab2010-01-27 11:46:17 +0800119
Dimitris Papastamos30539a182011-03-22 10:37:00 +0000120 return do_spi_write(control_data, msg, len);
Barry Song63b62ab2010-01-27 11:46:17 +0800121}
122#else
123#define snd_soc_4_12_spi_write NULL
124#endif
125
Mark Brown17a52fd2009-07-05 17:24:50 +0100126static unsigned int snd_soc_7_9_read(struct snd_soc_codec *codec,
127 unsigned int reg)
128{
Dimitris Papastamosb8cbc192011-03-22 10:36:59 +0000129 return do_hw_read(codec, reg);
Mark Brown17a52fd2009-07-05 17:24:50 +0100130}
131
132static int snd_soc_7_9_write(struct snd_soc_codec *codec, unsigned int reg,
133 unsigned int value)
134{
Mark Brown17a52fd2009-07-05 17:24:50 +0100135 u8 data[2];
Mark Brown17a52fd2009-07-05 17:24:50 +0100136
Mark Brown17a52fd2009-07-05 17:24:50 +0100137 data[0] = (reg << 1) | ((value >> 8) & 0x0001);
138 data[1] = value & 0x00ff;
139
Dimitris Papastamos26e99842011-03-22 10:36:58 +0000140 return do_hw_write(codec, reg, value, data, 2);
Mark Brown17a52fd2009-07-05 17:24:50 +0100141}
142
Mark Brown27ded042009-07-10 23:28:16 +0100143#if defined(CONFIG_SPI_MASTER)
144static int snd_soc_7_9_spi_write(void *control_data, const char *data,
145 int len)
146{
Mark Brown27ded042009-07-10 23:28:16 +0100147 u8 msg[2];
148
Mark Brown27ded042009-07-10 23:28:16 +0100149 msg[0] = data[0];
150 msg[1] = data[1];
151
Dimitris Papastamos30539a182011-03-22 10:37:00 +0000152 return do_spi_write(control_data, msg, len);
Mark Brown27ded042009-07-10 23:28:16 +0100153}
154#else
155#define snd_soc_7_9_spi_write NULL
156#endif
157
Joonyoung Shim341c9b82009-09-07 12:04:37 +0900158static int snd_soc_8_8_write(struct snd_soc_codec *codec, unsigned int reg,
159 unsigned int value)
160{
Joonyoung Shim341c9b82009-09-07 12:04:37 +0900161 u8 data[2];
162
Barry Songf4bee1b2010-03-18 16:17:01 +0800163 reg &= 0xff;
164 data[0] = reg;
Joonyoung Shim341c9b82009-09-07 12:04:37 +0900165 data[1] = value & 0xff;
166
Dimitris Papastamos26e99842011-03-22 10:36:58 +0000167 return do_hw_write(codec, reg, value, data, 2);
Joonyoung Shim341c9b82009-09-07 12:04:37 +0900168}
169
170static unsigned int snd_soc_8_8_read(struct snd_soc_codec *codec,
171 unsigned int reg)
172{
Dimitris Papastamosb8cbc192011-03-22 10:36:59 +0000173 return do_hw_read(codec, reg);
Joonyoung Shim341c9b82009-09-07 12:04:37 +0900174}
175
Dimitris Papastamosf479fd92010-10-04 11:25:13 +0100176#if defined(CONFIG_SPI_MASTER)
177static int snd_soc_8_8_spi_write(void *control_data, const char *data,
178 int len)
179{
Dimitris Papastamosf479fd92010-10-04 11:25:13 +0100180 u8 msg[2];
181
Dimitris Papastamosf479fd92010-10-04 11:25:13 +0100182 msg[0] = data[0];
183 msg[1] = data[1];
184
Dimitris Papastamos30539a182011-03-22 10:37:00 +0000185 return do_spi_write(control_data, msg, len);
Dimitris Papastamosf479fd92010-10-04 11:25:13 +0100186}
187#else
188#define snd_soc_8_8_spi_write NULL
189#endif
190
Mark Brownafa2f102009-07-10 23:11:24 +0100191static int snd_soc_8_16_write(struct snd_soc_codec *codec, unsigned int reg,
192 unsigned int value)
193{
Mark Brownafa2f102009-07-10 23:11:24 +0100194 u8 data[3];
195
196 data[0] = reg;
197 data[1] = (value >> 8) & 0xff;
198 data[2] = value & 0xff;
199
Dimitris Papastamos26e99842011-03-22 10:36:58 +0000200 return do_hw_write(codec, reg, value, data, 3);
Mark Brownafa2f102009-07-10 23:11:24 +0100201}
202
203static unsigned int snd_soc_8_16_read(struct snd_soc_codec *codec,
204 unsigned int reg)
205{
Dimitris Papastamosb8cbc192011-03-22 10:36:59 +0000206 return do_hw_read(codec, reg);
Mark Brownafa2f102009-07-10 23:11:24 +0100207}
208
Dimitris Papastamosf479fd92010-10-04 11:25:13 +0100209#if defined(CONFIG_SPI_MASTER)
210static int snd_soc_8_16_spi_write(void *control_data, const char *data,
Dimitris Papastamosfbda1822011-03-28 11:39:14 +0100211 int len)
Dimitris Papastamosf479fd92010-10-04 11:25:13 +0100212{
Dimitris Papastamosf479fd92010-10-04 11:25:13 +0100213 u8 msg[3];
214
Dimitris Papastamosf479fd92010-10-04 11:25:13 +0100215 msg[0] = data[0];
216 msg[1] = data[1];
217 msg[2] = data[2];
218
Dimitris Papastamos30539a182011-03-22 10:37:00 +0000219 return do_spi_write(control_data, msg, len);
Dimitris Papastamosf479fd92010-10-04 11:25:13 +0100220}
221#else
222#define snd_soc_8_16_spi_write NULL
223#endif
224
Randy Dunlap17244c22009-08-10 16:04:39 -0700225#if defined(CONFIG_I2C) || (defined(CONFIG_I2C_MODULE) && defined(MODULE))
Dimitris Papastamosf3594f52011-03-22 10:37:01 +0000226static unsigned int do_i2c_read(struct snd_soc_codec *codec,
227 void *reg, int reglen,
228 void *data, int datalen)
Cliff Cai85dfcdf2010-03-18 16:17:00 +0800229{
230 struct i2c_msg xfer[2];
Cliff Cai85dfcdf2010-03-18 16:17:00 +0800231 int ret;
232 struct i2c_client *client = codec->control_data;
233
234 /* Write register */
235 xfer[0].addr = client->addr;
236 xfer[0].flags = 0;
Dimitris Papastamosf3594f52011-03-22 10:37:01 +0000237 xfer[0].len = reglen;
238 xfer[0].buf = reg;
Cliff Cai85dfcdf2010-03-18 16:17:00 +0800239
240 /* Read data */
241 xfer[1].addr = client->addr;
242 xfer[1].flags = I2C_M_RD;
Dimitris Papastamosf3594f52011-03-22 10:37:01 +0000243 xfer[1].len = datalen;
244 xfer[1].buf = data;
Cliff Cai85dfcdf2010-03-18 16:17:00 +0800245
246 ret = i2c_transfer(client->adapter, xfer, 2);
Dimitris Papastamosf3594f52011-03-22 10:37:01 +0000247 if (ret == 2)
Cliff Cai85dfcdf2010-03-18 16:17:00 +0800248 return 0;
Dimitris Papastamosf3594f52011-03-22 10:37:01 +0000249 else if (ret < 0)
250 return ret;
251 else
252 return -EIO;
253}
254#endif
Cliff Cai85dfcdf2010-03-18 16:17:00 +0800255
Dimitris Papastamosf3594f52011-03-22 10:37:01 +0000256#if defined(CONFIG_I2C) || (defined(CONFIG_I2C_MODULE) && defined(MODULE))
257static unsigned int snd_soc_8_8_read_i2c(struct snd_soc_codec *codec,
Dimitris Papastamosfbda1822011-03-28 11:39:14 +0100258 unsigned int r)
Dimitris Papastamosf3594f52011-03-22 10:37:01 +0000259{
260 u8 reg = r;
261 u8 data;
262 int ret;
263
264 ret = do_i2c_read(codec, &reg, 1, &data, 1);
265 if (ret < 0)
266 return 0;
Cliff Cai85dfcdf2010-03-18 16:17:00 +0800267 return data;
268}
269#else
270#define snd_soc_8_8_read_i2c NULL
271#endif
272
273#if defined(CONFIG_I2C) || (defined(CONFIG_I2C_MODULE) && defined(MODULE))
Mark Brownafa2f102009-07-10 23:11:24 +0100274static unsigned int snd_soc_8_16_read_i2c(struct snd_soc_codec *codec,
275 unsigned int r)
276{
Mark Brownafa2f102009-07-10 23:11:24 +0100277 u8 reg = r;
278 u16 data;
279 int ret;
Mark Brownafa2f102009-07-10 23:11:24 +0100280
Dimitris Papastamosf3594f52011-03-22 10:37:01 +0000281 ret = do_i2c_read(codec, &reg, 1, &data, 2);
282 if (ret < 0)
Mark Brownafa2f102009-07-10 23:11:24 +0100283 return 0;
Mark Brownafa2f102009-07-10 23:11:24 +0100284 return (data >> 8) | ((data & 0xff) << 8);
285}
286#else
287#define snd_soc_8_16_read_i2c NULL
288#endif
Mark Brown17a52fd2009-07-05 17:24:50 +0100289
Barry Song994dc422010-01-27 11:46:18 +0800290#if defined(CONFIG_I2C) || (defined(CONFIG_I2C_MODULE) && defined(MODULE))
291static unsigned int snd_soc_16_8_read_i2c(struct snd_soc_codec *codec,
292 unsigned int r)
293{
Barry Song994dc422010-01-27 11:46:18 +0800294 u16 reg = r;
295 u8 data;
296 int ret;
Barry Song994dc422010-01-27 11:46:18 +0800297
Dimitris Papastamosf3594f52011-03-22 10:37:01 +0000298 ret = do_i2c_read(codec, &reg, 2, &data, 1);
299 if (ret < 0)
Barry Song994dc422010-01-27 11:46:18 +0800300 return 0;
Barry Song994dc422010-01-27 11:46:18 +0800301 return data;
302}
303#else
304#define snd_soc_16_8_read_i2c NULL
305#endif
306
307static unsigned int snd_soc_16_8_read(struct snd_soc_codec *codec,
Dimitris Papastamosfbda1822011-03-28 11:39:14 +0100308 unsigned int reg)
Barry Song994dc422010-01-27 11:46:18 +0800309{
Dimitris Papastamosb8cbc192011-03-22 10:36:59 +0000310 return do_hw_read(codec, reg);
Barry Song994dc422010-01-27 11:46:18 +0800311}
312
313static int snd_soc_16_8_write(struct snd_soc_codec *codec, unsigned int reg,
Dimitris Papastamosfbda1822011-03-28 11:39:14 +0100314 unsigned int value)
Barry Song994dc422010-01-27 11:46:18 +0800315{
Barry Song994dc422010-01-27 11:46:18 +0800316 u8 data[3];
Barry Song994dc422010-01-27 11:46:18 +0800317
Barry Song994dc422010-01-27 11:46:18 +0800318 data[0] = (reg >> 8) & 0xff;
319 data[1] = reg & 0xff;
320 data[2] = value;
Mark Brown8c961bc2010-02-01 18:46:10 +0000321
Dimitris Papastamos26e99842011-03-22 10:36:58 +0000322 return do_hw_write(codec, reg, value, data, 3);
Barry Song994dc422010-01-27 11:46:18 +0800323}
324
325#if defined(CONFIG_SPI_MASTER)
326static int snd_soc_16_8_spi_write(void *control_data, const char *data,
Dimitris Papastamosfbda1822011-03-28 11:39:14 +0100327 int len)
Barry Song994dc422010-01-27 11:46:18 +0800328{
Barry Song994dc422010-01-27 11:46:18 +0800329 u8 msg[3];
330
Barry Song994dc422010-01-27 11:46:18 +0800331 msg[0] = data[0];
332 msg[1] = data[1];
333 msg[2] = data[2];
334
Dimitris Papastamos30539a182011-03-22 10:37:00 +0000335 return do_spi_write(control_data, msg, len);
Barry Song994dc422010-01-27 11:46:18 +0800336}
337#else
338#define snd_soc_16_8_spi_write NULL
339#endif
340
Mark Brownbc6552f2010-03-05 16:27:15 +0000341#if defined(CONFIG_I2C) || (defined(CONFIG_I2C_MODULE) && defined(MODULE))
342static unsigned int snd_soc_16_16_read_i2c(struct snd_soc_codec *codec,
343 unsigned int r)
344{
Mark Brownbc6552f2010-03-05 16:27:15 +0000345 u16 reg = cpu_to_be16(r);
346 u16 data;
347 int ret;
Mark Brownbc6552f2010-03-05 16:27:15 +0000348
Dimitris Papastamosf3594f52011-03-22 10:37:01 +0000349 ret = do_i2c_read(codec, &reg, 2, &data, 2);
350 if (ret < 0)
Mark Brownbc6552f2010-03-05 16:27:15 +0000351 return 0;
Mark Brownbc6552f2010-03-05 16:27:15 +0000352 return be16_to_cpu(data);
353}
354#else
355#define snd_soc_16_16_read_i2c NULL
356#endif
357
358static unsigned int snd_soc_16_16_read(struct snd_soc_codec *codec,
359 unsigned int reg)
360{
Dimitris Papastamosb8cbc192011-03-22 10:36:59 +0000361 return do_hw_read(codec, reg);
Mark Brownbc6552f2010-03-05 16:27:15 +0000362}
363
364static int snd_soc_16_16_write(struct snd_soc_codec *codec, unsigned int reg,
365 unsigned int value)
366{
Mark Brownbc6552f2010-03-05 16:27:15 +0000367 u8 data[4];
Mark Brownbc6552f2010-03-05 16:27:15 +0000368
369 data[0] = (reg >> 8) & 0xff;
370 data[1] = reg & 0xff;
371 data[2] = (value >> 8) & 0xff;
372 data[3] = value & 0xff;
373
Dimitris Papastamos26e99842011-03-22 10:36:58 +0000374 return do_hw_write(codec, reg, value, data, 4);
Mark Brownbc6552f2010-03-05 16:27:15 +0000375}
Barry Song994dc422010-01-27 11:46:18 +0800376
Dimitris Papastamosf479fd92010-10-04 11:25:13 +0100377#if defined(CONFIG_SPI_MASTER)
378static int snd_soc_16_16_spi_write(void *control_data, const char *data,
Dimitris Papastamosfbda1822011-03-28 11:39:14 +0100379 int len)
Dimitris Papastamosf479fd92010-10-04 11:25:13 +0100380{
Dimitris Papastamosf479fd92010-10-04 11:25:13 +0100381 u8 msg[4];
382
Dimitris Papastamosf479fd92010-10-04 11:25:13 +0100383 msg[0] = data[0];
384 msg[1] = data[1];
385 msg[2] = data[2];
386 msg[3] = data[3];
387
Dimitris Papastamos30539a182011-03-22 10:37:00 +0000388 return do_spi_write(control_data, msg, len);
Dimitris Papastamosf479fd92010-10-04 11:25:13 +0100389}
390#else
391#define snd_soc_16_16_spi_write NULL
392#endif
393
Mark Brown34bad692011-04-04 17:55:42 +0900394/* Primitive bulk write support for soc-cache. The data pointed to by
395 * `data' needs to already be in the form the hardware expects
396 * including any leading register specific data. Any data written
397 * through this function will not go through the cache as it only
398 * handles writing to volatile or out of bounds registers.
Dimitris Papastamos5fb609d2011-03-22 10:37:03 +0000399 */
400static int snd_soc_hw_bulk_write_raw(struct snd_soc_codec *codec, unsigned int reg,
401 const void *data, size_t len)
402{
403 int ret;
404
Dimitris Papastamos64d27062011-05-05 14:18:11 +0100405 /* To ensure that we don't get out of sync with the cache, check
406 * whether the base register is volatile or if we've directly asked
407 * to bypass the cache. Out of bounds registers are considered
408 * volatile.
Dimitris Papastamos5fb609d2011-03-22 10:37:03 +0000409 */
Dimitris Papastamos64d27062011-05-05 14:18:11 +0100410 if (!codec->cache_bypass
411 && !snd_soc_codec_volatile_register(codec, reg)
Dimitris Papastamos5fb609d2011-03-22 10:37:03 +0000412 && reg < codec->driver->reg_cache_size)
413 return -EINVAL;
414
415 switch (codec->control_type) {
Seungwhan Youn898f8b02011-04-04 13:43:42 +0900416#if defined(CONFIG_I2C) || (defined(CONFIG_I2C_MODULE) && defined(MODULE))
Dimitris Papastamos5fb609d2011-03-22 10:37:03 +0000417 case SND_SOC_I2C:
418 ret = i2c_master_send(codec->control_data, data, len);
419 break;
Seungwhan Youn898f8b02011-04-04 13:43:42 +0900420#endif
421#if defined(CONFIG_SPI_MASTER)
Dimitris Papastamos5fb609d2011-03-22 10:37:03 +0000422 case SND_SOC_SPI:
423 ret = do_spi_write(codec->control_data, data, len);
424 break;
Seungwhan Youn898f8b02011-04-04 13:43:42 +0900425#endif
Dimitris Papastamos5fb609d2011-03-22 10:37:03 +0000426 default:
427 BUG();
428 }
429
430 if (ret == len)
431 return 0;
432 if (ret < 0)
433 return ret;
434 else
435 return -EIO;
436}
437
Mark Brown17a52fd2009-07-05 17:24:50 +0100438static struct {
439 int addr_bits;
440 int data_bits;
Mark Brownafa2f102009-07-10 23:11:24 +0100441 int (*write)(struct snd_soc_codec *codec, unsigned int, unsigned int);
Mark Brown27ded042009-07-10 23:28:16 +0100442 int (*spi_write)(void *, const char *, int);
Mark Brown17a52fd2009-07-05 17:24:50 +0100443 unsigned int (*read)(struct snd_soc_codec *, unsigned int);
Mark Brownafa2f102009-07-10 23:11:24 +0100444 unsigned int (*i2c_read)(struct snd_soc_codec *, unsigned int);
Mark Brown17a52fd2009-07-05 17:24:50 +0100445} io_types[] = {
Mark Brownd62ab352009-09-21 04:21:47 -0700446 {
Barry Song63b62ab2010-01-27 11:46:17 +0800447 .addr_bits = 4, .data_bits = 12,
448 .write = snd_soc_4_12_write, .read = snd_soc_4_12_read,
449 .spi_write = snd_soc_4_12_spi_write,
450 },
451 {
Mark Brownd62ab352009-09-21 04:21:47 -0700452 .addr_bits = 7, .data_bits = 9,
453 .write = snd_soc_7_9_write, .read = snd_soc_7_9_read,
Barry Song8998c892009-12-31 10:30:34 +0800454 .spi_write = snd_soc_7_9_spi_write,
Mark Brownd62ab352009-09-21 04:21:47 -0700455 },
456 {
457 .addr_bits = 8, .data_bits = 8,
458 .write = snd_soc_8_8_write, .read = snd_soc_8_8_read,
Cliff Cai85dfcdf2010-03-18 16:17:00 +0800459 .i2c_read = snd_soc_8_8_read_i2c,
Dimitris Papastamosf479fd92010-10-04 11:25:13 +0100460 .spi_write = snd_soc_8_8_spi_write,
Mark Brownd62ab352009-09-21 04:21:47 -0700461 },
462 {
463 .addr_bits = 8, .data_bits = 16,
464 .write = snd_soc_8_16_write, .read = snd_soc_8_16_read,
465 .i2c_read = snd_soc_8_16_read_i2c,
Dimitris Papastamosf479fd92010-10-04 11:25:13 +0100466 .spi_write = snd_soc_8_16_spi_write,
Mark Brownd62ab352009-09-21 04:21:47 -0700467 },
Barry Song994dc422010-01-27 11:46:18 +0800468 {
469 .addr_bits = 16, .data_bits = 8,
470 .write = snd_soc_16_8_write, .read = snd_soc_16_8_read,
471 .i2c_read = snd_soc_16_8_read_i2c,
472 .spi_write = snd_soc_16_8_spi_write,
473 },
Mark Brownbc6552f2010-03-05 16:27:15 +0000474 {
475 .addr_bits = 16, .data_bits = 16,
476 .write = snd_soc_16_16_write, .read = snd_soc_16_16_read,
477 .i2c_read = snd_soc_16_16_read_i2c,
Dimitris Papastamosf479fd92010-10-04 11:25:13 +0100478 .spi_write = snd_soc_16_16_spi_write,
Mark Brownbc6552f2010-03-05 16:27:15 +0000479 },
Mark Brown17a52fd2009-07-05 17:24:50 +0100480};
481
482/**
483 * snd_soc_codec_set_cache_io: Set up standard I/O functions.
484 *
485 * @codec: CODEC to configure.
Mark Brown17a52fd2009-07-05 17:24:50 +0100486 * @addr_bits: Number of bits of register address data.
487 * @data_bits: Number of bits of data per register.
Mark Brown7084a422009-07-10 22:24:27 +0100488 * @control: Control bus used.
Mark Brown17a52fd2009-07-05 17:24:50 +0100489 *
490 * Register formats are frequently shared between many I2C and SPI
491 * devices. In order to promote code reuse the ASoC core provides
492 * some standard implementations of CODEC read and write operations
493 * which can be set up using this function.
494 *
495 * The caller is responsible for allocating and initialising the
496 * actual cache.
497 *
498 * Note that at present this code cannot be used by CODECs with
499 * volatile registers.
500 */
501int snd_soc_codec_set_cache_io(struct snd_soc_codec *codec,
Mark Brown7084a422009-07-10 22:24:27 +0100502 int addr_bits, int data_bits,
503 enum snd_soc_control_type control)
Mark Brown17a52fd2009-07-05 17:24:50 +0100504{
505 int i;
506
Mark Brown17a52fd2009-07-05 17:24:50 +0100507 for (i = 0; i < ARRAY_SIZE(io_types); i++)
508 if (io_types[i].addr_bits == addr_bits &&
509 io_types[i].data_bits == data_bits)
510 break;
511 if (i == ARRAY_SIZE(io_types)) {
512 printk(KERN_ERR
513 "No I/O functions for %d bit address %d bit data\n",
514 addr_bits, data_bits);
515 return -EINVAL;
516 }
517
Mark Brownc3acec22010-12-02 16:15:29 +0000518 codec->write = io_types[i].write;
519 codec->read = io_types[i].read;
Dimitris Papastamos5fb609d2011-03-22 10:37:03 +0000520 codec->bulk_write_raw = snd_soc_hw_bulk_write_raw;
Mark Brown17a52fd2009-07-05 17:24:50 +0100521
Mark Brown7084a422009-07-10 22:24:27 +0100522 switch (control) {
523 case SND_SOC_CUSTOM:
524 break;
525
526 case SND_SOC_I2C:
Randy Dunlap17244c22009-08-10 16:04:39 -0700527#if defined(CONFIG_I2C) || (defined(CONFIG_I2C_MODULE) && defined(MODULE))
Mark Brown7084a422009-07-10 22:24:27 +0100528 codec->hw_write = (hw_write_t)i2c_master_send;
529#endif
Mark Brownafa2f102009-07-10 23:11:24 +0100530 if (io_types[i].i2c_read)
531 codec->hw_read = io_types[i].i2c_read;
Mark Browna6d14342010-08-12 10:59:15 +0100532
533 codec->control_data = container_of(codec->dev,
534 struct i2c_client,
535 dev);
Mark Brown7084a422009-07-10 22:24:27 +0100536 break;
537
538 case SND_SOC_SPI:
Mark Brown27ded042009-07-10 23:28:16 +0100539 if (io_types[i].spi_write)
540 codec->hw_write = io_types[i].spi_write;
Mark Browna6d14342010-08-12 10:59:15 +0100541
542 codec->control_data = container_of(codec->dev,
543 struct spi_device,
544 dev);
Mark Brown7084a422009-07-10 22:24:27 +0100545 break;
546 }
547
Mark Brown17a52fd2009-07-05 17:24:50 +0100548 return 0;
549}
550EXPORT_SYMBOL_GPL(snd_soc_codec_set_cache_io);
Dimitris Papastamos7a30a3d2010-11-11 10:04:57 +0000551
Dimitris Papastamos1321e882011-01-11 11:29:49 +0000552static bool snd_soc_set_cache_val(void *base, unsigned int idx,
553 unsigned int val, unsigned int word_size)
554{
555 switch (word_size) {
556 case 1: {
557 u8 *cache = base;
558 if (cache[idx] == val)
559 return true;
560 cache[idx] = val;
561 break;
562 }
563 case 2: {
564 u16 *cache = base;
565 if (cache[idx] == val)
566 return true;
567 cache[idx] = val;
568 break;
569 }
570 default:
571 BUG();
572 }
573 return false;
574}
575
576static unsigned int snd_soc_get_cache_val(const void *base, unsigned int idx,
577 unsigned int word_size)
578{
579 switch (word_size) {
580 case 1: {
581 const u8 *cache = base;
582 return cache[idx];
583 }
584 case 2: {
585 const u16 *cache = base;
586 return cache[idx];
587 }
588 default:
589 BUG();
590 }
591 /* unreachable */
592 return -1;
593}
594
Dimitris Papastamosa7f387d2010-11-11 10:04:59 +0000595struct snd_soc_rbtree_node {
596 struct rb_node node;
597 unsigned int reg;
598 unsigned int value;
599 unsigned int defval;
600} __attribute__ ((packed));
601
602struct snd_soc_rbtree_ctx {
603 struct rb_root root;
604};
605
606static struct snd_soc_rbtree_node *snd_soc_rbtree_lookup(
607 struct rb_root *root, unsigned int reg)
608{
609 struct rb_node *node;
610 struct snd_soc_rbtree_node *rbnode;
611
612 node = root->rb_node;
613 while (node) {
614 rbnode = container_of(node, struct snd_soc_rbtree_node, node);
615 if (rbnode->reg < reg)
616 node = node->rb_left;
617 else if (rbnode->reg > reg)
618 node = node->rb_right;
619 else
620 return rbnode;
621 }
622
623 return NULL;
624}
625
Dimitris Papastamosa7f387d2010-11-11 10:04:59 +0000626static int snd_soc_rbtree_insert(struct rb_root *root,
627 struct snd_soc_rbtree_node *rbnode)
628{
629 struct rb_node **new, *parent;
630 struct snd_soc_rbtree_node *rbnode_tmp;
631
632 parent = NULL;
633 new = &root->rb_node;
634 while (*new) {
635 rbnode_tmp = container_of(*new, struct snd_soc_rbtree_node,
636 node);
637 parent = *new;
638 if (rbnode_tmp->reg < rbnode->reg)
639 new = &((*new)->rb_left);
640 else if (rbnode_tmp->reg > rbnode->reg)
641 new = &((*new)->rb_right);
642 else
643 return 0;
644 }
645
646 /* insert the node into the rbtree */
647 rb_link_node(&rbnode->node, parent, new);
648 rb_insert_color(&rbnode->node, root);
649
650 return 1;
651}
652
653static int snd_soc_rbtree_cache_sync(struct snd_soc_codec *codec)
654{
655 struct snd_soc_rbtree_ctx *rbtree_ctx;
656 struct rb_node *node;
657 struct snd_soc_rbtree_node *rbnode;
658 unsigned int val;
Dimitris Papastamos7a33d4c2010-11-29 10:24:54 +0000659 int ret;
Dimitris Papastamosa7f387d2010-11-11 10:04:59 +0000660
661 rbtree_ctx = codec->reg_cache;
662 for (node = rb_first(&rbtree_ctx->root); node; node = rb_next(node)) {
663 rbnode = rb_entry(node, struct snd_soc_rbtree_node, node);
664 if (rbnode->value == rbnode->defval)
665 continue;
Dimitris Papastamosf20eda52011-03-28 11:39:15 +0100666 WARN_ON(codec->writable_register &&
667 codec->writable_register(codec, rbnode->reg));
Dimitris Papastamos7a33d4c2010-11-29 10:24:54 +0000668 ret = snd_soc_cache_read(codec, rbnode->reg, &val);
669 if (ret)
670 return ret;
Dimitris Papastamos99780072011-01-19 14:53:37 +0000671 codec->cache_bypass = 1;
Dimitris Papastamos7a33d4c2010-11-29 10:24:54 +0000672 ret = snd_soc_write(codec, rbnode->reg, val);
Dimitris Papastamos99780072011-01-19 14:53:37 +0000673 codec->cache_bypass = 0;
Dimitris Papastamos7a33d4c2010-11-29 10:24:54 +0000674 if (ret)
675 return ret;
Dimitris Papastamosa7f387d2010-11-11 10:04:59 +0000676 dev_dbg(codec->dev, "Synced register %#x, value = %#x\n",
677 rbnode->reg, val);
678 }
679
680 return 0;
681}
682
683static int snd_soc_rbtree_cache_write(struct snd_soc_codec *codec,
684 unsigned int reg, unsigned int value)
685{
686 struct snd_soc_rbtree_ctx *rbtree_ctx;
687 struct snd_soc_rbtree_node *rbnode;
688
689 rbtree_ctx = codec->reg_cache;
690 rbnode = snd_soc_rbtree_lookup(&rbtree_ctx->root, reg);
691 if (rbnode) {
692 if (rbnode->value == value)
693 return 0;
694 rbnode->value = value;
695 } else {
696 /* bail out early, no need to create the rbnode yet */
697 if (!value)
698 return 0;
699 /*
700 * for uninitialized registers whose value is changed
701 * from the default zero, create an rbnode and insert
702 * it into the tree.
703 */
704 rbnode = kzalloc(sizeof *rbnode, GFP_KERNEL);
705 if (!rbnode)
706 return -ENOMEM;
707 rbnode->reg = reg;
708 rbnode->value = value;
709 snd_soc_rbtree_insert(&rbtree_ctx->root, rbnode);
710 }
711
712 return 0;
713}
714
715static int snd_soc_rbtree_cache_read(struct snd_soc_codec *codec,
716 unsigned int reg, unsigned int *value)
717{
718 struct snd_soc_rbtree_ctx *rbtree_ctx;
719 struct snd_soc_rbtree_node *rbnode;
720
721 rbtree_ctx = codec->reg_cache;
722 rbnode = snd_soc_rbtree_lookup(&rbtree_ctx->root, reg);
723 if (rbnode) {
724 *value = rbnode->value;
725 } else {
726 /* uninitialized registers default to 0 */
727 *value = 0;
728 }
729
730 return 0;
731}
732
733static int snd_soc_rbtree_cache_exit(struct snd_soc_codec *codec)
734{
735 struct rb_node *next;
736 struct snd_soc_rbtree_ctx *rbtree_ctx;
737 struct snd_soc_rbtree_node *rbtree_node;
738
739 /* if we've already been called then just return */
740 rbtree_ctx = codec->reg_cache;
741 if (!rbtree_ctx)
742 return 0;
743
744 /* free up the rbtree */
745 next = rb_first(&rbtree_ctx->root);
746 while (next) {
747 rbtree_node = rb_entry(next, struct snd_soc_rbtree_node, node);
748 next = rb_next(&rbtree_node->node);
749 rb_erase(&rbtree_node->node, &rbtree_ctx->root);
750 kfree(rbtree_node);
751 }
752
753 /* release the resources */
754 kfree(codec->reg_cache);
755 codec->reg_cache = NULL;
756
757 return 0;
758}
759
760static int snd_soc_rbtree_cache_init(struct snd_soc_codec *codec)
761{
Dimitris Papastamos1321e882011-01-11 11:29:49 +0000762 struct snd_soc_rbtree_node *rbtree_node;
Dimitris Papastamosa7f387d2010-11-11 10:04:59 +0000763 struct snd_soc_rbtree_ctx *rbtree_ctx;
Dimitris Papastamos1321e882011-01-11 11:29:49 +0000764 unsigned int val;
765 unsigned int word_size;
766 int i;
767 int ret;
Dimitris Papastamosa7f387d2010-11-11 10:04:59 +0000768
769 codec->reg_cache = kmalloc(sizeof *rbtree_ctx, GFP_KERNEL);
770 if (!codec->reg_cache)
771 return -ENOMEM;
772
773 rbtree_ctx = codec->reg_cache;
774 rbtree_ctx->root = RB_ROOT;
775
Dimitris Papastamos3335ddc2010-12-02 16:11:05 +0000776 if (!codec->reg_def_copy)
Dimitris Papastamosa7f387d2010-11-11 10:04:59 +0000777 return 0;
778
Dimitris Papastamos1321e882011-01-11 11:29:49 +0000779 /*
780 * populate the rbtree with the initialized registers. All other
781 * registers will be inserted when they are first modified.
782 */
783 word_size = codec->driver->reg_word_size;
784 for (i = 0; i < codec->driver->reg_cache_size; ++i) {
785 val = snd_soc_get_cache_val(codec->reg_def_copy, i, word_size);
786 if (!val)
787 continue;
788 rbtree_node = kzalloc(sizeof *rbtree_node, GFP_KERNEL);
789 if (!rbtree_node) {
790 ret = -ENOMEM;
791 snd_soc_cache_exit(codec);
792 break;
793 }
794 rbtree_node->reg = i;
795 rbtree_node->value = val;
796 rbtree_node->defval = val;
797 snd_soc_rbtree_insert(&rbtree_ctx->root, rbtree_node);
Dimitris Papastamosa7f387d2010-11-11 10:04:59 +0000798 }
799
800 return 0;
801}
802
Mark Brown68d44ee2010-12-21 17:19:56 +0000803#ifdef CONFIG_SND_SOC_CACHE_LZO
Dimitris Papastamoscc28fb82010-11-11 10:04:58 +0000804struct snd_soc_lzo_ctx {
805 void *wmem;
806 void *dst;
807 const void *src;
808 size_t src_len;
809 size_t dst_len;
810 size_t decompressed_size;
811 unsigned long *sync_bmp;
812 int sync_bmp_nbits;
813};
814
815#define LZO_BLOCK_NUM 8
816static int snd_soc_lzo_block_count(void)
817{
818 return LZO_BLOCK_NUM;
819}
820
821static int snd_soc_lzo_prepare(struct snd_soc_lzo_ctx *lzo_ctx)
822{
823 lzo_ctx->wmem = kmalloc(LZO1X_MEM_COMPRESS, GFP_KERNEL);
824 if (!lzo_ctx->wmem)
825 return -ENOMEM;
826 return 0;
827}
828
829static int snd_soc_lzo_compress(struct snd_soc_lzo_ctx *lzo_ctx)
830{
831 size_t compress_size;
832 int ret;
833
834 ret = lzo1x_1_compress(lzo_ctx->src, lzo_ctx->src_len,
835 lzo_ctx->dst, &compress_size, lzo_ctx->wmem);
836 if (ret != LZO_E_OK || compress_size > lzo_ctx->dst_len)
837 return -EINVAL;
838 lzo_ctx->dst_len = compress_size;
839 return 0;
840}
841
842static int snd_soc_lzo_decompress(struct snd_soc_lzo_ctx *lzo_ctx)
843{
844 size_t dst_len;
845 int ret;
846
847 dst_len = lzo_ctx->dst_len;
848 ret = lzo1x_decompress_safe(lzo_ctx->src, lzo_ctx->src_len,
849 lzo_ctx->dst, &dst_len);
850 if (ret != LZO_E_OK || dst_len != lzo_ctx->dst_len)
851 return -EINVAL;
852 return 0;
853}
854
855static int snd_soc_lzo_compress_cache_block(struct snd_soc_codec *codec,
856 struct snd_soc_lzo_ctx *lzo_ctx)
857{
858 int ret;
859
860 lzo_ctx->dst_len = lzo1x_worst_compress(PAGE_SIZE);
861 lzo_ctx->dst = kmalloc(lzo_ctx->dst_len, GFP_KERNEL);
862 if (!lzo_ctx->dst) {
863 lzo_ctx->dst_len = 0;
864 return -ENOMEM;
865 }
866
867 ret = snd_soc_lzo_compress(lzo_ctx);
868 if (ret < 0)
869 return ret;
870 return 0;
871}
872
873static int snd_soc_lzo_decompress_cache_block(struct snd_soc_codec *codec,
874 struct snd_soc_lzo_ctx *lzo_ctx)
875{
876 int ret;
877
878 lzo_ctx->dst_len = lzo_ctx->decompressed_size;
879 lzo_ctx->dst = kmalloc(lzo_ctx->dst_len, GFP_KERNEL);
880 if (!lzo_ctx->dst) {
881 lzo_ctx->dst_len = 0;
882 return -ENOMEM;
883 }
884
885 ret = snd_soc_lzo_decompress(lzo_ctx);
886 if (ret < 0)
887 return ret;
888 return 0;
889}
890
891static inline int snd_soc_lzo_get_blkindex(struct snd_soc_codec *codec,
892 unsigned int reg)
893{
Mark Brown001ae4c2010-12-02 16:21:08 +0000894 const struct snd_soc_codec_driver *codec_drv;
Dimitris Papastamoscc28fb82010-11-11 10:04:58 +0000895
896 codec_drv = codec->driver;
Dimitris Papastamoscc28fb82010-11-11 10:04:58 +0000897 return (reg * codec_drv->reg_word_size) /
Dimitris Papastamosaea170a2011-01-12 10:38:58 +0000898 DIV_ROUND_UP(codec->reg_size, snd_soc_lzo_block_count());
Dimitris Papastamoscc28fb82010-11-11 10:04:58 +0000899}
900
901static inline int snd_soc_lzo_get_blkpos(struct snd_soc_codec *codec,
902 unsigned int reg)
903{
Mark Brown001ae4c2010-12-02 16:21:08 +0000904 const struct snd_soc_codec_driver *codec_drv;
Dimitris Papastamoscc28fb82010-11-11 10:04:58 +0000905
906 codec_drv = codec->driver;
Dimitris Papastamosaea170a2011-01-12 10:38:58 +0000907 return reg % (DIV_ROUND_UP(codec->reg_size, snd_soc_lzo_block_count()) /
Dimitris Papastamoscc28fb82010-11-11 10:04:58 +0000908 codec_drv->reg_word_size);
909}
910
911static inline int snd_soc_lzo_get_blksize(struct snd_soc_codec *codec)
912{
Mark Brown001ae4c2010-12-02 16:21:08 +0000913 const struct snd_soc_codec_driver *codec_drv;
Dimitris Papastamoscc28fb82010-11-11 10:04:58 +0000914
915 codec_drv = codec->driver;
Dimitris Papastamosaea170a2011-01-12 10:38:58 +0000916 return DIV_ROUND_UP(codec->reg_size, snd_soc_lzo_block_count());
Dimitris Papastamoscc28fb82010-11-11 10:04:58 +0000917}
918
919static int snd_soc_lzo_cache_sync(struct snd_soc_codec *codec)
920{
921 struct snd_soc_lzo_ctx **lzo_blocks;
922 unsigned int val;
923 int i;
Dimitris Papastamos7a33d4c2010-11-29 10:24:54 +0000924 int ret;
Dimitris Papastamoscc28fb82010-11-11 10:04:58 +0000925
926 lzo_blocks = codec->reg_cache;
927 for_each_set_bit(i, lzo_blocks[0]->sync_bmp, lzo_blocks[0]->sync_bmp_nbits) {
Dimitris Papastamosf20eda52011-03-28 11:39:15 +0100928 WARN_ON(codec->writable_register &&
929 codec->writable_register(codec, i));
Dimitris Papastamos7a33d4c2010-11-29 10:24:54 +0000930 ret = snd_soc_cache_read(codec, i, &val);
931 if (ret)
932 return ret;
Dimitris Papastamos99780072011-01-19 14:53:37 +0000933 codec->cache_bypass = 1;
Dimitris Papastamos7a33d4c2010-11-29 10:24:54 +0000934 ret = snd_soc_write(codec, i, val);
Dimitris Papastamos99780072011-01-19 14:53:37 +0000935 codec->cache_bypass = 0;
Dimitris Papastamos7a33d4c2010-11-29 10:24:54 +0000936 if (ret)
937 return ret;
Dimitris Papastamoscc28fb82010-11-11 10:04:58 +0000938 dev_dbg(codec->dev, "Synced register %#x, value = %#x\n",
939 i, val);
940 }
941
942 return 0;
943}
944
945static int snd_soc_lzo_cache_write(struct snd_soc_codec *codec,
946 unsigned int reg, unsigned int value)
947{
948 struct snd_soc_lzo_ctx *lzo_block, **lzo_blocks;
949 int ret, blkindex, blkpos;
950 size_t blksize, tmp_dst_len;
951 void *tmp_dst;
952
953 /* index of the compressed lzo block */
954 blkindex = snd_soc_lzo_get_blkindex(codec, reg);
955 /* register index within the decompressed block */
956 blkpos = snd_soc_lzo_get_blkpos(codec, reg);
957 /* size of the compressed block */
958 blksize = snd_soc_lzo_get_blksize(codec);
959 lzo_blocks = codec->reg_cache;
960 lzo_block = lzo_blocks[blkindex];
961
962 /* save the pointer and length of the compressed block */
963 tmp_dst = lzo_block->dst;
964 tmp_dst_len = lzo_block->dst_len;
965
966 /* prepare the source to be the compressed block */
967 lzo_block->src = lzo_block->dst;
968 lzo_block->src_len = lzo_block->dst_len;
969
970 /* decompress the block */
971 ret = snd_soc_lzo_decompress_cache_block(codec, lzo_block);
972 if (ret < 0) {
973 kfree(lzo_block->dst);
974 goto out;
975 }
976
977 /* write the new value to the cache */
Dimitris Papastamos1321e882011-01-11 11:29:49 +0000978 if (snd_soc_set_cache_val(lzo_block->dst, blkpos, value,
979 codec->driver->reg_word_size)) {
980 kfree(lzo_block->dst);
981 goto out;
Dimitris Papastamoscc28fb82010-11-11 10:04:58 +0000982 }
983
984 /* prepare the source to be the decompressed block */
985 lzo_block->src = lzo_block->dst;
986 lzo_block->src_len = lzo_block->dst_len;
987
988 /* compress the block */
989 ret = snd_soc_lzo_compress_cache_block(codec, lzo_block);
990 if (ret < 0) {
991 kfree(lzo_block->dst);
992 kfree(lzo_block->src);
993 goto out;
994 }
995
996 /* set the bit so we know we have to sync this register */
997 set_bit(reg, lzo_block->sync_bmp);
998 kfree(tmp_dst);
999 kfree(lzo_block->src);
1000 return 0;
1001out:
1002 lzo_block->dst = tmp_dst;
1003 lzo_block->dst_len = tmp_dst_len;
1004 return ret;
1005}
1006
1007static int snd_soc_lzo_cache_read(struct snd_soc_codec *codec,
1008 unsigned int reg, unsigned int *value)
1009{
1010 struct snd_soc_lzo_ctx *lzo_block, **lzo_blocks;
1011 int ret, blkindex, blkpos;
1012 size_t blksize, tmp_dst_len;
1013 void *tmp_dst;
1014
1015 *value = 0;
1016 /* index of the compressed lzo block */
1017 blkindex = snd_soc_lzo_get_blkindex(codec, reg);
1018 /* register index within the decompressed block */
1019 blkpos = snd_soc_lzo_get_blkpos(codec, reg);
1020 /* size of the compressed block */
1021 blksize = snd_soc_lzo_get_blksize(codec);
1022 lzo_blocks = codec->reg_cache;
1023 lzo_block = lzo_blocks[blkindex];
1024
1025 /* save the pointer and length of the compressed block */
1026 tmp_dst = lzo_block->dst;
1027 tmp_dst_len = lzo_block->dst_len;
1028
1029 /* prepare the source to be the compressed block */
1030 lzo_block->src = lzo_block->dst;
1031 lzo_block->src_len = lzo_block->dst_len;
1032
1033 /* decompress the block */
1034 ret = snd_soc_lzo_decompress_cache_block(codec, lzo_block);
Dimitris Papastamos1321e882011-01-11 11:29:49 +00001035 if (ret >= 0)
Dimitris Papastamoscc28fb82010-11-11 10:04:58 +00001036 /* fetch the value from the cache */
Dimitris Papastamos1321e882011-01-11 11:29:49 +00001037 *value = snd_soc_get_cache_val(lzo_block->dst, blkpos,
1038 codec->driver->reg_word_size);
Dimitris Papastamoscc28fb82010-11-11 10:04:58 +00001039
1040 kfree(lzo_block->dst);
1041 /* restore the pointer and length of the compressed block */
1042 lzo_block->dst = tmp_dst;
1043 lzo_block->dst_len = tmp_dst_len;
1044 return 0;
1045}
1046
1047static int snd_soc_lzo_cache_exit(struct snd_soc_codec *codec)
1048{
1049 struct snd_soc_lzo_ctx **lzo_blocks;
1050 int i, blkcount;
1051
1052 lzo_blocks = codec->reg_cache;
1053 if (!lzo_blocks)
1054 return 0;
1055
1056 blkcount = snd_soc_lzo_block_count();
1057 /*
1058 * the pointer to the bitmap used for syncing the cache
1059 * is shared amongst all lzo_blocks. Ensure it is freed
1060 * only once.
1061 */
1062 if (lzo_blocks[0])
1063 kfree(lzo_blocks[0]->sync_bmp);
1064 for (i = 0; i < blkcount; ++i) {
1065 if (lzo_blocks[i]) {
1066 kfree(lzo_blocks[i]->wmem);
1067 kfree(lzo_blocks[i]->dst);
1068 }
1069 /* each lzo_block is a pointer returned by kmalloc or NULL */
1070 kfree(lzo_blocks[i]);
1071 }
1072 kfree(lzo_blocks);
1073 codec->reg_cache = NULL;
1074 return 0;
1075}
1076
1077static int snd_soc_lzo_cache_init(struct snd_soc_codec *codec)
1078{
1079 struct snd_soc_lzo_ctx **lzo_blocks;
Dimitris Papastamosaea170a2011-01-12 10:38:58 +00001080 size_t bmp_size;
Mark Brown001ae4c2010-12-02 16:21:08 +00001081 const struct snd_soc_codec_driver *codec_drv;
Dimitris Papastamoscc28fb82010-11-11 10:04:58 +00001082 int ret, tofree, i, blksize, blkcount;
1083 const char *p, *end;
1084 unsigned long *sync_bmp;
1085
1086 ret = 0;
1087 codec_drv = codec->driver;
Dimitris Papastamoscc28fb82010-11-11 10:04:58 +00001088
1089 /*
1090 * If we have not been given a default register cache
1091 * then allocate a dummy zero-ed out region, compress it
1092 * and remember to free it afterwards.
1093 */
1094 tofree = 0;
Dimitris Papastamos3335ddc2010-12-02 16:11:05 +00001095 if (!codec->reg_def_copy)
Dimitris Papastamoscc28fb82010-11-11 10:04:58 +00001096 tofree = 1;
1097
Dimitris Papastamos3335ddc2010-12-02 16:11:05 +00001098 if (!codec->reg_def_copy) {
Dimitris Papastamosaea170a2011-01-12 10:38:58 +00001099 codec->reg_def_copy = kzalloc(codec->reg_size, GFP_KERNEL);
Dimitris Papastamos3335ddc2010-12-02 16:11:05 +00001100 if (!codec->reg_def_copy)
Dimitris Papastamoscc28fb82010-11-11 10:04:58 +00001101 return -ENOMEM;
1102 }
1103
1104 blkcount = snd_soc_lzo_block_count();
1105 codec->reg_cache = kzalloc(blkcount * sizeof *lzo_blocks,
1106 GFP_KERNEL);
1107 if (!codec->reg_cache) {
1108 ret = -ENOMEM;
1109 goto err_tofree;
1110 }
1111 lzo_blocks = codec->reg_cache;
1112
1113 /*
1114 * allocate a bitmap to be used when syncing the cache with
1115 * the hardware. Each time a register is modified, the corresponding
1116 * bit is set in the bitmap, so we know that we have to sync
1117 * that register.
1118 */
1119 bmp_size = codec_drv->reg_cache_size;
Dimitris Papastamos465d7fc2010-12-14 15:15:36 +00001120 sync_bmp = kmalloc(BITS_TO_LONGS(bmp_size) * sizeof(long),
Dimitris Papastamoscc28fb82010-11-11 10:04:58 +00001121 GFP_KERNEL);
1122 if (!sync_bmp) {
1123 ret = -ENOMEM;
1124 goto err;
1125 }
Dimitris Papastamos09c74a92010-11-29 11:43:33 +00001126 bitmap_zero(sync_bmp, bmp_size);
Dimitris Papastamoscc28fb82010-11-11 10:04:58 +00001127
1128 /* allocate the lzo blocks and initialize them */
1129 for (i = 0; i < blkcount; ++i) {
1130 lzo_blocks[i] = kzalloc(sizeof **lzo_blocks,
1131 GFP_KERNEL);
1132 if (!lzo_blocks[i]) {
1133 kfree(sync_bmp);
1134 ret = -ENOMEM;
1135 goto err;
1136 }
1137 lzo_blocks[i]->sync_bmp = sync_bmp;
Dimitris Papastamos04f8fd12011-01-11 11:24:02 +00001138 lzo_blocks[i]->sync_bmp_nbits = bmp_size;
Dimitris Papastamoscc28fb82010-11-11 10:04:58 +00001139 /* alloc the working space for the compressed block */
1140 ret = snd_soc_lzo_prepare(lzo_blocks[i]);
1141 if (ret < 0)
1142 goto err;
1143 }
1144
1145 blksize = snd_soc_lzo_get_blksize(codec);
Dimitris Papastamos3335ddc2010-12-02 16:11:05 +00001146 p = codec->reg_def_copy;
Dimitris Papastamosaea170a2011-01-12 10:38:58 +00001147 end = codec->reg_def_copy + codec->reg_size;
Dimitris Papastamoscc28fb82010-11-11 10:04:58 +00001148 /* compress the register map and fill the lzo blocks */
1149 for (i = 0; i < blkcount; ++i, p += blksize) {
1150 lzo_blocks[i]->src = p;
1151 if (p + blksize > end)
1152 lzo_blocks[i]->src_len = end - p;
1153 else
1154 lzo_blocks[i]->src_len = blksize;
1155 ret = snd_soc_lzo_compress_cache_block(codec,
1156 lzo_blocks[i]);
1157 if (ret < 0)
1158 goto err;
1159 lzo_blocks[i]->decompressed_size =
1160 lzo_blocks[i]->src_len;
1161 }
1162
Dimitris Papastamos3335ddc2010-12-02 16:11:05 +00001163 if (tofree) {
1164 kfree(codec->reg_def_copy);
1165 codec->reg_def_copy = NULL;
1166 }
Dimitris Papastamoscc28fb82010-11-11 10:04:58 +00001167 return 0;
1168err:
1169 snd_soc_cache_exit(codec);
1170err_tofree:
Dimitris Papastamos3335ddc2010-12-02 16:11:05 +00001171 if (tofree) {
1172 kfree(codec->reg_def_copy);
1173 codec->reg_def_copy = NULL;
1174 }
Dimitris Papastamoscc28fb82010-11-11 10:04:58 +00001175 return ret;
1176}
Mark Brown68d44ee2010-12-21 17:19:56 +00001177#endif
Dimitris Papastamoscc28fb82010-11-11 10:04:58 +00001178
Dimitris Papastamos7a30a3d2010-11-11 10:04:57 +00001179static int snd_soc_flat_cache_sync(struct snd_soc_codec *codec)
1180{
1181 int i;
Dimitris Papastamos7a33d4c2010-11-29 10:24:54 +00001182 int ret;
Mark Brown001ae4c2010-12-02 16:21:08 +00001183 const struct snd_soc_codec_driver *codec_drv;
Dimitris Papastamos7a30a3d2010-11-11 10:04:57 +00001184 unsigned int val;
1185
1186 codec_drv = codec->driver;
1187 for (i = 0; i < codec_drv->reg_cache_size; ++i) {
Dimitris Papastamosf20eda52011-03-28 11:39:15 +01001188 WARN_ON(codec->writable_register &&
1189 codec->writable_register(codec, i));
Dimitris Papastamos7a33d4c2010-11-29 10:24:54 +00001190 ret = snd_soc_cache_read(codec, i, &val);
1191 if (ret)
1192 return ret;
Dimitris Papastamosd779fce2011-01-12 10:22:28 +00001193 if (codec->reg_def_copy)
1194 if (snd_soc_get_cache_val(codec->reg_def_copy,
Dimitris Papastamos1321e882011-01-11 11:29:49 +00001195 i, codec_drv->reg_word_size) == val)
1196 continue;
Dimitris Papastamos7a33d4c2010-11-29 10:24:54 +00001197 ret = snd_soc_write(codec, i, val);
1198 if (ret)
1199 return ret;
Dimitris Papastamos7a30a3d2010-11-11 10:04:57 +00001200 dev_dbg(codec->dev, "Synced register %#x, value = %#x\n",
1201 i, val);
1202 }
1203 return 0;
1204}
1205
1206static int snd_soc_flat_cache_write(struct snd_soc_codec *codec,
1207 unsigned int reg, unsigned int value)
1208{
Dimitris Papastamos1321e882011-01-11 11:29:49 +00001209 snd_soc_set_cache_val(codec->reg_cache, reg, value,
1210 codec->driver->reg_word_size);
Dimitris Papastamos7a30a3d2010-11-11 10:04:57 +00001211 return 0;
1212}
1213
1214static int snd_soc_flat_cache_read(struct snd_soc_codec *codec,
1215 unsigned int reg, unsigned int *value)
1216{
Dimitris Papastamos1321e882011-01-11 11:29:49 +00001217 *value = snd_soc_get_cache_val(codec->reg_cache, reg,
1218 codec->driver->reg_word_size);
Dimitris Papastamos7a30a3d2010-11-11 10:04:57 +00001219 return 0;
1220}
1221
1222static int snd_soc_flat_cache_exit(struct snd_soc_codec *codec)
1223{
1224 if (!codec->reg_cache)
1225 return 0;
1226 kfree(codec->reg_cache);
1227 codec->reg_cache = NULL;
1228 return 0;
1229}
1230
1231static int snd_soc_flat_cache_init(struct snd_soc_codec *codec)
1232{
Mark Brown001ae4c2010-12-02 16:21:08 +00001233 const struct snd_soc_codec_driver *codec_drv;
Dimitris Papastamos7a30a3d2010-11-11 10:04:57 +00001234
1235 codec_drv = codec->driver;
Dimitris Papastamos7a30a3d2010-11-11 10:04:57 +00001236
Dimitris Papastamosd779fce2011-01-12 10:22:28 +00001237 if (codec->reg_def_copy)
1238 codec->reg_cache = kmemdup(codec->reg_def_copy,
Dimitris Papastamosaea170a2011-01-12 10:38:58 +00001239 codec->reg_size, GFP_KERNEL);
Dimitris Papastamos7a30a3d2010-11-11 10:04:57 +00001240 else
Dimitris Papastamosaea170a2011-01-12 10:38:58 +00001241 codec->reg_cache = kzalloc(codec->reg_size, GFP_KERNEL);
Dimitris Papastamos7a30a3d2010-11-11 10:04:57 +00001242 if (!codec->reg_cache)
1243 return -ENOMEM;
1244
1245 return 0;
1246}
1247
1248/* an array of all supported compression types */
1249static const struct snd_soc_cache_ops cache_types[] = {
Mark Brownbe4fcdd2010-12-21 17:09:48 +00001250 /* Flat *must* be the first entry for fallback */
Dimitris Papastamos7a30a3d2010-11-11 10:04:57 +00001251 {
Dimitris Papastamosdf0701b2010-11-29 10:54:28 +00001252 .id = SND_SOC_FLAT_COMPRESSION,
Dimitris Papastamos0d735ea2010-12-06 09:51:57 +00001253 .name = "flat",
Dimitris Papastamos7a30a3d2010-11-11 10:04:57 +00001254 .init = snd_soc_flat_cache_init,
1255 .exit = snd_soc_flat_cache_exit,
1256 .read = snd_soc_flat_cache_read,
1257 .write = snd_soc_flat_cache_write,
1258 .sync = snd_soc_flat_cache_sync
Dimitris Papastamoscc28fb82010-11-11 10:04:58 +00001259 },
Mark Brown68d44ee2010-12-21 17:19:56 +00001260#ifdef CONFIG_SND_SOC_CACHE_LZO
Dimitris Papastamoscc28fb82010-11-11 10:04:58 +00001261 {
1262 .id = SND_SOC_LZO_COMPRESSION,
Dimitris Papastamos0d735ea2010-12-06 09:51:57 +00001263 .name = "LZO",
Dimitris Papastamoscc28fb82010-11-11 10:04:58 +00001264 .init = snd_soc_lzo_cache_init,
1265 .exit = snd_soc_lzo_cache_exit,
1266 .read = snd_soc_lzo_cache_read,
1267 .write = snd_soc_lzo_cache_write,
1268 .sync = snd_soc_lzo_cache_sync
Dimitris Papastamosa7f387d2010-11-11 10:04:59 +00001269 },
Mark Brown68d44ee2010-12-21 17:19:56 +00001270#endif
Dimitris Papastamosa7f387d2010-11-11 10:04:59 +00001271 {
1272 .id = SND_SOC_RBTREE_COMPRESSION,
Dimitris Papastamos0d735ea2010-12-06 09:51:57 +00001273 .name = "rbtree",
Dimitris Papastamosa7f387d2010-11-11 10:04:59 +00001274 .init = snd_soc_rbtree_cache_init,
1275 .exit = snd_soc_rbtree_cache_exit,
1276 .read = snd_soc_rbtree_cache_read,
1277 .write = snd_soc_rbtree_cache_write,
1278 .sync = snd_soc_rbtree_cache_sync
Dimitris Papastamos7a30a3d2010-11-11 10:04:57 +00001279 }
1280};
1281
1282int snd_soc_cache_init(struct snd_soc_codec *codec)
1283{
1284 int i;
1285
1286 for (i = 0; i < ARRAY_SIZE(cache_types); ++i)
Dimitris Papastamos23bbce32010-12-02 14:53:01 +00001287 if (cache_types[i].id == codec->compress_type)
Dimitris Papastamos7a30a3d2010-11-11 10:04:57 +00001288 break;
Mark Brownbe4fcdd2010-12-21 17:09:48 +00001289
1290 /* Fall back to flat compression */
Dimitris Papastamos7a30a3d2010-11-11 10:04:57 +00001291 if (i == ARRAY_SIZE(cache_types)) {
Mark Brownbe4fcdd2010-12-21 17:09:48 +00001292 dev_warn(codec->dev, "Could not match compress type: %d\n",
1293 codec->compress_type);
1294 i = 0;
Dimitris Papastamos7a30a3d2010-11-11 10:04:57 +00001295 }
1296
1297 mutex_init(&codec->cache_rw_mutex);
1298 codec->cache_ops = &cache_types[i];
1299
Dimitris Papastamos0d735ea2010-12-06 09:51:57 +00001300 if (codec->cache_ops->init) {
1301 if (codec->cache_ops->name)
1302 dev_dbg(codec->dev, "Initializing %s cache for %s codec\n",
1303 codec->cache_ops->name, codec->name);
Dimitris Papastamos7a30a3d2010-11-11 10:04:57 +00001304 return codec->cache_ops->init(codec);
Dimitris Papastamos0d735ea2010-12-06 09:51:57 +00001305 }
Dimitris Papastamosacd61452011-03-22 10:48:49 +00001306 return -ENOSYS;
Dimitris Papastamos7a30a3d2010-11-11 10:04:57 +00001307}
1308
1309/*
1310 * NOTE: keep in mind that this function might be called
1311 * multiple times.
1312 */
1313int snd_soc_cache_exit(struct snd_soc_codec *codec)
1314{
Dimitris Papastamos0d735ea2010-12-06 09:51:57 +00001315 if (codec->cache_ops && codec->cache_ops->exit) {
1316 if (codec->cache_ops->name)
1317 dev_dbg(codec->dev, "Destroying %s cache for %s codec\n",
1318 codec->cache_ops->name, codec->name);
Dimitris Papastamos7a30a3d2010-11-11 10:04:57 +00001319 return codec->cache_ops->exit(codec);
Dimitris Papastamos0d735ea2010-12-06 09:51:57 +00001320 }
Dimitris Papastamosacd61452011-03-22 10:48:49 +00001321 return -ENOSYS;
Dimitris Papastamos7a30a3d2010-11-11 10:04:57 +00001322}
1323
1324/**
1325 * snd_soc_cache_read: Fetch the value of a given register from the cache.
1326 *
1327 * @codec: CODEC to configure.
1328 * @reg: The register index.
1329 * @value: The value to be returned.
1330 */
1331int snd_soc_cache_read(struct snd_soc_codec *codec,
1332 unsigned int reg, unsigned int *value)
1333{
1334 int ret;
1335
1336 mutex_lock(&codec->cache_rw_mutex);
1337
1338 if (value && codec->cache_ops && codec->cache_ops->read) {
1339 ret = codec->cache_ops->read(codec, reg, value);
1340 mutex_unlock(&codec->cache_rw_mutex);
1341 return ret;
1342 }
1343
1344 mutex_unlock(&codec->cache_rw_mutex);
Dimitris Papastamosacd61452011-03-22 10:48:49 +00001345 return -ENOSYS;
Dimitris Papastamos7a30a3d2010-11-11 10:04:57 +00001346}
1347EXPORT_SYMBOL_GPL(snd_soc_cache_read);
1348
1349/**
1350 * snd_soc_cache_write: Set the value of a given register in the cache.
1351 *
1352 * @codec: CODEC to configure.
1353 * @reg: The register index.
1354 * @value: The new register value.
1355 */
1356int snd_soc_cache_write(struct snd_soc_codec *codec,
1357 unsigned int reg, unsigned int value)
1358{
1359 int ret;
1360
1361 mutex_lock(&codec->cache_rw_mutex);
1362
1363 if (codec->cache_ops && codec->cache_ops->write) {
1364 ret = codec->cache_ops->write(codec, reg, value);
1365 mutex_unlock(&codec->cache_rw_mutex);
1366 return ret;
1367 }
1368
1369 mutex_unlock(&codec->cache_rw_mutex);
Dimitris Papastamosacd61452011-03-22 10:48:49 +00001370 return -ENOSYS;
Dimitris Papastamos7a30a3d2010-11-11 10:04:57 +00001371}
1372EXPORT_SYMBOL_GPL(snd_soc_cache_write);
1373
1374/**
1375 * snd_soc_cache_sync: Sync the register cache with the hardware.
1376 *
1377 * @codec: CODEC to configure.
1378 *
1379 * Any registers that should not be synced should be marked as
1380 * volatile. In general drivers can choose not to use the provided
1381 * syncing functionality if they so require.
1382 */
1383int snd_soc_cache_sync(struct snd_soc_codec *codec)
1384{
1385 int ret;
Dimitris Papastamosc358e642011-01-21 15:29:02 +00001386 const char *name;
Dimitris Papastamos7a30a3d2010-11-11 10:04:57 +00001387
1388 if (!codec->cache_sync) {
1389 return 0;
1390 }
1391
Dan Carpenter46fdaa32011-02-07 22:01:41 +03001392 if (!codec->cache_ops || !codec->cache_ops->sync)
Dimitris Papastamosacd61452011-03-22 10:48:49 +00001393 return -ENOSYS;
Dan Carpenter46fdaa32011-02-07 22:01:41 +03001394
Dimitris Papastamosc358e642011-01-21 15:29:02 +00001395 if (codec->cache_ops->name)
1396 name = codec->cache_ops->name;
1397 else
1398 name = "unknown";
1399
Dan Carpenter46fdaa32011-02-07 22:01:41 +03001400 if (codec->cache_ops->name)
1401 dev_dbg(codec->dev, "Syncing %s cache for %s codec\n",
1402 codec->cache_ops->name, codec->name);
1403 trace_snd_soc_cache_sync(codec, name, "start");
1404 ret = codec->cache_ops->sync(codec);
1405 if (!ret)
1406 codec->cache_sync = 0;
1407 trace_snd_soc_cache_sync(codec, name, "end");
1408 return ret;
Dimitris Papastamos7a30a3d2010-11-11 10:04:57 +00001409}
1410EXPORT_SYMBOL_GPL(snd_soc_cache_sync);
Dimitris Papastamos066d16c2011-01-13 12:20:36 +00001411
1412static int snd_soc_get_reg_access_index(struct snd_soc_codec *codec,
1413 unsigned int reg)
1414{
1415 const struct snd_soc_codec_driver *codec_drv;
1416 unsigned int min, max, index;
1417
1418 codec_drv = codec->driver;
1419 min = 0;
1420 max = codec_drv->reg_access_size - 1;
1421 do {
1422 index = (min + max) / 2;
1423 if (codec_drv->reg_access_default[index].reg == reg)
1424 return index;
1425 if (codec_drv->reg_access_default[index].reg < reg)
1426 min = index + 1;
1427 else
1428 max = index;
1429 } while (min <= max);
1430 return -1;
1431}
1432
1433int snd_soc_default_volatile_register(struct snd_soc_codec *codec,
1434 unsigned int reg)
1435{
1436 int index;
1437
1438 if (reg >= codec->driver->reg_cache_size)
1439 return 1;
1440 index = snd_soc_get_reg_access_index(codec, reg);
1441 if (index < 0)
1442 return 0;
1443 return codec->driver->reg_access_default[index].vol;
1444}
1445EXPORT_SYMBOL_GPL(snd_soc_default_volatile_register);
1446
1447int snd_soc_default_readable_register(struct snd_soc_codec *codec,
1448 unsigned int reg)
1449{
1450 int index;
1451
1452 if (reg >= codec->driver->reg_cache_size)
1453 return 1;
1454 index = snd_soc_get_reg_access_index(codec, reg);
1455 if (index < 0)
1456 return 0;
1457 return codec->driver->reg_access_default[index].read;
1458}
1459EXPORT_SYMBOL_GPL(snd_soc_default_readable_register);
Dimitris Papastamos80204542011-03-24 13:45:17 +00001460
1461int snd_soc_default_writable_register(struct snd_soc_codec *codec,
1462 unsigned int reg)
1463{
1464 int index;
1465
1466 if (reg >= codec->driver->reg_cache_size)
1467 return 1;
1468 index = snd_soc_get_reg_access_index(codec, reg);
1469 if (index < 0)
1470 return 0;
1471 return codec->driver->reg_access_default[index].write;
1472}
1473EXPORT_SYMBOL_GPL(snd_soc_default_writable_register);