diff options
Diffstat (limited to 'arch/arm/plat-omap/mcbsp.c')
-rw-r--r-- | arch/arm/plat-omap/mcbsp.c | 385 |
1 files changed, 164 insertions, 221 deletions
diff --git a/arch/arm/plat-omap/mcbsp.c b/arch/arm/plat-omap/mcbsp.c index 6c62af108710..4b15cd7926d7 100644 --- a/arch/arm/plat-omap/mcbsp.c +++ b/arch/arm/plat-omap/mcbsp.c | |||
@@ -24,45 +24,40 @@ | |||
24 | #include <linux/slab.h> | 24 | #include <linux/slab.h> |
25 | 25 | ||
26 | #include <plat/mcbsp.h> | 26 | #include <plat/mcbsp.h> |
27 | #include <plat/omap_device.h> | ||
28 | #include <linux/pm_runtime.h> | 27 | #include <linux/pm_runtime.h> |
29 | 28 | ||
30 | /* XXX These "sideways" includes are a sign that something is wrong */ | ||
31 | #include "../mach-omap2/cm2xxx_3xxx.h" | ||
32 | #include "../mach-omap2/cm-regbits-34xx.h" | ||
33 | |||
34 | struct omap_mcbsp **mcbsp_ptr; | 29 | struct omap_mcbsp **mcbsp_ptr; |
35 | int omap_mcbsp_count, omap_mcbsp_cache_size; | 30 | int omap_mcbsp_count; |
31 | |||
32 | #define omap_mcbsp_check_valid_id(id) (id < omap_mcbsp_count) | ||
33 | #define id_to_mcbsp_ptr(id) mcbsp_ptr[id]; | ||
36 | 34 | ||
37 | static void omap_mcbsp_write(struct omap_mcbsp *mcbsp, u16 reg, u32 val) | 35 | static void omap_mcbsp_write(struct omap_mcbsp *mcbsp, u16 reg, u32 val) |
38 | { | 36 | { |
39 | if (cpu_class_is_omap1()) { | 37 | void __iomem *addr = mcbsp->io_base + reg * mcbsp->pdata->reg_step; |
40 | ((u16 *)mcbsp->reg_cache)[reg / sizeof(u16)] = (u16)val; | 38 | |
41 | __raw_writew((u16)val, mcbsp->io_base + reg); | 39 | if (mcbsp->pdata->reg_size == 2) { |
42 | } else if (cpu_is_omap2420()) { | 40 | ((u16 *)mcbsp->reg_cache)[reg] = (u16)val; |
43 | ((u16 *)mcbsp->reg_cache)[reg / sizeof(u32)] = (u16)val; | 41 | __raw_writew((u16)val, addr); |
44 | __raw_writew((u16)val, mcbsp->io_base + reg); | ||
45 | } else { | 42 | } else { |
46 | ((u32 *)mcbsp->reg_cache)[reg / sizeof(u32)] = val; | 43 | ((u32 *)mcbsp->reg_cache)[reg] = val; |
47 | __raw_writel(val, mcbsp->io_base + reg); | 44 | __raw_writel(val, addr); |
48 | } | 45 | } |
49 | } | 46 | } |
50 | 47 | ||
51 | static int omap_mcbsp_read(struct omap_mcbsp *mcbsp, u16 reg, bool from_cache) | 48 | static int omap_mcbsp_read(struct omap_mcbsp *mcbsp, u16 reg, bool from_cache) |
52 | { | 49 | { |
53 | if (cpu_class_is_omap1()) { | 50 | void __iomem *addr = mcbsp->io_base + reg * mcbsp->pdata->reg_step; |
54 | return !from_cache ? __raw_readw(mcbsp->io_base + reg) : | 51 | |
55 | ((u16 *)mcbsp->reg_cache)[reg / sizeof(u16)]; | 52 | if (mcbsp->pdata->reg_size == 2) { |
56 | } else if (cpu_is_omap2420()) { | 53 | return !from_cache ? __raw_readw(addr) : |
57 | return !from_cache ? __raw_readw(mcbsp->io_base + reg) : | 54 | ((u16 *)mcbsp->reg_cache)[reg]; |
58 | ((u16 *)mcbsp->reg_cache)[reg / sizeof(u32)]; | ||
59 | } else { | 55 | } else { |
60 | return !from_cache ? __raw_readl(mcbsp->io_base + reg) : | 56 | return !from_cache ? __raw_readl(addr) : |
61 | ((u32 *)mcbsp->reg_cache)[reg / sizeof(u32)]; | 57 | ((u32 *)mcbsp->reg_cache)[reg]; |
62 | } | 58 | } |
63 | } | 59 | } |
64 | 60 | ||
65 | #ifdef CONFIG_ARCH_OMAP3 | ||
66 | static void omap_mcbsp_st_write(struct omap_mcbsp *mcbsp, u16 reg, u32 val) | 61 | static void omap_mcbsp_st_write(struct omap_mcbsp *mcbsp, u16 reg, u32 val) |
67 | { | 62 | { |
68 | __raw_writel(val, mcbsp->st_data->io_base_st + reg); | 63 | __raw_writel(val, mcbsp->st_data->io_base_st + reg); |
@@ -72,7 +67,6 @@ static int omap_mcbsp_st_read(struct omap_mcbsp *mcbsp, u16 reg) | |||
72 | { | 67 | { |
73 | return __raw_readl(mcbsp->st_data->io_base_st + reg); | 68 | return __raw_readl(mcbsp->st_data->io_base_st + reg); |
74 | } | 69 | } |
75 | #endif | ||
76 | 70 | ||
77 | #define MCBSP_READ(mcbsp, reg) \ | 71 | #define MCBSP_READ(mcbsp, reg) \ |
78 | omap_mcbsp_read(mcbsp, OMAP_MCBSP_REG_##reg, 0) | 72 | omap_mcbsp_read(mcbsp, OMAP_MCBSP_REG_##reg, 0) |
@@ -187,7 +181,7 @@ void omap_mcbsp_config(unsigned int id, const struct omap_mcbsp_reg_cfg *config) | |||
187 | MCBSP_WRITE(mcbsp, MCR2, config->mcr2); | 181 | MCBSP_WRITE(mcbsp, MCR2, config->mcr2); |
188 | MCBSP_WRITE(mcbsp, MCR1, config->mcr1); | 182 | MCBSP_WRITE(mcbsp, MCR1, config->mcr1); |
189 | MCBSP_WRITE(mcbsp, PCR0, config->pcr0); | 183 | MCBSP_WRITE(mcbsp, PCR0, config->pcr0); |
190 | if (cpu_is_omap2430() || cpu_is_omap34xx() || cpu_is_omap44xx()) { | 184 | if (mcbsp->pdata->has_ccr) { |
191 | MCBSP_WRITE(mcbsp, XCCR, config->xccr); | 185 | MCBSP_WRITE(mcbsp, XCCR, config->xccr); |
192 | MCBSP_WRITE(mcbsp, RCCR, config->rccr); | 186 | MCBSP_WRITE(mcbsp, RCCR, config->rccr); |
193 | } | 187 | } |
@@ -239,46 +233,28 @@ int omap_mcbsp_dma_reg_params(unsigned int id, unsigned int stream) | |||
239 | } | 233 | } |
240 | mcbsp = id_to_mcbsp_ptr(id); | 234 | mcbsp = id_to_mcbsp_ptr(id); |
241 | 235 | ||
242 | data_reg = mcbsp->phys_dma_base; | 236 | if (mcbsp->pdata->reg_size == 2) { |
243 | |||
244 | if (mcbsp->mcbsp_config_type < MCBSP_CONFIG_TYPE2) { | ||
245 | if (stream) | 237 | if (stream) |
246 | data_reg += OMAP_MCBSP_REG_DRR1; | 238 | data_reg = OMAP_MCBSP_REG_DRR1; |
247 | else | 239 | else |
248 | data_reg += OMAP_MCBSP_REG_DXR1; | 240 | data_reg = OMAP_MCBSP_REG_DXR1; |
249 | } else { | 241 | } else { |
250 | if (stream) | 242 | if (stream) |
251 | data_reg += OMAP_MCBSP_REG_DRR; | 243 | data_reg = OMAP_MCBSP_REG_DRR; |
252 | else | 244 | else |
253 | data_reg += OMAP_MCBSP_REG_DXR; | 245 | data_reg = OMAP_MCBSP_REG_DXR; |
254 | } | 246 | } |
255 | 247 | ||
256 | return data_reg; | 248 | return mcbsp->phys_dma_base + data_reg * mcbsp->pdata->reg_step; |
257 | } | 249 | } |
258 | EXPORT_SYMBOL(omap_mcbsp_dma_reg_params); | 250 | EXPORT_SYMBOL(omap_mcbsp_dma_reg_params); |
259 | 251 | ||
260 | #ifdef CONFIG_ARCH_OMAP3 | ||
261 | static struct omap_device *find_omap_device_by_dev(struct device *dev) | ||
262 | { | ||
263 | struct platform_device *pdev = container_of(dev, | ||
264 | struct platform_device, dev); | ||
265 | return container_of(pdev, struct omap_device, pdev); | ||
266 | } | ||
267 | |||
268 | static void omap_st_on(struct omap_mcbsp *mcbsp) | 252 | static void omap_st_on(struct omap_mcbsp *mcbsp) |
269 | { | 253 | { |
270 | unsigned int w; | 254 | unsigned int w; |
271 | struct omap_device *od; | ||
272 | 255 | ||
273 | od = find_omap_device_by_dev(mcbsp->dev); | 256 | if (mcbsp->pdata->enable_st_clock) |
274 | 257 | mcbsp->pdata->enable_st_clock(mcbsp->id, 1); | |
275 | /* | ||
276 | * Sidetone uses McBSP ICLK - which must not idle when sidetones | ||
277 | * are enabled or sidetones start sounding ugly. | ||
278 | */ | ||
279 | w = omap2_cm_read_mod_reg(OMAP3430_PER_MOD, CM_AUTOIDLE); | ||
280 | w &= ~(1 << (mcbsp->id - 2)); | ||
281 | omap2_cm_write_mod_reg(w, OMAP3430_PER_MOD, CM_AUTOIDLE); | ||
282 | 258 | ||
283 | /* Enable McBSP Sidetone */ | 259 | /* Enable McBSP Sidetone */ |
284 | w = MCBSP_READ(mcbsp, SSELCR); | 260 | w = MCBSP_READ(mcbsp, SSELCR); |
@@ -292,9 +268,6 @@ static void omap_st_on(struct omap_mcbsp *mcbsp) | |||
292 | static void omap_st_off(struct omap_mcbsp *mcbsp) | 268 | static void omap_st_off(struct omap_mcbsp *mcbsp) |
293 | { | 269 | { |
294 | unsigned int w; | 270 | unsigned int w; |
295 | struct omap_device *od; | ||
296 | |||
297 | od = find_omap_device_by_dev(mcbsp->dev); | ||
298 | 271 | ||
299 | w = MCBSP_ST_READ(mcbsp, SSELCR); | 272 | w = MCBSP_ST_READ(mcbsp, SSELCR); |
300 | MCBSP_ST_WRITE(mcbsp, SSELCR, w & ~(ST_SIDETONEEN)); | 273 | MCBSP_ST_WRITE(mcbsp, SSELCR, w & ~(ST_SIDETONEEN)); |
@@ -302,17 +275,13 @@ static void omap_st_off(struct omap_mcbsp *mcbsp) | |||
302 | w = MCBSP_READ(mcbsp, SSELCR); | 275 | w = MCBSP_READ(mcbsp, SSELCR); |
303 | MCBSP_WRITE(mcbsp, SSELCR, w & ~(SIDETONEEN)); | 276 | MCBSP_WRITE(mcbsp, SSELCR, w & ~(SIDETONEEN)); |
304 | 277 | ||
305 | w = omap2_cm_read_mod_reg(OMAP3430_PER_MOD, CM_AUTOIDLE); | 278 | if (mcbsp->pdata->enable_st_clock) |
306 | w |= 1 << (mcbsp->id - 2); | 279 | mcbsp->pdata->enable_st_clock(mcbsp->id, 0); |
307 | omap2_cm_write_mod_reg(w, OMAP3430_PER_MOD, CM_AUTOIDLE); | ||
308 | } | 280 | } |
309 | 281 | ||
310 | static void omap_st_fir_write(struct omap_mcbsp *mcbsp, s16 *fir) | 282 | static void omap_st_fir_write(struct omap_mcbsp *mcbsp, s16 *fir) |
311 | { | 283 | { |
312 | u16 val, i; | 284 | u16 val, i; |
313 | struct omap_device *od; | ||
314 | |||
315 | od = find_omap_device_by_dev(mcbsp->dev); | ||
316 | 285 | ||
317 | val = MCBSP_ST_READ(mcbsp, SSELCR); | 286 | val = MCBSP_ST_READ(mcbsp, SSELCR); |
318 | 287 | ||
@@ -340,9 +309,6 @@ static void omap_st_chgain(struct omap_mcbsp *mcbsp) | |||
340 | { | 309 | { |
341 | u16 w; | 310 | u16 w; |
342 | struct omap_mcbsp_st_data *st_data = mcbsp->st_data; | 311 | struct omap_mcbsp_st_data *st_data = mcbsp->st_data; |
343 | struct omap_device *od; | ||
344 | |||
345 | od = find_omap_device_by_dev(mcbsp->dev); | ||
346 | 312 | ||
347 | w = MCBSP_ST_READ(mcbsp, SSELCR); | 313 | w = MCBSP_ST_READ(mcbsp, SSELCR); |
348 | 314 | ||
@@ -525,14 +491,13 @@ void omap_mcbsp_set_tx_threshold(unsigned int id, u16 threshold) | |||
525 | { | 491 | { |
526 | struct omap_mcbsp *mcbsp; | 492 | struct omap_mcbsp *mcbsp; |
527 | 493 | ||
528 | if (!cpu_is_omap34xx() && !cpu_is_omap44xx()) | ||
529 | return; | ||
530 | |||
531 | if (!omap_mcbsp_check_valid_id(id)) { | 494 | if (!omap_mcbsp_check_valid_id(id)) { |
532 | printk(KERN_ERR "%s: Invalid id (%d)\n", __func__, id + 1); | 495 | printk(KERN_ERR "%s: Invalid id (%d)\n", __func__, id + 1); |
533 | return; | 496 | return; |
534 | } | 497 | } |
535 | mcbsp = id_to_mcbsp_ptr(id); | 498 | mcbsp = id_to_mcbsp_ptr(id); |
499 | if (mcbsp->pdata->buffer_size == 0) | ||
500 | return; | ||
536 | 501 | ||
537 | if (threshold && threshold <= mcbsp->max_tx_thres) | 502 | if (threshold && threshold <= mcbsp->max_tx_thres) |
538 | MCBSP_WRITE(mcbsp, THRSH2, threshold - 1); | 503 | MCBSP_WRITE(mcbsp, THRSH2, threshold - 1); |
@@ -548,14 +513,13 @@ void omap_mcbsp_set_rx_threshold(unsigned int id, u16 threshold) | |||
548 | { | 513 | { |
549 | struct omap_mcbsp *mcbsp; | 514 | struct omap_mcbsp *mcbsp; |
550 | 515 | ||
551 | if (!cpu_is_omap34xx() && !cpu_is_omap44xx()) | ||
552 | return; | ||
553 | |||
554 | if (!omap_mcbsp_check_valid_id(id)) { | 516 | if (!omap_mcbsp_check_valid_id(id)) { |
555 | printk(KERN_ERR "%s: Invalid id (%d)\n", __func__, id + 1); | 517 | printk(KERN_ERR "%s: Invalid id (%d)\n", __func__, id + 1); |
556 | return; | 518 | return; |
557 | } | 519 | } |
558 | mcbsp = id_to_mcbsp_ptr(id); | 520 | mcbsp = id_to_mcbsp_ptr(id); |
521 | if (mcbsp->pdata->buffer_size == 0) | ||
522 | return; | ||
559 | 523 | ||
560 | if (threshold && threshold <= mcbsp->max_rx_thres) | 524 | if (threshold && threshold <= mcbsp->max_rx_thres) |
561 | MCBSP_WRITE(mcbsp, THRSH1, threshold - 1); | 525 | MCBSP_WRITE(mcbsp, THRSH1, threshold - 1); |
@@ -625,6 +589,8 @@ u16 omap_mcbsp_get_tx_delay(unsigned int id) | |||
625 | return -ENODEV; | 589 | return -ENODEV; |
626 | } | 590 | } |
627 | mcbsp = id_to_mcbsp_ptr(id); | 591 | mcbsp = id_to_mcbsp_ptr(id); |
592 | if (mcbsp->pdata->buffer_size == 0) | ||
593 | return 0; | ||
628 | 594 | ||
629 | /* Returns the number of free locations in the buffer */ | 595 | /* Returns the number of free locations in the buffer */ |
630 | buffstat = MCBSP_READ(mcbsp, XBUFFSTAT); | 596 | buffstat = MCBSP_READ(mcbsp, XBUFFSTAT); |
@@ -648,6 +614,8 @@ u16 omap_mcbsp_get_rx_delay(unsigned int id) | |||
648 | return -ENODEV; | 614 | return -ENODEV; |
649 | } | 615 | } |
650 | mcbsp = id_to_mcbsp_ptr(id); | 616 | mcbsp = id_to_mcbsp_ptr(id); |
617 | if (mcbsp->pdata->buffer_size == 0) | ||
618 | return 0; | ||
651 | 619 | ||
652 | /* Returns the number of used locations in the buffer */ | 620 | /* Returns the number of used locations in the buffer */ |
653 | buffstat = MCBSP_READ(mcbsp, RBUFFSTAT); | 621 | buffstat = MCBSP_READ(mcbsp, RBUFFSTAT); |
@@ -683,46 +651,6 @@ int omap_mcbsp_get_dma_op_mode(unsigned int id) | |||
683 | } | 651 | } |
684 | EXPORT_SYMBOL(omap_mcbsp_get_dma_op_mode); | 652 | EXPORT_SYMBOL(omap_mcbsp_get_dma_op_mode); |
685 | 653 | ||
686 | static inline void omap34xx_mcbsp_request(struct omap_mcbsp *mcbsp) | ||
687 | { | ||
688 | struct omap_device *od; | ||
689 | |||
690 | od = find_omap_device_by_dev(mcbsp->dev); | ||
691 | /* | ||
692 | * Enable wakup behavior, smart idle and all wakeups | ||
693 | * REVISIT: some wakeups may be unnecessary | ||
694 | */ | ||
695 | if (cpu_is_omap34xx() || cpu_is_omap44xx()) { | ||
696 | MCBSP_WRITE(mcbsp, WAKEUPEN, XRDYEN | RRDYEN); | ||
697 | } | ||
698 | } | ||
699 | |||
700 | static inline void omap34xx_mcbsp_free(struct omap_mcbsp *mcbsp) | ||
701 | { | ||
702 | struct omap_device *od; | ||
703 | |||
704 | od = find_omap_device_by_dev(mcbsp->dev); | ||
705 | |||
706 | /* | ||
707 | * Disable wakup behavior, smart idle and all wakeups | ||
708 | */ | ||
709 | if (cpu_is_omap34xx() || cpu_is_omap44xx()) { | ||
710 | /* | ||
711 | * HW bug workaround - If no_idle mode is taken, we need to | ||
712 | * go to smart_idle before going to always_idle, or the | ||
713 | * device will not hit retention anymore. | ||
714 | */ | ||
715 | |||
716 | MCBSP_WRITE(mcbsp, WAKEUPEN, 0); | ||
717 | } | ||
718 | } | ||
719 | #else | ||
720 | static inline void omap34xx_mcbsp_request(struct omap_mcbsp *mcbsp) {} | ||
721 | static inline void omap34xx_mcbsp_free(struct omap_mcbsp *mcbsp) {} | ||
722 | static inline void omap_st_start(struct omap_mcbsp *mcbsp) {} | ||
723 | static inline void omap_st_stop(struct omap_mcbsp *mcbsp) {} | ||
724 | #endif | ||
725 | |||
726 | int omap_mcbsp_request(unsigned int id) | 654 | int omap_mcbsp_request(unsigned int id) |
727 | { | 655 | { |
728 | struct omap_mcbsp *mcbsp; | 656 | struct omap_mcbsp *mcbsp; |
@@ -735,7 +663,7 @@ int omap_mcbsp_request(unsigned int id) | |||
735 | } | 663 | } |
736 | mcbsp = id_to_mcbsp_ptr(id); | 664 | mcbsp = id_to_mcbsp_ptr(id); |
737 | 665 | ||
738 | reg_cache = kzalloc(omap_mcbsp_cache_size, GFP_KERNEL); | 666 | reg_cache = kzalloc(mcbsp->reg_cache_size, GFP_KERNEL); |
739 | if (!reg_cache) { | 667 | if (!reg_cache) { |
740 | return -ENOMEM; | 668 | return -ENOMEM; |
741 | } | 669 | } |
@@ -757,8 +685,9 @@ int omap_mcbsp_request(unsigned int id) | |||
757 | 685 | ||
758 | pm_runtime_get_sync(mcbsp->dev); | 686 | pm_runtime_get_sync(mcbsp->dev); |
759 | 687 | ||
760 | /* Do procedure specific to omap34xx arch, if applicable */ | 688 | /* Enable wakeup behavior */ |
761 | omap34xx_mcbsp_request(mcbsp); | 689 | if (mcbsp->pdata->has_wakeup) |
690 | MCBSP_WRITE(mcbsp, WAKEUPEN, XRDYEN | RRDYEN); | ||
762 | 691 | ||
763 | /* | 692 | /* |
764 | * Make sure that transmitter, receiver and sample-rate generator are | 693 | * Make sure that transmitter, receiver and sample-rate generator are |
@@ -795,8 +724,9 @@ err_clk_disable: | |||
795 | if (mcbsp->pdata && mcbsp->pdata->ops && mcbsp->pdata->ops->free) | 724 | if (mcbsp->pdata && mcbsp->pdata->ops && mcbsp->pdata->ops->free) |
796 | mcbsp->pdata->ops->free(id); | 725 | mcbsp->pdata->ops->free(id); |
797 | 726 | ||
798 | /* Do procedure specific to omap34xx arch, if applicable */ | 727 | /* Disable wakeup behavior */ |
799 | omap34xx_mcbsp_free(mcbsp); | 728 | if (mcbsp->pdata->has_wakeup) |
729 | MCBSP_WRITE(mcbsp, WAKEUPEN, 0); | ||
800 | 730 | ||
801 | pm_runtime_put_sync(mcbsp->dev); | 731 | pm_runtime_put_sync(mcbsp->dev); |
802 | 732 | ||
@@ -825,8 +755,9 @@ void omap_mcbsp_free(unsigned int id) | |||
825 | if (mcbsp->pdata && mcbsp->pdata->ops && mcbsp->pdata->ops->free) | 755 | if (mcbsp->pdata && mcbsp->pdata->ops && mcbsp->pdata->ops->free) |
826 | mcbsp->pdata->ops->free(id); | 756 | mcbsp->pdata->ops->free(id); |
827 | 757 | ||
828 | /* Do procedure specific to omap34xx arch, if applicable */ | 758 | /* Disable wakeup behavior */ |
829 | omap34xx_mcbsp_free(mcbsp); | 759 | if (mcbsp->pdata->has_wakeup) |
760 | MCBSP_WRITE(mcbsp, WAKEUPEN, 0); | ||
830 | 761 | ||
831 | pm_runtime_put_sync(mcbsp->dev); | 762 | pm_runtime_put_sync(mcbsp->dev); |
832 | 763 | ||
@@ -866,7 +797,7 @@ void omap_mcbsp_start(unsigned int id, int tx, int rx) | |||
866 | } | 797 | } |
867 | mcbsp = id_to_mcbsp_ptr(id); | 798 | mcbsp = id_to_mcbsp_ptr(id); |
868 | 799 | ||
869 | if (cpu_is_omap34xx()) | 800 | if (mcbsp->st_data) |
870 | omap_st_start(mcbsp); | 801 | omap_st_start(mcbsp); |
871 | 802 | ||
872 | /* Only enable SRG, if McBSP is master */ | 803 | /* Only enable SRG, if McBSP is master */ |
@@ -904,7 +835,7 @@ void omap_mcbsp_start(unsigned int id, int tx, int rx) | |||
904 | MCBSP_WRITE(mcbsp, SPCR2, w | (1 << 7)); | 835 | MCBSP_WRITE(mcbsp, SPCR2, w | (1 << 7)); |
905 | } | 836 | } |
906 | 837 | ||
907 | if (cpu_is_omap2430() || cpu_is_omap34xx() || cpu_is_omap44xx()) { | 838 | if (mcbsp->pdata->has_ccr) { |
908 | /* Release the transmitter and receiver */ | 839 | /* Release the transmitter and receiver */ |
909 | w = MCBSP_READ_CACHE(mcbsp, XCCR); | 840 | w = MCBSP_READ_CACHE(mcbsp, XCCR); |
910 | w &= ~(tx ? XDISABLE : 0); | 841 | w &= ~(tx ? XDISABLE : 0); |
@@ -934,7 +865,7 @@ void omap_mcbsp_stop(unsigned int id, int tx, int rx) | |||
934 | 865 | ||
935 | /* Reset transmitter */ | 866 | /* Reset transmitter */ |
936 | tx &= 1; | 867 | tx &= 1; |
937 | if (cpu_is_omap2430() || cpu_is_omap34xx() || cpu_is_omap44xx()) { | 868 | if (mcbsp->pdata->has_ccr) { |
938 | w = MCBSP_READ_CACHE(mcbsp, XCCR); | 869 | w = MCBSP_READ_CACHE(mcbsp, XCCR); |
939 | w |= (tx ? XDISABLE : 0); | 870 | w |= (tx ? XDISABLE : 0); |
940 | MCBSP_WRITE(mcbsp, XCCR, w); | 871 | MCBSP_WRITE(mcbsp, XCCR, w); |
@@ -944,7 +875,7 @@ void omap_mcbsp_stop(unsigned int id, int tx, int rx) | |||
944 | 875 | ||
945 | /* Reset receiver */ | 876 | /* Reset receiver */ |
946 | rx &= 1; | 877 | rx &= 1; |
947 | if (cpu_is_omap2430() || cpu_is_omap34xx() || cpu_is_omap44xx()) { | 878 | if (mcbsp->pdata->has_ccr) { |
948 | w = MCBSP_READ_CACHE(mcbsp, RCCR); | 879 | w = MCBSP_READ_CACHE(mcbsp, RCCR); |
949 | w |= (rx ? RDISABLE : 0); | 880 | w |= (rx ? RDISABLE : 0); |
950 | MCBSP_WRITE(mcbsp, RCCR, w); | 881 | MCBSP_WRITE(mcbsp, RCCR, w); |
@@ -961,39 +892,72 @@ void omap_mcbsp_stop(unsigned int id, int tx, int rx) | |||
961 | MCBSP_WRITE(mcbsp, SPCR2, w & ~(1 << 6)); | 892 | MCBSP_WRITE(mcbsp, SPCR2, w & ~(1 << 6)); |
962 | } | 893 | } |
963 | 894 | ||
964 | if (cpu_is_omap34xx()) | 895 | if (mcbsp->st_data) |
965 | omap_st_stop(mcbsp); | 896 | omap_st_stop(mcbsp); |
966 | } | 897 | } |
967 | EXPORT_SYMBOL(omap_mcbsp_stop); | 898 | EXPORT_SYMBOL(omap_mcbsp_stop); |
968 | 899 | ||
969 | /* | ||
970 | * The following functions are only required on an OMAP1-only build. | ||
971 | * mach-omap2/mcbsp.c contains the real functions | ||
972 | */ | ||
973 | #ifndef CONFIG_ARCH_OMAP2PLUS | ||
974 | int omap2_mcbsp_set_clks_src(u8 id, u8 fck_src_id) | 900 | int omap2_mcbsp_set_clks_src(u8 id, u8 fck_src_id) |
975 | { | 901 | { |
976 | WARN(1, "%s: should never be called on an OMAP1-only kernel\n", | 902 | struct omap_mcbsp *mcbsp; |
977 | __func__); | 903 | const char *src; |
978 | return -EINVAL; | 904 | |
905 | if (!omap_mcbsp_check_valid_id(id)) { | ||
906 | pr_err("%s: Invalid id (%d)\n", __func__, id + 1); | ||
907 | return -EINVAL; | ||
908 | } | ||
909 | mcbsp = id_to_mcbsp_ptr(id); | ||
910 | |||
911 | if (fck_src_id == MCBSP_CLKS_PAD_SRC) | ||
912 | src = "clks_ext"; | ||
913 | else if (fck_src_id == MCBSP_CLKS_PRCM_SRC) | ||
914 | src = "clks_fclk"; | ||
915 | else | ||
916 | return -EINVAL; | ||
917 | |||
918 | if (mcbsp->pdata->set_clk_src) | ||
919 | return mcbsp->pdata->set_clk_src(mcbsp->dev, mcbsp->fclk, src); | ||
920 | else | ||
921 | return -EINVAL; | ||
979 | } | 922 | } |
923 | EXPORT_SYMBOL(omap2_mcbsp_set_clks_src); | ||
980 | 924 | ||
981 | void omap2_mcbsp1_mux_clkr_src(u8 mux) | 925 | void omap2_mcbsp1_mux_clkr_src(u8 mux) |
982 | { | 926 | { |
983 | WARN(1, "%s: should never be called on an OMAP1-only kernel\n", | 927 | struct omap_mcbsp *mcbsp; |
984 | __func__); | 928 | const char *src; |
985 | return; | 929 | |
930 | if (mux == CLKR_SRC_CLKR) | ||
931 | src = "clkr"; | ||
932 | else if (mux == CLKR_SRC_CLKX) | ||
933 | src = "clkx"; | ||
934 | else | ||
935 | return; | ||
936 | |||
937 | mcbsp = id_to_mcbsp_ptr(0); | ||
938 | if (mcbsp->pdata->mux_signal) | ||
939 | mcbsp->pdata->mux_signal(mcbsp->dev, "clkr", src); | ||
986 | } | 940 | } |
941 | EXPORT_SYMBOL(omap2_mcbsp1_mux_clkr_src); | ||
987 | 942 | ||
988 | void omap2_mcbsp1_mux_fsr_src(u8 mux) | 943 | void omap2_mcbsp1_mux_fsr_src(u8 mux) |
989 | { | 944 | { |
990 | WARN(1, "%s: should never be called on an OMAP1-only kernel\n", | 945 | struct omap_mcbsp *mcbsp; |
991 | __func__); | 946 | const char *src; |
992 | return; | 947 | |
948 | if (mux == FSR_SRC_FSR) | ||
949 | src = "fsr"; | ||
950 | else if (mux == FSR_SRC_FSX) | ||
951 | src = "fsx"; | ||
952 | else | ||
953 | return; | ||
954 | |||
955 | mcbsp = id_to_mcbsp_ptr(0); | ||
956 | if (mcbsp->pdata->mux_signal) | ||
957 | mcbsp->pdata->mux_signal(mcbsp->dev, "fsr", src); | ||
993 | } | 958 | } |
994 | #endif | 959 | EXPORT_SYMBOL(omap2_mcbsp1_mux_fsr_src); |
995 | 960 | ||
996 | #ifdef CONFIG_ARCH_OMAP3 | ||
997 | #define max_thres(m) (mcbsp->pdata->buffer_size) | 961 | #define max_thres(m) (mcbsp->pdata->buffer_size) |
998 | #define valid_threshold(m, val) ((val) <= max_thres(m)) | 962 | #define valid_threshold(m, val) ((val) <= max_thres(m)) |
999 | #define THRESHOLD_PROP_BUILDER(prop) \ | 963 | #define THRESHOLD_PROP_BUILDER(prop) \ |
@@ -1084,6 +1048,17 @@ unlock: | |||
1084 | 1048 | ||
1085 | static DEVICE_ATTR(dma_op_mode, 0644, dma_op_mode_show, dma_op_mode_store); | 1049 | static DEVICE_ATTR(dma_op_mode, 0644, dma_op_mode_show, dma_op_mode_store); |
1086 | 1050 | ||
1051 | static const struct attribute *additional_attrs[] = { | ||
1052 | &dev_attr_max_tx_thres.attr, | ||
1053 | &dev_attr_max_rx_thres.attr, | ||
1054 | &dev_attr_dma_op_mode.attr, | ||
1055 | NULL, | ||
1056 | }; | ||
1057 | |||
1058 | static const struct attribute_group additional_attr_group = { | ||
1059 | .attrs = (struct attribute **)additional_attrs, | ||
1060 | }; | ||
1061 | |||
1087 | static ssize_t st_taps_show(struct device *dev, | 1062 | static ssize_t st_taps_show(struct device *dev, |
1088 | struct device_attribute *attr, char *buf) | 1063 | struct device_attribute *attr, char *buf) |
1089 | { | 1064 | { |
@@ -1142,27 +1117,6 @@ out: | |||
1142 | 1117 | ||
1143 | static DEVICE_ATTR(st_taps, 0644, st_taps_show, st_taps_store); | 1118 | static DEVICE_ATTR(st_taps, 0644, st_taps_show, st_taps_store); |
1144 | 1119 | ||
1145 | static const struct attribute *additional_attrs[] = { | ||
1146 | &dev_attr_max_tx_thres.attr, | ||
1147 | &dev_attr_max_rx_thres.attr, | ||
1148 | &dev_attr_dma_op_mode.attr, | ||
1149 | NULL, | ||
1150 | }; | ||
1151 | |||
1152 | static const struct attribute_group additional_attr_group = { | ||
1153 | .attrs = (struct attribute **)additional_attrs, | ||
1154 | }; | ||
1155 | |||
1156 | static inline int __devinit omap_additional_add(struct device *dev) | ||
1157 | { | ||
1158 | return sysfs_create_group(&dev->kobj, &additional_attr_group); | ||
1159 | } | ||
1160 | |||
1161 | static inline void __devexit omap_additional_remove(struct device *dev) | ||
1162 | { | ||
1163 | sysfs_remove_group(&dev->kobj, &additional_attr_group); | ||
1164 | } | ||
1165 | |||
1166 | static const struct attribute *sidetone_attrs[] = { | 1120 | static const struct attribute *sidetone_attrs[] = { |
1167 | &dev_attr_st_taps.attr, | 1121 | &dev_attr_st_taps.attr, |
1168 | NULL, | 1122 | NULL, |
@@ -1172,10 +1126,9 @@ static const struct attribute_group sidetone_attr_group = { | |||
1172 | .attrs = (struct attribute **)sidetone_attrs, | 1126 | .attrs = (struct attribute **)sidetone_attrs, |
1173 | }; | 1127 | }; |
1174 | 1128 | ||
1175 | static int __devinit omap_st_add(struct omap_mcbsp *mcbsp) | 1129 | static int __devinit omap_st_add(struct omap_mcbsp *mcbsp, |
1130 | struct resource *res) | ||
1176 | { | 1131 | { |
1177 | struct platform_device *pdev; | ||
1178 | struct resource *res; | ||
1179 | struct omap_mcbsp_st_data *st_data; | 1132 | struct omap_mcbsp_st_data *st_data; |
1180 | int err; | 1133 | int err; |
1181 | 1134 | ||
@@ -1185,9 +1138,6 @@ static int __devinit omap_st_add(struct omap_mcbsp *mcbsp) | |||
1185 | goto err1; | 1138 | goto err1; |
1186 | } | 1139 | } |
1187 | 1140 | ||
1188 | pdev = container_of(mcbsp->dev, struct platform_device, dev); | ||
1189 | |||
1190 | res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "sidetone"); | ||
1191 | st_data->io_base_st = ioremap(res->start, resource_size(res)); | 1141 | st_data->io_base_st = ioremap(res->start, resource_size(res)); |
1192 | if (!st_data->io_base_st) { | 1142 | if (!st_data->io_base_st) { |
1193 | err = -ENOMEM; | 1143 | err = -ENOMEM; |
@@ -1214,59 +1164,10 @@ static void __devexit omap_st_remove(struct omap_mcbsp *mcbsp) | |||
1214 | { | 1164 | { |
1215 | struct omap_mcbsp_st_data *st_data = mcbsp->st_data; | 1165 | struct omap_mcbsp_st_data *st_data = mcbsp->st_data; |
1216 | 1166 | ||
1217 | if (st_data) { | 1167 | sysfs_remove_group(&mcbsp->dev->kobj, &sidetone_attr_group); |
1218 | sysfs_remove_group(&mcbsp->dev->kobj, &sidetone_attr_group); | 1168 | iounmap(st_data->io_base_st); |
1219 | iounmap(st_data->io_base_st); | 1169 | kfree(st_data); |
1220 | kfree(st_data); | ||
1221 | } | ||
1222 | } | ||
1223 | |||
1224 | static inline void __devinit omap34xx_device_init(struct omap_mcbsp *mcbsp) | ||
1225 | { | ||
1226 | mcbsp->dma_op_mode = MCBSP_DMA_MODE_ELEMENT; | ||
1227 | if (cpu_is_omap34xx()) { | ||
1228 | /* | ||
1229 | * Initially configure the maximum thresholds to a safe value. | ||
1230 | * The McBSP FIFO usage with these values should not go under | ||
1231 | * 16 locations. | ||
1232 | * If the whole FIFO without safety buffer is used, than there | ||
1233 | * is a possibility that the DMA will be not able to push the | ||
1234 | * new data on time, causing channel shifts in runtime. | ||
1235 | */ | ||
1236 | mcbsp->max_tx_thres = max_thres(mcbsp) - 0x10; | ||
1237 | mcbsp->max_rx_thres = max_thres(mcbsp) - 0x10; | ||
1238 | /* | ||
1239 | * REVISIT: Set dmap_op_mode to THRESHOLD as default | ||
1240 | * for mcbsp2 instances. | ||
1241 | */ | ||
1242 | if (omap_additional_add(mcbsp->dev)) | ||
1243 | dev_warn(mcbsp->dev, | ||
1244 | "Unable to create additional controls\n"); | ||
1245 | |||
1246 | if (mcbsp->id == 2 || mcbsp->id == 3) | ||
1247 | if (omap_st_add(mcbsp)) | ||
1248 | dev_warn(mcbsp->dev, | ||
1249 | "Unable to create sidetone controls\n"); | ||
1250 | |||
1251 | } else { | ||
1252 | mcbsp->max_tx_thres = -EINVAL; | ||
1253 | mcbsp->max_rx_thres = -EINVAL; | ||
1254 | } | ||
1255 | } | ||
1256 | |||
1257 | static inline void __devexit omap34xx_device_exit(struct omap_mcbsp *mcbsp) | ||
1258 | { | ||
1259 | if (cpu_is_omap34xx()) { | ||
1260 | omap_additional_remove(mcbsp->dev); | ||
1261 | |||
1262 | if (mcbsp->id == 2 || mcbsp->id == 3) | ||
1263 | omap_st_remove(mcbsp); | ||
1264 | } | ||
1265 | } | 1170 | } |
1266 | #else | ||
1267 | static inline void __devinit omap34xx_device_init(struct omap_mcbsp *mcbsp) {} | ||
1268 | static inline void __devexit omap34xx_device_exit(struct omap_mcbsp *mcbsp) {} | ||
1269 | #endif /* CONFIG_ARCH_OMAP3 */ | ||
1270 | 1171 | ||
1271 | /* | 1172 | /* |
1272 | * McBSP1 and McBSP3 are directly mapped on 1610 and 1510. | 1173 | * McBSP1 and McBSP3 are directly mapped on 1610 and 1510. |
@@ -1316,7 +1217,7 @@ static int __devinit omap_mcbsp_probe(struct platform_device *pdev) | |||
1316 | } | 1217 | } |
1317 | } | 1218 | } |
1318 | mcbsp->phys_base = res->start; | 1219 | mcbsp->phys_base = res->start; |
1319 | omap_mcbsp_cache_size = resource_size(res); | 1220 | mcbsp->reg_cache_size = resource_size(res); |
1320 | mcbsp->io_base = ioremap(res->start, resource_size(res)); | 1221 | mcbsp->io_base = ioremap(res->start, resource_size(res)); |
1321 | if (!mcbsp->io_base) { | 1222 | if (!mcbsp->io_base) { |
1322 | ret = -ENOMEM; | 1223 | ret = -ENOMEM; |
@@ -1364,15 +1265,52 @@ static int __devinit omap_mcbsp_probe(struct platform_device *pdev) | |||
1364 | mcbsp->pdata = pdata; | 1265 | mcbsp->pdata = pdata; |
1365 | mcbsp->dev = &pdev->dev; | 1266 | mcbsp->dev = &pdev->dev; |
1366 | mcbsp_ptr[id] = mcbsp; | 1267 | mcbsp_ptr[id] = mcbsp; |
1367 | mcbsp->mcbsp_config_type = pdata->mcbsp_config_type; | ||
1368 | platform_set_drvdata(pdev, mcbsp); | 1268 | platform_set_drvdata(pdev, mcbsp); |
1369 | pm_runtime_enable(mcbsp->dev); | 1269 | pm_runtime_enable(mcbsp->dev); |
1370 | 1270 | ||
1371 | /* Initialize mcbsp properties for OMAP34XX if needed / applicable */ | 1271 | mcbsp->dma_op_mode = MCBSP_DMA_MODE_ELEMENT; |
1372 | omap34xx_device_init(mcbsp); | 1272 | if (mcbsp->pdata->buffer_size) { |
1273 | /* | ||
1274 | * Initially configure the maximum thresholds to a safe value. | ||
1275 | * The McBSP FIFO usage with these values should not go under | ||
1276 | * 16 locations. | ||
1277 | * If the whole FIFO without safety buffer is used, than there | ||
1278 | * is a possibility that the DMA will be not able to push the | ||
1279 | * new data on time, causing channel shifts in runtime. | ||
1280 | */ | ||
1281 | mcbsp->max_tx_thres = max_thres(mcbsp) - 0x10; | ||
1282 | mcbsp->max_rx_thres = max_thres(mcbsp) - 0x10; | ||
1283 | |||
1284 | ret = sysfs_create_group(&mcbsp->dev->kobj, | ||
1285 | &additional_attr_group); | ||
1286 | if (ret) { | ||
1287 | dev_err(mcbsp->dev, | ||
1288 | "Unable to create additional controls\n"); | ||
1289 | goto err_thres; | ||
1290 | } | ||
1291 | } else { | ||
1292 | mcbsp->max_tx_thres = -EINVAL; | ||
1293 | mcbsp->max_rx_thres = -EINVAL; | ||
1294 | } | ||
1295 | |||
1296 | res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "sidetone"); | ||
1297 | if (res) { | ||
1298 | ret = omap_st_add(mcbsp, res); | ||
1299 | if (ret) { | ||
1300 | dev_err(mcbsp->dev, | ||
1301 | "Unable to create sidetone controls\n"); | ||
1302 | goto err_st; | ||
1303 | } | ||
1304 | } | ||
1373 | 1305 | ||
1374 | return 0; | 1306 | return 0; |
1375 | 1307 | ||
1308 | err_st: | ||
1309 | if (mcbsp->pdata->buffer_size) | ||
1310 | sysfs_remove_group(&mcbsp->dev->kobj, | ||
1311 | &additional_attr_group); | ||
1312 | err_thres: | ||
1313 | clk_put(mcbsp->fclk); | ||
1376 | err_res: | 1314 | err_res: |
1377 | iounmap(mcbsp->io_base); | 1315 | iounmap(mcbsp->io_base); |
1378 | err_ioremap: | 1316 | err_ioremap: |
@@ -1392,7 +1330,12 @@ static int __devexit omap_mcbsp_remove(struct platform_device *pdev) | |||
1392 | mcbsp->pdata->ops->free) | 1330 | mcbsp->pdata->ops->free) |
1393 | mcbsp->pdata->ops->free(mcbsp->id); | 1331 | mcbsp->pdata->ops->free(mcbsp->id); |
1394 | 1332 | ||
1395 | omap34xx_device_exit(mcbsp); | 1333 | if (mcbsp->pdata->buffer_size) |
1334 | sysfs_remove_group(&mcbsp->dev->kobj, | ||
1335 | &additional_attr_group); | ||
1336 | |||
1337 | if (mcbsp->st_data) | ||
1338 | omap_st_remove(mcbsp); | ||
1396 | 1339 | ||
1397 | clk_put(mcbsp->fclk); | 1340 | clk_put(mcbsp->fclk); |
1398 | 1341 | ||