All of lore.kernel.org
 help / color / mirror / Atom feed
* ASoC: BeagleBoard driver development (PCM3168)
@ 2013-02-10 21:50 wendelin klimann
  2013-02-11 13:49 ` Peter Ujfalusi
  0 siblings, 1 reply; 11+ messages in thread
From: wendelin klimann @ 2013-02-10 21:50 UTC (permalink / raw)
  To: alsa-devel

hello

I try to implement an PCM3168 audio codec from TI to the BeagleBoard but
actually i am stuck and it would be rally nice if one could help me a
little bit.
My ALSA driver version is 1.0.24 and i use an 3.2.18 kernel.
As a startingpoint i used the files

*/linux-mainline-3.2.18-r121b/git/sound/soc/codecs/pcm3008.c*
*/linux-mainline-3.2.18-r121b/git/sound/soc/codecs/pcm3008.h*


The files                   (see end of e-mail)

*/linux-mainline-3.2.18-r121b/git/sound/soc/omap/pcm3168_soundcard.c
/linux-mainline-3.2.18-r121b/git/sound/soc/codecs/pcm3168.c
/linux-mainline-3.2.18-r121b/git/sound/soc/codecs/pcm3168.h*

could be compiled successfully and also the insmod loads the modules

*$: insmod
/lib/modules/3.2.18/kernel/sound/soc/omap/snd-soc-pcm3168_soundcard.ko*

*$: lsmod*
Module                  Size  Used by
snd_soc_pcm3168         1886  0
snd_soc_pcm3168_soundcard     2094  0
twl4
030_madc_hwmon      2569  0
snd_soc_omap3beagle     2239  0
rtc_twl                 4382  0
snd_soc_twl4030        37616  1
rtc_ds1307              6642  0
snd_soc_omap            3521  1
snd_soc_omap_mcbsp      8374  1
snd_soc_core          107346  6
snd_soc_pcm3168,snd_soc_pcm3168_soundcard,snd_soc_omap3beagle,snd_soc_twl4030,snd_soc_omap,snd_soc_omap_mcbsp
regmap_spi              1263  1 snd_soc_core
snd_pcm                78039  4
snd_soc_twl4030,snd_soc_omap,snd_soc_omap_mcbsp,snd_soc_core
snd_timer              18848  1 snd_pcm
snd                    57930  3 snd_soc_core,snd_pcm,snd_timer
soundcore               6954  1 snd
iptable_nat             3819  0
snd_page_alloc          4979  1 snd_pcm
nf_nat                 16515  1 iptable_nat
nf_conntrack_ipv4      12018  3 iptable_nat,nf_nat
nf_conntrack           71219  3 iptable_nat,nf_nat,nf_conntrack_ipv4
nf_defrag_ipv4          1379  1 nf_conntrack_ipv4
ip_tables              10537  1 iptable_nat
x_tables               16505  2 iptable_nat,ip_tables
gpio_keys               7117  0
autofs4                20492  2

but the new ALSA device is not recognized

*$:aplay -l*
**** List of PLAYBACK Hardware Devices ****
card 0: omap3beagle [omap3beagle], device 0: TWL4030 twl4030-hifi-0 []
  Subdevices
: 1/1
  Subdevice #0: subdevice #0

So i tried to get some information in

*$: cd /sys/kernel/debug/asoc*

*/sys/kernel/debug/asoc$: ls*
codecs       dais         omap3beagle  pcm3168      platforms

*/sys/kernel/debug/asoc$: cat codecs*
pcm3168-codec.0
twl4030-codec

*/sys/kernel/debug/asoc$: cat dais*
pcm3168-hifi
twl4030-voice
twl4030-hifi
omap-mcbsp-dai.4
omap-mcbsp-dai.3
omap-mcbsp-dai.2
omap-mcbsp-dai.1
omap-mcbsp-dai.0

*/sys/kernel/debug/asoc$: cat platforms*
omap-pcm-audio
snd-soc-dummy

*/sys/kernel/debug/asoc$:cd omap3beagle*

*/sys/kernel/debug/asoc/omap3beagle$:ls*
dapm           dapm_pop_time  twl4030-codec

*/sys/kernel/debug/asoc/omap3beagle$:cd /sys/kernel/debug/asoc/pcm3168*

*/sys/kernel/debug/asoc/pcm3168$: ls*
dapm_pop_time


At this point i have no idea how to solve the problem or how to debug
further and i would be very grateful for any hint.

Thanks a lot
Wendelin




*
***********************************************************************************************
*
/linux-mainline-3.2.18-r121b/git/sound/soc/omap/pcm3168_soundcard.c
*
**
***********************************************************************************************

*/*
 * PCM3168 ASoC driver for BeagleBoard.
 *
 * Author:    Hugo Villeneuve
 * Copyright (C) 2008 Lyrtech inc
 *
 * adapted by Klimann Wendelin <wklimann@hotmail.com>
 *
 *
 * Based on ASoC driver for TI DAVINCI EVM platform, original copyright
follow:
 * Copyright:   (C) 2007 MontaVista Software, Inc., <source@mvista.com>
 *
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License version 2 as
 * published by the Free Software Foundation.
 */

#include <linux/clk.h>
#include <linux/platform_device.h>
#include <linux/module.h>
#include <linux/moduleparam.h>
#include <linux/timer.h>
#include <linux/interrupt.h>
#include <linux/platform_device.h>
#include <linux/gpio.h>
#include <sound/core.h>
#include <sound/pcm.h>
#include <sound/pcm_params.h>
#include <sound/soc.h>
#include <sound/soc-dapm.h>

#include <asm/mach-types.h>
//#include <asm/dma.h>
#include <mach/hardware.h>
#include <mach/gpio.h>
//#include <mach/edma.h>
#include <plat/mcbsp.h>

#include "omap-mcbsp.h"
#include "omap-pcm.h"

#include "../codecs/pcm3168.h"

/*
 * CLKX and CLKR are the inputs for the Sample Rate Generator.
 * FSX and FSR are outputs, driven by the sample Rate Generator.
 */
/*
 * SND_SOC_DAIFMT_CBS_CFS
 * for codec in slave mode
 */
#define AUDIO_FORMAT (SND_SOC_DAIFMT_DSP_B |    \
              SND_SOC_DAIFMT_CBM_CFM |    \
              SND_SOC_DAIFMT_IB_NF)

static int pcm3168_hw_params(struct snd_pcm_substream *substream,
                struct snd_pcm_hw_params *params)
{
    struct snd_soc_pcm_runtime *rtd = substream->private_data;
    struct snd_soc_dai *cpu_dai = rtd->cpu_dai;
    int fs;
    int ret = 0;


printk("in hw_params -> by kli");


    /* Fsref can be 8000 to 96000. */
    fs = params_rate(params);

    /* set cpu DAI configuration */
    ret = snd_soc_dai_set_fmt(cpu_dai, AUDIO_FORMAT);
    if (ret < 0) {
        printk(KERN_ERR "can't set cpu DAI configuration\n");
        return ret;
    }

    pr_debug("pcm3168_hw_params: rate = %d Hz\n", fs);

    return 0;
}

static struct snd_soc_ops pcm3168_ops = {
    .hw_params = pcm3168_hw_params,
};

/* omap-pcm3168 digital audio interface glue - connects codec <--> CPU */
static struct snd_soc_dai_link pcm3168_dai = {
    .name = "PCM3168",  /* Codec name */
    .stream_name = "PCM3168",
    .cpu_dai_name = "omap-mcbsp-dai.2",
    .codec_dai_name = "pcm3168-hifi",
    .codec_name = "pcm3168-codec",
    .platform_name = "omap-pcm-audio",
    .ops = &pcm3168_ops,
};

/* omap-pcm3168 audio machine driver */
static struct snd_soc_card snd_soc_pcm3168 = {
    .name = "pcm3168",                      // -> "OMAP pcm3168"
    .owner = THIS_MODULE,
    .dai_link = &pcm3168_dai,
    .num_links = 1,
};

/* pcm3168 audio private data */
static struct pcm3168_setup_data pcm3168_pcm3168_setup = {
//    .dem0_pin = GPIO(45),
//    .dem1_pin = GPIO(46),
//    .pdad_pin = GPIO(47),
//    .pdda_pin = GPIO(38),
};

struct platform_device pcm3168_codec = {
        .name = "pcm3168-codec",
        .id = 0,
        .dev = {
                .platform_data = &pcm3168_pcm3168_setup,
        },
};



static struct platform_device *pcm3168_snd_device;

static int __init pcm3168_init(void)
{
    int ret;

printk(KERN_ALERT "in init soundcard \n");

    if (!(machine_is_omap3_beagle()))
        return -ENODEV;

    platform_device_register(&pcm3168_codec);

    pcm3168_snd_device = platform_device_alloc("soc-audio", 0);
    if (!pcm3168_snd_device) {
        printk(KERN_ERR "platform device allocation failed\n");
        return -ENOMEM;
    }

    platform_set_drvdata(pcm3168_snd_device, &snd_soc_pcm3168);
//    platform_device_add_data(pcm3168_snd_device, &pcm3168_snd_data,
//                 sizeof(pcm3168_snd_data));

/*    ret = platform_device_add_resources(pcm3168_snd_device,
                        pcm3168_snd_resources,
                        ARRAY_SIZE(pcm3168_snd_resources));
    if (ret) {
        printk(KERN_ERR "platform device add resources failed\n");
        goto error;
    }
*/
    ret = platform_device_add(pcm3168_snd_device);
    if (ret)
        goto error;

    return ret;

error:
    platform_device_put(pcm3168_snd_device);
    return ret;
}

static void __exit pcm3168_exit(void)
{
    platform_device_unregister(pcm3168_snd_device);
    platform_device_unregister(&pcm3168_codec);
}

module_init(pcm3168_init);
module_exit(pcm3168_exit);

MODULE_AUTHOR("Klimann Wendelin <wklimann@hotmail.com>");
MODULE_DESCRIPTION("PCM3168 Beagle ASoC driver");
MODULE_LICENSE("GPL");
MODULE_ALIAS("platform:pcm3168-soc-audio");




*
***********************************************************************************************
*
/linux-mainline-3.2.18-r121b/git/sound/soc/codecs/pcm3168.c
   *
**
***********************************************************************************************

*/*
 * ALSA Soc PCM3168 codec support
 *
 * Author:    Hugo Villeneuve
 * Copyright (C) 2008 Lyrtech inc
 *
 * adapted by Klimann Wendelin
 *
 *
 * Based on AC97 Soc codec, original copyright follow:
 * Copyright 2005 Wolfson Microelectronics PLC.
 *
 *  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.
 *
 * Generic PCM3168 support.
 */

#include <linux/init.h>
#include <linux/kernel.h>
#include <linux/device.h>
#include <linux/gpio.h>
#include <linux/slab.h>
#include <linux/module.h>
#include <linux/clk.h>
#include <linux/platform_device.h>
#include <linux/module.h>
#include <sound/core.h>
#include <sound/initval.h>
#include <sound/pcm.h>
#include <sound/pcm_params.h>
//#include <sound/soc-dapm.h>
#include <sound/soc.h>

#include <asm/mach-types.h>
#include <mach/hardware.h>
#include <mach/gpio.h>
#include <plat/mcbsp.h>

#include "../omap/omap-mcbsp.h"
#include "../omap/omap-pcm.h"

#include "pcm3168.h"



#define PCM3168_VERSION "0.1"

#define PCM3168_RATES   SNDRV_PCM_RATE_8000_96000 /*(SNDRV_PCM_RATE_32000 |
SNDRV_PCM_RATE_44100 |    \
               SNDRV_PCM_RATE_48000)*/

static struct snd_soc_dai_driver pcm3168_dai = {

    .name = "pcm3168-hifi",
    .playback = {
        .stream_name = "PCM3168 Playback",
        .channels_min = 2,
        .channels_max = 8,
        .rates = PCM3168_RATES,
        .formats = SNDRV_PCM_FMTBIT_S16_LE, //SNDRV_PCM_FMTBIT_S32_LE
    },
    .capture = {
        .stream_name = "PCM3168 Capture",
        .channels_min = 2,
        .channels_max = 6,
        .rates = PCM3168_RATES,
        .formats = SNDRV_PCM_FMTBIT_S16_LE, //SNDRV_PCM_FMTBIT_S32_LE
    },
};

static void pcm3168_gpio_free(struct pcm3168_setup_data *setup)
{
//    gpio_free(setup->dem0_pin);
//    gpio_free(setup->dem1_pin);
//    gpio_free(setup->pdad_pin);
//    gpio_free(setup->pdda_pin);
}

static int pcm3168_soc_probe(struct snd_soc_codec *codec)
{
    struct pcm3168_setup_data *setup = codec->dev->platform_data;
    int ret = 0;

printk(KERN_ALERT "in SOC Probe -> kli \n");

    printk(KERN_INFO "PCM3168 SoC Audio Codec %s\n", PCM3168_VERSION);

    return ret;

gpio_err:
//    pcm3168_gpio_free(setup);

    return ret;
}

static int pcm3168_soc_remove(struct snd_soc_codec *codec)
{
    struct pcm3168_setup_data *setup = codec->dev->platform_data;

//    pcm3168_gpio_free(setup);
    return 0;
}


#define pcm3168_soc_suspend NULL
#define pcm3168_soc_resume NULL


static struct snd_soc_codec_driver soc_codec_dev_pcm3168 = {
    .probe =     pcm3168_soc_probe,
    .remove =     pcm3168_soc_remove,
    .suspend =    pcm3168_soc_suspend,
    .resume =    pcm3168_soc_resume,
};

static int __devinit pcm3168_codec_probe(struct platform_device *pdev)
{
    int ret;
    printk(KERN_ALERT "probe pcm3168 -> kli \n");

    ret = snd_soc_register_codec(&pdev->dev,
            &soc_codec_dev_pcm3168, &pcm3168_dai, 1);

    printk(KERN_ALERT "probe_after pcm3168 -> kli = %d \n", ret);

    return ret;
}

static int __devexit pcm3168_codec_remove(struct platform_device *pdev)
{
    printk(KERN_ALERT "remove pcm3168 -> kli \n");

    snd_soc_unregister_codec(&pdev->dev);
    return 0;
}

MODULE_ALIAS("platform:pcm3168-codec");

static struct platform_driver pcm3168_codec_driver = {
    .probe        = pcm3168_codec_probe,
    .remove        = __devexit_p(pcm3168_codec_remove),
    .driver        = {
    .name        = "pcm3168-codec",
    .owner        = THIS_MODULE,
    },
};

static int __init pcm3168_modinit(void)
{
    printk(KERN_ALERT "in init of 3168 -> kli \n");
    return platform_driver_register(&pcm3168_codec_driver);
}
module_init(pcm3168_modinit);

static void __exit pcm3168_exit(void)
{
    printk(KERN_ALERT "in exit of 3168 -> kli \n");
    platform_driver_unregister(&pcm3168_codec_driver);
}
module_exit(pcm3168_exit);

MODULE_DESCRIPTION("Soc PCM3168 driver");
MODULE_AUTHOR("Klimann Wendelin <wklimann@hotmail.com>");
MODULE_LICENSE("GPL");


*
***********************************************************************************************
*
/linux-mainline-3.2.18-r121b/git/sound/soc/codecs/pcm3168.h
    *
***********************************************************************************************
*

/*
 * PCM3168 ALSA SoC Layer
 *
 * Author:    Hugo Villeneuve
 * Copyright (C) 2008 Lyrtech inc
 *
 * adapted by Klimann Wendelin <wklimann@hotmail.com>
 *
 *
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License version 2 as
 * published by the Free Software Foundation.
 */

#ifndef __LINUX_SND_SOC_PCM3168_2_H
#define __LINUX_SND_SOC_PCM3168_2_H

struct pcm3168_setup_data {
//    unsigned dem0_pin;
//    unsigned dem1_pin;
//    unsigned pdad_pin;
//    unsigned pdda_pin;
};

#endif

^ permalink raw reply	[flat|nested] 11+ messages in thread

* Re: ASoC: BeagleBoard driver development (PCM3168)
  2013-02-10 21:50 ASoC: BeagleBoard driver development (PCM3168) wendelin klimann
@ 2013-02-11 13:49 ` Peter Ujfalusi
  2013-02-16 12:05   ` wendelin klimann
  0 siblings, 1 reply; 11+ messages in thread
From: Peter Ujfalusi @ 2013-02-11 13:49 UTC (permalink / raw)
  To: wendelin klimann; +Cc: alsa-devel

Hi,

On 02/10/2013 10:50 PM, wendelin klimann wrote:
> hello
> 
> I try to implement an PCM3168 audio codec from TI to the BeagleBoard but
> actually i am stuck and it would be rally nice if one could help me a
> little bit.
> My ALSA driver version is 1.0.24 and i use an 3.2.18 kernel.
> As a startingpoint i used the files
> 
> */linux-mainline-3.2.18-r121b/git/sound/soc/codecs/pcm3008.c*
> */linux-mainline-3.2.18-r121b/git/sound/soc/codecs/pcm3008.h*
> 
> 
> The files                   (see end of e-mail)
> 
> */linux-mainline-3.2.18-r121b/git/sound/soc/omap/pcm3168_soundcard.c
> /linux-mainline-3.2.18-r121b/git/sound/soc/codecs/pcm3168.c
> /linux-mainline-3.2.18-r121b/git/sound/soc/codecs/pcm3168.h*
> 
> could be compiled successfully and also the insmod loads the modules
> 
> *$: insmod
> /lib/modules/3.2.18/kernel/sound/soc/omap/snd-soc-pcm3168_soundcard.ko*
> 
> *$: lsmod*
> Module                  Size  Used by
> snd_soc_pcm3168         1886  0
> snd_soc_pcm3168_soundcard     2094  0
> twl4
> 030_madc_hwmon      2569  0
> snd_soc_omap3beagle     2239  0
> rtc_twl                 4382  0
> snd_soc_twl4030        37616  1
> rtc_ds1307              6642  0
> snd_soc_omap            3521  1
> snd_soc_omap_mcbsp      8374  1
> snd_soc_core          107346  6
> snd_soc_pcm3168,snd_soc_pcm3168_soundcard,snd_soc_omap3beagle,snd_soc_twl4030,snd_soc_omap,snd_soc_omap_mcbsp
> regmap_spi              1263  1 snd_soc_core
> snd_pcm                78039  4
> snd_soc_twl4030,snd_soc_omap,snd_soc_omap_mcbsp,snd_soc_core
> snd_timer              18848  1 snd_pcm
> snd                    57930  3 snd_soc_core,snd_pcm,snd_timer
> soundcore               6954  1 snd
> iptable_nat             3819  0
> snd_page_alloc          4979  1 snd_pcm
> nf_nat                 16515  1 iptable_nat
> nf_conntrack_ipv4      12018  3 iptable_nat,nf_nat
> nf_conntrack           71219  3 iptable_nat,nf_nat,nf_conntrack_ipv4
> nf_defrag_ipv4          1379  1 nf_conntrack_ipv4
> ip_tables              10537  1 iptable_nat
> x_tables               16505  2 iptable_nat,ip_tables
> gpio_keys               7117  0
> autofs4                20492  2
> 
> but the new ALSA device is not recognized
> 
> *$:aplay -l*
> **** List of PLAYBACK Hardware Devices ****
> card 0: omap3beagle [omap3beagle], device 0: TWL4030 twl4030-hifi-0 []
>   Subdevices
> : 1/1
>   Subdevice #0: subdevice #0
> 
> So i tried to get some information in
> 
> *$: cd /sys/kernel/debug/asoc*
> 
> */sys/kernel/debug/asoc$: ls*
> codecs       dais         omap3beagle  pcm3168      platforms
> 
> */sys/kernel/debug/asoc$: cat codecs*
> pcm3168-codec.0
> twl4030-codec
> 
> */sys/kernel/debug/asoc$: cat dais*
> pcm3168-hifi
> twl4030-voice
> twl4030-hifi
> omap-mcbsp-dai.4
> omap-mcbsp-dai.3
> omap-mcbsp-dai.2
> omap-mcbsp-dai.1
> omap-mcbsp-dai.0
> 
> */sys/kernel/debug/asoc$: cat platforms*
> omap-pcm-audio
> snd-soc-dummy
> 
> */sys/kernel/debug/asoc$:cd omap3beagle*
> 
> */sys/kernel/debug/asoc/omap3beagle$:ls*
> dapm           dapm_pop_time  twl4030-codec
> 
> */sys/kernel/debug/asoc/omap3beagle$:cd /sys/kernel/debug/asoc/pcm3168*
> 
> */sys/kernel/debug/asoc/pcm3168$: ls*
> dapm_pop_time
> 
> 
> At this point i have no idea how to solve the problem or how to debug
> further and i would be very grateful for any hint.
> 
> Thanks a lot
> Wendelin
> 
> 
> 
> 
> *
> ***********************************************************************************************
> *
> /linux-mainline-3.2.18-r121b/git/sound/soc/omap/pcm3168_soundcard.c
> *
> **
> ***********************************************************************************************
> 
> */*
>  * PCM3168 ASoC driver for BeagleBoard.
>  *
>  * Author:    Hugo Villeneuve
>  * Copyright (C) 2008 Lyrtech inc
>  *
>  * adapted by Klimann Wendelin <wklimann@hotmail.com>
>  *
>  *
>  * Based on ASoC driver for TI DAVINCI EVM platform, original copyright
> follow:
>  * Copyright:   (C) 2007 MontaVista Software, Inc., <source@mvista.com>
>  *
>  * This program is free software; you can redistribute it and/or modify
>  * it under the terms of the GNU General Public License version 2 as
>  * published by the Free Software Foundation.
>  */
> 
> #include <linux/clk.h>
> #include <linux/platform_device.h>
> #include <linux/module.h>
> #include <linux/moduleparam.h>
> #include <linux/timer.h>
> #include <linux/interrupt.h>
> #include <linux/platform_device.h>
> #include <linux/gpio.h>
> #include <sound/core.h>
> #include <sound/pcm.h>
> #include <sound/pcm_params.h>
> #include <sound/soc.h>
> #include <sound/soc-dapm.h>
> 
> #include <asm/mach-types.h>
> //#include <asm/dma.h>
> #include <mach/hardware.h>
> #include <mach/gpio.h>
> //#include <mach/edma.h>
> #include <plat/mcbsp.h>
> 
> #include "omap-mcbsp.h"
> #include "omap-pcm.h"
> 
> #include "../codecs/pcm3168.h"
> 
> /*
>  * CLKX and CLKR are the inputs for the Sample Rate Generator.
>  * FSX and FSR are outputs, driven by the sample Rate Generator.
>  */
> /*
>  * SND_SOC_DAIFMT_CBS_CFS
>  * for codec in slave mode
>  */
> #define AUDIO_FORMAT (SND_SOC_DAIFMT_DSP_B |    \
>               SND_SOC_DAIFMT_CBM_CFM |    \
>               SND_SOC_DAIFMT_IB_NF)
> 
> static int pcm3168_hw_params(struct snd_pcm_substream *substream,
>                 struct snd_pcm_hw_params *params)
> {
>     struct snd_soc_pcm_runtime *rtd = substream->private_data;
>     struct snd_soc_dai *cpu_dai = rtd->cpu_dai;
>     int fs;
>     int ret = 0;
> 
> 
> printk("in hw_params -> by kli");
> 
> 
>     /* Fsref can be 8000 to 96000. */
>     fs = params_rate(params);
> 
>     /* set cpu DAI configuration */
>     ret = snd_soc_dai_set_fmt(cpu_dai, AUDIO_FORMAT);
>     if (ret < 0) {
>         printk(KERN_ERR "can't set cpu DAI configuration\n");
>         return ret;
>     }
> 
>     pr_debug("pcm3168_hw_params: rate = %d Hz\n", fs);
> 
>     return 0;
> }
> 
> static struct snd_soc_ops pcm3168_ops = {
>     .hw_params = pcm3168_hw_params,
> };
> 
> /* omap-pcm3168 digital audio interface glue - connects codec <--> CPU */
> static struct snd_soc_dai_link pcm3168_dai = {
>     .name = "PCM3168",  /* Codec name */
>     .stream_name = "PCM3168",
>     .cpu_dai_name = "omap-mcbsp-dai.2",

Are you sure you connect the codec to McBSP2?
If so I think it is better to disable the omap-twl4030 driver, but it should
not cause problems if you have it, just make sure you are not running the two
card at the same time.

>     .codec_dai_name = "pcm3168-hifi",
>     .codec_name = "pcm3168-codec",

codec name should be: pcm3168-codec.0

>     .platform_name = "omap-pcm-audio",
>     .ops = &pcm3168_ops,
> };
> 
> /* omap-pcm3168 audio machine driver */
> static struct snd_soc_card snd_soc_pcm3168 = {
>     .name = "pcm3168",                      // -> "OMAP pcm3168"
>     .owner = THIS_MODULE,
>     .dai_link = &pcm3168_dai,
>     .num_links = 1,
> };
> 
> /* pcm3168 audio private data */
> static struct pcm3168_setup_data pcm3168_pcm3168_setup = {
> //    .dem0_pin = GPIO(45),
> //    .dem1_pin = GPIO(46),
> //    .pdad_pin = GPIO(47),
> //    .pdda_pin = GPIO(38),
> };
> 
> struct platform_device pcm3168_codec = {
>         .name = "pcm3168-codec",
>         .id = 0,
>         .dev = {
>                 .platform_data = &pcm3168_pcm3168_setup,
>         },
> };
> 
> 
> 
> static struct platform_device *pcm3168_snd_device;
> 
> static int __init pcm3168_init(void)
> {
>     int ret;
> 
> printk(KERN_ALERT "in init soundcard \n");
> 
>     if (!(machine_is_omap3_beagle()))
>         return -ENODEV;
> 
>     platform_device_register(&pcm3168_codec);
> 
>     pcm3168_snd_device = platform_device_alloc("soc-audio", 0);
>     if (!pcm3168_snd_device) {
>         printk(KERN_ERR "platform device allocation failed\n");
>         return -ENOMEM;
>     }
> 
>     platform_set_drvdata(pcm3168_snd_device, &snd_soc_pcm3168);
> //    platform_device_add_data(pcm3168_snd_device, &pcm3168_snd_data,
> //                 sizeof(pcm3168_snd_data));
> 
> /*    ret = platform_device_add_resources(pcm3168_snd_device,
>                         pcm3168_snd_resources,
>                         ARRAY_SIZE(pcm3168_snd_resources));
>     if (ret) {
>         printk(KERN_ERR "platform device add resources failed\n");
>         goto error;
>     }
> */
>     ret = platform_device_add(pcm3168_snd_device);
>     if (ret)
>         goto error;
> 
>     return ret;
> 
> error:
>     platform_device_put(pcm3168_snd_device);
>     return ret;
> }

You should update you machine driver to use snd_soc_register_card() see other
machine drivers as example (omap-twl4030.c is in the same directory for
example and it is really simple).



> 
> static void __exit pcm3168_exit(void)
> {
>     platform_device_unregister(pcm3168_snd_device);
>     platform_device_unregister(&pcm3168_codec);
> }
> 
> module_init(pcm3168_init);
> module_exit(pcm3168_exit);
> 
> MODULE_AUTHOR("Klimann Wendelin <wklimann@hotmail.com>");
> MODULE_DESCRIPTION("PCM3168 Beagle ASoC driver");
> MODULE_LICENSE("GPL");
> MODULE_ALIAS("platform:pcm3168-soc-audio");
> 
> 
> 
> 
> *
> ***********************************************************************************************
> *
> /linux-mainline-3.2.18-r121b/git/sound/soc/codecs/pcm3168.c
>    *
> **
> ***********************************************************************************************
> 
> */*
>  * ALSA Soc PCM3168 codec support
>  *
>  * Author:    Hugo Villeneuve
>  * Copyright (C) 2008 Lyrtech inc
>  *
>  * adapted by Klimann Wendelin
>  *
>  *
>  * Based on AC97 Soc codec, original copyright follow:
>  * Copyright 2005 Wolfson Microelectronics PLC.
>  *
>  *  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.
>  *
>  * Generic PCM3168 support.
>  */
> 
> #include <linux/init.h>
> #include <linux/kernel.h>
> #include <linux/device.h>
> #include <linux/gpio.h>
> #include <linux/slab.h>
> #include <linux/module.h>
> #include <linux/clk.h>
> #include <linux/platform_device.h>
> #include <linux/module.h>
> #include <sound/core.h>
> #include <sound/initval.h>
> #include <sound/pcm.h>
> #include <sound/pcm_params.h>
> //#include <sound/soc-dapm.h>
> #include <sound/soc.h>
> 
> #include <asm/mach-types.h>
> #include <mach/hardware.h>
> #include <mach/gpio.h>
> #include <plat/mcbsp.h>
> 
> #include "../omap/omap-mcbsp.h"
> #include "../omap/omap-pcm.h"
> 
> #include "pcm3168.h"
> 
> 
> 
> #define PCM3168_VERSION "0.1"
> 
> #define PCM3168_RATES   SNDRV_PCM_RATE_8000_96000 /*(SNDRV_PCM_RATE_32000 |
> SNDRV_PCM_RATE_44100 |    \
>                SNDRV_PCM_RATE_48000)*/
> 
> static struct snd_soc_dai_driver pcm3168_dai = {
> 
>     .name = "pcm3168-hifi",
>     .playback = {
>         .stream_name = "PCM3168 Playback",
>         .channels_min = 2,
>         .channels_max = 8,
>         .rates = PCM3168_RATES,
>         .formats = SNDRV_PCM_FMTBIT_S16_LE, //SNDRV_PCM_FMTBIT_S32_LE
>     },
>     .capture = {
>         .stream_name = "PCM3168 Capture",
>         .channels_min = 2,
>         .channels_max = 6,
>         .rates = PCM3168_RATES,
>         .formats = SNDRV_PCM_FMTBIT_S16_LE, //SNDRV_PCM_FMTBIT_S32_LE
>     },
> };
> 
> static void pcm3168_gpio_free(struct pcm3168_setup_data *setup)
> {
> //    gpio_free(setup->dem0_pin);
> //    gpio_free(setup->dem1_pin);
> //    gpio_free(setup->pdad_pin);
> //    gpio_free(setup->pdda_pin);
> }
> 
> static int pcm3168_soc_probe(struct snd_soc_codec *codec)
> {
>     struct pcm3168_setup_data *setup = codec->dev->platform_data;
>     int ret = 0;
> 
> printk(KERN_ALERT "in SOC Probe -> kli \n");
> 
>     printk(KERN_INFO "PCM3168 SoC Audio Codec %s\n", PCM3168_VERSION);
> 
>     return ret;
> 
> gpio_err:
> //    pcm3168_gpio_free(setup);
> 
>     return ret;
> }
> 
> static int pcm3168_soc_remove(struct snd_soc_codec *codec)
> {
>     struct pcm3168_setup_data *setup = codec->dev->platform_data;
> 
> //    pcm3168_gpio_free(setup);
>     return 0;
> }
> 
> 
> #define pcm3168_soc_suspend NULL
> #define pcm3168_soc_resume NULL
> 
> 
> static struct snd_soc_codec_driver soc_codec_dev_pcm3168 = {
>     .probe =     pcm3168_soc_probe,
>     .remove =     pcm3168_soc_remove,
>     .suspend =    pcm3168_soc_suspend,
>     .resume =    pcm3168_soc_resume,
> };
> 
> static int __devinit pcm3168_codec_probe(struct platform_device *pdev)
> {
>     int ret;
>     printk(KERN_ALERT "probe pcm3168 -> kli \n");
> 
>     ret = snd_soc_register_codec(&pdev->dev,
>             &soc_codec_dev_pcm3168, &pcm3168_dai, 1);
> 
>     printk(KERN_ALERT "probe_after pcm3168 -> kli = %d \n", ret);
> 
>     return ret;
> }
> 
> static int __devexit pcm3168_codec_remove(struct platform_device *pdev)
> {
>     printk(KERN_ALERT "remove pcm3168 -> kli \n");
> 
>     snd_soc_unregister_codec(&pdev->dev);
>     return 0;
> }
> 
> MODULE_ALIAS("platform:pcm3168-codec");
> 
> static struct platform_driver pcm3168_codec_driver = {
>     .probe        = pcm3168_codec_probe,
>     .remove        = __devexit_p(pcm3168_codec_remove),
>     .driver        = {
>     .name        = "pcm3168-codec",
>     .owner        = THIS_MODULE,
>     },
> };

According to the datasheet the PCM3168 have I2C or SPI control interface. You
should have the driver as i2c/spi device so you can actually control it.

> 
> static int __init pcm3168_modinit(void)
> {
>     printk(KERN_ALERT "in init of 3168 -> kli \n");
>     return platform_driver_register(&pcm3168_codec_driver);
> }
> module_init(pcm3168_modinit);
> 
> static void __exit pcm3168_exit(void)
> {
>     printk(KERN_ALERT "in exit of 3168 -> kli \n");
>     platform_driver_unregister(&pcm3168_codec_driver);
> }
> module_exit(pcm3168_exit);
> 
> MODULE_DESCRIPTION("Soc PCM3168 driver");
> MODULE_AUTHOR("Klimann Wendelin <wklimann@hotmail.com>");
> MODULE_LICENSE("GPL");
> 
> 
> *
> ***********************************************************************************************
> *
> /linux-mainline-3.2.18-r121b/git/sound/soc/codecs/pcm3168.h
>     *
> ***********************************************************************************************
> *
> 
> /*
>  * PCM3168 ALSA SoC Layer
>  *
>  * Author:    Hugo Villeneuve
>  * Copyright (C) 2008 Lyrtech inc
>  *
>  * adapted by Klimann Wendelin <wklimann@hotmail.com>
>  *
>  *
>  * This program is free software; you can redistribute it and/or modify
>  * it under the terms of the GNU General Public License version 2 as
>  * published by the Free Software Foundation.
>  */
> 
> #ifndef __LINUX_SND_SOC_PCM3168_2_H
> #define __LINUX_SND_SOC_PCM3168_2_H
> 
> struct pcm3168_setup_data {
> //    unsigned dem0_pin;
> //    unsigned dem1_pin;
> //    unsigned pdad_pin;
> //    unsigned pdda_pin;
> };
> 
> #endif
> _______________________________________________
> Alsa-devel mailing list
> Alsa-devel@alsa-project.org
> http://mailman.alsa-project.org/mailman/listinfo/alsa-devel
> 


-- 
Péter

^ permalink raw reply	[flat|nested] 11+ messages in thread

* Re: ASoC: BeagleBoard driver development (PCM3168)
  2013-02-11 13:49 ` Peter Ujfalusi
