2 * bf6xx_sport.c Analog Devices BF6XX SPORT driver
4 * Copyright (c) 2012 Analog Devices Inc.
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License version 2 as
8 * published by the Free Software Foundation.
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
15 * You should have received a copy of the GNU General Public License
16 * along with this program; if not, write to the Free Software
17 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
20 #include <linux/device.h>
21 #include <linux/dma-mapping.h>
22 #include <linux/interrupt.h>
23 #include <linux/module.h>
24 #include <linux/platform_device.h>
25 #include <linux/slab.h>
27 #include <asm/blackfin.h>
29 #include <asm/portmux.h>
31 #include "bf6xx-sport.h"
33 int sport_set_tx_params(struct sport_device
*sport
,
34 struct sport_params
*params
)
36 if (sport
->tx_regs
->spctl
& SPORT_CTL_SPENPRI
)
38 sport
->tx_regs
->spctl
= params
->spctl
| SPORT_CTL_SPTRAN
;
39 sport
->tx_regs
->div
= params
->div
;
43 EXPORT_SYMBOL(sport_set_tx_params
);
45 int sport_set_rx_params(struct sport_device
*sport
,
46 struct sport_params
*params
)
48 if (sport
->rx_regs
->spctl
& SPORT_CTL_SPENPRI
)
50 sport
->rx_regs
->spctl
= params
->spctl
& ~SPORT_CTL_SPTRAN
;
51 sport
->rx_regs
->div
= params
->div
;
55 EXPORT_SYMBOL(sport_set_rx_params
);
57 static int compute_wdsize(size_t wdsize
)
61 return WDSIZE_8
| PSIZE_8
;
63 return WDSIZE_16
| PSIZE_16
;
65 return WDSIZE_32
| PSIZE_32
;
69 void sport_tx_start(struct sport_device
*sport
)
71 set_dma_next_desc_addr(sport
->tx_dma_chan
, sport
->tx_desc
);
72 set_dma_config(sport
->tx_dma_chan
, DMAFLOW_LIST
| DI_EN
73 | compute_wdsize(sport
->wdsize
) | NDSIZE_6
);
74 enable_dma(sport
->tx_dma_chan
);
75 sport
->tx_regs
->spctl
|= SPORT_CTL_SPENPRI
;
78 EXPORT_SYMBOL(sport_tx_start
);
80 void sport_rx_start(struct sport_device
*sport
)
82 set_dma_next_desc_addr(sport
->rx_dma_chan
, sport
->rx_desc
);
83 set_dma_config(sport
->rx_dma_chan
, DMAFLOW_LIST
| DI_EN
| WNR
84 | compute_wdsize(sport
->wdsize
) | NDSIZE_6
);
85 enable_dma(sport
->rx_dma_chan
);
86 sport
->rx_regs
->spctl
|= SPORT_CTL_SPENPRI
;
89 EXPORT_SYMBOL(sport_rx_start
);
91 void sport_tx_stop(struct sport_device
*sport
)
93 sport
->tx_regs
->spctl
&= ~SPORT_CTL_SPENPRI
;
95 disable_dma(sport
->tx_dma_chan
);
97 EXPORT_SYMBOL(sport_tx_stop
);
99 void sport_rx_stop(struct sport_device
*sport
)
101 sport
->rx_regs
->spctl
&= ~SPORT_CTL_SPENPRI
;
103 disable_dma(sport
->rx_dma_chan
);
105 EXPORT_SYMBOL(sport_rx_stop
);
107 void sport_set_tx_callback(struct sport_device
*sport
,
108 void (*tx_callback
)(void *), void *tx_data
)
110 sport
->tx_callback
= tx_callback
;
111 sport
->tx_data
= tx_data
;
113 EXPORT_SYMBOL(sport_set_tx_callback
);
115 void sport_set_rx_callback(struct sport_device
*sport
,
116 void (*rx_callback
)(void *), void *rx_data
)
118 sport
->rx_callback
= rx_callback
;
119 sport
->rx_data
= rx_data
;
121 EXPORT_SYMBOL(sport_set_rx_callback
);
123 static void setup_desc(struct dmasg
*desc
, void *buf
, int fragcount
,
124 size_t fragsize
, unsigned int cfg
,
125 unsigned int count
, size_t wdsize
)
130 for (i
= 0; i
< fragcount
; ++i
) {
131 desc
[i
].next_desc_addr
= &(desc
[i
+ 1]);
132 desc
[i
].start_addr
= (unsigned long)buf
+ i
*fragsize
;
134 desc
[i
].x_count
= count
;
135 desc
[i
].x_modify
= wdsize
;
137 desc
[i
].y_modify
= 0;
141 desc
[fragcount
-1].next_desc_addr
= desc
;
144 int sport_config_tx_dma(struct sport_device
*sport
, void *buf
,
145 int fragcount
, size_t fragsize
)
151 count
= fragsize
/sport
->wdsize
;
154 dma_free_coherent(NULL
, sport
->tx_desc_size
,
157 sport
->tx_desc
= dma_alloc_coherent(NULL
,
158 fragcount
* sizeof(struct dmasg
), &addr
, 0);
159 sport
->tx_desc_size
= fragcount
* sizeof(struct dmasg
);
164 sport
->tx_fragsize
= fragsize
;
165 sport
->tx_frags
= fragcount
;
166 cfg
= DMAFLOW_LIST
| DI_EN
| compute_wdsize(sport
->wdsize
) | NDSIZE_6
;
168 setup_desc(sport
->tx_desc
, buf
, fragcount
, fragsize
,
169 cfg
|DMAEN
, count
, sport
->wdsize
);
173 EXPORT_SYMBOL(sport_config_tx_dma
);
175 int sport_config_rx_dma(struct sport_device
*sport
, void *buf
,
176 int fragcount
, size_t fragsize
)
182 count
= fragsize
/sport
->wdsize
;
185 dma_free_coherent(NULL
, sport
->rx_desc_size
,
188 sport
->rx_desc
= dma_alloc_coherent(NULL
,
189 fragcount
* sizeof(struct dmasg
), &addr
, 0);
190 sport
->rx_desc_size
= fragcount
* sizeof(struct dmasg
);
195 sport
->rx_fragsize
= fragsize
;
196 sport
->rx_frags
= fragcount
;
197 cfg
= DMAFLOW_LIST
| DI_EN
| compute_wdsize(sport
->wdsize
)
200 setup_desc(sport
->rx_desc
, buf
, fragcount
, fragsize
,
201 cfg
|DMAEN
, count
, sport
->wdsize
);
205 EXPORT_SYMBOL(sport_config_rx_dma
);
207 unsigned long sport_curr_offset_tx(struct sport_device
*sport
)
209 unsigned long curr
= get_dma_curr_addr(sport
->tx_dma_chan
);
211 return (unsigned char *)curr
- sport
->tx_buf
;
213 EXPORT_SYMBOL(sport_curr_offset_tx
);
215 unsigned long sport_curr_offset_rx(struct sport_device
*sport
)
217 unsigned long curr
= get_dma_curr_addr(sport
->rx_dma_chan
);
219 return (unsigned char *)curr
- sport
->rx_buf
;
221 EXPORT_SYMBOL(sport_curr_offset_rx
);
223 static irqreturn_t
sport_tx_irq(int irq
, void *dev_id
)
225 struct sport_device
*sport
= dev_id
;
226 static unsigned long status
;
228 status
= get_dma_curr_irqstat(sport
->tx_dma_chan
);
229 if (status
& (DMA_DONE
|DMA_ERR
)) {
230 clear_dma_irqstat(sport
->tx_dma_chan
);
233 if (sport
->tx_callback
)
234 sport
->tx_callback(sport
->tx_data
);
238 static irqreturn_t
sport_rx_irq(int irq
, void *dev_id
)
240 struct sport_device
*sport
= dev_id
;
241 unsigned long status
;
243 status
= get_dma_curr_irqstat(sport
->rx_dma_chan
);
244 if (status
& (DMA_DONE
|DMA_ERR
)) {
245 clear_dma_irqstat(sport
->rx_dma_chan
);
248 if (sport
->rx_callback
)
249 sport
->rx_callback(sport
->rx_data
);
253 static irqreturn_t
sport_err_irq(int irq
, void *dev_id
)
255 struct sport_device
*sport
= dev_id
;
256 struct device
*dev
= &sport
->pdev
->dev
;
258 if (sport
->tx_regs
->spctl
& SPORT_CTL_DERRPRI
)
259 dev_err(dev
, "sport error: TUVF\n");
260 if (sport
->rx_regs
->spctl
& SPORT_CTL_DERRPRI
)
261 dev_err(dev
, "sport error: ROVF\n");
266 static int sport_get_resource(struct sport_device
*sport
)
268 struct platform_device
*pdev
= sport
->pdev
;
269 struct device
*dev
= &pdev
->dev
;
270 struct bfin_snd_platform_data
*pdata
= dev
->platform_data
;
271 struct resource
*res
;
274 dev_err(dev
, "No platform data\n");
277 sport
->pin_req
= pdata
->pin_req
;
279 res
= platform_get_resource(pdev
, IORESOURCE_MEM
, 0);
281 dev_err(dev
, "No tx MEM resource\n");
284 sport
->tx_regs
= (struct sport_register
*)res
->start
;
286 res
= platform_get_resource(pdev
, IORESOURCE_MEM
, 1);
288 dev_err(dev
, "No rx MEM resource\n");
291 sport
->rx_regs
= (struct sport_register
*)res
->start
;
293 res
= platform_get_resource(pdev
, IORESOURCE_DMA
, 0);
295 dev_err(dev
, "No tx DMA resource\n");
298 sport
->tx_dma_chan
= res
->start
;
300 res
= platform_get_resource(pdev
, IORESOURCE_DMA
, 1);
302 dev_err(dev
, "No rx DMA resource\n");
305 sport
->rx_dma_chan
= res
->start
;
307 res
= platform_get_resource(pdev
, IORESOURCE_IRQ
, 0);
309 dev_err(dev
, "No tx error irq resource\n");
312 sport
->tx_err_irq
= res
->start
;
314 res
= platform_get_resource(pdev
, IORESOURCE_IRQ
, 1);
316 dev_err(dev
, "No rx error irq resource\n");
319 sport
->rx_err_irq
= res
->start
;
324 static int sport_request_resource(struct sport_device
*sport
)
326 struct device
*dev
= &sport
->pdev
->dev
;
329 ret
= peripheral_request_list(sport
->pin_req
, "soc-audio");
331 dev_err(dev
, "Unable to request sport pin\n");
335 ret
= request_dma(sport
->tx_dma_chan
, "SPORT TX Data");
337 dev_err(dev
, "Unable to allocate DMA channel for sport tx\n");
340 set_dma_callback(sport
->tx_dma_chan
, sport_tx_irq
, sport
);
342 ret
= request_dma(sport
->rx_dma_chan
, "SPORT RX Data");
344 dev_err(dev
, "Unable to allocate DMA channel for sport rx\n");
347 set_dma_callback(sport
->rx_dma_chan
, sport_rx_irq
, sport
);
349 ret
= request_irq(sport
->tx_err_irq
, sport_err_irq
,
350 0, "SPORT TX ERROR", sport
);
352 dev_err(dev
, "Unable to allocate tx error IRQ for sport\n");
356 ret
= request_irq(sport
->rx_err_irq
, sport_err_irq
,
357 0, "SPORT RX ERROR", sport
);
359 dev_err(dev
, "Unable to allocate rx error IRQ for sport\n");
365 free_irq(sport
->tx_err_irq
, sport
);
367 free_dma(sport
->rx_dma_chan
);
369 free_dma(sport
->tx_dma_chan
);
371 peripheral_free_list(sport
->pin_req
);
375 static void sport_free_resource(struct sport_device
*sport
)
377 free_irq(sport
->rx_err_irq
, sport
);
378 free_irq(sport
->tx_err_irq
, sport
);
379 free_dma(sport
->rx_dma_chan
);
380 free_dma(sport
->tx_dma_chan
);
381 peripheral_free_list(sport
->pin_req
);
384 struct sport_device
*sport_create(struct platform_device
*pdev
)
386 struct device
*dev
= &pdev
->dev
;
387 struct sport_device
*sport
;
390 sport
= kzalloc(sizeof(*sport
), GFP_KERNEL
);
392 dev_err(dev
, "Unable to allocate memory for sport device\n");
397 ret
= sport_get_resource(sport
);
403 ret
= sport_request_resource(sport
);
409 dev_dbg(dev
, "SPORT create success\n");
412 EXPORT_SYMBOL(sport_create
);
414 void sport_delete(struct sport_device
*sport
)
417 dma_free_coherent(NULL
, sport
->tx_desc_size
,
420 dma_free_coherent(NULL
, sport
->rx_desc_size
,
422 sport_free_resource(sport
);
425 EXPORT_SYMBOL(sport_delete
);
427 MODULE_DESCRIPTION("Analog Devices BF6XX SPORT driver");
428 MODULE_AUTHOR("Scott Jiang <Scott.Jiang.Linux@gmail.com>");
429 MODULE_LICENSE("GPL v2");