summaryrefslogtreecommitdiff
path: root/recipes/linux
diff options
context:
space:
mode:
authorKristoffer Ericson <kristoffer.ericson@gmail.com>2009-12-27 20:25:22 +0100
committerKristoffer Ericson <kristoffer.ericson@gmail.com>2009-12-27 20:25:22 +0100
commit6e7bc0863c7228f02045b439c9ebf54b7ef67469 (patch)
treec91b91801085fdbb29db4a7d7c24f2d45b6d4f56 /recipes/linux
parent371a4860922514c2ae28c0209c8b0c6ccc41d623 (diff)
Updated JLiMe 2.6.17 kernel. Changes include addition of alsa driver and also rtc.
Signed-off-by: Alex Ferguson <thoughtmonster@gmail.com> Signed-off-by: Kristoffer Ericson <kristoffer.ericson@gmail.com>
Diffstat (limited to 'recipes/linux')
-rw-r--r--recipes/linux/linux-jlime-jornada6xx-2.6.17/LinuxSH-2.6.17.patch15
-rw-r--r--recipes/linux/linux-jlime-jornada6xx-2.6.17/alsa_hp6xx_2.6.17.patch636
-rw-r--r--recipes/linux/linux-jlime-jornada6xx-2.6.17/defconfig_jlime39
-rw-r--r--recipes/linux/linux-jlime-jornada6xx-2.6.17/rtc-2.6.17.patch987
-rw-r--r--recipes/linux/linux-jlime-jornada6xx_2.6.17.bb12
5 files changed, 1675 insertions, 14 deletions
diff --git a/recipes/linux/linux-jlime-jornada6xx-2.6.17/LinuxSH-2.6.17.patch b/recipes/linux/linux-jlime-jornada6xx-2.6.17/LinuxSH-2.6.17.patch
index 104b2e6a89..8c4b54d2e3 100644
--- a/recipes/linux/linux-jlime-jornada6xx-2.6.17/LinuxSH-2.6.17.patch
+++ b/recipes/linux/linux-jlime-jornada6xx-2.6.17/LinuxSH-2.6.17.patch
@@ -9965,8 +9965,8 @@ diff -ruN linux-2.6.17-vanilla/arch/sh/boards/hp6xx/hp6xx_apm.c linux-2.6.17/arc
+#define APM_CRITICAL 10
+#define APM_LOW 30
+
-+#define HP680_BATTERY_MAX 875
-+#define HP680_BATTERY_MIN 600
++#define HP680_BATTERY_MAX 896
++#define HP680_BATTERY_MIN 628
+#define HP680_BATTERY_AC_ON 900
+
+#define MODNAME "hp6x0_apm"
@@ -56277,3 +56277,14 @@ diff -ruN linux-2.6.17-vanilla/sound/sh/aica.h linux-2.6.17/sound/sh/aica.h
+
+#endif
+
+--- linux-2.6.17-vanilla/scripts/mod/sumversion.c 2006-06-18 04:49:35.000000000 +0300
++++ linux-2.6.17/scripts/mod/sumversion.c 2009-12-21 14:43:12.396274319 +0200
+@@ -36,6 +36,8 @@
+ #define MD4_BLOCK_WORDS 16
+ #define MD4_HASH_WORDS 4
+
++#define PATH_MAX 4096 /* # chars in a path name including nul */
++
+ struct md4_ctx {
+ uint32_t hash[MD4_HASH_WORDS];
+ uint32_t block[MD4_BLOCK_WORDS];
diff --git a/recipes/linux/linux-jlime-jornada6xx-2.6.17/alsa_hp6xx_2.6.17.patch b/recipes/linux/linux-jlime-jornada6xx-2.6.17/alsa_hp6xx_2.6.17.patch
new file mode 100644
index 0000000000..bca97bc87b
--- /dev/null
+++ b/recipes/linux/linux-jlime-jornada6xx-2.6.17/alsa_hp6xx_2.6.17.patch
@@ -0,0 +1,636 @@
+diff -up linux-2.6.17/sound/sh/Kconfig linux-2.6.17.alsa/sound/sh/Kconfig
+--- linux-2.6.17/sound/sh/Kconfig 2009-04-05 12:58:14.000000000 -0300
++++ linux-2.6.17.alsa/sound/sh/Kconfig 2009-04-05 11:41:34.000000000 -0300
+@@ -12,4 +12,13 @@ config SND_AICA
+ To compile this driver as a module, choose M here: the module
+ will be called snd-aica.
+
++config SND_SH_DAC_AUDIO
++ tristate "SuperH DAC audio support"
++ depends on SND
++ depends on CPU_SH3
++ select SND_PCM
++ help
++ Alsa Sound driver for the HP Jornada 680/690 and
++ HP Palmtop 620lx/660lx.
++
+ endmenu
+diff -up linux-2.6.17/sound/sh/Makefile linux-2.6.17.alsa/sound/sh/Makefile
+--- linux-2.6.17/sound/sh/Makefile 2009-04-05 12:58:14.000000000 -0300
++++ linux-2.6.17.alsa/sound/sh/Makefile 2009-04-05 11:41:34.000000000 -0300
+@@ -1,4 +1,4 @@
+
+ snd-aica-objs := aica.o
+ obj-$(CONFIG_SND_AICA) += snd-aica.o
+-
++obj-$(CONFIG_SND_SH_DAC_AUDIO) += snd_sh_dac_audio.o
+diff -up linux-2.6.17/sound/sh/snd_sh_dac_audio.c linux-2.6.17.alsa/sound/sh/snd_sh_dac_audio.c
+--- linux-2.6.17/sound/sh/snd_sh_dac_audio.c 2009-04-05 13:00:51.000000000 -0300
++++ linux-2.6.17.alsa/sound/sh/snd_sh_dac_audio.c 2009-04-05 12:24:23.000000000 -0300
+@@ -0,0 +1,606 @@
++/*
++ * snd_sh_dac_audio.c - SuperH DAC audio driver for ALSA
++ *
++ * Copyright (c) 2007 by Rafael Ignacio Zurita <rizurita@yahoo.com>
++ *
++ *
++ * Based completely on sh_dac_audio.c (Copyright (C) 2004,2005 by Andriy
++ * Skulysh) and "Writing an ALSA driver" (Copyright (c) 2002-2005 by Takashi
++ * Iwai <tiwai@suse.de>).
++ *
++ * This program is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License as published by
++ * the Free Software Foundation; either version 2 of the License, or
++ * (at your option) any later version.
++ *
++ * This program is distributed in the hope that it will be useful,
++ * but WITHOUT ANY WARRANTY; without even the implied warranty of
++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
++ * GNU General Public License for more details.
++ *
++ * You should have received a copy of the GNU General Public License
++ * along with this program; if not, write to the Free Software
++ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
++ *
++ */
++
++#include <linux/interrupt.h>
++#include <linux/platform_device.h>
++#include <sound/driver.h>
++#include <sound/core.h>
++#include <sound/pcm.h>
++#include <sound/initval.h>
++#include <asm/io.h>
++#include <asm/clock.h>
++#include <asm/cpu-sh3/dac.h>
++#include <asm/hp6xx/hp6xx.h>
++#include <asm/irq.h>
++#include <asm/hd64461.h>
++
++MODULE_AUTHOR("Rafael Ignacio Zurita <rizurita@yahoo.com>");
++MODULE_DESCRIPTION("SuperH DAC audio driver");
++MODULE_LICENSE("GPL");
++MODULE_SUPPORTED_DEVICE("{{SuperH DAC audio support}}");
++
++/* Module Parameters */
++static int index = SNDRV_DEFAULT_IDX1;
++static char *id = SNDRV_DEFAULT_STR1;
++module_param(index, int, 0444);
++MODULE_PARM_DESC(index, "Index value for SuperH DAC audio.");
++module_param(id, charp, 0444);
++MODULE_PARM_DESC(id, "ID string for SuperH DAC audio.");
++
++/* Simple platform device */
++static struct platform_device *pd;
++
++#define SND_SH_DAC_DRIVER "SH_DAC"
++#define BUFFER_SIZE 64000
++#define SH_DAC_AUDIO_CHANNEL 1
++
++#define HD64461_TMU_TIMR_TMU0 0x01
++#define HD64461_TMU_TIDR (CONFIG_HD64461_IOBASE + 0x600e)
++#define HD64461_TMU_TIRR_TMU0 0x01
++#define HD64461_TMU_TIRR (CONFIG_HD64461_IOBASE + 0x600c)
++#define HD64461_TMU_TCVR0 (CONFIG_HD64461_IOBASE + 0x6002)
++#define PKDR_SPEAKER 0x20
++#define PKDR 0xa4000132
++#define HD64461_GPADR_SPEAKER 0x01
++#define HD64461_TMU_TCR0 (CONFIG_HD64461_IOBASE + 0x600a)
++#define HD64461_TMU_TCR_STRT 0x01 /* Start Counting */
++
++
++/* main struct */
++struct snd_sh_dac {
++ struct snd_card *card;
++ struct snd_pcm_substream *substream;
++ int irq;
++
++ int rate;
++ int empty;
++ char *data_buffer, *buffer_begin, *buffer_end;
++ int processed; /* bytes proccesed, to compare with period_size */
++ int buffer_size;
++};
++
++
++/*
++ * Hardware functions (timer, DAC, speaker)
++ * Note: The driver uses a hd64461 timer
++ */
++
++static void dac_audio_start_timer(void)
++{
++ u16 tmu_tcr;
++
++ /*printk("dac_audio_start_timer\n"); */
++ /* Start HD64461 timer 0 countdown */
++ tmu_tcr = inb(HD64461_TMU_TCR0);
++ tmu_tcr |= HD64461_TMU_TCR_STRT;
++ outb(tmu_tcr, HD64461_TMU_TCR0);
++}
++
++static void dac_audio_stop_timer(void)
++{
++ u16 tmu_tcr;
++
++ /*printk("dac_audio_stop_timer\n"); */
++ /* Stop HD64461 timer 0 countdown */
++ tmu_tcr = inb(HD64461_TMU_TCR0);
++ tmu_tcr &= ~HD64461_TMU_TCR_STRT;
++ outb(tmu_tcr, HD64461_TMU_TCR0);
++}
++
++static void dac_audio_reset(struct snd_sh_dac *chip)
++{
++ /*printk("dac_audio_reset\n"); */
++ dac_audio_stop_timer();
++
++ chip->buffer_begin = chip->buffer_end = chip->data_buffer;
++ chip->processed = 0;
++ chip->empty = 1;
++}
++
++static void dac_audio_sync(struct snd_sh_dac *chip)
++{
++ /*printk("dac_audio_sync\n"); */
++ while (!chip->empty)
++ schedule();
++}
++
++static void dac_audio_start(void)
++{
++ u16 v;
++ u8 v8;
++
++ /*printk("dac_audio_start\n"); */
++ if (mach_is_hp6xx()) {
++ /* HP Jornada 680/690 speaker on */
++ v = inw(HD64461_GPADR);
++ v &= ~HD64461_GPADR_SPEAKER;
++ outw(v, HD64461_GPADR);
++
++ /* HP Palmtop 620lx/660lx speaker on */
++ v8 = inb(PKDR);
++ v8 &= ~PKDR_SPEAKER;
++ outb(v8, PKDR);
++ }
++
++ sh_dac_enable(SH_DAC_AUDIO_CHANNEL);
++}
++
++static void dac_audio_stop(void)
++{
++ u16 v;
++ u8 v8;
++
++ /*printk("dac_audio_stop\n"); */
++ dac_audio_stop_timer();
++
++ if (mach_is_hp6xx()) {
++ /* HP Jornada 680/690 speaker off */
++ v = inw(HD64461_GPADR);
++ v |= HD64461_GPADR_SPEAKER;
++ outw(v, HD64461_GPADR);
++
++ /* HP Palmtop 620lx/660lx speaker off */
++ v8 = inb(PKDR);
++ v8 |= PKDR_SPEAKER;
++ outb(v8, PKDR);
++ }
++
++ sh_dac_output(0, SH_DAC_AUDIO_CHANNEL);
++ sh_dac_disable(SH_DAC_AUDIO_CHANNEL);
++}
++
++static void dac_audio_set_rate(int rate)
++{
++ unsigned long interval;
++ struct clk *clk;
++
++ /*printk("dac_audio_set_rate\n"); */
++ /*
++ * Constant is autoloaded once zero is reached
++ * We need 8K interrupts per second
++ */
++ /* clk = clk_get(NULL, "module_clk"); */
++ clk = clk_get("module_clk");
++ interval = (clk_get_rate(clk) / 16) / rate;
++ ctrl_outl(interval, HD64461_TMU_TCVR0);
++}
++
++/* end of the hardware functions */
++
++
++/* PCM INTERFACE */
++
++static struct snd_pcm_hardware snd_sh_dac_pcm_hw = {
++ .info = (SNDRV_PCM_INFO_MMAP |
++ SNDRV_PCM_INFO_MMAP_VALID |
++ SNDRV_PCM_INFO_INTERLEAVED |
++ SNDRV_PCM_INFO_HALF_DUPLEX),
++ .formats = SNDRV_PCM_FMTBIT_U8,
++ .rates = SNDRV_PCM_RATE_8000,
++ .rate_min = 8000,
++ .rate_max = 8000,
++ .channels_min = 1,
++ .channels_max = 1,
++ .buffer_bytes_max = (48*1024),
++ .period_bytes_min = 1,
++ .period_bytes_max = (48*1024),
++ .periods_min = 1,
++ .periods_max = 1024,
++};
++
++static int snd_sh_dac_pcm_open(struct snd_pcm_substream *substream)
++{
++ struct snd_sh_dac *chip = snd_pcm_substream_chip(substream);
++ struct snd_pcm_runtime *runtime = substream->runtime;
++
++ /*printk("snd_sh_dac_pcm_open\n"); */
++ runtime->hw = snd_sh_dac_pcm_hw;
++
++ chip->substream = substream;
++ chip->buffer_begin = chip->buffer_end = chip->data_buffer;
++ chip->processed = 0;
++ chip->empty = 1;
++
++ dac_audio_start();
++
++ return 0;
++}
++
++static int snd_sh_dac_pcm_close(struct snd_pcm_substream *substream)
++{
++ struct snd_sh_dac *chip = snd_pcm_substream_chip(substream);
++
++ /*printk("snd_sh_dac_pcm_close\n"); */
++ dac_audio_sync(chip);
++ dac_audio_stop();
++
++ return 0;
++}
++
++static int snd_sh_dac_pcm_hw_params(struct snd_pcm_substream *substream,
++ struct snd_pcm_hw_params *hw_params)
++{
++ /*printk("snd_sh_dac_pcm_hw_params\n"); */
++ return
++ snd_pcm_lib_malloc_pages(substream, params_buffer_bytes(hw_params));
++}
++
++static int snd_sh_dac_pcm_hw_free(struct snd_pcm_substream *substream)
++{
++ /*printk("snd_sh_dac_pcm_hw_free\n"); */
++ /* Free the buffer */
++ return snd_pcm_lib_free_pages(substream);
++}
++
++static int snd_sh_dac_pcm_prepare(struct snd_pcm_substream *substream)
++{
++ struct snd_sh_dac *chip = snd_pcm_substream_chip(substream);
++ struct snd_pcm_runtime *runtime = chip->substream->runtime;
++ /*printk("snd_sh_dac_pcm_prepare\n"); */
++ chip->buffer_size = runtime->buffer_size;
++ memset(chip->data_buffer, 0, BUFFER_SIZE);
++ return 0;
++}
++
++static int snd_sh_dac_pcm_trigger(struct snd_pcm_substream *substream, int cmd)
++{
++ struct snd_sh_dac *chip = snd_pcm_substream_chip(substream);
++ /*printk("snd_sh_dac_pcm_trigger\n"); */
++ switch (cmd) {
++ case SNDRV_PCM_TRIGGER_START:
++ dac_audio_start_timer();
++ break;
++ case SNDRV_PCM_TRIGGER_STOP:
++ chip->buffer_begin = chip->buffer_end = chip->data_buffer;
++ chip->processed = 0;
++ chip->empty = 1;
++ dac_audio_stop_timer();
++ break;
++ default:
++ return -EINVAL;
++ }
++ return 0;
++}
++
++static int snd_sh_dac_pcm_copy(struct snd_pcm_substream *substream, int channel,
++ snd_pcm_uframes_t pos, void __user *src, snd_pcm_uframes_t count)
++{
++ /* channel is not used (interleaved data) */
++ struct snd_sh_dac *chip = snd_pcm_substream_chip(substream);
++ struct snd_pcm_runtime *runtime = substream->runtime;
++ ssize_t b_count = frames_to_bytes(runtime , count);
++ ssize_t b_pos = frames_to_bytes(runtime , pos);
++
++ /*printk("snd_sh_dac_pcm_copy\n"); */
++ if (count < 0)
++ return -EINVAL;
++
++ if (!count) {
++ dac_audio_sync(chip);
++ return 0;
++ }
++
++ memcpy_toio(chip->data_buffer + b_pos, src, b_count);
++ chip->buffer_end = chip->data_buffer + b_pos + b_count;
++
++ if (chip->empty) {
++ chip->empty = 0;
++ dac_audio_start_timer();
++ }
++
++ return 0;
++}
++
++static int snd_sh_dac_pcm_silence(struct snd_pcm_substream *substream,
++ int channel, snd_pcm_uframes_t pos,
++ snd_pcm_uframes_t count)
++{
++ /* channel is not used (interleaved data) */
++ struct snd_sh_dac *chip = snd_pcm_substream_chip(substream);
++ struct snd_pcm_runtime *runtime = substream->runtime;
++ ssize_t b_count = frames_to_bytes(runtime , count);
++ ssize_t b_pos = frames_to_bytes(runtime , pos);
++
++ /*printk("snd_sh_dac_pcm_silence\n"); */
++ if (count < 0)
++ return -EINVAL;
++
++ if (!count) {
++ dac_audio_sync(chip);
++ return 0;
++ }
++
++ memset_io(chip->data_buffer + b_pos, 0, b_count);
++ chip->buffer_end = chip->data_buffer + b_pos + b_count;
++
++ if (chip->empty) {
++ chip->empty = 0;
++ dac_audio_start_timer();
++ }
++ return 0;
++}
++
++static snd_pcm_uframes_t snd_sh_dac_pcm_pointer(struct snd_pcm_substream *substream)
++{
++ struct snd_sh_dac *chip = snd_pcm_substream_chip(substream);
++ int pointer = chip->buffer_begin - chip->data_buffer;
++
++ /*printk("snd_pcm_uframes_t \n"); */
++ return pointer;
++}
++
++/* pcm ops */
++static struct snd_pcm_ops snd_sh_dac_pcm_ops = {
++ .open = snd_sh_dac_pcm_open,
++ .close = snd_sh_dac_pcm_close,
++ .ioctl = snd_pcm_lib_ioctl,
++ .hw_params = snd_sh_dac_pcm_hw_params,
++ .hw_free = snd_sh_dac_pcm_hw_free,
++ .prepare = snd_sh_dac_pcm_prepare,
++ .trigger = snd_sh_dac_pcm_trigger,
++ .pointer = snd_sh_dac_pcm_pointer,
++ .copy = snd_sh_dac_pcm_copy,
++ .silence = snd_sh_dac_pcm_silence,
++ .mmap = snd_pcm_lib_mmap_iomem,
++};
++
++static int __devinit snd_sh_dac_pcm(struct snd_sh_dac *chip, int device)
++{
++ int err;
++ struct snd_pcm *pcm;
++ /*printk("snd_sh_dac_pcm\n"); */
++ /* device should be always 0 for us */
++ err = snd_pcm_new(chip->card, "SH_DAC PCM", device, 1, 0, &pcm);
++ if (err < 0)
++ return err;
++ pcm->private_data = chip;
++ strcpy(pcm->name, "SH_DAC PCM");
++ snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_PLAYBACK, &snd_sh_dac_pcm_ops);
++
++ /* buffer size=48K */
++ snd_pcm_lib_preallocate_pages_for_all(pcm, SNDRV_DMA_TYPE_CONTINUOUS,
++ snd_dma_continuous_data(GFP_KERNEL),
++ 48 * 1024,
++ 48 * 1024);
++ return 0;
++}
++/* END OF PCM INTERFACE */
++
++
++/* driver .remove -- destructor */
++static int snd_sh_dac_remove(struct platform_device *devptr)
++{
++ /*printk("snd_sh_dac_remove\n"); */
++ snd_card_free(platform_get_drvdata(devptr));
++ platform_set_drvdata(devptr, NULL);
++ return 0;
++}
++
++/* free -- it has been defined by create */
++static int snd_sh_dac_free(struct snd_sh_dac *chip)
++{
++ /*printk("snd_sh_dac_free\n"); */
++ /* release the irq */
++ free_irq(chip->irq, (void *)chip);
++
++ /* release the data */
++ kfree(chip->data_buffer);
++ kfree(chip);
++
++ return 0;
++}
++
++static int snd_sh_dac_dev_free(struct snd_device *device)
++{
++ struct snd_sh_dac *chip = device->device_data;
++ /*printk("snd_sh_dac_dev_free\n"); */
++ return snd_sh_dac_free(chip);
++}
++
++static irqreturn_t snd_sh_dac_interrupt(int irq, void *pdev, struct pt_regs *regs)
++{
++ u16 timer_status;
++ struct snd_sh_dac *chip = (struct snd_sh_dac *) pdev;
++ struct snd_pcm_runtime *runtime = chip->substream->runtime;
++ ssize_t b_ps = frames_to_bytes(runtime, runtime->period_size);
++
++/* printk("snd_sh_dac_interrupt\n"); */
++ /* HD64461_TMU0 mask interrupt */
++ timer_status = inw(HD64461_TMU_TIRR);
++ timer_status &= ~HD64461_TMU_TIRR_TMU0;
++ outw(timer_status, HD64461_TMU_TIRR);
++
++ if (!chip->empty) {
++ sh_dac_output(*chip->buffer_begin, SH_DAC_AUDIO_CHANNEL);
++ chip->buffer_begin++;
++ chip->processed++;
++
++ if (chip->processed >= b_ps) {
++ chip->processed -= b_ps;
++ snd_pcm_period_elapsed(chip->substream);
++ }
++
++ if (chip->buffer_begin == (chip->data_buffer +
++ chip->buffer_size - 1))
++ chip->buffer_begin = chip->data_buffer;
++
++ if (chip->buffer_begin == chip->buffer_end) {
++ chip->empty = 1;
++ dac_audio_stop_timer();
++ }
++
++ }
++ return IRQ_HANDLED;
++}
++
++/* create -- chip-specific constructor for the cards components */
++static int __devinit snd_sh_dac_create(struct snd_card *card,
++ struct platform_device *devptr,
++ struct snd_sh_dac **rchip)
++{
++ struct snd_sh_dac *chip;
++ int err;
++ u16 timer_status;
++ u16 hd64461_stbcr;
++
++ static struct snd_device_ops ops = {
++ .dev_free = snd_sh_dac_dev_free,
++ };
++
++ /*printk("snd_sh_dac_create\n"); */
++ *rchip = NULL;
++
++ chip = kzalloc(sizeof(*chip), GFP_KERNEL);
++ if (chip == NULL)
++ return -ENOMEM;
++
++ /* initialize the stuff */
++ chip->card = card;
++ chip->irq = -1;
++
++ /* Hardware Initialization */
++ /* get standby status of all devices */
++ hd64461_stbcr = inw(HD64461_STBCR);
++ /* remove standby mode for timer 0 */
++ hd64461_stbcr &= ~HD64461_STBCR_STM0ST;
++ outw(hd64461_stbcr, HD64461_STBCR);
++
++ dac_audio_reset(chip);
++ chip->rate = 8000;
++ dac_audio_set_rate(chip->rate);
++
++ /* set bit interrupt service request */
++ timer_status = inw(HD64461_TMU_TIRR);
++ timer_status &= ~HD64461_TMU_TIRR_TMU0;
++ outw(timer_status, HD64461_TMU_TIRR);
++
++ /* set interrupt service request mask bit */
++ timer_status = inw(HD64461_TMU_TIDR);
++ timer_status &= ~HD64461_TMU_TIMR_TMU0;
++ outw(timer_status, HD64461_TMU_TIDR);
++
++ chip->data_buffer = kmalloc(BUFFER_SIZE, GFP_KERNEL);
++ if (chip->data_buffer == NULL)
++ return -ENOMEM;
++
++ /* if (request_irq(HD64461_IRQ_TMU0, snd_sh_dac_interrupt, IRQF_DISABLED, */
++ if (request_irq(HD64461_IRQ_TMU0, snd_sh_dac_interrupt, SA_INTERRUPT,
++ "snd_sh_dac", (void *)chip)) {
++ snd_sh_dac_free(chip);
++ printk(KERN_ERR "cannot grab irq\n");
++ return -EBUSY;
++ }
++ chip->irq = HD64461_IRQ_TMU0;
++
++ if ((err = snd_device_new(card, SNDRV_DEV_LOWLEVEL, chip, &ops)) < 0) {
++ snd_sh_dac_free(chip);
++ return err;
++ }
++ *rchip = chip;
++
++ return 0;
++}
++
++/* driver .probe -- constructor */
++static int __devinit snd_sh_dac_probe(struct platform_device *devptr)
++{
++ struct snd_sh_dac *chip;
++ struct snd_card *card;
++ int err;
++
++ card = snd_card_new(index, id, THIS_MODULE, 0);
++ if (card == NULL)
++ return -ENOMEM;
++
++ err = snd_sh_dac_create(card, devptr, &chip);
++ if (err < 0)
++ goto probe_error;
++
++ err = snd_sh_dac_pcm(chip, 0);
++ if (err < 0)
++ goto probe_error;
++
++ strcpy(card->driver, "snd_sh_dac");
++ strcpy(card->shortname, "SuperH DAC audio driver");
++ /* sprintk(card->longname, "%s at HD64461 irq %i", card->shortname, */
++ printk("%s %s at HD64461 irq %i", card->longname, card->shortname,
++ chip->irq);
++
++ err = snd_card_register(card);
++ if (err < 0)
++ goto probe_error;
++
++ snd_printk("ALSA driver for SuperH DAC audio");
++
++ platform_set_drvdata(devptr, card);
++ return 0;
++
++probe_error:
++ snd_card_free(card);
++ return err;
++}
++
++/*
++ * "driver" definition
++ */
++static struct platform_driver driver = {
++ .probe = snd_sh_dac_probe,
++ .remove = snd_sh_dac_remove,
++ .driver = {
++ .name = SND_SH_DAC_DRIVER,
++ },
++};
++
++/* clean up the module */
++static void __exit sh_dac_exit(void)
++{
++ /*printk("sh_dac_exit\n"); */
++ platform_device_unregister(pd);
++ platform_driver_unregister(&driver);
++
++ free_irq(HD64461_IRQ_TMU0, 0);
++}
++
++
++static int __init sh_dac_init(void)
++{
++ int err;
++ /*printk("sh_dac_init\n"); */
++ err = platform_driver_register(&driver);
++ if (unlikely(err < 0))
++ return err;
++
++ pd = platform_device_register_simple(SND_SH_DAC_DRIVER, -1, NULL, 0);
++ if (unlikely(IS_ERR(pd))) {
++ platform_driver_unregister(&driver);
++ return PTR_ERR(pd);
++ }
++
++ return 0;
++}
++
++module_init(sh_dac_init);
++module_exit(sh_dac_exit);
diff --git a/recipes/linux/linux-jlime-jornada6xx-2.6.17/defconfig_jlime b/recipes/linux/linux-jlime-jornada6xx-2.6.17/defconfig_jlime
index 05a0c598a8..0db41d8604 100644
--- a/recipes/linux/linux-jlime-jornada6xx-2.6.17/defconfig_jlime
+++ b/recipes/linux/linux-jlime-jornada6xx-2.6.17/defconfig_jlime
@@ -858,16 +858,43 @@ CONFIG_SOUND=y
#
# Advanced Linux Sound Architecture
#
-# CONFIG_SND is not set
+CONFIG_SND=y
+CONFIG_SND_TIMER=y
+CONFIG_SND_PCM=y
+# CONFIG_SND_SEQUENCER is not set
+CONFIG_SND_OSSEMUL=y
+CONFIG_SND_MIXER_OSS=y
+CONFIG_SND_PCM_OSS=y
+CONFIG_SND_PCM_OSS_PLUGINS=y
+# CONFIG_SND_DYNAMIC_MINORS is not set
+CONFIG_SND_SUPPORT_OLD_API=y
+CONFIG_SND_VERBOSE_PROCFS=y
+# CONFIG_SND_VERBOSE_PRINTK is not set
+# CONFIG_SND_DEBUG is not set
+
+#
+# Generic devices
+#
+# CONFIG_SND_DUMMY is not set
+# CONFIG_SND_MTPAV is not set
+# CONFIG_SND_SERIAL_U16550 is not set
+# CONFIG_SND_MPU401 is not set
+
+#
+# SuperH devices
+#
+CONFIG_SND_SH_DAC_AUDIO=y
+
+#
+# PCMCIA devices
+#
+# CONFIG_SND_VXPOCKET is not set
+# CONFIG_SND_PDAUDIOCF is not set
#
# Open Sound System
#
-CONFIG_SOUND_PRIME=y
-# CONFIG_SOUND_MSNDCLAS is not set
-# CONFIG_SOUND_MSNDPIN is not set
-CONFIG_SOUND_SH_DAC_AUDIO=y
-CONFIG_SOUND_SH_DAC_AUDIO_CHANNEL=1
+# CONFIG_SOUND_PRIME is not set
#
# USB support
diff --git a/recipes/linux/linux-jlime-jornada6xx-2.6.17/rtc-2.6.17.patch b/recipes/linux/linux-jlime-jornada6xx-2.6.17/rtc-2.6.17.patch
new file mode 100644
index 0000000000..a744c268c8
--- /dev/null
+++ b/recipes/linux/linux-jlime-jornada6xx-2.6.17/rtc-2.6.17.patch
@@ -0,0 +1,987 @@
+diff -ru linux-2.6.17.old/arch/sh/boards/hp6xx/pm.c linux-2.6.17/arch/sh/boards/hp6xx/pm.c
+--- linux-2.6.17.old/arch/sh/boards/hp6xx/pm.c 2009-12-21 10:27:22.776442805 +0200
++++ linux-2.6.17/arch/sh/boards/hp6xx/pm.c 2009-12-21 10:30:09.366428509 +0200
+@@ -17,6 +17,10 @@
+ #include <asm/cpu/dac.h>
+ #include <asm/pm.h>
+
++#include <asm-sh/rtc.h>
++#include <linux/time.h>
++#include <asm-sh/rtc.h>
++
+ #define STBCR 0xffffff82
+ #define STBCR2 0xffffff88
+
+@@ -68,6 +72,8 @@
+ outb(0x00, HD64461_PCC1CSCR);
+ #endif
+
++ rtc_sh_get_time(&xtime);
++
+ return 0;
+ }
+
+diff -ru linux-2.6.17.old/arch/sh/kernel/cpu/irq/ipr.c linux-2.6.17/arch/sh/kernel/cpu/irq/ipr.c
+--- linux-2.6.17.old/arch/sh/kernel/cpu/irq/ipr.c 2006-06-18 04:49:35.000000000 +0300
++++ linux-2.6.17/arch/sh/kernel/cpu/irq/ipr.c 2009-12-21 10:29:58.713508059 +0200
+@@ -125,7 +125,12 @@
+ make_ipr_irq(TIMER_IRQ, TIMER_IPR_ADDR, TIMER_IPR_POS, TIMER_PRIORITY);
+ make_ipr_irq(TIMER1_IRQ, TIMER1_IPR_ADDR, TIMER1_IPR_POS, TIMER1_PRIORITY);
+ #if defined(CONFIG_SH_RTC)
++ make_ipr_irq(20, RTC_IPR_ADDR, RTC_IPR_POS, RTC_PRIORITY);
++ printk("kernel IRQ RTC =%i\n",20);
++ make_ipr_irq(21, RTC_IPR_ADDR, RTC_IPR_POS, RTC_PRIORITY);
++ printk("kernel IRQ RTC =%i\n",21);
+ make_ipr_irq(RTC_IRQ, RTC_IPR_ADDR, RTC_IPR_POS, RTC_PRIORITY);
++ printk("kernel IRQ RTC =%i\n",RTC_IRQ);
+ #endif
+
+ #ifdef SCI_ERI_IRQ
+diff -ru linux-2.6.17.old/arch/sh/kernel/cpu/sh3/Makefile linux-2.6.17/arch/sh/kernel/cpu/sh3/Makefile
+--- linux-2.6.17.old/arch/sh/kernel/cpu/sh3/Makefile 2006-06-18 04:49:35.000000000 +0300
++++ linux-2.6.17/arch/sh/kernel/cpu/sh3/Makefile 2009-12-21 10:29:58.713508059 +0200
+@@ -4,10 +4,13 @@
+
+ obj-y := ex.o probe.o
+
++obj-$(CONFIG_CPU_SUBTYPE_SH7709) += setup-sh770x.o
++
+ clock-$(CONFIG_CPU_SH3) := clock-sh3.o
+ clock-$(CONFIG_CPU_SUBTYPE_SH7300) := clock-sh7300.o
+ clock-$(CONFIG_CPU_SUBTYPE_SH7705) := clock-sh7705.o
+-clock-$(CONFIG_CPU_SUBTYPE_SH7709) := clock-sh7709.o
++# clock-$(CONFIG_CPU_SUBTYPE_SH7709) := clock-sh7709.o
++clock-$(CONFIG_CPU_SUBTYPE_SH7709) := clock-sh7709.o
+
+ obj-y += $(clock-y)
+
+diff -ru linux-2.6.17.old/arch/sh/kernel/cpu/sh3/setup-sh770x.c linux-2.6.17/arch/sh/kernel/cpu/sh3/setup-sh770x.c
+--- linux-2.6.17.old/arch/sh/kernel/cpu/sh3/setup-sh770x.c 2009-12-21 10:32:06.699746910 +0200
++++ linux-2.6.17/arch/sh/kernel/cpu/sh3/setup-sh770x.c 2009-12-21 10:29:58.713508059 +0200
+@@ -0,0 +1,217 @@
++/*
++ * SH3 Setup code for SH7706, SH7707, SH7708, SH7709
++ *
++ * Copyright (C) 2007 Magnus Damm
++ *
++ * Based on setup-sh7709.c
++ *
++ * Copyright (C) 2006 Paul Mundt
++ *
++ * This file is subject to the terms and conditions of the GNU General Public
++ * License. See the file "COPYING" in the main directory of this archive
++ * for more details.
++ */
++#include <linux/init.h>
++#include <linux/io.h>
++#include <linux/irq.h>
++#include <linux/platform_device.h>
++#include <linux/serial.h>
++#include <linux/serial_sci.h>
++
++enum {
++ UNUSED = 0,
++
++ /* interrupt sources */
++ IRQ0, IRQ1, IRQ2, IRQ3, IRQ4, IRQ5,
++ PINT07, PINT815,
++ DMAC_DEI0, DMAC_DEI1, DMAC_DEI2, DMAC_DEI3,
++ SCIF0_ERI, SCIF0_RXI, SCIF0_BRI, SCIF0_TXI,
++ SCIF2_ERI, SCIF2_RXI, SCIF2_BRI, SCIF2_TXI,
++ SCI_ERI, SCI_RXI, SCI_TXI, SCI_TEI,
++ ADC_ADI,
++ LCDC, PCC0, PCC1,
++ TMU0, TMU1, TMU2_TUNI, TMU2_TICPI,
++ RTC_ATI, RTC_PRI, RTC_CUI,
++ WDT,
++ REF_RCMI, REF_ROVI,
++
++ /* interrupt groups */
++ RTC, REF, TMU2, DMAC, SCI, SCIF2, SCIF0,
++};
++
++static struct intc_vect vectors[] __initdata = {
++ INTC_VECT(TMU0, 0x400), INTC_VECT(TMU1, 0x420),
++ INTC_VECT(TMU2_TUNI, 0x440), INTC_VECT(TMU2_TICPI, 0x460),
++ INTC_VECT(RTC_ATI, 0x480), INTC_VECT(RTC_PRI, 0x4a0),
++ INTC_VECT(RTC_CUI, 0x4c0),
++ INTC_VECT(SCI_ERI, 0x4e0), INTC_VECT(SCI_RXI, 0x500),
++ INTC_VECT(SCI_TXI, 0x520), INTC_VECT(SCI_TEI, 0x540),
++ INTC_VECT(WDT, 0x560),
++ INTC_VECT(REF_RCMI, 0x580),
++ INTC_VECT(REF_ROVI, 0x5a0),
++#if defined(CONFIG_CPU_SUBTYPE_SH7706) || \
++ defined(CONFIG_CPU_SUBTYPE_SH7707) || \
++ defined(CONFIG_CPU_SUBTYPE_SH7709)
++ INTC_VECT(IRQ4, 0x680), INTC_VECT(IRQ5, 0x6a0),
++ INTC_VECT(DMAC_DEI0, 0x800), INTC_VECT(DMAC_DEI1, 0x820),
++ INTC_VECT(DMAC_DEI2, 0x840), INTC_VECT(DMAC_DEI3, 0x860),
++ INTC_VECT(ADC_ADI, 0x980),
++ INTC_VECT(SCIF2_ERI, 0x900), INTC_VECT(SCIF2_RXI, 0x920),
++ INTC_VECT(SCIF2_BRI, 0x940), INTC_VECT(SCIF2_TXI, 0x960),
++#endif
++#if defined(CONFIG_CPU_SUBTYPE_SH7707) || \
++ defined(CONFIG_CPU_SUBTYPE_SH7709)
++ INTC_VECT(PINT07, 0x700), INTC_VECT(PINT815, 0x720),
++ INTC_VECT(SCIF0_ERI, 0x880), INTC_VECT(SCIF0_RXI, 0x8a0),
++ INTC_VECT(SCIF0_BRI, 0x8c0), INTC_VECT(SCIF0_TXI, 0x8e0),
++#endif
++#if defined(CONFIG_CPU_SUBTYPE_SH7707)
++ INTC_VECT(LCDC, 0x9a0),
++ INTC_VECT(PCC0, 0x9c0), INTC_VECT(PCC1, 0x9e0),
++#endif
++};
++
++static struct intc_group groups[] __initdata = {
++ INTC_GROUP(RTC, RTC_ATI, RTC_PRI, RTC_CUI),
++ INTC_GROUP(TMU2, TMU2_TUNI, TMU2_TICPI),
++ INTC_GROUP(REF, REF_RCMI, REF_ROVI),
++ INTC_GROUP(DMAC, DMAC_DEI0, DMAC_DEI1, DMAC_DEI2, DMAC_DEI3),
++ INTC_GROUP(SCI, SCI_ERI, SCI_RXI, SCI_TXI, SCI_TEI),
++ INTC_GROUP(SCIF0, SCIF0_ERI, SCIF0_RXI, SCIF0_BRI, SCIF0_TXI),
++ INTC_GROUP(SCIF2, SCIF2_ERI, SCIF2_RXI, SCIF2_BRI, SCIF2_TXI),
++};
++
++static struct intc_prio_reg prio_registers[] __initdata = {
++ { 0xfffffee2, 0, 16, 4, /* IPRA */ { TMU0, TMU1, TMU2, RTC } },
++ { 0xfffffee4, 0, 16, 4, /* IPRB */ { WDT, REF, SCI, 0 } },
++#if defined(CONFIG_CPU_SUBTYPE_SH7706) || \
++ defined(CONFIG_CPU_SUBTYPE_SH7707) || \
++ defined(CONFIG_CPU_SUBTYPE_SH7709)
++ { 0xa4000016, 0, 16, 4, /* IPRC */ { IRQ3, IRQ2, IRQ1, IRQ0 } },
++ { 0xa4000018, 0, 16, 4, /* IPRD */ { 0, 0, IRQ5, IRQ4 } },
++ { 0xa400001a, 0, 16, 4, /* IPRE */ { DMAC, 0, SCIF2, ADC_ADI } },
++#endif
++#if defined(CONFIG_CPU_SUBTYPE_SH7707) || \
++ defined(CONFIG_CPU_SUBTYPE_SH7709)
++ { 0xa4000018, 0, 16, 4, /* IPRD */ { PINT07, PINT815, } },
++ { 0xa400001a, 0, 16, 4, /* IPRE */ { 0, SCIF0 } },
++#endif
++#if defined(CONFIG_CPU_SUBTYPE_SH7707)
++ { 0xa400001c, 0, 16, 4, /* IPRF */ { 0, LCDC, PCC0, PCC1, } },
++#endif
++};
++
++static DECLARE_INTC_DESC(intc_desc, "sh770x", vectors, groups,
++ NULL, prio_registers, NULL);
++
++#if defined(CONFIG_CPU_SUBTYPE_SH7706) || \
++ defined(CONFIG_CPU_SUBTYPE_SH7707) || \
++ defined(CONFIG_CPU_SUBTYPE_SH7709)
++static struct intc_vect vectors_irq[] __initdata = {
++ INTC_VECT(IRQ0, 0x600), INTC_VECT(IRQ1, 0x620),
++ INTC_VECT(IRQ2, 0x640), INTC_VECT(IRQ3, 0x660),
++};
++
++static DECLARE_INTC_DESC(intc_desc_irq, "sh770x-irq", vectors_irq, NULL,
++ NULL, prio_registers, NULL);
++#endif
++
++static struct resource rtc_resources[] = {
++ [0] = {
++ .start = 0xfffffec0,
++ .end = 0xfffffec0 + 0x1e,
++ .flags = IORESOURCE_IO,
++ },
++ [1] = {
++ .start = 21,
++ .flags = IORESOURCE_IRQ,
++ },
++ [2] = {
++ .start = 22,
++ .flags = IORESOURCE_IRQ,
++ },
++ [3] = {
++ .start = 20,
++ .flags = IORESOURCE_IRQ,
++ },
++};
++
++static struct platform_device rtc_device = {
++ .name = "sh-rtc",
++ .id = -1,
++ .num_resources = ARRAY_SIZE(rtc_resources),
++ .resource = rtc_resources,
++};
++
++static struct plat_sci_port sci_platform_data[] = {
++ {
++ .mapbase = 0xfffffe80,
++ .flags = UPF_BOOT_AUTOCONF,
++ .type = PORT_SCI,
++ .irqs = { 23, 24, 25, 0 },
++ },
++#if defined(CONFIG_CPU_SUBTYPE_SH7706) || \
++ defined(CONFIG_CPU_SUBTYPE_SH7707) || \
++ defined(CONFIG_CPU_SUBTYPE_SH7709)
++ {
++ .mapbase = 0xa4000150,
++ .flags = UPF_BOOT_AUTOCONF,
++ .type = PORT_SCIF,
++ .irqs = { 56, 57, 59, 58 },
++ },
++#endif
++#if defined(CONFIG_CPU_SUBTYPE_SH7707) || \
++ defined(CONFIG_CPU_SUBTYPE_SH7709)
++ {
++ .mapbase = 0xa4000140,
++ .flags = UPF_BOOT_AUTOCONF,
++ .type = PORT_IRDA,
++ .irqs = { 52, 53, 55, 54 },
++ },
++#endif
++ {
++ .flags = 0,
++ }
++};
++
++static struct platform_device sci_device = {
++ .name = "sh-sci",
++ .id = -1,
++ .dev = {
++ .platform_data = sci_platform_data,
++ },
++};
++
++static struct platform_device *sh770x_devices[] __initdata = {
++ &sci_device,
++ &rtc_device,
++};
++
++static int __init sh770x_devices_setup(void)
++{
++ return platform_add_devices(sh770x_devices,
++ ARRAY_SIZE(sh770x_devices));
++}
++__initcall(sh770x_devices_setup);
++
++#define INTC_ICR1 0xa4000010UL
++#define INTC_ICR1_IRQLVL (1<<14)
++
++void __init plat_irq_setup_pins(int mode)
++{
++ if (mode == IRQ_MODE_IRQ) {
++#if defined(CONFIG_CPU_SUBTYPE_SH7706) || \
++ defined(CONFIG_CPU_SUBTYPE_SH7707) || \
++ defined(CONFIG_CPU_SUBTYPE_SH7709)
++ ctrl_outw(ctrl_inw(INTC_ICR1) & ~INTC_ICR1_IRQLVL, INTC_ICR1);
++/* register_intc_controller(&intc_desc_irq); */
++ return;
++#endif
++ }
++ BUG();
++}
++
++void __init plat_irq_setup(void)
++{
++/* register_intc_controller(&intc_desc); */
++}
+diff -ru linux-2.6.17.old/drivers/rtc/interface.c linux-2.6.17/drivers/rtc/interface.c
+--- linux-2.6.17.old/drivers/rtc/interface.c 2006-06-18 04:49:35.000000000 +0300
++++ linux-2.6.17/drivers/rtc/interface.c 2009-12-21 10:29:58.713508059 +0200
+@@ -145,11 +145,16 @@
+ }
+ EXPORT_SYMBOL_GPL(rtc_set_alarm);
+
+-void rtc_update_irq(struct class_device *class_dev,
++/**
++ * rtc_update_irq - report RTC periodic, alarm, and/or update irqs
++ * @rtc: the rtc device
++ * @num: how many irqs are being reported (usually one)
++ * @events: mask of RTC_IRQF with one or more of RTC_PF, RTC_AF, RTC_UF
++ * Context: in_interrupt(), irqs blocked
++ */
++void rtc_update_irq(struct rtc_device *rtc,
+ unsigned long num, unsigned long events)
+ {
+- struct rtc_device *rtc = to_rtc_device(class_dev);
+-
+ spin_lock(&rtc->irq_lock);
+ rtc->irq_data = (rtc->irq_data + (num << 8)) | events;
+ spin_unlock(&rtc->irq_lock);
+diff -ru linux-2.6.17.old/drivers/rtc/rtc-sh.c linux-2.6.17/drivers/rtc/rtc-sh.c
+--- linux-2.6.17.old/drivers/rtc/rtc-sh.c 2009-12-21 10:27:23.403110577 +0200
++++ linux-2.6.17/drivers/rtc/rtc-sh.c 2009-12-21 10:29:58.716840103 +0200
+@@ -1,7 +1,8 @@
+ /*
+ * SuperH On-Chip RTC Support
+ *
+- * Copyright (C) 2006 Paul Mundt
++ * Copyright (C) 2006, 2007 Paul Mundt
++ * Copyright (C) 2006 Jamie Lenehan
+ *
+ * Based on the old arch/sh/kernel/cpu/rtc.c by:
+ *
+@@ -21,34 +22,46 @@
+ #include <linux/seq_file.h>
+ #include <linux/interrupt.h>
+ #include <linux/spinlock.h>
+-#include <asm/io.h>
++#include <linux/io.h>
++#include <asm/rtc.h>
+
+-#ifdef CONFIG_CPU_SH3
+-#define rtc_reg_size sizeof(u16)
+-#define RTC_BIT_INVERTED 0 /* No bug on SH7708, SH7709A */
+-#elif defined(CONFIG_CPU_SH4)
+-#define rtc_reg_size sizeof(u32)
+-#define RTC_BIT_INVERTED 0x40 /* bug on SH7750, SH7750S */
+-#endif
++#define DRV_NAME "sh-rtc"
++#define DRV_VERSION "0.1.6"
+
+ #define RTC_REG(r) ((r) * rtc_reg_size)
+
+-#define R64CNT RTC_REG(0)
+-#define RSECCNT RTC_REG(1)
+-#define RMINCNT RTC_REG(2)
+-#define RHRCNT RTC_REG(3)
+-#define RWKCNT RTC_REG(4)
+-#define RDAYCNT RTC_REG(5)
+-#define RMONCNT RTC_REG(6)