aboutsummaryrefslogtreecommitdiffstats
path: root/recipes/linux/linux-2.6.18/at32-dac-oss-driver-clk-fix.patch
blob: 927cdc5ecee14fd2eea41571c5e9ceb3d8742184 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
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);