summaryrefslogtreecommitdiff
path: root/packages/linux/linux-2.6.18/at32-dac-oss-driver-clk-fix.patch
diff options
context:
space:
mode:
Diffstat (limited to 'packages/linux/linux-2.6.18/at32-dac-oss-driver-clk-fix.patch')
-rw-r--r--packages/linux/linux-2.6.18/at32-dac-oss-driver-clk-fix.patch175
1 files changed, 175 insertions, 0 deletions
diff --git a/packages/linux/linux-2.6.18/at32-dac-oss-driver-clk-fix.patch b/packages/linux/linux-2.6.18/at32-dac-oss-driver-clk-fix.patch
new file mode 100644
index 0000000000..927cdc5ece
--- /dev/null
+++ b/packages/linux/linux-2.6.18/at32-dac-oss-driver-clk-fix.patch
@@ -0,0 +1,175 @@
+---
+ sound/oss/at32dac.c | 72 +++++++++++++++++++++++++++++++---------------------
+ 1 file changed, 43 insertions(+), 29 deletions(-)
+
+Index: linux-2.6.18-avr32/sound/oss/at32dac.c
+===================================================================
+--- linux-2.6.18-avr32.orig/sound/oss/at32dac.c 2006-11-01 14:30:47.000000000 +0100
++++ linux-2.6.18-avr32/sound/oss/at32dac.c 2006-11-01 14:32:05.000000000 +0100
+@@ -71,6 +71,7 @@ struct at32_dac {
+ struct dma_request_cyclic req;
+
+ struct clk *mck;
++ struct clk *sample_clk;
+ struct platform_device *pdev;
+ int busy;
+ int playing;
+@@ -116,24 +117,6 @@ static void at32dac_update_dma_tail(stru
+ }
+ }
+
+-static int at32dac_start_genclock(struct at32_dac *dac)
+-{
+- unsigned int div;
+-
+- div = ((clk_get_rate(boot_cpu_data.clk) + 256 * dac->dsp_settings.sample_rate)
+- / (512 * dac->dsp_settings.sample_rate) - 1);
+- pr_debug("Real sample rate: %llu (div=%u)\n",
+- boot_cpu_data.cpu_hz / (512 * (div + 1)), div);
+- writel((div << 8) | 0x16, (void __iomem *)(0xfff00060 + 4 * 6));
+-
+- return 0;
+-}
+-
+-static void at32dac_stop_genclock(struct at32_dac *dac)
+-{
+- writel(0, (void __iomem *)(0xfff00060 + 4 * 6));
+-}
+-
+ static int at32dac_start(struct at32_dac *dac)
+ {
+ int ret;
+@@ -143,13 +126,11 @@ static int at32dac_start(struct at32_dac
+
+ memset(dac->dma.buf, 0, DMA_BUFFER_SIZE);
+
+- ret = at32dac_start_genclock(dac);
+- if (ret)
+- return ret;
++ clk_enable(dac->sample_clk);
+
+ ret = dma_prepare_request_cyclic(dac->req.req.dmac, &dac->req);
+ if (ret)
+- goto out_stop_genclock;
++ goto out_stop_clock;
+
+ pr_debug("Starting DMA...\n");
+ ret = dma_start_request(dac->req.req.dmac, dac->req.req.channel);
+@@ -164,8 +145,8 @@ static int at32dac_start(struct at32_dac
+ out_stop_request:
+ dma_stop_request(dac->req.req.dmac,
+ dac->req.req.channel);
+-out_stop_genclock:
+- at32dac_stop_genclock(dac);
++out_stop_clock:
++ clk_disable(dac->sample_clk);
+ return ret;
+ }
+
+@@ -176,7 +157,7 @@ static int at32dac_stop(struct at32_dac
+ dac_writel(dac, DATA, 0);
+ dac_writel(dac, CTRL, 0);
+ dac->playing = 0;
+- at32dac_stop_genclock(dac);
++ clk_disable(dac->sample_clk);
+ }
+
+ return 0;
+@@ -360,6 +341,26 @@ static int at32dac_set_format(struct at3
+ return 0;
+ }
+
++static int at32dac_set_sample_rate(struct at32_dac *dac, unsigned long rate)
++{
++ unsigned long new_rate;
++ int ret;
++
++ ret = clk_set_rate(dac->sample_clk, 256 * rate);
++ if (ret < 0)
++ return ret;
++
++ /* TODO: mplayer seems to have a problem with this */
++#if 0
++ new_rate = clk_get_rate(dac->sample_clk);
++ dac->dsp_settings.sample_rate = new_rate / 256;
++#else
++ dac->dsp_settings.sample_rate = rate;
++#endif
++
++ return 0;
++}
++
+ static ssize_t at32dac_dsp_write(struct file *file,
+ const char __user *buffer,
+ size_t count, loff_t *ppos)
+@@ -449,7 +450,9 @@ static int at32dac_dsp_ioctl(struct inod
+ return -EFAULT;
+ if (val >= 0) {
+ at32dac_stop(dac);
+- dac->dsp_settings.sample_rate = val;
++ ret = at32dac_set_sample_rate(dac, val);
++ if (ret)
++ return ret;
+ }
+ return put_user(dac->dsp_settings.sample_rate, up);
+
+@@ -534,10 +537,11 @@ static int at32dac_dsp_open(struct inode
+ dac->dma.head = dac->dma.tail = 0;
+
+ /* FIXME: What are the correct defaults? */
+- dac->dsp_settings.format = AFMT_S16_BE;
+ dac->dsp_settings.channels = 2;
+- dac->dsp_settings.sample_rate = 8000;
+- dac->dsp_settings.input_order = 2;
++ at32dac_set_format(dac, AFMT_S16_BE);
++ ret = at32dac_set_sample_rate(dac, 8000);
++ if (ret)
++ goto out;
+
+ file->private_data = dac;
+ dac->busy = 1;
+@@ -578,6 +582,7 @@ static int __devinit at32dac_probe(struc
+ struct at32_dac *dac;
+ struct resource *regs;
+ struct clk *mck;
++ struct clk *sample_clk;
+ int irq;
+ int ret;
+
+@@ -594,6 +599,11 @@ static int __devinit at32dac_probe(struc
+ mck = clk_get(&pdev->dev, "mck");
+ if (IS_ERR(mck))
+ return PTR_ERR(mck);
++ sample_clk = clk_get(&pdev->dev, "sample_clk");
++ if (IS_ERR(sample_clk)) {
++ ret = PTR_ERR(sample_clk);
++ goto out_put_mck;
++ }
+ clk_enable(mck);
+
+ ret = -ENOMEM;
+@@ -606,6 +616,7 @@ static int __devinit at32dac_probe(struc
+ init_waitqueue_head(&dac->write_wait);
+ dac->pdev = pdev;
+ dac->mck = mck;
++ dac->sample_clk = sample_clk;
+
+ dac->regs = ioremap(regs->start, regs->end - regs->start + 1);
+ if (!dac->regs)
+@@ -658,6 +669,8 @@ out_free_dac:
+ kfree(dac);
+ out_disable_clk:
+ clk_disable(mck);
++ clk_put(sample_clk);
++out_put_mck:
+ clk_put(mck);
+ return ret;
+ }
+@@ -673,6 +686,7 @@ static int __devexit at32dac_remove(stru
+ free_irq(platform_get_irq(pdev, 0), dac);
+ iounmap(dac->regs);
+ clk_disable(dac->mck);
++ clk_put(dac->sample_clk);
+ clk_put(dac->mck);
+ kfree(dac);
+ platform_set_drvdata(pdev, NULL);