@ 2013-02-16 12:05   ` wendelin klimann
  2013-02-19 11:10     ` Peter Ujfalusi
  0 siblings, 1 reply; 11+ messages in thread
From: wendelin klimann @ 2013-02-16 12:05 UTC (permalink / raw)
  To: Peter Ujfalusi; +Cc: alsa-devel

Hello and thanks for the support!

2013/2/11 Peter Ujfalusi <peter.ujfalusi@ti.com>

> Hi,
>
> On 02/10/2013 10:50 PM, wendelin klimann wrote:
> > hello
> >
> > I try to implement an PCM3168 audio codec from TI to the BeagleBoard but
> > actually i am stuck and it would be rally nice if one could help me a
> > little bit.
> > My ALSA driver version is 1.0.24 and i use an 3.2.18 kernel.
> > As a startingpoint i used the files
> >
> > */linux-mainline-3.2.18-r121b/git/sound/soc/codecs/pcm3008.c*
> > */linux-mainline-3.2.18-r121b/git/sound/soc/codecs/pcm3008.h*
> >
> >
> > The files                   (see end of e-mail)
> >
> > */linux-mainline-3.2.18-r121b/git/sound/soc/omap/pcm3168_soundcard.c
> > /linux-mainline-3.2.18-r121b/git/sound/soc/codecs/pcm3168.c
> > /linux-mainline-3.2.18-r121b/git/sound/soc/codecs/pcm3168.h*
> >
> > could be compiled successfully and also the insmod loads the modules
> >
> > *$: insmod
> > /lib/modules/3.2.18/kernel/sound/soc/omap/snd-soc-pcm3168_soundcard.ko*
> >
> > *$: lsmod*
> > Module                  Size  Used by
> > snd_soc_pcm3168         1886  0
> > snd_soc_pcm3168_soundcard     2094  0
> > twl4
> > 030_madc_hwmon      2569  0
> > snd_soc_omap3beagle     2239  0
> > rtc_twl                 4382  0
> > snd_soc_twl4030        37616  1
> > rtc_ds1307              6642  0
> > snd_soc_omap            3521  1
> > snd_soc_omap_mcbsp      8374  1
> > snd_soc_core          107346  6
> >
> snd_soc_pcm3168,snd_soc_pcm3168_soundcard,snd_soc_omap3beagle,snd_soc_twl4030,snd_soc_omap,snd_soc_omap_mcbsp
> > regmap_spi              1263  1 snd_soc_core
> > snd_pcm                78039  4
> > snd_soc_twl4030,snd_soc_omap,snd_soc_omap_mcbsp,snd_soc_core
> > snd_timer              18848  1 snd_pcm
> > snd                    57930  3 snd_soc_core,snd_pcm,snd_timer
> > soundcore               6954  1 snd
> > iptable_nat             3819  0
> > snd_page_alloc          4979  1 snd_pcm
> > nf_nat                 16515  1 iptable_nat
> > nf_conntrack_ipv4      12018  3 iptable_nat,nf_nat
> > nf_conntrack           71219  3 iptable_nat,nf_nat,nf_conntrack_ipv4
> > nf_defrag_ipv4          1379  1 nf_conntrack_ipv4
> > ip_tables              10537  1 iptable_nat
> > x_tables               16505  2 iptable_nat,ip_tables
> > gpio_keys               7117  0
> > autofs4                20492  2
> >
> > but the new ALSA device is not recognized
> >
> > *$:aplay -l*
> > **** List of PLAYBACK Hardware Devices ****
> > card 0: omap3beagle [omap3beagle], device 0: TWL4030 twl4030-hifi-0 []
> >   Subdevices
> > : 1/1
> >   Subdevice #0: subdevice #0
> >
> > So i tried to get some information in
> >
> > *$: cd /sys/kernel/debug/asoc*
> >
> > */sys/kernel/debug/asoc$: ls*
> > codecs       dais         omap3beagle  pcm3168      platforms
> >
> > */sys/kernel/debug/asoc$: cat codecs*
> > pcm3168-codec.0
> > twl4030-codec
> >
> > */sys/kernel/debug/asoc$: cat dais*
> > pcm3168-hifi
> > twl4030-voice
> > twl4030-hifi
> > omap-mcbsp-dai.4
> > omap-mcbsp-dai.3
> > omap-mcbsp-dai.2
> > omap-mcbsp-dai.1
> > omap-mcbsp-dai.0
> >
> > */sys/kernel/debug/asoc$: cat platforms*
> > omap-pcm-audio
> > snd-soc-dummy
> >
> > */sys/kernel/debug/asoc$:cd omap3beagle*
> >
> > */sys/kernel/debug/asoc/omap3beagle$:ls*
> > dapm           dapm_pop_time  twl4030-codec
> >
> > */sys/kernel/debug/asoc/omap3beagle$:cd /sys/kernel/debug/asoc/pcm3168*
> >
> > */sys/kernel/debug/asoc/pcm3168$: ls*
> > dapm_pop_time
> >
> >
> > At this point i have no idea how to solve the problem or how to debug
> > further and i would be very grateful for any hint.
> >
> > Thanks a lot
> > Wendelin
> >
> >
> >
> >
> > *
> >
> ***********************************************************************************************
> > *
> > /linux-mainline-3.2.18-r121b/git/sound/soc/omap/pcm3168_soundcard.c
> > *
> > **
> >
> ***********************************************************************************************
> >
> > */*
> >  * PCM3168 ASoC driver for BeagleBoard.
> >  *
> >  * Author:    Hugo Villeneuve
> >  * Copyright (C) 2008 Lyrtech inc
> >  *
> >  * adapted by Klimann Wendelin <wklimann@hotmail.com>
> >  *
> >  *
> >  * Based on ASoC driver for TI DAVINCI EVM platform, original copyright
> > follow:
> >  * Copyright:   (C) 2007 MontaVista Software, Inc., <source@mvista.com>
> >  *
> >  * This program is free software; you can redistribute it and/or modify
> >  * it under the terms of the GNU General Public License version 2 as
> >  * published by the Free Software Foundation.
> >  */
> >
> > #include <linux/clk.h>
> > #include <linux/platform_device.h>
> > #include <linux/module.h>
> > #include <linux/moduleparam.h>
> > #include <linux/timer.h>
> > #include <linux/interrupt.h>
> > #include <linux/platform_device.h>
> > #include <linux/gpio.h>
> > #include <sound/core.h>
> > #include <sound/pcm.h>
> > #include <sound/pcm_params.h>
> > #include <sound/soc.h>
> > #include <sound/soc-dapm.h>
> >
> > #include <asm/mach-types.h>
> > //#include <asm/dma.h>
> > #include <mach/hardware.h>
> > #include <mach/gpio.h>
> > //#include <mach/edma.h>
> > #include <plat/mcbsp.h>
> >
> > #include "omap-mcbsp.h"
> > #include "omap-pcm.h"
> >
> > #include "../codecs/pcm3168.h"
> >
> > /*
> >  * CLKX and CLKR are the inputs for the Sample Rate Generator.
> >  * FSX and FSR are outputs, driven by the sample Rate Generator.
> >  */
> > /*
> >  * SND_SOC_DAIFMT_CBS_CFS
> >  * for codec in slave mode
> >  */
> > #define AUDIO_FORMAT (SND_SOC_DAIFMT_DSP_B |    \
> >               SND_SOC_DAIFMT_CBM_CFM |    \
> >               SND_SOC_DAIFMT_IB_NF)
> >
> > static int pcm3168_hw_params(struct snd_pcm_substream *substream,
> >                 struct snd_pcm_hw_params *params)
> > {
> >     struct snd_soc_pcm_runtime *rtd = substream->private_data;
> >     struct snd_soc_dai *cpu_dai = rtd->cpu_dai;
> >     int fs;
> >     int ret = 0;
> >
> >
> > printk("in hw_params -> by kli");
> >
> >
> >     /* Fsref can be 8000 to 96000. */
> >     fs = params_rate(params);
> >
> >     /* set cpu DAI configuration */
> >     ret = snd_soc_dai_set_fmt(cpu_dai, AUDIO_FORMAT);
> >     if (ret < 0) {
> >         printk(KERN_ERR "can't set cpu DAI configuration\n");
> >         return ret;
> >     }
> >
> >     pr_debug("pcm3168_hw_params: rate = %d Hz\n", fs);
> >
> >     return 0;
> > }
> >
> > static struct snd_soc_ops pcm3168_ops = {
> >     .hw_params = pcm3168_hw_params,
> > };
> >
> > /* omap-pcm3168 digital audio interface glue - connects codec <--> CPU */
> > static struct snd_soc_dai_link pcm3168_dai = {
> >     .name = "PCM3168",  /* Codec name */
> >     .stream_name = "PCM3168",
> >     .cpu_dai_name = "omap-mcbsp-dai.2",
>
> Are you sure you connect the codec to McBSP2?
> If so I think it is better to disable the omap-twl4030 driver, but it
> should
> not cause problems if you have it, just make sure you are not running the
> two
> card at the same time.
>

The Beagleboard uses the omap3beagle.c file to include the TWL4030 and it
uses the "omap-mcbsp-dai.1" interface so i think there should be no proplem
in using booth drivers at the same time


>
> >     .codec_dai_name = "pcm3168-hifi",
> >     .codec_name = "pcm3168-codec",
>
> codec name should be: pcm3168-codec.0
>

Thanks that helpt to get the (old machine-driver) driver to load correctly
and now i can start with the mcbsp and hardware-testing.


>
> >     .platform_name = "omap-pcm-audio",
> >     .ops = &pcm3168_ops,
> > };
> >
> > /* omap-pcm3168 audio machine driver */
> > static struct snd_soc_card snd_soc_pcm3168 = {
> >     .name = "pcm3168",                      // -> "OMAP pcm3168"
> >     .owner = THIS_MODULE,
> >     .dai_link = &pcm3168_dai,
> >     .num_links = 1,
> > };
> >
> > /* pcm3168 audio private data */
> > static struct pcm3168_setup_data pcm3168_pcm3168_setup = {
> > //    .dem0_pin = GPIO(45),
> > //    .dem1_pin = GPIO(46),
> > //    .pdad_pin = GPIO(47),
> > //    .pdda_pin = GPIO(38),
> > };
> >
> > struct platform_device pcm3168_codec = {
> >         .name = "pcm3168-codec",
> >         .id = 0,
> >         .dev = {
> >                 .platform_data = &pcm3168_pcm3168_setup,
> >         },
> > };
> >
> >
> >
> > static struct platform_device *pcm3168_snd_device;
> >
> > static int __init pcm3168_init(void)
> > {
> >     int ret;
> >
> > printk(KERN_ALERT "in init soundcard \n");
> >
> >     if (!(machine_is_omap3_beagle()))
> >         return -ENODEV;
> >
> >     platform_device_register(&pcm3168_codec);
> >
> >     pcm3168_snd_device = platform_device_alloc("soc-audio", 0);
> >     if (!pcm3168_snd_device) {
> >         printk(KERN_ERR "platform device allocation failed\n");
> >         return -ENOMEM;
> >     }
> >
> >     platform_set_drvdata(pcm3168_snd_device, &snd_soc_pcm3168);
> > //    platform_device_add_data(pcm3168_snd_device, &pcm3168_snd_data,
> > //                 sizeof(pcm3168_snd_data));
> >
> > /*    ret = platform_device_add_resources(pcm3168_snd_device,
> >                         pcm3168_snd_resources,
> >                         ARRAY_SIZE(pcm3168_snd_resources));
> >     if (ret) {
> >         printk(KERN_ERR "platform device add resources failed\n");
> >         goto error;
> >     }
> > */
> >     ret = platform_device_add(pcm3168_snd_device);
> >     if (ret)
> >         goto error;
> >
> >     return ret;
> >
> > error:
> >     platform_device_put(pcm3168_snd_device);
> >     return ret;
> > }
>
> You should update you machine driver to use snd_soc_register_card() see
> other
> machine drivers as example (omap-twl4030.c is in the same directory for
> example and it is really simple).
>

