Angelo wrote:
>
> Pedro wrote:
>>Which library do you mean? I don't understand, sorry.
>
> In your previous mail (with code), each lines with an "#include " don't show
> the name of header file.
>
> thanks
>
Ups! Sorry, I send the code as an attached file, then.
>
>
> ________________________________
> L'email della prossima generazione? Puoi averla con la Nuova Yahoo! Mail
_________________________________________________________________
MSN Video.
http://video.msn.com/?mkt=es-es
/***************************************************************************
* Copyright (C) 2007 by Pedro L. DomÃnguez *
* [EMAIL PROTECTED] *
* *
* This program is free software; you can redistribute it and/or modify *
* it under the terms of the GNU General Public License as published by *
* the Free Software Foundation; either version 2 of the License, or *
* (at your option) any later version. *
* *
* This program is distributed in the hope that it will be useful, *
* but WITHOUT ANY WARRANTY; without even the implied warranty of *
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
* GNU General Public License for more details. *
* *
* You should have received a copy of the GNU General Public License *
* along with this program; if not, write to the *
* Free Software Foundation, Inc., *
* 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. *
* *
* History *
* Original Version by Bernhard Kuhn <[EMAIL PROTECTED]> *
* for 2.6.16 kernel *
***************************************************************************/
#define SPI_DBG
#ifdef SPI_DBG
#define DBG(x...) printk("(debug) " x)
#else
#define DBG(x...)
#endif
#include <linux/init.h>
#include <linux/kernel.h>
#include <linux/module.h>
#include <linux/slab.h>
#include <linux/fs.h>
#include <linux/errno.h>
#include <linux/types.h>
#include <linux/proc_fs.h>
#include <linux/fcntl.h>
#include <linux/spinlock.h>
#include <linux/platform_device.h>
#include <asm/system.h>
#include <asm/uaccess.h>
#include <asm/io.h>
#include <linux/string.h>
#include <linux/autoconf.h>
#include <linux/timer.h>
#include <linux/init.h>
#include <linux/version.h>
#include <linux/sched.h>
#include <linux/smp_lock.h>
#include <linux/miscdevice.h>
#include <linux/interrupt.h>
#include <linux/irq.h>
#include <linux/ioport.h>
#include <linux/poll.h>
#include <asm/io.h>
#include <asm/uaccess.h>
#include <asm/system.h>
#include <asm/delay.h>
#include <asm/mpc52xx.h>
#include <asm/mpc52xx_psc.h>
#include <asm/of_platform.h>
#include <sysdev/bestcomm/bestcomm.h>
#include <sysdev/bestcomm/gen_bd.h>
#include <sysdev/bestcomm/bestcomm_priv.h>
#include <sound/pcm.h>
#include <sound/asound.h>
// #include <sound/typedefs.h>
#define BPF 2 // bytes per frame
#define SLOTS 2
#define SAMPLESIZE (BPF*SLOTS)
#define FPP 1024 // bytes per copy period
#define PERIODS 8 // periods
#define PERIODSIZE (SAMPLESIZE/2*FPP)
#define BUFSIZE (SAMPLESIZE*FPP*PERIODS)
#define FPP_HW 128
//512 // 10 ms
#define PERIODS_HW 8 // periods
#define PERIODSIZE_HW (SAMPLESIZE*FPP_HW)
#define FIFOSIZE 512
#define RX_GRAN 4
#define TX_GRAN 4
#define RX_ALARM 0x120
#define TX_ALARM FIFOSIZE - (TX_GRAN * 4) - 208
#define DELAY_TIME_SLOT 0x20000000
#define GEN_CLK_INT 0x00800000
#define MULTIWD_ENABLE 0x00400000
#define CLK_POL_RISING 0x00200000
#define PROCFS_NAME "MPC52xx_SPI"
#define MCLKEN_DIV 0x8001
#define DRV_NAME "mpc52xx-psc-spi"
#define PROCFS_MAX_SIZE 1024
#define BUF_FRAMES 300
/* MBAR position */
#define MPC52xx_MBAR 0xf0000000 /* Phys address */
#define MPC52xx_MBAR_VIRT 0xf0000000 /* Virt address */
#define MPC52xx_MBAR_SIZE 0x00010000
#define MPC52xx_PA(x) ((phys_addr_t)(MPC52xx_MBAR + (x)))
#define MPC52xx_VA(x) ((void __iomem *)(MPC52xx_MBAR_VIRT + (x)))
/* Registers zone offset/size */
#define MPC52xx_MMAP_CTL_OFFSET 0x0000
#define MPC52xx_MMAP_CTL_SIZE 0x068
#define MPC52xx_SDRAM_OFFSET 0x0100
#define MPC52xx_SDRAM_SIZE 0x010
#define MPC52xx_CDM_OFFSET 0x0200
#define MPC52xx_CDM_SIZE 0x038
#define MPC52xx_INTR_OFFSET 0x0500
#define MPC52xx_INTR_SIZE 0x04c
#define MPC52xx_GPTx_OFFSET(x) (0x0600 + ((x)<<4))
#define MPC52xx_GPT_SIZE 0x010
#define MPC52xx_RTC_OFFSET 0x0800
#define MPC52xx_RTC_SIZE 0x024
#define MPC52xx_GPIO_OFFSET 0x0b00
#define MPC52xx_GPIO_SIZE 0x040
#define MPC52xx_GPIO_WKUP_OFFSET 0x0c00
#define MPC52xx_GPIO_WKUP_SIZE 0x028
#define MPC52xx_PCI_OFFSET 0x0d00
#define MPC52xx_PCI_SIZE 0x100
#define MPC52xx_SDMA_OFFSET 0x1200
#define MPC52xx_SDMA_SIZE 0x100
#define MPC52xx_XLB_OFFSET 0x1f00
#define MPC52xx_XLB_SIZE 0x100
#define MPC52xx_PSCx_OFFSET(x) (((x)!=6)?(0x1e00+((x)<<9)):0x2c00)
#define MPC52xx_PSC_SIZE 0x0a0
#define PORT_CONFIG_PSC1 0x00000006
#define PSC1_CLK_EN 0x00000020
typedef unsigned long uint32;
typedef unsigned long UInteger32;
typedef unsigned short UInteger16;
struct proc_dir_entry *Our_Proc_File;
struct SPI_buffer {
char *va;
dma_addr_t pa;
};
static struct SPI_buffer SPI_tx_silence;
static struct SPI_buffer SPI_rx_bufs;
typedef struct _node {
struct SPI_buffer buffer;
struct _node *next;
} Node;
static Node *LastNode;
static Node *FirstNode;
Node *FirstNodeFree;
Node *LastNodeFree;
struct bcom_task *tx_bcom;
struct bcom_task *rx_bcom;
int r_irq;
int t_irq;
struct mpc52xx_psc *psc;
struct mpc52xx_spi_priv {
struct device *dev;
resource_size_t mem_start;
resource_size_t mem_len;
int irq;
struct mpc52xx_psc __iomem *psc;
struct bcom_task *tsk_tx;
spinlock_t dma_lock;
int period_byte_size;
u32 period_start, period_end, period_next_p;
};
static int initiator_tx;
static int initiator_rx;
static struct snd_pcm_substream *snd_SPI_substream;
static int snd_SPImgt_running = 0;
static int snd_SPImgt_started = 2;
static int SPI_pos = 0;
static int SPI_play = 0;
static int nodecounter=0;
static unsigned int dmablockcounter=0;
static struct hrtimer start_timer;
static struct timeval tclockup = {.tv_sec = 1,.tv_usec = 0};
static struct timeval tclockdown= {.tv_sec = 0,.tv_usec = 615080};
static ktime_t kt_timedown, kt_timeup ;
void (*hook_per_elap)(int, int);
UInteger32 (*hook_frames_rcv)(void);
int SPI_buffers_init(void) {
int i;
Node *node;
FirstNodeFree = (Node *)kmalloc(sizeof(Node), GFP_KERNEL);
FirstNodeFree->buffer.va = kmalloc(PERIODSIZE_HW, GFP_DMA);
FirstNodeFree->buffer.pa = virt_to_phys((void *)FirstNodeFree->buffer.va);
node = FirstNodeFree;
for (i=1;i<BUF_FRAMES;i++)
{
node->next = (Node *)kmalloc(sizeof(Node), GFP_KERNEL);
node->next->buffer.va = kmalloc(PERIODSIZE_HW, GFP_DMA);
node->next->buffer.pa = virt_to_phys((void *)node->next->buffer.va);
node = node->next;
}
LastNodeFree = node;
LastNodeFree->next=NULL;
DBG("SPI_buffers_init()\n");
// prepare reception buffer
SPI_rx_bufs.va = kmalloc(BUFSIZE, GFP_DMA);
SPI_rx_bufs.pa = virt_to_phys((void *)SPI_rx_bufs.va);
// prepare silence buffer
SPI_tx_silence.va = kmalloc(BUFSIZE, GFP_DMA);
SPI_tx_silence.pa = virt_to_phys((void *)SPI_tx_silence.va);
memset(SPI_tx_silence.va,0,BUFSIZE);
return 0;
}
int snd_SPI_pcm_trigger(struct snd_pcm_substream *substream, int cmd) {
#ifdef SND_I2S_DEBUG
printk("snd_SPI_pcm_trigger\n");
#endif
switch (cmd) {
case SNDRV_PCM_TRIGGER_START:
case SNDRV_PCM_TRIGGER_RESUME:
#ifdef SND_I2S_DEBUG
printk("START\n");
#endif
snd_SPI_substream=substream;
snd_SPImgt_started=2;
snd_SPImgt_running=1;
break;
case SNDRV_PCM_TRIGGER_STOP:
case SNDRV_PCM_TRIGGER_SUSPEND:
#ifdef SND_I2S_DEBUG
printk("STOP\n");
#endif
snd_SPImgt_running=0;
break;
case SNDRV_PCM_TRIGGER_PAUSE_PUSH:
printk(" PAUSE_PUSH\n");
break;
case SNDRV_PCM_TRIGGER_PAUSE_RELEASE:
printk(" PAUSE_RELEASE\n");
break;
default:
return -EINVAL;
}
return 0;
};
EXPORT_SYMBOL(snd_SPI_pcm_trigger);
static irqreturn_t SPI_rx_irq(int irq, void *dev_id) {
// no need for TaskIntClear(rxtask), OS masks and acks IRQ
struct mpc52xx_spi_priv *priv = dev_id;
spin_lock(&priv->dma_lock);
while (bcom_buffer_done(rx_bcom)) {
struct bcom_gen_bd *bd;
bcom_retrieve_buffer(rx_bcom, NULL, NULL);
/* Submit a new one */
bd = (struct bcom_gen_bd *) bcom_prepare_next_buffer(rx_bcom);
bd->status = 512;
bd->buf_pa = SPI_rx_bufs.pa;
bcom_submit_next_buffer(rx_bcom, NULL);
bcom_enable(rx_bcom);
}
spin_unlock(&priv->dma_lock);
return IRQ_HANDLED;
};
static irqreturn_t SPI_tx_irq(int irq, void *dev_id) {
// no need for TaskIntClear(txtask), OS masks and acks IRQ
struct mpc52xx_spi_priv *priv = dev_id;
struct bcom_gen_bd *bd;
Node *node;
if(psc->mpc52xx_psc_status&0x1800) {
printk("PSC Reset\n");
psc->command = MPC52xx_PSC_RST_RX;
psc->command = MPC52xx_PSC_RST_TX;
psc->command = MPC52xx_PSC_SEL_MODE_REG_1;
psc->command = MPC52xx_PSC_RST_ERR_STAT;
psc->command = MPC52xx_PSC_TX_ENABLE | MPC52xx_PSC_RX_ENABLE;
};
spin_lock(&priv->dma_lock);
for(;;)
{
if(!bcom_buffer_done(tx_bcom)) {
break;
}
bcom_retrieve_buffer(tx_bcom, NULL, NULL);
/* Submit a new one */
bd = (struct bcom_gen_bd *) bcom_prepare_next_buffer(tx_bcom);
if (snd_SPImgt_running)
{
if((FirstNode == NULL)) {
bd->status = PERIODSIZE_HW;
bd->buf_pa = SPI_tx_silence.pa;
bcom_submit_next_buffer(tx_bcom, NULL);
if(hook_per_elap != NULL) {
hook_per_elap(SPI_pos, SPI_play);
}
}
else
{
node=FirstNode;
FirstNode=node->next;
if(FirstNode==NULL)LastNode=NULL;
bd->status = PERIODSIZE_HW;
bd->buf_pa = (void *)(((u32)node->buffer.pa));
bcom_submit_next_buffer(tx_bcom, NULL);
node->next=NULL;
if(LastNodeFree!=NULL)
LastNodeFree->next=node;
LastNodeFree=node;
if(FirstNodeFree==NULL)FirstNodeFree=LastNodeFree;
nodecounter--;
}
dmablockcounter++;
} else {
bd->status = PERIODSIZE_HW;
bd->buf_pa = SPI_tx_silence.pa;
bcom_submit_next_buffer(tx_bcom, NULL);
}
bcom_enable(tx_bcom);
}
spin_unlock(&priv->dma_lock);
return IRQ_HANDLED;
};
typedef struct {
unsigned short l;
unsigned short r;
} sample_t;
static int frame=0;
static Node *nodebuild;
static int counter =0;
static int *ptr=NULL;
int snd_SPI_pcm_copy(struct snd_pcm_substream *substream,
int voice,
snd_pcm_uframes_t pos,
void *src,
snd_pcm_uframes_t count) {
snd_pcm_uframes_t i;
// sample_t* data = (sample_t*) src;
UInteger32 *data = (UInteger32 *) src;
int cnt=count;
// unsigned short aux;
// printk("1.cnt %d, frame %d\n",cnt, frame);
while (cnt > 0)
{
counter++;
if(counter == 1000){
// printk("Frames: %d\n",nodecounter);
counter=0;
}
if(ptr==NULL)
{
if(FirstNodeFree != NULL)
{
nodebuild = FirstNodeFree;
FirstNodeFree = FirstNodeFree->next;
if(FirstNodeFree==NULL)LastNodeFree=NULL;
}
else
{
nodebuild = (Node *)kmalloc(sizeof(Node), GFP_KERNEL);
nodebuild->buffer.va = kmalloc(PERIODSIZE_HW, GFP_DMA);
nodebuild->buffer.pa = virt_to_phys((void *)nodebuild->buffer.va);
nodebuild->next=NULL;
// printk("Getting more Frames buffers, num of nodes %d\n",nodecounter);
}
ptr=(int *)nodebuild->buffer.va;
frame=0;
}
// printk("2.cnt %d, frame %d\n",cnt, frame);
if(cnt >= (FPP_HW -frame))
{
for(i=0;i<(FPP_HW-frame);i++) {
// printk(" 0x%04x ",data->l);
// printk(" 0x%04x ",data->r);
//Big Endian
// aux=((data->l>>8)&0xff)+((data->l << 8)&0xff00);
// *(ptr+(i*SLOTS)+(frame*SLOTS)) = (aux<<16);
// aux=((data->r>>8)&0xff)+((data->r << 8)&0xff00);
// *(ptr+(i*SLOTS)+(frame*SLOTS)+1) = (aux<<16);
//Little Endian
// *(ptr+(i*SLOTS)+(frame*SLOTS)) = (data->l<<16);
// *(ptr+(i*SLOTS)+(frame*SLOTS)+1) = (data->r<<16);
//Raw Data
// printk("src: 0x%08x\n", *(UInteger32 *)data);
*(ptr+i) = *(UInteger32 *)data;
data++;
};
cnt=cnt-(FPP_HW-frame);
frame=0;
ptr=NULL;
nodebuild->next=NULL;
if(LastNode != NULL) LastNode->next = nodebuild;
if(FirstNode == NULL) FirstNode = nodebuild;
LastNode = nodebuild;
nodecounter++;
// printk("3.cnt %d, frame %d\n",cnt, frame);
}
else
{
for(i=0;i<cnt;i++) {
// printk("%04x ",data->l);
// printk("%04x ",data->r);
//Big Endian
// aux=((data->l>>8)&0xff)+((data->l << 8)&0xff00);
// *(ptr+(i*SLOTS)+(frame*SLOTS)) = (aux<<16);
// aux=((data->r>>8)&0xff)+((data->r << 8)&0xff00);
// *(ptr+(i*SLOTS)+(frame*SLOTS)+1) = (aux<<16);
//Little Endian
// *(ptr+(i*SLOTS)+(frame*SLOTS)) = (data->l<<16);
// *(ptr+(i*SLOTS)+(frame*SLOTS)+1) = (data->r<<16);
//Raw Data
*(ptr+i) = *(UInteger32 *)data;
data++;
// printk("f\n");
}
frame=cnt+frame;
cnt=0;
// printk("4.cnt %d, frame %d\n",cnt, frame);
}
}
return 0;
};
EXPORT_SYMBOL(snd_SPI_pcm_copy);
static enum hrtimer_restart timer_funct (void *data) {
static unsigned int counter = 0;
static unsigned int start = 0;
UInteger32 framesnum;
static int diff=0;
counter = dmablockcounter*128;
dmablockcounter=0;
framesnum=hook_frames_rcv();
// printk("Frequenz=%d\n",framesnum);
if(snd_SPImgt_running){
diff=diff+counter-framesnum;
start=1;
}
else
{
start=0;
}
hrtimer_forward(&start_timer, hrtimer_cb_get_time(&start_timer),kt_timeup);
return HRTIMER_RESTART;
}
static void SPI_setup(void)
{
// printk("SPI_setup()\n");
int psc_num = 1, rv;
phys_addr_t rx_fifo;
phys_addr_t tx_fifo;
struct bcom_bd *bd;
struct mpc52xx_spi_priv *priv;
uint32 SICR;
struct mpc52xx_cdm __iomem *cdm;
priv = (struct mpc52xx_spi_priv *)kmalloc(sizeof(struct mpc52xx_spi_priv), GFP_KERNEL);
struct mpc52xx_gpio __iomem *gpio =
(struct mpc52xx_gpio __iomem *) MPC52xx_PA(MPC52xx_GPIO_OFFSET);
switch(psc_num) {
case 1:
initiator_tx = BCOM_INITIATOR_PSC1_TX;
initiator_rx = BCOM_INITIATOR_PSC1_RX;
break;
case 2:
initiator_tx = BCOM_INITIATOR_PSC2_TX;
initiator_rx = BCOM_INITIATOR_PSC2_RX;
break;
default:
panic("snd-SPImgt.o: invalid value for psc_num (%i)\n",psc_num);
break;
};
// printk("Before request mem region\n");
if (!request_mem_region(0xF0002000, 0x00000100, DRV_NAME)) {
printk(KERN_ERR DRV_NAME ": request_mem_region failed\n");
rv = -EBUSY;
}
// printk("Before ioremaps\n");
psc = ioremap(MPC52xx_PA(MPC52xx_PSCx_OFFSET(1)), MPC52xx_PSC_SIZE);
gpio = ioremap(MPC52xx_PA(MPC52xx_GPIO_OFFSET), MPC52xx_GPIO_SIZE);
cdm = ioremap(MPC52xx_PA(MPC52xx_CDM_OFFSET), MPC52xx_CDM_SIZE);
psc->tfdata = 0xF0010000; // Power-down [Table 1, MAX5712 Datasheet]
gpio->port_config |= PORT_CONFIG_PSC1;
cdm->clk_enables |= PSC1_CLK_EN;
cdm->mclken_div_psc1 = 0x8010;
rx_fifo = MPC52xx_PA(MPC52xx_PSCx_OFFSET(psc_num))+0x60;
tx_fifo = MPC52xx_PA(MPC52xx_PSCx_OFFSET(psc_num))+0x80;
spin_lock_init(&priv->dma_lock);
// printk("Before Tasks init\n");
rx_bcom = bcom_gen_bd_rx_init(2, (phys_addr_t)rx_fifo, initiator_rx, BCOM_IPR_PSC1_RX, 512);
tx_bcom = bcom_gen_bd_tx_init(8, (phys_addr_t)tx_fifo, initiator_tx, BCOM_IPR_PSC1_TX);
r_irq = bcom_get_task_irq(rx_bcom);
t_irq = bcom_get_task_irq(tx_bcom);
printk("r_irq %d 0x%08x t_irq %d 0x%08x, r_tasknum %d, t_tasknum %d\n", r_irq, r_irq, t_irq, t_irq, rx_bcom->tasknum, tx_bcom->tasknum);
psc->command = (MPC52xx_PSC_TX_DISABLE | MPC52xx_PSC_RX_DISABLE);
psc->command = MPC52xx_PSC_RST_RX;
psc->command = MPC52xx_PSC_RST_TX;
psc->command = MPC52xx_PSC_RST_ERR_STAT;
psc->op1 = 0x03;
udelay(10);
psc->op0 = 0x02;
udelay(50);
SICR = 0x0F90E000;
psc->command = 0x0A;
psc->sicr = SICR;
psc->ctur = 0x03;
psc->ctlr = 0x34;
psc->ccr = 0x070F0000;
psc->rfalarm = RX_ALARM;
psc->tfalarm = TX_ALARM;
psc->rfcntl = RX_GRAN;
psc->tfcntl = TX_GRAN;
psc->isr_imr.isr = 0x00;
psc->isr_imr.imr = 0x00;
psc->mode = 0x00; /* set RX interrupt to RxRDY */
psc->command = (MPC52xx_PSC_TX_ENABLE | MPC52xx_PSC_RX_ENABLE);
psc->tfdata = 0xF0010000; // Power-down [Table 1, MAX5712 Datasheet]
udelay(100);
psc->tfdata = 0xF0000000; // Wake-up [Table 1, MAX5712 Datasheet]
udelay(100);
// printk("Before request_irq's\n");
if (request_irq(r_irq, &SPI_rx_irq, /*IRQF_DISABLED*/0, "SPI rx dma", priv)) {
printk(KERN_ERR "SPI: SDMA rx irq allocation failed\n");
return;
}
if (request_irq(t_irq, &SPI_tx_irq, /*IRQF_DISABLED*/0, "SPI tx dma", priv)) {
printk(KERN_ERR "SPI: SDMA tx irq allocation failed\n");
return;
}
bcom_gen_bd_tx_reset(tx_bcom);
bcom_gen_bd_rx_reset(rx_bcom);
// printk("Before submitting a buffer\n");
spin_lock(&priv->dma_lock);
while (!bcom_queue_full(tx_bcom)) {
struct bcom_gen_bd *bd;
/* Submit a new one */
bd = (struct bcom_gen_bd *) bcom_prepare_next_buffer(tx_bcom);
bd->status = PERIODSIZE_HW;
bd->buf_pa = SPI_tx_silence.pa;
bcom_submit_next_buffer(tx_bcom, NULL);;
}
spin_unlock(&priv->dma_lock);
bd = bcom_prepare_next_buffer(rx_bcom);
bd->status = 512;
bd->data[0] = SPI_rx_bufs.pa;
bcom_submit_next_buffer(rx_bcom, (void *)SPI_rx_bufs.pa);
psc->command = MPC52xx_PSC_RST_RX;
psc->command = MPC52xx_PSC_RST_TX;
psc->command = MPC52xx_PSC_TX_ENABLE | MPC52xx_PSC_RX_ENABLE;
bcom_enable(tx_bcom);
bcom_enable(rx_bcom);
kt_timeup = timeval_to_ktime(tclockup);
kt_timedown = timeval_to_ktime(tclockdown);
hrtimer_init(&start_timer, CLOCK_REALTIME, HRTIMER_MODE_REL);
start_timer.function = timer_funct;
// printk("Before exit in Setup_SPI()\n");
}
void register_period_elapsed(void (*funcptr)()) {
/* printk("Function registered\n");*/
hook_per_elap = funcptr;
};
void register_hook_frames_rcv(UInteger32 (*funcptr)()) {
/* printk("Function registered\n");*/
hook_frames_rcv = funcptr;
hrtimer_start(&start_timer, kt_timeup, HRTIMER_MODE_REL);
};
int snd_SPI_pcm_prepare(struct snd_pcm_substream * substream) {
#ifdef SND_I2S_DEBUG
snd_pcm_runtime_t *runtime = substream->runtime;
printk("snd_I2Smgt_pcm_prepare\n");
printk(" runtime->buffer_size=%i\n",(int)runtime->buffer_size);
printk(" runtime->period_size=%i\n",(int)runtime->period_size);
printk(" runtime->periods=%i\n",(int)runtime->periods);
#endif
SPI_play = SPI_pos = 0;
return 0;
};
EXPORT_SYMBOL(register_period_elapsed);
EXPORT_SYMBOL(register_hook_frames_rcv);
EXPORT_SYMBOL(snd_SPI_pcm_prepare);
int SPIspeaker_init(void) {
SPI_buffers_init();
SPI_setup();
return 0;
}
void SPIspeaker_exit(void) {
/* Freeing buffer SPIspeaker */
if (SPI_rx_bufs.va) {
kfree(SPI_rx_bufs.va);
}
if (SPI_tx_silence.va) {
kfree(SPI_tx_silence.va);
}
}
module_init(SPIspeaker_init);
module_exit(SPIspeaker_exit);
MODULE_DESCRIPTION("MPC52xx SPI");
MODULE_AUTHOR("Pedro DomÃnguez,,,, ([EMAIL PROTECTED])");
MODULE_LICENSE("GPL");
_______________________________________________
Linuxppc-embedded mailing list
[email protected]
https://ozlabs.org/mailman/listinfo/linuxppc-embedded