Subject: [E3-hacking] [PATCH] sound support

From: Mark Underwood <[email-masked]>
Date: Thu, 27 Apr 2006 23:02:17 +0100 (BST)

Here (at last!) the Voice Modem sound patch. The driver is an ALSA driver and it along with OSS
emulation and a few other things will need to be enable if you want any sound. I have tested it
with rawrec/rawplay and mpg321 which can't seem to decode the MP3 quick enough (tested with a
192KB MP3).

Mark

___________________________________________________________ 
24 FIFA World Cup tickets to be won with Yahoo! Mail http://uk.mail.yahoo.com

diff -uprN linux-2.6.16/arch/arm/mach-omap1/board-ams-delta.c linux-2.6.16-sound/arch/arm/mach-omap1/board-ams-delta.c
--- linux-2.6.16/arch/arm/mach-omap1/board-ams-delta.c	2006-04-27 21:27:48.000000000 +0000
+++ linux-2.6.16-sound/arch/arm/mach-omap1/board-ams-delta.c	2006-04-27 21:39:30.000000000 +0000
@@ -32,6 +32,8 @@
 #include <asm/arch/usb.h>
 #include <asm/arch/board.h>
 #include <asm/arch/common.h>
+#include <asm/arch/mcbsp.h>
+#include <asm/arch/omap-alsa.h>
 
 #ifdef CONFIG_AMS_DELTA_FIQ
 #include <asm/ams-delta-fiq.h>
@@ -215,10 +217,41 @@ static struct platform_device ams_delta_
 	.id	= -1,
 };
 