I took the omap3beagle.c (and the omap-twl4030.c with same results) file as
template and adapted it. The driver can be compiled correctly but when i
load it it is not inseting the corresponding codec (snd_soc_pcm3168.ko).
Even if i load the snd_soc_pcm3168.ko driver manually and after load the
snd_soc_pcm3168_soundcard.ko driver i do not find the soundcard and the
codec in:

 $/sys/kernel/debug/asoc$: ls
       codecs       dais         omap3beagle      platforms

 $/sys/kernel/debug/asoc$: cat codecs
       twl4030-codec

******************************************************************************************************************************************
*   new
machine-driver:
*
*
/linux-mainline-3.2.18-r121b/git/sound/soc/omap/pcm3168_soundcard.c
*
*
*
*
START
*
******************************************************************************************************************************************

/*
 * PCM3168 ASoC driver for BeagleBoard.
 *
 * based on:
 *   > omap3beagle.c  --  SoC audio for OMAP3 Beagle
 *   > Author: Steve Sakoman <steve@sakoman.com>
 *
 * adapted by Klimann Wendelin <wklimann@hotmail.com>
 *
 *
 * This program is free software; you can redistribute it and/or
 * modify it under the terms of the GNU General Public License
 * version 2 as published by the Free Software Foundation.
 *
 * 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., 51 Franklin St, Fifth Floor, Boston, MA
 * 02110-1301 USA
 *
 */

#include <linux/clk.h>
#include <linux/platform_device.h>
#include <linux/module.h>
#include <sound/core.h>
#include <sound/pcm.h>
#include <sound/soc.h>

#include <asm/mach-types.h>
#include <mach/hardware.h>
#include <mach/gpio.h>
#include <plat/mcbsp.h>

#include "omap-mcbsp.h"
#include "omap-pcm.h"


static int pcm3168_hw_params(struct snd_pcm_substream *substream,
    struct snd_pcm_hw_params *params)
{
    struct snd_soc_pcm_runtime *rtd = substream->private_data;
    struct snd_soc_dai *codec_dai = rtd->codec_dai;
    struct snd_soc_dai *cpu_dai = rtd->cpu_dai;
    unsigned int fmt;
    int ret;

        fmt =    SND_SOC_DAIFMT_DSP_B |
            SND_SOC_DAIFMT_CBM_CFM |
            SND_SOC_DAIFMT_IB_NF;


    /* Set codec DAI configuration */
    ret = snd_soc_dai_set_fmt(codec_dai, fmt);
    if (ret < 0) {
        printk(KERN_ERR "can't set codec DAI configuration\n");
        return ret;
    }

    /* Set cpu DAI configuration */
    ret = snd_soc_dai_set_fmt(cpu_dai, fmt);
    if (ret < 0) {
        printk(KERN_ERR "can't set cpu DAI configuration\n");
        return ret;
    }

    /* Set the codec system clock for DAC and ADC */
    ret = snd_soc_dai_set_sysclk(codec_dai, 0, 26000000,
                     SND_SOC_CLOCK_IN);
    if (ret < 0) {
        printk(KERN_ERR "can't set codec system clock\n");
        return ret;
    }

    return 0;
}

static struct snd_soc_ops pcm3168_ops = {
    .hw_params = pcm3168_hw_params,
};

/* Digital audio interface glue - connects codec <--> CPU */
static struct snd_soc_dai_link pcm3168_dai = {
    .name = "PCM3168",
    .stream_name = "PCM3168",
    .cpu_dai_name = "omap-mcbsp-dai.2",
    .platform_name = "omap-pcm-audio",
    .codec_dai_name = "pcm3168-hifi",
    .codec_name = "pcm3168-codec.0",
    .ops = &pcm3168_ops,
};

/* Audio machine driver */
static struct snd_soc_card snd_soc_pcm3168 = {
    .name = "pcm3168",
    .owner = THIS_MODULE,
    .dai_link = &pcm3168_dai,
    .num_links = 1,
};

static int __devinit pcm3168_soc_probe(struct platform_device *pdev)
{
    struct snd_soc_card *card = &snd_soc_pcm3168;
    int ret;

    pr_info("OMAP3 Beagle/Devkit8000 SoC init\n");

    card->dev = &pdev->dev;

    ret = snd_soc_register_card(card);
    if (ret) {
        dev_err(&pdev->dev, "snd_soc_register_card() failed: %d\n",
            ret);
        return ret;
    }

    return 0;
}

static int __devexit pcm3168_soc_remove(struct platform_device *pdev)
{
    struct snd_soc_card *card = platform_get_drvdata(pdev);

    snd_soc_unregister_card(card);

    return 0;
}

static struct platform_driver pcm3168_driver = {
    .driver = {
        .name = "pcm3168-soc-audio",
        .owner = THIS_MODULE,
    },

    .probe = pcm3168_soc_probe,
    .remove = __devexit_p(pcm3168_soc_remove),
};

static int __init pcm3168_soc_init(void)
{
    return platform_driver_register(&pcm3168_driver);
}
module_init(pcm3168_soc_init);

static void __exit pcm3168_soc_exit(void)
{
    platform_driver_unregister(&pcm3168_driver);
}
module_exit(pcm3168_soc_exit);

MODULE_AUTHOR("Klimann Wendelin <wklimann@hotmail.com>");
MODULE_DESCRIPTION("ALSA SoC PCM3168 add on Soundcard");
MODULE_LICENSE("GPL");
MODULE_ALIAS("platform:pcm3168-soc-audio");

******************************************************************************************************************************************
*   new
machine-driver:
*
*
/linux-mainline-3.2.18-r121b/git/sound/soc/omap/pcm3168_soundcard.c
*
*
*
*
    END

*
******************************************************************************************************************************************


