Author | Tokens | Token Proportion | Commits | Commit Proportion |
---|---|---|---|---|
Jaroslav Kysela | 1321 | 79.63% | 7 | 11.86% |
Linus Torvalds (pre-git) | 188 | 11.33% | 36 | 61.02% |
Takashi Iwai | 98 | 5.91% | 4 | 6.78% |
Brian Waters | 24 | 1.45% | 1 | 1.69% |
Linus Torvalds | 13 | 0.78% | 4 | 6.78% |
David S. Miller | 6 | 0.36% | 2 | 3.39% |
Paul Gortmaker | 3 | 0.18% | 1 | 1.69% |
Thomas Gleixner | 2 | 0.12% | 1 | 1.69% |
Joe Perches | 2 | 0.12% | 1 | 1.69% |
Julia Lawall | 1 | 0.06% | 1 | 1.69% |
Ingo Molnar | 1 | 0.06% | 1 | 1.69% |
Total | 1659 | 59 |
// SPDX-License-Identifier: GPL-2.0-or-later /* * Generic i2c interface for ALSA * * (c) 1998 Gerd Knorr <kraxel@cs.tu-berlin.de> * Modified for the ALSA driver by Jaroslav Kysela <perex@perex.cz> */ #include <linux/init.h> #include <linux/slab.h> #include <linux/module.h> #include <linux/string.h> #include <linux/errno.h> #include <sound/core.h> #include <sound/i2c.h> MODULE_AUTHOR("Jaroslav Kysela <perex@perex.cz>"); MODULE_DESCRIPTION("Generic i2c interface for ALSA"); MODULE_LICENSE("GPL"); static int snd_i2c_bit_sendbytes(struct snd_i2c_device *device, unsigned char *bytes, int count); static int snd_i2c_bit_readbytes(struct snd_i2c_device *device, unsigned char *bytes, int count); static int snd_i2c_bit_probeaddr(struct snd_i2c_bus *bus, unsigned short addr); static const struct snd_i2c_ops snd_i2c_bit_ops = { .sendbytes = snd_i2c_bit_sendbytes, .readbytes = snd_i2c_bit_readbytes, .probeaddr = snd_i2c_bit_probeaddr, }; static int snd_i2c_bus_free(struct snd_i2c_bus *bus) { struct snd_i2c_bus *slave; struct snd_i2c_device *device; if (snd_BUG_ON(!bus)) return -EINVAL; while (!list_empty(&bus->devices)) { device = snd_i2c_device(bus->devices.next); snd_i2c_device_free(device); } if (bus->master) list_del(&bus->buses); else { while (!list_empty(&bus->buses)) { slave = snd_i2c_slave_bus(bus->buses.next); snd_device_free(bus->card, slave); } } if (bus->private_free) bus->private_free(bus); kfree(bus); return 0; } static int snd_i2c_bus_dev_free(struct snd_device *device) { struct snd_i2c_bus *bus = device->device_data; return snd_i2c_bus_free(bus); } int snd_i2c_bus_create(struct snd_card *card, const char *name, struct snd_i2c_bus *master, struct snd_i2c_bus **ri2c) { struct snd_i2c_bus *bus; int err; static const struct snd_device_ops ops = { .dev_free = snd_i2c_bus_dev_free, }; *ri2c = NULL; bus = kzalloc(sizeof(*bus), GFP_KERNEL); if (bus == NULL) return -ENOMEM; mutex_init(&bus->lock_mutex); INIT_LIST_HEAD(&bus->devices); INIT_LIST_HEAD(&bus->buses); bus->card = card; bus->ops = &snd_i2c_bit_ops; if (master) { list_add_tail(&bus->buses, &master->buses); bus->master = master; } strscpy(bus->name, name, sizeof(bus->name)); err = snd_device_new(card, SNDRV_DEV_BUS, bus, &ops); if (err < 0) { snd_i2c_bus_free(bus); return err; } *ri2c = bus; return 0; } EXPORT_SYMBOL(snd_i2c_bus_create); int snd_i2c_device_create(struct snd_i2c_bus *bus, const char *name, unsigned char addr, struct snd_i2c_device **rdevice) { struct snd_i2c_device *device; *rdevice = NULL; if (snd_BUG_ON(!bus)) return -EINVAL; device = kzalloc(sizeof(*device), GFP_KERNEL); if (device == NULL) return -ENOMEM; device->addr = addr; strscpy(device->name, name, sizeof(device->name)); list_add_tail(&device->list, &bus->devices); device->bus = bus; *rdevice = device; return 0; } EXPORT_SYMBOL(snd_i2c_device_create); int snd_i2c_device_free(struct snd_i2c_device *device) { if (device->bus) list_del(&device->list); if (device->private_free) device->private_free(device); kfree(device); return 0; } EXPORT_SYMBOL(snd_i2c_device_free); int snd_i2c_sendbytes(struct snd_i2c_device *device, unsigned char *bytes, int count) { return device->bus->ops->sendbytes(device, bytes, count); } EXPORT_SYMBOL(snd_i2c_sendbytes); int snd_i2c_readbytes(struct snd_i2c_device *device, unsigned char *bytes, int count) { return device->bus->ops->readbytes(device, bytes, count); } EXPORT_SYMBOL(snd_i2c_readbytes); int snd_i2c_probeaddr(struct snd_i2c_bus *bus, unsigned short addr) { return bus->ops->probeaddr(bus, addr); } EXPORT_SYMBOL(snd_i2c_probeaddr); /* * bit-operations */ static inline void snd_i2c_bit_hw_start(struct snd_i2c_bus *bus) { if (bus->hw_ops.bit->start) bus->hw_ops.bit->start(bus); } static inline void snd_i2c_bit_hw_stop(struct snd_i2c_bus *bus) { if (bus->hw_ops.bit->stop) bus->hw_ops.bit->stop(bus); } static void snd_i2c_bit_direction(struct snd_i2c_bus *bus, int clock, int data) { if (bus->hw_ops.bit->direction) bus->hw_ops.bit->direction(bus, clock, data); } static void snd_i2c_bit_set(struct snd_i2c_bus *bus, int clock, int data) { bus->hw_ops.bit->setlines(bus, clock, data); } #if 0 static int snd_i2c_bit_clock(struct snd_i2c_bus *bus) { if (bus->hw_ops.bit->getclock) return bus->hw_ops.bit->getclock(bus); return -ENXIO; } #endif static int snd_i2c_bit_data(struct snd_i2c_bus *bus, int ack) { return bus->hw_ops.bit->getdata(bus, ack); } static void snd_i2c_bit_start(struct snd_i2c_bus *bus) { snd_i2c_bit_hw_start(bus); snd_i2c_bit_direction(bus, 1, 1); /* SCL - wr, SDA - wr */ snd_i2c_bit_set(bus, 1, 1); snd_i2c_bit_set(bus, 1, 0); snd_i2c_bit_set(bus, 0, 0); } static void snd_i2c_bit_stop(struct snd_i2c_bus *bus) { snd_i2c_bit_set(bus, 0, 0); snd_i2c_bit_set(bus, 1, 0); snd_i2c_bit_set(bus, 1, 1); snd_i2c_bit_hw_stop(bus); } static void snd_i2c_bit_send(struct snd_i2c_bus *bus, int data) { snd_i2c_bit_set(bus, 0, data); snd_i2c_bit_set(bus, 1, data); snd_i2c_bit_set(bus, 0, data); } static int snd_i2c_bit_ack(struct snd_i2c_bus *bus) { int ack; snd_i2c_bit_set(bus, 0, 1); snd_i2c_bit_set(bus, 1, 1); snd_i2c_bit_direction(bus, 1, 0); /* SCL - wr, SDA - rd */ ack = snd_i2c_bit_data(bus, 1); snd_i2c_bit_direction(bus, 1, 1); /* SCL - wr, SDA - wr */ snd_i2c_bit_set(bus, 0, 1); return ack ? -EIO : 0; } static int snd_i2c_bit_sendbyte(struct snd_i2c_bus *bus, unsigned char data) { int i, err; for (i = 7; i >= 0; i--) snd_i2c_bit_send(bus, !!(data & (1 << i))); err = snd_i2c_bit_ack(bus); if (err < 0) return err; return 0; } static int snd_i2c_bit_readbyte(struct snd_i2c_bus *bus, int last) { int i; unsigned char data = 0; snd_i2c_bit_set(bus, 0, 1); snd_i2c_bit_direction(bus, 1, 0); /* SCL - wr, SDA - rd */ for (i = 7; i >= 0; i--) { snd_i2c_bit_set(bus, 1, 1); if (snd_i2c_bit_data(bus, 0)) data |= (1 << i); snd_i2c_bit_set(bus, 0, 1); } snd_i2c_bit_direction(bus, 1, 1); /* SCL - wr, SDA - wr */ snd_i2c_bit_send(bus, !!last); return data; } static int snd_i2c_bit_sendbytes(struct snd_i2c_device *device, unsigned char *bytes, int count) { struct snd_i2c_bus *bus = device->bus; int err, res = 0; if (device->flags & SND_I2C_DEVICE_ADDRTEN) return -EIO; /* not yet implemented */ snd_i2c_bit_start(bus); err = snd_i2c_bit_sendbyte(bus, device->addr << 1); if (err < 0) { snd_i2c_bit_hw_stop(bus); return err; } while (count-- > 0) { err = snd_i2c_bit_sendbyte(bus, *bytes++); if (err < 0) { snd_i2c_bit_hw_stop(bus); return err; } res++; } snd_i2c_bit_stop(bus); return res; } static int snd_i2c_bit_readbytes(struct snd_i2c_device *device, unsigned char *bytes, int count) { struct snd_i2c_bus *bus = device->bus; int err, res = 0; if (device->flags & SND_I2C_DEVICE_ADDRTEN) return -EIO; /* not yet implemented */ snd_i2c_bit_start(bus); err = snd_i2c_bit_sendbyte(bus, (device->addr << 1) | 1); if (err < 0) { snd_i2c_bit_hw_stop(bus); return err; } while (count-- > 0) { err = snd_i2c_bit_readbyte(bus, count == 0); if (err < 0) { snd_i2c_bit_hw_stop(bus); return err; } *bytes++ = (unsigned char)err; res++; } snd_i2c_bit_stop(bus); return res; } static int snd_i2c_bit_probeaddr(struct snd_i2c_bus *bus, unsigned short addr) { int err; if (addr & 0x8000) /* 10-bit address */ return -EIO; /* not yet implemented */ if (addr & 0x7f80) /* invalid address */ return -EINVAL; snd_i2c_bit_start(bus); err = snd_i2c_bit_sendbyte(bus, addr << 1); snd_i2c_bit_stop(bus); return err; }
Information contained on this website is for historical information purposes only and does not indicate or represent copyright ownership.
Created with Cregit http://github.com/cregit/cregit
Version 2.0-RC1