This thread has been locked.

If you have a related question, please click the "Ask a related question" button in the top right corner. The newly created question will be automatically linked to this question.

mcbsp problem with external loopback uder linux

Other Parts Discussed in Thread: OMAPL138, OMAP3530

Hello,

I'm using the OMAPL138 board running Linux with mcbsp_test module.

when I run the:

insmod mcbsp_test.ko buf_size=512 num_pkts=3 master=1 tx_rx=3 dlb=1

its works fine (DLB=1) , I can see the incomming data. I'm using mcbsp1 since mcbsp0 used by LAN

But

when I try to run it with external wire loopback its fails (DR connected to DX ,FSR to FSX,CLKR to CLKX)

For doing this I have modife the mcbsp.c PCR register, so TX side will be master and RX side will be slave , in original mcbsp.c both RX and TX was configure as master.

I can see the DX,CLKX signals on scope but not the FSX ... I think this is why its not works, but I dont know how to make the FSX run

see below the code modification and the running results:

Code:

/**
 * davinci_mcbsp_config_pcr: Configure the Port Contorl Register
 * @dev: McBSP device pointer
 *
 * Called by the McBSP configuration fucntion to program the port as
 * inputs or outputs for master or slave operation
 */
static void davinci_mcbsp_config_pcr_shaul(struct davinci_mcbsp_dev *dev)
{
    u32 val = 0;

    if (dev->master == 1) //tx master
        val |= (CLKXM | FSXM);
    if (dev->master == 2) //rx master
        val |= (CLKRM | FSRM);
    if (dev->master == 3) //tx & rx master
        val |= (CLKXM | CLKRM | FSXM | FSRM);   
    if (dev->master == 0) //slave
        val |= SCLKME;

    davinci_mcbsp_write_reg(dev, MCBSP_PCR, val);
    if (dev->master == 0) {
        /* clock source from CLKR */
        val = davinci_mcbsp_read_reg(dev, MCBSP_SRGR);
        val &= ~CLKSM;
        davinci_mcbsp_write_reg(dev, MCBSP_SRGR, val);
    }
}

Monitor results:

(I have added some printk started with "shaul")

root@da850-omapl138-evm:/home/mcbsp# insmod mcbsp_test.ko buf_size=512 num_pkts=
3 master=1 tx_rx=3

Starting McBSP test
Request for McBSP1 sucessful
shaul davinci_mcbsp_config_pcr_shaul:value writen to MCBSP_PCR 2560(0xa00)
shaul davinci_mcbsp_config_clock:Clock rate is 150000000, Freq is 48000
shaul davinci_mcbsp_config_clock:The divider  value is 47(0x2f)
value written to SRGR is 303f002f
shaul:before davinci_mcbsp_config_fifo()
shaul:after davinci_mcbsp_config_fifo()
shaul:before davinci_mcbsp_config_multichannel_mode()
shaul:after davinci_mcbsp_config_multichannel_mode()
No DLB mode
Starting McBSP RX
shaul;davinci_mcbsp_start_rx:Configuring RX in master mode master=1
shaul:davinci_mcbsp_start_rx:Configuring RX in master mode
Transmitting Packet 1
Starting McBSP TX
shaul:davinci_mcbsp_start_tx:start master=1
shaul:davinci_mcbsp_start_tx:Configuring TX master mode
McBSP started
Receving data...
shaul:davinci_mcbsp_recv_buf:Triggering the receiver
shaul:davinci_mcbsp_trigger_rx:Configuring RX in master mode
shaul:davinci_mcbsp_recv_buf:--after--Triggering the receiver

Here its stack.

 

Did someone test the mcbsp_test with external loopback?

How to make FSX run?

Thanks