>
>
> >
> > static void __exit pcm3168_exit(void)
> > {
> >     platform_device_unregister(pcm3168_snd_device);
> >     platform_device_unregister(&pcm3168_codec);
> > }
> >
> > module_init(pcm3168_init);
> > module_exit(pcm3168_exit);
> >
> > MODULE_AUTHOR("Klimann Wendelin <wklimann@hotmail.com>");
> > MODULE_DESCRIPTION("PCM3168 Beagle ASoC driver");
> > MODULE_LICENSE("GPL");
> > MODULE_ALIAS("platform:pcm3168-soc-audio");
> >
> >
> >
> >
> > *
> >
> ***********************************************************************************************
> > *
> > /linux-mainline-3.2.18-r121b/git/sound/soc/codecs/pcm3168.c
> >    *
> > **
> >
> ***********************************************************************************************
> >
> > */*
> >  * ALSA Soc PCM3168 codec support
> >  *
> >  * Author:    Hugo Villeneuve
> >  * Copyright (C) 2008 Lyrtech inc
> >  *
> >  * adapted by Klimann Wendelin
> >  *
> >  *
> >  * Based on AC97 Soc codec, original copyright follow:
> >  * Copyright 2005 Wolfson Microelectronics PLC.
> >  *
> >  *  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.
> >  *
> >  * Generic PCM3168 support.
> >  */
> >
> > #include <linux/init.h>
> > #include <linux/kernel.h>
> > #include <linux/device.h>
> > #include <linux/gpio.h>
> > #include <linux/slab.h>
> > #include <linux/module.h>
> > #include <linux/clk.h>
> > #include <linux/platform_device.h>
> > #include <linux/module.h>
> > #include <sound/core.h>
> > #include <sound/initval.h>
> > #include <sound/pcm.h>
> > #include <sound/pcm_params.h>
> > //#include <sound/soc-dapm.h>
> > #include <sound/soc.h>
> >
> > #include <asm/mach-types.h>
> > #include <mach/hardware.h>
> > #include <mach/gpio.h>
> > #include <plat/mcbsp.h>
> >
> > #include "../omap/omap-mcbsp.h"
> > #include "../omap/omap-pcm.h"
> >
> > #include "pcm3168.h"
> >
> >
> >
> > #define PCM3168_VERSION "0.1"
> >
> > #define PCM3168_RATES   SNDRV_PCM_RATE_8000_96000
> /*(SNDRV_PCM_RATE_32000 |
> > SNDRV_PCM_RATE_44100 |    \
> >                SNDRV_PCM_RATE_48000)*/
> >
> > static struct snd_soc_dai_driver pcm3168_dai = {
> >
> >     .name = "pcm3168-hifi",
> >     .playback = {
> >         .stream_name = "PCM3168 Playback",
> >         .channels_min = 2,
> >         .channels_max = 8,
> >         .rates = PCM3168_RATES,
> >         .formats = SNDRV_PCM_FMTBIT_S16_LE, //SNDRV_PCM_FMTBIT_S32_LE
> >     },
> >     .capture = {
> >         .stream_name = "PCM3168 Capture",
> >         .channels_min = 2,
> >         .channels_max = 6,
> >         .rates = PCM3168_RATES,
> >         .formats = SNDRV_PCM_FMTBIT_S16_LE, //SNDRV_PCM_FMTBIT_S32_LE
> >     },
> > };
> >
> > static void pcm3168_gpio_free(struct pcm3168_setup_data *setup)
> > {
> > //    gpio_free(setup->dem0_pin);
> > //    gpio_free(setup->dem1_pin);
> > //    gpio_free(setup->pdad_pin);
> > //    gpio_free(setup->pdda_pin);
> > }
> >
> > static int pcm3168_soc_probe(struct snd_soc_codec *codec)
> > {
> >     struct pcm3168_setup_data *setup = codec->dev->platform_data;
> >     int ret = 0;
> >
> > printk(KERN_ALERT "in SOC Probe -> kli \n");
> >
> >     printk(KERN_INFO "PCM3168 SoC Audio Codec %s\n", PCM3168_VERSION);
> >
> >     return ret;
> >
> > gpio_err:
> > //    pcm3168_gpio_free(setup);
> >
> >     return ret;
> > }
> >
> > static int pcm3168_soc_remove(struct snd_soc_codec *codec)
> > {
> >     struct pcm3168_setup_data *setup = codec->dev->platform_data;
> >
> > //    pcm3168_gpio_free(setup);
> >     return 0;
> > }
> >
> >
> > #define pcm3168_soc_suspend NULL
> > #define pcm3168_soc_resume NULL
> >
> >
> > static struct snd_soc_codec_driver soc_codec_dev_pcm3168 = {
> >     .probe =     pcm3168_soc_probe,
> >     .remove =     pcm3168_soc_remove,
> >     .suspend =    pcm3168_soc_suspend,
> >     .resume =    pcm3168_soc_resume,
> > };
> >
> > static int __devinit pcm3168_codec_probe(struct platform_device *pdev)
> > {
> >     int ret;
> >     printk(KERN_ALERT "probe pcm3168 -> kli \n");
> >
> >     ret = snd_soc_register_codec(&pdev->dev,
> >             &soc_codec_dev_pcm3168, &pcm3168_dai, 1);
> >
> >     printk(KERN_ALERT "probe_after pcm3168 -> kli = %d \n", ret);
> >
> >     return ret;
> > }
> >
> > static int __devexit pcm3168_codec_remove(struct platform_device *pdev)
> > {
> >     printk(KERN_ALERT "remove pcm3168 -> kli \n");
> >
> >     snd_soc_unregister_codec(&pdev->dev);
> >     return 0;
> > }
> >
> > MODULE_ALIAS("platform:pcm3168-codec");
> >
> > static struct platform_driver pcm3168_codec_driver = {
> >     .probe        = pcm3168_codec_probe,
> >     .remove        = __devexit_p(pcm3168_codec_remove),
> >     .driver        = {
> >     .name        = "pcm3168-codec",
> >     .owner        = THIS_MODULE,
> >     },
> > };
>
> According to the datasheet the PCM3168 have I2C or SPI control interface.
> You
> should have the driver as i2c/spi device so you can actually control it.
>

As it is my first attempt to implement an audio codec i thought to start as
simple as possible and do all the setup with the external pins and avoid to
use the I2C or SPI at first. Of course i want to add it later on but i
thought it would be wise to test the hardware first.


>
> >
> > static int __init pcm3168_modinit(void)
> > {
> >     printk(KERN_ALERT "in init of 3168 -> kli \n");
> >     return platform_driver_register(&pcm3168_codec_driver);
> > }
> > module_init(pcm3168_modinit);
> >
> > static void __exit pcm3168_exit(void)
> > {
> >     printk(KERN_ALERT "in exit of 3168 -> kli \n");
> >     platform_driver_unregister(&pcm3168_codec_driver);
> > }
> > module_exit(pcm3168_exit);
> >
> > MODULE_DESCRIPTION("Soc PCM3168 driver");
> > MODULE_AUTHOR("Klimann Wendelin <wklimann@hotmail.com>");
> > MODULE_LICENSE("GPL");
> >
> >
> > *
> >
> ***********************************************************************************************
> > *
> > /linux-mainline-3.2.18-r121b/git/sound/soc/codecs/pcm3168.h
> >     *
> >
> ***********************************************************************************************
> > *
> >
> > /*
> >  * PCM3168 ALSA SoC Layer
> >  *
> >  * Author:    Hugo Villeneuve
> >  * Copyright (C) 2008 Lyrtech inc
> >  *
> >  * adapted by Klimann Wendelin <wklimann@hotmail.com>
> >  *
> >  *
> >  * This program is free software; you can redistribute it and/or modify
> >  * it under the terms of the GNU General Public License version 2 as
> >  * published by the Free Software Foundation.
> >  */
> >
> > #ifndef __LINUX_SND_SOC_PCM3168_2_H
> > #define __LINUX_SND_SOC_PCM3168_2_H
> >
> > struct pcm3168_setup_data {
> > //    unsigned dem0_pin;
> > //    unsigned dem1_pin;
> > //    unsigned pdad_pin;
> > //    unsigned pdda_pin;
> > };
> >
> > #endif
> > _______________________________________________
> > Alsa-devel mailing list
> > Alsa-devel@alsa-project.org
> > http://mailman.alsa-project.org/mailman/listinfo/alsa-devel
> >
>
>
> --
> Péter
>

Thanks
Wendelin

^ permalink raw reply	[flat|nested] 11+ messages in thread

* Re: ASoC: BeagleBoard driver development (PCM3168)
  2013-02-16 12:05   ` wendelin klimann
@ 2013-02-19 11:10     ` Peter Ujfalusi
       [not found]       ` <CAGxc5aDQ5btyvhcEnCcvNJZhRuCZWz8XS9SxOqcgmgBSx+bYZQ@mail.gmail.com>
  0 siblings, 1 reply; 11+ messages in thread
From: Peter Ujfalusi @ 2013-02-19 11:10 UTC (permalink / raw)
  To: wendelin klimann; +Cc: alsa-devel

On 02/16/2013 01:05 PM, wendelin klimann wrote:
>     > I try to implement an PCM3168 audio codec from TI to the BeagleBoard but
>     > actually i am stuck and it would be rally nice if one could help me a
>     > little bit.
>     > My ALSA driver version is 1.0.24 and i use an 3.2.18 kernel.
>     > As a startingpoint i used the files

Is there any particular reason to use so ancient kernel and alsa-driver package?

>     >     .codec_dai_name = "pcm3168-hifi",
>     >     .codec_name = "pcm3168-codec",
> 
>     codec name should be: pcm3168-codec.0
> 
> Thanks that helpt to get the (old machine-driver) driver to load correctly and
> now i can start with the mcbsp and hardware-testing.

...

>     You should update you machine driver to use snd_soc_register_card() see other
>     machine drivers as example (omap-twl4030.c is in the same directory for
>     example and it is really simple).
> 
> I took the omap3beagle.c (and the omap-twl4030.c with same results) file as
> template and adapted it. The driver can be compiled correctly but when i load
> it it is not inseting the corresponding codec (snd_soc_pcm3168.ko).
> Even if i load the snd_soc_pcm3168.ko driver manually and after load the
> snd_soc_pcm3168_soundcard.ko driver i do not find the soundcard and the codec in:

I'm confused now. Previously you said it is working and now you are telling
that it is not...

> 
>  $/sys/kernel/debug/asoc$: ls
>        codecs       dais         omap3beagle      platforms
> 
>  $/sys/kernel/debug/asoc$: cat codecs
>        twl4030-codec      

You do not have the codec loaded so the card is not going to come up.
What do you have in the kernel messages around this time?
Have you registered the platform device for your testing codec driver?


>     According to the datasheet the PCM3168 have I2C or SPI control interface. You
>     should have the driver as i2c/spi device so you can actually control it.
> 
> 
> As it is my first attempt to implement an audio codec i thought to start as
> simple as possible and do all the setup with the external pins and avoid to
> use the I2C or SPI at first. Of course i want to add it later on but i thought
> it would be wise to test the hardware first.

The time to start the driver in a proper way will save you lots of time... You
don't need to write two drivers (platform driver for testing followed by a new
real driver).

-- 
Péter

^ permalink raw reply	[flat|nested] 11+ messages in thread

* Re: ASoC: BeagleBoard driver development (PCM3168)
       [not found]         ` <5124D1EB.9030404@ti.com>
@ 2013-03-01 20:00           ` wendelin klimann
  2013-03-23 14:37           ` Wendelin Klimann
  1 sibling, 0 replies; 11+ messages in thread
From: wendelin klimann @ 2013-03-01 20:00 UTC (permalink / raw)
  To: Peter Ujfalusi; +Cc: alsa-devel

Hello and thanks for the support


I would advice to update. Eventually you want to upstream the codec driver,
> so
> it is going to be easier for you.
>

Well i followed your advice and updated to kernel version 3.7.4+ and to
ALSA version k3.7.4+, and i will be glad to upstram the finalized driver.
As you recommended i am using your omap_twl4030.c file as a starting-point
for my driver development, and i am trying to get the adapted machine
driver to run but without success.
The machine driver is not even going into

*   static __devinit int omap_pcm3168_probe(struct platform_device *pdev)*

and i am really stuck at this point.

It would be really nice if you could help me.


Regards
Wendelin


File:

/*
 * omap-pcm3168.c  --  PCM3168 ASoC driver for the BeagleBoard.
 *
 * based on:
 *    > omap-twl4030.c  --  SoC audio for TI SoC based boards with twl4030
codec
 *    >
 *    > Copyright (C) 2012 Texas Instruments Incorporated -
http://www.ti.com
 *    > All rights reserved.
 *    >
 *    > Author: Peter Ujfalusi <peter.ujfalusi@ti.com>
 *
 * adapted by Klimann Wendelin <wklimann@hotmail.com>
 *
 *
 * This program is free software; you can redistribute it and/or
 * modify it under the terms of the GNU General Public License
 * version 2 as published by the Free Software Foundation.
 *
 * 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., 51 Franklin St, Fifth Floor, Boston, MA
 * 02110-1301 USA
 *
 */

#include <linux/platform_device.h>
//#include <linux/platform_data/omap-twl4030.h>
#include <linux/module.h>
#include <linux/of.h>

#include <sound/core.h>
#include <sound/pcm.h>
#include <sound/soc.h>

#include "omap-mcbsp.h"
#include "omap-pcm.h"

static int omap_pcm3168_hw_params(struct snd_pcm_substream *substream,
    struct snd_pcm_hw_params *params)
{
    struct snd_soc_pcm_runtime *rtd = substream->private_data;
    struct snd_soc_dai *codec_dai = rtd->codec_dai;
    struct snd_soc_dai *cpu_dai = rtd->cpu_dai;
    struct snd_soc_codec *codec = rtd->codec;
    struct snd_soc_card *card = codec->card;
    unsigned int fmt;
    int ret;

    fmt =    SND_SOC_DAIFMT_DSP_B     |
            SND_SOC_DAIFMT_CBM_CFM  |
            SND_SOC_DAIFMT_IB_NF;

    /* Set codec DAI configuration */
    ret = snd_soc_dai_set_fmt(codec_dai, fmt);
    if (ret < 0) {
        dev_err(card->dev, "can't set codec DAI configuration\n");
        return ret;
    }

    /* Set cpu DAI configuration */
    ret = snd_soc_dai_set_fmt(cpu_dai, fmt);
    if (ret < 0) {
        dev_err(card->dev, "can't set cpu DAI configuration\n");
        return ret;
    }

    return 0;
}

static struct snd_soc_ops omap_pcm3168_ops = {
    .hw_params = omap_pcm3168_hw_params,
};

/* Digital audio interface glue - connects codec <--> CPU */
static struct snd_soc_dai_link omap_pcm3168_dai_links[] = {
    {
        .name = "PCM3168",
        .stream_name = "PCM3168",
        .cpu_dai_name = "omap-mcbsp.3",
        .codec_dai_name = "pcm3168-hifi",
        .platform_name = "omap-pcm-audio",
        .codec_name = "pcm3168-codec.0",
        .ops = &omap_pcm3168_ops,
    },
};

/* Audio machine driver */
static struct snd_soc_card omap_pcm3168_card = {
    .owner = THIS_MODULE,
    .dai_link = omap_pcm3168_dai_links,
    .num_links = ARRAY_SIZE(omap_pcm3168_dai_links),
};

static __devinit int omap_pcm3168_probe(struct platform_device *pdev)
{
    printk("in __devinit omap_pcm3168_probe -> by kli");

    struct omap_tw4030_pdata *pdata = dev_get_platdata(&pdev->dev);
    struct device_node *node = pdev->dev.of_node;
    struct snd_soc_card *card = &omap_pcm3168_card;
    int ret = 0;

    card->dev = &pdev->dev;

    if (node) {
        struct device_node *dai_node;

        if (snd_soc_of_parse_card_name(card, "ti,model")) {
            dev_err(&pdev->dev, "Card name is not provided\n");
            return -ENODEV;
        }

        dai_node = of_parse_phandle(node, "ti,mcbsp", 0);
        if (!dai_node) {
            dev_err(&pdev->dev, "McBSP node is not provided\n");
            return -EINVAL;
        }
        omap_pcm3168_dai_links[0].cpu_dai_name  = NULL;
        omap_pcm3168_dai_links[0].cpu_of_node = dai_node;

    }
    /*else if (pdata) {
        if (pdata->card_name) {
            card->name = pdata->card_name;
        } else {
            dev_err(&pdev->dev, "Card name is not provided\n");
            return -ENODEV;
        }
    }*/
    else {
        dev_err(&pdev->dev, "Missing pdata\n");
        return -ENODEV;
    }

    ret = snd_soc_register_card(card);
    if (ret) {
        dev_err(&pdev->dev, "snd_soc_register_card() failed: %d\n",
            ret);
        return ret;
    }

    return 0;
}

static int __devexit omap_pcm3168_remove(struct platform_device *pdev)
{
    struct snd_soc_card *card = platform_get_drvdata(pdev);

    snd_soc_unregister_card(card);

    return 0;
}


static const struct of_device_id omap_pcm3168_of_match[] = {
    {.compatible = "ti,omap-pcm3168", },
    { },
};
MODULE_DEVICE_TABLE(of, omap_pcm3168_of_match);

static struct platform_driver omap_pcm3168_driver = {
    .driver = {
        .name = "omap-pcm3168",
        .owner = THIS_MODULE,
//        .pm = &snd_soc_pm_ops,
//        .of_match_table = omap_pcm3168_of_match,
    },
    .probe = omap_pcm3168_probe,
    .remove = __devexit_p(omap_pcm3168_remove),
};

module_platform_driver(omap_pcm3168_driver);

MODULE_AUTHOR("Klimann Wendelin <wklimann@hotmail.com>");
MODULE_DESCRIPTION("ALSA SoC PCM3168 add on Soundcard");
MODULE_LICENSE("GPL");
MODULE_ALIAS("platform:omap-pcm3168");

^ permalink raw reply	[flat|nested] 11+ messages in thread

* ASoC: BeagleBoard driver development (PCM3168)
       [not found]         ` <5124D1EB.9030404@ti.com>
  2013-03-01 20:00           ` wendelin klimann
@ 2013-03-23 14:37           ` Wendelin Klimann
  2013-03-23 15:57             ` Daniel Mack
  1 sibling, 1 reply; 11+ messages in thread
From: Wendelin Klimann @ 2013-03-23 14:37 UTC (permalink / raw)
  To: Peter Ujfalusi, alsa-devel

Hello Peter

I am stuck again in my ASoc driver development and it would be really 
nice if you could give me an hint how i could solve this.

Acctually i try to connect my PCM3168 Audio Codec to the McBSP on the 
BeagleBoard.
My new driver loads fine and i got 2 soundcards:

*root@beagleboard:/lib/modules/3.7.4+/kernel/sound/soc/omap# aplay -l*
    **** List of PLAYBACK Hardware Devices ****
    card 0: omap3beagle [omap3beagle], device 0: TWL4030 twl4030-hifi-0 []
      Subdevices: 1/1
      Subdevice #0: subdevice #0
    card 1: pcm3168 [pcm3168], device 0: PCM3168 pcm3168-hifi-0 []
      Subdevices: 1/1
      Subdevice #0: subdevice #0

Your TWL4030 driver is still working perfect with:

*root@beagleboard:/lib/modules/3.7.4+/kernel/sound/soc/omap# aplay 
-Dhw:0,0 /home/root/fifi.wav*
    [ 1245.302551] omap-dma-engine omap-dma-engine: allocating channel 
for 33
    Playing WAVE '/home/root/fifi.wav' : Signed 16 bit Little Endian, 
Rate 44100 Hz, Stereo

but when i play the same file with my new driver i get an error (as 
codec master and also as codec slave):

*root@beagleboard:/lib/modules/3.7.4+/kernel/sound/soc/omap# aplay 
-Dhw:1,0 /home/root/fifi.wav*
    [ 1128.677337] omap-dma-engine omap-dma-engine: allocating channel 
for 17
    Playing WAVE '/h[ 1128.689544] can't set codec DAI configuration - 
pcm3168
    ome/root/fifi.wa[ 1128.695281] asoc: machine hw_params failed: -524
    v' : Signed 16 b[ 1128.702514] omap-dma-engine omap-dma-engine: 