+static struct omap_mcbsp_reg_cfg mcbsp_regs = { 
+	.spcr2 = FREE | XRST | GRST | XINTM(3) | FRST,
+	.spcr1 =  RINTM(3) | RRST,
+	.rcr2 =  RPHASE | RWDLEN2(OMAP_MCBSP_WORD_16) | RFRLEN2(0),
+	.rcr1 = RWDLEN1(OMAP_MCBSP_WORD_16) | RFRLEN1(0),
+	.xcr2 = XPHASE | XWDLEN2(OMAP_MCBSP_WORD_16) | XFRLEN2(0),
+	.xcr1 =  XWDLEN1(OMAP_MCBSP_WORD_16) | XFRLEN1(0),
+	.srgr1 = CLKGDV(0),
+	.srgr2 = GSYNC,
+};
+
+static struct omap_alsa_codec_config alsa_config = {
+	.name			= "AMS-DELTA-VC",
+	.mcbsp_regs_alsa	= &mcbsp_regs,
+	.codec_configure_dev	= NULL,
+	.codec_set_samplerate	= NULL,
+	.codec_clock_setup	= NULL,
+	.codec_clock_on		= NULL,
+	.codec_clock_off	= NULL,
+	.get_default_samplerate	= NULL,
+};
+
+static struct platform_device ams_delta_mcbsp1_device = {
+	.name	= "omap_alsa_mcbsp",
+	.id	= 1,
+	.dev = {
+		.platform_data	= &alsa_config,
+	},
+};
+
 static struct platform_device *ams_delta_devices[] __initdata = {
 	&ams_delta_bl_device,
 	&ams_delta_kp_device,
 	&ams_delta_lcd_device,
+	&ams_delta_mcbsp1_device,
 };
 
 static struct uart_port ams_delta_modem_port = {
diff -uprN linux-2.6.16/sound/arm/Kconfig linux-2.6.16-sound/sound/arm/Kconfig
--- linux-2.6.16/sound/arm/Kconfig	2006-04-27 21:27:09.000000000 +0000
+++ linux-2.6.16-sound/sound/arm/Kconfig	2006-04-27 21:34:52.000000000 +0000
@@ -59,4 +59,15 @@ config SND_OMAP_TSC2101
  	  To compile this driver as a module, choose M here: the module
  	  will be called snd-omap-tsc2101.
 
+config SND_OMAP_AMS_DELTA
+	tristate "Amstrad Delta (E3) alsa driver"
+	depends on ARCH_OMAP && SND
+	select SND_PCM
+	help
+	  Say Y here if you have a Amstrad E3 and want to use
+	  its modems VC to output sound through the speaker.
+
+	  To compile this driver as a module, choose M here: the module
+	  will be called snd-omap-ams-delta.
+
 endmenu
diff -uprN linux-2.6.16/sound/arm/omap/Makefile linux-2.6.16-sound/sound/arm/omap/Makefile
--- linux-2.6.16/sound/arm/omap/Makefile	2006-04-27 21:27:09.000000000 +0000
+++ linux-2.6.16-sound/sound/arm/omap/Makefile	2006-04-27 21:34:52.000000000 +0000
@@ -7,3 +7,6 @@ snd-omap-alsa-aic23-objs := omap-alsa.o 
 
 obj-$(CONFIG_SND_OMAP_TSC2101) += snd-omap-alsa-tsc2101.o
 snd-omap-alsa-tsc2101-objs := omap-alsa.o omap-alsa-dma.o omap-alsa-tsc2101.o omap-alsa-tsc2101-mixer.o
+
+obj-$(CONFIG_SND_OMAP_AMS_DELTA) += snd-omap-alsa-ams-delta.o
+snd-omap-alsa-ams-delta-objs := omap-alsa.o omap-alsa-dma.o omap-alsa-ams-delta.o omap-alsa-ams-delta-mixer.o
diff -uprN linux-2.6.16/sound/arm/omap/omap-alsa-ams-delta-mixer.c linux-2.6.16-sound/sound/arm/omap/omap-alsa-ams-delta-mixer.c
--- linux-2.6.16/sound/arm/omap/omap-alsa-ams-delta-mixer.c	1970-01-01 00:00:00.000000000 +0000
+++ linux-2.6.16-sound/sound/arm/omap/omap-alsa-ams-delta-mixer.c	2006-04-27 22:32:23.000000000 +0000
@@ -0,0 +1,78 @@
+/*
+ * sound/arm/omap/omap-alsa-ams-delta-mixer.c
+ * 
+ * Alsa Driver Mixer for the amstrad E3
+ *
+ * Copyright (C) 2006 Mark Underwood <[email-masked]>
+ *
+ * Based on omap-alsa-aic32-mixer.c
+ * Based on es1688_lib.c, 
+ * Copyright (c) by Jaroslav Kysela <[email-masked]>
+ *  
+ * 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 SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN
+ * NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
+ * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+ * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * 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.,
+ * 675 Mass Ave, Cambridge, MA 02139, USA.
+ *
+ */
+
+#include <linux/config.h>
+#include <sound/driver.h>
+
+#include <asm/arch/omap-alsa.h>
+#include "omap-alsa-ams-delta.h"
+#include <sound/initval.h>
+#include <sound/control.h>
+
+MODULE_AUTHOR("Mark Underwood");
+MODULE_LICENSE("GPL");
+MODULE_DESCRIPTION("OMAP Alsa mixer driver for the VC on the E3");
+
+/*
+ * Codec dependent region
+ */
+
+#define MIXER_NAME "Mixer AMS-DELTA"
+
+#ifdef CONFIG_PM
+
+void snd_omap_suspend_mixer(void)
+{
+}
+
+void snd_omap_resume_mixer(void)
+{
+}
+#endif
+
+void snd_omap_init_mixer(void)
+{
+}
+
+int snd_omap_mixer(struct snd_card_omap_codec *chip)
+{
+	snd_card_t *card;
+
+	snd_assert(chip != NULL && chip->card != NULL, return -EINVAL);
+
+	card = chip->card;
+
+	strcpy(card->mixername, MIXER_NAME);
+
+	return 0;
+}
diff -uprN linux-2.6.16/sound/arm/omap/omap-alsa-ams-delta.c linux-2.6.16-sound/sound/arm/omap/omap-alsa-ams-delta.c
--- linux-2.6.16/sound/arm/omap/omap-alsa-ams-delta.c	1970-01-01 00:00:00.000000000 +0000
+++ linux-2.6.16-sound/sound/arm/omap/omap-alsa-ams-delta.c	2006-04-27 22:34:45.000000000 +0000
@@ -0,0 +1,206 @@
+/*
+ * arch/arm/mach-omap1/omap-alsa-ams-delta.c
+ * 
+ * Alsa codec Driver for modem Voice Codec (VC) (CX20442-11) on the amstrad E3
+ *
+ * Copyright (C) 2006 Mark Underwood <[email-masked]>
+ *
+ * Based on omap-alsa-aic32.c
+ *
+ * Copyright (C) 2005 Instituto Nokia de Tecnologia - INdT - Manaus Brazil
+ * Written by Daniel Petrini, David Cohen, Anderson Briglia
+ *            {daniel.petrini, david.cohen, [email-masked]
+ *
+ * Copyright (C) 2006 Mika Laitio <[email-masked]>
+ *
+ * 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.
+ */
+
+#include <sound/driver.h>
+#include <sound/core.h>
+#include <sound/pcm.h>
+#include <sound/initval.h>
+#include <sound/control.h>
+#include <linux/clk.h>
+#include <asm/arch/clock.h>
+
+#include <asm/arch/omap-alsa.h>
+#include "omap-alsa-ams-delta.h"
+#include  <asm/arch/board-ams-delta.h>
+
+static struct clk *vc_mclk = 0;
+
+static unsigned int rates[] = {
+	8000,
+};
+static snd_pcm_hw_constraint_list_t vc_hw_constraints_rates = {
+	.count = ARRAY_SIZE(rates),
+	.list = rates,
+	.mask = 0,
+};
+
+static snd_pcm_hardware_t vc_snd_omap_alsa_playback = {
+	.info = (SNDRV_PCM_INFO_INTERLEAVED | SNDRV_PCM_INFO_BLOCK_TRANSFER |
+		 SNDRV_PCM_INFO_MMAP | SNDRV_PCM_INFO_MMAP_VALID),	
+	.formats = (SNDRV_PCM_FMTBIT_S16_LE),
+	.rates = (SNDRV_PCM_RATE_8000 |
+		  SNDRV_PCM_RATE_KNOT),
+	.rate_min = 8000,
+	.rate_max = 8000,
+	.channels_min = 2,
+	.channels_max = 2,
+	.buffer_bytes_max = 128 * 1024,
+	.period_bytes_min = 32,
+	.period_bytes_max = 8 * 1024,
+	.periods_min = 16,
+	.periods_max = 255,
+	.fifo_size = 0,
+};
+
+static snd_pcm_hardware_t vc_snd_omap_alsa_capture = {
+	.info = (SNDRV_PCM_INFO_INTERLEAVED | SNDRV_PCM_INFO_BLOCK_TRANSFER |
+		 SNDRV_PCM_INFO_MMAP | SNDRV_PCM_INFO_MMAP_VALID),
+	.formats = (SNDRV_PCM_FMTBIT_S16_LE),
+	.rates = (SNDRV_PCM_RATE_8000 |
+		  SNDRV_PCM_RATE_KNOT),
+	.rate_min = 8000,
+	.rate_max = 8000,
+	.channels_min = 2,
+	.channels_max = 2,
+	.buffer_bytes_max = 128 * 1024,
+	.period_bytes_min = 32,
+	.period_bytes_max = 8 * 1024,
+	.periods_min = 16,
+	.periods_max = 255,
+	.fifo_size = 0,
+};
+
+inline void vc_configure(void)
+{
+	ams_delta_latch2_write(AMS_DELTA_LATCH2_MODEM_CODEC, 0);
+}
+
+void vc_set_samplerate(long rate)
+{
+}
+
+/*
+ *  Omap MCBSP clock configuration and Power Management
+ *  
+ *  Here we have some functions that allows clock to be enabled and
+ *   disabled only when needed. Besides doing clock configuration 
+ *   it allows turn on/turn off audio when necessary. 
+ */
+/*
+ * Do clock framework mclk search
+ */
+void vc_clock_setup(void)
+{
+	vc_mclk = clk_get(0, "mclk");
+}
+
+/*
+ * Do some sanity check, set clock rate, starts it and
+ *  turn codec audio on 
+ */
+int vc_clock_on(void)
+{
+	if (clk_get_usecount(vc_mclk) > 0) {
+		/* MCLK is already in use */
+		printk(KERN_WARNING
+		       "MCLK in use at %d Hz. We change it to %d Hz\n",
+		       (uint) clk_get_rate(vc_mclk),
+		       CODEC_CLOCK);
+	}
+
+	clk_enable(vc_mclk);
+
+	printk(KERN_DEBUG
+		"MCLK = %d [%d], usecount = %d\n",
+	       (uint) clk_get_rate(vc_mclk), CODEC_CLOCK,
+	       clk_get_usecount(vc_mclk));
+
+	ams_delta_latch2_write(AMS_DELTA_LATCH2_MODEM_CODEC, 0);
+	return 0;
+}
+/*
+ * Do some sanity check, turn clock off and then turn
+ *  codec audio off
+ */
+int vc_clock_off(void)
+{
+	if  (clk_get_usecount(vc_mclk) > 0) { 
+		if (clk_get_rate(vc_mclk) != CODEC_CLOCK) {
+			printk(KERN_WARNING
+			       "MCLK for audio should be %d Hz. But is %d Hz\n",
+			       (uint) clk_get_rate(vc_mclk),
+			       CODEC_CLOCK);
+		}
+
+		clk_disable(vc_mclk);
+	}
+
+	ams_delta_latch2_write(AMS_DELTA_LATCH2_MODEM_CODEC, AMS_DELTA_LATCH2_MODEM_CODEC);
+	return 0;
+}
+
+int vc_get_default_samplerate(void)
+{
+	return DEFAULT_SAMPLE_RATE;
+}
+
+static int __init snd_omap_alsa_vc_probe(struct platform_device *pdev)
+{
+	int	ret;
+	struct	omap_alsa_codec_config *codec_cfg;
+	
+	codec_cfg = pdev->dev.platform_data;
+	if (codec_cfg != NULL) {
+		codec_cfg->hw_constraints_rates	= &vc_hw_constraints_rates;
+		codec_cfg->snd_omap_alsa_playback  = &vc_snd_omap_alsa_playback;
+		codec_cfg->snd_omap_alsa_capture  = &vc_snd_omap_alsa_capture;		
+		codec_cfg->codec_configure_dev	= vc_configure;
+		codec_cfg->codec_set_samplerate	= vc_set_samplerate;
+		codec_cfg->codec_clock_setup	= vc_clock_setup;
+		codec_cfg->codec_clock_on	= vc_clock_on;
+		codec_cfg->codec_clock_off	= vc_clock_off;
+		codec_cfg->get_default_samplerate = vc_get_default_samplerate;
+		ret	= snd_omap_alsa_post_probe(pdev, codec_cfg);
+	}
+	else
+		ret = -ENODEV;
+	return ret;
+}
+
+static struct platform_driver omap_alsa_driver = {
+	.probe		= snd_omap_alsa_vc_probe,
+	.remove 	= snd_omap_alsa_remove,
+	.suspend	= snd_omap_alsa_suspend,
+	.resume		= snd_omap_alsa_resume,
+	.driver	= {
+		.name =	"omap_alsa_mcbsp",
+	},
+};
+
+static int __init omap_alsa_vc_init(void)
+{
+	int err;
+	
+	ADEBUG();
+	err = platform_driver_register(&omap_alsa_driver);
+
+	return err;
+}
+
+static void __exit omap_alsa_vc_exit(void)
+{
+	ADEBUG();
+	
+	platform_driver_unregister(&omap_alsa_driver);
+}
+
+module_init(omap_alsa_vc_init);
+module_exit(omap_alsa_vc_exit);
diff -uprN linux-2.6.16/sound/arm/omap/omap-alsa-ams-delta.h linux-2.6.16-sound/sound/arm/omap/omap-alsa-ams-delta.h
--- linux-2.6.16/sound/arm/omap/omap-alsa-ams-delta.h	1970-01-01 00:00:00.000000000 +0000
+++ linux-2.6.16-sound/sound/arm/omap/omap-alsa-ams-delta.h	2006-04-27 22:32:39.000000000 +0000
@@ -0,0 +1,55 @@
+/*
+ * sound/arm/omap-alsa-ams-delta.h
+ * 
+ * Alsa codec Driver for modem Voice Codec (VC) (CX20442-11) on the amstrad E3
+ *
+ * Copyright (C) 2006 Mark Underwood <[email-masked]>
+ *
+ * Based on omap-alsa-aic32.h
+ *
+ * Copyright (C) 2005 Instituto Nokia de Tecnologia - INdT - Manaus Brazil
+ * Written by Daniel Petrini, David Cohen, Anderson Briglia
+ *            {daniel.petrini, david.cohen, [email-masked]
+ *
+ * Copyright (C) 2006 Mika Laitio <[email-masked]>
+ *
+ * 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.
+ */
+
+#ifndef __OMAP_ALSA_VC_H
+#define __OMAP_ALSA_VC_H
+
+#include <sound/driver.h>
+#include <asm/arch/dma.h>
+#include <sound/core.h>
+#include <sound/pcm.h>
+#include <asm/arch/mcbsp.h>
+
+/*
+ * AUDIO related MACROS
+ */
+#ifndef DEFAULT_BITPERSAMPLE
+#define DEFAULT_BITPERSAMPLE		16
+#endif
+
+#define DEFAULT_SAMPLE_RATE		8000
+/* ?? */
+#define CODEC_CLOCK			12000000
+#define AUDIO_MCBSP			OMAP_MCBSP1
+
+/*
+ * Defines codec specific functions pointers that can be used from the 
+ * common omap-alse base driver for all omap codecs. (tsc2101 and aic23)
+ */
+//void define_codec_functions(struct omap_alsa_codec_config *codec_config);
+inline void vc_configure(void);
+void vc_set_samplerate(long rate);
+void vc_clock_setup(void);
+int vc_clock_on(void);
+int vc_clock_off(void);
+int vc_get_default_samplerate(void);
+
+#endif
diff -uprN linux-2.6.16/sound/arm/omap/omap-alsa-dma.c linux-2.6.16-sound/sound/arm/omap/omap-alsa-dma.c
--- linux-2.6.16/sound/arm/omap/omap-alsa-dma.c	2006-04-27 21:27:09.000000000 +0000
+++ linux-2.6.16-sound/sound/arm/omap/omap-alsa-dma.c	2006-04-27 22:12:12.000000000 +0000
@@ -70,6 +70,8 @@
 
 #include <asm/arch/omap-alsa.h>
 
+#include <asm/mach-types.h>
+
 #undef DEBUG
 
 #define ERR(ARGS...) printk(KERN_ERR "{%s}-ERROR: ", __FUNCTION__);printk(ARGS);
@@ -350,6 +352,12 @@ static int audio_start_dma_chain(struct 
 		s->started = 1;
 		s->hw_start();	   /* start McBSP interface */
 	}
+		if (machine_is_ams_delta())
+			/* Not sure why we need to do this, but if we don't only the
+			 * first sample buffer gets transferred.
+			 */
+			omap_start_dma(channel);
+
 	/* else the dma itself will progress forward with out our help */
 	FN_OUT(0);
 	return 0;

---

From: Jasmine Strong <[email-masked]>
Date: Fri, 28 Apr 2006 06:09:36 +0200

> quick enough (tested with a

It will work with madplay.

-J.

---

From: Jonathan McDowell <[email-masked]>
Date: Fri, 28 Apr 2006 12:25:09 +0100

On Fri, Apr 28, 2006 at 06:09:36AM +0200, Jasmine Strong wrote:
> >Here (at last!) the Voice Modem sound patch. The driver is an ALSA
> >driver and it along with OSS emulation and a few other things will
> >need to be enable if you want  any sound. I have tested it with
> >rawrec/rawplay and mpg321 which can't seem to decode the MP3  quick
> >enough (tested with a 192KB MP3).
> 

It will indeed. My E3 is currently predicting a riot. Rock 'n roll.

J.

-- 
] http://www.earth.li/~noodles/ [] Why do I get the feeling I'm going  [
]  PGP/GPG Key @ the.earth.li   []           to regret this?           [
] via keyserver, web or email.  []                                     [
] RSA: 4DC4E7FD / DSA: 5B430367 []                                     [

---

From: Matt Callow <[email-masked]>
Date: Sat, 29 Apr 2006 19:08:04 +0100

>with rawrec/rawplay and mpg321 which can't seem to decode the MP3 quick enough (tested with a
Nice work Mark. Patch applied without problems. I tested playback using
mpd and madplayer (both use libmad) and it seems to decode mp3s without
problems (as reported by others). I've not tested capture yet.

A few questions/observations:

1. The sound comes out of the handset. Is that expected?
2. The sound is very distorted - are other people experiencing this?

Matt

(P.S. it seems to mess up my camera driver once I've installed the sound
modules, but that could well be a problem with the camera driver)

---

From: Jonathan McDowell <[email-masked]>
Date: Sun, 30 Apr 2006 17:57:08 +0100

> 1. The sound comes out of the handset. Is that expected?

Certainly it's what I get.

> 2. The sound is very distorted - are other people experiencing this?

Yes; I believe it's due to there being no mixer device so it comes
through at max volume?

J.

-- 
          noodles is al's          |  .''`.  Debian GNU/Linux Developer
                                   | : :' :  Happy to accept PGP signed
                                   | `. `'   or encrypted mail - RSA +
                                   |   `-    DSA keys on the keyservers.

---

From: Mark Underwood <[email-masked]>
Date: Sun, 30 Apr 2006 17:57:29 +0100 (BST)

> 1. The sound comes out of the handset. Is that expected?
Yes, I'm not sure to change it to come out the speaker on the unit. I think someone has an AT
command which worked, but I'm not sure what it was.
> 2. The sound is very distorted - are other people experiencing this?
With madplayer yes. With the default settings the amp is being driven too hard, you need to turn
down the volume :-).

Mark
> modules, but that could well be a problem with the camera driver)
Hmm, not sure what would cause that, unless your using the same clock the as sound driver.
> 
> 
> 
> 
> 
> _______________________________________________
> e3-hacking mailing list
> [email-masked]
> http://www.earth.li/cgi-bin/mailman/listinfo/e3-hacking
>