[oe-commits] org.oe.dev linux-efika: Sound driver altered to keep hands of register bits it shouldn't touch.

likewise commit openembedded-commits at lists.openembedded.org
Sun Jan 14 23:17:44 UTC 2007


linux-efika: Sound driver altered to keep hands of register bits it shouldn't touch.

Author: likewise at openembedded.org
Branch: org.openembedded.dev
Revision: 1617d5220cf3c41dace36385d3a618ac76b756d8
ViewMTN: http://monotone.openembedded.org/revision.psp?id=1617d5220cf3c41dace36385d3a618ac76b756d8
Files:
1
packages/linux/linux-efika/0001-sound-Add-support-for-the-MPC52xx-PSC-AC97-Link.txt
packages/linux/linux-efika_2.6.18+2.6.19-rc6.bb
Diffs:

#
# mt diff -r85717d4bcfba093765597e2d42478a058f595247 -r1617d5220cf3c41dace36385d3a618ac76b756d8
#
# 
# 
# add_file "packages/linux/linux-efika/0001-sound-Add-support-for-the-MPC52xx-PSC-AC97-Link.txt"
#  content [b188c829ede0ff599c37bb956c6f0350e5630d2d]
# 
# patch "packages/linux/linux-efika_2.6.18+2.6.19-rc6.bb"
#  from [31d40613d38032ef7fe32bd654cabcf9bba27e2f]
#    to [06382c243ca16578b84f66e7542adebbc64a76a5]
# 
============================================================
--- packages/linux/linux-efika/0001-sound-Add-support-for-the-MPC52xx-PSC-AC97-Link.txt	b188c829ede0ff599c37bb956c6f0350e5630d2d
+++ packages/linux/linux-efika/0001-sound-Add-support-for-the-MPC52xx-PSC-AC97-Link.txt	b188c829ede0ff599c37bb956c6f0350e5630d2d
@@ -0,0 +1,834 @@
+I cleaned up the setting of the port_config register on the MPC5200B.
+This driver now touches only the two relevant bits without overriding
+the others.
+
+Signed-off-by: Leon Woestenberg <leonw at mailcan.com>
+
+From 144658ad3d23bb426e29562235e40f0f9797a9c7 Mon Sep 17 00:00:00 2001
+From: Sylvain Munaut <tnt at 246tNt.com>
+Date: Mon, 18 Dec 2006 22:51:38 +0100
+Subject: [PATCH] sound: Add support for the MPC52xx PSC AC97 Link
+
+Messy driver, to be cleaned ... a lot ...
+
+Signed-off-by: Sylvain Munaut <tnt at 246tNt.com>
+---
+ include/asm-ppc/mpc52xx_psc.h |   10 -
+ sound/ppc/Kconfig             |   16 +
+ sound/ppc/Makefile            |    3 
+ sound/ppc/mpc52xx_ac97.c      |  738 +++++++++++++++++++++++++++++++++++++++++
+ 4 files changed, 765 insertions(+), 2 deletions(-)
+
+Index: linux-2.6.19-rc6_efika/include/asm-ppc/mpc52xx_psc.h
+===================================================================
+--- linux-2.6.19-rc6_efika.orig/include/asm-ppc/mpc52xx_psc.h	2007-01-14 19:45:07.000000000 +0100
++++ linux-2.6.19-rc6_efika/include/asm-ppc/mpc52xx_psc.h	2007-01-14 19:45:07.000000000 +0100
+@@ -28,6 +28,10 @@
+ #define MPC52xx_PSC_MAXNUM	6
+ 
+ /* Programmable Serial Controller (PSC) status register bits */
++#define MPC52xx_PSC_SR_UNEX_RX	0x0001
++#define MPC52xx_PSC_SR_DATA_VAL	0x0002
++#define MPC52xx_PSC_SR_DATA_OVR	0x0004
++#define MPC52xx_PSC_SR_CMDSEND	0x0008
+ #define MPC52xx_PSC_SR_CDE	0x0080
+ #define MPC52xx_PSC_SR_RXRDY	0x0100
+ #define MPC52xx_PSC_SR_RXFULL	0x0200
+@@ -132,8 +136,10 @@
+ 	u8		reserved5[3];
+ 	u8		ctlr;		/* PSC + 0x1c */
+ 	u8		reserved6[3];
+-	u16		ccr;		/* PSC + 0x20 */
+-	u8		reserved7[14];
++	u32		ccr;		/* PSC + 0x20 */
++	u32		ac97_slots;	/* PSC + 0x24 */
++	u32		ac97_cmd;	/* PSC + 0x28 */
++	u32		ac97_data;	/* PSC + 0x2c */
+ 	u8		ivr;		/* PSC + 0x30 */
+ 	u8		reserved8[3];
+ 	u8		ip;		/* PSC + 0x34 */
+Index: linux-2.6.19-rc6_efika/sound/ppc/Kconfig
+===================================================================
+--- linux-2.6.19-rc6_efika.orig/sound/ppc/Kconfig	2007-01-14 19:45:07.000000000 +0100
++++ linux-2.6.19-rc6_efika/sound/ppc/Kconfig	2007-01-14 19:45:07.000000000 +0100
+@@ -33,3 +33,19 @@
+ 	  option.
+ 
+ endmenu
++
++
++# ALSA ppc drivers
++
++menu "ALSA PPC devices"
++	depends on SND!=n && PPC
++
++config SND_PPC_MPC52xx_AC97
++	tristate "Freescale MPC52xx AC97 interface support"
++	depends on SND && PPC_MPC52xx
++	select SND_AC97_CODEC
++	help
++	  Say Y or M if you want to support any AC97 codec attached to
++	  the Freescqle MPC52xx AC97 interface.
++
++endmenu
+Index: linux-2.6.19-rc6_efika/sound/ppc/Makefile
+===================================================================
+--- linux-2.6.19-rc6_efika.orig/sound/ppc/Makefile	2007-01-14 19:45:07.000000000 +0100
++++ linux-2.6.19-rc6_efika/sound/ppc/Makefile	2007-01-14 19:45:07.000000000 +0100
+@@ -4,6 +4,9 @@
+ #
+ 
+ snd-powermac-objs := powermac.o pmac.o awacs.o burgundy.o daca.o tumbler.o keywest.o beep.o
++snd-mpc52xx-ac97-objs := mpc52xx_ac97.o
+ 
+ # Toplevel Module Dependency
+ obj-$(CONFIG_SND_POWERMAC) += snd-powermac.o
++
++obj-$(CONFIG_SND_PPC_MPC52xx_AC97)	+= snd-mpc52xx-ac97.o
+Index: linux-2.6.19-rc6_efika/sound/ppc/mpc52xx_ac97.c
+===================================================================
+--- /dev/null	1970-01-01 00:00:00.000000000 +0000
++++ linux-2.6.19-rc6_efika/sound/ppc/mpc52xx_ac97.c	2007-01-14 22:45:55.000000000 +0100
+@@ -0,0 +1,742 @@
++/*
++ * Driver for the PSC of the Freescale MPC52xx configured as AC97 interface
++ *
++ *
++ * Copyright (C) 2006 Sylvain Munaut <tnt at 246tNt.com>
++ *
++ * This file is licensed under the terms of the GNU General Public License
++ * version 2. This program is licensed "as is" without any warranty of any
++ * kind, whether express or implied.
++ */
++
++#define DEBUG
++
++#include <linux/kernel.h>
++#include <linux/module.h>
++#include <linux/interrupt.h>
++
++#include <sound/driver.h>
++#include <sound/core.h>
++#include <sound/initval.h>
++#include <sound/pcm.h>
++#include <sound/pcm_params.h>
++#include <sound/ac97_codec.h>
++
++#include <asm/of_platform.h>
++#include <asm/mpc52xx_psc.h>
++
++
++#define DRV_NAME "mpc52xx-psc-ac97"
++
++
++/* ======================================================================== */
++/* Structs / Defines                                                        */
++/* ======================================================================== */
++
++/* Private structure */
++struct mpc52xx_ac97_priv {
++	struct device *dev;
++	resource_size_t	mem_start;
++	resource_size_t mem_len;
++	int irq;
++	struct mpc52xx_psc __iomem *psc;
++	struct snd_card *card;
++	struct snd_pcm *pcm;
++	struct snd_ac97 *ac97;
++
++	struct snd_pcm_substream *substream_playback;
++	unsigned int buf_pos;
++};
++
++/* Register bit definition (AC97 mode specific) */
++#define PSC_AC97_SLOT_BIT(n)		(1<<(12-n))
++#define PSC_AC97_SLOTS_XMIT_SHIFT	16
++#define PSC_AC97_SLOTS_RECV_SHIFT	 0
++
++
++
++/* ======================================================================== */
++/* ISR routine                                                              */
++/* ======================================================================== */
++
++static irqreturn_t
++mpc52xx_ac97_irq(int irq, void *dev_id)
++{
++	struct mpc52xx_ac97_priv *priv = dev_id;
++
++	static int icnt = 0;
++	#if 0
++	{
++	unsigned int val;
++//	val = in_be32(&priv->psc->ac97_data);
++	printk(KERN_INFO "mpc52xx_ac97_irq fired (isr=%04x, status=%04x) %08x\n", in_be16(&priv->psc->mpc52xx_psc_imr), in_be16(&priv->psc->mpc52xx_psc_status), val);
++	out_8(&priv->psc->command,MPC52xx_PSC_RST_ERR_STAT);
++	}
++	#endif
++
++	/* Anti Crash during dev ;) */
++	#if 0
++	if ((icnt++) > 50000)
++		out_be16(&priv->psc->mpc52xx_psc_imr, 0);
++	#endif
++
++	/* Copy 64 data into the buffer */
++	if (in_be16(&priv->psc->mpc52xx_psc_imr) & 0x0100) {
++		if (priv->substream_playback) {
++			struct snd_pcm_runtime *rt;
++
++			rt = priv->substream_playback->runtime;
++
++			if (snd_pcm_playback_hw_avail(rt) < bytes_to_frames(rt,128)) {
++				int i;
++				/* Push silence */
++				for (i=0; i<64; i++)
++					out_be32(&priv->psc->mpc52xx_psc_buffer_32, 0x00000800);
++				printk(KERN_DEBUG "pushed silence ...\n");
++			} else {
++				int i;
++				unsigned short *data;
++
++				data = (unsigned short *)
++					(&rt->dma_area[frames_to_bytes(rt, priv->buf_pos)]);
++
++				for (i=0; i<64; i++)
++					out_be32(&priv->psc->mpc52xx_psc_buffer_32,
++						(((unsigned int)data[i]) << 16) | 0x00000000);
++							/* Setting the sof bit looks useless */
++
++				priv->buf_pos += bytes_to_frames(rt,128);;
++				if (priv->buf_pos >= rt->buffer_size)
++					priv->buf_pos = 0;
++
++				snd_pcm_period_elapsed(priv->substream_playback);
++			}
++		} else {
++			out_be16(&priv->psc->mpc52xx_psc_imr, 0);
++			printk(KERN_DEBUG "Interrupt with no stream ...\n");
++		}
++	} else {
++		printk(KERN_ERR "Spurious int\n");
++	}
++
++	return IRQ_HANDLED;
++}
++
++
++/* ======================================================================== */
++/* PCM interface                                                            */
++/* ======================================================================== */
++
++/* HW desc */
++
++static struct snd_pcm_hardware mpc52xx_ac97_hw = {
++	.info			= SNDRV_PCM_INFO_INTERLEAVED		|
++					SNDRV_PCM_INFO_MMAP		|
++					SNDRV_PCM_INFO_MMAP_VALID,
++	.formats		= SNDRV_PCM_FMTBIT_S16_BE,
++	.rates			= SNDRV_PCM_RATE_8000_48000,
++	.rate_min		= 8000,
++	.rate_max		= 48000,
++	.channels_min		= 1,
++	.channels_max		= 2,	/* Support for more ? */
++	.buffer_bytes_max	= 128*1024,
++	.period_bytes_min	= 128, /* 32, */
++	.period_bytes_max	= 128, /* 16*1024, */
++	.periods_min		= 8,
++	.periods_max		= 256,
++	.fifo_size		= 512,
++};
++
++
++/* Playback */
++
++static int
++mpc52xx_ac97_playback_open(struct snd_pcm_substream *substream)
++{
++	struct mpc52xx_ac97_priv *priv = substream->pcm->private_data;
++
++	dev_dbg(priv->dev, "mpc52xx_ac97_playback_open(%p)\n", substream);
++
++	substream->runtime->hw = mpc52xx_ac97_hw;
++
++	priv->substream_playback = substream;
++	priv->buf_pos = 0;	/* FIXME Do that where ? */
++
++	return 0;	/* FIXME */
++}
++
++static int
++mpc52xx_ac97_playback_close(struct snd_pcm_substream *substream)
++{
++	struct mpc52xx_ac97_priv *priv = substream->pcm->private_data;
++	dev_dbg(priv->dev, "mpc52xx_ac97_playback_close(%p)\n", substream);
++	priv->substream_playback = NULL;
++	return 0;	/* FIXME */
++}
++
++static int
++mpc52xx_ac97_playback_prepare(struct snd_pcm_substream *substream)
++{
++	struct mpc52xx_ac97_priv *priv = substream->pcm->private_data;
++
++	dev_dbg(priv->dev, "mpc52xx_ac97_playback_prepare(%p)\n", substream);
++
++	/* FIXME, need a spinlock to protect access */
++	if (substream->runtime->channels == 1)
++		out_be32(&priv->psc->ac97_slots, 0x01000000);
++	else
++		out_be32(&priv->psc->ac97_slots, 0x03000000);
++
++	snd_ac97_set_rate(priv->ac97, AC97_PCM_FRONT_DAC_RATE, substream->runtime->rate);
++
++	return 0;	/* FIXME */
++}
++
++
++/* Capture */
++
++static int
++mpc52xx_ac97_capture_open(struct snd_pcm_substream *substream)
++{
++	struct mpc52xx_ac97_priv *priv = substream->pcm->private_data;
++	return 0;	/* FIXME */
++}
++
++static int
++mpc52xx_ac97_capture_close(struct snd_pcm_substream *substream)
++{
++	struct mpc52xx_ac97_priv *priv = substream->pcm->private_data;
++	return 0;	/* FIXME */
++}
++
++static int
++mpc52xx_ac97_capture_prepare(struct snd_pcm_substream *substream)
++{
++	struct mpc52xx_ac97_priv *priv = substream->pcm->private_data;
++	return 0;	/* FIXME */
++}
++
++
++/* Common */
++
++static int
++mpc52xx_ac97_hw_params(struct snd_pcm_substream *substream,
++			struct snd_pcm_hw_params *params)
++{
++	struct mpc52xx_ac97_priv *priv = substream->pcm->private_data;
++	int rv;
++
++	dev_dbg(priv->dev, "mpc52xx_ac97_hw_params(%p)\n", substream);
++
++	rv = snd_pcm_lib_malloc_pages(substream,
++					params_buffer_bytes(params));
++	if (rv < 0) {
++		printk(KERN_ERR "hw params failes\n");	/* FIXME */
++		return rv;
++	}
++
++	printk(KERN_DEBUG "%d %d %d\n", params_buffer_bytes(params), params_period_bytes(params), params_periods(params));
++
++
++	return 0;
++}
++
++static int
++mpc52xx_ac97_hw_free(struct snd_pcm_substream *substream)
++{
++	struct mpc52xx_ac97_priv *priv = substream->pcm->private_data;
++
++	dev_dbg(priv->dev, "mpc52xx_ac97_hw_free(%p)\n", substream);
++
++	return snd_pcm_lib_free_pages(substream);
++}
++
++static int
++mpc52xx_ac97_trigger(struct snd_pcm_substream *substream, int cmd)
++{
++	struct mpc52xx_ac97_priv *priv = substream->pcm->private_data;
++	int rv = 0;
++
++	dev_dbg(priv->dev, "mpc52xx_ac97_trigger(%p,%d)\n", substream, cmd);
++
++	switch (cmd) {
++		case SNDRV_PCM_TRIGGER_START:
++			/* Enable TX interrupt */
++			out_be16(&priv->psc->mpc52xx_psc_imr, 0x0100); // 0x0100
++
++			break;
++
++		case SNDRV_PCM_TRIGGER_STOP:
++			/* Disable TX interrupt */
++			out_be16(&priv->psc->mpc52xx_psc_imr, 0x0000);
++
++			break;
++
++		default:
++			rv = -EINVAL;
++	}
++
++	/* FIXME */
++	return rv;
++}
++
++static snd_pcm_uframes_t
++mpc52xx_ac97_pointer(struct snd_pcm_substream *substream)
++{
++	struct mpc52xx_ac97_priv *priv = substream->pcm->private_data;
++
++//	dev_dbg(priv->dev, "mpc52xx_ac97_pointer(%p)\n", substream);
++
++	if (substream->runtime->channels == 1)
++		return priv->buf_pos;	/* FIXME */
++	else
++		return priv->buf_pos >> 1;	/* FIXME */
++}
++
++
++/* Ops */
++
++static struct snd_pcm_ops mpc52xx_ac97_playback_ops = {
++	.open		= mpc52xx_ac97_playback_open,
++	.close		= mpc52xx_ac97_playback_close,
++	.ioctl		= snd_pcm_lib_ioctl,
++	.hw_params	= mpc52xx_ac97_hw_params,
++	.hw_free	= mpc52xx_ac97_hw_free,
++	.prepare	= mpc52xx_ac97_playback_prepare,
++	.trigger	= mpc52xx_ac97_trigger,
++	.pointer	= mpc52xx_ac97_pointer,
++};
++
++static struct snd_pcm_ops mpc52xx_ac97_capture_ops = {
++	.open		= mpc52xx_ac97_capture_open,
++	.close		= mpc52xx_ac97_capture_close,
++	.ioctl		= snd_pcm_lib_ioctl,
++	.hw_params	= mpc52xx_ac97_hw_params,
++	.hw_free	= mpc52xx_ac97_hw_free,
++	.prepare	= mpc52xx_ac97_capture_prepare,
++	.trigger	= mpc52xx_ac97_trigger,
++	.pointer	= mpc52xx_ac97_pointer,
++};
++
++
++/* ======================================================================== */
++/* AC97 Bus interface                                                       */
++/* ======================================================================== */
++
++static unsigned short
++mpc52xx_ac97_bus_read(struct snd_ac97 *ac97, unsigned short reg)
++{
++	struct mpc52xx_ac97_priv *priv = ac97->private_data;
++	int timeout;
++	unsigned int val;
++
++	dev_dbg(priv->dev, "ac97 read: reg %04x\n", reg);
++
++	/* Wait for it to be ready */
++	timeout = 1000;
++	while ((--timeout) && (in_be16(&priv->psc->mpc52xx_psc_status) &
++						MPC52xx_PSC_SR_CMDSEND) )
++		udelay(10);
++
++	if (!timeout) {
++		printk(KERN_ERR DRV_NAME ": timeout on ac97 bus (rdy)\n");
++		return 0xffff;
++	}
++
++	/* Do the read */
++	out_be32(&priv->psc->ac97_cmd, (1<<31) | ((reg & 0x7f) << 24));
++
++	/* Wait for the answer */
++	timeout = 1000;
++	while ((--timeout) && !(in_be16(&priv->psc->mpc52xx_psc_status) &
++						MPC52xx_PSC_SR_DATA_VAL) )
++		udelay(10);
++
++	if (!timeout) {
++		printk(KERN_ERR DRV_NAME ": timeout on ac97 read (val)\n");
++		return 0xffff;
++	}
++
++	/* Get the data */
++	val = in_be32(&priv->psc->ac97_data);
++	if ( ((val>>24) & 0x7f) != reg ) {
++		printk(KERN_ERR DRV_NAME ": reg echo error on ac97 read\n");
++		return 0xffff;
++	}
++	val = (val >> 8) & 0xffff;
++
++	dev_dbg(priv->dev, "ac97 read ok: reg %04x  val %04x\n",
++				reg, val);
++
++	return (unsigned short) val;
++}
++
++static void
++mpc52xx_ac97_bus_write(struct snd_ac97 *ac97,
++			unsigned short reg, unsigned short val)
++{
++	struct mpc52xx_ac97_priv *priv = ac97->private_data;
++	int timeout;
++
++	dev_dbg(priv->dev, "ac97 write: reg %04x  val %04x\n",
++				reg, val);
++
++	/* Wait for it to be ready */
++	timeout = 1000;
++	while ((--timeout) && (in_be16(&priv->psc->mpc52xx_psc_status) &
++						MPC52xx_PSC_SR_CMDSEND) )
++		udelay(10);
++
++	if (!timeout) {
++		printk(KERN_ERR DRV_NAME ": timeout on ac97 write\n");
++		return;
++	}
++
++	/* Write data */
++	out_be32(&priv->psc->ac97_cmd, ((reg & 0x7f) << 24) | (val << 8));
++}
++
++static void
++mpc52xx_ac97_bus_reset(struct snd_ac97 *ac97)
++{
++	struct mpc52xx_ac97_priv *priv = ac97->private_data;
++
++	dev_dbg(priv->dev, "ac97 codec reset\n");
++
++	/* Do a cold reset */
++	out_8(&priv->psc->op1, 0x03);
++	udelay(10);
++	out_8(&priv->psc->op0, 0x02);
++	udelay(50);
++
++	/* PSC recover from cold reset (cfr user manual, not sure if useful) */
++	out_be32(&priv->psc->sicr, in_be32(&priv->psc->sicr));
++}
++
++
++static struct snd_ac97_bus_ops mpc52xx_ac97_bus_ops = {
++	.read	= mpc52xx_ac97_bus_read,
++	.write	= mpc52xx_ac97_bus_write,
++	.reset	= mpc52xx_ac97_bus_reset,
++};
++
++
++/* ======================================================================== */
++/* Sound driver setup                                                       */
++/* ======================================================================== */
++
++static int
++mpc52xx_ac97_setup_pcm(struct mpc52xx_ac97_priv *priv)
++{
++	int rv;
++
++	rv = snd_pcm_new(priv->card, DRV_NAME "-pcm", 0, 1, 1, &priv->pcm);
++	if (rv) {
++		printk(KERN_ERR DRV_NAME ": snd_pcm_new failed\n");
++		return rv;
++	}
++
++	rv = snd_pcm_lib_preallocate_pages_for_all(priv->pcm,
++		SNDRV_DMA_TYPE_CONTINUOUS, snd_dma_continuous_data(GFP_KERNEL),
++		128*1024, 128*1024);
++	if (rv) {
++		printk(KERN_ERR DRV_NAME
++			": snd_pcm_lib_preallocate_pages_for%s
>>> DIFF TRUNCATED @ 16K






More information about the Openembedded-commits mailing list