freeing channel for 17
    it Little Endian, Rate 44100 Hz, Stereo
    aplay: set_params:1145: Unable to install hw params:
    ACCESS:  RW_INTERLEAVED
    FORMAT:  S16_LE
    SUBFORMAT:  STD
    SAMPLE_BITS: 16
    FRAME_BITS: 32
    CHANNELS: 2
    RATE: 44100
    PERIOD_TIME: (124988 124989)
    PERIOD_SIZE: 5512
    PERIOD_BYTES: 22048
    PERIODS: 5
    BUFFER_TIME: (624943 624944)
    BUFFER_SIZE: 27560
    BUFFER_BYTES: 110240
    TICK_TIME: 0

To check whether my machine driver (/omap-pcm3168.c/) is working i tried 
to implement the /twl4030.c/ codec driver into it (and deactivated the 
omap_twl4030_audio_init() function), which worked just fine.
With this setup i changed the /.cpu_dai_name = "omap-mcbsp.2"/ to 
/.cpu_dai_name = "omap-mcbsp.3"/ and i adjusted the codec as slave 
(/SND_SOC_DAIFMT_CBS_CFS/) to test whether the McBSP3 setup is right 
(the PCM3168 codec was disconnected).
I still got a clock signal on the McBSP2 but the McBSP2_DX had no signal 
anymore and on the McBSP3 i did not get any signal at all (measured with 
an osziloscope).
I am a little bit confused as i am not shure why there is still the clk 
signal on the McBSP2 and furthermore i am not shure whether i test the 
McBSP3 properly or whether there is a proplem in the McBSP3 setup.
The PinMUX for the McBSP3 is done in the kernel (/board-omap3beagle.c/) 
by setting:

static void __init omap3_beagle_config_mcbsp3_mux(void)
{
     omap_mux_init_signal("mcbsp3_fsx.mcbsp3_fsx", OMAP_PIN_INPUT);
     omap_mux_init_signal("uart2_cts.mcbsp3_dx", OMAP_PIN_OUTPUT);
     omap_mux_init_signal("uart2_rts.mcbsp3_dr", OMAP_PIN_INPUT);
     /* NOTE: Clock pins need to be in input mode */
     omap_mux_init_signal("uart2_tx.mcbsp3_clkx", OMAP_PIN_INPUT);
}

It would be really nice if you could help me.

Thanks
Wendelin




******************************************************************************************************
* kernel_3.7.4+/sound/soc/omap/omap-pcm3168.c *
******************************************************************************************************
/*
  * PCM3168 ASoC driver for BeagleBoard.
  *
  * based on:
  *   > omap3beagle.c  --  SoC audio for OMAP3 Beagle
  *   > Author: Steve Sakoman <steve@sakoman.com>
  *
  * adapted by Klimann Wendelin <wklimann@hotmail.com>
  *
  *
  * This program is free software; you can redistribute it and/or
  * modify it under the terms of the GNU General Public License
  * version 2 as published by the Free Software Foundation.
  *
  * 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., 51 Franklin St, Fifth Floor, Boston, MA
  * 02110-1301 USA
  *
  */

#include <linux/clk.h>
#include <linux/platform_device.h>
#include <linux/module.h>
#include <sound/core.h>
#include <sound/pcm.h>
#include <sound/soc.h>
#include <sound/pcm_params.h>

#include <asm/mach-types.h>
#include <mach/hardware.h>
#include <mach/gpio.h>
//#include <plat/mcbsp.h>

#include "omap-mcbsp.h"
#include "omap-pcm.h"


/*
  * Uncomment to test codec in slave mode or without actual codec. This 
makes
  * possible to test this driver by letting the OMAP to be DAI link master
  */
#define PCM3168_CODEC_SLAVE        1



static int pcm3168_hw_params(struct snd_pcm_substream *substream,
     struct snd_pcm_hw_params *params)
{
     struct snd_soc_pcm_runtime *rtd = substream->private_data;
     struct snd_soc_dai *codec_dai = rtd->codec_dai;
     struct snd_soc_dai *cpu_dai = rtd->cpu_dai;
     unsigned int fmt, div;
     int ret;



#ifdef PCM3168_CODEC_SLAVE
         fmt =    SND_SOC_DAIFMT_DSP_B |
                 SND_SOC_DAIFMT_CBS_CFS |
                 SND_SOC_DAIFMT_IB_NF;
#else
         fmt =    SND_SOC_DAIFMT_DSP_B |
                 SND_SOC_DAIFMT_CBM_CFM |
                 SND_SOC_DAIFMT_IB_NF;
#endif



     /* Set codec DAI configuration */
     ret = snd_soc_dai_set_fmt(codec_dai, fmt);
     if (ret < 0) {
         printk(KERN_ERR "can't set codec DAI configuration - pcm3168\n");
         return ret;
     }

     /* Set cpu DAI configuration */
     ret = snd_soc_dai_set_fmt(cpu_dai, fmt);
     if (ret < 0) {
         printk(KERN_ERR "can't set cpu DAI configuration - pcm3168\n");
         return ret;
     }


#ifdef PCM3168_CODEC_SLAVE

     ret = snd_soc_dai_set_sysclk(cpu_dai, OMAP_MCBSP_SYSCLK_CLKS_FCLK,
                      48000000, SND_SOC_CLOCK_IN);
     if (ret < 0) {
         pr_err("can't set McBSP sysclk - pcm3168\n");
         return ret;
     }

     /*
      * Calculate McBSP SRG divisor in McBSP master mode
      */
     div = 48000000 / params_rate(params) / params_channels(params);

     switch (params_format(params)) {
     case SNDRV_PCM_FORMAT_S16_LE:
         div /= 16;
         break;
     case SNDRV_PCM_FORMAT_S24_LE:
     case SNDRV_PCM_FORMAT_S32_LE:
         div /= 32;
         break;
     };


     /*
      * Round to maximum divisor if needed. This means that extra bit-clock
      * cycles are transmitted when sample rate and number of bits in frame
      * (channels * sample bits) are low.
      */
     if (div >= 256)
         div = 256;

     ret = snd_soc_dai_set_clkdiv(cpu_dai, OMAP_MCBSP_CLKGDV, div);
     if (ret < 0) {
         pr_err("can't set SRG clock divider - pcm3168\n");
         return ret;
     }

#endif


     return 0;
}

static struct snd_soc_ops pcm3168_ops = {
     .hw_params = pcm3168_hw_params,
};

/* Digital audio interface glue - connects codec <--> CPU */
static struct snd_soc_dai_link pcm3168_dai = {
     .name = "PCM3168",
     .stream_name = "PCM3168",
     .cpu_dai_name = "omap-mcbsp.3",
     .platform_name = "omap-pcm-audio",
     .codec_dai_name = "pcm3168-hifi",
     .codec_name = "pcm3168-codec.0",
     .ops = &pcm3168_ops,
};

/* Audio machine driver */
static struct snd_soc_card snd_soc_pcm3168 = {
     .name = "pcm3168",
     .owner = THIS_MODULE,
     .dai_link = &pcm3168_dai,
     .num_links = 1,
};

struct platform_device pcm3168_codec = {
         .name = "pcm3168-codec",
         .id = 0,
};

struct platform_device pcm3168_soc_audio = {
         .name = "pcm3168-soc-audio",
         .id = 0,
};

static int __devinit pcm3168_soc_probe(struct platform_device *pdev)
{
     struct snd_soc_card *card = &snd_soc_pcm3168;
     int ret;

     pr_info("OMAP3 Beagle - PCM3168 ASoC init\n");

     card->dev = &pdev->dev;

     ret = snd_soc_register_card(card);
     if (ret) {
         dev_err(&pdev->dev, "snd_soc_register_card() failed: %d - 
pcm3168\n",
             ret);
         return ret;
     }

     return 0;
}

static int __devexit pcm3168_soc_remove(struct platform_device *pdev)
{
     struct snd_soc_card *card = platform_get_drvdata(pdev);

     snd_soc_unregister_card(card);

     return 0;
}

static struct platform_driver pcm3168_driver = {
     .driver = {
         .name = "pcm3168-soc-audio",
         .owner = THIS_MODULE,
     },

     .probe = pcm3168_soc_probe,
     .remove = __devexit_p(pcm3168_soc_remove),
};


static int __init pcm3168_soc_init(void)
{
     platform_device_register(&pcm3168_codec);
     platform_device_register(&pcm3168_soc_audio);
     return platform_driver_register(&pcm3168_driver);
}
module_init(pcm3168_soc_init);

static void __exit pcm3168_soc_exit(void)
{
     platform_driver_unregister(&pcm3168_driver);
     platform_device_unregister(&pcm3168_soc_audio);
     platform_device_unregister(&pcm3168_codec);
}
module_exit(pcm3168_soc_exit);

MODULE_AUTHOR("Klimann Wendelin <wklimann@hotmail.com>");
MODULE_DESCRIPTION("ALSA SoC PCM3168 add on Soundcard");
MODULE_LICENSE("GPL");
MODULE_ALIAS("platform:pcm3168-soc-audio");



******************************************************************************************************
* kernel_3.7.4+/sound/soc/codecs/pcm3168.c *
******************************************************************************************************
/*
  * ALSA Soc PCM3168 codec support
  *
  * Author: Klimann Wendelin <wklimann@hotmail.com>
  *
  * based on:
  *   > pcm3008.c
  *   > Author:    Hugo Villeneuve
  *   > Copyright (C) 2008 Lyrtech inc
  *   >
  *   > Based on AC97 Soc codec, original copyright follow:
  *   > Copyright 2005 Wolfson Microelectronics PLC.
  *
  * This program is free software; you can redistribute it and/or
  * modify it under the terms of the GNU General Public License
  * version 2 as published by the Free Software Foundation.
  *
  * 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., 51 Franklin St, Fifth Floor, Boston, MA
  * 02110-1301 USA
  */

#include <linux/init.h>
#include <linux/kernel.h>
#include <linux/device.h>
#include <linux/gpio.h>
#include <linux/slab.h>
#include <linux/module.h>
#include <linux/clk.h>
#include <linux/platform_device.h>
#include <linux/module.h>
#include <sound/core.h>
#include <sound/initval.h>
#include <sound/pcm.h>
#include <sound/pcm_params.h>
//#include <sound/soc-dapm.h>
#include <sound/soc.h>

#include <asm/mach-types.h>
#include <mach/hardware.h>
#include <mach/gpio.h>
//#include <plat/mcbsp.h>

#include "../omap/omap-mcbsp.h"
#include "../omap/omap-pcm.h"

#include "pcm3168.h"



#define PCM3168_VERSION "0.1"

#define PCM3168_RATES   SNDRV_PCM_RATE_8000_96000 
/*(SNDRV_PCM_RATE_32000 | SNDRV_PCM_RATE_44100 |    \
                SNDRV_PCM_RATE_48000)*/
#define PCM3168_FORMATS     (SNDRV_PCM_FMTBIT_S16_LE | 
SNDRV_PCM_FMTBIT_S32_LE)

static struct snd_soc_dai_driver pcm3168_dai = {

     .name = "pcm3168-hifi",
     .playback = {
         .stream_name = "PCM3168 Playback",
         .channels_min = 2,
         .channels_max = 8,
         .rates = PCM3168_RATES,
         .formats = PCM3168_FORMATS,  //SNDRV_PCM_FMTBIT_S16_LE, 
//SNDRV_PCM_FMTBIT_S32_LE
         .sig_bits = 24,
     },
     .capture = {
         .stream_name = "PCM3168 Capture",
         .channels_min = 2,
         .channels_max = 6,
         .rates = PCM3168_RATES,
         .formats = PCM3168_FORMATS,  //SNDRV_PCM_FMTBIT_S16_LE, 
//SNDRV_PCM_FMTBIT_S32_LE
         .sig_bits = 24,
     },
};

static void pcm3168_gpio_free(struct pcm3168_setup_data *setup)
{
//    gpio_free(setup->dem0_pin);
//    gpio_free(setup->dem1_pin);
//    gpio_free(setup->pdad_pin);
//    gpio_free(setup->pdda_pin);
}

static int pcm3168_soc_probe(struct snd_soc_codec *codec)
{
     struct pcm3168_setup_data *setup = codec->dev->platform_data;
     int ret = 0;

printk(KERN_ALERT "in SOC Probe codec -> kli \n");

     printk(KERN_INFO "PCM3168 SoC Audio Codec %s\n", PCM3168_VERSION);

     return ret;

gpio_err:
//    pcm3168_gpio_free(setup);

     return ret;
}

static int pcm3168_soc_remove(struct snd_soc_codec *codec)
{
     struct pcm3168_setup_data *setup = codec->dev->platform_data;

//    pcm3168_gpio_free(setup);
     return 0;
}


#define pcm3168_soc_suspend NULL
#define pcm3168_soc_resume NULL


static struct snd_soc_codec_driver soc_codec_dev_pcm3168 = {
     .probe =     pcm3168_soc_probe,
     .remove =     pcm3168_soc_remove,
     .suspend =    pcm3168_soc_suspend,
     .resume =    pcm3168_soc_resume,
};

static int __devinit pcm3168_codec_probe(struct platform_device *pdev)
{
     int ret;
     printk(KERN_ALERT "probe pcm3168 codec -> kli \n");

     ret = snd_soc_register_codec(&pdev->dev,
             &soc_codec_dev_pcm3168, &pcm3168_dai, 1);

     printk(KERN_ALERT "probe_after pcm3168 codec -> kli = %d \n", ret);

     return ret;
}

static int __devexit pcm3168_codec_remove(struct platform_device *pdev)
{
     printk(KERN_ALERT "remove pcm3168 codec -> kli \n");

     snd_soc_unregister_codec(&pdev->dev);
     return 0;
}

MODULE_ALIAS("platform:pcm3168-codec");

static struct platform_driver pcm3168_codec_driver = {
     .probe        = pcm3168_codec_probe,
     .remove        = __devexit_p(pcm3168_codec_remove),
     .driver        = {
         .name        = "pcm3168-codec",
         .owner        = THIS_MODULE,
     },
};

static int __init pcm3168_modinit(void)
{
     printk(KERN_ALERT "in init of 3168 -> kli \n");
     return platform_driver_register(&pcm3168_codec_driver);
}
module_init(pcm3168_modinit);

static void __exit pcm3168_exit(void)
{
     printk(KERN_ALERT "in exit of 3168 -> kli \n");
     platform_driver_unregister(&pcm3168_codec_driver);
}
module_exit(pcm3168_exit);

MODULE_DESCRIPTION("Soc PCM3168 driver");
MODULE_AUTHOR("Klimann Wendelin <wklimann@hotmail.com>");
MODULE_LICENSE("GPL");

^ permalink raw reply	[flat|nested] 11+ messages in thread

* Re: ASoC: BeagleBoard driver development (PCM3168)
  2013-03-23 14:37           ` Wendelin Klimann
@ 2013-03-23 15:57             ` Daniel Mack
  2013-03-23 21:56               ` wendelin klimann
  0 siblings, 1 reply; 11+ messages in thread
From: Daniel Mack @ 2013-03-23 15:57 UTC (permalink / raw)
  To: Wendelin Klimann; +Cc: Peter Ujfalusi, alsa-devel

On 23.03.2013 15:37, Wendelin Klimann wrote:
> Hello Peter
> 
> I am stuck again in my ASoc driver development and it would be really 
> nice if you could give me an hint how i could solve this.
> 
> Acctually i try to connect my PCM3168 Audio Codec to the McBSP on the 
> BeagleBoard.
> My new driver loads fine and i got 2 soundcards:
> 
> *root@beagleboard:/lib/modules/3.7.4+/kernel/sound/soc/omap# aplay -l*
>     **** List of PLAYBACK Hardware Devices ****
>     card 0: omap3beagle [omap3beagle], device 0: TWL4030 twl4030-hifi-0 []
>       Subdevices: 1/1
>       Subdevice #0: subdevice #0
>     card 1: pcm3168 [pcm3168], device 0: PCM3168 pcm3168-hifi-0 []
>       Subdevices: 1/1
>       Subdevice #0: subdevice #0
> 
> Your TWL4030 driver is still working perfect with:
> 
> *root@beagleboard:/lib/modules/3.7.4+/kernel/sound/soc/omap# aplay 
> -Dhw:0,0 /home/root/fifi.wav*
>     [ 1245.302551] omap-dma-engine omap-dma-engine: allocating channel 
> for 33
>     Playing WAVE '/home/root/fifi.wav' : Signed 16 bit Little Endian, 
> Rate 44100 Hz, Stereo
> 
> but when i play the same file with my new driver i get an error (as 
> codec master and also as codec slave):
> 
> *root@beagleboard:/lib/modules/3.7.4+/kernel/sound/soc/omap# aplay 
> -Dhw:1,0 /home/root/fifi.wav*
>     [ 1128.677337] omap-dma-engine omap-dma-engine: allocating channel 
> for 17
>     Playing WAVE '/h[ 1128.689544] can't set codec DAI configuration - 
> pcm3168

This is where your trouble starts, and the reason is that when you call
snd_soc_dai_set_fmt() on your codec dai, the core will do this:

        if (dai->driver->ops->set_fmt == NULL)
                return -ENOTSUPP;

And because you didn't implement that callback in your codec driver, the
setup will fail. You need to implement that callback, and acknowledge
that the codec is able to operate under the wanted conditions. See other
codec drivers for a reference.

Also, you seem to wildly mix machine and codec code, which is exactly
what ASoC tries to prevent. Codec drivers are completely separated from
the machine part, because they are supposed to be exchangeable. See what
other machine code and codec drivers do. In general, as soon you as you
import a machine or platform specific header file from your codec code,
you're doing something wrong.


HTH,
Daniel

^ permalink raw reply	[flat|nested] 11+ messages in thread

* Re: ASoC: BeagleBoard driver development (PCM3168)
  2013-03-23 15:57             ` Daniel Mack
@ 2013-03-23 21:56               ` wendelin klimann
  2013-03-24  0:12                 ` Daniel Mack
  0 siblings, 1 reply; 11+ messages in thread
From: wendelin klimann @ 2013-03-23 21:56 UTC (permalink / raw)
  To: Daniel Mack; +Cc: Peter Ujfalusi, alsa-devel

Hello Daniel


> *root@beagleboard:/lib/modules/3.7.4+/kernel/sound/soc/omap# aplay

