aboutsummaryrefslogtreecommitdiff
path: root/sound/i2c
diff options
context:
space:
mode:
Diffstat (limited to 'sound/i2c')
-rw-r--r--sound/i2c/Makefile2
-rw-r--r--sound/i2c/cs8427.c94
-rw-r--r--sound/i2c/i2c.c25
-rw-r--r--sound/i2c/l3/Makefile8
-rw-r--r--sound/i2c/l3/uda1341.c936
-rw-r--r--sound/i2c/other/Makefile5
-rw-r--r--sound/i2c/other/ak4113.c639
-rw-r--r--sound/i2c/other/ak4114.c45
-rw-r--r--sound/i2c/other/ak4117.c8
-rw-r--r--sound/i2c/other/ak4xxx-adda.c151
-rw-r--r--sound/i2c/other/pt2258.c1
-rw-r--r--sound/i2c/other/tea575x-tuner.c239
-rw-r--r--sound/i2c/tea6330t.c1
13 files changed, 864 insertions, 1290 deletions
diff --git a/sound/i2c/Makefile b/sound/i2c/Makefile
index 37970666a45..36879bf8870 100644
--- a/sound/i2c/Makefile
+++ b/sound/i2c/Makefile
@@ -7,8 +7,6 @@ snd-i2c-objs := i2c.o
snd-cs8427-objs := cs8427.o
snd-tea6330t-objs := tea6330t.o
-obj-$(CONFIG_L3) += l3/
-
obj-$(CONFIG_SND) += other/
# Toplevel Module Dependency
diff --git a/sound/i2c/cs8427.c b/sound/i2c/cs8427.c
index e57e9cbe6a0..7e21621e492 100644
--- a/sound/i2c/cs8427.c
+++ b/sound/i2c/cs8427.c
@@ -23,6 +23,9 @@
#include <linux/slab.h>
#include <linux/delay.h>
#include <linux/init.h>
+#include <linux/bitrev.h>
+#include <linux/module.h>
+#include <asm/unaligned.h>
#include <sound/core.h>
#include <sound/control.h>
#include <sound/pcm.h>
@@ -54,18 +57,6 @@ struct cs8427 {
struct cs8427_stream capture;
};
-static unsigned char swapbits(unsigned char val)
-{
- int bit;
- unsigned char res = 0;
- for (bit = 0; bit < 8; bit++) {
- res <<= 1;
- res |= val & 1;
- val >>= 1;
- }
- return res;
-}
-
int snd_cs8427_reg_write(struct snd_i2c_device *device, unsigned char reg,
unsigned char val)
{
@@ -148,7 +139,7 @@ static int snd_cs8427_send_corudata(struct snd_i2c_device *device,
}
data[0] = CS8427_REG_AUTOINC | CS8427_REG_CORU_DATABUF;
for (idx = 0; idx < count; idx++)
- data[idx + 1] = swapbits(ndata[idx]);
+ data[idx + 1] = bitrev8(ndata[idx]);
if (snd_i2c_sendbytes(device, data, count + 1) != count + 1)
return -EIO;
return 1;
@@ -159,10 +150,8 @@ static void snd_cs8427_free(struct snd_i2c_device *device)
kfree(device->private_data);
}
-int snd_cs8427_create(struct snd_i2c_bus *bus,
- unsigned char addr,
- unsigned int reset_timeout,
- struct snd_i2c_device **r_cs8427)
+int snd_cs8427_init(struct snd_i2c_bus *bus,
+ struct snd_i2c_device *device)
{
static unsigned char initvals1[] = {
CS8427_REG_CONTROL1 | CS8427_REG_AUTOINC,
@@ -209,22 +198,10 @@ int snd_cs8427_create(struct snd_i2c_bus *bus,
Inhibit E->F transfers. */
CS8427_UD | CS8427_EFTUI | CS8427_DETUI,
};
+ struct cs8427 *chip = device->private_data;
int err;
- struct cs8427 *chip;
- struct snd_i2c_device *device;
unsigned char buf[24];
- if ((err = snd_i2c_device_create(bus, "CS8427",
- CS8427_ADDR | (addr & 7),
- &device)) < 0)
- return err;
- chip = device->private_data = kzalloc(sizeof(*chip), GFP_KERNEL);
- if (chip == NULL) {
- snd_i2c_device_free(device);
- return -ENOMEM;
- }
- device->private_free = snd_cs8427_free;
-
snd_i2c_lock(bus);
err = snd_cs8427_reg_read(device, CS8427_REG_ID_AND_VER);
if (err != CS8427_VER8427A) {
@@ -264,10 +241,7 @@ int snd_cs8427_create(struct snd_i2c_bus *bus,
goto __fail;
}
/* write default channel status bytes */
- buf[0] = ((unsigned char)(SNDRV_PCM_DEFAULT_CON_SPDIF >> 0));
- buf[1] = ((unsigned char)(SNDRV_PCM_DEFAULT_CON_SPDIF >> 8));
- buf[2] = ((unsigned char)(SNDRV_PCM_DEFAULT_CON_SPDIF >> 16));
- buf[3] = ((unsigned char)(SNDRV_PCM_DEFAULT_CON_SPDIF >> 24));
+ put_unaligned_le32(SNDRV_PCM_DEFAULT_CON_SPDIF, buf);
memset(buf + 4, 0, 24 - 4);
if (snd_cs8427_send_corudata(device, 0, buf, 24) < 0)
goto __fail;
@@ -276,10 +250,44 @@ int snd_cs8427_create(struct snd_i2c_bus *bus,
snd_i2c_unlock(bus);
/* turn on run bit and rock'n'roll */
+ snd_cs8427_reset(device);
+
+ return 0;
+
+__fail:
+ snd_i2c_unlock(bus);
+
+ return err;
+}
+EXPORT_SYMBOL(snd_cs8427_init);
+
+int snd_cs8427_create(struct snd_i2c_bus *bus,
+ unsigned char addr,
+ unsigned int reset_timeout,
+ struct snd_i2c_device **r_cs8427)
+{
+ int err;
+ struct cs8427 *chip;
+ struct snd_i2c_device *device;
+
+ err = snd_i2c_device_create(bus, "CS8427", CS8427_ADDR | (addr & 7),
+ &device);
+ if (err < 0)
+ return err;
+ chip = device->private_data = kzalloc(sizeof(*chip), GFP_KERNEL);
+ if (chip == NULL) {
+ snd_i2c_device_free(device);
+ return -ENOMEM;
+ }
+ device->private_free = snd_cs8427_free;
+
if (reset_timeout < 1)
reset_timeout = 1;
chip->reset_timeout = reset_timeout;
- snd_cs8427_reset(device);
+
+ err = snd_cs8427_init(bus, device);
+ if (err)
+ goto __fail;
#if 0 // it's nice for read tests
{
@@ -298,7 +306,6 @@ int snd_cs8427_create(struct snd_i2c_bus *bus,
return 0;
__fail:
- snd_i2c_unlock(bus);
snd_i2c_device_free(device);
return err < 0 ? err : -EIO;
}
@@ -316,7 +323,8 @@ static void snd_cs8427_reset(struct snd_i2c_device *cs8427)
unsigned long end_time;
int data, aes3input = 0;
- snd_assert(cs8427, return);
+ if (snd_BUG_ON(!cs8427))
+ return;
chip = cs8427->private_data;
snd_i2c_lock(cs8427->bus);
if ((chip->regmap[CS8427_REG_CLOCKSOURCE] & CS8427_RXDAES3INPUT) ==
@@ -528,7 +536,8 @@ int snd_cs8427_iec958_build(struct snd_i2c_device *cs8427,
unsigned int idx;
int err;
- snd_assert(play_substream && cap_substream, return -EINVAL);
+ if (snd_BUG_ON(!play_substream || !cap_substream))
+ return -EINVAL;
for (idx = 0; idx < ARRAY_SIZE(snd_cs8427_iec958_controls); idx++) {
kctl = snd_ctl_new1(&snd_cs8427_iec958_controls[idx], cs8427);
if (kctl == NULL)
@@ -545,7 +554,8 @@ int snd_cs8427_iec958_build(struct snd_i2c_device *cs8427,
chip->playback.substream = play_substream;
chip->capture.substream = cap_substream;
- snd_assert(chip->playback.pcm_ctl, return -EIO);
+ if (snd_BUG_ON(!chip->playback.pcm_ctl))
+ return -EIO;
return 0;
}
@@ -555,7 +565,8 @@ int snd_cs8427_iec958_active(struct snd_i2c_device *cs8427, int active)
{
struct cs8427 *chip;
- snd_assert(cs8427, return -ENXIO);
+ if (snd_BUG_ON(!cs8427))
+ return -ENXIO;
chip = cs8427->private_data;
if (active)
memcpy(chip->playback.pcm_status,
@@ -575,7 +586,8 @@ int snd_cs8427_iec958_pcm(struct snd_i2c_device *cs8427, unsigned int rate)
char *status;
int err, reset;
- snd_assert(cs8427, return -ENXIO);
+ if (snd_BUG_ON(!cs8427))
+ return -ENXIO;
chip = cs8427->private_data;
status = chip->playback.pcm_status;
snd_i2c_lock(cs8427->bus);
diff --git a/sound/i2c/i2c.c b/sound/i2c/i2c.c
index b1e74e40cba..4677037f0c8 100644
--- a/sound/i2c/i2c.c
+++ b/sound/i2c/i2c.c
@@ -22,6 +22,7 @@
#include <linux/init.h>
#include <linux/slab.h>
+#include <linux/module.h>
#include <linux/string.h>
#include <linux/errno.h>
#include <sound/core.h>
@@ -49,7 +50,8 @@ static int snd_i2c_bus_free(struct snd_i2c_bus *bus)
struct snd_i2c_bus *slave;
struct snd_i2c_device *device;
- snd_assert(bus != NULL, return -EINVAL);
+ if (snd_BUG_ON(!bus))
+ return -EINVAL;
while (!list_empty(&bus->devices)) {
device = snd_i2c_device(bus->devices.next);
snd_i2c_device_free(device);
@@ -97,7 +99,8 @@ int snd_i2c_bus_create(struct snd_card *card, const char *name,
bus->master = master;
}
strlcpy(bus->name, name, sizeof(bus->name));
- if ((err = snd_device_new(card, SNDRV_DEV_BUS, bus, &ops)) < 0) {
+ err = snd_device_new(card, SNDRV_DEV_BUS, bus, &ops);
+ if (err < 0) {
snd_i2c_bus_free(bus);
return err;
}
@@ -113,7 +116,8 @@ int snd_i2c_device_create(struct snd_i2c_bus *bus, const char *name,
struct snd_i2c_device *device;
*rdevice = NULL;
- snd_assert(bus != NULL, return -EINVAL);
+ if (snd_BUG_ON(!bus))
+ return -EINVAL;
device = kzalloc(sizeof(*device), GFP_KERNEL);
if (device == NULL)
return -ENOMEM;
@@ -244,7 +248,8 @@ static int snd_i2c_bit_sendbyte(struct snd_i2c_bus *bus, unsigned char data)
for (i = 7; i >= 0; i--)
snd_i2c_bit_send(bus, !!(data & (1 << i)));
- if ((err = snd_i2c_bit_ack(bus)) < 0)
+ err = snd_i2c_bit_ack(bus);
+ if (err < 0)
return err;
return 0;
}
@@ -276,12 +281,14 @@ static int snd_i2c_bit_sendbytes(struct snd_i2c_device *device,
if (device->flags & SND_I2C_DEVICE_ADDRTEN)
return -EIO; /* not yet implemented */
snd_i2c_bit_start(bus);
- if ((err = snd_i2c_bit_sendbyte(bus, device->addr << 1)) < 0) {
+ err = snd_i2c_bit_sendbyte(bus, device->addr << 1);
+ if (err < 0) {
snd_i2c_bit_hw_stop(bus);
return err;
}
while (count-- > 0) {
- if ((err = snd_i2c_bit_sendbyte(bus, *bytes++)) < 0) {
+ err = snd_i2c_bit_sendbyte(bus, *bytes++);
+ if (err < 0) {
snd_i2c_bit_hw_stop(bus);
return err;
}
@@ -300,12 +307,14 @@ static int snd_i2c_bit_readbytes(struct snd_i2c_device *device,
if (device->flags & SND_I2C_DEVICE_ADDRTEN)
return -EIO; /* not yet implemented */
snd_i2c_bit_start(bus);
- if ((err = snd_i2c_bit_sendbyte(bus, (device->addr << 1) | 1)) < 0) {
+ err = snd_i2c_bit_sendbyte(bus, (device->addr << 1) | 1);
+ if (err < 0) {
snd_i2c_bit_hw_stop(bus);
return err;
}
while (count-- > 0) {
- if ((err = snd_i2c_bit_readbyte(bus, count == 0)) < 0) {
+ err = snd_i2c_bit_readbyte(bus, count == 0);
+ if (err < 0) {
snd_i2c_bit_hw_stop(bus);
return err;
}
diff --git a/sound/i2c/l3/Makefile b/sound/i2c/l3/Makefile
deleted file mode 100644
index 49455b8dcc0..00000000000
--- a/sound/i2c/l3/Makefile
+++ /dev/null
@@ -1,8 +0,0 @@
-#
-# Makefile for ALSA
-#
-
-snd-uda1341-objs := uda1341.o
-
-# Module Dependency
-obj-$(CONFIG_SND_SA11XX_UDA1341) += snd-uda1341.o
diff --git a/sound/i2c/l3/uda1341.c b/sound/i2c/l3/uda1341.c
deleted file mode 100644
index bfa5d2c3608..00000000000
--- a/sound/i2c/l3/uda1341.c
+++ /dev/null
@@ -1,936 +0,0 @@
-/*
- * Philips UDA1341 mixer device driver
- * Copyright (c) 2002 Tomas Kasparek <tomas.kasparek@seznam.cz>
- *
- * Portions are Copyright (C) 2000 Lernout & Hauspie Speech Products, N.V.
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public License.
- *
- * History:
- *
- * 2002-03-13 Tomas Kasparek initial release - based on uda1341.c from OSS
- * 2002-03-28 Tomas Kasparek basic mixer is working (volume, bass, treble)
- * 2002-03-30 Tomas Kasparek proc filesystem support, complete mixer and DSP
- * features support
- * 2002-04-12 Tomas Kasparek proc interface update, code cleanup
- * 2002-05-12 Tomas Kasparek another code cleanup
- */
-
-/* $Id: uda1341.c,v 1.18 2005/11/17 14:17:21 tiwai Exp $ */
-
-#include <linux/module.h>
-#include <linux/init.h>
-#include <linux/types.h>
-#include <linux/slab.h>
-#include <linux/errno.h>
-#include <linux/ioctl.h>
-
-#include <asm/uaccess.h>
-
-#include <sound/core.h>
-#include <sound/control.h>
-#include <sound/initval.h>
-#include <sound/info.h>
-
-#include <linux/l3/l3.h>
-
-#include <sound/uda1341.h>
-
-/* {{{ HW regs definition */
-
-#define STAT0 0x00
-#define STAT1 0x80
-#define STAT_MASK 0x80
-
-#define DATA0_0 0x00
-#define DATA0_1 0x40
-#define DATA0_2 0x80
-#define DATA_MASK 0xc0
-
-#define IS_DATA0(x) ((x) >= data0_0 && (x) <= data0_2)
-#define IS_DATA1(x) ((x) == data1)
-#define IS_STATUS(x) ((x) == stat0 || (x) == stat1)
-#define IS_EXTEND(x) ((x) >= ext0 && (x) <= ext6)
-
-/* }}} */
-
-
-static const char *peak_names[] = {
- "before",
- "after",
-};
-
-static const char *filter_names[] = {
- "flat",
- "min",
- "min",
- "max",
-};
-
-static const char *mixer_names[] = {
- "double differential",
- "input channel 1 (line in)",
- "input channel 2 (microphone)",
- "digital mixer",
-};
-
-static const char *deemp_names[] = {
- "none",
- "32 kHz",
- "44.1 kHz",
- "48 kHz",
-};
-
-enum uda1341_regs_names {
- stat0,
- stat1,
- data0_0,
- data0_1,
- data0_2,
- data1,
- ext0,
- ext1,
- ext2,
- empty,
- ext4,
- ext5,
- ext6,
- uda1341_reg_last,
-};
-
-static const char *uda1341_reg_names[] = {
- "stat 0 ",
- "stat 1 ",
- "data 00",
- "data 01",
- "data 02",
- "data 1 ",
- "ext 0",
- "ext 1",
- "ext 2",
- "empty",
- "ext 4",
- "ext 5",
- "ext 6",
-};
-
-static const int uda1341_enum_items[] = {
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 2, //peak - before/after
- 4, //deemp - none/32/44.1/48
- 0,
- 4, //filter - flat/min/min/max
- 0, 0, 0,
- 4, //mixer - differ/line/mic/mixer
- 0, 0, 0, 0, 0,
-};
-
-static const char ** uda1341_enum_names[] = {
- NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
- peak_names, //peak - before/after
- deemp_names, //deemp - none/32/44.1/48
- NULL,
- filter_names, //filter - flat/min/min/max
- NULL, NULL, NULL,
- mixer_names, //mixer - differ/line/mic/mixer
- NULL, NULL, NULL, NULL, NULL,
-};
-
-typedef int uda1341_cfg[CMD_LAST];
-
-struct uda1341 {
- int (*write) (struct l3_client *uda1341, unsigned short reg, unsigned short val);
- int (*read) (struct l3_client *uda1341, unsigned short reg);
- unsigned char regs[uda1341_reg_last];
- int active;
- spinlock_t reg_lock;
- struct snd_card *card;
- uda1341_cfg cfg;
-#ifdef CONFIG_PM
- unsigned char suspend_regs[uda1341_reg_last];
- uda1341_cfg suspend_cfg;
-#endif
-};
-
-/* transfer 8bit integer into string with binary representation */
-static void int2str_bin8(uint8_t val, char *buf)
-{
- const int size = sizeof(val) * 8;
- int i;
-
- for (i= 0; i < size; i++){
- *(buf++) = (val >> (size - 1)) ? '1' : '0';
- val <<= 1;
- }
- *buf = '\0'; //end the string with zero
-}
-
-/* {{{ HW manipulation routines */
-
-static int snd_uda1341_codec_write(struct l3_client *clnt, unsigned short reg, unsigned short val)
-{
- struct uda1341 *uda = clnt->driver_data;
- unsigned char buf[2] = { 0xc0, 0xe0 }; // for EXT addressing
- int err = 0;
-
- uda->regs[reg] = val;
-
- if (uda->active) {
- if (IS_DATA0(reg)) {
- err = l3_write(clnt, UDA1341_DATA0, (const unsigned char *)&val, 1);
- } else if (IS_DATA1(reg)) {
- err = l3_write(clnt, UDA1341_DATA1, (const unsigned char *)&val, 1);
- } else if (IS_STATUS(reg)) {
- err = l3_write(clnt, UDA1341_STATUS, (const unsigned char *)&val, 1);
- } else if (IS_EXTEND(reg)) {
- buf[0] |= (reg - ext0) & 0x7; //EXT address
- buf[1] |= val; //EXT data
- err = l3_write(clnt, UDA1341_DATA0, (const unsigned char *)buf, 2);
- }
- } else
- printk(KERN_ERR "UDA1341 codec not active!\n");
- return err;
-}
-
-static int snd_uda1341_codec_read(struct l3_client *clnt, unsigned short reg)
-{
- unsigned char val;
- int err;
-
- err = l3_read(clnt, reg, &val, 1);
- if (err == 1)
- // use just 6bits - the rest is address of the reg
- return val & 63;
- return err < 0 ? err : -EIO;
-}
-
-static inline int snd_uda1341_valid_reg(struct l3_client *clnt, unsigned short reg)
-{
- return reg < uda1341_reg_last;
-}
-
-static int snd_uda1341_update_bits(struct l3_client *clnt, unsigned short reg,
- unsigned short mask, unsigned short shift,
- unsigned short value, int flush)
-{
- int change;
- unsigned short old, new;
- struct uda1341 *uda = clnt->driver_data;
-
-#if 0
- printk(KERN_DEBUG "update_bits: reg: %s mask: %d shift: %d val: %d\n",
- uda1341_reg_names[reg], mask, shift, value);
-#endif
-
- if (!snd_uda1341_valid_reg(clnt, reg))
- return -EINVAL;
- spin_lock(&uda->reg_lock);
- old = uda->regs[reg];
- new = (old & ~(mask << shift)) | (value << shift);
- change = old != new;
- if (change) {
- if (flush) uda->write(clnt, reg, new);
- uda->regs[reg] = new;
- }
- spin_unlock(&uda->reg_lock);
- return change;
-}
-
-static int snd_uda1341_cfg_write(struct l3_client *clnt, unsigned short what,
- unsigned short value, int flush)
-{
- struct uda1341 *uda = clnt->driver_data;
- int ret = 0;
-#ifdef CONFIG_PM
- int reg;
-#endif
-
-#if 0
- printk(KERN_DEBUG "cfg_write what: %d value: %d\n", what, value);
-#endif
-
- uda->cfg[what] = value;
-
- switch(what) {
- case CMD_RESET:
- ret = snd_uda1341_update_bits(clnt, data0_2, 1, 2, 1, flush); // MUTE
- ret = snd_uda1341_update_bits(clnt, stat0, 1, 6, 1, flush); // RESET
- ret = snd_uda1341_update_bits(clnt, stat0, 1, 6, 0, flush); // RESTORE
- uda->cfg[CMD_RESET]=0;
- break;
- case CMD_FS:
- ret = snd_uda1341_update_bits(clnt, stat0, 3, 4, value, flush);
- break;
- case CMD_FORMAT:
- ret = snd_uda1341_update_bits(clnt, stat0, 7, 1, value, flush);
- break;
- case CMD_OGAIN:
- ret = snd_uda1341_update_bits(clnt, stat1, 1, 6, value, flush);
- break;
- case CMD_IGAIN:
- ret = snd_uda1341_update_bits(clnt, stat1, 1, 5, value, flush);
- break;
- case CMD_DAC:
- ret = snd_uda1341_update_bits(clnt, stat1, 1, 0, value, flush);
- break;
- case CMD_ADC:
- ret = snd_uda1341_update_bits(clnt, stat1, 1, 1, value, flush);
- break;
- case CMD_VOLUME:
- ret = snd_uda1341_update_bits(clnt, data0_0, 63, 0, value, flush);
- break;
- case CMD_BASS:
- ret = snd_uda1341_update_bits(clnt, data0_1, 15, 2, value, flush);
- break;
- case CMD_TREBBLE:
- ret = snd_uda1341_update_bits(clnt, data0_1, 3, 0, value, flush);
- break;
- case CMD_PEAK:
- ret = snd_uda1341_update_bits(clnt, data0_2, 1, 5, value, flush);
- break;
- case CMD_DEEMP:
- ret = snd_uda1341_update_bits(clnt, data0_2, 3, 3, value, flush);
- break;
- case CMD_MUTE:
- ret = snd_uda1341_update_bits(clnt, data0_2, 1, 2, value, flush);
- break;
- case CMD_FILTER:
- ret = snd_uda1341_update_bits(clnt, data0_2, 3, 0, value, flush);
- break;
- case CMD_CH1:
- ret = snd_uda1341_update_bits(clnt, ext0, 31, 0, value, flush);
- break;
- case CMD_CH2:
- ret = snd_uda1341_update_bits(clnt, ext1, 31, 0, value, flush);
- break;
- case CMD_MIC:
- ret = snd_uda1341_update_bits(clnt, ext2, 7, 2, value, flush);
- break;
- case CMD_MIXER:
- ret = snd_uda1341_update_bits(clnt, ext2, 3, 0, value, flush);
- break;
- case CMD_AGC:
- ret = snd_uda1341_update_bits(clnt, ext4, 1, 4, value, flush);
- break;
- case CMD_IG:
- ret = snd_uda1341_update_bits(clnt, ext4, 3, 0, value & 0x3, flush);
- ret = snd_uda1341_update_bits(clnt, ext5, 31, 0, value >> 2, flush);
- break;
- case CMD_AGC_TIME:
- ret = snd_uda1341_update_bits(clnt, ext6, 7, 2, value, flush);
- break;
- case CMD_AGC_LEVEL:
- ret = snd_uda1341_update_bits(clnt, ext6, 3, 0, value, flush);
- break;
-#ifdef CONFIG_PM
- case CMD_SUSPEND:
- for (reg = stat0; reg < uda1341_reg_last; reg++)
- uda->suspend_regs[reg] = uda->regs[reg];
- for (reg = 0; reg < CMD_LAST; reg++)
- uda->suspend_cfg[reg] = uda->cfg[reg];
- break;
- case CMD_RESUME:
- for (reg = stat0; reg < uda1341_reg_last; reg++)
- snd_uda1341_codec_write(clnt, reg, uda->suspend_regs[reg]);
- for (reg = 0; reg < CMD_LAST; reg++)
- uda->cfg[reg] = uda->suspend_cfg[reg];
- break;
-#endif
- default:
- ret = -EINVAL;
- break;
- }
-
- if (!uda->active)
- printk(KERN_ERR "UDA1341 codec not active!\n");
- return ret;
-}
-
-/* }}} */
-
-/* {{{ Proc interface */
-#ifdef CONFIG_PROC_FS
-
-static const char *format_names[] = {
- "I2S-bus",
- "LSB 16bits",
- "LSB 18bits",
- "LSB 20bits",
- "MSB",
- "in LSB 16bits/out MSB",
- "in LSB 18bits/out MSB",
- "in LSB 20bits/out MSB",
-};
-
-static const char *fs_names[] = {
- "512*fs",
- "384*fs",
- "256*fs",
- "Unused - bad value!",
-};
-
-static const char* bass_values[][16] = {
- {"0 dB", "0 dB", "0 dB", "0 dB", "0 dB", "0 dB", "0 dB", "0 dB", "0 dB", "0 dB", "0 dB",
- "0 dB", "0 dB", "0 dB", "0 dB", "undefined", }, //flat
- {"0 dB", "2 dB", "4 dB", "6 dB", "8 dB", "10 dB", "12 dB", "14 dB", "16 dB", "18 dB", "18 dB",
- "18 dB", "18 dB", "18 dB", "18 dB", "undefined",}, // min
- {"0 dB", "2 dB", "4 dB", "6 dB", "8 dB", "10 dB", "12 dB", "14 dB", "16 dB", "18 dB", "18 dB",
- "18 dB", "18 dB", "18 dB", "18 dB", "undefined",}, // min
- {"0 dB", "2 dB", "4 dB", "6 dB", "8 dB", "10 dB", "12 dB", "14 dB", "16 dB", "18 dB", "20 dB",
- "22 dB", "24 dB", "24 dB", "24 dB", "undefined",}, // max
-};
-
-static const char *mic_sens_value[] = {
- "-3 dB", "0 dB", "3 dB", "9 dB", "15 dB", "21 dB", "27 dB", "not used",
-};
-
-static const unsigned short AGC_atime[] = {
- 11, 16, 11, 16, 21, 11, 16, 21,
-};
-
-static const unsigned short AGC_dtime[] = {
- 100, 100, 200, 200, 200, 400, 400, 400,
-};
-
-static const char *AGC_level[] = {
- "-9.0", "-11.5", "-15.0", "-17.5",
-};
-
-static const char *ig_small_value[] = {
- "-3.0", "-2.5", "-2.0", "-1.5", "-1.0", "-0.5",
-};
-
-/*
- * this was computed as peak_value[i] = pow((63-i)*1.42,1.013)
- *
- * UDA1341 datasheet on page 21: Peak value (dB) = (Peak level - 63.5)*5*log2
- * There is an table with these values [level]=value: [3]=-90.31, [7]=-84.29
- * [61]=-2.78, [62] = -1.48, [63] = 0.0
- * I tried to compute it, but using but even using logarithm with base either 10 or 2
- * i was'n able to get values in the table from the formula. So I constructed another
- * formula (see above) to interpolate the values as good as possible. If there is some
- * mistake, please contact me on tomas.kasparek@seznam.cz. Thanks.
- * UDA1341TS datasheet is available at:
- * http://www-us9.semiconductors.com/acrobat/datasheets/UDA1341TS_3.pdf
- */
-static const char *peak_value[] = {
- "-INF dB", "N.A.", "N.A", "90.31 dB", "N.A.", "N.A.", "N.A.", "-84.29 dB",
- "-82.65 dB", "-81.13 dB", "-79.61 dB", "-78.09 dB", "-76.57 dB", "-75.05 dB", "-73.53 dB",
- "-72.01 dB", "-70.49 dB", "-68.97 dB", "-67.45 dB", "-65.93 dB", "-64.41 dB", "-62.90 dB",
- "-61.38 dB", "-59.86 dB", "-58.35 dB", "-56.83 dB", "-55.32 dB", "-53.80 dB", "-52.29 dB",
- "-50.78 dB", "-49.26 dB", "-47.75 dB", "-46.24 dB", "-44.73 dB", "-43.22 dB", "-41.71 dB",
- "-40.20 dB", "-38.69 dB", "-37.19 dB", "-35.68 dB", "-34.17 dB", "-32.67 dB", "-31.17 dB",
- "-29.66 dB", "-28.16 dB", "-26.66 dB", "-25.16 dB", "-23.66 dB", "-22.16 dB", "-20.67 dB",
- "-19.17 dB", "-17.68 dB", "-16.19 dB", "-14.70 dB", "-13.21 dB", "-11.72 dB", "-10.24 dB",
- "-8.76 dB", "-7.28 dB", "-5.81 dB", "-4.34 dB", "-2.88 dB", "-1.43 dB", "0.00 dB",
-};
-
-static void snd_uda1341_proc_read(struct snd_info_entry *entry,
- struct snd_info_buffer *buffer)
-{
- struct l3_client *clnt = entry->private_data;
- struct uda1341 *uda = clnt->driver_data;
- int peak;
-
- peak = snd_uda1341_codec_read(clnt, UDA1341_DATA1);
- if (peak < 0)
- peak = 0;
-
- snd_iprintf(buffer, "%s\n\n", uda->card->longname);
-
- // for information about computed values see UDA1341TS datasheet pages 15 - 21
- snd_iprintf(buffer, "DAC power : %s\n", uda->cfg[CMD_DAC] ? "on" : "off");
- snd_iprintf(buffer, "ADC power : %s\n", uda->cfg[CMD_ADC] ? "on" : "off");
- snd_iprintf(buffer, "Clock frequency : %s\n", fs_names[uda->cfg[CMD_FS]]);
- snd_iprintf(buffer, "Data format : %s\n\n", format_names[uda->cfg[CMD_FORMAT]]);
-
- snd_iprintf(buffer, "Filter mode : %s\n", filter_names[uda->cfg[CMD_FILTER]]);
- snd_iprintf(buffer, "Mixer mode : %s\n", mixer_names[uda->cfg[CMD_MIXER]]);
- snd_iprintf(buffer, "De-emphasis : %s\n", deemp_names[uda->cfg[CMD_DEEMP]]);
- snd_iprintf(buffer, "Peak detection pos. : %s\n", uda->cfg[CMD_PEAK] ? "after" : "before");
- snd_iprintf(buffer, "Peak value : %s\n\n", peak_value[peak]);
-
- snd_iprintf(buffer, "Automatic Gain Ctrl : %s\n", uda->cfg[CMD_AGC] ? "on" : "off");
- snd_iprintf(buffer, "AGC attack time : %d ms\n", AGC_atime[uda->cfg[CMD_AGC_TIME]]);
- snd_iprintf(buffer, "AGC decay time : %d ms\n", AGC_dtime[uda->cfg[CMD_AGC_TIME]]);
- snd_iprintf(buffer, "AGC output level : %s dB\n\n", AGC_level[uda->cfg[CMD_AGC_LEVEL]]);
-
- snd_iprintf(buffer, "Mute : %s\n", uda->cfg[CMD_MUTE] ? "on" : "off");
-
- if (uda->cfg[CMD_VOLUME] == 0)
- snd_iprintf(buffer, "Volume : 0 dB\n");
- else if (uda->cfg[CMD_VOLUME] < 62)
- snd_iprintf(buffer, "Volume : %d dB\n", -1*uda->cfg[CMD_VOLUME] +1);
- else
- snd_iprintf(buffer, "Volume : -INF dB\n");
- snd_iprintf(buffer, "Bass : %s\n", bass_values[uda->cfg[CMD_FILTER]][uda->cfg[CMD_BASS]]);
- snd_iprintf(buffer, "Trebble : %d dB\n", uda->cfg[CMD_FILTER] ? 2*uda->cfg[CMD_TREBBLE] : 0);
- snd_iprintf(buffer, "Input Gain (6dB) : %s\n", uda->cfg[CMD_IGAIN] ? "on" : "off");
- snd_iprintf(buffer, "Output Gain (6dB) : %s\n", uda->cfg[CMD_OGAIN] ? "on" : "off");
- snd_iprintf(buffer, "Mic sensitivity : %s\n", mic_sens_value[uda->cfg[CMD_MIC]]);
-
-
- if(uda->cfg[CMD_CH1] < 31)
- snd_iprintf(buffer, "Mixer gain channel 1: -%d.%c dB\n",
- ((uda->cfg[CMD_CH1] >> 1) * 3) + (uda->cfg[CMD_CH1] & 1),
- uda->cfg[CMD_CH1] & 1 ? '5' : '0');
- else
- snd_iprintf(buffer, "Mixer gain channel 1: -INF dB\n");
- if(uda->cfg[CMD_CH2] < 31)
- snd_iprintf(buffer, "Mixer gain channel 2: -%d.%c dB\n",
- ((uda->cfg[CMD_CH2] >> 1) * 3) + (uda->cfg[CMD_CH2] & 1),
- uda->cfg[CMD_CH2] & 1 ? '5' : '0');
- else
- snd_iprintf(buffer, "Mixer gain channel 2: -INF dB\n");
-
- if(uda->cfg[CMD_IG] > 5)
- snd_iprintf(buffer, "Input Amp. Gain ch 2: %d.%c dB\n",
- (uda->cfg[CMD_IG] >> 1) -3, uda->cfg[CMD_IG] & 1 ? '5' : '0');
- else
- snd_iprintf(buffer, "Input Amp. Gain ch 2: %s dB\n", ig_small_value[uda->cfg[CMD_IG]]);
-}
-
-static void snd_uda1341_proc_regs_read(struct snd_info_entry *entry,
- struct snd_info_buffer *buffer)
-{
- struct l3_client *clnt = entry->private_data;
- struct uda1341 *uda = clnt->driver_data;
- int reg;
- char buf[12];
-
- for (reg = 0; reg < uda1341_reg_last; reg ++) {
- if (reg == empty)
- continue;
- int2str_bin8(uda->regs[reg], buf);
- snd_iprintf(buffer, "%s = %s\n", uda1341_reg_names[reg], buf);
- }
-
- int2str_bin8(snd_uda1341_codec_read(clnt, UDA1341_DATA1), buf);
- snd_iprintf(buffer, "DATA1 = %s\n", buf);
-}
-#endif /* CONFIG_PROC_FS */
-
-static void __devinit snd_uda1341_proc_init(struct snd_card *card, struct l3_client *clnt)
-{
- struct snd_info_entry *entry;
-
- if (! snd_card_proc_new(card, "uda1341", &entry))
- snd_info_set_text_ops(entry, clnt, snd_uda1341_proc_read);
- if (! snd_card_proc_new(card, "uda1341-regs", &entry))
- snd_info_set_text_ops(entry, clnt, snd_uda1341_proc_regs_read);
-}
-
-/* }}} */
-
-/* {{{ Mixer controls setting */
-
-/* {{{ UDA1341 single functions */
-
-#define UDA1341_SINGLE(xname, where, reg, shift, mask, invert) \
-{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = xname, .info = snd_uda1341_info_single, \
- .get = snd_uda1341_get_single, .put = snd_uda1341_put_single, \
- .private_value = where | (reg << 5) | (shift << 9) | (mask << 12) | (invert << 18) \
-}
-
-static int snd_uda1341_info_single(struct snd_kcontrol *kcontrol,
- struct snd_ctl_elem_info *uinfo)
-{
- int mask = (kcontrol->private_value >> 12) & 63;
-
- uinfo->type = mask == 1 ? SNDRV_CTL_ELEM_TYPE_BOOLEAN : SNDRV_CTL_ELEM_TYPE_INTEGER;
- uinfo->count = 1;
- uinfo->value.integer.min = 0;
- uinfo->value.integer.max = mask;
- return 0;
-}
-
-static int snd_uda1341_get_single(struct snd_kcontrol *kcontrol,
- struct snd_ctl_elem_value *ucontrol)
-{
- struct l3_client *clnt = snd_kcontrol_chip(kcontrol);
- struct uda1341 *uda = clnt->driver_data;
- int where = kcontrol->private_value & 31;
- int mask = (kcontrol->private_value >> 12) & 63;
- int invert = (kcontrol->private_value >> 18) & 1;
-
- ucontrol->value.integer.value[0] = uda->cfg[where];
- if (invert)
- ucontrol->value.integer.value[0] = mask - ucontrol->value.integer.value[0];
-
- return 0;
-}
-
-static int snd_uda1341_put_single(struct snd_kcontrol *kcontrol,
- struct snd_ctl_elem_value *ucontrol)
-{
- struct l3_client *clnt = snd_kcontrol_chip(kcontrol);
- struct uda1341 *uda = clnt->driver_data;
- int where = kcontrol->private_value & 31;
- int reg = (kcontrol->private_value >> 5) & 15;
- int shift = (kcontrol->private_value >> 9) & 7;
- int mask = (kcontrol->private_value >> 12) & 63;
- int invert = (kcontrol->private_value >> 18) & 1;
- unsigned short val;
-
- val = (ucontrol->value.integer.value[0] & mask);
- if (invert)
- val = mask - val;
-
- uda->cfg[where] = val;
- return snd_uda1341_update_bits(clnt, reg, mask, shift, val, FLUSH);
-}
-
-/* }}} */
-
-/* {{{ UDA1341 enum functions */
-
-#define UDA1341_ENUM(xname, where, reg, shift, mask, invert) \
-{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = xname, .info = snd_uda1341_info_enum, \
- .get = snd_uda1341_get_enum, .put = snd_uda1341_put_enum, \
- .private_value = where | (reg << 5) | (shift << 9) | (mask << 12) | (invert << 18) \
-}
-
-static int snd_uda1341_info_enum(struct snd_kcontrol *kcontrol,
- struct snd_ctl_elem_info *uinfo)
-{
- int where = kcontrol->private_value & 31;
- const char **texts;
-
- // this register we don't handle this way
- if (!uda1341_enum_items[where])
- return -EINVAL;
-
- uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED;
- uinfo->count = 1;
- uinfo->value.enumerated.items = uda1341_enum_items[where];
-
- if (uinfo->value.enumerated.item >= uda1341_enum_items[where])
- uinfo->value.enumerated.item = uda1341_enum_items[where] - 1;
-
- texts = uda1341_enum_names[where];
- strcpy(uinfo->value.enumerated.name, texts[uinfo->value.enumerated.item]);
- return 0;
-}
-
-static int snd_uda1341_get_enum(struct snd_kcontrol *kcontrol,
- struct snd_ctl_elem_value *ucontrol)
-{
- struct l3_client *clnt = snd_kcontrol_chip(kcontrol);
- struct uda1341 *uda = clnt->driver_data;
- int where = kcontrol->private_value & 31;
-
- ucontrol->value.enumerated.item[0] = uda->cfg[where];
- return 0;
-}
-
-static int snd_uda1341_put_enum(struct snd_kcontrol *kcontrol,
- struct snd_ctl_elem_value *ucontrol)
-{
- struct l3_client *clnt = snd_kcontrol_chip(kcontrol);
- struct uda1341 *uda = clnt->driver_data;
- int where = kcontrol->private_value & 31;
- int reg = (kcontrol->private_value >> 5) & 15;
- int shift = (kcontrol->private_value >> 9) & 7;
- int mask = (kcontrol->private_value >> 12) & 63;
-
- uda->cfg[where] = (ucontrol->value.enumerated.item[0] & mask);
-
- return snd_uda1341_update_bits(clnt, reg, mask, shift, uda->cfg[where], FLUSH);
-}
-
-/* }}} */
-
-/* {{{ UDA1341 2regs functions */
-
-#define UDA1341_2REGS(xname, where, reg_1, reg_2, shift_1, shift_2, mask_1, mask_2, invert) \
-{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = (xname), .info = snd_uda1341_info_2regs, \
- .get = snd_uda1341_get_2regs, .put = snd_uda1341_put_2regs, \
- .private_value = where | (reg_1 << 5) | (reg_2 << 9) | (shift_1 << 13) | (shift_2 << 16) | \
- (mask_1 << 19) | (mask_2 << 25) | (invert << 31) \
-}
-
-
-static int snd_uda1341_info_2regs(struct snd_kcontrol *kcontrol,
- struct snd_ctl_elem_info *uinfo)
-{
- int mask_1 = (kcontrol->private_value >> 19) & 63;
- int mask_2 = (kcontrol->private_value >> 25) & 63;
- int mask;
-
- mask = (mask_2 + 1) * (mask_1 + 1) - 1;
- uinfo->type = mask == 1 ? SNDRV_CTL_ELEM_TYPE_BOOLEAN : SNDRV_CTL_ELEM_TYPE_INTEGER;
- uinfo->count = 1;
- uinfo->value.integer.min = 0;
- uinfo->value.integer.max = mask;
- return 0;
-}
-
-static int snd_uda1341_get_2regs(struct snd_kcontrol *kcontrol,
- struct snd_ctl_elem_value *ucontrol)
-{
- struct l3_client *clnt = snd_kcontrol_chip(kcontrol);
- struct uda1341 *uda = clnt->driver_data;
- int where = kcontrol->private_value & 31;
- int mask_1 = (kcontrol->private_value >> 19) & 63;
- int mask_2 = (kcontrol->private_value >> 25) & 63;
- int invert = (kcontrol->private_value >> 31) & 1;
- int mask;
-
- mask = (mask_2 + 1) * (mask_1 + 1) - 1;
-
- ucontrol->value.integer.value[0] = uda->cfg[where];
- if (invert)
- ucontrol->value.integer.value[0] = mask - ucontrol->value.integer.value[0];
- return 0;
-}
-
-static int snd_uda1341_put_2regs(struct snd_kcontrol *kcontrol,
- struct snd_ctl_elem_value *ucontrol)
-{
- struct l3_client *clnt = snd_kcontrol_chip(kcontrol);
- struct uda1341 *uda = clnt->driver_data;
- int where = kcontrol->private_value & 31;
- int reg_1 = (kcontrol->private_value >> 5) & 15;
- int reg_2 = (kcontrol->private_value >> 9) & 15;
- int shift_1 = (kcontrol->private_value >> 13) & 7;
- int shift_2 = (kcontrol->private_value >> 16) & 7;
- int mask_1 = (kcontrol->private_value >> 19) & 63;
- int mask_2 = (kcontrol->private_value >> 25) & 63;
- int invert = (kcontrol->private_value >> 31) & 1;
- int mask;
- unsigned short val1, val2, val;
-
- val = ucontrol->value.integer.value[0];
-
- mask = (mask_2 + 1) * (mask_1 + 1) - 1;
-
- val1 = val & mask_1;
- val2 = (val / (mask_1 + 1)) & mask_2;
-
- if (invert) {
- val1 = mask_1 - val1;
- val2 = mask_2 - val2;
- }
-
- uda->cfg[where] = invert ? mask - val : val;
-
- //FIXME - return value
- snd_uda1341_update_bits(clnt, reg_1, mask_1, shift_1, val1, FLUSH);
- return snd_uda1341_update_bits(clnt, reg_2, mask_2, shift_2, val2, FLUSH);
-}
-
-/* }}} */
-
-static struct snd_kcontrol_new snd_uda1341_controls[] = {
- UDA1341_SINGLE("Master Playback Switch", CMD_MUTE, data0_2, 2, 1, 1),
- UDA1341_SINGLE("Master Playback Volume", CMD_VOLUME, data0_0, 0, 63, 1),
-
- UDA1341_SINGLE("Bass Playback Volume", CMD_BASS, data0_1, 2, 15, 0),
- UDA1341_SINGLE("Treble Playback Volume", CMD_TREBBLE, data0_1, 0, 3, 0),
-
- UDA1341_SINGLE("Input Gain Switch", CMD_IGAIN, stat1, 5, 1, 0),
- UDA1341_SINGLE("Output Gain Switch", CMD_OGAIN, stat1, 6, 1, 0),
-
- UDA1341_SINGLE("Mixer Gain Channel 1 Volume", CMD_CH1, ext0, 0, 31, 1),
- UDA1341_SINGLE("Mixer Gain Channel 2 Volume", CMD_CH2, ext1, 0, 31, 1),
-
- UDA1341_SINGLE("Mic Sensitivity Volume", CMD_MIC, ext2, 2, 7, 0),
-
- UDA1341_SINGLE("AGC Output Level", CMD_AGC_LEVEL, ext6, 0, 3, 0),
- UDA1341_SINGLE("AGC Time Constant", CMD_AGC_TIME, ext6, 2, 7, 0),
- UDA1341_SINGLE("AGC Time Constant Switch", CMD_AGC, ext4, 4, 1, 0),
-
- UDA1341_SINGLE("DAC Power", CMD_DAC, stat1, 0, 1, 0),
- UDA1341_SINGLE("ADC Power", CMD_ADC, stat1, 1, 1, 0),
-
- UDA1341_ENUM("Peak detection", CMD_PEAK, data0_2, 5, 1, 0),
- UDA1341_ENUM("De-emphasis", CMD_DEEMP, data0_2, 3, 3, 0),
- UDA1341_ENUM("Mixer mode", CMD_MIXER, ext2, 0, 3, 0),
- UDA1341_ENUM("Filter mode", CMD_FILTER, data0_2, 0, 3, 0),
-
- UDA1341_2REGS("Gain Input Amplifier Gain (channel 2)", CMD_IG, ext4, ext5, 0, 0, 3, 31, 0),
-};
-
-static void uda1341_free(struct l3_client *clnt)
-{
- l3_detach_client(clnt); // calls kfree for driver_data (struct uda1341)
- kfree(clnt);
-}
-
-static int uda1341_dev_free(struct snd_device *device)
-{
- struct l3_client *clnt = device->device_data;
- uda1341_free(clnt);
- return 0;
-}
-
-int __init snd_chip_uda1341_mixer_new(struct snd_card *card, struct l3_client **clntp)
-{
- static struct snd_device_ops ops = {
- .dev_free = uda1341_dev_free,
- };
- struct l3_client *clnt;
- int idx, err;
-
- snd_assert(card != NULL, return -EINVAL);
-
- clnt = kzalloc(sizeof(*clnt), GFP_KERNEL);
- if (clnt == NULL)
- return -ENOMEM;
-
- if ((err = l3_attach_client(clnt, "l3-bit-sa1100-gpio", UDA1341_ALSA_NAME))) {
- kfree(clnt);
- return err;
- }
-
- for (idx = 0; idx < ARRAY_SIZE(snd_uda1341_controls); idx++) {
- if ((err = snd_ctl_add(card, snd_ctl_new1(&snd_uda1341_controls[idx], clnt))) < 0) {
- uda1341_free(clnt);
- return err;
- }
- }
-
- if ((err = snd_device_new(card, SNDRV_DEV_CODEC, clnt, &ops)) < 0) {
- uda1341_free(clnt);
- return err;
- }
-
- *clntp = clnt;
- strcpy(card->mixername, "UDA1341TS Mixer");
- ((struct uda1341 *)clnt->driver_data)->card = card;
-
- snd_uda1341_proc_init(card, clnt);
-
- return 0;
-}
-
-/* }}} */
-
-/* {{{ L3 operations */
-
-static int uda1341_attach(struct l3_client *clnt)
-{
- struct uda1341 *uda;
-
- uda = kzalloc(sizeof(*uda), 0, GFP_KERNEL);
- if (!uda)
- return -ENOMEM;
-
- /* init fixed parts of my copy of registers */
- uda->regs[stat0] = STAT0;
- uda->regs[stat1] = STAT1;
-
- uda->regs[data0_0] = DATA0_0;
- uda->regs[data0_1] = DATA0_1;
- uda->regs[data0_2] = DATA0_2;
-
- uda->write = snd_uda1341_codec_write;
- uda->read = snd_uda1341_codec_read;
-
- spin_lock_init(&uda->reg_lock);
-
- clnt->driver_data = uda;
- return 0;
-}
-
-static void uda1341_detach(struct l3_client *clnt)
-{
- kfree(clnt->driver_data);
-}
-
-static int
-uda1341_command(struct l3_client *clnt, int cmd, void *arg)
-{
- if (cmd != CMD_READ_REG)
- return snd_uda1341_cfg_write(clnt, cmd, (int) arg, FLUSH);
-
- return snd_uda1341_codec_read(clnt, (int) arg);
-}
-
-static int uda1341_open(struct l3_client *clnt)
-{
- struct uda1341 *uda = clnt->driver_data;
-
- uda->active = 1;
-
- /* init default configuration */
- snd_uda1341_cfg_write(clnt, CMD_RESET, 0, REGS_ONLY);
- snd_uda1341_cfg_write(clnt, CMD_FS, F256, FLUSH); // unknown state after reset
- snd_uda1341_cfg_write(clnt, CMD_FORMAT, LSB16, FLUSH); // unknown state after reset
- snd_uda1341_cfg_write(clnt, CMD_OGAIN, ON, FLUSH); // default off after reset
- snd_uda1341_cfg_write(clnt, CMD_IGAIN, ON, FLUSH); // default off after reset
- snd_uda1341_cfg_write(clnt, CMD_DAC, ON, FLUSH); // ??? default value after reset
- snd_uda1341_cfg_write(clnt, CMD_ADC, ON, FLUSH); // ??? default value after reset
- snd_uda1341_cfg_write(clnt, CMD_VOLUME, 20, FLUSH); // default 0dB after reset
- snd_uda1341_cfg_write(clnt, CMD_BASS, 0, REGS_ONLY); // default value after reset
- snd_uda1341_cfg_write(clnt, CMD_TREBBLE, 0, REGS_ONLY); // default value after reset
- snd_uda1341_cfg_write(clnt, CMD_PEAK, AFTER, REGS_ONLY);// default value after reset
- snd_uda1341_cfg_write(clnt, CMD_DEEMP, NONE, REGS_ONLY);// default value after reset
- //at this moment should be QMUTED by h3600_audio_init
- snd_uda1341_cfg_write(clnt, CMD_MUTE, OFF, REGS_ONLY); // default value after reset
- snd_uda1341_cfg_write(clnt, CMD_FILTER, MAX, FLUSH); // defaul flat after reset
- snd_uda1341_cfg_write(clnt, CMD_CH1, 31, FLUSH); // default value after reset
- snd_uda1341_cfg_write(clnt, CMD_CH2, 4, FLUSH); // default value after reset
- snd_uda1341_cfg_write(clnt, CMD_MIC, 4, FLUSH); // default 0dB after reset
- snd_uda1341_cfg_write(clnt, CMD_MIXER, MIXER, FLUSH); // default doub.dif.mode
- snd_uda1341_cfg_write(clnt, CMD_AGC, OFF, FLUSH); // default value after reset
- snd_uda1341_cfg_write(clnt, CMD_IG, 0, FLUSH); // unknown state after reset
- snd_uda1341_cfg_write(clnt, CMD_AGC_TIME, 0, FLUSH); // default value after reset
- snd_uda1341_cfg_write(clnt, CMD_AGC_LEVEL, 0, FLUSH); // default value after reset
-
- return 0;
-}
-
-static void uda1341_close(struct l3_client *clnt)
-{
- struct uda1341 *uda = clnt->driver_data;
-
- uda->active = 0;
-}
-
-/* }}} */
-
-/* {{{ Module and L3 initialization */
-
-static struct l3_ops uda1341_ops = {
- .open = uda1341_open,
- .command = uda1341_command,
- .close = uda1341_close,
-};
-
-static struct l3_driver uda1341_driver = {
- .name = UDA1341_ALSA_NAME,
- .attach_client = uda1341_attach,
- .detach_client = uda1341_detach,
- .ops = &uda1341_ops,
- .owner = THIS_MODULE,
-};
-
-static int __init uda1341_init(void)
-{
- return l3_add_driver(&uda1341_driver);
-}
-
-static void __exit uda1341_exit(void)
-{
- l3_del_driver(&uda1341_driver);
-}
-
-module_init(uda1341_init);
-module_exit(uda1341_exit);
-
-MODULE_AUTHOR("Tomas Kasparek <tomas.kasparek@seznam.cz>");
-MODULE_LICENSE("GPL");
-MODULE_DESCRIPTION("Philips UDA1341 CODEC driver for ALSA");
-MODULE_SUPPORTED_DEVICE("{{UDA1341,UDA1341TS}}");
-
-EXPORT_SYMBOL(snd_chip_uda1341_mixer_new);
-
-/* }}} */
-
-/*
- * Local variables:
- * indent-tabs-mode: t
- * End:
- */
diff --git a/sound/i2c/other/Makefile b/sound/i2c/other/Makefile
index 703d954238f..5526b03b95a 100644
--- a/sound/i2c/other/Makefile
+++ b/sound/i2c/other/Makefile
@@ -5,12 +5,11 @@
snd-ak4114-objs := ak4114.o
snd-ak4117-objs := ak4117.o
+snd-ak4113-objs := ak4113.o
snd-ak4xxx-adda-objs := ak4xxx-adda.o
snd-pt2258-objs := pt2258.o
-snd-tea575x-tuner-objs := tea575x-tuner.o
# Module Dependency
obj-$(CONFIG_SND_PDAUDIOCF) += snd-ak4117.o
obj-$(CONFIG_SND_ICE1712) += snd-ak4xxx-adda.o
-obj-$(CONFIG_SND_ICE1724) += snd-ak4114.o snd-ak4xxx-adda.o snd-pt2258.o
-obj-$(CONFIG_SND_FM801_TEA575X) += snd-tea575x-tuner.o
+obj-$(CONFIG_SND_ICE1724) += snd-ak4114.o snd-ak4113.o snd-ak4xxx-adda.o snd-pt2258.o
diff --git a/sound/i2c/other/ak4113.c b/sound/i2c/other/ak4113.c
new file mode 100644
index 00000000000..1a3a6fa2715
--- /dev/null
+++ b/sound/i2c/other/ak4113.c
@@ -0,0 +1,639 @@
+/*
+ * Routines for control of the AK4113 via I2C/4-wire serial interface
+ * IEC958 (S/PDIF) receiver by Asahi Kasei
+ * Copyright (c) by Jaroslav Kysela <perex@perex.cz>
+ * Copyright (c) by Pavel Hofman <pavel.hofman@ivitera.com>
+ *
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ *
+ */
+
+#include <linux/slab.h>
+#include <linux/delay.h>
+#include <linux/module.h>
+#include <sound/core.h>
+#include <sound/control.h>
+#include <sound/pcm.h>
+#include <sound/ak4113.h>
+#include <sound/asoundef.h>
+#include <sound/info.h>
+
+MODULE_AUTHOR("Pavel Hofman <pavel.hofman@ivitera.com>");
+MODULE_DESCRIPTION("AK4113 IEC958 (S/PDIF) receiver by Asahi Kasei");
+MODULE_LICENSE("GPL");
+
+#define AK4113_ADDR 0x00 /* fixed address */
+
+static void ak4113_stats(struct work_struct *work);
+static void ak4113_init_regs(struct ak4113 *chip);
+
+
+static void reg_write(struct ak4113 *ak4113, unsigned char reg,
+ unsigned char val)
+{
+ ak4113->write(ak4113->private_data, reg, val);
+ if (reg < sizeof(ak4113->regmap))
+ ak4113->regmap[reg] = val;
+}
+
+static inline unsigned char reg_read(struct ak4113 *ak4113, unsigned char reg)
+{
+ return ak4113->read(ak4113->private_data, reg);
+}
+
+static void snd_ak4113_free(struct ak4113 *chip)
+{
+ chip->init = 1; /* don't schedule new work */
+ mb();
+ cancel_delayed_work_sync(&chip->work);
+ kfree(chip);
+}
+
+static int snd_ak4113_dev_free(struct snd_device *device)
+{
+ struct ak4113 *chip = device->device_data;
+ snd_ak4113_free(chip);
+ return 0;
+}
+
+int snd_ak4113_create(struct snd_card *card, ak4113_read_t *read,
+ ak4113_write_t *write, const unsigned char *pgm,
+ void *private_data, struct ak4113 **r_ak4113)
+{
+ struct ak4113 *chip;
+ int err = 0;
+ unsigned char reg;
+ static struct snd_device_ops ops = {
+ .dev_free = snd_ak4113_dev_free,
+ };
+
+ chip = kzalloc(sizeof(*chip), GFP_KERNEL);
+ if (chip == NULL)
+ return -ENOMEM;
+ spin_lock_init(&chip->lock);
+ chip->card = card;
+ chip->read = read;
+ chip->write = write;
+ chip->private_data = private_data;
+ INIT_DELAYED_WORK(&chip->work, ak4113_stats);
+
+ for (reg = 0; reg < AK4113_WRITABLE_REGS ; reg++)
+ chip->regmap[reg] = pgm[reg];
+ ak4113_init_regs(chip);
+
+ chip->rcs0 = reg_read(chip, AK4113_REG_RCS0) & ~(AK4113_QINT |
+ AK4113_CINT | AK4113_STC);
+ chip->rcs1 = reg_read(chip, AK4113_REG_RCS1);
+ chip->rcs2 = reg_read(chip, AK4113_REG_RCS2);
+ err = snd_device_new(card, SNDRV_DEV_CODEC, chip, &ops);
+ if (err < 0)
+ goto __fail;
+
+ if (r_ak4113)
+ *r_ak4113 = chip;
+ return 0;
+
+__fail:
+ snd_ak4113_free(chip);
+ return err < 0 ? err : -EIO;
+}
+EXPORT_SYMBOL_GPL(snd_ak4113_create);
+
+void snd_ak4113_reg_write(struct ak4113 *chip, unsigned char reg,
+ unsigned char mask, unsigned char val)
+{
+ if (reg >= AK4113_WRITABLE_REGS)
+ return;
+ reg_write(chip, reg, (chip->regmap[reg] & ~mask) | val);
+}
+EXPORT_SYMBOL_GPL(snd_ak4113_reg_write);
+
+static void ak4113_init_regs(struct ak4113 *chip)
+{
+ unsigned char old = chip->regmap[AK4113_REG_PWRDN], reg;
+
+ /* bring the chip to reset state and powerdown state */
+ reg_write(chip, AK4113_REG_PWRDN, old & ~(AK4113_RST|AK4113_PWN));
+ udelay(200);
+ /* release reset, but leave powerdown */
+ reg_write(chip, AK4113_REG_PWRDN, (old | AK4113_RST) & ~AK4113_PWN);
+ udelay(200);
+ for (reg = 1; reg < AK4113_WRITABLE_REGS; reg++)
+ reg_write(chip, reg, chip->regmap[reg]);
+ /* release powerdown, everything is initialized now */
+ reg_write(chip, AK4113_REG_PWRDN, old | AK4113_RST | AK4113_PWN);
+}
+
+void snd_ak4113_reinit(struct ak4113 *chip)
+{
+ chip->init = 1;
+ mb();
+ flush_delayed_work(&chip->work);
+ ak4113_init_regs(chip);
+ /* bring up statistics / event queing */
+ chip->init = 0;
+ if (chip->kctls[0])
+ schedule_delayed_work(&chip->work, HZ / 10);
+}
+EXPORT_SYMBOL_GPL(snd_ak4113_reinit);
+
+static unsigned int external_rate(unsigned char rcs1)
+{
+ switch (rcs1 & (AK4113_FS0|AK4113_FS1|AK4113_FS2|AK4113_FS3)) {
+ case AK4113_FS_8000HZ:
+ return 8000;
+ case AK4113_FS_11025HZ:
+ return 11025;
+ case AK4113_FS_16000HZ:
+ return 16000;
+ case AK4113_FS_22050HZ:
+ return 22050;
+ case AK4113_FS_24000HZ:
+ return 24000;
+ case AK4113_FS_32000HZ:
+ return 32000;
+ case AK4113_FS_44100HZ:
+ return 44100;
+ case AK4113_FS_48000HZ:
+ return 48000;
+ case AK4113_FS_64000HZ:
+ return 64000;
+ case AK4113_FS_88200HZ:
+ return 88200;
+ case AK4113_FS_96000HZ:
+ return 96000;
+ case AK4113_FS_176400HZ:
+ return 176400;
+ case AK4113_FS_192000HZ:
+ return 192000;
+ default:
+ return 0;
+ }
+}
+
+static int snd_ak4113_in_error_info(struct snd_kcontrol *kcontrol,
+ struct snd_ctl_elem_info *uinfo)
+{
+ uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER;
+ uinfo->count = 1;
+ uinfo->value.integer.min = 0;
+ uinfo->value.integer.max = LONG_MAX;
+ return 0;
+}
+
+static int snd_ak4113_in_error_get(struct snd_kcontrol *kcontrol,
+ struct snd_ctl_elem_value *ucontrol)
+{
+ struct ak4113 *chip = snd_kcontrol_chip(kcontrol);
+ long *ptr;
+
+ spin_lock_irq(&chip->lock);
+ ptr = (long *)(((char *)chip) + kcontrol->private_value);
+ ucontrol->value.integer.value[0] = *ptr;
+ *ptr = 0;
+ spin_unlock_irq(&chip->lock);
+ return 0;
+}
+
+#define snd_ak4113_in_bit_info snd_ctl_boolean_mono_info
+
+static int snd_ak4113_in_bit_get(struct snd_kcontrol *kcontrol,
+ struct snd_ctl_elem_value *ucontrol)
+{
+ struct ak4113 *chip = snd_kcontrol_chip(kcontrol);
+ unsigned char reg = kcontrol->private_value & 0xff;
+ unsigned char bit = (kcontrol->private_value >> 8) & 0xff;
+ unsigned char inv = (kcontrol->private_value >> 31) & 1;
+
+ ucontrol->value.integer.value[0] =
+ ((reg_read(chip, reg) & (1 << bit)) ? 1 : 0) ^ inv;
+ return 0;
+}
+
+static int snd_ak4113_rx_info(struct snd_kcontrol *kcontrol,
+ struct snd_ctl_elem_info *uinfo)
+{
+ uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER;
+ uinfo->count = 1;
+ uinfo->value.integer.min = 0;
+ uinfo->value.integer.max = 5;
+ return 0;
+}
+
+static int snd_ak4113_rx_get(struct snd_kcontrol *kcontrol,
+ struct snd_ctl_elem_value *ucontrol)
+{
+ struct ak4113 *chip = snd_kcontrol_chip(kcontrol);
+
+ ucontrol->value.integer.value[0] =
+ (AK4113_IPS(chip->regmap[AK4113_REG_IO1]));
+ return 0;
+}
+
+static int snd_ak4113_rx_put(struct snd_kcontrol *kcontrol,
+ struct snd_ctl_elem_value *ucontrol)
+{
+ struct ak4113 *chip = snd_kcontrol_chip(kcontrol);
+ int change;
+ u8 old_val;
+
+ spin_lock_irq(&chip->lock);
+ old_val = chip->regmap[AK4113_REG_IO1];
+ change = ucontrol->value.integer.value[0] != AK4113_IPS(old_val);
+ if (change)
+ reg_write(chip, AK4113_REG_IO1,
+ (old_val & (~AK4113_IPS(0xff))) |
+ (AK4113_IPS(ucontrol->value.integer.value[0])));
+ spin_unlock_irq(&chip->lock);
+ return change;
+}
+
+static int snd_ak4113_rate_info(struct snd_kcontrol *kcontrol,
+ struct snd_ctl_elem_info *uinfo)
+{
+ uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER;
+ uinfo->count = 1;
+ uinfo->value.integer.min = 0;
+ uinfo->value.integer.max = 192000;
+ return 0;
+}
+
+static int snd_ak4113_rate_get(struct snd_kcontrol *kcontrol,
+ struct snd_ctl_elem_value *ucontrol)
+{
+ struct ak4113 *chip = snd_kcontrol_chip(kcontrol);
+
+ ucontrol->value.integer.value[0] = external_rate(reg_read(chip,
+ AK4113_REG_RCS1));
+ return 0;
+}
+
+static int snd_ak4113_spdif_info(struct snd_kcontrol *kcontrol,
+ struct snd_ctl_elem_info *uinfo)
+{
+ uinfo->type = SNDRV_CTL_ELEM_TYPE_IEC958;
+ uinfo->count = 1;
+ return 0;
+}
+
+static int snd_ak4113_spdif_get(struct snd_kcontrol *kcontrol,
+ struct snd_ctl_elem_value *ucontrol)
+{
+ struct ak4113 *chip = snd_kcontrol_chip(kcontrol);
+ unsigned i;
+
+ for (i = 0; i < AK4113_REG_RXCSB_SIZE; i++)
+ ucontrol->value.iec958.status[i] = reg_read(chip,
+ AK4113_REG_RXCSB0 + i);
+ return 0;
+}
+
+static int snd_ak4113_spdif_mask_info(struct snd_kcontrol *kcontrol,
+ struct snd_ctl_elem_info *uinfo)
+{
+ uinfo->type = SNDRV_CTL_ELEM_TYPE_IEC958;
+ uinfo->count = 1;
+ return 0;
+}
+
+static int snd_ak4113_spdif_mask_get(struct snd_kcontrol *kcontrol,
+ struct snd_ctl_elem_value *ucontrol)
+{
+ memset(ucontrol->value.iec958.status, 0xff, AK4113_REG_RXCSB_SIZE);
+ return 0;
+}
+
+static int snd_ak4113_spdif_pinfo(struct snd_kcontrol *kcontrol,
+ struct snd_ctl_elem_info *uinfo)
+{
+ uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER;
+ uinfo->value.integer.min = 0;
+ uinfo->value.integer.max = 0xffff;
+ uinfo->count = 4;
+ return 0;
+}
+
+static int snd_ak4113_spdif_pget(struct snd_kcontrol *kcontrol,
+ struct snd_ctl_elem_value *ucontrol)
+{
+ struct ak4113 *chip = snd_kcontrol_chip(kcontrol);
+ unsigned short tmp;
+
+ ucontrol->value.integer.value[0] = 0xf8f2;
+ ucontrol->value.integer.value[1] = 0x4e1f;
+ tmp = reg_read(chip, AK4113_REG_Pc0) |
+ (reg_read(chip, AK4113_REG_Pc1) << 8);
+ ucontrol->value.integer.value[2] = tmp;
+ tmp = reg_read(chip, AK4113_REG_Pd0) |
+ (reg_read(chip, AK4113_REG_Pd1) << 8);
+ ucontrol->value.integer.value[3] = tmp;
+ return 0;
+}
+
+static int snd_ak4113_spdif_qinfo(struct snd_kcontrol *kcontrol,
+ struct snd_ctl_elem_info *uinfo)
+{
+ uinfo->type = SNDRV_CTL_ELEM_TYPE_BYTES;
+ uinfo->count = AK4113_REG_QSUB_SIZE;
+ return 0;
+}
+
+static int snd_ak4113_spdif_qget(struct snd_kcontrol *kcontrol,
+ struct snd_ctl_elem_value *ucontrol)
+{
+ struct ak4113 *chip = snd_kcontrol_chip(kcontrol);
+ unsigned i;
+
+ for (i = 0; i < AK4113_REG_QSUB_SIZE; i++)
+ ucontrol->value.bytes.data[i] = reg_read(chip,
+ AK4113_REG_QSUB_ADDR + i);
+ return 0;
+}
+
+/* Don't forget to change AK4113_CONTROLS define!!! */
+static struct snd_kcontrol_new snd_ak4113_iec958_controls[] = {
+{
+ .iface = SNDRV_CTL_ELEM_IFACE_PCM,
+ .name = "IEC958 Parity Errors",
+ .access = SNDRV_CTL_ELEM_ACCESS_READ |
+ SNDRV_CTL_ELEM_ACCESS_VOLATILE,
+ .info = snd_ak4113_in_error_info,
+ .get = snd_ak4113_in_error_get,
+ .private_value = offsetof(struct ak4113, parity_errors),
+},
+{
+ .iface = SNDRV_CTL_ELEM_IFACE_PCM,
+ .name = "IEC958 V-Bit Errors",
+ .access = SNDRV_CTL_ELEM_ACCESS_READ |
+ SNDRV_CTL_ELEM_ACCESS_VOLATILE,
+ .info = snd_ak4113_in_error_info,
+ .get = snd_ak4113_in_error_get,
+ .private_value = offsetof(struct ak4113, v_bit_errors),
+},
+{
+ .iface = SNDRV_CTL_ELEM_IFACE_PCM,
+ .name = "IEC958 C-CRC Errors",
+ .access = SNDRV_CTL_ELEM_ACCESS_READ |
+ SNDRV_CTL_ELEM_ACCESS_VOLATILE,
+ .info = snd_ak4113_in_error_info,
+ .get = snd_ak4113_in_error_get,
+ .private_value = offsetof(struct ak4113, ccrc_errors),
+},
+{
+ .iface = SNDRV_CTL_ELEM_IFACE_PCM,
+ .name = "IEC958 Q-CRC Errors",
+ .access = SNDRV_CTL_ELEM_ACCESS_READ |
+ SNDRV_CTL_ELEM_ACCESS_VOLATILE,
+ .info = snd_ak4113_in_error_info,
+ .get = snd_ak4113_in_error_get,
+ .private_value = offsetof(struct ak4113, qcrc_errors),
+},
+{
+ .iface = SNDRV_CTL_ELEM_IFACE_PCM,
+ .name = "IEC958 External Rate",
+ .access = SNDRV_CTL_ELEM_ACCESS_READ |
+ SNDRV_CTL_ELEM_ACCESS_VOLATILE,
+ .info = snd_ak4113_rate_info,
+ .get = snd_ak4113_rate_get,
+},
+{
+ .iface = SNDRV_CTL_ELEM_IFACE_PCM,
+ .name = SNDRV_CTL_NAME_IEC958("", CAPTURE, MASK),
+ .access = SNDRV_CTL_ELEM_ACCESS_READ,
+ .info = snd_ak4113_spdif_mask_info,
+ .get = snd_ak4113_spdif_mask_get,
+},
+{
+ .iface = SNDRV_CTL_ELEM_IFACE_PCM,
+ .name = SNDRV_CTL_NAME_IEC958("", CAPTURE, DEFAULT),
+ .access = SNDRV_CTL_ELEM_ACCESS_READ |
+ SNDRV_CTL_ELEM_ACCESS_VOLATILE,
+ .info = snd_ak4113_spdif_info,
+ .get = snd_ak4113_spdif_get,
+},
+{
+ .iface = SNDRV_CTL_ELEM_IFACE_PCM,
+ .name = "IEC958 Preamble Capture Default",
+ .access = SNDRV_CTL_ELEM_ACCESS_READ |
+ SNDRV_CTL_ELEM_ACCESS_VOLATILE,
+ .info = snd_ak4113_spdif_pinfo,
+ .get = snd_ak4113_spdif_pget,
+},
+{
+ .iface = SNDRV_CTL_ELEM_IFACE_PCM,
+ .name = "IEC958 Q-subcode Capture Default",
+ .access = SNDRV_CTL_ELEM_ACCESS_READ |
+ SNDRV_CTL_ELEM_ACCESS_VOLATILE,
+ .info = snd_ak4113_spdif_qinfo,
+ .get = snd_ak4113_spdif_qget,
+},
+{
+ .iface = SNDRV_CTL_ELEM_IFACE_PCM,
+ .name = "IEC958 Audio",
+ .access = SNDRV_CTL_ELEM_ACCESS_READ |
+ SNDRV_CTL_ELEM_ACCESS_VOLATILE,
+ .info = snd_ak4113_in_bit_info,
+ .get = snd_ak4113_in_bit_get,
+ .private_value = (1<<31) | (1<<8) | AK4113_REG_RCS0,
+},
+{
+ .iface = SNDRV_CTL_ELEM_IFACE_PCM,
+ .name = "IEC958 Non-PCM Bitstream",
+ .access = SNDRV_CTL_ELEM_ACCESS_READ |
+ SNDRV_CTL_ELEM_ACCESS_VOLATILE,
+ .info = snd_ak4113_in_bit_info,
+ .get = snd_ak4113_in_bit_get,
+ .private_value = (0<<8) | AK4113_REG_RCS1,
+},
+{
+ .iface = SNDRV_CTL_ELEM_IFACE_PCM,
+ .name = "IEC958 DTS Bitstream",
+ .access = SNDRV_CTL_ELEM_ACCESS_READ |
+ SNDRV_CTL_ELEM_ACCESS_VOLATILE,
+ .info = snd_ak4113_in_bit_info,
+ .get = snd_ak4113_in_bit_get,
+ .private_value = (1<<8) | AK4113_REG_RCS1,
+},
+{
+ .iface = SNDRV_CTL_ELEM_IFACE_PCM,
+ .name = "AK4113 Input Select",
+ .access = SNDRV_CTL_ELEM_ACCESS_READ |
+ SNDRV_CTL_ELEM_ACCESS_WRITE,
+ .info = snd_ak4113_rx_info,
+ .get = snd_ak4113_rx_get,
+ .put = snd_ak4113_rx_put,
+}
+};
+
+static void snd_ak4113_proc_regs_read(struct snd_info_entry *entry,
+ struct snd_info_buffer *buffer)
+{
+ struct ak4113 *ak4113 = entry->private_data;
+ int reg, val;
+ /* all ak4113 registers 0x00 - 0x1c */
+ for (reg = 0; reg < 0x1d; reg++) {
+ val = reg_read(ak4113, reg);
+ snd_iprintf(buffer, "0x%02x = 0x%02x\n", reg, val);
+ }
+}
+
+static void snd_ak4113_proc_init(struct ak4113 *ak4113)
+{
+ struct snd_info_entry *entry;
+ if (!snd_card_proc_new(ak4113->card, "ak4113", &entry))
+ snd_info_set_text_ops(entry, ak4113, snd_ak4113_proc_regs_read);
+}
+
+int snd_ak4113_build(struct ak4113 *ak4113,
+ struct snd_pcm_substream *cap_substream)
+{
+ struct snd_kcontrol *kctl;
+ unsigned int idx;
+ int err;
+
+ if (snd_BUG_ON(!cap_substream))
+ return -EINVAL;
+ ak4113->substream = cap_substream;
+ for (idx = 0; idx < AK4113_CONTROLS; idx++) {
+ kctl = snd_ctl_new1(&snd_ak4113_iec958_controls[idx], ak4113);
+ if (kctl == NULL)
+ return -ENOMEM;
+ kctl->id.device = cap_substream->pcm->device;
+ kctl->id.subdevice = cap_substream->number;
+ err = snd_ctl_add(ak4113->card, kctl);
+ if (err < 0)
+ return err;
+ ak4113->kctls[idx] = kctl;
+ }
+ snd_ak4113_proc_init(ak4113);
+ /* trigger workq */
+ schedule_delayed_work(&ak4113->work, HZ / 10);
+ return 0;
+}
+EXPORT_SYMBOL_GPL(snd_ak4113_build);
+
+int snd_ak4113_external_rate(struct ak4113 *ak4113)
+{
+ unsigned char rcs1;
+
+ rcs1 = reg_read(ak4113, AK4113_REG_RCS1);
+ return external_rate(rcs1);
+}
+EXPORT_SYMBOL_GPL(snd_ak4113_external_rate);
+
+int snd_ak4113_check_rate_and_errors(struct ak4113 *ak4113, unsigned int flags)
+{
+ struct snd_pcm_runtime *runtime =
+ ak4113->substream ? ak4113->substream->runtime : NULL;
+ unsigned long _flags;
+ int res = 0;
+ unsigned char rcs0, rcs1, rcs2;
+ unsigned char c0, c1;
+
+ rcs1 = reg_read(ak4113, AK4113_REG_RCS1);
+ if (flags & AK4113_CHECK_NO_STAT)
+ goto __rate;
+ rcs0 = reg_read(ak4113, AK4113_REG_RCS0);
+ rcs2 = reg_read(ak4113, AK4113_REG_RCS2);
+ spin_lock_irqsave(&ak4113->lock, _flags);
+ if (rcs0 & AK4113_PAR)
+ ak4113->parity_errors++;
+ if (rcs0 & AK4113_V)
+ ak4113->v_bit_errors++;
+ if (rcs2 & AK4113_CCRC)
+ ak4113->ccrc_errors++;
+ if (rcs2 & AK4113_QCRC)
+ ak4113->qcrc_errors++;
+ c0 = (ak4113->rcs0 & (AK4113_QINT | AK4113_CINT | AK4113_STC |
+ AK4113_AUDION | AK4113_AUTO | AK4113_UNLCK)) ^
+ (rcs0 & (AK4113_QINT | AK4113_CINT | AK4113_STC |
+ AK4113_AUDION | AK4113_AUTO | AK4113_UNLCK));
+ c1 = (ak4113->rcs1 & (AK4113_DTSCD | AK4113_NPCM | AK4113_PEM |
+ AK4113_DAT | 0xf0)) ^
+ (rcs1 & (AK4113_DTSCD | AK4113_NPCM | AK4113_PEM |
+ AK4113_DAT | 0xf0));
+ ak4113->rcs0 = rcs0 & ~(AK4113_QINT | AK4113_CINT | AK4113_STC);
+ ak4113->rcs1 = rcs1;
+ ak4113->rcs2 = rcs2;
+ spin_unlock_irqrestore(&ak4113->lock, _flags);
+
+ if (rcs0 & AK4113_PAR)
+ snd_ctl_notify(ak4113->card, SNDRV_CTL_EVENT_MASK_VALUE,
+ &ak4113->kctls[0]->id);
+ if (rcs0 & AK4113_V)
+ snd_ctl_notify(ak4113->card, SNDRV_CTL_EVENT_MASK_VALUE,
+ &ak4113->kctls[1]->id);
+ if (rcs2 & AK4113_CCRC)
+ snd_ctl_notify(ak4113->card, SNDRV_CTL_EVENT_MASK_VALUE,
+ &ak4113->kctls[2]->id);
+ if (rcs2 & AK4113_QCRC)
+ snd_ctl_notify(ak4113->card, SNDRV_CTL_EVENT_MASK_VALUE,
+ &ak4113->kctls[3]->id);
+
+ /* rate change */
+ if (c1 & 0xf0)
+ snd_ctl_notify(ak4113->card, SNDRV_CTL_EVENT_MASK_VALUE,
+ &ak4113->kctls[4]->id);
+
+ if ((c1 & AK4113_PEM) | (c0 & AK4113_CINT))
+ snd_ctl_notify(ak4113->card, SNDRV_CTL_EVENT_MASK_VALUE,
+ &ak4113->kctls[6]->id);
+ if (c0 & AK4113_QINT)
+ snd_ctl_notify(ak4113->card, SNDRV_CTL_EVENT_MASK_VALUE,
+ &ak4113->kctls[8]->id);
+
+ if (c0 & AK4113_AUDION)
+ snd_ctl_notify(ak4113->card, SNDRV_CTL_EVENT_MASK_VALUE,
+ &ak4113->kctls[9]->id);
+ if (c1 & AK4113_NPCM)
+ snd_ctl_notify(ak4113->card, SNDRV_CTL_EVENT_MASK_VALUE,
+ &ak4113->kctls[10]->id);
+ if (c1 & AK4113_DTSCD)
+ snd_ctl_notify(ak4113->card, SNDRV_CTL_EVENT_MASK_VALUE,
+ &ak4113->kctls[11]->id);
+
+ if (ak4113->change_callback && (c0 | c1) != 0)
+ ak4113->change_callback(ak4113, c0, c1);
+
+__rate:
+ /* compare rate */
+ res = external_rate(rcs1);
+ if (!(flags & AK4113_CHECK_NO_RATE) && runtime &&
+ (runtime->rate != res)) {
+ snd_pcm_stream_lock_irqsave(ak4113->substream, _flags);
+ if (snd_pcm_running(ak4113->substream)) {
+ /*printk(KERN_DEBUG "rate changed (%i <- %i)\n",
+ * runtime->rate, res); */
+ snd_pcm_stop(ak4113->substream,
+ SNDRV_PCM_STATE_DRAINING);
+ wake_up(&runtime->sleep);
+ res = 1;
+ }
+ snd_pcm_stream_unlock_irqrestore(ak4113->substream, _flags);
+ }
+ return res;
+}
+EXPORT_SYMBOL_GPL(snd_ak4113_check_rate_and_errors);
+
+static void ak4113_stats(struct work_struct *work)
+{
+ struct ak4113 *chip = container_of(work, struct ak4113, work.work);
+
+ if (!chip->init)
+ snd_ak4113_check_rate_and_errors(chip, chip->check_flags);
+
+ schedule_delayed_work(&chip->work, HZ / 10);
+}
diff --git a/sound/i2c/other/ak4114.c b/sound/i2c/other/ak4114.c
index 15061bd7277..c7f56339415 100644
--- a/sound/i2c/other/ak4114.c
+++ b/sound/i2c/other/ak4114.c
@@ -22,11 +22,13 @@
#include <linux/slab.h>
#include <linux/delay.h>
+#include <linux/module.h>
#include <sound/core.h>
#include <sound/control.h>
#include <sound/pcm.h>
#include <sound/ak4114.h>
#include <sound/asoundef.h>
+#include <sound/info.h>
MODULE_AUTHOR("Jaroslav Kysela <perex@perex.cz>");
MODULE_DESCRIPTION("AK4114 IEC958 (S/PDIF) receiver by Asahi Kasei");
@@ -58,7 +60,7 @@ static void reg_dump(struct ak4114 *ak4114)
printk(KERN_DEBUG "AK4114 REG DUMP:\n");
for (i = 0; i < 0x20; i++)
- printk(KERN_DEBUG "reg[%02x] = %02x (%02x)\n", i, reg_read(ak4114, i), i < sizeof(ak4114->regmap) ? ak4114->regmap[i] : 0);
+ printk(KERN_DEBUG "reg[%02x] = %02x (%02x)\n", i, reg_read(ak4114, i), i < ARRAY_SIZE(ak4114->regmap) ? ak4114->regmap[i] : 0);
}
#endif
@@ -66,8 +68,7 @@ static void snd_ak4114_free(struct ak4114 *chip)
{
chip->init = 1; /* don't schedule new work */
mb();
- cancel_delayed_work(&chip->work);
- flush_scheduled_work();
+ cancel_delayed_work_sync(&chip->work);
kfree(chip);
}
@@ -80,7 +81,7 @@ static int snd_ak4114_dev_free(struct snd_device *device)
int snd_ak4114_create(struct snd_card *card,
ak4114_read_t *read, ak4114_write_t *write,
- const unsigned char pgm[7], const unsigned char txcsb[5],
+ const unsigned char pgm[6], const unsigned char txcsb[5],
void *private_data, struct ak4114 **r_ak4114)
{
struct ak4114 *chip;
@@ -100,7 +101,7 @@ int snd_ak4114_create(struct snd_card *card,
chip->private_data = private_data;
INIT_DELAYED_WORK(&chip->work, ak4114_stats);
- for (reg = 0; reg < 7; reg++)
+ for (reg = 0; reg < 6; reg++)
chip->regmap[reg] = pgm[reg];
for (reg = 0; reg < 5; reg++)
chip->txcsb[reg] = txcsb[reg];
@@ -110,7 +111,7 @@ int snd_ak4114_create(struct snd_card *card,
chip->rcs0 = reg_read(chip, AK4114_REG_RCS0) & ~(AK4114_QINT | AK4114_CINT);
chip->rcs1 = reg_read(chip, AK4114_REG_RCS1);
- if ((err = snd_device_new(card, SNDRV_DEV_LOWLEVEL, chip, &ops)) < 0)
+ if ((err = snd_device_new(card, SNDRV_DEV_CODEC, chip, &ops)) < 0)
goto __fail;
if (r_ak4114)
@@ -141,7 +142,7 @@ static void ak4114_init_regs(struct ak4114 *chip)
/* release reset, but leave powerdown */
reg_write(chip, AK4114_REG_PWRDN, (old | AK4114_RST) & ~AK4114_PWN);
udelay(200);
- for (reg = 1; reg < 7; reg++)
+ for (reg = 1; reg < 6; reg++)
reg_write(chip, reg, chip->regmap[reg]);
for (reg = 0; reg < 5; reg++)
reg_write(chip, reg + AK4114_REG_TXCSB0, chip->txcsb[reg]);
@@ -153,7 +154,7 @@ void snd_ak4114_reinit(struct ak4114 *chip)
{
chip->init = 1;
mb();
- flush_scheduled_work();
+ flush_delayed_work(&chip->work);
ak4114_init_regs(chip);
/* bring up statistics / event queing */
chip->init = 0;
@@ -400,7 +401,7 @@ static struct snd_kcontrol_new snd_ak4114_iec958_controls[] = {
},
{
.iface = SNDRV_CTL_ELEM_IFACE_PCM,
- .name = "IEC958 Preample Capture Default",
+ .name = "IEC958 Preamble Capture Default",
.access = SNDRV_CTL_ELEM_ACCESS_READ | SNDRV_CTL_ELEM_ACCESS_VOLATILE,
.info = snd_ak4114_spdif_pinfo,
.get = snd_ak4114_spdif_pget,
@@ -446,6 +447,26 @@ static struct snd_kcontrol_new snd_ak4114_iec958_controls[] = {
}
};
+
+static void snd_ak4114_proc_regs_read(struct snd_info_entry *entry,
+ struct snd_info_buffer *buffer)
+{
+ struct ak4114 *ak4114 = entry->private_data;
+ int reg, val;
+ /* all ak4114 registers 0x00 - 0x1f */
+ for (reg = 0; reg < 0x20; reg++) {
+ val = reg_read(ak4114, reg);
+ snd_iprintf(buffer, "0x%02x = 0x%02x\n", reg, val);
+ }
+}
+
+static void snd_ak4114_proc_init(struct ak4114 *ak4114)
+{
+ struct snd_info_entry *entry;
+ if (!snd_card_proc_new(ak4114->card, "ak4114", &entry))
+ snd_info_set_text_ops(entry, ak4114, snd_ak4114_proc_regs_read);
+}
+
int snd_ak4114_build(struct ak4114 *ak4114,
struct snd_pcm_substream *ply_substream,
struct snd_pcm_substream *cap_substream)
@@ -454,7 +475,8 @@ int snd_ak4114_build(struct ak4114 *ak4114,
unsigned int idx;
int err;
- snd_assert(cap_substream, return -EINVAL);
+ if (snd_BUG_ON(!cap_substream))
+ return -EINVAL;
ak4114->playback_substream = ply_substream;
ak4114->capture_substream = cap_substream;
for (idx = 0; idx < AK4114_CONTROLS; idx++) {
@@ -478,6 +500,7 @@ int snd_ak4114_build(struct ak4114 *ak4114,
return err;
ak4114->kctls[idx] = kctl;
}
+ snd_ak4114_proc_init(ak4114);
/* trigger workq */
schedule_delayed_work(&ak4114->work, HZ / 10);
return 0;
@@ -590,7 +613,7 @@ static void ak4114_stats(struct work_struct *work)
struct ak4114 *chip = container_of(work, struct ak4114, work.work);
if (!chip->init)
- snd_ak4114_check_rate_and_errors(chip, 0);
+ snd_ak4114_check_rate_and_errors(chip, chip->check_flags);
schedule_delayed_work(&chip->work, HZ / 10);
}
diff --git a/sound/i2c/other/ak4117.c b/sound/i2c/other/ak4117.c
index f350835ade9..88452e899bd 100644
--- a/sound/i2c/other/ak4117.c
+++ b/sound/i2c/other/ak4117.c
@@ -22,6 +22,7 @@
#include <linux/slab.h>
#include <linux/delay.h>
+#include <linux/module.h>
#include <sound/core.h>
#include <sound/control.h>
#include <sound/pcm.h>
@@ -61,7 +62,7 @@ static void reg_dump(struct ak4117 *ak4117)
static void snd_ak4117_free(struct ak4117 *chip)
{
- del_timer(&chip->timer);
+ del_timer_sync(&chip->timer);
kfree(chip);
}
@@ -379,7 +380,7 @@ static struct snd_kcontrol_new snd_ak4117_iec958_controls[] = {
},
{
.iface = SNDRV_CTL_ELEM_IFACE_PCM,
- .name = "IEC958 Preample Capture Default",
+ .name = "IEC958 Preamble Capture Default",
.access = SNDRV_CTL_ELEM_ACCESS_READ | SNDRV_CTL_ELEM_ACCESS_VOLATILE,
.info = snd_ak4117_spdif_pinfo,
.get = snd_ak4117_spdif_pget,
@@ -431,7 +432,8 @@ int snd_ak4117_build(struct ak4117 *ak4117, struct snd_pcm_substream *cap_substr
unsigned int idx;
int err;
- snd_assert(cap_substream, return -EINVAL);
+ if (snd_BUG_ON(!cap_substream))
+ return -EINVAL;
ak4117->substream = cap_substream;
for (idx = 0; idx < AK4117_CONTROLS; idx++) {
kctl = snd_ctl_new1(&snd_ak4117_iec958_controls[idx], ak4117);
diff --git a/sound/i2c/other/ak4xxx-adda.c b/sound/i2c/other/ak4xxx-adda.c
index 35fbbf2cb9f..f3735e64791 100644
--- a/sound/i2c/other/ak4xxx-adda.c
+++ b/sound/i2c/other/ak4xxx-adda.c
@@ -19,16 +19,18 @@
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*
- */
+ */
#include <asm/io.h>
#include <linux/delay.h>
#include <linux/interrupt.h>
#include <linux/init.h>
+#include <linux/module.h>
#include <sound/core.h>
#include <sound/control.h>
#include <sound/tlv.h>
#include <sound/ak4xxx-adda.h>
+#include <sound/info.h>
MODULE_AUTHOR("Jaroslav Kysela <perex@perex.cz>, Takashi Iwai <tiwai@suse.de>");
MODULE_DESCRIPTION("Routines for control of AK452x / AK43xx AD/DA converters");
@@ -52,25 +54,21 @@ EXPORT_SYMBOL(snd_akm4xxx_write);
static void ak4524_reset(struct snd_akm4xxx *ak, int state)
{
unsigned int chip;
- unsigned char reg, maxreg;
+ unsigned char reg;
- if (ak->type == SND_AK4528)
- maxreg = 0x06;
- else
- maxreg = 0x08;
for (chip = 0; chip < ak->num_dacs/2; chip++) {
snd_akm4xxx_write(ak, chip, 0x01, state ? 0x00 : 0x03);
if (state)
continue;
/* DAC volumes */
- for (reg = 0x04; reg < maxreg; reg++)
+ for (reg = 0x04; reg < ak->total_regs; reg++)
snd_akm4xxx_write(ak, chip, reg,
snd_akm4xxx_get(ak, chip, reg));
}
}
/* reset procedure for AK4355 and AK4358 */
-static void ak4355_reset(struct snd_akm4xxx *ak, int state)
+static void ak435X_reset(struct snd_akm4xxx *ak, int state)
{
unsigned char reg;
@@ -78,7 +76,7 @@ static void ak4355_reset(struct snd_akm4xxx *ak, int state)
snd_akm4xxx_write(ak, 0, 0x01, 0x02); /* reset and soft-mute */
return;
}
- for (reg = 0x00; reg < 0x0b; reg++)
+ for (reg = 0x00; reg < ak->total_regs; reg++)
if (reg != 0x01)
snd_akm4xxx_write(ak, 0, reg,
snd_akm4xxx_get(ak, 0, reg));
@@ -90,12 +88,11 @@ static void ak4381_reset(struct snd_akm4xxx *ak, int state)
{
unsigned int chip;
unsigned char reg;
-
for (chip = 0; chip < ak->num_dacs/2; chip++) {
snd_akm4xxx_write(ak, chip, 0x00, state ? 0x0c : 0x0f);
if (state)
continue;
- for (reg = 0x01; reg < 0x05; reg++)
+ for (reg = 0x01; reg < ak->total_regs; reg++)
snd_akm4xxx_write(ak, chip, reg,
snd_akm4xxx_get(ak, chip, reg));
}
@@ -112,14 +109,17 @@ void snd_akm4xxx_reset(struct snd_akm4xxx *ak, int state)
switch (ak->type) {
case SND_AK4524:
case SND_AK4528:
+ case SND_AK4620:
ak4524_reset(ak, state);
break;
case SND_AK4529:
/* FIXME: needed for ak4529? */
break;
case SND_AK4355:
+ ak435X_reset(ak, state);
+ break;
case SND_AK4358:
- ak4355_reset(ak, state);
+ ak435X_reset(ak, state);
break;
case SND_AK4381:
ak4381_reset(ak, state);
@@ -136,7 +136,7 @@ EXPORT_SYMBOL(snd_akm4xxx_reset);
* Volume conversion table for non-linear volumes
* from -63.5dB (mute) to 0dB step 0.5dB
*
- * Used for AK4524 input/ouput attenuation, AK4528, and
+ * Used for AK4524/AK4620 input/ouput attenuation, AK4528, and
* AK5365 input attenuation
*/
static const unsigned char vol_cvt_datt[128] = {
@@ -230,8 +230,8 @@ void snd_akm4xxx_init(struct snd_akm4xxx *ak)
0x01, 0x02, /* 1: reset and soft-mute */
0x00, 0x06, /* 0: mode3(i2s), disable auto-clock detect,
* disable DZF, sharp roll-off, RSTN#=0 */
- 0x02, 0x0e, /* 2: DA's power up, normal speed, RSTN#=0 */
- // 0x02, 0x2e, /* quad speed */
+ 0x02, 0x4e, /* 2: DA's power up, normal speed, RSTN#=0 */
+ /* 0x02, 0x6e,*/ /* quad speed */
0x03, 0x01, /* 3: de-emphasis off */
0x04, 0x00, /* 4: LOUT1 volume muted */
0x05, 0x00, /* 5: ROUT1 volume muted */
@@ -256,8 +256,22 @@ void snd_akm4xxx_init(struct snd_akm4xxx *ak)
0x00, 0x0f, /* 0: power-up, un-reset */
0xff, 0xff
};
+ static const unsigned char inits_ak4620[] = {
+ 0x00, 0x07, /* 0: normal */
+ 0x01, 0x00, /* 0: reset */
+ 0x01, 0x02, /* 1: RSTAD */
+ 0x01, 0x03, /* 1: RSTDA */
+ 0x01, 0x0f, /* 1: normal */
+ 0x02, 0x60, /* 2: 24bit I2S */
+ 0x03, 0x01, /* 3: deemphasis off */
+ 0x04, 0x00, /* 4: LIN muted */
+ 0x05, 0x00, /* 5: RIN muted */
+ 0x06, 0x00, /* 6: LOUT muted */
+ 0x07, 0x00, /* 7: ROUT muted */
+ 0xff, 0xff
+ };
- int chip, num_chips;
+ int chip;
const unsigned char *ptr, *inits;
unsigned char reg, data;
@@ -267,47 +281,64 @@ void snd_akm4xxx_init(struct snd_akm4xxx *ak)
switch (ak->type) {
case SND_AK4524:
inits = inits_ak4524;
- num_chips = ak->num_dacs / 2;
+ ak->num_chips = ak->num_dacs / 2;
+ ak->name = "ak4524";
+ ak->total_regs = 0x08;
break;
case SND_AK4528:
inits = inits_ak4528;
- num_chips = ak->num_dacs / 2;
+ ak->num_chips = ak->num_dacs / 2;
+ ak->name = "ak4528";
+ ak->total_regs = 0x06;
break;
case SND_AK4529:
inits = inits_ak4529;
- num_chips = 1;
+ ak->num_chips = 1;
+ ak->name = "ak4529";
+ ak->total_regs = 0x0d;
break;
case SND_AK4355:
inits = inits_ak4355;
- num_chips = 1;
+ ak->num_chips = 1;
+ ak->name = "ak4355";
+ ak->total_regs = 0x0b;
break;
case SND_AK4358:
inits = inits_ak4358;
- num_chips = 1;
+ ak->num_chips = 1;
+ ak->name = "ak4358";
+ ak->total_regs = 0x10;
break;
case SND_AK4381:
inits = inits_ak4381;
- num_chips = ak->num_dacs / 2;
+ ak->num_chips = ak->num_dacs / 2;
+ ak->name = "ak4381";
+ ak->total_regs = 0x05;
break;
case SND_AK5365:
/* FIXME: any init sequence? */
+ ak->num_chips = 1;
+ ak->name = "ak5365";
+ ak->total_regs = 0x08;
return;
- case NON_AKM:
- /* fake value for non-akm codecs using akm infrastructure
- * (e.g. of ice1724) - certainly FIXME
- */
- return;
+ case SND_AK4620:
+ inits = inits_ak4620;
+ ak->num_chips = ak->num_dacs / 2;
+ ak->name = "ak4620";
+ ak->total_regs = 0x08;
+ break;
default:
snd_BUG();
return;
}
- for (chip = 0; chip < num_chips; chip++) {
+ for (chip = 0; chip < ak->num_chips; chip++) {
ptr = inits;
while (*ptr != 0xff) {
reg = *ptr++;
data = *ptr++;
snd_akm4xxx_write(ak, chip, reg, data);
+ udelay(10);
}
}
}
@@ -374,6 +405,8 @@ static int put_ak_reg(struct snd_kcontrol *kcontrol, int addr,
nval = mask - nval;
if (AK_GET_NEEDSMSB(kcontrol->private_value))
nval |= 0x80;
+ /* printk(KERN_DEBUG "DEBUG - AK writing reg: chip %x addr %x,
+ nval %x\n", chip, addr, nval); */
snd_akm4xxx_write(ak, chip, addr, nval);
return 1;
}
@@ -538,7 +571,7 @@ static int ak4xxx_capture_source_info(struct snd_kcontrol *kcontrol,
struct snd_akm4xxx *ak = snd_kcontrol_chip(kcontrol);
int mixer_ch = AK_GET_SHIFT(kcontrol->private_value);
const char **input_names;
- int num_names, idx;
+ unsigned int num_names, idx;
num_names = ak4xxx_capture_num_inputs(ak, mixer_ch);
if (!num_names)
@@ -550,7 +583,7 @@ static int ak4xxx_capture_source_info(struct snd_kcontrol *kcontrol,
if (idx >= num_names)
return -EINVAL;
input_names = ak->adc_info[mixer_ch].input_names;
- strncpy(uinfo->value.enumerated.name, input_names[idx],
+ strlcpy(uinfo->value.enumerated.name, input_names[idx],
sizeof(uinfo->value.enumerated.name));
return 0;
}
@@ -688,6 +721,12 @@ static int build_dac_controls(struct snd_akm4xxx *ak)
AK_COMPOSE(idx/2, (idx%2) + 3, 0, 255);
knew.tlv.p = db_scale_linear;
break;
+ case SND_AK4620:
+ /* register 6 & 7 */
+ knew.private_value =
+ AK_COMPOSE(idx/2, (idx%2) + 6, 0, 255);
+ knew.tlv.p = db_scale_linear;
+ break;
default:
return -EINVAL;
}
@@ -704,10 +743,12 @@ static int build_dac_controls(struct snd_akm4xxx *ak)
static int build_adc_controls(struct snd_akm4xxx *ak)
{
- int idx, err, mixer_ch, num_stereo;
+ int idx, err, mixer_ch, num_stereo, max_steps;
struct snd_kcontrol_new knew;
mixer_ch = 0;
+ if (ak->type == SND_AK4528)
+ return 0; /* no controls */
for (idx = 0; idx < ak->num_adcs;) {
memset(&knew, 0, sizeof(knew));
if (! ak->adc_info || ! ak->adc_info[mixer_ch].name) {
@@ -733,13 +774,12 @@ static int build_adc_controls(struct snd_akm4xxx *ak)
}
/* register 4 & 5 */
if (ak->type == SND_AK5365)
- knew.private_value =
- AK_COMPOSE(idx/2, (idx%2) + 4, 0, 151) |
- AK_VOL_CVT | AK_IPGA;
+ max_steps = 152;
else
- knew.private_value =
- AK_COMPOSE(idx/2, (idx%2) + 4, 0, 163) |
- AK_VOL_CVT | AK_IPGA;
+ max_steps = 164;
+ knew.private_value =
+ AK_COMPOSE(idx/2, (idx%2) + 4, 0, max_steps) |
+ AK_VOL_CVT | AK_IPGA;
knew.tlv.p = db_scale_vol_datt;
err = snd_ctl_add(ak->card, snd_ctl_new1(&knew, ak));
if (err < 0)
@@ -808,6 +848,7 @@ static int build_deemphasis(struct snd_akm4xxx *ak, int num_emphs)
switch (ak->type) {
case SND_AK4524:
case SND_AK4528:
+ case SND_AK4620:
/* register 3 */
knew.private_value = AK_COMPOSE(idx, 3, 0, 0);
break;
@@ -834,6 +875,35 @@ static int build_deemphasis(struct snd_akm4xxx *ak, int num_emphs)
return 0;
}
+#ifdef CONFIG_PROC_FS
+static void proc_regs_read(struct snd_info_entry *entry,
+ struct snd_info_buffer *buffer)
+{
+ struct snd_akm4xxx *ak = entry->private_data;
+ int reg, val, chip;
+ for (chip = 0; chip < ak->num_chips; chip++) {
+ for (reg = 0; reg < ak->total_regs; reg++) {
+ val = snd_akm4xxx_get(ak, chip, reg);
+ snd_iprintf(buffer, "chip %d: 0x%02x = 0x%02x\n", chip,
+ reg, val);
+ }
+ }
+}
+
+static int proc_init(struct snd_akm4xxx *ak)
+{
+ struct snd_info_entry *entry;
+ int err;
+ err = snd_card_proc_new(ak->card, ak->name, &entry);
+ if (err < 0)
+ return err;
+ snd_info_set_text_ops(entry, ak, proc_regs_read);
+ return 0;
+}
+#else /* !CONFIG_PROC_FS */
+static int proc_init(struct snd_akm4xxx *ak) { return 0; }
+#endif
+
int snd_akm4xxx_build_controls(struct snd_akm4xxx *ak)
{
int err, num_emphs;
@@ -845,18 +915,21 @@ int snd_akm4xxx_build_controls(struct snd_akm4xxx *ak)
err = build_adc_controls(ak);
if (err < 0)
return err;
-
if (ak->type == SND_AK4355 || ak->type == SND_AK4358)
num_emphs = 1;
+ else if (ak->type == SND_AK4620)
+ num_emphs = 0;
else
num_emphs = ak->num_dacs / 2;
err = build_deemphasis(ak, num_emphs);
if (err < 0)
return err;
+ err = proc_init(ak);
+ if (err < 0)
+ return err;
return 0;
}
-
EXPORT_SYMBOL(snd_akm4xxx_build_controls);
static int __init alsa_akm4xxx_module_init(void)
diff --git a/sound/i2c/other/pt2258.c b/sound/i2c/other/pt2258.c
index 797d3a6687e..9fa390ba171 100644
--- a/sound/i2c/other/pt2258.c
+++ b/sound/i2c/other/pt2258.c
@@ -24,6 +24,7 @@
#include <sound/tlv.h>
#include <sound/i2c.h>
#include <sound/pt2258.h>
+#include <linux/module.h>
MODULE_AUTHOR("Jochen Voss <voss@seehuhn.de>");
MODULE_DESCRIPTION("PT2258 volume controller (Princeton Technology Corp.)");
diff --git a/sound/i2c/other/tea575x-tuner.c b/sound/i2c/other/tea575x-tuner.c
deleted file mode 100644
index 87e3aefeddc..00000000000
--- a/sound/i2c/other/tea575x-tuner.c
+++ /dev/null
@@ -1,239 +0,0 @@
-/*
- * ALSA driver for TEA5757/5759 Philips AM/FM radio tuner chips
- *
- * Copyright (c) 2004 Jaroslav Kysela <perex@perex.cz>
- *
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
- *
- */
-
-#include <asm/io.h>
-#include <linux/delay.h>
-#include <linux/interrupt.h>
-#include <linux/init.h>
-#include <sound/core.h>
-#include <sound/tea575x-tuner.h>
-
-MODULE_AUTHOR("Jaroslav Kysela <perex@perex.cz>");
-MODULE_DESCRIPTION("Routines for control of TEA5757/5759 Philips AM/FM radio tuner chips");
-MODULE_LICENSE("GPL");
-
-/*
- * definitions
- */
-
-#define TEA575X_BIT_SEARCH (1<<24) /* 1 = search action, 0 = tuned */
-#define TEA575X_BIT_UPDOWN (1<<23) /* 0 = search down, 1 = search up */
-#define TEA575X_BIT_MONO (1<<22) /* 0 = stereo, 1 = mono */
-#define TEA575X_BIT_BAND_MASK (3<<20)
-#define TEA575X_BIT_BAND_FM (0<<20)
-#define TEA575X_BIT_BAND_MW (1<<20)
-#define TEA575X_BIT_BAND_LW (1<<21)
-#define TEA575X_BIT_BAND_SW (1<<22)
-#define TEA575X_BIT_PORT_0 (1<<19) /* user bit */
-#define TEA575X_BIT_PORT_1 (1<<18) /* user bit */
-#define TEA575X_BIT_SEARCH_MASK (3<<16) /* search level */
-#define TEA575X_BIT_SEARCH_5_28 (0<<16) /* FM >5uV, AM >28uV */
-#define TEA575X_BIT_SEARCH_10_40 (1<<16) /* FM >10uV, AM > 40uV */
-#define TEA575X_BIT_SEARCH_30_63 (2<<16) /* FM >30uV, AM > 63uV */
-#define TEA575X_BIT_SEARCH_150_1000 (3<<16) /* FM > 150uV, AM > 1000uV */
-#define TEA575X_BIT_DUMMY (1<<15) /* buffer */
-#define TEA575X_BIT_FREQ_MASK 0x7fff
-
-/*
- * lowlevel part
- */
-
-static void snd_tea575x_set_freq(struct snd_tea575x *tea)
-{
- unsigned long freq;
-
- freq = tea->freq / 16; /* to kHz */
- if (freq > 108000)
- freq = 108000;
- if (freq < 87000)
- freq = 87000;
- /* crystal fixup */
- if (tea->tea5759)
- freq -= tea->freq_fixup;
- else
- freq += tea->freq_fixup;
- /* freq /= 12.5 */
- freq *= 10;
- freq /= 125;
-
- tea->val &= ~TEA575X_BIT_FREQ_MASK;
- tea->val |= freq & TEA575X_BIT_FREQ_MASK;
- tea->ops->write(tea, tea->val);
-}
-
-/*
- * Linux Video interface
- */
-
-static int snd_tea575x_ioctl(struct inode *inode, struct file *file,
- unsigned int cmd, unsigned long data)
-{
- struct video_device *dev = video_devdata(file);
- struct snd_tea575x *tea = video_get_drvdata(dev);
- void __user *arg = (void __user *)data;
-
- switch(cmd) {
- case VIDIOCGCAP:
- {
- struct video_capability v;
- v.type = VID_TYPE_TUNER;
- v.channels = 1;
- v.audios = 1;
- /* No we don't do pictures */
- v.maxwidth = 0;
- v.maxheight = 0;
- v.minwidth = 0;
- v.minheight = 0;
- strcpy(v.name, tea->tea5759 ? "TEA5759" : "TEA5757");
- if (copy_to_user(arg,&v,sizeof(v)))
- return -EFAULT;
- return 0;
- }
- case VIDIOCGTUNER:
- {
- struct video_tuner v;
- if (copy_from_user(&v, arg,sizeof(v))!=0)
- return -EFAULT;
- if (v.tuner) /* Only 1 tuner */
- return -EINVAL;
- v.rangelow = (87*16000);
- v.rangehigh = (108*16000);
- v.flags = VIDEO_TUNER_LOW;
- v.mode = VIDEO_MODE_AUTO;
- strcpy(v.name, "FM");
- v.signal = 0xFFFF;
- if (copy_to_user(arg, &v, sizeof(v)))
- return -EFAULT;
- return 0;
- }
- case VIDIOCSTUNER:
- {
- struct video_tuner v;
- if(copy_from_user(&v, arg, sizeof(v)))
- return -EFAULT;
- if(v.tuner!=0)
- return -EINVAL;
- /* Only 1 tuner so no setting needed ! */
- return 0;
- }
- case VIDIOCGFREQ:
- if(copy_to_user(arg, &tea->freq, sizeof(tea->freq)))
- return -EFAULT;
- return 0;
- case VIDIOCSFREQ:
- if(copy_from_user(&tea->freq, arg, sizeof(tea->freq)))
- return -EFAULT;
- snd_tea575x_set_freq(tea);
- return 0;
- case VIDIOCGAUDIO:
- {
- struct video_audio v;
- memset(&v, 0, sizeof(v));
- strcpy(v.name, "Radio");
- if(copy_to_user(arg,&v, sizeof(v)))
- return -EFAULT;
- return 0;
- }
- case VIDIOCSAUDIO:
- {
- struct video_audio v;
- if(copy_from_user(&v, arg, sizeof(v)))
- return -EFAULT;
- if (tea->ops->mute)
- tea->ops->mute(tea,
- (v.flags &
- VIDEO_AUDIO_MUTE) ? 1 : 0);
- if(v.audio)
- return -EINVAL;
- return 0;
- }
- default:
- return -ENOIOCTLCMD;
- }
-}
-
-static void snd_tea575x_release(struct video_device *vfd)
-{
-}
-
-/*
- * initialize all the tea575x chips
- */
-void snd_tea575x_init(struct snd_tea575x *tea)
-{
- unsigned int val;
-
- val = tea->ops->read(tea);
- if (val == 0x1ffffff || val == 0) {
- snd_printk(KERN_ERR "Cannot find TEA575x chip\n");
- return;
- }
-
- memset(&tea->vd, 0, sizeof(tea->vd));
- tea->vd.owner = tea->card->module;
- strcpy(tea->vd.name, tea->tea5759 ? "TEA5759 radio" : "TEA5757 radio");
- tea->vd.type = VID_TYPE_TUNER;
- tea->vd.release = snd_tea575x_release;
- video_set_drvdata(&tea->vd, tea);
- tea->vd.fops = &tea->fops;
- tea->fops.owner = tea->card->module;
- tea->fops.open = video_exclusive_open;
- tea->fops.release = video_exclusive_release;
- tea->fops.ioctl = snd_tea575x_ioctl;
- if (video_register_device(&tea->vd, VFL_TYPE_RADIO, tea->dev_nr - 1) < 0) {
- snd_printk(KERN_ERR "unable to register tea575x tuner\n");
- return;
- }
- tea->vd_registered = 1;
-
- tea->val = TEA575X_BIT_BAND_FM | TEA575X_BIT_SEARCH_10_40;
- tea->freq = 90500 * 16; /* 90.5Mhz default */
-
- snd_tea575x_set_freq(tea);
-
- /* mute on init */
- if (tea->ops->mute)
- tea->ops->mute(tea, 1);
-}
-
-void snd_tea575x_exit(struct snd_tea575x *tea)
-{
- if (tea->vd_registered) {
- video_unregister_device(&tea->vd);
- tea->vd_registered = 0;
- }
-}
-
-static int __init alsa_tea575x_module_init(void)
-{
- return 0;
-}
-
-static void __exit alsa_tea575x_module_exit(void)
-{
-}
-
-module_init(alsa_tea575x_module_init)
-module_exit(alsa_tea575x_module_exit)
-
-EXPORT_SYMBOL(snd_tea575x_init);
-EXPORT_SYMBOL(snd_tea575x_exit);
diff --git a/sound/i2c/tea6330t.c b/sound/i2c/tea6330t.c
index 0e3a9f2c529..2d22310dce0 100644
--- a/sound/i2c/tea6330t.c
+++ b/sound/i2c/tea6330t.c
@@ -22,6 +22,7 @@
#include <linux/init.h>
#include <linux/slab.h>
+#include <linux/module.h>
#include <sound/core.h>
#include <sound/control.h>
#include <sound/tea6330t.h>