diff options
author | Florian Fainelli <florian@openwrt.org> | 2012-11-30 10:53:47 +0000 |
---|---|---|
committer | Florian Fainelli <florian@openwrt.org> | 2012-11-30 10:53:47 +0000 |
commit | 527afd0e9ad14751e4b26c70aa9e9883c839218e (patch) | |
tree | d478bdde0069ca371b27ff57f86cb7e92d1c5cfb /target/linux/ubicom32/files/sound | |
parent | a68f386663f09d3abb315fd8d01e5733547c3005 (diff) | |
download | mtk-20170518-527afd0e9ad14751e4b26c70aa9e9883c839218e.zip mtk-20170518-527afd0e9ad14751e4b26c70aa9e9883c839218e.tar.gz mtk-20170518-527afd0e9ad14751e4b26c70aa9e9883c839218e.tar.bz2 |
remove target
This target is unused, does not support any off the shelf hardware and
has been a maintenance burden for quite some time now.
Signed-off-by: Florian Fainelli <florian@openwrt.org>
SVN-Revision: 34430
Diffstat (limited to 'target/linux/ubicom32/files/sound')
8 files changed, 0 insertions, 2808 deletions
diff --git a/target/linux/ubicom32/files/sound/ubicom32/Kconfig b/target/linux/ubicom32/files/sound/ubicom32/Kconfig deleted file mode 100644 index c57bd34..0000000 --- a/target/linux/ubicom32/files/sound/ubicom32/Kconfig +++ /dev/null @@ -1,42 +0,0 @@ -# ALSA Ubicom32 drivers - -menuconfig SND_UBI32 - tristate "Ubicom32 sound devices" - select SND_PCM - default n - help - Say Y here to include support for audio on the Ubicom32 platform. - To compile this driver as a module, say M here: the module will be - called snd_ubi32. - -if SND_UBI32 - -config SND_UBI32_AUDIO_GENERIC_CAPTURE - bool "Generic Capture Support" - default n - help - Use this option to support ADCs which don't require special drivers. - -config SND_UBI32_AUDIO_GENERIC - bool "Generic Playback Support" - default n - help - Use this option to support DACs which don't require special drivers. - -comment "I2C Based Codecs" - -config SND_UBI32_AUDIO_CS4350 - bool "Cirrus Logic CS4350 DAC" - depends on I2C - default n - help - Support for the Cirrus Logic CS4350 DAC. - -config SND_UBI32_AUDIO_CS4384 - bool "Cirrus Logic CS4384 DAC" - depends on I2C - default n - help - Support for the Cirrus Logic CS4384 DAC. - -endif #SND_UBI32 diff --git a/target/linux/ubicom32/files/sound/ubicom32/Makefile b/target/linux/ubicom32/files/sound/ubicom32/Makefile deleted file mode 100644 index ffdcc29..0000000 --- a/target/linux/ubicom32/files/sound/ubicom32/Makefile +++ /dev/null @@ -1,41 +0,0 @@ -# -# sound/ubicom32/Makefile -# Makefile for ALSA -# -# (C) Copyright 2009, Ubicom, Inc. -# -# This file is part of the Ubicom32 Linux Kernel Port. -# -# The Ubicom32 Linux Kernel Port 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. -# -# The Ubicom32 Linux Kernel Port 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 the Ubicom32 Linux Kernel Port. If not, -# see <http://www.gnu.org/licenses/>. -# -# Ubicom32 implementation derived from (with many thanks): -# arch/m68knommu -# arch/blackfin -# arch/parisc -# - -CFLAGS_ubi32.o += -O2 -snd-ubi32-pcm-objs := ubi32-pcm.o -snd-ubi32-generic-objs := ubi32-generic.o -snd-ubi32-generic-capture-objs := ubi32-generic-capture.o -snd-ubi32-cs4350-objs := ubi32-cs4350.o -snd-ubi32-cs4384-objs := ubi32-cs4384.o - -# Toplevel Module Dependency -obj-$(CONFIG_SND_UBI32) += snd-ubi32-pcm.o -obj-$(CONFIG_SND_UBI32_AUDIO_GENERIC) += snd-ubi32-generic.o -obj-$(CONFIG_SND_UBI32_AUDIO_GENERIC_CAPTURE) += snd-ubi32-generic-capture.o -obj-$(CONFIG_SND_UBI32_AUDIO_CS4350) += snd-ubi32-cs4350.o -obj-$(CONFIG_SND_UBI32_AUDIO_CS4384) += snd-ubi32-cs4384.o diff --git a/target/linux/ubicom32/files/sound/ubicom32/ubi32-cs4350.c b/target/linux/ubicom32/files/sound/ubicom32/ubi32-cs4350.c deleted file mode 100644 index 7e6f9ac..0000000 --- a/target/linux/ubicom32/files/sound/ubicom32/ubi32-cs4350.c +++ /dev/null @@ -1,583 +0,0 @@ -/* - * sound/ubicom32/ubi32-cs4350.c - * Interface to ubicom32 virtual audio peripheral - using CS4350 DAC - * - * (C) Copyright 2009, Ubicom, Inc. - * - * This file is part of the Ubicom32 Linux Kernel Port. - * - * The Ubicom32 Linux Kernel Port 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. - * - * The Ubicom32 Linux Kernel Port 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 the Ubicom32 Linux Kernel Port. If not, - * see <http://www.gnu.org/licenses/>. - */ - -#include <linux/i2c.h> -#include <linux/module.h> -#include <linux/moduleparam.h> -#include <sound/core.h> -#include <sound/tlv.h> -#include <sound/control.h> -#include <sound/pcm.h> -#include <sound/initval.h> -#include "ubi32.h" - -#define DRIVER_NAME "snd-ubi32-cs4350" - -/* - * Module properties - */ -static const struct i2c_device_id snd_ubi32_cs4350_id[] = { - {"cs4350", 0 }, - { } -}; -MODULE_DEVICE_TABLE(i2c, ubicom32audio_id); - -static int index = SNDRV_DEFAULT_IDX1; /* Index 0-MAX */ - -/* - * The dB scale for the Cirrus Logic cs4350. The output range is from - * -127.5 dB to 0 dB. - */ -static const DECLARE_TLV_DB_SCALE(snd_ubi32_cs4350_db, -12750, 50, 0); - -#define ubi32_cs4350_mute_info snd_ctl_boolean_stereo_info - -/* - * Private data for cs4350 chip - */ -struct ubi32_cs4350_priv { - /* - * The current volume settings - */ - uint8_t volume[2]; - - /* - * Bitmask of mutes MSB (unused, ..., unused, right_ch, left_ch) LSB - */ - uint8_t mute; - - /* - * Lock to protect this struct because callbacks are not atomic. - */ - spinlock_t lock; -}; - -/* - * The info for the cs4350. The volume currently has one channel, - * and 255 possible settings. - */ -static int ubi32_cs4350_volume_info(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_info *uinfo) -{ - uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER; - uinfo->count = 2; - uinfo->value.integer.min = 0; - uinfo->value.integer.max = 255; // 8 bits in cirrus logic cs4350 volume register - return 0; -} - -static int ubi32_cs4350_volume_get(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_value *ucontrol) -{ - struct ubi32_snd_priv *ubi32_priv = snd_kcontrol_chip(kcontrol); - struct ubi32_cs4350_priv *cs4350_priv; - unsigned long flags; - - cs4350_priv = snd_ubi32_priv_get_drv(ubi32_priv); - - spin_lock_irqsave(&cs4350_priv->lock, flags); - - ucontrol->value.integer.value[0] = cs4350_priv->volume[0]; - ucontrol->value.integer.value[1] = cs4350_priv->volume[1]; - - spin_unlock_irqrestore(&cs4350_priv->lock, flags); - - return 0; -} - -static int ubi32_cs4350_volume_put(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_value *ucontrol) -{ - struct ubi32_snd_priv *ubi32_priv = snd_kcontrol_chip(kcontrol); - struct i2c_client *client = (struct i2c_client *)ubi32_priv->client; - struct ubi32_cs4350_priv *cs4350_priv; - unsigned long flags; - int ret, changed; - char send[2]; - uint8_t volume_reg_value_left, volume_reg_value_right; - - changed = 0; - - cs4350_priv = snd_ubi32_priv_get_drv(ubi32_priv); - volume_reg_value_left = 255 - (ucontrol->value.integer.value[0] & 0xFF); - volume_reg_value_right = 255 - (ucontrol->value.integer.value[1] & 0xFF); - -#if SND_UBI32_DEBUG - snd_printk(KERN_INFO "Setting volume: writing %d,%d to CS4350 volume registers\n", volume_reg_value_left, volume_reg_value_right); -#endif - spin_lock_irqsave(&cs4350_priv->lock, flags); - - if (cs4350_priv->volume[0] != ucontrol->value.integer.value[0]) { - send[0] = 0x05; // left channel - send[1] = volume_reg_value_left; - ret = i2c_master_send(client, send, 2); - if (ret != 2) { - snd_printk(KERN_ERR "Failed to set channel A volume on CS4350\n"); - return changed; - } - cs4350_priv->volume[0] = ucontrol->value.integer.value[0]; - changed = 1; - } - - if (cs4350_priv->volume[1] != ucontrol->value.integer.value[1]) { - send[0] = 0x06; // right channel - send[1] = volume_reg_value_right; - ret = i2c_master_send(client, send, 2); - if (ret != 2) { - snd_printk(KERN_ERR "Failed to set channel B volume on CS4350\n"); - return changed; - } - cs4350_priv->volume[1] = ucontrol->value.integer.value[1]; - changed = 1; - } - - spin_unlock_irqrestore(&cs4350_priv->lock, flags); - - return changed; -} - -static struct snd_kcontrol_new ubi32_cs4350_volume __devinitdata = { - .iface = SNDRV_CTL_ELEM_IFACE_MIXER, - .access = SNDRV_CTL_ELEM_ACCESS_READWRITE | - SNDRV_CTL_ELEM_ACCESS_TLV_READ, - .name = "PCM Playback Volume", - .info = ubi32_cs4350_volume_info, - .get = ubi32_cs4350_volume_get, - .put = ubi32_cs4350_volume_put, - .tlv.p = snd_ubi32_cs4350_db, -}; - -static int ubi32_cs4350_mute_get(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_value *ucontrol) -{ - struct ubi32_snd_priv *ubi32_priv = snd_kcontrol_chip(kcontrol); - struct ubi32_cs4350_priv *cs4350_priv; - unsigned long flags; - - cs4350_priv = snd_ubi32_priv_get_drv(ubi32_priv); - - spin_lock_irqsave(&cs4350_priv->lock, flags); - - ucontrol->value.integer.value[0] = cs4350_priv->mute & 1; - ucontrol->value.integer.value[1] = (cs4350_priv->mute & (1 << 1)) ? 1 : 0; - - spin_unlock_irqrestore(&cs4350_priv->lock, flags); - - return 0; -} - -static int ubi32_cs4350_mute_put(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_value *ucontrol) -{ - struct ubi32_snd_priv *ubi32_priv = snd_kcontrol_chip(kcontrol); - struct i2c_client *client = (struct i2c_client *)ubi32_priv->client; - struct ubi32_cs4350_priv *cs4350_priv; - unsigned long flags; - int ret, changed; - char send[2]; - char recv[1]; - uint8_t mute; - - changed = 0; - - cs4350_priv = snd_ubi32_priv_get_drv(ubi32_priv); - - spin_lock_irqsave(&cs4350_priv->lock, flags); - - if ((cs4350_priv->mute & 1) != ucontrol->value.integer.value[0]) { - send[0] = 0x04; - ret = i2c_master_send(client, send, 1); - if (ret != 1) { - snd_printk(KERN_ERR "Failed to write to mute register: channel 0\n"); - return changed; - } - - ret = i2c_master_recv(client, recv, 1); - if (ret != 1) { - snd_printk(KERN_ERR "Failed to read mute register: channel 0\n"); - return changed; - } - - mute = recv[0]; - - if (ucontrol->value.integer.value[0]) { - cs4350_priv->mute |= 1; - mute &= ~(1 << 4); -#if SND_UBI32_DEBUG - snd_printk(KERN_INFO "Unmuted channel A\n"); -#endif - } else { - cs4350_priv->mute &= ~1; - mute |= (1 << 4); -#if SND_UBI32_DEBUG - snd_printk(KERN_INFO "Muted channel A\n"); -#endif - } - - send[0] = 0x04; - send[1] = mute; - ret = i2c_master_send(client, send, 2); - if (ret != 2) { - snd_printk(KERN_ERR "Failed to set channel A mute on CS4350\n"); - return changed; - } - changed = 1; - } - - if (((cs4350_priv->mute & 2) >> 1) != ucontrol->value.integer.value[1]) { - send[0] = 0x04; - ret = i2c_master_send(client, send, 1); - if (ret != 1) { - snd_printk(KERN_ERR "Failed to write to mute register: channel 1\n"); - return changed; - } - - ret = i2c_master_recv(client, recv, 1); - if (ret != 1) { - snd_printk(KERN_ERR "Failed to read mute register: channel 1\n"); - return changed; - } - - mute = recv[0]; - - if (ucontrol->value.integer.value[1]) { - cs4350_priv->mute |= (1 << 1); - mute &= ~(1 << 3); -#if SND_UBI32_DEBUG - snd_printk(KERN_INFO "Unmuted channel B\n"); -#endif - } else { - cs4350_priv->mute &= ~(1 << 1); - mute |= (1 << 3); -#if SND_UBI32_DEBUG - snd_printk(KERN_INFO "Muted channel B\n"); -#endif - } - - send[0] = 0x04; - send[1] = mute; - ret = i2c_master_send(client, send, 2); - if (ret != 2) { - snd_printk(KERN_ERR "Failed to set channel A mute on CS4350\n"); - return changed; - } - changed = 1; - } - - spin_unlock_irqrestore(&cs4350_priv->lock, flags); - - return changed; -} - -static struct snd_kcontrol_new ubi32_cs4350_mute __devinitdata = { - .iface = SNDRV_CTL_ELEM_IFACE_MIXER, - .access = SNDRV_CTL_ELEM_ACCESS_READWRITE, - .name = "PCM Playback Switch", - .info = ubi32_cs4350_mute_info, - .get = ubi32_cs4350_mute_get, - .put = ubi32_cs4350_mute_put, -}; - -/* - * snd_ubi32_cs4350_free - * Card private data free function - */ -void snd_ubi32_cs4350_free(struct snd_card *card) -{ - struct ubi32_snd_priv *ubi32_priv; - struct ubi32_cs4350_priv *cs4350_priv; - - ubi32_priv = card->private_data; - cs4350_priv = snd_ubi32_priv_get_drv(ubi32_priv); - if (cs4350_priv) { - kfree(cs4350_priv); - } -} - -/* - * snd_ubi32_cs4350_dac_init - */ -static int snd_ubi32_cs4350_dac_init(struct i2c_client *client, const struct i2c_device_id *id) -{ - int ret; - char send[2]; - char recv[8]; - - /* - * Initialize the CS4350 DAC over the I2C interface - */ - snd_printk(KERN_INFO "Initializing CS4350 DAC\n"); - - /* - * Register 0x01: device/revid - */ - send[0] = 0x01; - ret = i2c_master_send(client, send, 1); - if (ret != 1) { - snd_printk(KERN_ERR "Failed 1st attempt to write to CS4350 register 0x01\n"); - goto fail; - } - ret = i2c_master_recv(client, recv, 1); - if (ret != 1) { - snd_printk(KERN_ERR "Failed initial read of CS4350 registers\n"); - goto fail; - } - snd_printk(KERN_INFO "CS4350 DAC Device/Rev: %08x\n", recv[0]); - - /* - * Register 0x02: Mode control - * I2S DIF[2:0] = 001, no De-Emphasis, Auto speed mode - */ - send[0] = 0x02; - send[1] = 0x10; - ret = i2c_master_send(client, send, 2); - if (ret != 2) { - snd_printk(KERN_ERR "Failed to set CS4350 to I2S mode\n"); - goto fail; - } - - /* - * Register 0x05/0x06: Volume control - * Channel A volume set to 0 dB - * Channel B volume set to 0 dB - */ - send[0] = 0x05; - send[1] = 0x00; - ret = i2c_master_send(client, send, 2); - if (ret != 2) { - snd_printk(KERN_ERR "Failed to set channel A volume on CS4350\n"); - goto fail; - } - - send[0] = 0x06; - send[1] = 0x00; - ret = i2c_master_send(client, send, 2); - if (ret != 2) { - snd_printk(KERN_ERR "Failed to set channel A volume on CS4350\n"); - goto fail; - } - - /* - * Make sure the changes took place, this helps verify we are talking to - * the correct chip. - */ - send[0] = 0x81; - ret = i2c_master_send(client, send, 1); - if (ret != 1) { - snd_printk(KERN_ERR "Failed to initiate readback\n"); - goto fail; - } - - ret = i2c_master_recv(client, recv, 8); - if (ret != 8) { - snd_printk(KERN_ERR "Failed second read of CS4350 registers\n"); - goto fail; - } - - if ((recv[1] != 0x10) || (recv[4] != 0x00) || (recv[5] != 0x00)) { - snd_printk(KERN_ERR "Failed to initialize CS4350 DAC\n"); - goto fail; - } - - snd_printk(KERN_INFO "CS4350 DAC Initialized\n"); - return 0; - -fail: - return -ENODEV; -} - -/* - * snd_ubi32_cs4350_i2c_probe - */ -static int snd_ubi32_cs4350_i2c_probe(struct i2c_client *client, const struct i2c_device_id *id) -{ - struct snd_card *card; - struct ubi32_snd_priv *ubi32_priv; - struct ubi32_cs4350_priv *cs4350_priv; - int err, ret; - struct platform_device *pdev; - - pdev = client->dev.platform_data; - if (!pdev) { - return -ENODEV; - } - - /* - * Initialize the CS4350 DAC - */ - ret = snd_ubi32_cs4350_dac_init(client, id); - if (ret < 0) { - /* - * Initialization failed. Propagate the error. - */ - return ret; - } - - /* - * Create a snd_card structure - */ - card = snd_card_new(index, "Ubi32-CS4350", THIS_MODULE, sizeof(struct ubi32_snd_priv)); - if (card == NULL) { - return -ENOMEM; - } - - card->private_free = snd_ubi32_cs4350_free; /* Not sure if correct */ - ubi32_priv = card->private_data; - - /* - * CS4350 DAC has a minimum sample rate of 30khz and an - * upper limit of 216khz for it's auto-detect. - */ - ubi32_priv->min_sample_rate = 30000; - ubi32_priv->max_sample_rate = 216000; - - /* - * Initialize the snd_card's private data structure - */ - ubi32_priv->card = card; - ubi32_priv->client = client; - - /* - * Create our private data structure - */ - cs4350_priv = kzalloc(sizeof(struct ubi32_cs4350_priv), GFP_KERNEL); - if (!cs4350_priv) { - snd_card_free(card); - return -ENOMEM; - } - snd_ubi32_priv_set_drv(ubi32_priv, cs4350_priv); - spin_lock_init(&cs4350_priv->lock); - - /* - * Initial volume is set to max by probe function - */ - cs4350_priv->volume[0] = 0xFF; - cs4350_priv->volume[1] = 0xFF; - - /* - * The CS4350 starts off unmuted (bit set = not muted) - */ - cs4350_priv->mute = 3; - - /* - * Create the new PCM instance - */ - err = snd_ubi32_pcm_probe(ubi32_priv, pdev); - if (err < 0) { - snd_card_free(card); - return err; /* What is err? Need to include correct file */ - } - - strcpy(card->driver, "Ubi32-CS4350"); - strcpy(card->shortname, "Ubi32-CS4350"); - snprintf(card->longname, sizeof(card->longname), - "%s at sendirq=%d.%d recvirq=%d.%d regs=%p", - card->shortname, ubi32_priv->tx_irq, ubi32_priv->irq_idx, - ubi32_priv->rx_irq, ubi32_priv->irq_idx, ubi32_priv->adr); - - snd_card_set_dev(card, &client->dev); - - /* - * Set up the mixer components - */ - err = snd_ctl_add(card, snd_ctl_new1(&ubi32_cs4350_volume, ubi32_priv)); - if (err) { - snd_printk(KERN_WARNING "Failed to add volume mixer control\n"); - } - err = snd_ctl_add(card, snd_ctl_new1(&ubi32_cs4350_mute, ubi32_priv)); - if (err) { - snd_printk(KERN_WARNING "Failed to add mute mixer control\n"); - } - - /* - * Register the sound card - */ - if ((err = snd_card_register(card)) != 0) { - snd_printk(KERN_WARNING "snd_card_register error\n"); - } - - /* - * Store card for access from other methods - */ - i2c_set_clientdata(client, card); - - return 0; -} - -/* - * snd_ubi32_cs4350_i2c_remove - */ -static int __devexit snd_ubi32_cs4350_i2c_remove(struct i2c_client *client) -{ - struct snd_card *card; - struct ubi32_snd_priv *ubi32_priv; - - card = i2c_get_clientdata(client); - - ubi32_priv = card->private_data; - snd_ubi32_pcm_remove(ubi32_priv); - - snd_card_free(i2c_get_clientdata(client)); - i2c_set_clientdata(client, NULL); - - return 0; -} - -/* - * I2C driver description - */ -static struct i2c_driver snd_ubi32_cs4350_driver = { - .driver = { - .name = DRIVER_NAME, - .owner = THIS_MODULE, - }, - .id_table = snd_ubi32_cs4350_id, - .probe = snd_ubi32_cs4350_i2c_probe, - .remove = __devexit_p(snd_ubi32_cs4350_i2c_remove), -}; - -/* - * Driver init - */ -static int __init snd_ubi32_cs4350_init(void) -{ - return i2c_add_driver(&snd_ubi32_cs4350_driver); -} -module_init(snd_ubi32_cs4350_init); - -/* - * snd_ubi32_cs4350_exit - */ -static void __exit snd_ubi32_cs4350_exit(void) -{ - i2c_del_driver(&snd_ubi32_cs4350_driver); -} -module_exit(snd_ubi32_cs4350_exit); - -/* - * Module properties - */ -MODULE_ALIAS("i2c:" DRIVER_NAME); -MODULE_AUTHOR("Patrick Tjin"); -MODULE_DESCRIPTION("Driver for Ubicom32 audio devices CS4350"); -MODULE_LICENSE("GPL"); diff --git a/target/linux/ubicom32/files/sound/ubicom32/ubi32-cs4384.c b/target/linux/ubicom32/files/sound/ubicom32/ubi32-cs4384.c deleted file mode 100644 index 2679267..0000000 --- a/target/linux/ubicom32/files/sound/ubicom32/ubi32-cs4384.c +++ /dev/null @@ -1,996 +0,0 @@ -/* - * sound/ubicom32/ubi32-cs4384.c - * Interface to ubicom32 virtual audio peripheral - using CS4384 DAC - * - * (C) Copyright 2009, Ubicom, Inc. - * - * This file is part of the Ubicom32 Linux Kernel Port. - * - * The Ubicom32 Linux Kernel Port 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. - * - * The Ubicom32 Linux Kernel Port 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 the Ubicom32 Linux Kernel Port. If not, - * see <http://www.gnu.org/licenses/>. - */ - -#include <linux/i2c.h> -#include <linux/module.h> -#include <linux/moduleparam.h> -#include <linux/delay.h> -#include <sound/core.h> -#include <sound/tlv.h> -#include <sound/control.h> -#include <sound/pcm.h> -#include <sound/initval.h> -#include <asm/ip5000.h> -#include <asm/gpio.h> -#include <asm/audio.h> -#include <asm/ubi32-cs4384.h> -#include "ubi32.h" - -#define DRIVER_NAME "snd-ubi32-cs4384" - -/* - * Module properties - */ -static const struct i2c_device_id snd_ubi32_cs4384_id[] = { - {"cs4384", 0 }, - { } -}; -MODULE_DEVICE_TABLE(i2c, ubicom32audio_id); - -static int index = SNDRV_DEFAULT_IDX1; /* Index 0-MAX */ - -/* - * Mixer properties - */ -enum { - /* - * Be careful of changing the order of these IDs, they - * are used to index the volume array. - */ - SND_UBI32_CS4384_FRONT_ID, - SND_UBI32_CS4384_SURROUND_ID, - SND_UBI32_CS4384_CENTER_ID, - SND_UBI32_CS4384_LFE_ID, - SND_UBI32_CS4384_REAR_ID, - - /* - * This should be the last ID - */ - SND_UBI32_CS4384_LAST_ID, -}; -static const u8_t snd_ubi32_cs4384_ch_ofs[] = {0, 2, 4, 5, 6}; - -static const DECLARE_TLV_DB_SCALE(snd_ubi32_cs4384_db, -12750, 50, 0); - -#define snd_ubi32_cs4384_info_mute snd_ctl_boolean_stereo_info -#define snd_ubi32_cs4384_info_mute_mono snd_ctl_boolean_mono_info - -/* - * Mixer controls - */ -static int snd_ubi32_cs4384_info_volume(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info *uinfo); -static int snd_ubi32_cs4384_get_volume(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol); -static int snd_ubi32_cs4384_put_volume(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol); -static int snd_ubi32_cs4384_get_mute(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol); -static int snd_ubi32_cs4384_put_mute(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol); - -/* - * Make sure to update these if the structure below is changed - */ -#define SND_UBI32_MUTE_CTL_START 5 -#define SND_UBI32_MUTE_CTL_END 9 -static struct snd_kcontrol_new snd_ubi32_cs4384_controls[] __devinitdata = { - { - .iface = SNDRV_CTL_ELEM_IFACE_MIXER, - .access = SNDRV_CTL_ELEM_ACCESS_READWRITE | - SNDRV_CTL_ELEM_ACCESS_TLV_READ, - .name = "Front Playback Volume", - .info = snd_ubi32_cs4384_info_volume, - .get = snd_ubi32_cs4384_get_volume, - .put = snd_ubi32_cs4384_put_volume, - .private_value = SND_UBI32_CS4384_FRONT_ID, - .tlv = { - .p = snd_ubi32_cs4384_db, - }, - }, - { - .iface = SNDRV_CTL_ELEM_IFACE_MIXER, - .access = SNDRV_CTL_ELEM_ACCESS_READWRITE | - SNDRV_CTL_ELEM_ACCESS_TLV_READ, - .name = "Surround Playback Volume", - .info = snd_ubi32_cs4384_info_volume, - .get = snd_ubi32_cs4384_get_volume, - .put = snd_ubi32_cs4384_put_volume, - .private_value = SND_UBI32_CS4384_SURROUND_ID, - .tlv = { - .p = snd_ubi32_cs4384_db, - }, - }, - { - .iface = SNDRV_CTL_ELEM_IFACE_MIXER, - .access = SNDRV_CTL_ELEM_ACCESS_READWRITE | - SNDRV_CTL_ELEM_ACCESS_TLV_READ, - .name = "Center Playback Volume", - .info = snd_ubi32_cs4384_info_volume, - .get = snd_ubi32_cs4384_get_volume, - .put = snd_ubi32_cs4384_put_volume, - .private_value = SND_UBI32_CS4384_CENTER_ID, - .tlv = { - .p = snd_ubi32_cs4384_db, - }, - }, - { - .iface = SNDRV_CTL_ELEM_IFACE_MIXER, - .access = SNDRV_CTL_ELEM_ACCESS_READWRITE | - SNDRV_CTL_ELEM_ACCESS_TLV_READ, - .name = "LFE Playback Volume", - .info = snd_ubi32_cs4384_info_volume, - .get = snd_ubi32_cs4384_get_volume, - .put = snd_ubi32_cs4384_put_volume, - .private_value = SND_UBI32_CS4384_LFE_ID, - .tlv = { - .p = snd_ubi32_cs4384_db, - }, - }, - { - .iface = SNDRV_CTL_ELEM_IFACE_MIXER, - .access = SNDRV_CTL_ELEM_ACCESS_READWRITE | - SNDRV_CTL_ELEM_ACCESS_TLV_READ, - .name = "Rear Playback Volume", - .info = snd_ubi32_cs4384_info_volume, - .get = snd_ubi32_cs4384_get_volume, - .put = snd_ubi32_cs4384_put_volume, - .private_value = SND_UBI32_CS4384_REAR_ID, - .tlv = { - .p = snd_ubi32_cs4384_db, - }, - }, - { - .iface = SNDRV_CTL_ELEM_IFACE_MIXER, - .access = SNDRV_CTL_ELEM_ACCESS_READWRITE | - SNDRV_CTL_ELEM_ACCESS_TLV_READ, - .name = "Front Playback Switch", - .info = snd_ubi32_cs4384_info_mute, - .get = snd_ubi32_cs4384_get_mute, - .put = snd_ubi32_cs4384_put_mute, - .private_value = SND_UBI32_CS4384_FRONT_ID, - }, - { - .iface = SNDRV_CTL_ELEM_IFACE_MIXER, - .access = SNDRV_CTL_ELEM_ACCESS_READWRITE | - SNDRV_CTL_ELEM_ACCESS_TLV_READ, - .name = "Surround Playback Switch", - .info = snd_ubi32_cs4384_info_mute, - .get = snd_ubi32_cs4384_get_mute, - .put = snd_ubi32_cs4384_put_mute, - .private_value = SND_UBI32_CS4384_SURROUND_ID, - }, - { - .iface = SNDRV_CTL_ELEM_IFACE_MIXER, - .access = SNDRV_CTL_ELEM_ACCESS_READWRITE | - SNDRV_CTL_ELEM_ACCESS_TLV_READ, - .name = "Center Playback Switch", - .info = snd_ubi32_cs4384_info_mute_mono, - .get = snd_ubi32_cs4384_get_mute, - .put = snd_ubi32_cs4384_put_mute, - .private_value = SND_UBI32_CS4384_CENTER_ID, - }, - { - .iface = SNDRV_CTL_ELEM_IFACE_MIXER, - .access = SNDRV_CTL_ELEM_ACCESS_READWRITE | - SNDRV_CTL_ELEM_ACCESS_TLV_READ, - .name = "LFE Playback Switch", - .info = snd_ubi32_cs4384_info_mute_mono, - .get = snd_ubi32_cs4384_get_mute, - .put = snd_ubi32_cs4384_put_mute, - .private_value = SND_UBI32_CS4384_LFE_ID, - }, - { - .iface = SNDRV_CTL_ELEM_IFACE_MIXER, - .access = SNDRV_CTL_ELEM_ACCESS_READWRITE | - SNDRV_CTL_ELEM_ACCESS_TLV_READ, - .name = "Rear Playback Switch", - .info = snd_ubi32_cs4384_info_mute, - .get = snd_ubi32_cs4384_get_mute, - .put = snd_ubi32_cs4384_put_mute, - .private_value = SND_UBI32_CS4384_REAR_ID, - }, -}; - -/* - * Our private data - */ -struct snd_ubi32_cs4384_priv { - /* - * Array of current volumes - * (L, R, SL, SR, C, LFE, RL, RR) - */ - uint8_t volume[8]; - - /* - * Bitmask of mutes - * MSB (RR, RL, LFE, C, SR, SL, R, L) LSB - */ - uint8_t mute; - - /* - * Array of controls - */ - struct snd_kcontrol *kctls[ARRAY_SIZE(snd_ubi32_cs4384_controls)]; - - /* - * Lock to protect our card - */ - spinlock_t lock; -}; - -/* - * snd_ubi32_cs4384_info_volume - */ -static int snd_ubi32_cs4384_info_volume(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info *uinfo) -{ - unsigned int id = (unsigned int)kcontrol->private_value; - - uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER; - uinfo->count = 1; - if ((id != SND_UBI32_CS4384_LFE_ID) && - (id != SND_UBI32_CS4384_CENTER_ID)) { - uinfo->count = 2; - } - uinfo->value.integer.min = 0; - uinfo->value.integer.max = 255; - return 0; -} - -/* - * snd_ubi32_cs4384_get_volume - */ -static int snd_ubi32_cs4384_get_volume(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) -{ - struct ubi32_snd_priv *priv = snd_kcontrol_chip(kcontrol); - struct snd_ubi32_cs4384_priv *cs4384_priv; - unsigned int id = (unsigned int)kcontrol->private_value; - int ch = snd_ubi32_cs4384_ch_ofs[id]; - unsigned long flags; - - if (id >= SND_UBI32_CS4384_LAST_ID) { - return -EINVAL; - } - - cs4384_priv = snd_ubi32_priv_get_drv(priv); - - spin_lock_irqsave(&cs4384_priv->lock, flags); - - ucontrol->value.integer.value[0] = cs4384_priv->volume[ch]; - if ((id != SND_UBI32_CS4384_LFE_ID) && - (id != SND_UBI32_CS4384_CENTER_ID)) { - ch++; - ucontrol->value.integer.value[1] = cs4384_priv->volume[ch]; - } - - spin_unlock_irqrestore(&cs4384_priv->lock, flags); - - return 0; -} - -/* - * snd_ubi32_cs4384_put_volume - */ -static int snd_ubi32_cs4384_put_volume(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) -{ - struct ubi32_snd_priv *priv = snd_kcontrol_chip(kcontrol); - struct i2c_client *client = (struct i2c_client *)priv->client; - struct snd_ubi32_cs4384_priv *cs4384_priv; - unsigned int id = (unsigned int)kcontrol->private_value; - int ch = snd_ubi32_cs4384_ch_ofs[id]; - unsigned long flags; - unsigned char send[3]; - int nch; - int ret = -EINVAL; - - if (id >= SND_UBI32_CS4384_LAST_ID) { - return -EINVAL; - } - - cs4384_priv = snd_ubi32_priv_get_drv(priv); - - spin_lock_irqsave(&cs4384_priv->lock, flags); - - send[0] = 0; - switch (id) { - case SND_UBI32_CS4384_REAR_ID: - send[0] = 0x06; - - /* - * Fall through - */ - - case SND_UBI32_CS4384_SURROUND_ID: - send[0] += 0x03; - - /* - * Fall through - */ - - case SND_UBI32_CS4384_FRONT_ID: - send[0] += 0x8B; - nch = 2; - send[1] = 255 - (ucontrol->value.integer.value[0] & 0xFF); - send[2] = 255 - (ucontrol->value.integer.value[1] & 0xFF); - cs4384_priv->volume[ch++] = send[1]; - cs4384_priv->volume[ch] = send[2]; - break; - - case SND_UBI32_CS4384_LFE_ID: - send[0] = 0x81; - - /* - * Fall through - */ - - case SND_UBI32_CS4384_CENTER_ID: - send[0] += 0x11; - nch = 1; - send[1] = 255 - (ucontrol->value.integer.value[0] & 0xFF); - cs4384_priv->volume[ch] = send[1]; - break; - - default: - spin_unlock_irqrestore(&cs4384_priv->lock, flags); - goto done; - - } - - /* - * Send the volume to the chip - */ - nch++; - ret = i2c_master_send(client, send, nch); - if (ret != nch) { - snd_printk(KERN_ERR "Failed to set volume on CS4384\n"); - } - -done: - spin_unlock_irqrestore(&cs4384_priv->lock, flags); - - return ret; -} - -/* - * snd_ubi32_cs4384_get_mute - */ -static int snd_ubi32_cs4384_get_mute(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) -{ - struct ubi32_snd_priv *priv = snd_kcontrol_chip(kcontrol); - struct snd_ubi32_cs4384_priv *cs4384_priv; - unsigned int id = (unsigned int)kcontrol->private_value; - int ch = snd_ubi32_cs4384_ch_ofs[id]; - unsigned long flags; - - if (id >= SND_UBI32_CS4384_LAST_ID) { - return -EINVAL; - } - - cs4384_priv = snd_ubi32_priv_get_drv(priv); - - spin_lock_irqsave(&cs4384_priv->lock, flags); - - ucontrol->value.integer.value[0] = !(cs4384_priv->mute & (1 << ch)); - - if ((id != SND_UBI32_CS4384_LFE_ID) && - (id != SND_UBI32_CS4384_CENTER_ID)) { - ch++; - ucontrol->value.integer.value[1] = !(cs4384_priv->mute & (1 << ch)); - } - - spin_unlock_irqrestore(&cs4384_priv->lock, flags); - - return 0; -} - -/* - * snd_ubi32_cs4384_put_mute - */ -static int snd_ubi32_cs4384_put_mute(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) -{ - struct ubi32_snd_priv *priv = snd_kcontrol_chip(kcontrol); - struct i2c_client *client = (struct i2c_client *)priv->client; - struct snd_ubi32_cs4384_priv *cs4384_priv; - unsigned int id = (unsigned int)kcontrol->private_value; - int ch = snd_ubi32_cs4384_ch_ofs[id]; - unsigned long flags; - unsigned char send[2]; - int ret = -EINVAL; - - if (id >= SND_UBI32_CS4384_LAST_ID) { - return -EINVAL; - } - - cs4384_priv = snd_ubi32_priv_get_drv(priv); - - spin_lock_irqsave(&cs4384_priv->lock, flags); - - if (ucontrol->value.integer.value[0]) { - cs4384_priv->mute &= ~(1 << ch); - } else { - cs4384_priv->mute |= (1 << ch); - } - - if ((id != SND_UBI32_CS4384_LFE_ID) && (id != SND_UBI32_CS4384_CENTER_ID)) { - ch++; - if (ucontrol->value.integer.value[1]) { - cs4384_priv->mute &= ~(1 << ch); - } else { - cs4384_priv->mute |= (1 << ch); - } - } - - /* - * Update the chip's mute reigster - */ - send[0] = 0x09; - send[1] = cs4384_priv->mute; - ret = i2c_master_send(client, send, 2); - if (ret != 2) { - snd_printk(KERN_ERR "Failed to set mute on CS4384\n"); - } - - spin_unlock_irqrestore(&cs4384_priv->lock, flags); - - return ret; -} - -/* - * snd_ubi32_cs4384_mixer - * Setup the mixer controls - */ -static int __devinit snd_ubi32_cs4384_mixer(struct ubi32_snd_priv *priv) -{ - struct snd_card *card = priv->card; - struct snd_ubi32_cs4384_priv *cs4384_priv; - int i; - - cs4384_priv = snd_ubi32_priv_get_drv(priv); - for (i = 0; i < ARRAY_SIZE(snd_ubi32_cs4384_controls); i++) { - int err; - - cs4384_priv->kctls[i] = snd_ctl_new1(&snd_ubi32_cs4384_controls[i], priv); - err = snd_ctl_add(card, cs4384_priv->kctls[i]); - if (err) { - snd_printk(KERN_WARNING "Failed to add control %d\n", i); - return err; - } - } - return 0; -} - -/* - * snd_ubi32_cs4384_free - * Card private data free function - */ -void snd_ubi32_cs4384_free(struct snd_card *card) -{ - struct snd_ubi32_cs4384_priv *cs4384_priv; - struct ubi32_snd_priv *ubi32_priv; - - ubi32_priv = card->private_data; - cs4384_priv = snd_ubi32_priv_get_drv(ubi32_priv); - if (cs4384_priv) { - kfree(cs4384_priv); - } -} - -/* - * snd_ubi32_cs4384_setup_mclk - */ -static int snd_ubi32_cs4384_setup_mclk(struct ubi32_cs4384_platform_data *pdata) -{ - struct ubicom32_io_port *ioa = (struct ubicom32_io_port *)RA; - struct ubicom32_io_port *ioc = (struct ubicom32_io_port *)RC; - struct ubicom32_io_port *iod = (struct ubicom32_io_port *)RD; - struct ubicom32_io_port *ioe = (struct ubicom32_io_port *)RE; - struct ubicom32_io_port *ioh = (struct ubicom32_io_port *)RH; - unsigned int ctl0; - unsigned int ctlx; - unsigned int div; - - div = pdata->mclk_entries[0].div; - - ctl0 = (1 << 13); - ctlx = ((div - 1) << 16) | (div / 2); - - switch (pdata->mclk_src) { - case UBI32_CS4384_MCLK_PWM_0: - ioc->function |= 2; - ioc->ctl0 |= ctl0; - ioc->ctl1 = ctlx; - if (!ioa->function) { - ioa->function = 3; - } - return 0; - - case UBI32_CS4384_MCLK_PWM_1: - ioc->function |= 2; - ioc->ctl0 |= ctl0 << 16; - ioc->ctl2 = ctlx; - if (!ioe->function) { - ioe->function = 3; - } - return 0; - - case UBI32_CS4384_MCLK_PWM_2: - ioh->ctl0 |= ctl0; - ioh->ctl1 = ctlx; - if (!iod->function) { - iod->function = 3; - } - return 0; - - case UBI32_CS4384_MCLK_CLKDIV_1: - ioa->gpio_mask &= (1 << 7); - ioa->ctl1 &= ~(0x7F << 14); - ioa->ctl1 |= ((div - 1) << 14); - return 0; - - case UBI32_CS4384_MCLK_OTHER: - return 0; - } - - return 1; -} - -/* - * snd_ubi32_cs4384_set_rate - */ -static int snd_ubi32_cs4384_set_rate(struct ubi32_snd_priv *priv, int rate) -{ - struct ubi32_cs4384_platform_data *cpd = priv->pdata->priv_data; - struct ubicom32_io_port *ioa = (struct ubicom32_io_port *)RA; - struct ubicom32_io_port *ioc = (struct ubicom32_io_port *)RC; - struct ubicom32_io_port *ioh = (struct ubicom32_io_port *)RH; - unsigned int ctl; - unsigned int div = 0; - const u16_t mult[] = {64, 96, 128, 192, 256, 384, 512, 768, 1024}; - int i; - int j; - - - for (i = 0; i < sizeof(mult) / sizeof(u16_t); i++) { - for (j = 0; j < cpd->n_mclk; j++) { - if (((unsigned int)rate * (unsigned int)mult[i]) == - cpd->mclk_entries[j].rate) { - div = cpd->mclk_entries[j].div; - break; - } - } - } - - ctl = ((div - 1) << 16) | (div / 2); - - switch (cpd->mclk_src) { - case UBI32_CS4384_MCLK_PWM_0: - ioc->ctl1 = ctl; - return 0; - - case UBI32_CS4384_MCLK_PWM_1: - ioc->ctl2 = ctl; - return 0; - - case UBI32_CS4384_MCLK_PWM_2: - ioh->ctl1 = ctl; - return 0; - - case UBI32_CS4384_MCLK_CLKDIV_1: - ioa->ctl1 &= ~(0x7F << 14); - ioa->ctl1 |= ((div - 1) << 14); - return 0; - - case UBI32_CS4384_MCLK_OTHER: - return 0; - } - - return 1; -} - -/* - * snd_ubi32_cs4384_set_channels - * Mute unused channels - */ -static int snd_ubi32_cs4384_set_channels(struct ubi32_snd_priv *priv, int channels) -{ - struct i2c_client *client = (struct i2c_client *)priv->client; - struct snd_ubi32_cs4384_priv *cs4384_priv; - unsigned char send[2]; - int ret; - int i; - unsigned long flags; - - /* - * Only support 0, 2, 4, 6, 8 channels - */ - if ((channels > 8) || (channels & 1)) { - return -EINVAL; - } - - cs4384_priv = snd_ubi32_priv_get_drv(priv); - spin_lock_irqsave(&cs4384_priv->lock, flags); - - /* - * Address 09h, Mute control - */ - send[0] = 0x09; - send[1] = (unsigned char)(0xFF << channels); - - ret = i2c_master_send(client, send, 2); - - spin_unlock_irqrestore(&cs4384_priv->lock, flags); - - /* - * Notify the system that we changed the mutes - */ - cs4384_priv->mute = (unsigned char)(0xFF << channels); - - for (i = SND_UBI32_MUTE_CTL_START; i < SND_UBI32_MUTE_CTL_END; i++) { - snd_ctl_notify(priv->card, SNDRV_CTL_EVENT_MASK_VALUE, - &cs4384_priv->kctls[i]->id); - } - - if (ret != 2) { - return -ENXIO; - } - - return 0; -} - -/* - * snd_ubi32_cs4384_dac_init - */ -static int snd_ubi32_cs4384_dac_init(struct i2c_client *client, const struct i2c_device_id *id) -{ - int ret; - unsigned char send[2]; - unsigned char recv[2]; - - /* - * Initialize the CS4384 DAC over the I2C interface - */ - snd_printk(KERN_INFO "Initializing CS4384 DAC\n"); - - /* - * Register 0x01: device/revid - */ - send[0] = 0x01; - ret = i2c_master_send(client, send, 1); - if (ret != 1) { - snd_printk(KERN_ERR "Failed 1st attempt to write to CS4384 register 0x01\n"); - goto fail; - } - ret = i2c_master_recv(client, recv, 1); - if (ret != 1) { - snd_printk(KERN_ERR "Failed initial read of CS4384 registers\n"); - goto fail; - } - snd_printk(KERN_INFO "CS4384 DAC Device/Rev: %08x\n", recv[0]); - - /* - * Register 0x02: Mode Control 1 - * Control Port Enable, PCM, All DACs enabled, Power Down - */ - send[0] = 0x02; - send[1] = 0x81; - ret = i2c_master_send(client, send, 2); - if (ret != 2) { - snd_printk(KERN_ERR "Failed to set CPEN CS4384\n"); - goto fail; - } - - /* - * Register 0x08: Ramp and Mute - * RMP_UP, RMP_DN, PAMUTE, DAMUTE - */ - send[0] = 0x08; - send[1] = 0xBC; - ret = i2c_master_send(client, send, 2); - if (ret != 2) { - snd_printk(KERN_ERR "Failed to set CPEN CS4384\n"); - goto fail; - } - - /* - * Register 0x03: PCM Control - * I2S DIF[3:0] = 0001, no De-Emphasis, Auto speed mode - */ - send[0] = 0x03; - send[1] = 0x13; - ret = i2c_master_send(client, send, 2); - if (ret != 2) { - snd_printk(KERN_ERR "Failed to set CS4384 to I2S mode\n"); - goto fail; - } - - /* - * Register 0x0B/0x0C: Volume control A1/B1 - * Register 0x0E/0x0F: Volume control A2/B2 - * Register 0x11/0x12: Volume control A3/B3 - * Register 0x14/0x15: Volume control A4/B4 - */ - send[0] = 0x80 | 0x0B; - send[1] = 0x00; - send[2] = 0x00; - ret = i2c_master_send(client, send, 3); - if (ret != 3) { - snd_printk(KERN_ERR "Failed to set ch1 volume on CS4384\n"); - goto fail; - } - - send[0] = 0x80 | 0x0E; - send[1] = 0x00; - send[2] = 0x00; - ret = i2c_master_send(client, send, 3); - if (ret != 3) { - snd_printk(KERN_ERR "Failed to set ch2 volume on CS4384\n"); - goto fail; - } - - send[0] = 0x80 | 0x11; - send[1] = 0x00; - send[2] = 0x00; - ret = i2c_master_send(client, send, 3); - if (ret != 3) { - snd_printk(KERN_ERR "Failed to set ch3 volume on CS4384\n"); - goto fail; - } - - send[0] = 0x80 | 0x14; - send[1] = 0x00; - send[2] = 0x00; - ret = i2c_master_send(client, send, 3); - if (ret != 3) { - snd_printk(KERN_ERR "Failed to set ch4 volume on CS4384\n"); - goto fail; - } - - /* - * Register 09h: Mute control - * Mute all (we will unmute channels as needed) - */ - send[0] = 0x09; - send[1] = 0xFF; - ret = i2c_master_send(client, send, 2); - if (ret != 2) { - snd_printk(KERN_ERR "Failed to power up CS4384\n"); - goto fail; - } - - /* - * Register 0x02: Mode Control 1 - * Control Port Enable, PCM, All DACs enabled, Power Up - */ - send[0] = 0x02; - send[1] = 0x80; - ret = i2c_master_send(client, send, 2); - if (ret != 2) { - snd_printk(KERN_ERR "Failed to power up CS4384\n"); - goto fail; - } - - /* - * Make sure the changes took place, this helps verify we are talking to - * the correct chip. - */ - send[0] = 0x80 | 0x03; - ret = i2c_master_send(client, send, 1); - if (ret != 1) { - snd_printk(KERN_ERR "Failed to initiate readback\n"); - goto fail; - } - - ret = i2c_master_recv(client, recv, 1); - if (ret != 1) { - snd_printk(KERN_ERR "Failed second read of CS4384 registers\n"); - goto fail; - } - - if (recv[0] != 0x13) { - snd_printk(KERN_ERR "Failed to initialize CS4384 DAC\n"); - goto fail; - } - - snd_printk(KERN_INFO "CS4384 DAC Initialized\n"); - return 0; - -fail: - return -ENODEV; -} - -/* - * snd_ubi32_cs4384_i2c_probe - */ -static int snd_ubi32_cs4384_i2c_probe(struct i2c_client *client, const struct i2c_device_id *id) -{ - struct snd_card *card; - struct ubi32_snd_priv *ubi32_priv; - int err, ret; - struct platform_device *pdev; - struct ubi32_cs4384_platform_data *pdata; - struct snd_ubi32_cs4384_priv *cs4384_priv; - - /* - * pdev is audio device - */ - pdev = client->dev.platform_data; - if (!pdev) { - return -ENODEV; - } - - /* - * pdev->dev.platform_data is ubi32-pcm platform_data - */ - pdata = audio_device_priv(pdev); - if (!pdata) { - return -ENODEV; - } - - /* - * Initialize the CS4384 DAC - */ - ret = snd_ubi32_cs4384_dac_init(client, id); - if (ret < 0) { - /* - * Initialization failed. Propagate the error. - */ - return ret; - } - - if (snd_ubi32_cs4384_setup_mclk(pdata)) { - return -EINVAL; - } - - /* - * Create a snd_card structure - */ - card = snd_card_new(index, "Ubi32-CS4384", THIS_MODULE, sizeof(struct ubi32_snd_priv)); - if (card == NULL) { - return -ENOMEM; - } - - card->private_free = snd_ubi32_cs4384_free; - ubi32_priv = card->private_data; - - /* - * Initialize the snd_card's private data structure - */ - ubi32_priv->card = card; - ubi32_priv->client = client; - ubi32_priv->set_channels = snd_ubi32_cs4384_set_channels; - ubi32_priv->set_rate = snd_ubi32_cs4384_set_rate; - - /* - * CS4384 DAC has a minimum sample rate of 4khz and an - * upper limit of 216khz for it's auto-detect. - */ - ubi32_priv->min_sample_rate = 4000; - ubi32_priv->max_sample_rate = 216000; - - /* - * Create our private data (to manage volume, etc) - */ - cs4384_priv = kzalloc(sizeof(struct snd_ubi32_cs4384_priv), GFP_KERNEL); - if (!cs4384_priv) { - snd_card_free(card); - return -ENOMEM; - } - snd_ubi32_priv_set_drv(ubi32_priv, cs4384_priv); - spin_lock_init(&cs4384_priv->lock); - - /* - * We start off all muted and max volume - */ - cs4384_priv->mute = 0xFF; - memset(cs4384_priv->volume, 0xFF, 8); - - /* - * Create the new PCM instance - */ - err = snd_ubi32_pcm_probe(ubi32_priv, pdev); - if (err < 0) { - snd_card_free(card); - return err; /* What is err? Need to include correct file */ - } - - strcpy(card->driver, "Ubi32-CS4384"); - strcpy(card->shortname, "Ubi32-CS4384"); - snprintf(card->longname, sizeof(card->longname), - "%s at sendirq=%d.%d recvirq=%d.%d regs=%p", - card->shortname, ubi32_priv->tx_irq, ubi32_priv->irq_idx, - ubi32_priv->rx_irq, ubi32_priv->irq_idx, ubi32_priv->adr); - - snd_card_set_dev(card, &client->dev); - - /* - * Set up the mixer - */ - snd_ubi32_cs4384_mixer(ubi32_priv); - - /* - * Register the sound card - */ - if ((err = snd_card_register(card)) != 0) { - snd_printk(KERN_INFO "snd_card_register error\n"); - } - - /* - * Store card for access from other methods - */ - i2c_set_clientdata(client, card); - - return 0; -} - -/* - * snd_ubi32_cs4384_i2c_remove - */ -static int __devexit snd_ubi32_cs4384_i2c_remove(struct i2c_client *client) -{ - struct snd_card *card; - struct ubi32_snd_priv *ubi32_priv; - - card = i2c_get_clientdata(client); - - ubi32_priv = card->private_data; - snd_ubi32_pcm_remove(ubi32_priv); - - snd_card_free(i2c_get_clientdata(client)); - i2c_set_clientdata(client, NULL); - - return 0; -} - -/* - * I2C driver description - */ -static struct i2c_driver snd_ubi32_cs4384_driver = { - .driver = { - .name = DRIVER_NAME, - .owner = THIS_MODULE, - }, - .id_table = snd_ubi32_cs4384_id, - .probe = snd_ubi32_cs4384_i2c_probe, - .remove = __devexit_p(snd_ubi32_cs4384_i2c_remove), -}; - -/* - * Driver init - */ -static int __init snd_ubi32_cs4384_init(void) -{ - return i2c_add_driver(&snd_ubi32_cs4384_driver); -} -module_init(snd_ubi32_cs4384_init); - -/* - * snd_ubi32_cs4384_exit - */ -static void __exit snd_ubi32_cs4384_exit(void) -{ - i2c_del_driver(&snd_ubi32_cs4384_driver); -} -module_exit(snd_ubi32_cs4384_exit); - -/* - * Module properties - */ -MODULE_ALIAS("i2c:" DRIVER_NAME); -MODULE_AUTHOR("Patrick Tjin"); -MODULE_DESCRIPTION("Driver for Ubicom32 audio devices CS4384"); -MODULE_LICENSE("GPL"); diff --git a/target/linux/ubicom32/files/sound/ubicom32/ubi32-generic-capture.c b/target/linux/ubicom32/files/sound/ubicom32/ubi32-generic-capture.c deleted file mode 100644 index a911cc6..0000000 --- a/target/linux/ubicom32/files/sound/ubicom32/ubi32-generic-capture.c +++ /dev/null @@ -1,167 +0,0 @@ -/* - * sound/ubicom32/ubi32-generic-capture.c - * Interface to ubicom32 virtual audio peripheral - * - * (C) Copyright 2009, Ubicom, Inc. - * - * This file is part of the Ubicom32 Linux Kernel Port. - * - * The Ubicom32 Linux Kernel Port 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. - * - * The Ubicom32 Linux Kernel Port 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 the Ubicom32 Linux Kernel Port. If not, - * see <http://www.gnu.org/licenses/>. - * - * Ubicom32 implementation derived from (with many thanks): - * arch/m68knommu - * arch/blackfin - * arch/parisc - */ - -#include <linux/platform_device.h> -#include <linux/module.h> -#include <linux/moduleparam.h> -#include <sound/core.h> -#include <sound/pcm.h> -#include <sound/initval.h> -#include "ubi32.h" - -#define DRIVER_NAME "snd-ubi32-generic-capture" - -/* - * Module properties - */ -static int index = SNDRV_DEFAULT_IDX1; /* Index 0-MAX */ - -/* - * Card private data free function - */ -void snd_ubi32_generic_capture_free(struct snd_card *card) -{ - /* - * Free all the fields in the snd_ubi32_priv struct - */ - // Nothing to free at this time because ubi32_priv just maintains pointers -} - -/* - * Ubicom audio driver probe() method. Args change depending on whether we use - * platform_device or i2c_device. - */ -static int snd_ubi32_generic_capture_probe(struct platform_device *dev) -{ - struct snd_card *card; - struct ubi32_snd_priv *ubi32_priv; - int err; - - /* - * Create a snd_card structure - */ - card = snd_card_new(index, "Ubi32-Generic-C", THIS_MODULE, sizeof(struct ubi32_snd_priv)); - - if (card == NULL) { - return -ENOMEM; - } - - card->private_free = snd_ubi32_generic_capture_free; /* Not sure if correct */ - ubi32_priv = card->private_data; - - /* - * Initialize the snd_card's private data structure - */ - ubi32_priv->card = card; - ubi32_priv->is_capture = 1; - - /* - * Create the new PCM instance - */ - err = snd_ubi32_pcm_probe(ubi32_priv, dev); - if (err < 0) { - snd_card_free(card); - return err; - } - - strcpy(card->driver, "Ubi32-Generic-C"); - strcpy(card->shortname, "Ubi32-Generic-C"); - snprintf(card->longname, sizeof(card->longname), - "%s at sendirq=%d.%d recvirq=%d.%d regs=%p", - card->shortname, ubi32_priv->tx_irq, ubi32_priv->irq_idx, - ubi32_priv->rx_irq, ubi32_priv->irq_idx, ubi32_priv->adr); - - snd_card_set_dev(card, &dev->dev); - - /* Register the sound card */ - if ((err = snd_card_register(card)) != 0) { - snd_printk(KERN_INFO "snd_card_register error\n"); - } - - /* Store card for access from other methods */ - platform_set_drvdata(dev, card); - - return 0; -} - -/* - * Ubicom audio driver remove() method - */ -static int __devexit snd_ubi32_generic_capture_remove(struct platform_device *dev) -{ - struct snd_card *card; - struct ubi32_snd_priv *ubi32_priv; - - card = platform_get_drvdata(dev); - ubi32_priv = card->private_data; - snd_ubi32_pcm_remove(ubi32_priv); - - snd_card_free(platform_get_drvdata(dev)); - platform_set_drvdata(dev, NULL); - return 0; -} - -/* - * Platform driver definition - */ -static struct platform_driver snd_ubi32_generic_capture_driver = { - .driver = { - .name = DRIVER_NAME, - .owner = THIS_MODULE, - }, - .probe = snd_ubi32_generic_capture_probe, - .remove = __devexit_p(snd_ubi32_generic_capture_remove), -}; - -/* - * snd_ubi32_generic_capture_init - */ -static int __init snd_ubi32_generic_capture_init(void) -{ - return platform_driver_register(&snd_ubi32_generic_capture_driver); -} -module_init(snd_ubi32_generic_capture_init); - -/* - * snd_ubi32_generic_capture_exit - */ -static void __exit snd_ubi32_generic_capture_exit(void) -{ - platform_driver_unregister(&snd_ubi32_generic_capture_driver); -} -module_exit(snd_ubi32_generic_capture_exit); - -/* - * Module properties - */ -//#if defined(CONFIG_SND_UBI32_AUDIO_I2C) -//MODULE_ALIAS("i2c:snd-ubi32"); -//#endif -MODULE_AUTHOR("Patrick Tjin"); -MODULE_DESCRIPTION("Driver for Ubicom32 audio devices"); -MODULE_LICENSE("GPL"); diff --git a/target/linux/ubicom32/files/sound/ubicom32/ubi32-generic.c b/target/linux/ubicom32/files/sound/ubicom32/ubi32-generic.c deleted file mode 100644 index eee6066..0000000 --- a/target/linux/ubicom32/files/sound/ubicom32/ubi32-generic.c +++ /dev/null @@ -1,166 +0,0 @@ -/* - * sound/ubicom32/ubi32-generic.c - * Interface to ubicom32 virtual audio peripheral - * - * (C) Copyright 2009, Ubicom, Inc. - * - * This file is part of the Ubicom32 Linux Kernel Port. - * - * The Ubicom32 Linux Kernel Port 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. - * - * The Ubicom32 Linux Kernel Port 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 the Ubicom32 Linux Kernel Port. If not, - * see <http://www.gnu.org/licenses/>. - * - * Ubicom32 implementation derived from (with many thanks): - * arch/m68knommu - * arch/blackfin - * arch/parisc - */ - -#include <linux/platform_device.h> -#include <linux/module.h> -#include <linux/moduleparam.h> -#include <sound/core.h> -#include <sound/pcm.h> -#include <sound/initval.h> -#include "ubi32.h" - -#define DRIVER_NAME "snd-ubi32-generic" - -/* - * Module properties - */ -static int index = SNDRV_DEFAULT_IDX1; /* Index 0-MAX */ - -/* - * Card private data free function - */ -void snd_ubi32_generic_free(struct snd_card *card) -{ - /* - * Free all the fields in the snd_ubi32_priv struct - */ - // Nothing to free at this time because ubi32_priv just maintains pointers -} - -/* - * Ubicom audio driver probe() method. Args change depending on whether we use - * platform_device or i2c_device. - */ -static int snd_ubi32_generic_probe(struct platform_device *dev) -{ - struct snd_card *card; - struct ubi32_snd_priv *ubi32_priv; - int err; - - /* - * Create a snd_card structure - */ - card = snd_card_new(index, "Ubi32-Generic", THIS_MODULE, sizeof(struct ubi32_snd_priv)); - - if (card == NULL) { - return -ENOMEM; - } - - card->private_free = snd_ubi32_generic_free; /* Not sure if correct */ - ubi32_priv = card->private_data; - - /* - * Initialize the snd_card's private data structure - */ - ubi32_priv->card = card; - - /* - * Create the new PCM instance - */ - err = snd_ubi32_pcm_probe(ubi32_priv, dev); - if (err < 0) { - snd_card_free(card); - return err; - } - - strcpy(card->driver, "Ubi32-Generic"); - strcpy(card->shortname, "Ubi32-Generic"); - snprintf(card->longname, sizeof(card->longname), - "%s at sendirq=%d.%d recvirq=%d.%d regs=%p", - card->shortname, ubi32_priv->tx_irq, ubi32_priv->irq_idx, - ubi32_priv->rx_irq, ubi32_priv->irq_idx, ubi32_priv->adr); - - snd_card_set_dev(card, &dev->dev); - - /* Register the sound card */ - if ((err = snd_card_register(card)) != 0) { - snd_printk(KERN_INFO "snd_card_register error\n"); - } - - /* Store card for access from other methods */ - platform_set_drvdata(dev, card); - - return 0; -} - -/* - * Ubicom audio driver remove() method - */ -static int __devexit snd_ubi32_generic_remove(struct platform_device *dev) -{ - struct snd_card *card; - struct ubi32_snd_priv *ubi32_priv; - - card = platform_get_drvdata(dev); - ubi32_priv = card->private_data; - snd_ubi32_pcm_remove(ubi32_priv); - - snd_card_free(platform_get_drvdata(dev)); - platform_set_drvdata(dev, NULL); - return 0; -} - -/* - * Platform driver definition - */ -static struct platform_driver snd_ubi32_generic_driver = { - .driver = { - .name = DRIVER_NAME, - .owner = THIS_MODULE, - }, - .probe = snd_ubi32_generic_probe, - .remove = __devexit_p(snd_ubi32_generic_remove), -}; - -/* - * snd_ubi32_generic_init - */ -static int __init snd_ubi32_generic_init(void) -{ - return platform_driver_register(&snd_ubi32_generic_driver); -} -module_init(snd_ubi32_generic_init); - -/* - * snd_ubi32_generic_exit - */ -static void __exit snd_ubi32_generic_exit(void) -{ - platform_driver_unregister(&snd_ubi32_generic_driver); -} -module_exit(snd_ubi32_generic_exit); - -/* - * Module properties - */ -//#if defined(CONFIG_SND_UBI32_AUDIO_I2C) -//MODULE_ALIAS("i2c:snd-ubi32"); -//#endif -MODULE_AUTHOR("Aaron Jow, Patrick Tjin"); -MODULE_DESCRIPTION("Driver for Ubicom32 audio devices"); -MODULE_LICENSE("GPL"); diff --git a/target/linux/ubicom32/files/sound/ubicom32/ubi32-pcm.c b/target/linux/ubicom32/files/sound/ubicom32/ubi32-pcm.c deleted file mode 100644 index 2bc300b..0000000 --- a/target/linux/ubicom32/files/sound/ubicom32/ubi32-pcm.c +++ /dev/null @@ -1,711 +0,0 @@ -/* - * sound/ubicom32/ubi32-pcm.c - * Interface to ubicom32 virtual audio peripheral - * - * (C) Copyright 2009, Ubicom, Inc. - * - * This file is part of the Ubicom32 Linux Kernel Port. - * - * The Ubicom32 Linux Kernel Port 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. - * - * The Ubicom32 Linux Kernel Port 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 the Ubicom32 Linux Kernel Port. If not, - * see <http://www.gnu.org/licenses/>. - * - * Ubicom32 implementation derived from (with many thanks): - * arch/m68knommu - * arch/blackfin - * arch/parisc - */ - -#include <linux/interrupt.h> -#include <sound/core.h> -#include <sound/pcm.h> -#include <sound/pcm_params.h> -#include <asm/ip5000.h> -#include <asm/ubi32-pcm.h> -#include <linux/dma-mapping.h> -#include <linux/delay.h> -#include "ubi32.h" - -struct ubi32_snd_runtime_data { - dma_addr_t dma_buffer; /* Physical address of DMA buffer */ - dma_addr_t dma_buffer_end; /* First address beyond end of DMA buffer */ - size_t period_size; - dma_addr_t period_ptr; /* Physical address of next period */ - unsigned int flags; -}; - -static void snd_ubi32_vp_int_set(struct snd_pcm *pcm) -{ - struct ubi32_snd_priv *ubi32_priv = pcm->private_data; - ubi32_priv->ar->int_req |= (1 << ubi32_priv->irq_idx); - ubicom32_set_interrupt(ubi32_priv->tx_irq); -} - -static snd_pcm_uframes_t snd_ubi32_pcm_pointer(struct snd_pcm_substream *substream) -{ - - struct ubi32_snd_priv *ubi32_priv = snd_pcm_substream_chip(substream); - struct audio_dev_regs *adr = ubi32_priv->adr; - struct snd_pcm_runtime *runtime = substream->runtime; - struct ubi32_snd_runtime_data *ubi32_rd = substream->runtime->private_data; - - dma_addr_t read_pos; - - snd_pcm_uframes_t frames; - if (!adr->primary_os_buffer_ptr) { - /* - * If primary_os_buffer_ptr is NULL (e.g. right after the HW is started or - * when the HW is stopped), then handle this case separately. - */ - return 0; - } - - read_pos = (dma_addr_t)adr->primary_os_buffer_ptr; - frames = bytes_to_frames(runtime, read_pos - ubi32_rd->dma_buffer); - if (frames == runtime->buffer_size) { - frames = 0; - } - return frames; -} - -/* - * Audio trigger - */ -static int snd_ubi32_pcm_trigger(struct snd_pcm_substream *substream, int cmd) -{ - struct ubi32_snd_priv *ubi32_priv = substream->pcm->private_data; - struct audio_dev_regs *adr = ubi32_priv->adr; - struct ubi32_snd_runtime_data *ubi32_rd = substream->runtime->private_data; - int ret = 0; - -#ifdef CONFIG_SND_DEBUG - snd_printk(KERN_INFO "snd_ubi32_pcm_trigger cmd=%d=", cmd); -#endif - - if (adr->command != AUDIO_CMD_NONE) { - snd_printk(KERN_WARNING "Can't send command to audio device at this time\n"); - // Set a timer to call this function back later. How to do this? - return 0; - } - - /* - * Set interrupt flag to indicate that we interrupted audio device - * to send a command - */ - - switch (cmd) { - case SNDRV_PCM_TRIGGER_START: - -#ifdef CONFIG_SND_DEBUG - snd_printk(KERN_INFO "START\n"); -#endif - /* - * Ready the DMA transfer - */ - ubi32_rd->period_ptr = ubi32_rd->dma_buffer; - -#ifdef CONFIG_SND_DEBUG - snd_printk(KERN_INFO "trigger period_ptr=%lx\n", (unsigned long)ubi32_rd->period_ptr); -#endif - adr->dma_xfer_requests[0].ptr = (void *)ubi32_rd->period_ptr; - adr->dma_xfer_requests[0].ctr = ubi32_rd->period_size; - adr->dma_xfer_requests[0].active = 1; - -#ifdef CONFIG_SND_DEBUG - snd_printk(KERN_INFO "xfer_request 0 ptr=0x%x ctr=%u\n", ubi32_rd->period_ptr, ubi32_rd->period_size); -#endif - - ubi32_rd->period_ptr += ubi32_rd->period_size; - adr->dma_xfer_requests[1].ptr = (void *)ubi32_rd->period_ptr; - adr->dma_xfer_requests[1].ctr = ubi32_rd->period_size; - adr->dma_xfer_requests[1].active = 1; - -#ifdef CONFIG_SND_DEBUG - snd_printk(KERN_INFO "xfer_request 1 ptr=0x%x ctr=%u\n", ubi32_rd->period_ptr, ubi32_rd->period_size); -#endif - - /* - * Tell the VP that we want to begin playback by filling in the - * command field and then interrupting the audio VP - */ - adr->int_flags |= AUDIO_INT_FLAG_COMMAND; - adr->command = AUDIO_CMD_START; - snd_ubi32_vp_int_set(substream->pcm); - break; - - case SNDRV_PCM_TRIGGER_STOP: - -#ifdef CONFIG_SND_DEBUG - snd_printk(KERN_INFO "STOP\n"); -#endif - - /* - * Tell the VP that we want to stop playback by filling in the - * command field and then interrupting the audio VP - */ - adr->int_flags |= AUDIO_INT_FLAG_COMMAND; - adr->command = AUDIO_CMD_STOP; - snd_ubi32_vp_int_set(substream->pcm); - break; - - case SNDRV_PCM_TRIGGER_PAUSE_PUSH: - -#ifdef CONFIG_SND_DEBUG - snd_printk(KERN_INFO "PAUSE_PUSH\n"); -#endif - - /* - * Tell the VP that we want to pause playback by filling in the - * command field and then interrupting the audio VP - */ - adr->int_flags |= AUDIO_INT_FLAG_COMMAND; - adr->command = AUDIO_CMD_PAUSE; - snd_ubi32_vp_int_set(substream->pcm); - break; - - case SNDRV_PCM_TRIGGER_PAUSE_RELEASE: - -#ifdef CONFIG_SND_DEBUG - snd_printk(KERN_INFO "PAUSE_RELEASE\n"); -#endif - /* - * Tell the VP that we want to resume paused playback by filling - * in the command field and then interrupting the audio VP - */ - adr->int_flags |= AUDIO_INT_FLAG_COMMAND; - adr->command = AUDIO_CMD_RESUME; - snd_ubi32_vp_int_set(substream->pcm); - break; - - default: - snd_printk(KERN_WARNING "Unhandled trigger\n"); - ret = -EINVAL; - break; - } - - return ret; -} - -/* - * Prepare to transfer an audio stream to the codec - */ -static int snd_ubi32_pcm_prepare(struct snd_pcm_substream *substream) -{ - /* - * Configure registers and setup the runtime instance for DMA transfers - */ - struct ubi32_snd_priv *ubi32_priv = substream->pcm->private_data; - struct audio_dev_regs *adr = ubi32_priv->adr; - -#ifdef CONFIG_SND_DEBUG - snd_printk(KERN_INFO "snd_ubi32_pcm_prepare: sending STOP command to audio device\n"); -#endif - - /* - * Make sure the audio device is stopped - */ - - /* - * Set interrupt flag to indicate that we interrupted audio device - * to send a command - */ - adr->int_flags |= AUDIO_INT_FLAG_COMMAND; - adr->command = AUDIO_CMD_STOP; - snd_ubi32_vp_int_set(substream->pcm); - - return 0; -} - -/* - * Allocate DMA buffers from preallocated memory. - * Preallocation was done in snd_ubi32_pcm_new() - */ -static int snd_ubi32_pcm_hw_params(struct snd_pcm_substream *substream, - struct snd_pcm_hw_params *hw_params) -{ - struct snd_pcm_runtime *runtime = substream->runtime; - struct ubi32_snd_priv *ubi32_priv = substream->pcm->private_data; - struct audio_dev_regs *adr = ubi32_priv->adr; - struct ubi32_snd_runtime_data *ubi32_rd = substream->runtime->private_data; - - /* - * Use pre-allocated memory from ubi32_snd_pcm_new() to satisfy - * this memory request. - */ - int ret = snd_pcm_lib_malloc_pages(substream, params_buffer_bytes(hw_params)); - if (ret < 0) { - return ret; - } - -#ifdef CONFIG_SND_DEBUG - snd_printk(KERN_INFO "snd_ubi32_pcm_hw_params\n"); -#endif - - if (!(adr->channel_mask & (1 << params_channels(hw_params)))) { - snd_printk(KERN_INFO "snd_ubi32_pcm_hw_params unsupported number of channels %d mask %08x\n", params_channels(hw_params), adr->channel_mask); - return -EINVAL; - } - - if (ubi32_priv->set_channels) { - int ret = ubi32_priv->set_channels(ubi32_priv, params_channels(hw_params)); - if (ret) { - snd_printk(KERN_WARNING "Unable to set channels to %d, ret=%d\n", params_channels(hw_params), ret); - return ret; - } - } - - if (ubi32_priv->set_rate) { - int ret = ubi32_priv->set_rate(ubi32_priv, params_rate(hw_params)); - if (ret) { - snd_printk(KERN_WARNING "Unable to set rate to %d, ret=%d\n", params_rate(hw_params), ret); - return ret; - } - } - - if (ubi32_priv->pdata->set_rate) { - int ret = ubi32_priv->pdata->set_rate(ubi32_priv->pdata->appdata, params_rate(hw_params)); - if (ret) { - snd_printk(KERN_WARNING "Unable to set rate to %d, ret=%d\n", params_rate(hw_params), ret); - return ret; - } - } - - if (adr->command != AUDIO_CMD_NONE) { - snd_printk(KERN_WARNING "snd_ubi32_pcm_hw_params: tio busy\n"); - return -EAGAIN; - } - - if (params_format(hw_params) == SNDRV_PCM_FORMAT_S16_LE) { - adr->flags |= CMD_START_FLAG_LE; - } else { - adr->flags &= ~CMD_START_FLAG_LE; - } - adr->channels = params_channels(hw_params); - adr->sample_rate = params_rate(hw_params); - adr->command = AUDIO_CMD_SETUP; - adr->int_flags |= AUDIO_INT_FLAG_COMMAND; - snd_ubi32_vp_int_set(substream->pcm); - - /* - * Wait for the command to complete - */ - while (adr->command != AUDIO_CMD_NONE) { - udelay(1); - } - - /* - * Put the DMA info into the DMA descriptor that we will - * use to do transfers to our audio VP "hardware" - */ - - /* - * Mark both DMA transfers as not ready/inactive - */ - adr->dma_xfer_requests[0].active = 0; - adr->dma_xfer_requests[1].active = 0; - - /* - * Put the location of the buffer into the runtime data instance - */ - ubi32_rd->dma_buffer = (dma_addr_t)runtime->dma_area; - ubi32_rd->dma_buffer_end = (dma_addr_t)(runtime->dma_area + runtime->dma_bytes); - - /* - * Get the period size - */ - ubi32_rd->period_size = params_period_bytes(hw_params); - -#ifdef CONFIG_SND_DEBUG - snd_printk(KERN_INFO "DMA for ubi32 audio initialized dma_area=0x%x dma_bytes=%d, period_size=%d\n", (unsigned int)runtime->dma_area, (unsigned int)runtime->dma_bytes, ubi32_rd->period_size); - snd_printk(KERN_INFO "Private buffer ubi32_rd: dma_buffer=0x%x dma_buffer_end=0x%x ret=%d\n", ubi32_rd->dma_buffer, ubi32_rd->dma_buffer_end, ret); -#endif - - return ret; -} - -/* - * This is the reverse of snd_ubi32_pcm_hw_params - */ -static int snd_ubi32_pcm_hw_free(struct snd_pcm_substream *substream) -{ -#ifdef CONFIG_SND_DEBUG - snd_printk(KERN_INFO "snd_ubi32_pcm_hw_free\n"); -#endif - return snd_pcm_lib_free_pages(substream); -} - -/* - * Audio virtual peripheral capabilities (capture and playback are identical) - */ -static struct snd_pcm_hardware snd_ubi32_pcm_hw = -{ - .info = (SNDRV_PCM_INFO_INTERLEAVED | SNDRV_PCM_INFO_BLOCK_TRANSFER | - SNDRV_PCM_INFO_PAUSE | SNDRV_PCM_INFO_RESUME), - .buffer_bytes_max = (64*1024), - .period_bytes_min = 64, - .period_bytes_max = 8184,//8184,//8176, - .periods_min = 2, - .periods_max = 255, - .fifo_size = 0, // THIS IS IGNORED BY ALSA -}; - -/* - * We fill this in later - */ -static struct snd_pcm_hw_constraint_list ubi32_pcm_rates; - -/* - * snd_ubi32_pcm_close - */ -static int snd_ubi32_pcm_close(struct snd_pcm_substream *substream) -{ - /* Disable codec, stop DMA, free private data structures */ - //struct ubi32_snd_priv *ubi32_priv = snd_pcm_substream_chip(substream); - struct ubi32_snd_runtime_data *ubi32_rd = substream->runtime->private_data; - -#ifdef CONFIG_SND_DEBUG - snd_printk(KERN_INFO "snd_ubi32_pcm_close\n"); -#endif - - substream->runtime->private_data = NULL; - - kfree(ubi32_rd); - - return 0; -} - -/* - * snd_ubi32_pcm_open - */ -static int snd_ubi32_pcm_open(struct snd_pcm_substream *substream) -{ - struct snd_pcm_runtime *runtime = substream->runtime; - struct ubi32_snd_runtime_data *ubi32_rd; - int ret = 0; - -#ifdef CONFIG_SND_DEBUG - snd_printk(KERN_INFO "ubi32 pcm open\n"); -#endif - - /* Associate capabilities with component */ - runtime->hw = snd_ubi32_pcm_hw; - - /* - * Inform ALSA about constraints of the audio device - */ - ret = snd_pcm_hw_constraint_list(runtime, 0, SNDRV_PCM_HW_PARAM_RATE, &ubi32_pcm_rates); - if (ret < 0) { - snd_printk(KERN_INFO "invalid rate\n"); - goto out; - } - - /* Force the buffer size to be an integer multiple of period size */ - ret = snd_pcm_hw_constraint_integer(runtime, SNDRV_PCM_HW_PARAM_PERIODS); - if (ret < 0) { - snd_printk(KERN_INFO "invalid period\n"); - goto out; - } - /* Initialize structures/registers */ - ubi32_rd = kzalloc(sizeof(struct ubi32_snd_runtime_data), GFP_KERNEL); - if (ubi32_rd == NULL) { - ret = -ENOMEM; - goto out; - } - - runtime->private_data = ubi32_rd; - -#ifdef CONFIG_SND_DEBUG - snd_printk(KERN_INFO "snd_ubi32_pcm_open returned 0\n"); -#endif - - return 0; -out: -#ifdef CONFIG_SND_DEBUG - snd_printk(KERN_INFO "snd_ubi32_pcm_open returned %d\n", ret); -#endif - - return ret; -} - -static struct snd_pcm_ops snd_ubi32_pcm_ops = { - .open = snd_ubi32_pcm_open, /* Open */ - .close = snd_ubi32_pcm_close, /* Close */ - .ioctl = snd_pcm_lib_ioctl, /* Generic IOCTL handler */ - .hw_params = snd_ubi32_pcm_hw_params, /* Hardware parameters/capabilities */ - .hw_free = snd_ubi32_pcm_hw_free, /* Free function for hw_params */ - .prepare = snd_ubi32_pcm_prepare, - .trigger = snd_ubi32_pcm_trigger, - .pointer = snd_ubi32_pcm_pointer, -}; - -/* - * Interrupt handler that gets called when the audio device - * interrupts Linux - */ -static irqreturn_t snd_ubi32_pcm_interrupt(int irq, void *appdata) -{ - struct snd_pcm *pcm = (struct snd_pcm *)appdata; - struct ubi32_snd_priv *ubi32_priv = pcm->private_data; - struct audio_dev_regs *adr = ubi32_priv->adr; - struct snd_pcm_substream *substream; - struct ubi32_snd_runtime_data *ubi32_rd; - int dma_to_fill = 0; - - /* - * Check to see if the interrupt is for us - */ - if (!(ubi32_priv->ar->int_status & (1 << ubi32_priv->irq_idx))) { - return IRQ_NONE; - } - - /* - * Clear the interrupt - */ - ubi32_priv->ar->int_status &= ~(1 << ubi32_priv->irq_idx); - - /* - * We only have one stream since we don't mix. Therefore - * we don't need to search through substreams. - */ - if (ubi32_priv->is_capture) { - substream = pcm->streams[SNDRV_PCM_STREAM_CAPTURE].substream; - } else { - substream = pcm->streams[SNDRV_PCM_STREAM_PLAYBACK].substream; - } - - if (!substream->runtime) { - snd_printk(KERN_WARNING "No runtime data\n"); - return IRQ_NONE; - } - - ubi32_rd = substream->runtime->private_data; - -#ifdef CONFIG_SND_DEBUG - snd_printk(KERN_INFO "Ubi32 ALSA interrupt\n"); -#endif - - if (ubi32_rd == NULL) { - snd_printk(KERN_WARNING "No private data\n"); - return IRQ_NONE; - } - - // Check interrupt cause - if (0) { - // Handle the underflow case - } else if ((adr->status & AUDIO_STATUS_PLAY_DMA0_REQUEST) || - (adr->status & AUDIO_STATUS_PLAY_DMA1_REQUEST)) { - if (adr->status & AUDIO_STATUS_PLAY_DMA0_REQUEST) { - dma_to_fill = 0; - adr->status &= ~AUDIO_STATUS_PLAY_DMA0_REQUEST; - } else if (adr->status & AUDIO_STATUS_PLAY_DMA1_REQUEST) { - dma_to_fill = 1; - adr->status &= ~AUDIO_STATUS_PLAY_DMA1_REQUEST; - } - ubi32_rd->period_ptr += ubi32_rd->period_size; - if (ubi32_rd->period_ptr >= ubi32_rd->dma_buffer_end) { - ubi32_rd->period_ptr = ubi32_rd->dma_buffer; - } - adr->dma_xfer_requests[dma_to_fill].ptr = (void *)ubi32_rd->period_ptr; - adr->dma_xfer_requests[dma_to_fill].ctr = ubi32_rd->period_size; - adr->dma_xfer_requests[dma_to_fill].active = 1; -#ifdef CONFIG_SND_DEBUG - snd_printk(KERN_INFO "xfer_request %d ptr=0x%x ctr=%u\n", dma_to_fill, ubi32_rd->period_ptr, ubi32_rd->period_size); -#endif - adr->int_flags |= AUDIO_INT_FLAG_MORE_SAMPLES; - snd_ubi32_vp_int_set(substream->pcm); - } - // If we are interrupted by the VP, that means we completed - // processing one period of audio. We need to inform the upper - // layers of ALSA of this. - snd_pcm_period_elapsed(substream); - - return IRQ_HANDLED; -} - -void __devexit snd_ubi32_pcm_remove(struct ubi32_snd_priv *ubi32_priv) -{ - struct snd_pcm *pcm = ubi32_priv->pcm; - free_irq(ubi32_priv->rx_irq, pcm); -} - -#if SNDRV_PCM_RATE_5512 != 1 << 0 || SNDRV_PCM_RATE_192000 != 1 << 12 -#error "Change this table to match pcm.h" -#endif -static unsigned int rates[] __initdata = {5512, 8000, 11025, 16000, 22050, - 32000, 44100, 48000, 64000, 88200, - 96000, 176400, 192000}; - -/* - * snd_ubi32_pcm_probe - */ -int __devinit snd_ubi32_pcm_probe(struct ubi32_snd_priv *ubi32_priv, struct platform_device *pdev) -{ - struct snd_pcm *pcm; - int ret, err; - int i; - int j; - int nrates; - unsigned int rate_max = 0; - unsigned int rate_min = 0xFFFFFFFF; - unsigned int rate_mask = 0; - struct audio_dev_regs *adr; - struct resource *res_adr; - struct resource *res_irq_tx; - struct resource *res_irq_rx; - struct ubi32pcm_platform_data *pdata; - - pdata = pdev->dev.platform_data; - if (!pdata) { - return -ENODEV; - } - - /* - * Get our resources, adr is the hardware driver base address - * and the tx and rx irqs are used to communicate with the - * hardware driver. - */ - res_adr = platform_get_resource(pdev, IORESOURCE_MEM, AUDIO_MEM_RESOURCE); - res_irq_tx = platform_get_resource(pdev, IORESOURCE_IRQ, AUDIO_TX_IRQ_RESOURCE); - res_irq_rx = platform_get_resource(pdev, IORESOURCE_IRQ, AUDIO_RX_IRQ_RESOURCE); - if (!res_adr || !res_irq_tx || !res_irq_rx) { - snd_printk(KERN_WARNING "Could not get resources"); - return -ENODEV; - } - - ubi32_priv->ar = (struct audio_regs *)res_adr->start; - ubi32_priv->tx_irq = res_irq_tx->start; - ubi32_priv->rx_irq = res_irq_rx->start; - ubi32_priv->irq_idx = pdata->inst_num; - ubi32_priv->adr = &(ubi32_priv->ar->adr[pdata->inst_num]); - - /* - * Check the version - */ - adr = ubi32_priv->adr; - if (adr->version != AUDIO_DEV_REGS_VERSION) { - snd_printk(KERN_WARNING "This audio_dev_reg is not compatible with this driver\n"); - return -ENODEV; - } - - /* - * Find out the standard rates, also find max and min rates - */ - for (i = 0; i < ARRAY_SIZE(rates); i++) { - int found = 0; - for (j = 0; j < adr->n_sample_rates; j++) { - if (rates[i] == adr->sample_rates[j]) { - /* - * Check to see if it is supported by the dac - */ - if ((rates[i] >= ubi32_priv->min_sample_rate) && - (!ubi32_priv->max_sample_rate || - (ubi32_priv->max_sample_rate && (rates[i] <= ubi32_priv->max_sample_rate)))) { - found = 1; - rate_mask |= (1 << i); - nrates++; - if (rates[i] < rate_min) { - rate_min = rates[i]; - } - if (rates[i] > rate_max) { - rate_max = rates[i]; - } - break; - } - } - } - if (!found) { - rate_mask |= SNDRV_PCM_RATE_KNOT; - } - } - - snd_ubi32_pcm_hw.rates = rate_mask; - snd_ubi32_pcm_hw.rate_min = rate_min; - snd_ubi32_pcm_hw.rate_max = rate_max; - ubi32_pcm_rates.count = adr->n_sample_rates; - ubi32_pcm_rates.list = (unsigned int *)adr->sample_rates; - ubi32_pcm_rates.mask = 0; - - for (i = 0; i < 32; i++) { - if (adr->channel_mask & (1 << i)) { - if (!snd_ubi32_pcm_hw.channels_min) { - snd_ubi32_pcm_hw.channels_min = i; - } - snd_ubi32_pcm_hw.channels_max = i; - } - } - snd_printk(KERN_INFO "Ubi32PCM: channels_min:%u channels_max:%u\n", - snd_ubi32_pcm_hw.channels_min, - snd_ubi32_pcm_hw.channels_max); - - if (adr->caps & AUDIONODE_CAP_BE) { - snd_ubi32_pcm_hw.formats |= SNDRV_PCM_FMTBIT_S16_BE; - } - if (adr->caps & AUDIONODE_CAP_LE) { - snd_ubi32_pcm_hw.formats |= SNDRV_PCM_FMTBIT_S16_LE; - } - - snd_printk(KERN_INFO "Ubi32PCM: rates:%08x min:%u max:%u count:%d fmts:%016llx (%s)\n", - snd_ubi32_pcm_hw.rates, - snd_ubi32_pcm_hw.rate_min, - snd_ubi32_pcm_hw.rate_max, - ubi32_pcm_rates.count, - snd_ubi32_pcm_hw.formats, - ubi32_priv->is_capture ? "capture" : "playback"); - - if (ubi32_priv->is_capture) { - ret = snd_pcm_new(ubi32_priv->card, "Ubi32 PCM", 0, 0, 1, &pcm); - } else { - ret = snd_pcm_new(ubi32_priv->card, "Ubi32 PCM", 0, 1, 0, &pcm); - } - - if (ret < 0) { - return ret; - } - - pcm->private_data = ubi32_priv; - ubi32_priv->pcm = pcm; - ubi32_priv->pdata = pdata; - - pcm->info_flags = 0; - - strcpy(pcm->name, "Ubi32-PCM"); - - snd_pcm_lib_preallocate_pages_for_all(pcm, SNDRV_DMA_TYPE_CONTINUOUS, - snd_dma_continuous_data(GFP_KERNEL), - 45*1024, 64*1024); - - if (ubi32_priv->is_capture) { - snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_CAPTURE, &snd_ubi32_pcm_ops); - } else { - snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_PLAYBACK, &snd_ubi32_pcm_ops); - } - - /* - * Start up the audio device - */ - adr->int_flags |= AUDIO_INT_FLAG_COMMAND; - adr->command = AUDIO_CMD_ENABLE; - snd_ubi32_vp_int_set(pcm); - - /* - * Request IRQ - */ - err = request_irq(ubi32_priv->rx_irq, snd_ubi32_pcm_interrupt, IRQF_SHARED | IRQF_DISABLED, pcm->name, pcm); - if (err) { - snd_printk(KERN_WARNING "request_irq failed: irq=%d err=%d\n", ubi32_priv->rx_irq, err); - return -ENODEV; - } - - return ret; - -} diff --git a/target/linux/ubicom32/files/sound/ubicom32/ubi32.h b/target/linux/ubicom32/files/sound/ubicom32/ubi32.h deleted file mode 100644 index f43a215..0000000 --- a/target/linux/ubicom32/files/sound/ubicom32/ubi32.h +++ /dev/null @@ -1,102 +0,0 @@ -/* - * sound/ubicom32/ubi32.h - * Common header file for all ubi32- sound drivers - * - * (C) Copyright 2009, Ubicom, Inc. - * - * This file is part of the Ubicom32 Linux Kernel Port. - * - * The Ubicom32 Linux Kernel Port 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. - * - * The Ubicom32 Linux Kernel Port 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 the Ubicom32 Linux Kernel Port. If not, - * see <http://www.gnu.org/licenses/>. - */ - -#ifndef _UBI32_H -#define _UBI32_H - -#define SND_UBI32_DEBUG 0 // Debug flag - -#include <linux/platform_device.h> -#include <asm/devtree.h> -#include <asm/audio.h> -#include <asm/ubi32-pcm.h> - -struct ubi32_snd_priv; - -typedef int (*set_channels_t)(struct ubi32_snd_priv *priv, int channels); -typedef int (*set_rate_t)(struct ubi32_snd_priv *priv, int rate); - -struct ubi32_snd_priv { - /* - * Any variables that are needed locally here but NOT in - * the VP itself should go in here. - */ - struct snd_card *card; - struct snd_pcm *pcm; - - /* - * capture (1) or playback (0) - */ - int is_capture; - /* - * DAC parameters. These are the parameters for the specific - * DAC we are driving. The I2S component can run at a range - * of frequencies, but the DAC may be limited. We may want - * to make this an array of some sort in the future? - * - * min/max_sample_rate if set to 0 are ignored. - */ - int max_sample_rate; - int min_sample_rate; - - /* - * The size a period (group) of audio samples. The VP does - * not need to know this; each DMA transfer is made to be - * one period. - */ - u32_t period_size; - - spinlock_t ubi32_lock; - - struct audio_regs *ar; - struct audio_dev_regs *adr; - u32 irq_idx; - u8 tx_irq; - u8 rx_irq; - - void *client; - - /* - * Operations which the base DAC driver can implement - */ - set_channels_t set_channels; - set_rate_t set_rate; - - /* - * platform data - */ - struct ubi32pcm_platform_data *pdata; - - /* - * Private driver data (used for DAC driver control, etc) - */ - void *drvdata; -}; - -#define snd_ubi32_priv_get_drv(priv) ((priv)->drvdata) -#define snd_ubi32_priv_set_drv(priv, data) (((priv)->drvdata) = (void *)(data)) - -extern int snd_ubi32_pcm_probe(struct ubi32_snd_priv *ubi32_priv, struct platform_device *pdev); -extern void snd_ubi32_pcm_remove(struct ubi32_snd_priv *ubi32_priv); - -#endif |