Help to port ADI's codec SSM2603 to at91sam9g45

Discussion around AT91RM9200 and SAM9 Series Products.

Moderator: nferre

Posts: 3
Joined: Mon Jun 27, 2016 3:07 am

Help to port ADI's codec SSM2603 to at91sam9g45

Mon Jul 11, 2016 4:54 pm

Recently I want to port Analog Device's codec :SSM2603 to my at91sam9g45 board with "Ethernet AVB" app; but stopped by this linux driver,I need some guide.

kernel: linux3.10
chip : at91sam9g45;
i2c0 and ssc0 connect to ssm2603 and a 12.288MHz crystal osc connect to it.

I modify the file as follows:


Code: Select all

 * I2C
static struct i2c_board_info __initdata at91_i2c_board_info[]  = {
			I2C_BOARD_INFO("ssm2603",  0x1b)
		#if 0
			I2C_BOARD_INFO("cs2100cp", 0x04)

static struct platform_device sam9g45_audio_device = {
	.name	= "ssm2602",
	.id 	= -1,

static void __init ek_add_device_audio(void)

/* I2C */
at91_add_device_i2c(0, at91_i2c_board_info, ARRAY_SIZE(at91_i2c_board_info));

/* SSC0 */
at91_add_device_ssc(AT91SAM9G45_ID_SSC0, ATMEL_SSC_TX | ATMEL_SSC_RX);

Code: Select all

config SND_AT91_SOC_SAM9G45_SSM2603
        tristate "SoC Audio support for SSM2603-based At91sam9g45 AVB board"
        depends on ARCH_AT91 && ATMEL_SSC && SND_ATMEL_SOC
        select SND_ATMEL_SOC_PDC
        select SND_ATMEL_SOC_SSC
        select SND_SOC_SSM2602
          Say Y if you want to add support for SoC audio on SSM2603-based
          AT91sam9g45 AVB board.