> > -Dhw:1,0 /home/root/fifi.wav*
> >     [ 1128.677337] omap-dma-engine omap-dma-engine: allocating channel
> > for 17
> >     Playing WAVE '/h[ 1128.689544] can't set codec DAI configuration -
> > pcm3168
>
> This is where your trouble starts, and the reason is that when you call
> snd_soc_dai_set_fmt() on your codec dai, the core will do this:
>
>         if (dai->driver->ops->set_fmt == NULL)
>                 return -ENOTSUPP;
>
> And because you didn't implement that callback in your codec driver, the
> setup will fail. You need to implement that callback, and acknowledge
> that the codec is able to operate under the wanted conditions. See other
> codec drivers for a reference.
>

Thanks that helped to understand the problem and i was able to measure
first signals on my McBSP :-)


>
> Also, you seem to wildly mix machine and codec code, which is exactly
> what ASoC tries to prevent. Codec drivers are completely separated from
> the machine part, because they are supposed to be exchangeable. See what
> other machine code and codec drivers do. In general, as soon you as you
> import a machine or platform specific header file from your codec code,
> you're doing something wrong.
>
>
well i had several headers in my codec file which were not used but i think
there is no code which is mixed between the codec- and the machine-driver.
Next time i will clean up my code before sending it.

Thanks a lot for the fast answer
Wendelin


ps.:
The cleaned up files are added, if there are still mixes between the codec-
and machine-driver i would be glad if you could tell me.

******************************************************************************************************
*
kernel_3.7.4+/sound/soc/codecs/pcm3168.c
*
******************************************************************************************************
/*
 * ALSA Soc PCM3168 codec support
 *
 * Author: Klimann Wendelin <wklimann@hotmail.com>
 *
 * based on:
 *   > pcm3008.c
 *   > Author:    Hugo Villeneuve
 *   > Copyright (C) 2008 Lyrtech inc
 *   >
 *   > Based on AC97 Soc codec, original copyright follow:
 *   > Copyright 2005 Wolfson Microelectronics PLC.
 *
 * This program is free software; you can redistribute it and/or
 * modify it under the terms of the GNU General Public License
 * version 2 as published by the Free Software Foundation.
 *
 * 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., 51 Franklin St, Fifth Floor, Boston, MA
 * 02110-1301 USA
 */

#include <linux/init.h>
#include <linux/kernel.h>
#include <linux/device.h>
#include <linux/gpio.h>
#include <linux/slab.h>
#include <linux/module.h>
#include <linux/clk.h>
#include <linux/platform_device.h>
#include <linux/module.h>
#include <sound/core.h>
#include <sound/initval.h>
#include <sound/pcm.h>
#include <sound/pcm_params.h>
#include <sound/soc.h>

#include "pcm3168.h"

#define PCM3168_VERSION "0.1"


static int pcm3168_hw_params(struct snd_pcm_substream *substream,
                struct snd_pcm_hw_params *params,
                struct snd_soc_dai *dai)
{
    struct snd_soc_pcm_runtime *rtd = substream->private_data;
    struct snd_soc_codec *codec = rtd->codec;

    dev_dbg(codec->dev, "Sample format 0x%X\n", params_format(params));
    dev_dbg(codec->dev, "Channels %d\n", params_channels(params));
    dev_dbg(codec->dev, "Rate %d\n", params_rate(params));

    return 0;
}

static int pcm3168_set_dai_fmt(struct snd_soc_dai *codec_dai,
                  unsigned int fmt)
{
    struct snd_soc_codec *codec = codec_dai->codec;

    /* codec role */
    switch (fmt & SND_SOC_DAIFMT_MASTER_MASK) {
    case SND_SOC_DAIFMT_CBM_CFM:
        dev_dbg(codec->dev, "Codec is master\n");
        break;
    case SND_SOC_DAIFMT_CBS_CFS:
        dev_dbg(codec->dev, "Codec is slave\n");
        break;
    default:
        return -EINVAL;
    }

    /* DAI format */
    dev_dbg(codec->dev, "DAI format 0x%X",
        fmt & SND_SOC_DAIFMT_FORMAT_MASK);

    /* Bit clock and frame sync polarities */
    dev_dbg(codec->dev, "Clock polarities 0x%X\n",
        fmt & SND_SOC_DAIFMT_INV_MASK);

    return 0;
}

#define PCM3168_RATES   SNDRV_PCM_RATE_8000_96000 /*(SNDRV_PCM_RATE_32000 |
SNDRV_PCM_RATE_44100 |    \
               SNDRV_PCM_RATE_48000)*/
#define PCM3168_FORMATS     (SNDRV_PCM_FMTBIT_S16_LE |
SNDRV_PCM_FMTBIT_S32_LE)

static const struct snd_soc_dai_ops pcm3168_dai_hifi_ops = {
    .hw_params    = pcm3168_hw_params,
    .set_fmt    = pcm3168_set_dai_fmt,
};

static struct snd_soc_dai_driver pcm3168_dai = {
    .name = "pcm3168-hifi",
    .playback = {
        .stream_name = "PCM3168 Playback",
        .channels_min = 2,
        .channels_max = 8,
        .rates = PCM3168_RATES,
        .formats = PCM3168_FORMATS,     //SNDRV_PCM_FMTBIT_S16_LE,
//SNDRV_PCM_FMTBIT_S32_LE
        .sig_bits = 24,
    },
    .capture = {
        .stream_name = "PCM3168 Capture",
        .channels_min = 2,
        .channels_max = 6,
        .rates = PCM3168_RATES,
        .formats = PCM3168_FORMATS,     //SNDRV_PCM_FMTBIT_S16_LE,
//SNDRV_PCM_FMTBIT_S32_LE
        .sig_bits = 24,
    },
    .ops = &pcm3168_dai_hifi_ops,
};

static int pcm3168_soc_probe(struct snd_soc_codec *codec)
{
    struct pcm3168_setup_data *setup = codec->dev->platform_data;
    int ret = 0;

    printk(KERN_INFO "PCM3168 SoC Audio Codec %s\n", PCM3168_VERSION);

    return ret;
}

static int pcm3168_soc_remove(struct snd_soc_codec *codec)
{
    struct pcm3168_setup_data *setup = codec->dev->platform_data;

    return 0;
}

#define pcm3168_soc_suspend NULL
#define pcm3168_soc_resume NULL

static struct snd_soc_codec_driver soc_codec_dev_pcm3168 = {
    .probe =     pcm3168_soc_probe,
    .remove =     pcm3168_soc_remove,
    .suspend =    pcm3168_soc_suspend,
    .resume =    pcm3168_soc_resume,
};

static int __devinit pcm3168_codec_probe(struct platform_device *pdev)
{
    int ret;
    printk(KERN_ALERT "probe pcm3168 codec -> kli \n");

    ret = snd_soc_register_codec(&pdev->dev,
            &soc_codec_dev_pcm3168, &pcm3168_dai, 1);

    printk(KERN_ALERT "probe_after pcm3168 codec -> kli = %d \n", ret);

    return ret;
}

static int __devexit pcm3168_codec_remove(struct platform_device *pdev)
{
    printk(KERN_ALERT "remove pcm3168 codec -> kli \n");

    snd_soc_unregister_codec(&pdev->dev);
    return 0;
}

static struct platform_driver pcm3168_codec_driver = {
    .probe        = pcm3168_codec_probe,
    .remove        = __devexit_p(pcm3168_codec_remove),
    .driver        = {
        .name        = "pcm3168-codec",
        .owner        = THIS_MODULE,
    },
};

static int __init pcm3168_modinit(void)
{
    printk(KERN_ALERT "in init of 3168 -> kli \n");
    return platform_driver_register(&pcm3168_codec_driver);
}
module_init(pcm3168_modinit);

static void __exit pcm3168_exit(void)
{
    printk(KERN_ALERT "in exit of 3168 -> kli \n");
    platform_driver_unregister(&pcm3168_codec_driver);
}
module_exit(pcm3168_exit);

MODULE_DESCRIPTION("Soc PCM3168 driver");
MODULE_AUTHOR("Klimann Wendelin <wklimann@hotmail.com>");
MODULE_LICENSE("GPL");
MODULE_ALIAS("platform:pcm3168-codec");



******************************************************************************************************
*
kernel_3.7.4+/sound/soc/omap/omap-pcm3168.c
*
******************************************************************************************************
/*
 * PCM3168 ASoC driver for BeagleBoard.
 *
 * based on:
 *   > omap3beagle.c  --  SoC audio for OMAP3 Beagle
 *   > Author: Steve Sakoman <steve@sakoman.com>
 *
 * adapted by Klimann Wendelin <wklimann@hotmail.com>
 *
 *
 * This program is free software; you can redistribute it and/or
 * modify it under the terms of the GNU General Public License
 * version 2 as published by the Free Software Foundation.
 *
 * 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., 51 Franklin St, Fifth Floor, Boston, MA
 * 02110-1301 USA
 *
 */

#include <linux/clk.h>
#include <linux/platform_device.h>
#include <linux/module.h>
#include <sound/core.h>
#include <sound/pcm.h>
#include <sound/soc.h>
#include <sound/pcm_params.h>

#include <asm/mach-types.h>
#include <mach/hardware.h>
#include <mach/gpio.h>
//#include <plat/mcbsp.h>

#include "omap-mcbsp.h"
#include "omap-pcm.h"

/*
 * Uncomment to test codec in slave mode or without actual codec. This makes
 * possible to test this driver by letting the OMAP to be DAI link master
 */
#define PCM3168_CODEC_SLAVE        1


static int pcm3168_hw_params(struct snd_pcm_substream *substream,
    struct snd_pcm_hw_params *params)
{
    struct snd_soc_pcm_runtime *rtd = substream->private_data;
    struct snd_soc_dai *codec_dai = rtd->codec_dai;
    struct snd_soc_dai *cpu_dai = rtd->cpu_dai;
    unsigned int fmt, div;
    int ret;

#ifdef PCM3168_CODEC_SLAVE
        fmt =    SND_SOC_DAIFMT_DSP_B |
                SND_SOC_DAIFMT_CBS_CFS |
                SND_SOC_DAIFMT_IB_NF;
#else
        fmt =    SND_SOC_DAIFMT_DSP_B |
                SND_SOC_DAIFMT_CBM_CFM |
                SND_SOC_DAIFMT_IB_NF;
#endif

    /* Set codec DAI configuration */
    ret = snd_soc_dai_set_fmt(codec_dai, fmt);
    if (ret < 0) {
        printk(KERN_ERR "can't set codec DAI configuration - pcm3168\n");
        return ret;
    }

    /* Set cpu DAI configuration */
    ret = snd_soc_dai_set_fmt(cpu_dai, fmt);
    if (ret < 0) {
        printk(KERN_ERR "can't set cpu DAI configuration - pcm3168\n");
        return ret;
    }

#ifdef PCM3168_CODEC_SLAVE

    ret = snd_soc_dai_set_sysclk(cpu_dai, OMAP_MCBSP_SYSCLK_CLKS_FCLK,
                     48000000, SND_SOC_CLOCK_IN);
    if (ret < 0) {
        pr_err("can't set McBSP sysclk - pcm3168\n");
        return ret;
    }

    /*
     * Calculate McBSP SRG divisor in McBSP master mode
     */
    div = 48000000 / params_rate(params) / params_channels(params);

    switch (params_format(params)) {
    case SNDRV_PCM_FORMAT_S16_LE:
        div /= 16;
        break;
    case SNDRV_PCM_FORMAT_S24_LE:
    case SNDRV_PCM_FORMAT_S32_LE:
        div /= 32;
        break;
    };

    /*
     * Round to maximum divisor if needed. This means that extra bit-clock
     * cycles are transmitted when sample rate and number of bits in frame
     * (channels * sample bits) are low.
     */
    if (div >= 256)
        div = 256;

    ret = snd_soc_dai_set_clkdiv(cpu_dai, OMAP_MCBSP_CLKGDV, div);
    if (ret < 0) {
        pr_err("can't set SRG clock divider - pcm3168\n");
        return ret;
    }
#endif

    return 0;
}

static struct snd_soc_ops pcm3168_ops = {
    .hw_params = pcm3168_hw_params,
};

/* Digital audio interface glue - connects codec <--> CPU */
static struct snd_soc_dai_link pcm3168_dai = {
    .name = "PCM3168",
    .stream_name = "PCM3168",
    .cpu_dai_name = "omap-mcbsp.3",
    .platform_name = "omap-pcm-audio",
    .codec_dai_name = "pcm3168-hifi",
    .codec_name = "pcm3168-codec.0",
    .ops = &pcm3168_ops,
};

/* Audio machine driver */
static struct snd_soc_card snd_soc_pcm3168 = {
    .name = "pcm3168",
    .owner = THIS_MODULE,
    .dai_link = &pcm3168_dai,
    .num_links = 1,
};

struct platform_device pcm3168_codec = {
        .name = "pcm3168-codec",
        .id = 0,
};

struct platform_device pcm3168_soc_audio = {
        .name = "pcm3168-soc-audio",
        .id = 0,
};

static int __devinit pcm3168_soc_probe(struct platform_device *pdev)
{
    struct snd_soc_card *card = &snd_soc_pcm3168;
    int ret;

    pr_info("OMAP3 Beagle - PCM3168 ASoC init\n");
    card->dev = &pdev->dev;

    ret = snd_soc_register_card(card);
    if (ret) {
        dev_err(&pdev->dev, "snd_soc_register_card() failed: %d -
pcm3168\n",
            ret);
        return ret;
    }
    return 0;
}

static int __devexit pcm3168_soc_remove(struct platform_device *pdev)
{
    struct snd_soc_card *card = platform_get_drvdata(pdev);
    snd_soc_unregister_card(card);

    return 0;
}

static struct platform_driver pcm3168_driver = {
    .driver = {
        .name = "pcm3168-soc-audio",
        .owner = THIS_MODULE,
    },
    .probe = pcm3168_soc_probe,
    .remove = __devexit_p(pcm3168_soc_remove),
};

static int __init pcm3168_soc_init(void)
{
    platform_device_register(&pcm3168_codec);
    platform_device_register(&pcm3168_soc_audio);
    return platform_driver_register(&pcm3168_driver);
}
module_init(pcm3168_soc_init);

static void __exit pcm3168_soc_exit(void)
{
    platform_driver_unregister(&pcm3168_driver);
    platform_device_unregister(&pcm3168_soc_audio);
    platform_device_unregister(&pcm3168_codec);
}
module_exit(pcm3168_soc_exit);

MODULE_AUTHOR("Klimann Wendelin <wklimann@hotmail.com>");
MODULE_DESCRIPTION("ALSA SoC PCM3168 add on Soundcard");
MODULE_LICENSE("GPL");
MODULE_ALIAS("platform:pcm3168-soc-audio");

^ permalink raw reply	[flat|nested] 11+ messages in thread

