1// SPDX-License-Identifier: GPL-2.0-or-later
2/*
3 *   Generic i2c interface for ALSA
4 *
5 *   (c) 1998 Gerd Knorr <kraxel@cs.tu-berlin.de>
6 *   Modified for the ALSA driver by Jaroslav Kysela <perex@perex.cz>
7 */
8
9#include <linux/init.h>
10#include <linux/slab.h>
11#include <linux/module.h>
12#include <linux/string.h>
13#include <linux/errno.h>
14#include <sound/core.h>
15#include <sound/i2c.h>
16
17MODULE_AUTHOR("Jaroslav Kysela <perex@perex.cz>");
18MODULE_DESCRIPTION("Generic i2c interface for ALSA");
19MODULE_LICENSE("GPL");
20
21static int snd_i2c_bit_sendbytes(struct snd_i2c_device *device,
22				 unsigned char *bytes, int count);
23static int snd_i2c_bit_readbytes(struct snd_i2c_device *device,
24				 unsigned char *bytes, int count);
25static int snd_i2c_bit_probeaddr(struct snd_i2c_bus *bus,
26				 unsigned short addr);
27
28static const struct snd_i2c_ops snd_i2c_bit_ops = {
29	.sendbytes = snd_i2c_bit_sendbytes,
30	.readbytes = snd_i2c_bit_readbytes,
31	.probeaddr = snd_i2c_bit_probeaddr,
32};
33
34static int snd_i2c_bus_free(struct snd_i2c_bus *bus)
35{
36	struct snd_i2c_bus *slave;
37	struct snd_i2c_device *device;
38
39	if (snd_BUG_ON(!bus))
40		return -EINVAL;
41	while (!list_empty(&bus->devices)) {
42		device = snd_i2c_device(bus->devices.next);
43		snd_i2c_device_free(device);
44	}
45	if (bus->master)
46		list_del(&bus->buses);
47	else {
48		while (!list_empty(&bus->buses)) {
49			slave = snd_i2c_slave_bus(bus->buses.next);
50			snd_device_free(bus->card, slave);
51		}
52	}
53	if (bus->private_free)
54		bus->private_free(bus);
55	kfree(bus);
56	return 0;
57}
58
59static int snd_i2c_bus_dev_free(struct snd_device *device)
60{
61	struct snd_i2c_bus *bus = device->device_data;
62	return snd_i2c_bus_free(bus);
63}
64
65int snd_i2c_bus_create(struct snd_card *card, const char *name,
66		       struct snd_i2c_bus *master, struct snd_i2c_bus **ri2c)
67{
68	struct snd_i2c_bus *bus;
69	int err;
70	static const struct snd_device_ops ops = {
71		.dev_free =	snd_i2c_bus_dev_free,
72	};
73
74	*ri2c = NULL;
75	bus = kzalloc(sizeof(*bus), GFP_KERNEL);
76	if (bus == NULL)
77		return -ENOMEM;
78	mutex_init(&bus->lock_mutex);
79	INIT_LIST_HEAD(&bus->devices);
80	INIT_LIST_HEAD(&bus->buses);
81	bus->card = card;
82	bus->ops = &snd_i2c_bit_ops;
83	if (master) {
84		list_add_tail(&bus->buses, &master->buses);
85		bus->master = master;
86	}
87	strscpy(bus->name, name, sizeof(bus->name));
88	err = snd_device_new(card, SNDRV_DEV_BUS, bus, &ops);
89	if (err < 0) {
90		snd_i2c_bus_free(bus);
91		return err;
92	}
93	*ri2c = bus;
94	return 0;
95}
96
97EXPORT_SYMBOL(snd_i2c_bus_create);
98
99int snd_i2c_device_create(struct snd_i2c_bus *bus, const char *name,
100			  unsigned char addr, struct snd_i2c_device **rdevice)
101{
102	struct snd_i2c_device *device;
103
104	*rdevice = NULL;
105	if (snd_BUG_ON(!bus))
106		return -EINVAL;
107	device = kzalloc(sizeof(*device), GFP_KERNEL);
108	if (device == NULL)
109		return -ENOMEM;
110	device->addr = addr;
111	strscpy(device->name, name, sizeof(device->name));
112	list_add_tail(&device->list, &bus->devices);
113	device->bus = bus;
114	*rdevice = device;
115	return 0;
116}
117
118EXPORT_SYMBOL(snd_i2c_device_create);
119
120int snd_i2c_device_free(struct snd_i2c_device *device)
121{
122	if (device->bus)
123		list_del(&device->list);
124	if (device->private_free)
125		device->private_free(device);
126	kfree(device);
127	return 0;
128}
129
130EXPORT_SYMBOL(snd_i2c_device_free);
131
132int snd_i2c_sendbytes(struct snd_i2c_device *device, unsigned char *bytes, int count)
133{
134	return device->bus->ops->sendbytes(device, bytes, count);
135}
136
137EXPORT_SYMBOL(snd_i2c_sendbytes);
138
139int snd_i2c_readbytes(struct snd_i2c_device *device, unsigned char *bytes, int count)
140{
141	return device->bus->ops->readbytes(device, bytes, count);
142}
143
144EXPORT_SYMBOL(snd_i2c_readbytes);
145
146int snd_i2c_probeaddr(struct snd_i2c_bus *bus, unsigned short addr)
147{
148	return bus->ops->probeaddr(bus, addr);
149}
150
151EXPORT_SYMBOL(snd_i2c_probeaddr);
152
153/*
154 *  bit-operations
155 */
156
157static inline void snd_i2c_bit_hw_start(struct snd_i2c_bus *bus)
158{
159	if (bus->hw_ops.bit->start)
160		bus->hw_ops.bit->start(bus);
161}
162
163static inline void snd_i2c_bit_hw_stop(struct snd_i2c_bus *bus)
164{
165	if (bus->hw_ops.bit->stop)
166		bus->hw_ops.bit->stop(bus);
167}
168
169static void snd_i2c_bit_direction(struct snd_i2c_bus *bus, int clock, int data)
170{
171	if (bus->hw_ops.bit->direction)
172		bus->hw_ops.bit->direction(bus, clock, data);
173}
174
175static void snd_i2c_bit_set(struct snd_i2c_bus *bus, int clock, int data)
176{
177	bus->hw_ops.bit->setlines(bus, clock, data);
178}
179
180#if 0
181static int snd_i2c_bit_clock(struct snd_i2c_bus *bus)
182{
183	if (bus->hw_ops.bit->getclock)
184		return bus->hw_ops.bit->getclock(bus);
185	return -ENXIO;
186}
187#endif
188
189static int snd_i2c_bit_data(struct snd_i2c_bus *bus, int ack)
190{
191	return bus->hw_ops.bit->getdata(bus, ack);
192}
193
194static void snd_i2c_bit_start(struct snd_i2c_bus *bus)
195{
196	snd_i2c_bit_hw_start(bus);
197	snd_i2c_bit_direction(bus, 1, 1);	/* SCL - wr, SDA - wr */
198	snd_i2c_bit_set(bus, 1, 1);
199	snd_i2c_bit_set(bus, 1, 0);
200	snd_i2c_bit_set(bus, 0, 0);
201}
202
203static void snd_i2c_bit_stop(struct snd_i2c_bus *bus)
204{
205	snd_i2c_bit_set(bus, 0, 0);
206	snd_i2c_bit_set(bus, 1, 0);
207	snd_i2c_bit_set(bus, 1, 1);
208	snd_i2c_bit_hw_stop(bus);
209}
210
211static void snd_i2c_bit_send(struct snd_i2c_bus *bus, int data)
212{
213	snd_i2c_bit_set(bus, 0, data);
214	snd_i2c_bit_set(bus, 1, data);
215	snd_i2c_bit_set(bus, 0, data);
216}
217
218static int snd_i2c_bit_ack(struct snd_i2c_bus *bus)
219{
220	int ack;
221
222	snd_i2c_bit_set(bus, 0, 1);
223	snd_i2c_bit_set(bus, 1, 1);
224	snd_i2c_bit_direction(bus, 1, 0);	/* SCL - wr, SDA - rd */
225	ack = snd_i2c_bit_data(bus, 1);
226	snd_i2c_bit_direction(bus, 1, 1);	/* SCL - wr, SDA - wr */
227	snd_i2c_bit_set(bus, 0, 1);
228	return ack ? -EIO : 0;
229}
230
231static int snd_i2c_bit_sendbyte(struct snd_i2c_bus *bus, unsigned char data)
232{
233	int i, err;
234
235	for (i = 7; i >= 0; i--)
236		snd_i2c_bit_send(bus, !!(data & (1 << i)));
237	err = snd_i2c_bit_ack(bus);
238	if (err < 0)
239		return err;
240	return 0;
241}
242
243static int snd_i2c_bit_readbyte(struct snd_i2c_bus *bus, int last)
244{
245	int i;
246	unsigned char data = 0;
247
248	snd_i2c_bit_set(bus, 0, 1);
249	snd_i2c_bit_direction(bus, 1, 0);	/* SCL - wr, SDA - rd */
250	for (i = 7; i >= 0; i--) {
251		snd_i2c_bit_set(bus, 1, 1);
252		if (snd_i2c_bit_data(bus, 0))
253			data |= (1 << i);
254		snd_i2c_bit_set(bus, 0, 1);
255	}
256	snd_i2c_bit_direction(bus, 1, 1);	/* SCL - wr, SDA - wr */
257	snd_i2c_bit_send(bus, !!last);
258	return data;
259}
260
261static int snd_i2c_bit_sendbytes(struct snd_i2c_device *device,
262				 unsigned char *bytes, int count)
263{
264	struct snd_i2c_bus *bus = device->bus;
265	int err, res = 0;
266
267	if (device->flags & SND_I2C_DEVICE_ADDRTEN)
268		return -EIO;		/* not yet implemented */
269	snd_i2c_bit_start(bus);
270	err = snd_i2c_bit_sendbyte(bus, device->addr << 1);
271	if (err < 0) {
272		snd_i2c_bit_hw_stop(bus);
273		return err;
274	}
275	while (count-- > 0) {
276		err = snd_i2c_bit_sendbyte(bus, *bytes++);
277		if (err < 0) {
278			snd_i2c_bit_hw_stop(bus);
279			return err;
280		}
281		res++;
282	}
283	snd_i2c_bit_stop(bus);
284	return res;
285}
286
287static int snd_i2c_bit_readbytes(struct snd_i2c_device *device,
288				 unsigned char *bytes, int count)
289{
290	struct snd_i2c_bus *bus = device->bus;
291	int err, res = 0;
292
293	if (device->flags & SND_I2C_DEVICE_ADDRTEN)
294		return -EIO;		/* not yet implemented */
295	snd_i2c_bit_start(bus);
296	err = snd_i2c_bit_sendbyte(bus, (device->addr << 1) | 1);
297	if (err < 0) {
298		snd_i2c_bit_hw_stop(bus);
299		return err;
300	}
301	while (count-- > 0) {
302		err = snd_i2c_bit_readbyte(bus, count == 0);
303		if (err < 0) {
304			snd_i2c_bit_hw_stop(bus);
305			return err;
306		}
307		*bytes++ = (unsigned char)err;
308		res++;
309	}
310	snd_i2c_bit_stop(bus);
311	return res;
312}
313
314static int snd_i2c_bit_probeaddr(struct snd_i2c_bus *bus, unsigned short addr)
315{
316	int err;
317
318	if (addr & 0x8000)	/* 10-bit address */
319		return -EIO;	/* not yet implemented */
320	if (addr & 0x7f80)	/* invalid address */
321		return -EINVAL;
322	snd_i2c_bit_start(bus);
323	err = snd_i2c_bit_sendbyte(bus, addr << 1);
324	snd_i2c_bit_stop(bus);
325	return err;
326}
327