	tristate "DMA support for AT91SAM9G45 SOC INTERFACE"
	depends on ARCH_AT91 && ATMEL_SSC && SND_ATMEL_SOC
	  Say Y if you want to use SOC with AT91 DMA interface.

Code: Select all

# AT91 Platform Support
snd-soc-atmel-pcm-objs := atmel-pcm.o
snd-soc-atmel-pcm-pdc-objs := atmel-pcm-pdc.o
snd-soc-atmel-pcm-dma-objs := atmel-pcm-dma.o
snd-soc-atmel_ssc_dai-objs := atmel_ssc_dai.o

obj-$(CONFIG_SND_ATMEL_SOC) += snd-soc-atmel-pcm.o
obj-$(CONFIG_SND_ATMEL_SOC_PDC) += snd-soc-atmel-pcm-pdc.o
obj-$(CONFIG_SND_ATMEL_SOC_DMA) += snd-soc-atmel-pcm-dma.o
obj-$(CONFIG_SND_ATMEL_SOC_SSC) += snd-soc-atmel_ssc_dai.o

# AT91 Machine Support
snd-soc-sam9g20-wm8731-objs := sam9g20_wm8731.o
snd-soc-sam9x5-wm8731-objs := sam9x5_wm8731.o
snd-atmel-soc-wm8904-objs := atmel_wm8904.o
snd-atmel-soc-sii9022-objs := atmel_sii9022.o
snd-soc-sam9g45-ssm2603-objs := sam9g45_ssm2603.o

obj-$(CONFIG_SND_AT91_SOC_SAM9G20_WM8731) += snd-soc-sam9g20-wm8731.o
obj-$(CONFIG_SND_AT91_SOC_SAM9X5_WM8731) += snd-soc-sam9x5-wm8731.o
obj-$(CONFIG_SND_ATMEL_SOC_WM8904) += snd-atmel-soc-wm8904.o
obj-$(CONFIG_SND_AT91_SOC_AFEB9260) += snd-soc-afeb9260.o
obj-$(CONFIG_SND_ATMEL_SOC_SII9022) += snd-atmel-soc-sii9022.o
obj-$(CONFIG_SND_AT91_SOC_SAM9G45_SSM2603) += snd-soc-sam9g45-ssm2603.o

add sam9g45_ssm2603.c to path /linux-3.10-at91/sound/soc/atmel/* as follows

Code: Select all

#include <linux/of.h>
#include <linux/export.h>
#include <linux/module.h>
#include <linux/mod_devicetable.h>
#include <linux/platform_device.h>
#include <linux/device.h>
#include <linux/interrupt.h>
#include <linux/timer.h>

#include <sound/soc.h>
#include <sound/soc-dai.h>
#include <sound/soc-dapm.h>
#include <sound/core.h>
#include <sound/pcm.h>

#include "../codecs/ssm2602.h"
#include "atmel_ssc_dai.h"

#define MCLK_RATE 12288000

#define DRV_NAME "at91-snd-ssm2603"

static int at91_ssm2603_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;
	unsigned int pll_rate;
	int ret;

	switch (params_rate(params)) {
	case 8000:
	case 12000:
	case 16000:
	case 24000:
	case 32000:
	case 48000:
	case 96000:
		pll_rate  = 12288000;
		return -EINVAL;

	//todo which clock type ? SSM2602_SYSCLK 
	ret = snd_soc_dai_set_sysclk(codec_dai, SSM2602_CLK_CLKOUT, MCLK_RATE,

	return ret;

static int at91sam9g45_ssm2603_init(void)
		"\r\nat91sam9g45_avb_ssm2603 "
		": at91sam9g45_ssm2603_init() called !\r\n");
	return 0;

static struct snd_soc_ops at91_ssm2603_ops = {
	.hw_params = at91_ssm2603_hw_params,

static struct snd_soc_dai_link at91_ssm2603_dai_link = {
	.name = "ssm2602",
	.stream_name = "ssm2602",

	.cpu_dai_name = "at91sam9g45_ssc.0",	//

	.codec_dai_name = "ssm2602-hifi",

	.init = at91sam9g45_ssm2603_init,	//

	.platform_name = "at91sam9g45_ssc.0",	//
	.codec_name = "ssm2603.0-001b",

	.dai_fmt = SND_SOC_DAIFMT_I2S |
	.ops = &at91_ssm2603_ops,

static struct snd_soc_card at91_ssm2603_card = {
	.name = "AVB SSM2603",
	.owner = THIS_MODULE,
	.dai_link = &at91_ssm2603_dai_link,
	.num_links = 1,

static int at91_ssm2603_probe(struct platform_device *pdev)
	int ret;
	struct snd_soc_card *card = &at91_ssm2603_card;
	struct device_node *of_node = pdev->dev.of_node;

	if (!of_node)
		return -ENXIO;

	card->dev = &pdev->dev;

	at91_ssm2603_dai_link.codec_of_node = of_parse_phandle(of_node,
						"audio-codec", 0);
	at91_ssm2603_dai_link.cpu_of_node = of_parse_phandle(of_node,
						"cpu-dai", 0);
	at91_ssm2603_dai_link.platform_of_node =

	if (!at91_ssm2603_dai_link.codec_of_node ||
		return -ENXIO;

	ret = snd_soc_register_card(card);
	if (ret) {
		printk(KERN_ERR "ASoC: snd_soc_ssm2603_register_card() failed\n");
	return ret;

static int at91_ssm2603_remove(struct platform_device *pdev)
	struct snd_soc_card *card = platform_get_drvdata(pdev);


	return 0;

static const struct of_device_id at91_ssm2603_of_match[] = {
	{ .compatible = "atmel,at91-sound", },
MODULE_DEVICE_TABLE(of, at91_ssm2603_of_match);

static struct platform_driver at91_ssm2603_card_driver = {
	.driver = {
		.name = DRV_NAME,
		.owner = THIS_MODULE,
		.of_match_table = of_match_ptr(at91_ssm2603_of_match),
		.pm = &snd_soc_pm_ops,
	.probe = at91_ssm2603_probe,
	.remove = at91_ssm2603_remove,

MODULE_DESCRIPTION("ASoC AVB board SSM2603 driver");
MODULE_AUTHOR("origin Lars-Peter Clausen <>");
my dmesg command print as follows, I don't use "dts":

[root@buildroot ~]# dmesg
Booting Linux on physical CPU 0x0
Linux version 3.10.0 (root@MACBOOK) (gcc version 4.6.3 (Ubuntu/Linaro 4.6.3-1ubuntu5) ) #51 Mon Jul 11 22:13:34 CST 2016
CPU: ARM926EJ-S [41069265] revision 5 (ARMv5TEJ), cr=00053177
CPU: VIVT data cache, VIVT instruction cache
Machine: Atmel AT91SAM9M10G45-EK
Memory policy: ECC disabled, Data cache writeback
AT91: Detected soc type: at91sam9g45
AT91: Detected soc subtype: Unknown
AT91: sram at 0x300000 of 0x10000 mapped at 0xfef68000
On node 0 totalpages: 65536
free_area_init_node: node 0, pgdat c041bde0, node_mem_map c0434000
Normal zone: 512 pages used for memmap
Normal zone: 0 pages reserved
Normal zone: 65536 pages, LIFO batch:15
Clocks: CPU 400 MHz, master 133 MHz, main 12.000 MHz
pcpu-alloc: s0 r0 d32768 u32768 alloc=1*32768
pcpu-alloc: [0] 0
Built 1 zonelists in Zone order, mobility grouping on. Total pages: 65024
Kernel command line: console=ttyS0,115200 mtdparts=atmel_nand:8M(bootstrap/uboot/kernel)ro,-(rootfs) root=/dev/mmcblk0p2 rw rootwait
PID hash table entries: 1024 (order: 0, 4096 bytes)
Dentry cache hash table entries: 32768 (order: 5, 131072 bytes)
Inode-cache hash table entries: 16384 (order: 4, 65536 bytes)
Memory: 256MB = 256MB total
Memory: 255548k/255548k available, 6596k reserved, 0K highmem
Virtual kernel memory layout:
vector : 0xffff0000 - 0xffff1000 ( 4 kB)
fixmap : 0xfff00000 - 0xfffe0000 ( 896 kB)
vmalloc : 0xd0800000 - 0xff000000 ( 744 MB)
lowmem : 0xc0000000 - 0xd0000000 ( 256 MB)
modules : 0xbf000000 - 0xc0000000 ( 16 MB)
.text : 0xc0008000 - 0xc03cee34 (3868 kB)
.init : 0xc03cf000 - 0xc03f4fcc ( 152 kB)
.data : 0xc03f6000 - 0xc041c4e0 ( 154 kB)
.bss : 0xc041c4e0 - 0xc04330dc ( 91 kB)
NR_IRQS:16 nr_irqs:16 16
AT91: 160 gpio irqs in 5 banks
sched_clock: 32 bits at 100 Hz, resolution 10000000ns, wraps every 4294967286ms
Console: colour dummy device 80x30
Calibrating delay loop... 199.06 BogoMIPS (lpj=995328)
pid_max: default: 32768 minimum: 301
Mount-cache hash table entries: 512
CPU: Testing write buffer coherency: ok
Setting up static identity map for 0xc02d3f60 - 0xc02d3fb8
devtmpfs: initialized
pinctrl core: initialized pinctrl subsystem
NET: Registered protocol family 16
DMA: preallocated 256 KiB pool for atomic coherent allocations
i2c-core: driver [dummy] registered
AT91: Power Management (with slow clock mode)
AT91: Starting after software reset
bio: create slab <bio-0> at 0
at_hdmac at91sam9g45_dma: Atmel AHB DMA Controller ( cpy slave ), 8 channels
at91_i2c i2c-at91sam9g10.0: cdiv 165 ckdiv 2
i2c i2c-0: adapter [AT91] registered
i2c 0-001b: uevent
i2c i2c-0: client [ssm2603] registered with bus id 0-001b
at91_i2c i2c-at91sam9g10.0: AT91 i2c bus driver.
pps_core: LinuxPPS API ver. 1 registered
pps_core: Software ver. 5.3.6 - Copyright 2005-2007 Rodolfo Giometti <>
PTP clock support registered
Advanced Linux Sound Architecture Driver Initialized.
Switching to clocksource pit
NET: Registered protocol family 2
TCP established hash table entries: 2048 (order: 2, 16384 bytes)
TCP bind hash table entries: 2048 (order: 1, 8192 bytes)
TCP: Hash tables configured (established 2048 bind 2048)
TCP: reno registered
UDP hash table entries: 256 (order: 0, 4096 bytes)
UDP-Lite hash table entries: 256 (order: 0, 4096 bytes)
NET: Registered protocol family 1
RPC: Registered named UNIX socket transport module.
RPC: Registered udp transport module.
RPC: Registered tcp transport module.
RPC: Registered tcp NFSv4.1 backchannel transport module.
msgmni has been set to 499
io scheduler noop registered (default)
atmel_usart.0: ttyS0 at MMIO 0xffffee00 (irq = 17) is a ATMEL_SERIAL
console [ttyS0] enabled
brd: module loaded
loop: module loaded
ssc at91sam9g45_ssc.0: Atmel SSC device at 0xd0858000 (irq 32)
atmel_spi atmel_spi.0: version: 0x210
atmel_spi atmel_spi.0: Atmel SPI Controller at 0xfffa4000 (irq 30)
atmel_spi atmel_spi.0: master is unqueued, this is deprecated
mtd_dataflash spi0.0: AT45DB161x (2112 KBytes) pagesize 528 bytes (OTP)
macb macb (unregistered net_device): invalid hw address, using random
libphy: MACB_mii_bus: probed
macb macb eth0: Cadence rev 0x0001010c
macb macb eth0: Cadence MACB at 0xfffbc000 irq 41 (d2:1d:e2:28:93:ad)
macb macb eth0: attached PHY driver [NatSemi DP83640] (mii_bus:phy_addr=macb-ffffffff:02, irq=162)
at91_rtc at91_rtc: rtc core: registered at91_rtc as rtc0
at91_rtc at91_rtc: AT91 Real Time Clock driver.
i2c /dev entries driver
i2c-dev: adapter [AT91] registered as minor 0
pps_core: source ktimer got cdev (253:0)
pps pps0: new PPS source ktimer
pps pps0: ktimer PPS source registered
pps_ldisc: PPS line discipline registered
ssm2602 0-001b: probe
i2c-core: driver [ssm2602] registered

TCP: cubic registered
NET: Registered protocol family 17
at91_rtc at91_rtc: setting system clock to 2007-01-01 01:04:40 UTC (1167613480)
atmel_mci atmel_mci.0: version: 0x410
atmel_mci atmel_mci.0: using dma0chan0 for DMA transfers
atmel_mci atmel_mci.0: Atmel MCI controller at 0xfff80000 irq 27, 1 slots
ALSA device list:
No soundcards found.

Waiting for root device /dev/mmcblk0p2...
mmc0: host does not support reading read-only switch. assuming write-enable.
mmc0: new high speed SDHC card at address 1234
mmcblk0: mmc0:1234 SA08G 7.24 GiB
mmcblk0: p1 p2
EXT4-fs (mmcblk0p2): couldn't mount as ext3 due to feature incompatibilities
EXT4-fs (mmcblk0p2): mounting ext2 file system using the ext4 subsystem
EXT4-fs (mmcblk0p2): warning: mounting unchecked fs, running e2fsck is recommended
EXT4-fs (mmcblk0p2): mounted filesystem without journal. Opts: (null)
VFS: Mounted root (ext2 filesystem) on device 179:2.
devtmpfs: mounted
Freeing unused kernel memory: 148K (c03cf000 - c03f4000)

shell command:
[root@buildroot ~]# ls /proc/asound/
cards devices pcm timers version
[root@buildroot ~]# cat /proc/asound/cards
--- no soundcards ---
[root@buildroot ~]# cat /proc/asound/version
Advanced Linux Sound Architecture Driver Version k3.10.0.
[root@buildroot ~]#
[root@buildroot ~]# ls /sys/class/sound/
[root@buildroot ~]# ls /dev/snd/
[root@buildroot ~]#

that's all, what should I do ?
Location: USA
Posts: 1497
Joined: Thu Apr 19, 2007 10:15 pm

Re: Help to port ADI's codec SSM2603 to at91sam9g45

Wed Jul 13, 2016 10:09 pm

Normally a post would have a description of the problem.
But you post some code and console output, and expect us to figure out the problem and the solution?

Do you even know if the device is connected properly and is functional?


Return to “SAM9 ARM9 MPU”

Who is online

Users browsing this forum: No registered users and 2 guests