* Re: ASoC: BeagleBoard driver development (PCM3168)
  2013-03-23 21:56               ` wendelin klimann
@ 2013-03-24  0:12                 ` Daniel Mack
  2013-04-04 13:15                   ` Wendelin Klimann
  0 siblings, 1 reply; 11+ messages in thread
From: Daniel Mack @ 2013-03-24  0:12 UTC (permalink / raw)
  To: wendelin klimann; +Cc: Peter Ujfalusi, alsa-devel

On 23.03.2013 22:56, wendelin klimann wrote:
> The cleaned up files are added, if there are still mixes between the
> codec- and machine-driver i would be glad if you could tell me. 

It looks much better already, but your codec functions are currently
just stubs. So you need to fill them with logic that actually sets up
the hardware of course, and you should use regmap for abstracting the
registers.

Also, the codec driver has to become a i2c/spi driver rather than a
platform device. There are tons of other drivers for reference.

There are many smaller things to comment on, but you can submit the
codec driver first once you're finished, so it can be reviewed
independently from the rest. Note, however, that all new drivers have to
be written in a device-tree aware fashion.


Daniel



> 
> ******************************************************************************************************
> *          
> kernel_3.7.4+/sound/soc/codecs/pcm3168.c                                                
> *
> ******************************************************************************************************
> /*
>  * ALSA Soc PCM3168 codec support
>  *
>  * Author: Klimann Wendelin <wklimann@hotmail.com
> <mailto:wklimann@hotmail.com>>
>  *
>  * based on:
>  *   > pcm3008.c
>  *   > Author:    Hugo Villeneuve
>  *   > Copyright (C) 2008 Lyrtech inc
>  *   >
>  *   > Based on AC97 Soc codec, original copyright follow:
>  *   > Copyright 2005 Wolfson Microelectronics PLC.
>  *
>  * This program is free software; you can redistribute it and/or
>  * modify it under the terms of the GNU General Public License
>  * version 2 as published by the Free Software Foundation.
>  *
>  * 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., 51 Franklin St, Fifth Floor, Boston, MA
>  * 02110-1301 USA
>  */
> 
> #include <linux/init.h>
> #include <linux/kernel.h>
> #include <linux/device.h>
> #include <linux/gpio.h>
> #include <linux/slab.h>
> #include <linux/module.h>
> #include <linux/clk.h>
> #include <linux/platform_device.h>
> #include <linux/module.h>
> #include <sound/core.h>
> #include <sound/initval.h>
> #include <sound/pcm.h>
> #include <sound/pcm_params.h>
> #include <sound/soc.h>
> 
> #include "pcm3168.h"
> 
> #define PCM3168_VERSION "0.1"
> 
> 
> static int pcm3168_hw_params(struct snd_pcm_substream *substream,
>                 struct snd_pcm_hw_params *params,
>                 struct snd_soc_dai *dai)
> {
>     struct snd_soc_pcm_runtime *rtd = substream->private_data;
>     struct snd_soc_codec *codec = rtd->codec;
> 
>     dev_dbg(codec->dev, "Sample format 0x%X\n", params_format(params));
>     dev_dbg(codec->dev, "Channels %d\n", params_channels(params));
>     dev_dbg(codec->dev, "Rate %d\n", params_rate(params));
> 
>     return 0;
> }
> 
> static int pcm3168_set_dai_fmt(struct snd_soc_dai *codec_dai,
>                   unsigned int fmt)
> {
>     struct snd_soc_codec *codec = codec_dai->codec;
> 
>     /* codec role */
>     switch (fmt & SND_SOC_DAIFMT_MASTER_MASK) {
>     case SND_SOC_DAIFMT_CBM_CFM:
>         dev_dbg(codec->dev, "Codec is master\n");
>         break;
>     case SND_SOC_DAIFMT_CBS_CFS:
>         dev_dbg(codec->dev, "Codec is slave\n");
>         break;
>     default:
>         return -EINVAL;
>     }
> 
>     /* DAI format */
>     dev_dbg(codec->dev, "DAI format 0x%X",
>         fmt & SND_SOC_DAIFMT_FORMAT_MASK);
> 
>     /* Bit clock and frame sync polarities */
>     dev_dbg(codec->dev, "Clock polarities 0x%X\n",
>         fmt & SND_SOC_DAIFMT_INV_MASK);
> 
>     return 0;
> }
> 
> #define PCM3168_RATES   SNDRV_PCM_RATE_8000_96000
> /*(SNDRV_PCM_RATE_32000 | SNDRV_PCM_RATE_44100 |    \
>                SNDRV_PCM_RATE_48000)*/
> #define PCM3168_FORMATS     (SNDRV_PCM_FMTBIT_S16_LE |
> SNDRV_PCM_FMTBIT_S32_LE)
> 
> static const struct snd_soc_dai_ops pcm3168_dai_hifi_ops = {
>     .hw_params    = pcm3168_hw_params,
>     .set_fmt    = pcm3168_set_dai_fmt,
> };
> 
> static struct snd_soc_dai_driver pcm3168_dai = {
>     .name = "pcm3168-hifi",
>     .playback = {
>         .stream_name = "PCM3168 Playback",
>         .channels_min = 2,
>         .channels_max = 8,
>         .rates = PCM3168_RATES,
>         .formats = PCM3168_FORMATS,     //SNDRV_PCM_FMTBIT_S16_LE,
> //SNDRV_PCM_FMTBIT_S32_LE
>         .sig_bits = 24,
>     },
>     .capture = {
>         .stream_name = "PCM3168 Capture",
>         .channels_min = 2,
>         .channels_max = 6,
>         .rates = PCM3168_RATES,
>         .formats = PCM3168_FORMATS,     //SNDRV_PCM_FMTBIT_S16_LE,
> //SNDRV_PCM_FMTBIT_S32_LE
>         .sig_bits = 24,
>     },
>     .ops = &pcm3168_dai_hifi_ops,
> };
> 
> static int pcm3168_soc_probe(struct snd_soc_codec *codec)
> {
>     struct pcm3168_setup_data *setup = codec->dev->platform_data;
>     int ret = 0;
> 
>     printk(KERN_INFO "PCM3168 SoC Audio Codec %s\n", PCM3168_VERSION);
> 
>     return ret;
> }
> 
> static int pcm3168_soc_remove(struct snd_soc_codec *codec)
> {
>     struct pcm3168_setup_data *setup = codec->dev->platform_data;
> 
>     return 0;
> }
> 
> #define pcm3168_soc_suspend NULL
> #define pcm3168_soc_resume NULL
> 
> static struct snd_soc_codec_driver soc_codec_dev_pcm3168 = {
>     .probe =     pcm3168_soc_probe,
>     .remove =     pcm3168_soc_remove,
>     .suspend =    pcm3168_soc_suspend,
>     .resume =    pcm3168_soc_resume,
> };
> 
> static int __devinit pcm3168_codec_probe(struct platform_device *pdev)
> {
>     int ret;
>     printk(KERN_ALERT "probe pcm3168 codec -> kli \n");
> 
>     ret = snd_soc_register_codec(&pdev->dev,
>             &soc_codec_dev_pcm3168, &pcm3168_dai, 1);
> 
>     printk(KERN_ALERT "probe_after pcm3168 codec -> kli = %d \n", ret);
> 
>     return ret;
> }
> 
> static int __devexit pcm3168_codec_remove(struct platform_device *pdev)
> {
>     printk(KERN_ALERT "remove pcm3168 codec -> kli \n");
> 
>     snd_soc_unregister_codec(&pdev->dev);
>     return 0;
> }
> 
> static struct platform_driver pcm3168_codec_driver = {
>     .probe        = pcm3168_codec_probe,
>     .remove        = __devexit_p(pcm3168_codec_remove),
>     .driver        = {
>         .name        = "pcm3168-codec",
>         .owner        = THIS_MODULE,
>     },
> };
> 
> static int __init pcm3168_modinit(void)
> {
>     printk(KERN_ALERT "in init of 3168 -> kli \n");
>     return platform_driver_register(&pcm3168_codec_driver);
> }
> module_init(pcm3168_modinit);
> 
> static void __exit pcm3168_exit(void)
> {
>     printk(KERN_ALERT "in exit of 3168 -> kli \n");
>     platform_driver_unregister(&pcm3168_codec_driver);
> }
> module_exit(pcm3168_exit);
> 
> MODULE_DESCRIPTION("Soc PCM3168 driver");
> MODULE_AUTHOR("Klimann Wendelin <wklimann@hotmail.com
> <mailto:wklimann@hotmail.com>>");
> MODULE_LICENSE("GPL");
> MODULE_ALIAS("platform:pcm3168-codec");
> 
> 
> 
> ******************************************************************************************************
> *          
> kernel_3.7.4+/sound/soc/omap/omap-pcm3168.c                                             
> *
> ******************************************************************************************************
> /*
>  * PCM3168 ASoC driver for BeagleBoard.
>  *
>  * based on:
>  *   > omap3beagle.c  --  SoC audio for OMAP3 Beagle
>  *   > Author: Steve Sakoman <steve@sakoman.com <mailto:steve@sakoman.com>>
>  *
>  * adapted by Klimann Wendelin <wklimann@hotmail.com
> <mailto:wklimann@hotmail.com>>
>  *
>  *
>  * This program is free software; you can redistribute it and/or
>  * modify it under the terms of the GNU General Public License
>  * version 2 as published by the Free Software Foundation.
>  *
>  * 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., 51 Franklin St, Fifth Floor, Boston, MA
>  * 02110-1301 USA
>  *
>  */
> 
> #include <linux/clk.h>
> #include <linux/platform_device.h>
> #include <linux/module.h>
> #include <sound/core.h>
> #include <sound/pcm.h>
> #include <sound/soc.h>
> #include <sound/pcm_params.h>
> 
> #include <asm/mach-types.h>
> #include <mach/hardware.h>
> #include <mach/gpio.h>
> //#include <plat/mcbsp.h>
> 
> #include "omap-mcbsp.h"
> #include "omap-pcm.h"
> 
> /*
>  * Uncomment to test codec in slave mode or without actual codec. This makes
>  * possible to test this driver by letting the OMAP to be DAI link master
>  */
> #define PCM3168_CODEC_SLAVE        1
> 
> 
> static int pcm3168_hw_params(struct snd_pcm_substream *substream,
>     struct snd_pcm_hw_params *params)
> {
>     struct snd_soc_pcm_runtime *rtd = substream->private_data;
>     struct snd_soc_dai *codec_dai = rtd->codec_dai;
>     struct snd_soc_dai *cpu_dai = rtd->cpu_dai;
>     unsigned int fmt, div;
>     int ret;
> 
> #ifdef PCM3168_CODEC_SLAVE
>         fmt =    SND_SOC_DAIFMT_DSP_B |
>                 SND_SOC_DAIFMT_CBS_CFS |
>                 SND_SOC_DAIFMT_IB_NF;
> #else
>         fmt =    SND_SOC_DAIFMT_DSP_B |
>                 SND_SOC_DAIFMT_CBM_CFM |
>                 SND_SOC_DAIFMT_IB_NF;
> #endif
> 
>     /* Set codec DAI configuration */
>     ret = snd_soc_dai_set_fmt(codec_dai, fmt);
>     if (ret < 0) {
>         printk(KERN_ERR "can't set codec DAI configuration - pcm3168\n");
>         return ret;
>     }
> 
>     /* Set cpu DAI configuration */
>     ret = snd_soc_dai_set_fmt(cpu_dai, fmt);
>     if (ret < 0) {
>         printk(KERN_ERR "can't set cpu DAI configuration - pcm3168\n");
>         return ret;
>     }
> 
> #ifdef PCM3168_CODEC_SLAVE
> 
>     ret = snd_soc_dai_set_sysclk(cpu_dai, OMAP_MCBSP_SYSCLK_CLKS_FCLK,
>                      48000000, SND_SOC_CLOCK_IN);
>     if (ret < 0) {
>         pr_err("can't set McBSP sysclk - pcm3168\n");
>         return ret;
>     }
> 
>     /*
>      * Calculate McBSP SRG divisor in McBSP master mode
>      */
>     div = 48000000 / params_rate(params) / params_channels(params);
> 
>     switch (params_format(params)) {
>     case SNDRV_PCM_FORMAT_S16_LE:
>         div /= 16;
>         break;
>     case SNDRV_PCM_FORMAT_S24_LE:
>     case SNDRV_PCM_FORMAT_S32_LE:
>         div /= 32;
>         break;
>     };
> 
>     /*
>      * Round to maximum divisor if needed. This means that extra bit-clock
>      * cycles are transmitted when sample rate and number of bits in frame
>      * (channels * sample bits) are low.
>      */
>     if (div >= 256)
>         div = 256;
> 
>     ret = snd_soc_dai_set_clkdiv(cpu_dai, OMAP_MCBSP_CLKGDV, div);
>     if (ret < 0) {
>         pr_err("can't set SRG clock divider - pcm3168\n");
>         return ret;
>     }
> #endif
> 
>     return 0;
> }
> 
> static struct snd_soc_ops pcm3168_ops = {
>     .hw_params = pcm3168_hw_params,
> };
> 
> /* Digital audio interface glue - connects codec <--> CPU */
> static struct snd_soc_dai_link pcm3168_dai = {
>     .name = "PCM3168",
>     .stream_name = "PCM3168",
>     .cpu_dai_name = "omap-mcbsp.3",
>     .platform_name = "omap-pcm-audio",
>     .codec_dai_name = "pcm3168-hifi",
>     .codec_name = "pcm3168-codec.0",
>     .ops = &pcm3168_ops,
> };
> 
> /* Audio machine driver */
> static struct snd_soc_card snd_soc_pcm3168 = {
>     .name = "pcm3168",
>     .owner = THIS_MODULE,
>     .dai_link = &pcm3168_dai,
>     .num_links = 1,
> };
> 
> struct platform_device pcm3168_codec = {
>         .name = "pcm3168-codec",
>         .id = 0,
> };
> 
> struct platform_device pcm3168_soc_audio = {
>         .name = "pcm3168-soc-audio",
>         .id = 0,
> };
> 
> static int __devinit pcm3168_soc_probe(struct platform_device *pdev)
> {
>     struct snd_soc_card *card = &snd_soc_pcm3168;
>     int ret;
> 
>     pr_info("OMAP3 Beagle - PCM3168 ASoC init\n");
>     card->dev = &pdev->dev;
> 
>     ret = snd_soc_register_card(card);
>     if (ret) {
>         dev_err(&pdev->dev, "snd_soc_register_card() failed: %d -
> pcm3168\n",
>             ret);
>         return ret;
>     }
>     return 0;
> }
> 
> static int __devexit pcm3168_soc_remove(struct platform_device *pdev)
> {
>     struct snd_soc_card *card = platform_get_drvdata(pdev);
>     snd_soc_unregister_card(card);
> 
>     return 0;
> }
> 
> static struct platform_driver pcm3168_driver = {
>     .driver = {
>         .name = "pcm3168-soc-audio",
>         .owner = THIS_MODULE,
>     },
>     .probe = pcm3168_soc_probe,
>     .remove = __devexit_p(pcm3168_soc_remove),
> };
> 
> static int __init pcm3168_soc_init(void)
> {
>     platform_device_register(&pcm3168_codec);
>     platform_device_register(&pcm3168_soc_audio);
>     return platform_driver_register(&pcm3168_driver);
> }
> module_init(pcm3168_soc_init);
> 
> static void __exit pcm3168_soc_exit(void)
> {
>     platform_driver_unregister(&pcm3168_driver);
>     platform_device_unregister(&pcm3168_soc_audio);
>     platform_device_unregister(&pcm3168_codec);
> }
> module_exit(pcm3168_soc_exit);
> 
> MODULE_AUTHOR("Klimann Wendelin <wklimann@hotmail.com
> <mailto:wklimann@hotmail.com>>");
> MODULE_DESCRIPTION("ALSA SoC PCM3168 add on Soundcard");
> MODULE_LICENSE("GPL");
> MODULE_ALIAS("platform:pcm3168-soc-audio");
> 

^ permalink raw reply	[flat|nested] 11+ messages in thread

* Re: ASoC: BeagleBoard driver development (PCM3168)
  2013-03-24  0:12                 ` Daniel Mack
@ 2013-04-04 13:15                   ` Wendelin Klimann
  2013-04-04 13:29                     ` Daniel Mack
  0 siblings, 1 reply; 11+ messages in thread
From: Wendelin Klimann @ 2013-04-04 13:15 UTC (permalink / raw)
  To: Daniel Mack; +Cc: Peter Ujfalusi, alsa-devel

Hello

Well i gess slowly i get some success, as i have some kind of audio 
output on the audio codec :-)

    On 23.03.2013 22:56, wendelin klimann wrote:

>     The cleaned up files are added, if there are still mixes between the
>     codec- and machine-driver i would be glad if you could tell me.

    It looks much better already, but your codec functions are currently
    just stubs. So you need to fill them with logic that actually sets up
    the hardware of course, and you should use regmap for abstracting the
    registers.

Do you mean that i should setup the audiocodec over i2c/spi or miss i 
something else?

      Also, the codec driver has to become a i2c/spi driver rather than a
    platform device. There are tons of other drivers for reference.

I am trying to add support for i2c but can not find how to setup the 
correct i2c -> that one which will be used for the communication (i2c-2 
in my case)
It would be nice if you could give me an hint how to find that.

    There are many smaller things to comment on, but you can submit the
    codec driver first once you're finished, so it can be reviewed
    independently from the rest. Note, however, that all new drivers have to
    be written in a device-tree aware fashion.

I give my best to learn from other device drivers :-)

Acctually i am stuck at a point where i get just 4 channels instead of 8 
channels audio output on my audio codec (PCM3168 from TI)
i get every second channel on the audio codec
(alsa channel 1 -> to audio codec channel 1;
  alsa channel 3 -> to audio codec channel 2;
  alsa channel 5 -> to audio codec channel 3;
  alsa channel 7 -> to audio codec channel 4)

The audio codec is setup to use I2S-TDM (24Bit (32Bit frame), 48kHz) 
mode and i test the system with:

soc/omap# speaker-test -Dhw:1,0 -c8 -twav

    speaker-test 1.0.25

    Playback device is hw:1,0
    Stream parameters are 48000Hz, S16_LE, 8 channels
    WAV file(s)
    [  657.989562] omap-dma-engine omap-dma-engine: allocating channel
    for 17
    Rate set to 48000Hz (requested 48000Hz)
    Buffer size range from 16 to 8192
    Period size range from 2 to 4096
    Using max buffer size 8192
    Periods = 4
    was set period_size = 2048
    was set buffer_size = 8192
      0 - Front Left
      4 - Center
      1 - Front Right
      7 - Side Right
      3 - Rear Right
      2 - Rear Left
      6 - Side Left
      5 - LFE
    Time per period = 11.223022

When i meassure the digital signal with an osziloscope i see that alsa 
send all 8 channels (16Bit) on just half of the LRCKL

  ________________________________
|                                |                              |
|                                |                              | LRCKL 
- AD/DA
|                                |                              |
|                                |______________________________|

|       all 8 channels           |           nothing            |  AudioCodec-IN  / Alsa-OUT


I gess that is because it is using S16_LE format instead of a S32_LE 
format but till now i was not able to find a way to change that neither 
in the driver by changing the

#define PCM3168_FORMATS SNDRV_PCM_FMTBIT_S32_LE

nor by using

speaker-test -Dhw:1,0 -c8 -twav -FS32_LE

which has the same output as the one without -F32_LE


Please help and thanks in advance

Wendelin



******************************************************************************************************
* kernel_3.7.4+/sound/soc/codecs/pcm3168.c *
******************************************************************************************************

/*
  * ALSA Soc PCM3168 codec support
  *
  * Author: Klimann Wendelin <wklimann@hotmail.com 
<mailto:wklimann@hotmail.com>>
  *
  * based on:
  *   > pcm3008.c
  *   > Author:    Hugo Villeneuve
  *   > Copyright (C) 2008 Lyrtech inc
  *   >
  *   > Based on AC97 Soc codec, original copyright follow:
  *   > Copyright 2005 Wolfson Microelectronics PLC.
  *
  * This program is free software; you can redistribute it and/or
  * modify it under the terms of the GNU General Public License
  * version 2 as published by the Free Software Foundation.
  *
  * 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., 51 Franklin St, Fifth Floor, Boston, MA
  * 02110-1301 USA
  */

#include <linux/init.h>
#include <linux/kernel.h>
#include <linux/device.h>
#include <linux/gpio.h>
#include <linux/slab.h>
#include <linux/module.h>
#include <linux/clk.h>
#include <linux/platform_device.h>
#include <linux/module.h>
#include <sound/core.h>
#include <sound/initval.h>
#include <sound/pcm.h>
#include <sound/pcm_params.h>
#include <sound/soc.h>

#include "pcm3168.h"

#define PCM3168_VERSION "0.1"


static int pcm3168_hw_params(struct snd_pcm_substream *substream,
                 struct snd_pcm_hw_params *params,
                 struct snd_soc_dai *dai)
{
     struct snd_soc_pcm_runtime *rtd = substream->private_data;
     struct snd_soc_codec *codec = rtd->codec;

     dev_dbg(codec->dev, "Sample format 0x%X\n", params_format(params));
     dev_dbg(codec->dev, "Channels %d\n", params_channels(params));
     dev_dbg(codec->dev, "Rate %d\n", params_rate(params));

     return 0;
}

static int pcm3168_set_dai_fmt(struct snd_soc_dai *codec_dai,
                   unsigned int fmt)
{
     struct snd_soc_codec *codec = codec_dai->codec;

     /* codec role */
     switch (fmt & SND_SOC_DAIFMT_MASTER_MASK) {
     case SND_SOC_DAIFMT_CBM_CFM:
         dev_dbg(codec->dev, "Codec is master\n");
         break;
     case SND_SOC_DAIFMT_CBS_CFS:
         dev_dbg(codec->dev, "Codec is slave\n");
         break;
     default:
         return -EINVAL;
     }

     /* DAI format */
     dev_dbg(codec->dev, "DAI format 0x%X",
         fmt & SND_SOC_DAIFMT_FORMAT_MASK);

     /* Bit clock and frame sync polarities */
     dev_dbg(codec->dev, "Clock polarities 0x%X\n",
         fmt & SND_SOC_DAIFMT_INV_MASK);

     return 0;
}

