PageRenderTime 82ms CodeModel.GetById 22ms app.highlight 48ms RepoModel.GetById 2ms app.codeStats 0ms

/sound/soc/soc-cache.c

https://bitbucket.org/abioy/linux
C | 465 lines | 351 code | 78 blank | 36 comment | 52 complexity | a07b6c0025c54463fb2c648f118820e3 MD5 | raw file
Possible License(s): CC-BY-SA-3.0, GPL-2.0, LGPL-2.0, AGPL-1.0
  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
 18static 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
 27static 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)
 57static 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
 86static 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
 95static 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)
125static 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
154static 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
179static 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
188static 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
212static 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))
229static 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))
263static 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
296static 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
307static 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)
339static 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
370static 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 */
425int 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}
465EXPORT_SYMBOL_GPL(snd_soc_codec_set_cache_io);