From e2ba40379836d0e9968bb4ed485f21d8ba67af49 Mon Sep 17 00:00:00 2001 From: Ulf Samuelsson Date: Mon, 29 Dec 2008 15:13:32 +0000 Subject: Use correct filename for patch --- .../2.6.28-rc6-at91-wm8731.patch | 423 --------------------- .../2.6.28-rc6-at91.patch.gz | Bin 84237 -> 0 bytes .../linux-2.6.28-rc6-at91-wm8731.patch | 423 +++++++++++++++++++++ .../linux-2.6.28-rc6-at91.patch.gz | Bin 0 -> 84237 bytes 4 files changed, 423 insertions(+), 423 deletions(-) delete mode 100644 target/device/Atmel/arch-arm/kernel-patches-2.6.28-rc6/2.6.28-rc6-at91-wm8731.patch delete mode 100644 target/device/Atmel/arch-arm/kernel-patches-2.6.28-rc6/2.6.28-rc6-at91.patch.gz create mode 100644 target/device/Atmel/arch-arm/kernel-patches-2.6.28-rc6/linux-2.6.28-rc6-at91-wm8731.patch create mode 100644 target/device/Atmel/arch-arm/kernel-patches-2.6.28-rc6/linux-2.6.28-rc6-at91.patch.gz (limited to 'target/device/Atmel/arch-arm') diff --git a/target/device/Atmel/arch-arm/kernel-patches-2.6.28-rc6/2.6.28-rc6-at91-wm8731.patch b/target/device/Atmel/arch-arm/kernel-patches-2.6.28-rc6/2.6.28-rc6-at91-wm8731.patch deleted file mode 100644 index 4c0a0a289..000000000 --- a/target/device/Atmel/arch-arm/kernel-patches-2.6.28-rc6/2.6.28-rc6-at91-wm8731.patch +++ /dev/null @@ -1,423 +0,0 @@ -diff -urN linux-2.6.28-rc6/sound/soc/at91/at91sam9g20ek_wm8731.c linux-2.6.28-rc6-0rig/sound/soc/at91/at91sam9g20ek_wm8731.c ---- linux-2.6.28-rc6/sound/soc/at91/at91sam9g20ek_wm8731.c 1970-01-01 01:00:00.000000000 +0100 -+++ linux-2.6.28-rc6-0rig/sound/soc/at91/at91sam9g20ek_wm8731.c 2008-11-29 20:33:23.000000000 +0100 -@@ -0,0 +1,383 @@ -+/* -+ * at91sam9g20ek_wm8731 -- SoC audio for AT91SAM9G20-based Atmel AT91SAM9G20EK board. -+ * -+ * Author: Ulf Samuelsson -+ * Atmel Nordic AB. -+ * Created: Mar 29, 2006 -+ * -+ * Based on eti_b1_wm8731.c by: -+ * -+ * Authors: Frank Mandarino -+ * -+ * which is based on corgi.c by: -+ * -+ * Copyright 2005 Wolfson Microelectronics PLC. -+ * Copyright 2005 Openedhand Ltd. -+ * -+ * Authors: Liam Girdwood -+ * Richard Purdie -+ * -+ * 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. -+ * -+ */ -+ -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+ -+#include -+#include -+ -+#include "../codecs/wm8731.h" -+#include "at91-pcm.h" -+#include "at91-ssc.h" -+ -+#define AT91SAM9G20_BASE_SSC AT91SAM9260_BASE_SSC -+#define AT91SAM9G20_ID_SSC AT91SAM9260_ID_SSC -+ -+ -+#if 0 -+#define DBG(x...) printk(KERN_INFO "at91sam9g20ek_wm8731: " x) -+#else -+#define DBG(x...) -+#endif -+ -+static struct clk *pck1_clk; -+static struct clk *pllb_clk; -+ -+ -+static int at91sam9g20ek_startup(struct snd_pcm_substream *substream) -+{ -+ struct snd_soc_pcm_runtime *rtd = substream->private_data; -+ struct snd_soc_dai *codec_dai = rtd->dai->codec_dai; -+ struct snd_soc_dai *cpu_dai = rtd->dai->cpu_dai; -+ int ret; -+ -+ /* cpu clock is the AT91 master clock sent to the SSC */ -+ ret = snd_soc_dai_set_sysclk(cpu_dai, AT91_SYSCLK_MCK, -+ 100000000, SND_SOC_CLOCK_IN); -+ if (ret < 0) -+ return ret; -+ -+ /* codec system clock is supplied by PCK1, set to 12MHz */ -+ ret = snd_soc_dai_set_sysclk(codec_dai, WM8731_SYSCLK, -+ 12000000, SND_SOC_CLOCK_IN); -+ if (ret < 0) -+ return ret; -+ -+ /* Start PCK1 clock. */ -+ clk_enable(pck1_clk); -+ DBG("pck1 started\n"); -+ -+ return 0; -+} -+ -+static void at91sam9g20ek_shutdown(struct snd_pcm_substream *substream) -+{ -+ /* Stop PCK1 clock. */ -+ clk_disable(pck1_clk); -+ DBG("pck1 stopped\n"); -+} -+ -+static int at91sam9g20ek_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->dai->codec_dai; -+ struct snd_soc_dai *cpu_dai = rtd->dai->cpu_dai; -+ int ret; -+ -+#ifdef CONFIG_SND_AT91_SOC_AT91SAM9G20EK_SLAVE -+ unsigned int rate; -+ int cmr_div, period; -+ -+ /* set codec DAI configuration */ -+ ret = snd_soc_dai_set_fmt(codec_dai, SND_SOC_DAIFMT_I2S | -+ SND_SOC_DAIFMT_NB_NF | SND_SOC_DAIFMT_CBS_CFS); -+ if (ret < 0) -+ return ret; -+ -+ /* set cpu DAI configuration */ -+ ret = snd_soc_dai_set_fmt(cpu_dai, SND_SOC_DAIFMT_I2S | -+ SND_SOC_DAIFMT_NB_NF | SND_SOC_DAIFMT_CBS_CFS); -+ if (ret < 0) -+ return ret; -+ -+ /* -+ * The SSC clock dividers depend on the sample rate. The CMR.DIV -+ * field divides the system master clock MCK to drive the SSC TK -+ * signal which provides the codec BCLK. The TCMR.PERIOD and -+ * RCMR.PERIOD fields further divide the BCLK signal to drive -+ * the SSC TF and RF signals which provide the codec DACLRC and -+ * ADCLRC clocks. -+ * -+ * The dividers were determined through trial and error, where a -+ * CMR.DIV value is chosen such that the resulting BCLK value is -+ * divisible, or almost divisible, by (2 * sample rate), and then -+ * the TCMR.PERIOD or RCMR.PERIOD is BCLK / (2 * sample rate) - 1. -+ */ -+ -+ /* -+ * 8000: P=25 D=124 IF=2000000.00 OF= 8000.00 ERROR=0.000000 -+ * 16000: P=22 D=70 IF=2272727.27 OF=16005.12 ERROR=0.000320 -+ * 32000: P=17 D=45 IF=2941176.47 OF=31969.31 ERROR=0.000959 -+ * 48000: P=13 D=39 IF=3846153.85 OF=48076.92 ERROR=0.001603 -+ * 11025: P=14 D=161 IF=3571428.57 OF=11022.93 ERROR=0.000188 -+ * 22050: P=14 D=80 IF=3571428.57 OF=22045.86 ERROR=0.000188 -+ * 44100: P=21 D=26 IF=2380952.38 OF=44091.71 ERROR=0.000188 -+ */ -+ rate = params_rate(params); -+ -+ switch (rate) { -+ case 8000: -+ cmr_div = 25; /* BCLK = 100MHz/(2*25) = 2.000000MHz */ -+ period = 124; /* LRC = BCLK/(2*(124+1)) = 8000Hz */ -+ break; -+ case 16000: -+ cmr_div = 22; /* BCLK = 100MHz/(2*22) ~= 2,272727MHz */ -+ period = 70; /* LRC = BCLK/(2*(70+1)) = 16005.12Hz */ -+ break; -+ case 32000: -+ cmr_div = 17; /* BCLK = 100MHz/(2*17) ~= 2.941176MHz */ -+ period = 45; /* LRC = BCLK/(2*(45+1)) = 31969.31Hz */ -+ break; -+ case 48000: -+ cmr_div = 13; /* BCLK = 100MHz/(2*13) ~= 3.846154MHz */ -+ period = 39; /* LRC = BCLK/(2*(39+1)) = 48076.92Hz */ -+ break; -+ case 11025: -+ cmr_div = 14; /* BCLK = 100MHz/(2*14) ~= 3.571429MHz */ -+ period = 161; /* LRC = BCLK/(2*(161+1)) = 11022.93Hz */ -+ break; -+ case 22050: -+ cmr_div = 14; /* BCLK = 100MHz/(2*14) ~= 3.571429MHz */ -+ period = 80; /* LRC = BCLK/(2*(80+1)) = 22045.86Hz */ -+ break; -+ case 44100: -+ cmr_div = 21; /* BCLK = 100MHz/(2*21) ~= 2.380952MHz */ -+ period = 26; /* LRC = BCLK/(2*(26+1)) = 44091.71Hz */ -+ break; -+ default: -+ printk(KERN_WARNING "unsupported rate %d on AT91SAM9G20EK board\n", rate); -+ return -EINVAL; -+ } -+ -+ /* set the MCK divider for BCLK */ -+ ret = snd_soc_dai_set_clkdiv(cpu_dai, AT91SSC_CMR_DIV, cmr_div); -+ if (ret < 0) -+ return ret; -+ -+ if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) { -+ /* set the BCLK divider for DACLRC */ -+ ret = snd_soc_dai_set_clkdiv(cpu_dai, -+ AT91SSC_TCMR_PERIOD, period); -+ } else { -+ /* set the BCLK divider for ADCLRC */ -+ ret = snd_soc_dai_set_clkdiv(cpu_dai, -+ AT91SSC_RCMR_PERIOD, period); -+ } -+ if (ret < 0) -+ return ret; -+ -+#else /* CONFIG_SND_AT91_SOC_AT91SAM9G20EK_SLAVE */ -+ /* -+ * Codec in Master Mode. -+ */ -+ -+ /* set codec DAI configuration */ -+ ret = snd_soc_dai_set_fmt(codec_dai, SND_SOC_DAIFMT_I2S | -+ SND_SOC_DAIFMT_NB_NF | SND_SOC_DAIFMT_CBM_CFM); -+ if (ret < 0) -+ return ret; -+ -+ /* set cpu DAI configuration */ -+ ret = snd_soc_dai_set_fmt(cpu_dai, SND_SOC_DAIFMT_I2S | -+ SND_SOC_DAIFMT_NB_NF | SND_SOC_DAIFMT_CBM_CFM); -+ if (ret < 0) -+ return ret; -+ -+#endif /* CONFIG_SND_AT91_SOC_AT91SAM9G20EK_SLAVE */ -+ -+ return 0; -+} -+ -+static struct snd_soc_ops at91sam9g20ek_ops = { -+ .startup = at91sam9g20ek_startup, -+ .hw_params = at91sam9g20ek_hw_params, -+ .shutdown = at91sam9g20ek_shutdown, -+}; -+ -+ -+static const struct snd_soc_dapm_widget at91sam9g20ek_dapm_widgets[] = { -+ SND_SOC_DAPM_MIC("Int Mic", NULL), -+ SND_SOC_DAPM_SPK("Ext Spk", NULL), -+}; -+ -+static const struct snd_soc_dapm_route intercon[] = { -+ -+ /* speaker connected to LHPOUT */ -+ {"Ext Spk", NULL, "LHPOUT"}, -+ -+ /* mic is connected to Mic Jack, with WM8731 Mic Bias */ -+ {"MICIN", NULL, "Mic Bias"}, -+ {"Mic Bias", NULL, "Int Mic"}, -+}; -+ -+/* -+ * Logic for a wm8731 as connected on a Atmel AT91SAM9G20EK board. -+ */ -+static int at91sam9g20ek_wm8731_init(struct snd_soc_codec *codec) -+{ -+ DBG("at91sam9g20ek_wm8731_init() called\n"); -+ -+ /* Add specific widgets */ -+ snd_soc_dapm_new_controls(codec, at91sam9g20ek_dapm_widgets, -+ ARRAY_SIZE(at91sam9g20ek_dapm_widgets)); -+ -+ /* Set up specific audio path interconnects */ -+ snd_soc_dapm_add_route(codec, intercon, ARRAY_SIZE(intercon)); -+ -+ /* not connected */ -+ snd_soc_dapm_disable_pin(codec, "RLINEIN"); -+ snd_soc_dapm_disable_pin(codec, "LLINEIN"); -+ -+ /* always connected */ -+ snd_soc_dapm_enable_pin(codec, "Int Mic"); -+ snd_soc_dapm_enable_pin(codec, "Ext Spk"); -+ -+ snd_soc_dapm_sync(codec); -+ -+ return 0; -+} -+ -+static struct snd_soc_dai_link at91sam9g20ek_dai = { -+ .name = "WM8731", -+ .stream_name = "WM8731 PCM", -+ .cpu_dai = &at91_ssc_dai[1], -+ .codec_dai = &wm8731_dai, -+ .init = at91sam9g20ek_wm8731_init, -+ .ops = &at91sam9g20ek_ops, -+}; -+ -+static struct snd_soc_machine snd_soc_machine_at91sam9g20ek = { -+ .name = "AT91SAM9G20EK_WM8731", -+ .dai_link = &at91sam9g20ek_dai, -+ .num_links = 1, -+}; -+ -+static struct wm8731_setup_data at91sam9g20ek_wm8731_setup = { -+ .i2c_address = 0x1a, -+}; -+ -+static struct snd_soc_device at91sam9g20ek_snd_devdata = { -+ .machine = &snd_soc_machine_at91sam9g20ek, -+ .platform = &at91_soc_platform, -+ .codec_dev = &soc_codec_dev_wm8731, -+ .codec_data = &at91sam9g20ek_wm8731_setup, -+}; -+ -+static struct platform_device *at91sam9g20ek_snd_device; -+ -+static int __init at91sam9g20ek_init(void) -+{ -+ int ret; -+ struct at91_ssc_periph *ssc = at91sam9g20ek_dai.cpu_dai->private_data; -+ -+ if (!request_mem_region(AT91SAM9G20_BASE_SSC, SZ_16K, "soc-audio")) { -+ DBG("SSC memory region is busy\n"); -+ return -EBUSY; -+ } -+ -+ ssc->base = ioremap(AT91SAM9G20_BASE_SSC, SZ_16K); -+ if (!ssc->base) { -+ DBG("SSC memory ioremap failed\n"); -+ ret = -ENOMEM; -+ goto fail_release_mem; -+ } -+ -+ ssc->pid = AT91SAM9G20_ID_SSC; -+ -+ at91sam9g20ek_snd_device = platform_device_alloc("soc-audio", -1); -+ if (!at91sam9g20ek_snd_device) { -+ DBG("platform device allocation failed\n"); -+ ret = -ENOMEM; -+ goto fail_io_unmap; -+ } -+ -+ platform_set_drvdata(at91sam9g20ek_snd_device, &at91sam9g20ek_snd_devdata); -+ at91sam9g20ek_snd_devdata.dev = &at91sam9g20ek_snd_device->dev; -+ -+ ret = platform_device_add(at91sam9g20ek_snd_device); -+ if (ret) { -+ DBG("platform device add failed\n"); -+ platform_device_put(at91sam9g20ek_snd_device); -+ goto fail_io_unmap; -+ } -+ -+ at91_set_A_periph(AT91_PIN_PB16, 0); /* TK0 */ -+ at91_set_A_periph(AT91_PIN_PB17, 0); /* TF0 */ -+ at91_set_A_periph(AT91_PIN_PB18, 0); /* TD0 */ -+#if 0 /* Bidirectional support not available on the SAM9G20EK */ -+ at91_set_A_periph(AT91_PIN_PB19, 0); /* RD0 */ -+ at91_set_A_periph(AT91_PIN_PB20, 0); /* RK0 */ -+ at91_set_A_periph(AT91_PIN_PB21, 0); /* RF0 */ -+#endif -+ /* -+ * Set PCK1 parent to PLLB and its rate to 12 Mhz. -+ */ -+ pllb_clk = clk_get(NULL, "pllb"); -+ pck1_clk = clk_get(NULL, "pck1"); -+ -+ clk_set_parent(pck1_clk, pllb_clk); -+ clk_set_rate(pck1_clk, 12000000); -+ -+ DBG("MCLK rate %luHz\n", clk_get_rate(pck1_clk)); -+ -+ /* assign the GPIO pin to PCK1 */ -+ at91_set_B_periph(AT91_PIN_PC1, 0); -+ -+#ifdef CONFIG_SND_AT91_SOC_AT91SAM9G20EK_SLAVE -+ printk(KERN_INFO "at91sam9g20ek_wm8731: Codec in Slave Mode\n"); -+#else -+ printk(KERN_INFO "at91sam9g20ek_wm8731: Codec in Master Mode\n"); -+#endif -+ return ret; -+ -+fail_io_unmap: -+ iounmap(ssc->base); -+fail_release_mem: -+ release_mem_region(AT91SAM9G20_BASE_SSC, SZ_16K); -+ return ret; -+} -+ -+static void __exit at91sam9g20ek_exit(void) -+{ -+ struct at91_ssc_periph *ssc = at91sam9g20ek_dai.cpu_dai->private_data; -+ -+ clk_put(pck1_clk); -+ clk_put(pllb_clk); -+ -+ platform_device_unregister(at91sam9g20ek_snd_device); -+ -+ iounmap(ssc->base); -+ release_mem_region(AT91SAM9G20_BASE_SSC, SZ_16K); -+} -+ -+module_init(at91sam9g20ek_init); -+module_exit(at91sam9g20ek_exit); -+ -+/* Module information */ -+MODULE_AUTHOR("Ulf Samuelsson "); -+MODULE_DESCRIPTION("ALSA SoC AT91SAM9G20EK-WM8731"); -+MODULE_LICENSE("GPL"); -diff -urN linux-2.6.28-rc6/sound/soc/at91/Kconfig linux-2.6.28-rc6-0rig/sound/soc/at91/Kconfig ---- linux-2.6.28-rc6/sound/soc/at91/Kconfig 2008-10-10 00:13:53.000000000 +0200 -+++ linux-2.6.28-rc6-0rig/sound/soc/at91/Kconfig 2008-11-29 20:39:30.000000000 +0100 -@@ -25,3 +25,20 @@ - help - Say Y if you want to run with the AT91 SSC generating the BCLK - and LRC signals on Endrelia boards. -+ -+config SND_AT91_SOC_AT91SAM9G20EK_WM8731 -+ tristate "SoC Audio support for WM8731-based Atmel AT91SAM9G20EK boards" -+ depends on SND_AT91_SOC && (MACH_AT91SAM9G20EK) -+ select SND_AT91_SOC_SSC -+ select SND_SOC_WM8731 -+ help -+ Say Y if you want to add support for SoC audio on WM8731-based -+ Atmel AT91SAM9G20EK boards. -+ -+config SND_AT91_SOC_AT91SAM9G20EK_SLAVE -+ bool "Run codec in slave Mode on the AT91SAM92G20EK board" -+ depends on SND_AT91_SOC_AT91SAM9G20EK_WM8731 -+ default n -+ help -+ Say Y if you want to run with the AT91 SSC generating the BCLK -+ and LRC signals on Atmel boards. -diff -urN linux-2.6.28-rc6/sound/soc/at91/Makefile linux-2.6.28-rc6-0rig/sound/soc/at91/Makefile ---- linux-2.6.28-rc6/sound/soc/at91/Makefile 2008-10-10 00:13:53.000000000 +0200 -+++ linux-2.6.28-rc6-0rig/sound/soc/at91/Makefile 2008-11-29 20:39:35.000000000 +0100 -@@ -7,5 +7,8 @@ - - # AT91 Machine Support - snd-soc-eti-b1-wm8731-objs := eti_b1_wm8731.o -+snd-soc-at91sam9g20ek-wm8731-objs := at91sam9g20ek_wm8731.o - - obj-$(CONFIG_SND_AT91_SOC_ETI_B1_WM8731) += snd-soc-eti-b1-wm8731.o -+obj-$(CONFIG_SND_AT91_SOC_AT91SAM9G20_WM8731) += snd-soc-at91sam9g20ek-wm8731.o -+ diff --git a/target/device/Atmel/arch-arm/kernel-patches-2.6.28-rc6/2.6.28-rc6-at91.patch.gz b/target/device/Atmel/arch-arm/kernel-patches-2.6.28-rc6/2.6.28-rc6-at91.patch.gz deleted file mode 100644 index f44dfe178..000000000 Binary files a/target/device/Atmel/arch-arm/kernel-patches-2.6.28-rc6/2.6.28-rc6-at91.patch.gz and /dev/null differ diff --git a/target/device/Atmel/arch-arm/kernel-patches-2.6.28-rc6/linux-2.6.28-rc6-at91-wm8731.patch b/target/device/Atmel/arch-arm/kernel-patches-2.6.28-rc6/linux-2.6.28-rc6-at91-wm8731.patch new file mode 100644 index 000000000..4c0a0a289 --- /dev/null +++ b/target/device/Atmel/arch-arm/kernel-patches-2.6.28-rc6/linux-2.6.28-rc6-at91-wm8731.patch @@ -0,0 +1,423 @@ +diff -urN linux-2.6.28-rc6/sound/soc/at91/at91sam9g20ek_wm8731.c linux-2.6.28-rc6-0rig/sound/soc/at91/at91sam9g20ek_wm8731.c +--- linux-2.6.28-rc6/sound/soc/at91/at91sam9g20ek_wm8731.c 1970-01-01 01:00:00.000000000 +0100 ++++ linux-2.6.28-rc6-0rig/sound/soc/at91/at91sam9g20ek_wm8731.c 2008-11-29 20:33:23.000000000 +0100 +@@ -0,0 +1,383 @@ ++/* ++ * at91sam9g20ek_wm8731 -- SoC audio for AT91SAM9G20-based Atmel AT91SAM9G20EK board. ++ * ++ * Author: Ulf Samuelsson ++ * Atmel Nordic AB. ++ * Created: Mar 29, 2006 ++ * ++ * Based on eti_b1_wm8731.c by: ++ * ++ * Authors: Frank Mandarino ++ * ++ * which is based on corgi.c by: ++ * ++ * Copyright 2005 Wolfson Microelectronics PLC. ++ * Copyright 2005 Openedhand Ltd. ++ * ++ * Authors: Liam Girdwood ++ * Richard Purdie ++ * ++ * 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. ++ * ++ */ ++ ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++ ++#include ++#include ++ ++#include "../codecs/wm8731.h" ++#include "at91-pcm.h" ++#include "at91-ssc.h" ++ ++#define AT91SAM9G20_BASE_SSC AT91SAM9260_BASE_SSC ++#define AT91SAM9G20_ID_SSC AT91SAM9260_ID_SSC ++ ++ ++#if 0 ++#define DBG(x...) printk(KERN_INFO "at91sam9g20ek_wm8731: " x) ++#else ++#define DBG(x...) ++#endif ++ ++static struct clk *pck1_clk; ++static struct clk *pllb_clk; ++ ++ ++static int at91sam9g20ek_startup(struct snd_pcm_substream *substream) ++{ ++ struct snd_soc_pcm_runtime *rtd = substream->private_data; ++ struct snd_soc_dai *codec_dai = rtd->dai->codec_dai; ++ struct snd_soc_dai *cpu_dai = rtd->dai->cpu_dai; ++ int ret; ++ ++ /* cpu clock is the AT91 master clock sent to the SSC */ ++ ret = snd_soc_dai_set_sysclk(cpu_dai, AT91_SYSCLK_MCK, ++ 100000000, SND_SOC_CLOCK_IN); ++ if (ret < 0) ++ return ret; ++ ++ /* codec system clock is supplied by PCK1, set to 12MHz */ ++ ret = snd_soc_dai_set_sysclk(codec_dai, WM8731_SYSCLK, ++ 12000000, SND_SOC_CLOCK_IN); ++ if (ret < 0) ++ return ret; ++ ++ /* Start PCK1 clock. */ ++ clk_enable(pck1_clk); ++ DBG("pck1 started\n"); ++ ++ return 0; ++} ++ ++static void at91sam9g20ek_shutdown(struct snd_pcm_substream *substream) ++{ ++ /* Stop PCK1 clock. */ ++ clk_disable(pck1_clk); ++ DBG("pck1 stopped\n"); ++} ++ ++static int at91sam9g20ek_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->dai->codec_dai; ++ struct snd_soc_dai *cpu_dai = rtd->dai->cpu_dai; ++ int ret; ++ ++#ifdef CONFIG_SND_AT91_SOC_AT91SAM9G20EK_SLAVE ++ unsigned int rate; ++ int cmr_div, period; ++ ++ /* set codec DAI configuration */ ++ ret = snd_soc_dai_set_fmt(codec_dai, SND_SOC_DAIFMT_I2S | ++ SND_SOC_DAIFMT_NB_NF | SND_SOC_DAIFMT_CBS_CFS); ++ if (ret < 0) ++ return ret; ++ ++ /* set cpu DAI configuration */ ++ ret = snd_soc_dai_set_fmt(cpu_dai, SND_SOC_DAIFMT_I2S | ++ SND_SOC_DAIFMT_NB_NF | SND_SOC_DAIFMT_CBS_CFS); ++ if (ret < 0) ++ return ret; ++ ++ /* ++ * The SSC clock dividers depend on the sample rate. The CMR.DIV ++ * field divides the system master clock MCK to drive the SSC TK ++ * signal which provides the codec BCLK. The TCMR.PERIOD and ++ * RCMR.PERIOD fields further divide the BCLK signal to drive ++ * the SSC TF and RF signals which provide the codec DACLRC and ++ * ADCLRC clocks. ++ * ++ * The dividers were determined through trial and error, where a ++ * CMR.DIV value is chosen such that the resulting BCLK value is ++ * divisible, or almost divisible, by (2 * sample rate), and then ++ * the TCMR.PERIOD or RCMR.PERIOD is BCLK / (2 * sample rate) - 1. ++ */ ++ ++ /* ++ * 8000: P=25 D=124 IF=2000000.00 OF= 8000.00 ERROR=0.000000 ++ * 16000: P=22 D=70 IF=2272727.27 OF=16005.12 ERROR=0.000320 ++ * 32000: P=17 D=45 IF=2941176.47 OF=31969.31 ERROR=0.000959 ++ * 48000: P=13 D=39 IF=3846153.85 OF=48076.92 ERROR=0.001603 ++ * 11025: P=14 D=161 IF=3571428.57 OF=11022.93 ERROR=0.000188 ++ * 22050: P=14 D=80 IF=3571428.57 OF=22045.86 ERROR=0.000188 ++ * 44100: P=21 D=26 IF=2380952.38 OF=44091.71 ERROR=0.000188 ++ */ ++ rate = params_rate(params); ++ ++ switch (rate) { ++ case 8000: ++ cmr_div = 25; /* BCLK = 100MHz/(2*25) = 2.000000MHz */ ++ period = 124; /* LRC = BCLK/(2*(124+1)) = 8000Hz */ ++ break; ++ case 16000: ++ cmr_div = 22; /* BCLK = 100MHz/(2*22) ~= 2,272727MHz */ ++ period = 70; /* LRC = BCLK/(2*(70+1)) = 16005.12Hz */ ++ break; ++ case 32000: ++ cmr_div = 17; /* BCLK = 100MHz/(2*17) ~= 2.941176MHz */ ++ period = 45; /* LRC = BCLK/(2*(45+1)) = 31969.31Hz */ ++ break; ++ case 48000: ++ cmr_div = 13; /* BCLK = 100MHz/(2*13) ~= 3.846154MHz */ ++ period = 39; /* LRC = BCLK/(2*(39+1)) = 48076.92Hz */ ++ break; ++ case 11025: ++ cmr_div = 14; /* BCLK = 100MHz/(2*14) ~= 3.571429MHz */ ++ period = 161; /* LRC = BCLK/(2*(161+1)) = 11022.93Hz */ ++ break; ++ case 22050: ++ cmr_div = 14; /* BCLK = 100MHz/(2*14) ~= 3.571429MHz */ ++ period = 80; /* LRC = BCLK/(2*(80+1)) = 22045.86Hz */ ++ break; ++ case 44100: ++ cmr_div = 21; /* BCLK = 100MHz/(2*21) ~= 2.380952MHz */ ++ period = 26; /* LRC = BCLK/(2*(26+1)) = 44091.71Hz */ ++ break; ++ default: ++ printk(KERN_WARNING "unsupported rate %d on AT91SAM9G20EK board\n", rate); ++ return -EINVAL; ++ } ++ ++ /* set the MCK divider for BCLK */ ++ ret = snd_soc_dai_set_clkdiv(cpu_dai, AT91SSC_CMR_DIV, cmr_div); ++ if (ret < 0) ++ return ret; ++ ++ if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) { ++ /* set the BCLK divider for DACLRC */ ++ ret = snd_soc_dai_set_clkdiv(cpu_dai, ++ AT91SSC_TCMR_PERIOD, period); ++ } else { ++ /* set the BCLK divider for ADCLRC */ ++ ret = snd_soc_dai_set_clkdiv(cpu_dai, ++ AT91SSC_RCMR_PERIOD, period); ++ } ++ if (ret < 0) ++ return ret; ++ ++#else /* CONFIG_SND_AT91_SOC_AT91SAM9G20EK_SLAVE */ ++ /* ++ * Codec in Master Mode. ++ */ ++ ++ /* set codec DAI configuration */ ++ ret = snd_soc_dai_set_fmt(codec_dai, SND_SOC_DAIFMT_I2S | ++ SND_SOC_DAIFMT_NB_NF | SND_SOC_DAIFMT_CBM_CFM); ++ if (ret < 0) ++ return ret; ++ ++ /* set cpu DAI configuration */ ++ ret = snd_soc_dai_set_fmt(cpu_dai, SND_SOC_DAIFMT_I2S | ++ SND_SOC_DAIFMT_NB_NF | SND_SOC_DAIFMT_CBM_CFM); ++ if (ret < 0) ++ return ret; ++ ++#endif /* CONFIG_SND_AT91_SOC_AT91SAM9G20EK_SLAVE */ ++ ++ return 0; ++} ++ ++static struct snd_soc_ops at91sam9g20ek_ops = { ++ .startup = at91sam9g20ek_startup, ++ .hw_params = at91sam9g20ek_hw_params, ++ .shutdown = at91sam9g20ek_shutdown, ++}; ++ ++ ++static const struct snd_soc_dapm_widget at91sam9g20ek_dapm_widgets[] = { ++ SND_SOC_DAPM_MIC("Int Mic", NULL), ++ SND_SOC_DAPM_SPK("Ext Spk", NULL), ++}; ++ ++static const struct snd_soc_dapm_route intercon[] = { ++ ++ /* speaker connected to LHPOUT */ ++ {"Ext Spk", NULL, "LHPOUT"}, ++ ++ /* mic is connected to Mic Jack, with WM8731 Mic Bias */ ++ {"MICIN", NULL, "Mic Bias"}, ++ {"Mic Bias", NULL, "Int Mic"}, ++}; ++ ++/* ++ * Logic for a wm8731 as connected on a Atmel AT91SAM9G20EK board. ++ */ ++static int at91sam9g20ek_wm8731_init(struct snd_soc_codec *codec) ++{ ++ DBG("at91sam9g20ek_wm8731_init() called\n"); ++ ++ /* Add specific widgets */ ++ snd_soc_dapm_new_controls(codec, at91sam9g20ek_dapm_widgets, ++ ARRAY_SIZE(at91sam9g20ek_dapm_widgets)); ++ ++ /* Set up specific audio path interconnects */ ++ snd_soc_dapm_add_route(codec, intercon, ARRAY_SIZE(intercon)); ++ ++ /* not connected */ ++ snd_soc_dapm_disable_pin(codec, "RLINEIN"); ++ snd_soc_dapm_disable_pin(codec, "LLINEIN"); ++ ++ /* always connected */ ++ snd_soc_dapm_enable_pin(codec, "Int Mic"); ++ snd_soc_dapm_enable_pin(codec, "Ext Spk"); ++ ++ snd_soc_dapm_sync(codec); ++ ++ return 0; ++} ++ ++static struct snd_soc_dai_link at91sam9g20ek_dai = { ++ .name = "WM8731", ++ .stream_name = "WM8731 PCM", ++ .cpu_dai = &at91_ssc_dai[1], ++ .codec_dai = &wm8731_dai, ++ .init = at91sam9g20ek_wm8731_init, ++ .ops = &at91sam9g20ek_ops, ++}; ++ ++static struct snd_soc_machine snd_soc_machine_at91sam9g20ek = { ++ .name = "AT91SAM9G20EK_WM8731", ++ .dai_link = &at91sam9g20ek_dai, ++ .num_links = 1, ++}; ++ ++static struct wm8731_setup_data at91sam9g20ek_wm8731_setup = { ++ .i2c_address = 0x1a, ++}; ++ ++static struct snd_soc_device at91sam9g20ek_snd_devdata = { ++ .machine = &snd_soc_machine_at91sam9g20ek, ++ .platform = &at91_soc_platform, ++ .codec_dev = &soc_codec_dev_wm8731, ++ .codec_data = &at91sam9g20ek_wm8731_setup, ++}; ++ ++static struct platform_device *at91sam9g20ek_snd_device; ++ ++static int __init at91sam9g20ek_init(void) ++{ ++ int ret; ++ struct at91_ssc_periph *ssc = at91sam9g20ek_dai.cpu_dai->private_data; ++ ++ if (!request_mem_region(AT91SAM9G20_BASE_SSC, SZ_16K, "soc-audio")) { ++ DBG("SSC memory region is busy\n"); ++ return -EBUSY; ++ } ++ ++ ssc->base = ioremap(AT91SAM9G20_BASE_SSC, SZ_16K); ++ if (!ssc->base) { ++ DBG("SSC memory ioremap failed\n"); ++ ret = -ENOMEM; ++ goto fail_release_mem; ++ } ++ ++ ssc->pid = AT91SAM9G20_ID_SSC; ++ ++ at91sam9g20ek_snd_device = platform_device_alloc("soc-audio", -1); ++ if (!at91sam9g20ek_snd_device) { ++ DBG("platform device allocation failed\n"); ++ ret = -ENOMEM; ++ goto fail_io_unmap; ++ } ++ ++ platform_set_drvdata(at91sam9g20ek_snd_device, &at91sam9g20ek_snd_devdata); ++ at91sam9g20ek_snd_devdata.dev = &at91sam9g20ek_snd_device->dev; ++ ++ ret = platform_device_add(at91sam9g20ek_snd_device); ++ if (ret) { ++ DBG("platform device add failed\n"); ++ platform_device_put(at91sam9g20ek_snd_device); ++ goto fail_io_unmap; ++ } ++ ++ at91_set_A_periph(AT91_PIN_PB16, 0); /* TK0 */ ++ at91_set_A_periph(AT91_PIN_PB17, 0); /* TF0 */ ++ at91_set_A_periph(AT91_PIN_PB18, 0); /* TD0 */ ++#if 0 /* Bidirectional support not available on the SAM9G20EK */ ++ at91_set_A_periph(AT91_PIN_PB19, 0); /* RD0 */ ++ at91_set_A_periph(AT91_PIN_PB20, 0); /* RK0 */ ++ at91_set_A_periph(AT91_PIN_PB21, 0); /* RF0 */ ++#endif ++ /* ++ * Set PCK1 parent to PLLB and its rate to 12 Mhz. ++ */ ++ pllb_clk = clk_get(NULL, "pllb"); ++ pck1_clk = clk_get(NULL, "pck1"); ++ ++ clk_set_parent(pck1_clk, pllb_clk); ++ clk_set_rate(pck1_clk, 12000000); ++ ++ DBG("MCLK rate %luHz\n", clk_get_rate(pck1_clk)); ++ ++ /* assign the GPIO pin to PCK1 */ ++ at91_set_B_periph(AT91_PIN_PC1, 0); ++ ++#ifdef CONFIG_SND_AT91_SOC_AT91SAM9G20EK_SLAVE ++ printk(KERN_INFO "at91sam9g20ek_wm8731: Codec in Slave Mode\n"); ++#else ++ printk(KERN_INFO "at91sam9g20ek_wm8731: Codec in Master Mode\n"); ++#endif ++ return ret; ++ ++fail_io_unmap: ++ iounmap(ssc->base); ++fail_release_mem: ++ release_mem_region(AT91SAM9G20_BASE_SSC, SZ_16K); ++ return ret; ++} ++ ++static void __exit at91sam9g20ek_exit(void) ++{ ++ struct at91_ssc_periph *ssc = at91sam9g20ek_dai.cpu_dai->private_data; ++ ++ clk_put(pck1_clk); ++ clk_put(pllb_clk); ++ ++ platform_device_unregister(at91sam9g20ek_snd_device); ++ ++ iounmap(ssc->base); ++ release_mem_region(AT91SAM9G20_BASE_SSC, SZ_16K); ++} ++ ++module_init(at91sam9g20ek_init); ++module_exit(at91sam9g20ek_exit); ++ ++/* Module information */ ++MODULE_AUTHOR("Ulf Samuelsson "); ++MODULE_DESCRIPTION("ALSA SoC AT91SAM9G20EK-WM8731"); ++MODULE_LICENSE("GPL"); +diff -urN linux-2.6.28-rc6/sound/soc/at91/Kconfig linux-2.6.28-rc6-0rig/sound/soc/at91/Kconfig +--- linux-2.6.28-rc6/sound/soc/at91/Kconfig 2008-10-10 00:13:53.000000000 +0200 ++++ linux-2.6.28-rc6-0rig/sound/soc/at91/Kconfig 2008-11-29 20:39:30.000000000 +0100 +@@ -25,3 +25,20 @@ + help + Say Y if you want to run with the AT91 SSC generating the BCLK + and LRC signals on Endrelia boards. ++ ++config SND_AT91_SOC_AT91SAM9G20EK_WM8731 ++ tristate "SoC Audio support for WM8731-based Atmel AT91SAM9G20EK boards" ++ depends on SND_AT91_SOC && (MACH_AT91SAM9G20EK) ++ select SND_AT91_SOC_SSC ++ select SND_SOC_WM8731 ++ help ++ Say Y if you want to add support for SoC audio on WM8731-based ++ Atmel AT91SAM9G20EK boards. ++ ++config SND_AT91_SOC_AT91SAM9G20EK_SLAVE ++ bool "Run codec in slave Mode on the AT91SAM92G20EK board" ++ depends on SND_AT91_SOC_AT91SAM9G20EK_WM8731 ++ default n ++ help ++ Say Y if you want to run with the AT91 SSC generating the BCLK ++ and LRC signals on Atmel boards. +diff -urN linux-2.6.28-rc6/sound/soc/at91/Makefile linux-2.6.28-rc6-0rig/sound/soc/at91/Makefile +--- linux-2.6.28-rc6/sound/soc/at91/Makefile 2008-10-10 00:13:53.000000000 +0200 ++++ linux-2.6.28-rc6-0rig/sound/soc/at91/Makefile 2008-11-29 20:39:35.000000000 +0100 +@@ -7,5 +7,8 @@ + + # AT91 Machine Support + snd-soc-eti-b1-wm8731-objs := eti_b1_wm8731.o ++snd-soc-at91sam9g20ek-wm8731-objs := at91sam9g20ek_wm8731.o + + obj-$(CONFIG_SND_AT91_SOC_ETI_B1_WM8731) += snd-soc-eti-b1-wm8731.o ++obj-$(CONFIG_SND_AT91_SOC_AT91SAM9G20_WM8731) += snd-soc-at91sam9g20ek-wm8731.o ++ diff --git a/target/device/Atmel/arch-arm/kernel-patches-2.6.28-rc6/linux-2.6.28-rc6-at91.patch.gz b/target/device/Atmel/arch-arm/kernel-patches-2.6.28-rc6/linux-2.6.28-rc6-at91.patch.gz new file mode 100644 index 000000000..f44dfe178 Binary files /dev/null and b/target/device/Atmel/arch-arm/kernel-patches-2.6.28-rc6/linux-2.6.28-rc6-at91.patch.gz differ -- cgit v1.2.3