#define PCM3168_RATES   SNDRV_PCM_RATE_8000_96000 
/*(SNDRV_PCM_RATE_32000 | SNDRV_PCM_RATE_44100 |    \
                SNDRV_PCM_RATE_48000)*/
#define PCM3168_FORMATS     (SNDRV_PCM_FMTBIT_S16_LE | 
SNDRV_PCM_FMTBIT_S32_LE)

static const struct snd_soc_dai_ops pcm3168_dai_hifi_ops = {
     .hw_params    = pcm3168_hw_params,
     .set_fmt    = pcm3168_set_dai_fmt,
};

static struct snd_soc_dai_driver pcm3168_dai = {
     .name = "pcm3168-hifi",
     .playback = {
         .stream_name = "PCM3168 Playback",
         .channels_min = 8,
         .channels_max = 8,
         .rates = PCM3168_RATES,
         .formats = PCM3168_FORMATS,  //SNDRV_PCM_FMTBIT_S16_LE, 
//SNDRV_PCM_FMTBIT_S32_LE
         .sig_bits = 24,
     },
     .capture = {
         .stream_name = "PCM3168 Capture",
         .channels_min = 6,
         .channels_max = 6,
         .rates = PCM3168_RATES,
         .formats = PCM3168_FORMATS,  //SNDRV_PCM_FMTBIT_S16_LE, 
//SNDRV_PCM_FMTBIT_S32_LE
         .sig_bits = 24,
     },
     .ops = &pcm3168_dai_hifi_ops,
};

static int pcm3168_soc_probe(struct snd_soc_codec *codec)
{
     struct pcm3168_setup_data *setup = codec->dev->platform_data;
     int ret = 0;

     printk(KERN_INFO "PCM3168 SoC Audio Codec %s\n", PCM3168_VERSION);

     return ret;
}

static int pcm3168_soc_remove(struct snd_soc_codec *codec)
{
     struct pcm3168_setup_data *setup = codec->dev->platform_data;

     return 0;
}

#define pcm3168_soc_suspend NULL
#define pcm3168_soc_resume NULL

static struct snd_soc_codec_driver soc_codec_dev_pcm3168 = {
     .probe =     pcm3168_soc_probe,
     .remove =     pcm3168_soc_remove,
     .suspend =    pcm3168_soc_suspend,
     .resume =    pcm3168_soc_resume,
};

static int __devinit pcm3168_codec_probe(struct platform_device *pdev)
{
     int ret;
     printk(KERN_ALERT "probe pcm3168 codec -> kli \n");

     ret = snd_soc_register_codec(&pdev->dev,
             &soc_codec_dev_pcm3168, &pcm3168_dai, 1);

     printk(KERN_ALERT "probe_after pcm3168 codec -> kli = %d \n", ret);

     return ret;
}

static int __devexit pcm3168_codec_remove(struct platform_device *pdev)
{
     printk(KERN_ALERT "remove pcm3168 codec -> kli \n");

     snd_soc_unregister_codec(&pdev->dev);
     return 0;
}

static struct platform_driver pcm3168_codec_driver = {
     .probe        = pcm3168_codec_probe,
     .remove        = __devexit_p(pcm3168_codec_remove),
     .driver        = {
         .name        = "pcm3168-codec",
         .owner        = THIS_MODULE,
     },
};

static int __init pcm3168_modinit(void)
{
     printk(KERN_ALERT "in init of 3168 -> kli \n");
     return platform_driver_register(&pcm3168_codec_driver);
}
module_init(pcm3168_modinit);

static void __exit pcm3168_exit(void)
{
     printk(KERN_ALERT "in exit of 3168 -> kli \n");
     platform_driver_unregister(&pcm3168_codec_driver);
}
module_exit(pcm3168_exit);

MODULE_DESCRIPTION("Soc PCM3168 driver");
MODULE_AUTHOR("Klimann Wendelin <wklimann@hotmail.com 
<mailto:wklimann@hotmail.com>>");
MODULE_LICENSE("GPL");
MODULE_ALIAS("platform:pcm3168-codec");




******************************************************************************************************
* kernel_3.7.4+/sound/soc/omap/omap-pcm3168.c *
******************************************************************************************************

/*
  * PCM3168 ASoC driver for BeagleBoard.
  *
  * based on:
  *   > omap3beagle.c  --  SoC audio for OMAP3 Beagle
  *   > Author: Steve Sakoman <steve@sakoman.com <mailto:steve@sakoman.com>>
  *
  * adapted by Klimann Wendelin <wklimann@hotmail.com 
<mailto:wklimann@hotmail.com>>
  *
  *
  * This program is free software; you can redistribute it and/or
  * modify it under the terms of the GNU General Public License
  * version 2 as published by the Free Software Foundation.
  *
  * 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., 51 Franklin St, Fifth Floor, Boston, MA
  * 02110-1301 USA
  *
  */

#include <linux/clk.h>
#include <linux/platform_device.h>
#include <linux/module.h>
#include <sound/core.h>
#include <sound/pcm.h>
#include <sound/soc.h>
#include <sound/pcm_params.h>

#include <asm/mach-types.h>
#include <mach/hardware.h>
#include <mach/gpio.h>
//#include <plat/mcbsp.h>

#include "omap-mcbsp.h"
#include "omap-pcm.h"


/*
  * Uncomment to test codec in slave mode or without actual codec. This 
makes
  * possible to test this driver by letting the OMAP to be DAI link master
  */
//#define PCM3168_CODEC_SLAVE        1



static int pcm3168_hw_params(struct snd_pcm_substream *substream,
     struct snd_pcm_hw_params *params)
{
     struct snd_soc_pcm_runtime *rtd = substream->private_data;
     struct snd_soc_dai *codec_dai = rtd->codec_dai;
     struct snd_soc_dai *cpu_dai = rtd->cpu_dai;
     unsigned int fmt, div;
     int ret;


#ifdef PCM3168_CODEC_SLAVE
         fmt =    SND_SOC_DAIFMT_I2S |
                 SND_SOC_DAIFMT_CBS_CFS |
                 SND_SOC_DAIFMT_NB_NF;
#else
         fmt =    SND_SOC_DAIFMT_I2S |
                 SND_SOC_DAIFMT_CBM_CFM |
                 SND_SOC_DAIFMT_NB_NF;
#endif


     /* Set codec DAI configuration */
     ret = snd_soc_dai_set_fmt(codec_dai, fmt);
     if (ret < 0) {
         printk(KERN_ERR "can't set codec DAI configuration - pcm3168\n");
         return ret;
     }

     /* Set cpu DAI configuration */
     ret = snd_soc_dai_set_fmt(cpu_dai, fmt);
     if (ret < 0) {
         printk(KERN_ERR "can't set cpu DAI configuration - pcm3168\n");
         return ret;
     }

     /* Set the codec system clock for DAC and ADC */
     /*
     ret = snd_soc_dai_set_sysclk(codec_dai, 0, 26000000,
                      SND_SOC_CLOCK_IN);
     if (ret < 0) {
         printk(KERN_ERR "can't set codec system clock\n");
         return ret;
     }*/


#ifdef PCM3168_CODEC_SLAVE

     ret = snd_soc_dai_set_sysclk(cpu_dai, OMAP_MCBSP_SYSCLK_CLKS_FCLK,
                      48000000, SND_SOC_CLOCK_IN);
     if (ret < 0) {
         pr_err("can't set McBSP sysclk - pcm3168\n");
         return ret;
     }

     /*
      * Calculate McBSP SRG divisor in McBSP master mode
      */
     div = 48000000 / params_rate(params) / params_channels(params);

     switch (params_format(params)) {
     case SNDRV_PCM_FORMAT_S16_LE:
         div /= 16;
         break;
     case SNDRV_PCM_FORMAT_S24_LE:
     case SNDRV_PCM_FORMAT_S32_LE:
         div /= 32;
         break;
     };


     /*
      * Round to maximum divisor if needed. This means that extra bit-clock
      * cycles are transmitted when sample rate and number of bits in frame
      * (channels * sample bits) are low.
      */
     if (div >= 256)
         div = 256;

     ret = snd_soc_dai_set_clkdiv(cpu_dai, OMAP_MCBSP_CLKGDV, div);
     if (ret < 0) {
         pr_err("can't set SRG clock divider - pcm3168\n");
         return ret;
     }

#endif


     return 0;
}

static struct snd_soc_ops pcm3168_ops = {
     .hw_params = pcm3168_hw_params,
};

/* Digital audio interface glue - connects codec <--> CPU */
static struct snd_soc_dai_link pcm3168_dai = {
     .name = "PCM3168",
     .stream_name = "PCM3168",
     .cpu_dai_name = "omap-mcbsp.3",
     .platform_name = "omap-pcm-audio",
     .codec_dai_name = "pcm3168-hifi",
     .codec_name = "pcm3168-codec.0",
     .ops = &pcm3168_ops,
};

/* Audio machine driver */
static struct snd_soc_card snd_soc_pcm3168 = {
     .name = "pcm3168",
     .owner = THIS_MODULE,
     .dai_link = &pcm3168_dai,
     .num_links = 1,
};

struct platform_device pcm3168_codec = {
         .name = "pcm3168-codec",
         .id = 0,
};

struct platform_device pcm3168_soc_audio = {
         .name = "pcm3168-soc-audio",
         .id = 0,
};

static int __devinit pcm3168_soc_probe(struct platform_device *pdev)
{
     struct snd_soc_card *card = &snd_soc_pcm3168;
     int ret;

     pr_info("OMAP3 Beagle - PCM3168 ASoC init\n");

     card->dev = &pdev->dev;

     ret = snd_soc_register_card(card);
     if (ret) {
         dev_err(&pdev->dev, "snd_soc_register_card() failed: %d - 
pcm3168\n",
             ret);
         return ret;
     }

     return 0;
}

static int __devexit pcm3168_soc_remove(struct platform_device *pdev)
{
     struct snd_soc_card *card = platform_get_drvdata(pdev);

     snd_soc_unregister_card(card);

     return 0;
}

static struct platform_driver pcm3168_driver = {
     .driver = {
         .name = "pcm3168-soc-audio",
         .owner = THIS_MODULE,
     },

     .probe = pcm3168_soc_probe,
     .remove = __devexit_p(pcm3168_soc_remove),
};


static int __init pcm3168_soc_init(void)
{
     platform_device_register(&pcm3168_codec);
     platform_device_register(&pcm3168_soc_audio);
     return platform_driver_register(&pcm3168_driver);
}
module_init(pcm3168_soc_init);

static void __exit pcm3168_soc_exit(void)
{
     platform_driver_unregister(&pcm3168_driver);
     platform_device_unregister(&pcm3168_soc_audio);
     platform_device_unregister(&pcm3168_codec);
}
module_exit(pcm3168_soc_exit);

MODULE_AUTHOR("Klimann Wendelin <wklimann@hotmail.com 
<mailto:wklimann@hotmail.com>>");
MODULE_DESCRIPTION("ALSA SoC PCM3168 add on Soundcard");
MODULE_LICENSE("GPL");
MODULE_ALIAS("platform:pcm3168-soc-audio");


  

^ permalink raw reply	[flat|nested] 11+ messages in thread

* Re: ASoC: BeagleBoard driver development (PCM3168)
  2013-04-04 13:15                   ` Wendelin Klimann
@ 2013-04-04 13:29                     ` Daniel Mack
  0 siblings, 0 replies; 11+ messages in thread
From: Daniel Mack @ 2013-04-04 13:29 UTC (permalink / raw)
  To: Wendelin Klimann; +Cc: Peter Ujfalusi, alsa-devel

Hi,

there's something badly wrong with your mail client. Please do not send
HTML emails and configure your client for proper quoting.

On 04.04.2013 15:15, Wendelin Klimann wrote:
>     On 23.03.2013 22:56, wendelin klimann wrote:
> 
>>     The cleaned up files are added, if there are still mixes between the
>>     codec- and machine-driver i would be glad if you could tell me. 
> 
>     It looks much better already, but your codec functions are currently
>     just stubs. So you need to fill them with logic that actually sets up
>     the hardware of course, and you should use regmap for abstracting the
>     registers.
> 
> Do you mean that i should setup the audiocodec over i2c/spi or miss i
> something else?

Yes, you need to tell the codec which format and frequency it runs on.
Also, you might want to control some volume registers, mute flags or
other mixer switches. As I said, just use regmap for that, which
abstracts the register access for you.

>      Also, the codec driver has to become a i2c/spi driver rather than a
>     platform device. There are tons of other drivers for reference.
> 
> I am trying to add support for i2c but can not find how to setup the
> correct i2c -> that one which will be used for the communication (i2c-2
> in my case)
> It would be nice if you could give me an hint how to find that. 

That is of course not codec driver specific. Why would you want to alter
the codec driver if you want to re-use it on a different platform, where
the chip is wired to some other controller?

This information is configured on the platform side - in board support
files for legacy kernels, in device-tree for newer versions.

Just grep through some board files
(arch/arm/mach-omap2/board-omap3beagle.c for instance) and look for
"i2c_board_info".

>     There are many smaller things to comment on, but you can submit the
>     codec driver first once you're finished, so it can be reviewed
>     independently from the rest. Note, however, that all new drivers have to
>     be written in a device-tree aware fashion.
> 
> I give my best to learn from other device drivers :-)
> 
> Acctually i am stuck at a point where i get just 4 channels instead of 8
> channels audio output on my audio codec (PCM3168 from TI)
> i get every second channel on the audio codec 
> (alsa channel 1 -> to audio codec channel 1;
>  alsa channel 3 -> to audio codec channel 2;
>  alsa channel 5 -> to audio codec channel 3;
>  alsa channel 7 -> to audio codec channel 4)
> 
> The audio codec is setup to use I2S-TDM (24Bit (32Bit frame), 48kHz)
> mode and i test the system with:
> 
> soc/omap# speaker-test -Dhw:1,0 -c8 -twav
> 
>     speaker-test 1.0.25
> 
>     Playback device is hw:1,0
>     Stream parameters are 48000Hz, S16_LE, 8 channels
>     WAV file(s)
>     [  657.989562] omap-dma-engine omap-dma-engine: allocating channel
>     for 17
>     Rate set to 48000Hz (requested 48000Hz)
>     Buffer size range from 16 to 8192
>     Period size range from 2 to 4096
>     Using max buffer size 8192
>     Periods = 4
>     was set period_size = 2048
>     was set buffer_size = 8192
>      0 - Front Left
>      4 - Center
>      1 - Front Right
>      7 - Side Right
>      3 - Rear Right
>      2 - Rear Left
>      6 - Side Left
>      5 - LFE
>     Time per period = 11.223022
> 
> When i meassure the digital signal with an osziloscope i see that alsa
> send all 8 channels (16Bit) on just half of the LRCKL
> 
>  ________________________________
> |                                |                              |
> |                                |                              |  LRCKL
> - AD/DA
> |                                |                              |
> |                                |______________________________|      
> 
> |       all 8 channels           |           nothing            |  AudioCodec-IN  / Alsa-OUT
> 

This has nothing to do with the codec driver of course.

You should trace which audio format is selected on the CPU side.

> static int pcm3168_hw_params(struct snd_pcm_substream *substream,
>                 struct snd_pcm_hw_params *params,
>                 struct snd_soc_dai *dai)
> {
>     struct snd_soc_pcm_runtime *rtd = substream->private_data;
>     struct snd_soc_codec *codec = rtd->codec;
> 
>     dev_dbg(codec->dev, "Sample format 0x%X\n", params_format(params));
>     dev_dbg(codec->dev, "Channels %d\n", params_channels(params));
>     dev_dbg(codec->dev, "Rate %d\n", params_rate(params));
> 
>     return 0;
> }

Again - you have to tell the chip about your runtime configuration when
this function is called.

> 
> static int pcm3168_set_dai_fmt(struct snd_soc_dai *codec_dai,
>                   unsigned int fmt)
> {
>     struct snd_soc_codec *codec = codec_dai->codec;
> 
>     /* codec role */
>     switch (fmt & SND_SOC_DAIFMT_MASTER_MASK) {
>     case SND_SOC_DAIFMT_CBM_CFM:
>         dev_dbg(codec->dev, "Codec is master\n");
>         break;
>     case SND_SOC_DAIFMT_CBS_CFS:
>         dev_dbg(codec->dev, "Codec is slave\n");
>         break;
>     default:
>         return -EINVAL;
>     }
> 
>     /* DAI format */
>     dev_dbg(codec->dev, "DAI format 0x%X",
>         fmt & SND_SOC_DAIFMT_FORMAT_MASK);
> 
>     /* Bit clock and frame sync polarities */
>     dev_dbg(codec->dev, "Clock polarities 0x%X\n",
>         fmt & SND_SOC_DAIFMT_INV_MASK);
> 
>     return 0;
> }

Dito. Your driver cannot work until you fill these functions with life.


Daniel

^ permalink raw reply	[flat|nested] 11+ messages in thread

end of thread, other threads:[~2013-04-04 13:29 UTC | newest]

Thread overview: 11+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2013-02-10 21:50 ASoC: BeagleBoard driver development (PCM3168) wendelin klimann
2013-02-11 13:49 ` Peter Ujfalusi
2013-02-16 12:05   ` wendelin klimann
2013-02-19 11:10     ` Peter Ujfalusi
     [not found]       ` <CAGxc5aDQ5btyvhcEnCcvNJZhRuCZWz8XS9SxOqcgmgBSx+bYZQ@mail.gmail.com>
     [not found]         ` <5124D1EB.9030404@ti.com>
2013-03-01 20:00           ` wendelin klimann
2013-03-23 14:37           ` Wendelin Klimann
2013-03-23 15:57             ` Daniel Mack
2013-03-23 21:56               ` wendelin klimann
2013-03-24  0:12                 ` Daniel Mack
2013-04-04 13:15                   ` Wendelin Klimann
2013-04-04 13:29                     ` Daniel Mack

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.