Shaul

  • Shaul,

    I would check on the following:

    1. PINMUX register has FSX configured as output master
    2. FSXM set in PCR to configure FSX as output
    3. For initial debug, FSGM cleared in SRGR so that a frame-sync is generated on every DXR-to-XSR copy

    -Tommy

  • Tommy thanks,


    I'll find the PINMUX in the linux and configure the FSR for output
    the PCR is configure properly

    I also find that the S7:2 on board should be ON to output the FSR other is for audio

    Shaul

     

  • Tommy,

    I found the place where to make the change

    arch/arm/mach-davinci/da850.c

    static const struct mux_config da850_pins[] = {

    .

    .

    .

        /* McBSP1 function */
        MUX_CFG(DA850,    MCBSP1_CLKR,    1,    4,    15,    2,    false)
        MUX_CFG(DA850,    MCBSP1_CLKX,    1,    8,    15,    2,    false)
        MUX_CFG(DA850,    MCBSP1_FSR,    1,    12,    15,    2,    false)
        MUX_CFG(DA850,    MCBSP1_FSX,    1,    16,    15,    2,    false)
        MUX_CFG(DA850,    MCBSP1_DR,    1,    20,    15,    2,    false)
        MUX_CFG(DA850,    MCBSP1_DX,    1,    24,    15,    2,    false)
        MUX_CFG(DA850,    MCBSP1_CLKS,    1,    28,    15,    2,    false)

     

    There is any explanation? what value should be writing for FSR/X to be output?

    Shaul

     

  • Shaul, See http://focus.ti.com/lit/ug/sprugm7d/sprugm7d.pdf Regards, Yair

  • Yair,

    According to this doc configuration is ok.

    all pins configured as mcbsp1 mode 2, PINMUX1

    /*
     * Device specific mux setup
     *
     *        soc  ;  description ;   mux reg   ; mode offset ;   mode mask ;   mux mode ;      dbg
                    
     */
    static const struct mux_config da850_pins[] = {
        /* McBSP1 function */
        MUX_CFG(DA850,    MCBSP1_CLKR,    1,    4,    15,    2,    false)
        MUX_CFG(DA850,    MCBSP1_CLKX,    1,    8,    15,    2,    false)
        MUX_CFG(DA850,    MCBSP1_FSR,    1,    12,    15,    2,    false)
        MUX_CFG(DA850,    MCBSP1_FSX,    1,    16,    15,    2,    false)
        MUX_CFG(DA850,    MCBSP1_DR,    1,    20,    15,    2,    false)
        MUX_CFG(DA850,    MCBSP1_DX,    1,    24,    15,    2,    false)
        MUX_CFG(DA850,    MCBSP1_CLKS,    1,    28,    15,    2,    false)

    Shaul

     

  • Shaul,

    Can you configure the FSX1 pin as GPIO0[3] output to see if you can toggle the signal through GPIO?  This would eliminate the possibility of some other contention on the board that we are not thinking of.

    -Tommy

  • Tommy,

    I can configure it as GP0[3] with PINMUX1, but to toggle it I'll need gpio driver.

    There is linux gpio driver for L138? 

    I'll try to find one ... or other way to toggle the pin ...if you have information on this please let me know

    Shaul

     

     

     

     

  • Shaul,

    I'm sure that somebody has done this already.  You can try the Linux forum: http://e2e.ti.com/support/embedded/f/354.aspx

    Otherwise, if you have a driver that lets you write values to internal addresses, you would only need to make a handful of register writes.

    -Tommy

  • Hello Shaul and TI support,

    I have been trying to do a wired loopback test of the mcbsp also. Thank you for posting this question to the forums, your work to date has been invaluable. 

    I can confirm that the mcbsp_test with dlb=1 works (for the parameters that you specified). I can also confirm that mcbsp_test does not work with a wired loopback plug and dlb=0 with the code changes you posted and with SW7:2 set to ON (for reference, this is using the DA850 EVM).

    I have done some work to verify that the pin is in fact being driven. I enabled GPIO0_3 by changing the pin mux and I also enabled the GPIO sysfs interface to control it from userspace.

    diff --git a/arch/arm/configs/helios-breadboard_defconfig b/arch/arm/configs/helios-breadboard_defco

    index ef5e3b5..f792fac 100644

    --- a/arch/arm/configs/helios-breadboard_defconfig

    +++ b/arch/arm/configs/helios-breadboard_defconfig

    @@ -1,7 +1,7 @@

     #

     # Automatically generated make config: don't edit

     # Linux kernel version: 2.6.33-rc4

    -# Fri Oct 15 17:15:15 2010

    +# Tue Oct 19 14:08:50 2010

     #

     CONFIG_ARM=y

     CONFIG_SYS_SUPPORTS_APM_EMULATION=y

    @@ -978,7 +978,7 @@ CONFIG_SPI_BITBANG=y

     CONFIG_ARCH_REQUIRE_GPIOLIB=y

     CONFIG_GPIOLIB=y

     # CONFIG_DEBUG_GPIO is not set

    -# CONFIG_GPIO_SYSFS is not set

    +CONFIG_GPIO_SYSFS=y

     

     #

     # Memory mapped GPIO expanders:

     

    diff --git a/arch/arm/mach-davinci/da850.c b/arch/arm/mach-davinci/da850.c

    index dff1bba..0a29e61 100755

    --- a/arch/arm/mach-davinci/da850.c

    +++ b/arch/arm/mach-davinci/da850.c

    @@ -629,6 +629,7 @@ static const struct mux_config da850_pins[] = {

            MUX_CFG(DA850,  MCBSP1_CLKX,    1,      8,      15,     2,      false)

            MUX_CFG(DA850,  MCBSP1_FSR,     1,      12,     15,     2,      false)

            MUX_CFG(DA850,  MCBSP1_FSX,     1,      16,     15,     2,      false)

    +       MUX_CFG(DA850,  GPIO0_3,        1,      16,     15,     8,      false)

            MUX_CFG(DA850,  MCBSP1_DR,      1,      20,     15,     2,      false)

            MUX_CFG(DA850,  MCBSP1_DX,      1,      24,     15,     2,      false)

            MUX_CFG(DA850,  MCBSP1_CLKS,    1,      28,     15,     2,      false)

    @@ -795,7 +796,7 @@ const short da850_mcbsp0_pins[] __initdata = {

     

     const short da850_mcbsp1_pins[] __initdata = {

            DA850_MCBSP1_CLKR, DA850_MCBSP1_CLKX, DA850_MCBSP1_FSR,

    -       DA850_MCBSP1_FSX, DA850_MCBSP1_DR, DA850_MCBSP1_DX, DA850_MCBSP1_CLKS,

    +       /* DA850_MCBSP1_FSX */ DA850_GPIO0_3, DA850_MCBSP1_DR, DA850_MCBSP1_DX, DA850_MCBSP1_CLKS,

            -1

     };

     

    diff --git a/arch/arm/mach-davinci/include/mach/mux.h b/arch/arm/mach-davinci/include/mach/mux.h

    index 51aac5b..3667bae 100644

    --- a/arch/arm/mach-davinci/include/mach/mux.h

    +++ b/arch/arm/mach-davinci/include/mach/mux.h

    @@ -927,6 +927,7 @@ enum davinci_da850_index {

            DA850_MCBSP1_CLKX,

            DA850_MCBSP1_FSR,

            DA850_MCBSP1_FSX,

    +       DA850_GPIO0_3,

            DA850_MCBSP1_DR,

            DA850_MCBSP1_DX,

            DA850_MCBSP1_CLKS,

     

     

    I commanded the driven value of the GPIO0_3 using the following commands in the console:

    cd /sys/class/gpio/

    echo 3 > export

    cd gpio3

    echo out > direction

    echo 0 > value

    echo 1 > value

    echo 0 >value

    With this, I confirmed that GPIO0_3 was being driven.

    I have also noticed when running the mcbsp_test module that FSX starts high and goes low immeadiately after the module is inserted but doesn't appear to get toggled at all as shaul has described.

    TI: What else can be attempted to get a successful wired loopback test of the McBSP?

  • Hello Ben,

    good works.

    In order to make it works I have done this steps:

    • Force the PINMUX register to use the FSX as mcbsp. it was configure as audio.
    • Change in the mcbsp.c  as mention above , TX master , RX salve
    • Make external loop back connection, SW7:2 on
    • Write Linux driver base on mcbsp_test.c
    • Write app from user that use the driver with two tasks:

                    1.      Receive task that wait for receive data , this task run first

                    2.      Sent task that send data to mcbsp , this task run after the receive task

    After that I can see the sending data and all signals on scope.

    You can't use the mcbsp_test as is for external loop back since you need to wait for receive before sending data the mcbsp_test don’t give you this option

    With two board the mcbsp_test ,I guess, will works fine.

    hope this help

    Shaul.


  • That helps alot. Thank you, Shaul.

    I would be interested in seeing the driver you wrote base on the mscbsp_test.c -- if you are able to provide the source.

    Thanks again.

  •  

    Hello Ben

    Please feel free to ask any quastion

    attach the driver mcbsp_drc.c and mcbsp_usr.c , driver and user app.

    *****  THIS DRIVER IS FOR DEBUG ONLY  , GIVEN FOR REFERENCE  ****

    instruction:

    Compile the mcbsp_drv.c , this make mcbsp.ko

    mknod -m 666 /dev/mcbsp_drv c 123 0

    insmod mcbsp_drv.ko

    compile the mcbsp_usr.c   for begin use ioctl 55 this will output the TX sync ,data and clk and you can see it on scope

    ./mcbsp_usr &

     

    Terminal reports:

     _____                    _____           _         _  
    |  _  |___ ___ ___ ___   |  _  |___ ___  |_|___ ___| |_
    |     |  _| .'| . | . |  |   __|  _| . | | | -_|  _|  _|
    |__|__|_| |__,|_  |___|  |__|  |_| |___|_| |___|___|_| 
                  |___|                    |___|           

    Arago Project http://arago-project.org da850-omapl138-evm ttyS2

    Arago 2009.11 da850-omapl138-evm ttyS2

    da850-omapl138-evm login: root
    root@da850-omapl138-evm:~# mknod -m 666 /dev/mcbsp_drv c 123 0
    root@da850-omapl138-evm:~# cd /home/mcbsp/
    root@da850-omapl138-evm:/home/mcbsp# insmod mcbsp_drv.ko
    mcbsp_drv registering init start...
     reg_read_pinmux1 orig  = 0x22222220
     reg_read_pinmux1 after = 0x22222220
    mcbsp_drv: registering module successfuly!
    Request for McBSP1 sucessful
    root@da850-omapl138-evm:/home/mcbsp#

     

     

     

    Driver: mcbsp_drv.c

    #include <linux/module.h>
    #include <linux/kernel.h>   
    #include <linux/moduleparam.h>
    #include <linux/fs.h>
    #include <linux/gfp.h>
    #include <linux/cdev.h>
    #include <linux/sched.h>
    #include <linux/proc_fs.h>
    #include <linux/ioctl.h>
    #include <linux/mm.h>

    #include <linux/errno.h>
    #include <linux/interrupt.h>
    #include <linux/sched.h>
    #include <asm/uaccess.h>
    #include <asm/io.h>


    // for mcbsp
    #include <mach/memory.h>
    #include <mach/hardware.h>
    #include <mach/irqs.h>
    #include <mach/edma.h>
    #include <mach/mcbsp.h>

    #include <linux/init.h>
    #include <linux/types.h>
    #include <linux/io.h>
    #include <linux/sysctl.h>
    #include <linux/dma-mapping.h>
    #include <linux/delay.h>

    /* Register offset macros */
    #define MCBSP_DRR    (0x00)
    #define MCBSP_DXR    (0x04)
    #define MCBSP_SPCR    (0x08)
    #define MCBSP_RCR    (0x0C)
    #define MCBSP_XCR    (0x10)
    #define MCBSP_SRGR    (0x14)
    #define MCBSP_MCR    (0x18)
    #define MCBSP_RCER0    (0x1C)
    #define MCBSP_XCER0    (0x20)
    #define MCBSP_PCR    (0x24)
    #define MCBSP_RCER1    (0x28)
    #define MCBSP_XCER1    (0x2C)
    #define MCBSP_RCER2    (0x30)
    #define MCBSP_XCER2    (0x34)
    #define MCBSP_RCER3    (0x38)
    #define MCBSP_XCER3    (0x3C)
    #define MCBSP_WFIFOCTL    (0x810)
    #define MCBSP_WFIFOSTS    (0x814)
    #define MCBSP_RFIFOCTL    (0x818)
    #define MCBSP_RFIFOSTS    (0x81C)

    /* Register bit definitions */

    /* SPCR */

    #define FRST        BIT(23)
    #define GRST        BIT(22)
    #define XINTM_MASK    (BIT(21) | BIT(20))
    #define XSYNCERR    BIT(19)
    #define XEMPTY        BIT(18)
    #define XRDY        BIT(17)
    #define    XRST        BIT(16)
    #define DLB        BIT(15)
    #define RJUST_MASK    (BIT(14) | BIT(13))
    #define CLKSTP_MASK    (BIT(12) | BIT(11))
    #define DXENA        BIT(7)
    #define    RINTM_MASK    (BIT(5) | BIT(4))
    #define RSYNCERR    BIT(3)
    #define RFULL        BIT(2)
    #define RRDY        BIT(1)
    #define RRST        BIT(0)

    #define    RINTM(value)    (value << 4)
    #define CLKSTP(value)    (value << 11)
    #define RJUST(value)    (value << 13)
    #define XINTM(value)    (value << 20)

    /* PCR */

    #define FSXM        BIT(11)
    #define FSRM        BIT(10)
    #define CLKXM        BIT(9)
    #define CLKRM        BIT(8)
    #define SCLKME        BIT(7)
    #define FSXP        BIT(3)
    #define FSRP        BIT(2)
    #define CLKXP        BIT(1)
    #define CLKRP        BIT(0)

    /* RCR / XCR */

    #define PHASE        BIT(31)
    #define FRLEN2(value)    (value << 24)
    #define WDLEN2(value)    (value << 21)
    #define COMPAND(value)    (value << 19)
    #define FIG        BIT(18)
    #define DATDLY(value)    (value << 16)
    #define FRLEN1(value)    (value << 8)
    #define WDLEN1(value)    (value << 5)
    #define WDREVRS        BIT(4)

    /* SRGR */
    /*
     * 31        30    29    28    27 16    15 8    7 0
     * GSYNC    CLKSP    CLKSM    FSGM    FPER    FWID    CLKGDV
     * RW, +0    RW, +0    RW    RW, +0    RW, +0    RW, +0    RW
     *
     */

    #define GSYNC        BIT(31)
    #define CLKSP        BIT(30)
    #define CLKSM        BIT(29)
    #define    FSGM        BIT(28)
    #define    FPER(value)    (value << 16)
    #define    FWID(value)    (value << 8)
    #define CLKGDV(value)    (value)
    #define CLKGDV_MASK    (0xff)

    /* MCR */

    #define XMCME        BIT(25)
    #define XPBBLK(value)    (value << 23)
    #define XPABLK(value)    (value << 21)
    #define XCBLK        (BIT(20) | BIT(19) | BIT(18))
    #define XMCM(value)    (value << 16)
    #define RMCME        BIT(9)
    #define RPBBLK(value)    (value << 7)
    #define RPABLK(value)    (value << 5)
    #define RCBLK        (BIT(4) | BIT(3) | BIT(2))
    #define RMCM        BIT(0)
    #define XMCM_MASK    (BIT(16) | BIT(17))

    /* WFIFOCTL / RFIFOCTL */
    #define FIFOEN        BIT(16)
    #define NUMEVT(value)    (value << 8)
    #define NUMDMA(value)    (value)
    #define NUMEVT_MASK    (0xff << 8)
    #define NUMDMA_MASK    0xff

    /* WFIFOSTS / RFIFOSTS */
    #define LVL_MASK    0xff

    #define NUM_MCBSP_INSTANCES 2

    u32 val;

    void delay_i(int i)
    {
          int c,r=0;
            printk("delay ...\n");
            for(c=0;c<i*1000;c++)
          r++;
        printk(" r=%d \n",r);
    }

    static struct davinci_mcbsp_dev *mcbsp[NUM_MCBSP_INSTANCES];

    static inline void davinci_mcbsp_write_reg(struct davinci_mcbsp_dev *dev,
                           int reg, u32 val)
    {
        writel(val, dev->io_base + reg);
    }

    static inline u32 davinci_mcbsp_read_reg(struct davinci_mcbsp_dev *dev, int reg)
    {
        return readl(dev->io_base + reg);
    }


    static dma_addr_t mcbsp_physsrc = 0;
    static char *mcbsp_bufsrc = NULL;
    static dma_addr_t mcbsp_physdest = 0;
    static char *mcbsp_bufdest = NULL;

    static int device_id = 1;
    static int mcbsp_buf_size = (1 * 1024);  // 8
    //static int buf_fmt = 0;
    //static int num_pkts = 1;
    static int word_len = 32;
    static int frame_len = 2;
    static int freq = 480;
    static bool dlb = 1;
    static int numevt = 0;
    static int mc_mode = 0;
    static int master = 3;
    static int tx_rx = 3;

    struct davinci_mcbsp_dev *dev = NULL;
    int i;
    int loopcnt = 0;
    int errcnt;


    #define PHY_IO_ADD 0xb0000
    #define HW_STATUS_REGS_ADD 0x30000000
    #define HW_STATUS_REGS_SIZE 1024
    #define HW_BUF_SIZE 1024
    #define MCBSP_DRV_MAJOR 123


    struct file_operations mcbsp_drv_fops;

    static void *buffer;
    static int buf_size = 1024;


    static int *buffer_pinmux1;


    static ssize_t
    mcbsp_drv_read(struct file *file, char __user *buf,size_t count,loff_t *ppos)
    {
       int remaining_bytes,i;
       remaining_bytes = min(buf_size - (int) (*ppos), (int) count);
      
       if (remaining_bytes == 0)
          return 0;
         
        printk("mcbsp_drv_read:Receving data...\n");
           *ppos += remaining_bytes;
          printk("mcbsp_drv_read:memcopy...\n");
          memcpy((char*)buf,(char*)mcbsp_bufdest,count);
          memset((char*)mcbsp_bufdest, 0 , count);

          for( i=0;i<count;i++){
        printk("mcbsp_drv_read:mcbsp_bufdest[%d] = %d \n",i,mcbsp_bufdest[i]);
        printk("mcbsp_drv_read:buf[%d] = %d \n",i,buf[i]);
          }

          return remaining_bytes;
    }

    static ssize_t
    mcbsp_drv_write(struct file *file1,const char __user *buf,size_t count,loff_t *ppos)
    {
      int remaining_bytes,i;
       remaining_bytes = buf_size - (*ppos);
       printk("mcbsp_drv_write:buffer = 0x%x ; count=0x%x ; *ppos+buffer (write address).  = 0x%x\n",buffer,count,*ppos+buffer);
     
       if (count > remaining_bytes)
       return -EIO;

          printk("mcbsp_drv_write:memcopy...\n");
          memcpy((char*)mcbsp_bufsrc,(char*)buf,count);
          for( i=0;i<count;i++){
        printk("mcbsp_drv_write:mcbsp_bufsrc[%d] = %d\n",i,mcbsp_bufsrc[i]);
        printk("mcbsp_drv_write:buf[%d] = %d \n",i,buf[i]);
          }
       
           *ppos += count;
          printk("write successfully from process=%s",current->comm);
          return count;
    }




    static int mcbsp_drv_ioctl(struct inode *inode,struct file*file,unsigned int cmd,unsigned long arg)
    {

        int reg_read_pinmux1;
        int i;
        switch (cmd)
        {
            case 4: // word_length1
            printk("mcbsp_drv: mcbsp_drv_ioctl word_length1 \n");
                 dev->tx_params.word_length1 = arg; //word_len; /* 32 bits */
                 dev->rx_params.word_length1 = arg; //word_len; /* 32 bits */
                    break;
            case 5: // frame_length1         
            printk("mcbsp_drv: mcbsp_drv_ioctl frame_length1 \n");
                dev->tx_params.frame_length1 = arg; // frame_len;
                dev->rx_params.frame_length1 = arg; // frame_len;
                    break;
            case 6: // freq
            printk("mcbsp_drv: mcbsp_drv_ioctl sample rate \n");
                /* sample rate generator conifguration */
            davinci_mcbsp_config_clock(dev, freq);
                    break;
            case 7: // DLB
            printk("mcbsp_drv: mcbsp_drv_ioctl DLB mode \n");
                  if (arg == 1) {
                printk("Setting DLB mode \n");
                dlb = 1;
                dev->op_mode |= DAVINCI_MCBSP_DLB_MODE;
                } else {
                printk("No DLB mode \n");
                dlb = 0;
                    }
                    break;
               
            case 8:
            printk("mcbsp_drv: mcbsp_drv_ioctl12  cmd=%u arg=%lu\n",cmd,arg);
            printk("master=%lu \n",arg);
            master=arg;     
            break;
          
             
            case 9:
               printk("mcbsp_drv: mcbsp_drv_ioctl genral configuration cmd=%u arg=%lu \n",cmd,arg);
                  dev->tx_params.word_length1 = word_len; /* 32 bits */
                  dev->tx_params.frame_length1 = frame_len;

                  dev->rx_params.word_length1 = word_len; /* 32 bits */
                  dev->rx_params.frame_length1 = frame_len;
                 
                  dev->rx_params.buf_fmt = 0;
                  dev->tx_params.buf_fmt = 0;
                  davinci_mcbsp_config_params(dev, master);
                  /* sample rate generator conifguration */
                  davinci_mcbsp_config_clock(dev, freq);
                  dev->tx_params.numevt = numevt;
                  dev->rx_params.numevt = numevt;
                  dev->tx_params.numdma = 1;
                  dev->rx_params.numdma = 1;
                  davinci_mcbsp_config_fifo(dev);
                  printk("mcbsp_drv: mcbsp_drv_ioctl genral configuratio:davinci_mcbsp_config_fifo after\n");
                  dev->tx_params.mc_mode = mc_mode;
                  dev->rx_params.mc_mode = mc_mode;
                 
        
                  dev->tx_params.cer[0] = 0x5555;
                  dev->tx_params.cer[1] = 0x5555;
                  dev->tx_params.cer[2] = 0x5555;
                  dev->tx_params.cer[3] = 0x5555;
                  dev->tx_params.cer[4] = 0x5555;
                  dev->tx_params.cer[5] = 0x5555;
                  dev->tx_params.cer[6] = 0x5555;
                  dev->tx_params.cer[7] = 0x5555;

                  dev->rx_params.cer[0] = 0x5555;
                  dev->rx_params.cer[1] = 0x5555;
                  dev->rx_params.cer[2] = 0x5555;
                  dev->rx_params.cer[3] = 0x5555;
                  dev->rx_params.cer[4] = 0x5555;
                  dev->rx_params.cer[5] = 0x5555;
                  dev->rx_params.cer[6] = 0x5555;
                  dev->rx_params.cer[7] = 0x5555;

                  davinci_mcbsp_config_multichannel_mode(dev);
                  printk("mcbsp_drv: mcbsp_drv_ioctl genral configuration:davinci_mcbsp_config_multichannel_mode after\n");
                 
                  /* DMA Mode */
                  dev->op_mode = DAVINCI_MCBSP_DMA_MODE;
                 
                  break;
                 
             case 20:    
                printk("Starting McBSP TX\n");
                davinci_mcbsp_start_tx(dev);
                break;
             case 21:   
                printk("Starting McBSP RX\n");
                davinci_mcbsp_start_rx(dev);
                break;
             case 30:   
                printk("Receving data...\n");
                davinci_mcbsp_recv_buf(dev, mcbsp_physdest, mcbsp_buf_size);
                break;
             case 31:   
                printk("Transmitting data...\n");
                davinci_mcbsp_xmit_buf(dev, mcbsp_physsrc, mcbsp_buf_size);
                break;
             case 40:   
                wait_for_completion(&dev->tx_params.dma_completion);
                printk("...TX complete\n");
                break;
             case 41:   
                wait_for_completion(&dev->rx_params.dma_completion);
                printk("...RX complete\n");
                break;
             case 50:
                davinci_mcbsp_stop_tx(dev);
                printk("TX stopped\n");
                break;
             case 51:   
                davinci_mcbsp_stop_rx(dev);
                printk("RX stopped\n");
                break;
             case 60:   
                for( i=0;i<mcbsp_buf_size;i++){
                printk("mcbsp_drv: mcbsp_drv_ioctl genral configuration::mcbsp_bufdest[%d] = %d \n",i,mcbsp_bufdest[i]);
                }
            break;   
               
                           

               
        case 55:   
            printk("case 55:  sending data:\n");
            printk("write data to MCBSP_DXR \n");
            davinci_mcbsp_write_reg(dev, MCBSP_DXR, 0x81818181);
            /* configure rcr and xcr */
            dev->tx_params.word_length1 = word_len; /* 32 bits */
            dev->tx_params.frame_length1 = frame_len;
            dev->rx_params.word_length1 = word_len; /* 32 bits */
            dev->rx_params.frame_length1 = frame_len;
            dev->rx_params.buf_fmt = 0;
            dev->tx_params.buf_fmt = 0;
                davinci_mcbsp_config_params_shaul(dev, master);

        // step 1  ,int  , step 1 done in the init module function
        // step 2  ,reset  ,
            val = davinci_mcbsp_read_reg(dev, MCBSP_SPCR);
            val &= (~FRST &  ~GRST & ~XRST & ~RRST);
            davinci_mcbsp_write_reg(dev, MCBSP_SPCR, val);
             printk(" **** step 2: MCBSP_PCR ****:\n");
            davinci_mcbsp_dump_reg_shaul(dev);       
        // step 3 need to be complete ....
            /* configure rcr and xcr */
            dev->tx_params.word_length1 = word_len; /* 32 bits */
            dev->tx_params.frame_length1 = frame_len;

            dev->rx_params.word_length1 = word_len; /* 32 bits */
            dev->rx_params.frame_length1 = frame_len;

            dev->rx_params.buf_fmt = 0;
            dev->tx_params.buf_fmt = 0;
                //davinci_mcbsp_config_params_shaul(dev, master);
            // FSGM
            val = davinci_mcbsp_read_reg(dev, MCBSP_SRGR);
            val |= FSGM;
            davinci_mcbsp_write_reg(dev, MCBSP_SRGR, val);
            // pin configuration
            val = davinci_mcbsp_read_reg(dev, MCBSP_SPCR);       
            val |= (CLKXM | FSXM);
            davinci_mcbsp_write_reg(dev, MCBSP_PCR, val);
            /* sample rate generator conifguration */
            davinci_mcbsp_config_clock(dev, freq);

             printk(" **** step 3: MCBSP_PCR pin configuration, FSGM(28 SRGS),clk ****:\n");
            davinci_mcbsp_dump_reg_shaul(dev);
           
        // step 4 ,internal clk ,
            delay_i(50000);
            /* clock source from internal  */
            val = davinci_mcbsp_read_reg(dev, MCBSP_SRGR);
            val |= CLKSM;  // CLKSM = 1
            davinci_mcbsp_write_reg(dev, MCBSP_SRGR, val);       
            printk(" **** step 4: MCBSP_PCR , MCBSP_SRGR ,CLKSM = 1, SCLKME = 0****:\n");
            davinci_mcbsp_dump_reg_shaul(dev);
        // step 5 , clk enable
            val = davinci_mcbsp_read_reg(dev, MCBSP_SPCR);
            val |= GRST; // GRST = 1
            davinci_mcbsp_write_reg(dev, MCBSP_SPCR, val);
                   delay_i(50000);
            printk(" **** step 5: MCBSP_SPCR ,GRST= 1  ****:\n");
            davinci_mcbsp_dump_reg_shaul(dev);
        // step 6 ,  clear sync error
            val = davinci_mcbsp_read_reg(dev, MCBSP_SPCR);
            val |= XRST; // XRST = 1
            davinci_mcbsp_write_reg(dev, MCBSP_SPCR, val);
                   delay_i(50000);
            val &= ~XRST; // XRST = 0
            davinci_mcbsp_write_reg(dev, MCBSP_SPCR, val);
            printk(" **** step 6: MCBSP_SPCR ,XRST 1 -> 0 ****:\n");
            davinci_mcbsp_dump_reg_shaul(dev);
        // step 7 , n/a
        // step 8 , enable transmit
            val = davinci_mcbsp_read_reg(dev, MCBSP_SPCR);
            val |= (XRST | RRST); // XRST = 1 , RRST = 1
            davinci_mcbsp_write_reg(dev, MCBSP_SPCR, val);
                   delay_i(50000);
                printk("write data to MCBSP_DXR \n");
            davinci_mcbsp_write_reg(dev, MCBSP_DXR, 0x81818181);
            printk(" **** step 8:  MCBSP_SPCR ,XRST = 1 , RRST = 1 ****:\n");
            davinci_mcbsp_dump_reg_shaul(dev);
        // step 9 , n/a   
        // step 10 , n/a   
        // step 11 , enable transmit
            val = davinci_mcbsp_read_reg(dev, MCBSP_SPCR);
            val |= FRST; // FRST = 1
            davinci_mcbsp_write_reg(dev, MCBSP_SPCR, val);
            printk(" **** step 11:  MCBSP_SPCR ,FRST = 1 ****:\n");
            davinci_mcbsp_dump_reg_shaul(dev);
           
        // step 12 , write data
                printk("write data to MCBSP_DXR \n");
            davinci_mcbsp_write_reg(dev, MCBSP_DXR, 0x81818181);
       
            break;
            default:
                return 0;
        }
       

    return 0;
    }


    static int
    mcbsp_drv_init (void)
    {

        int ret,i;
        int reg_read_pinmux1;
       
        printk("mcbsp_drv registering init start... \n");
        ret = register_chrdev(MCBSP_DRV_MAJOR,"mcbsp_drv",&mcbsp_drv_fops); /* this make the connection to sudo mknod -m 666 /dev/mcbsp_drv c 123 0    */
        if (ret < 0){
                printk("Error registering mcbsp_drv device \n");
                goto mcbsp_drv_fail1;
               }   
        // make sure you configure as mcbsp
        buffer_pinmux1 =ioremap(0x01c14124,0x64);
        reg_read_pinmux1 = *buffer_pinmux1;
         printk(" reg_read_pinmux1 orig  = 0x%x \n",reg_read_pinmux1);
             *buffer_pinmux1  = reg_read_pinmux1 | 0x22220000;  //mode 2 MCBSP
         reg_read_pinmux1 = *buffer_pinmux1;
         printk(" reg_read_pinmux1 after = 0x%x \n",reg_read_pinmux1);
          
         printk ("mcbsp_drv: registering module successfuly! \n");

         mcbsp_bufsrc = dma_alloc_coherent(NULL, mcbsp_buf_size, &mcbsp_physsrc, 0);
         if (!mcbsp_bufsrc) {
             printk ("dma_alloc_coherent failed for physsrc\n");
            return -ENOMEM;
        }
       
            for (i = 0; i < mcbsp_buf_size; i++)
                mcbsp_bufsrc[i] = (i % 256) * 3;
       
        mcbsp_bufdest = dma_alloc_coherent(NULL, mcbsp_buf_size, &mcbsp_physdest, 0);
        if (!mcbsp_bufdest) {
            printk ("dma_alloc_coherent failed for physdest\n");
            return -ENOMEM;
        }

             davinci_mcbsp_request(device_id, &dev);
         return 0;

        mcbsp_drv_fail1:
            return ret;           

    }


    static void
    mcbsp_drv_cleanup (void)
    {
        printk("mcbsp_drv device exit \n");
    }


    static int
    mcbsp_drv_open (struct inode *inode,struct file *file)
    {
        printk("mcbsp_drv device open \n");
         return 0;
    }



    static int
    mcbsp_drv_release (struct inode *inode,struct file *file)
    {
        printk("mcbsp_drv device release \n");
        davinci_mcbsp_free(device_id);
         return 0;
    }

    struct file_operations mcbsp_drv_fops =
    {
        owner:   THIS_MODULE,
        read:    mcbsp_drv_read,
        write:   mcbsp_drv_write,
        ioctl:   mcbsp_drv_ioctl,
        open:    mcbsp_drv_open,
        release: mcbsp_drv_release,
    };


    module_init (mcbsp_drv_init);
    module_exit (mcbsp_drv_cleanup);
    MODULE_LICENSE("GPL");
    MODULE_AUTHOR("Shaul Yafee");
    MODULE_DESCRIPTION("MCBSP Driver");

     

     

     

     

    mcbsp_usr.c

    #include <stdio.h>   /* Standard input/output definitions */
    #include <string.h>  /* String function definitions */
    #include <unistd.h>  /* UNIX standard function definitions */
    #include <fcntl.h>   /* File control definitions */
    #include <errno.h>   /* Error number definitions */
    #include <termios.h> /* POSIX terminal control definitions */
    #include <sys/ioctl.h>

    #include <resolv.h>

    #include <pthread.h>

    void delay_i(int i);
    int thread_RX_Func (void);
    int thread_TX_Func (void);

    int fd_mcbsp;
    int len, write_len;
    char string[128] = "UUUUUUUU";
    char receive[128];

     int main(int argc, char * argv[] )
    {
         pthread_t thread_RX,thread_TX;
    long t ;

            // open device
        fd_mcbsp = open("/dev/mcbsp_drv", O_RDWR | O_SYNC );
        if (fd_mcbsp == -1)printf("mcbsp_usr:open_mcbsp: Unable to open /dev/mcbsp_control_char \n");
         else     printf("mcbsp_usr:open_mcbsp: open /dev/mcbsp_control_char success \n");
         
        // ioctl
    //    ioctl(fd_mcbsp,0,1); // test
    //        delay_i(1000);   
    //s    ioctl(fd_mcbsp,4,8); //  word_length1
    //s        delay_i(1000);   
    //s    ioctl(fd_mcbsp,5,2); //  frame_len
    //s        delay_i(1000);
    //s    ioctl(fd_mcbsp,55,0); //  frame_len

    //#if 0
        ioctl(fd_mcbsp,8,1); // master = 3
            delay_i(1000);
        ioctl(fd_mcbsp,9,0); // configuration
            delay_i(1000);
        ioctl(fd_mcbsp,7,0); // DLB
        ioctl(fd_mcbsp,17,0); // read regs
    //#endif

        // shaul, next lines for test only don't use for threads   
    //#if 0
        ioctl(fd_mcbsp,20,0); // Starting McBSP TX
        ioctl(fd_mcbsp,17,0); // read regs
        ioctl(fd_mcbsp,31,0); // Transmitting data...
    //#endif


    //#if 0   
    if( pthread_create(&thread_RX, NULL, thread_RX_Func,  (void *)t) ) {
            printf("Thread creation thread_main_print_Id was not successful \n");
        }
      delay_i(30000);
    if( pthread_create(&thread_TX, NULL, thread_TX_Func,  (void *)t) ) {
            printf("Thread creation thread_pri_print_Id was not successful \n");
        }
       
        pthread_join(thread_RX,NULL);
        pthread_join(thread_TX,NULL);
    //#endif   
           // close device
      close(fd_mcbsp);
    return(0);
    }
       
    void delay_i(int i)
    {
          int c,r=0;
            printf("delay ...\n");
            for(c=0;c<i*1000;c++)
          r++;
        printf(" r=%d \n",r);
    }

    int thread_RX_Func()
    {
        int i;

        printf("thread_RX_Func:enter \n"); 
       
        ioctl(fd_mcbsp,21,0); // Starting McBSP RX
        delay_i(1);
     
        ioctl(fd_mcbsp,30,0); // Receving data...
           
        // read device     
        len = read(fd_mcbsp, receive, 8);
        if( len == -1 )
        {
                    printf("mcbsp_usr:read error...\n");
                    return(1);
        }
       
            printf("mcbsp_usr:String '%s' read from /dev/mcbsp_control_char len = %d\n", receive,len);
        for( i=0;i<len;i++)
          printf("mcbsp_usr:receive[%d] = %d \n",i,receive[i]);

        ioctl(fd_mcbsp,51,0); // RX stopped

        printf("thread_RX_Func:exit \n");
    }

    int thread_TX_Func ()
    {
          
        printf("thread_TX_Func:enter \n"); 
           
            // write device
            write_len = strlen(string) + 1;
            len = write(fd_mcbsp, string, write_len);
        printf(" write len = 0x%x    \n",len);
            if( len == -1 )
        {
                    printf("mcbsp_usr:write error...\n");
                    return(1);
            }

          ioctl(fd_mcbsp,20,0); // Starting McBSP TX
        ioctl(fd_mcbsp,17,0); // read regs
        ioctl(fd_mcbsp,31,0); // Transmitting data...
    //    ioctl(fd_mcbsp,50,0); // TX stopped
       
        printf("thread_TX_Func:exit \n");
    }

     

     

    shaul

     

  • How can i find mcbsp_test.c ?

  •  

    You can find it  :  DaVinci-PSP-SDK-03.20.00.11/src/examples/mcbsp

     

    Shaul

     

  • Hi shaul

    Is it possible to port this mcbsp driver for OMAP3?

    I need the same mcbsp device driver. Does it work well? or maybe you have a new version.

    Thanks

    Eyal

  • Hi,

    Thanks to Eyal for sharing the davinci mcbsp driver code with us. Were you  finally been able to wirite an mcbsp-dma chardevice in OMAP3530?

    I was also looking into the possibility of writing a 'mcbsp with dma' linux driver for omap3530. I have only started the driver part, but, I am stuck up in the idea of how could I 'blockingly' do read mcbsp with dma irq.

    I did look into /sound/soc/omap/omap-mcbsp.c which is the sound driver for omap3530(it used mcbsp1 and dma). But I am totally confused. TI was nice to package a mcbsp sample driver with the davici PSP. I wish omap3530 also had a similar mcbsp sample driver.

     

    Thanks

    Ajit