diff options
Diffstat (limited to 'arch/arm')
-rw-r--r-- | arch/arm/mach-omap2/mcbsp.c | 5 | ||||
-rw-r--r-- | arch/arm/mach-pxa/include/mach/audio.h | 3 | ||||
-rw-r--r-- | arch/arm/plat-omap/dma.c | 10 | ||||
-rw-r--r-- | arch/arm/plat-omap/include/mach/mcbsp.h | 51 | ||||
-rw-r--r-- | arch/arm/plat-omap/mcbsp.c | 401 | ||||
-rw-r--r-- | arch/arm/plat-s3c/include/plat/audio-simtec.h | 37 | ||||
-rw-r--r-- | arch/arm/plat-s3c/include/plat/regs-s3c2412-iis.h | 5 |
7 files changed, 491 insertions, 21 deletions
diff --git a/arch/arm/mach-omap2/mcbsp.c b/arch/arm/mach-omap2/mcbsp.c index 99b6e1546311..0447d26d454b 100644 --- a/arch/arm/mach-omap2/mcbsp.c +++ b/arch/arm/mach-omap2/mcbsp.c | |||
@@ -128,6 +128,7 @@ static struct omap_mcbsp_platform_data omap34xx_mcbsp_pdata[] = { | |||
128 | .rx_irq = INT_24XX_MCBSP1_IRQ_RX, | 128 | .rx_irq = INT_24XX_MCBSP1_IRQ_RX, |
129 | .tx_irq = INT_24XX_MCBSP1_IRQ_TX, | 129 | .tx_irq = INT_24XX_MCBSP1_IRQ_TX, |
130 | .ops = &omap2_mcbsp_ops, | 130 | .ops = &omap2_mcbsp_ops, |
131 | .buffer_size = 0x6F, | ||
131 | }, | 132 | }, |
132 | { | 133 | { |
133 | .phys_base = OMAP34XX_MCBSP2_BASE, | 134 | .phys_base = OMAP34XX_MCBSP2_BASE, |
@@ -136,6 +137,7 @@ static struct omap_mcbsp_platform_data omap34xx_mcbsp_pdata[] = { | |||
136 | .rx_irq = INT_24XX_MCBSP2_IRQ_RX, | 137 | .rx_irq = INT_24XX_MCBSP2_IRQ_RX, |
137 | .tx_irq = INT_24XX_MCBSP2_IRQ_TX, | 138 | .tx_irq = INT_24XX_MCBSP2_IRQ_TX, |
138 | .ops = &omap2_mcbsp_ops, | 139 | .ops = &omap2_mcbsp_ops, |
140 | .buffer_size = 0x3FF, | ||
139 | }, | 141 | }, |
140 | { | 142 | { |
141 | .phys_base = OMAP34XX_MCBSP3_BASE, | 143 | .phys_base = OMAP34XX_MCBSP3_BASE, |
@@ -144,6 +146,7 @@ static struct omap_mcbsp_platform_data omap34xx_mcbsp_pdata[] = { | |||
144 | .rx_irq = INT_24XX_MCBSP3_IRQ_RX, | 146 | .rx_irq = INT_24XX_MCBSP3_IRQ_RX, |
145 | .tx_irq = INT_24XX_MCBSP3_IRQ_TX, | 147 | .tx_irq = INT_24XX_MCBSP3_IRQ_TX, |
146 | .ops = &omap2_mcbsp_ops, | 148 | .ops = &omap2_mcbsp_ops, |
149 | .buffer_size = 0x6F, | ||
147 | }, | 150 | }, |
148 | { | 151 | { |
149 | .phys_base = OMAP34XX_MCBSP4_BASE, | 152 | .phys_base = OMAP34XX_MCBSP4_BASE, |
@@ -152,6 +155,7 @@ static struct omap_mcbsp_platform_data omap34xx_mcbsp_pdata[] = { | |||
152 | .rx_irq = INT_24XX_MCBSP4_IRQ_RX, | 155 | .rx_irq = INT_24XX_MCBSP4_IRQ_RX, |
153 | .tx_irq = INT_24XX_MCBSP4_IRQ_TX, | 156 | .tx_irq = INT_24XX_MCBSP4_IRQ_TX, |
154 | .ops = &omap2_mcbsp_ops, | 157 | .ops = &omap2_mcbsp_ops, |
158 | .buffer_size = 0x6F, | ||
155 | }, | 159 | }, |
156 | { | 160 | { |
157 | .phys_base = OMAP34XX_MCBSP5_BASE, | 161 | .phys_base = OMAP34XX_MCBSP5_BASE, |
@@ -160,6 +164,7 @@ static struct omap_mcbsp_platform_data omap34xx_mcbsp_pdata[] = { | |||
160 | .rx_irq = INT_24XX_MCBSP5_IRQ_RX, | 164 | .rx_irq = INT_24XX_MCBSP5_IRQ_RX, |
161 | .tx_irq = INT_24XX_MCBSP5_IRQ_TX, | 165 | .tx_irq = INT_24XX_MCBSP5_IRQ_TX, |
162 | .ops = &omap2_mcbsp_ops, | 166 | .ops = &omap2_mcbsp_ops, |
167 | .buffer_size = 0x6F, | ||
163 | }, | 168 | }, |
164 | }; | 169 | }; |
165 | #define OMAP34XX_MCBSP_PDATA_SZ ARRAY_SIZE(omap34xx_mcbsp_pdata) | 170 | #define OMAP34XX_MCBSP_PDATA_SZ ARRAY_SIZE(omap34xx_mcbsp_pdata) |
diff --git a/arch/arm/mach-pxa/include/mach/audio.h b/arch/arm/mach-pxa/include/mach/audio.h index 16eb02552d5d..a3449e35a6f5 100644 --- a/arch/arm/mach-pxa/include/mach/audio.h +++ b/arch/arm/mach-pxa/include/mach/audio.h | |||
@@ -3,10 +3,12 @@ | |||
3 | 3 | ||
4 | #include <sound/core.h> | 4 | #include <sound/core.h> |
5 | #include <sound/pcm.h> | 5 | #include <sound/pcm.h> |
6 | #include <sound/ac97_codec.h> | ||
6 | 7 | ||
7 | /* | 8 | /* |
8 | * @reset_gpio: AC97 reset gpio (normally gpio113 or gpio95) | 9 | * @reset_gpio: AC97 reset gpio (normally gpio113 or gpio95) |
9 | * a -1 value means no gpio will be used for reset | 10 | * a -1 value means no gpio will be used for reset |
11 | * @codec_pdata: AC97 codec platform_data | ||
10 | 12 | ||
11 | * reset_gpio should only be specified for pxa27x CPUs where a silicon | 13 | * reset_gpio should only be specified for pxa27x CPUs where a silicon |
12 | * bug prevents correct operation of the reset line. If not specified, | 14 | * bug prevents correct operation of the reset line. If not specified, |
@@ -20,6 +22,7 @@ typedef struct { | |||
20 | void (*resume)(void *); | 22 | void (*resume)(void *); |
21 | void *priv; | 23 | void *priv; |
22 | int reset_gpio; | 24 | int reset_gpio; |
25 | void *codec_pdata[AC97_BUS_MAX_DEVICES]; | ||
23 | } pxa2xx_audio_ops_t; | 26 | } pxa2xx_audio_ops_t; |
24 | 27 | ||
25 | extern void pxa_set_ac97_info(pxa2xx_audio_ops_t *ops); | 28 | extern void pxa_set_ac97_info(pxa2xx_audio_ops_t *ops); |
diff --git a/arch/arm/plat-omap/dma.c b/arch/arm/plat-omap/dma.c index e3ac94f09006..9b00f4cbc903 100644 --- a/arch/arm/plat-omap/dma.c +++ b/arch/arm/plat-omap/dma.c | |||
@@ -1127,6 +1127,11 @@ int omap_dma_running(void) | |||
1127 | void omap_dma_link_lch(int lch_head, int lch_queue) | 1127 | void omap_dma_link_lch(int lch_head, int lch_queue) |
1128 | { | 1128 | { |
1129 | if (omap_dma_in_1510_mode()) { | 1129 | if (omap_dma_in_1510_mode()) { |
1130 | if (lch_head == lch_queue) { | ||
1131 | dma_write(dma_read(CCR(lch_head)) | (3 << 8), | ||
1132 | CCR(lch_head)); | ||
1133 | return; | ||
1134 | } | ||
1130 | printk(KERN_ERR "DMA linking is not supported in 1510 mode\n"); | 1135 | printk(KERN_ERR "DMA linking is not supported in 1510 mode\n"); |
1131 | BUG(); | 1136 | BUG(); |
1132 | return; | 1137 | return; |
@@ -1149,6 +1154,11 @@ EXPORT_SYMBOL(omap_dma_link_lch); | |||
1149 | void omap_dma_unlink_lch(int lch_head, int lch_queue) | 1154 | void omap_dma_unlink_lch(int lch_head, int lch_queue) |
1150 | { | 1155 | { |
1151 | if (omap_dma_in_1510_mode()) { | 1156 | if (omap_dma_in_1510_mode()) { |
1157 | if (lch_head == lch_queue) { | ||
1158 | dma_write(dma_read(CCR(lch_head)) & ~(3 << 8), | ||
1159 | CCR(lch_head)); | ||
1160 | return; | ||
1161 | } | ||
1152 | printk(KERN_ERR "DMA linking is not supported in 1510 mode\n"); | 1162 | printk(KERN_ERR "DMA linking is not supported in 1510 mode\n"); |
1153 | BUG(); | 1163 | BUG(); |
1154 | return; | 1164 | return; |
diff --git a/arch/arm/plat-omap/include/mach/mcbsp.h b/arch/arm/plat-omap/include/mach/mcbsp.h index bb154ea76769..63a3f254af7b 100644 --- a/arch/arm/plat-omap/include/mach/mcbsp.h +++ b/arch/arm/plat-omap/include/mach/mcbsp.h | |||
@@ -134,6 +134,11 @@ | |||
134 | #define OMAP_MCBSP_REG_XCERG 0x74 | 134 | #define OMAP_MCBSP_REG_XCERG 0x74 |
135 | #define OMAP_MCBSP_REG_XCERH 0x78 | 135 | #define OMAP_MCBSP_REG_XCERH 0x78 |
136 | #define OMAP_MCBSP_REG_SYSCON 0x8C | 136 | #define OMAP_MCBSP_REG_SYSCON 0x8C |
137 | #define OMAP_MCBSP_REG_THRSH2 0x90 | ||
138 | #define OMAP_MCBSP_REG_THRSH1 0x94 | ||
139 | #define OMAP_MCBSP_REG_IRQST 0xA0 | ||
140 | #define OMAP_MCBSP_REG_IRQEN 0xA4 | ||
141 | #define OMAP_MCBSP_REG_WAKEUPEN 0xA8 | ||
137 | #define OMAP_MCBSP_REG_XCCR 0xAC | 142 | #define OMAP_MCBSP_REG_XCCR 0xAC |
138 | #define OMAP_MCBSP_REG_RCCR 0xB0 | 143 | #define OMAP_MCBSP_REG_RCCR 0xB0 |
139 | 144 | ||
@@ -249,8 +254,27 @@ | |||
249 | #define RDISABLE 0x0001 | 254 | #define RDISABLE 0x0001 |
250 | 255 | ||
251 | /********************** McBSP SYSCONFIG bit definitions ********************/ | 256 | /********************** McBSP SYSCONFIG bit definitions ********************/ |
257 | #define CLOCKACTIVITY(value) ((value)<<8) | ||
258 | #define SIDLEMODE(value) ((value)<<3) | ||
259 | #define ENAWAKEUP 0x0004 | ||
252 | #define SOFTRST 0x0002 | 260 | #define SOFTRST 0x0002 |
253 | 261 | ||
262 | /********************** McBSP DMA operating modes **************************/ | ||
263 | #define MCBSP_DMA_MODE_ELEMENT 0 | ||
264 | #define MCBSP_DMA_MODE_THRESHOLD 1 | ||
265 | #define MCBSP_DMA_MODE_FRAME 2 | ||
266 | |||
267 | /********************** McBSP WAKEUPEN bit definitions *********************/ | ||
268 | #define XEMPTYEOFEN 0x4000 | ||
269 | #define XRDYEN 0x0400 | ||
270 | #define XEOFEN 0x0200 | ||
271 | #define XFSXEN 0x0100 | ||
272 | #define XSYNCERREN 0x0080 | ||
273 | #define RRDYEN 0x0008 | ||
274 | #define REOFEN 0x0004 | ||
275 | #define RFSREN 0x0002 | ||
276 | #define RSYNCERREN 0x0001 | ||
277 | |||
254 | /* we don't do multichannel for now */ | 278 | /* we don't do multichannel for now */ |
255 | struct omap_mcbsp_reg_cfg { | 279 | struct omap_mcbsp_reg_cfg { |
256 | u16 spcr2; | 280 | u16 spcr2; |
@@ -344,6 +368,9 @@ struct omap_mcbsp_platform_data { | |||
344 | u8 dma_rx_sync, dma_tx_sync; | 368 | u8 dma_rx_sync, dma_tx_sync; |
345 | u16 rx_irq, tx_irq; | 369 | u16 rx_irq, tx_irq; |
346 | struct omap_mcbsp_ops *ops; | 370 | struct omap_mcbsp_ops *ops; |
371 | #ifdef CONFIG_ARCH_OMAP34XX | ||
372 | u16 buffer_size; | ||
373 | #endif | ||
347 | }; | 374 | }; |
348 | 375 | ||
349 | struct omap_mcbsp { | 376 | struct omap_mcbsp { |
@@ -377,6 +404,11 @@ struct omap_mcbsp { | |||
377 | struct omap_mcbsp_platform_data *pdata; | 404 | struct omap_mcbsp_platform_data *pdata; |
378 | struct clk *iclk; | 405 | struct clk *iclk; |
379 | struct clk *fclk; | 406 | struct clk *fclk; |
407 | #ifdef CONFIG_ARCH_OMAP34XX | ||
408 | int dma_op_mode; | ||
409 | u16 max_tx_thres; | ||
410 | u16 max_rx_thres; | ||
411 | #endif | ||
380 | }; | 412 | }; |
381 | extern struct omap_mcbsp **mcbsp_ptr; | 413 | extern struct omap_mcbsp **mcbsp_ptr; |
382 | extern int omap_mcbsp_count; | 414 | extern int omap_mcbsp_count; |
@@ -385,10 +417,25 @@ int omap_mcbsp_init(void); | |||
385 | void omap_mcbsp_register_board_cfg(struct omap_mcbsp_platform_data *config, | 417 | void omap_mcbsp_register_board_cfg(struct omap_mcbsp_platform_data *config, |
386 | int size); | 418 | int size); |
387 | void omap_mcbsp_config(unsigned int id, const struct omap_mcbsp_reg_cfg * config); | 419 | void omap_mcbsp_config(unsigned int id, const struct omap_mcbsp_reg_cfg * config); |
420 | #ifdef CONFIG_ARCH_OMAP34XX | ||
421 | void omap_mcbsp_set_tx_threshold(unsigned int id, u16 threshold); | ||
422 | void omap_mcbsp_set_rx_threshold(unsigned int id, u16 threshold); | ||
423 | u16 omap_mcbsp_get_max_tx_threshold(unsigned int id); | ||
424 | u16 omap_mcbsp_get_max_rx_threshold(unsigned int id); | ||
425 | int omap_mcbsp_get_dma_op_mode(unsigned int id); | ||
426 | #else | ||
427 | static inline void omap_mcbsp_set_tx_threshold(unsigned int id, u16 threshold) | ||
428 | { } | ||
429 | static inline void omap_mcbsp_set_rx_threshold(unsigned int id, u16 threshold) | ||
430 | { } | ||
431 | static inline u16 omap_mcbsp_get_max_tx_threshold(unsigned int id) { return 0; } | ||
432 | static inline u16 omap_mcbsp_get_max_rx_threshold(unsigned int id) { return 0; } | ||
433 | static inline int omap_mcbsp_get_dma_op_mode(unsigned int id) { return 0; } | ||
434 | #endif | ||
388 | int omap_mcbsp_request(unsigned int id); | 435 | int omap_mcbsp_request(unsigned int id); |
389 | void omap_mcbsp_free(unsigned int id); | 436 | void omap_mcbsp_free(unsigned int id); |
390 | void omap_mcbsp_start(unsigned int id); | 437 | void omap_mcbsp_start(unsigned int id, int tx, int rx); |
391 | void omap_mcbsp_stop(unsigned int id); | 438 | void omap_mcbsp_stop(unsigned int id, int tx, int rx); |
392 | void omap_mcbsp_xmit_word(unsigned int id, u32 word); | 439 | void omap_mcbsp_xmit_word(unsigned int id, u32 word); |
393 | u32 omap_mcbsp_recv_word(unsigned int id); | 440 | u32 omap_mcbsp_recv_word(unsigned int id); |
394 | 441 | ||
diff --git a/arch/arm/plat-omap/mcbsp.c b/arch/arm/plat-omap/mcbsp.c index efa0e0111f38..8dc7927906f1 100644 --- a/arch/arm/plat-omap/mcbsp.c +++ b/arch/arm/plat-omap/mcbsp.c | |||
@@ -198,6 +198,170 @@ void omap_mcbsp_config(unsigned int id, const struct omap_mcbsp_reg_cfg *config) | |||
198 | } | 198 | } |
199 | EXPORT_SYMBOL(omap_mcbsp_config); | 199 | EXPORT_SYMBOL(omap_mcbsp_config); |
200 | 200 | ||
201 | #ifdef CONFIG_ARCH_OMAP34XX | ||
202 | /* | ||
203 | * omap_mcbsp_set_tx_threshold configures how to deal | ||
204 | * with transmit threshold. the threshold value and handler can be | ||
205 | * configure in here. | ||
206 | */ | ||
207 | void omap_mcbsp_set_tx_threshold(unsigned int id, u16 threshold) | ||
208 | { | ||
209 | struct omap_mcbsp *mcbsp; | ||
210 | void __iomem *io_base; | ||
211 | |||
212 | if (!cpu_is_omap34xx()) | ||
213 | return; | ||
214 | |||
215 | if (!omap_mcbsp_check_valid_id(id)) { | ||
216 | printk(KERN_ERR "%s: Invalid id (%d)\n", __func__, id + 1); | ||
217 | return; | ||
218 | } | ||
219 | mcbsp = id_to_mcbsp_ptr(id); | ||
220 | io_base = mcbsp->io_base; | ||
221 | |||
222 | OMAP_MCBSP_WRITE(io_base, THRSH2, threshold); | ||
223 | } | ||
224 | EXPORT_SYMBOL(omap_mcbsp_set_tx_threshold); | ||
225 | |||
226 | /* | ||
227 | * omap_mcbsp_set_rx_threshold configures how to deal | ||
228 | * with receive threshold. the threshold value and handler can be | ||
229 | * configure in here. | ||
230 | */ | ||
231 | void omap_mcbsp_set_rx_threshold(unsigned int id, u16 threshold) | ||
232 | { | ||
233 | struct omap_mcbsp *mcbsp; | ||
234 | void __iomem *io_base; | ||
235 | |||
236 | if (!cpu_is_omap34xx()) | ||
237 | return; | ||
238 | |||
239 | if (!omap_mcbsp_check_valid_id(id)) { | ||
240 | printk(KERN_ERR "%s: Invalid id (%d)\n", __func__, id + 1); | ||
241 | return; | ||
242 | } | ||
243 | mcbsp = id_to_mcbsp_ptr(id); | ||
244 | io_base = mcbsp->io_base; | ||
245 | |||
246 | OMAP_MCBSP_WRITE(io_base, THRSH1, threshold); | ||
247 | } | ||
248 | EXPORT_SYMBOL(omap_mcbsp_set_rx_threshold); | ||
249 | |||
250 | /* | ||
251 | * omap_mcbsp_get_max_tx_thres just return the current configured | ||
252 | * maximum threshold for transmission | ||
253 | */ | ||
254 | u16 omap_mcbsp_get_max_tx_threshold(unsigned int id) | ||
255 | { | ||
256 | struct omap_mcbsp *mcbsp; | ||
257 | |||
258 | if (!omap_mcbsp_check_valid_id(id)) { | ||
259 | printk(KERN_ERR "%s: Invalid id (%d)\n", __func__, id + 1); | ||
260 | return -ENODEV; | ||
261 | } | ||
262 | mcbsp = id_to_mcbsp_ptr(id); | ||
263 | |||
264 | return mcbsp->max_tx_thres; | ||
265 | } | ||
266 | EXPORT_SYMBOL(omap_mcbsp_get_max_tx_threshold); | ||
267 | |||
268 | /* | ||
269 | * omap_mcbsp_get_max_rx_thres just return the current configured | ||
270 | * maximum threshold for reception | ||
271 | */ | ||
272 | u16 omap_mcbsp_get_max_rx_threshold(unsigned int id) | ||
273 | { | ||
274 | struct omap_mcbsp *mcbsp; | ||
275 | |||
276 | if (!omap_mcbsp_check_valid_id(id)) { | ||
277 | printk(KERN_ERR "%s: Invalid id (%d)\n", __func__, id + 1); | ||
278 | return -ENODEV; | ||
279 | } | ||
280 | mcbsp = id_to_mcbsp_ptr(id); | ||
281 | |||
282 | return mcbsp->max_rx_thres; | ||
283 | } | ||
284 | EXPORT_SYMBOL(omap_mcbsp_get_max_rx_threshold); | ||
285 | |||
286 | /* | ||
287 | * omap_mcbsp_get_dma_op_mode just return the current configured | ||
288 | * operating mode for the mcbsp channel | ||
289 | */ | ||
290 | int omap_mcbsp_get_dma_op_mode(unsigned int id) | ||
291 | { | ||
292 | struct omap_mcbsp *mcbsp; | ||
293 | int dma_op_mode; | ||
294 | |||
295 | if (!omap_mcbsp_check_valid_id(id)) { | ||
296 | printk(KERN_ERR "%s: Invalid id (%u)\n", __func__, id + 1); | ||
297 | return -ENODEV; | ||
298 | } | ||
299 | mcbsp = id_to_mcbsp_ptr(id); | ||
300 | |||
301 | spin_lock_irq(&mcbsp->lock); | ||
302 | dma_op_mode = mcbsp->dma_op_mode; | ||
303 | spin_unlock_irq(&mcbsp->lock); | ||
304 | |||
305 | return dma_op_mode; | ||
306 | } | ||
307 | EXPORT_SYMBOL(omap_mcbsp_get_dma_op_mode); | ||
308 | |||
309 | static inline void omap34xx_mcbsp_request(struct omap_mcbsp *mcbsp) | ||
310 | { | ||
311 | /* | ||
312 | * Enable wakup behavior, smart idle and all wakeups | ||
313 | * REVISIT: some wakeups may be unnecessary | ||
314 | */ | ||
315 | if (cpu_is_omap34xx()) { | ||
316 | u16 syscon; | ||
317 | |||
318 | syscon = OMAP_MCBSP_READ(mcbsp->io_base, SYSCON); | ||
319 | syscon &= ~(ENAWAKEUP | SIDLEMODE(0x03) | CLOCKACTIVITY(0x03)); | ||
320 | |||
321 | spin_lock_irq(&mcbsp->lock); | ||
322 | if (mcbsp->dma_op_mode == MCBSP_DMA_MODE_THRESHOLD) { | ||
323 | syscon |= (ENAWAKEUP | SIDLEMODE(0x02) | | ||
324 | CLOCKACTIVITY(0x02)); | ||
325 | OMAP_MCBSP_WRITE(mcbsp->io_base, WAKEUPEN, | ||
326 | XRDYEN | RRDYEN); | ||
327 | } else { | ||
328 | syscon |= SIDLEMODE(0x01); | ||
329 | } | ||
330 | spin_unlock_irq(&mcbsp->lock); | ||
331 | |||
332 | OMAP_MCBSP_WRITE(mcbsp->io_base, SYSCON, syscon); | ||
333 | } | ||
334 | } | ||
335 | |||
336 | static inline void omap34xx_mcbsp_free(struct omap_mcbsp *mcbsp) | ||
337 | { | ||
338 | /* | ||
339 | * Disable wakup behavior, smart idle and all wakeups | ||
340 | */ | ||
341 | if (cpu_is_omap34xx()) { | ||
342 | u16 syscon; | ||
343 | |||
344 | syscon = OMAP_MCBSP_READ(mcbsp->io_base, SYSCON); | ||
345 | syscon &= ~(ENAWAKEUP | SIDLEMODE(0x03) | CLOCKACTIVITY(0x03)); | ||
346 | /* | ||
347 | * HW bug workaround - If no_idle mode is taken, we need to | ||
348 | * go to smart_idle before going to always_idle, or the | ||
349 | * device will not hit retention anymore. | ||
350 | */ | ||
351 | syscon |= SIDLEMODE(0x02); | ||
352 | OMAP_MCBSP_WRITE(mcbsp->io_base, SYSCON, syscon); | ||
353 | |||
354 | syscon &= ~(SIDLEMODE(0x03)); | ||
355 | OMAP_MCBSP_WRITE(mcbsp->io_base, SYSCON, syscon); | ||
356 | |||
357 | OMAP_MCBSP_WRITE(mcbsp->io_base, WAKEUPEN, 0); | ||
358 | } | ||
359 | } | ||
360 | #else | ||
361 | static inline void omap34xx_mcbsp_request(struct omap_mcbsp *mcbsp) {} | ||
362 | static inline void omap34xx_mcbsp_free(struct omap_mcbsp *mcbsp) {} | ||
363 | #endif | ||
364 | |||
201 | /* | 365 | /* |
202 | * We can choose between IRQ based or polled IO. | 366 | * We can choose between IRQ based or polled IO. |
203 | * This needs to be called before omap_mcbsp_request(). | 367 | * This needs to be called before omap_mcbsp_request(). |
@@ -257,6 +421,9 @@ int omap_mcbsp_request(unsigned int id) | |||
257 | clk_enable(mcbsp->iclk); | 421 | clk_enable(mcbsp->iclk); |
258 | clk_enable(mcbsp->fclk); | 422 | clk_enable(mcbsp->fclk); |
259 | 423 | ||
424 | /* Do procedure specific to omap34xx arch, if applicable */ | ||
425 | omap34xx_mcbsp_request(mcbsp); | ||
426 | |||
260 | /* | 427 | /* |
261 | * Make sure that transmitter, receiver and sample-rate generator are | 428 | * Make sure that transmitter, receiver and sample-rate generator are |
262 | * not running before activating IRQs. | 429 | * not running before activating IRQs. |
@@ -305,6 +472,9 @@ void omap_mcbsp_free(unsigned int id) | |||
305 | if (mcbsp->pdata && mcbsp->pdata->ops && mcbsp->pdata->ops->free) | 472 | if (mcbsp->pdata && mcbsp->pdata->ops && mcbsp->pdata->ops->free) |
306 | mcbsp->pdata->ops->free(id); | 473 | mcbsp->pdata->ops->free(id); |
307 | 474 | ||
475 | /* Do procedure specific to omap34xx arch, if applicable */ | ||
476 | omap34xx_mcbsp_free(mcbsp); | ||
477 | |||
308 | clk_disable(mcbsp->fclk); | 478 | clk_disable(mcbsp->fclk); |
309 | clk_disable(mcbsp->iclk); | 479 | clk_disable(mcbsp->iclk); |
310 | 480 | ||
@@ -328,14 +498,15 @@ void omap_mcbsp_free(unsigned int id) | |||
328 | EXPORT_SYMBOL(omap_mcbsp_free); | 498 | EXPORT_SYMBOL(omap_mcbsp_free); |
329 | 499 | ||
330 | /* | 500 | /* |
331 | * Here we start the McBSP, by enabling the sample | 501 | * Here we start the McBSP, by enabling transmitter, receiver or both. |
332 | * generator, both transmitter and receivers, | 502 | * If no transmitter or receiver is active prior calling, then sample-rate |
333 | * and the frame sync. | 503 | * generator and frame sync are started. |
334 | */ | 504 | */ |
335 | void omap_mcbsp_start(unsigned int id) | 505 | void omap_mcbsp_start(unsigned int id, int tx, int rx) |
336 | { | 506 | { |
337 | struct omap_mcbsp *mcbsp; | 507 | struct omap_mcbsp *mcbsp; |
338 | void __iomem *io_base; | 508 | void __iomem *io_base; |
509 | int idle; | ||
339 | u16 w; | 510 | u16 w; |
340 | 511 | ||
341 | if (!omap_mcbsp_check_valid_id(id)) { | 512 | if (!omap_mcbsp_check_valid_id(id)) { |
@@ -348,32 +519,58 @@ void omap_mcbsp_start(unsigned int id) | |||
348 | mcbsp->rx_word_length = (OMAP_MCBSP_READ(io_base, RCR1) >> 5) & 0x7; | 519 | mcbsp->rx_word_length = (OMAP_MCBSP_READ(io_base, RCR1) >> 5) & 0x7; |
349 | mcbsp->tx_word_length = (OMAP_MCBSP_READ(io_base, XCR1) >> 5) & 0x7; | 520 | mcbsp->tx_word_length = (OMAP_MCBSP_READ(io_base, XCR1) >> 5) & 0x7; |
350 | 521 | ||
351 | /* Start the sample generator */ | 522 | idle = !((OMAP_MCBSP_READ(io_base, SPCR2) | |
352 | w = OMAP_MCBSP_READ(io_base, SPCR2); | 523 | OMAP_MCBSP_READ(io_base, SPCR1)) & 1); |
353 | OMAP_MCBSP_WRITE(io_base, SPCR2, w | (1 << 6)); | 524 | |
525 | if (idle) { | ||
526 | /* Start the sample generator */ | ||
527 | w = OMAP_MCBSP_READ(io_base, SPCR2); | ||
528 | OMAP_MCBSP_WRITE(io_base, SPCR2, w | (1 << 6)); | ||
529 | } | ||
354 | 530 | ||
355 | /* Enable transmitter and receiver */ | 531 | /* Enable transmitter and receiver */ |
532 | tx &= 1; | ||
356 | w = OMAP_MCBSP_READ(io_base, SPCR2); | 533 | w = OMAP_MCBSP_READ(io_base, SPCR2); |
357 | OMAP_MCBSP_WRITE(io_base, SPCR2, w | 1); | 534 | OMAP_MCBSP_WRITE(io_base, SPCR2, w | tx); |
358 | 535 | ||
536 | rx &= 1; | ||
359 | w = OMAP_MCBSP_READ(io_base, SPCR1); | 537 | w = OMAP_MCBSP_READ(io_base, SPCR1); |
360 | OMAP_MCBSP_WRITE(io_base, SPCR1, w | 1); | 538 | OMAP_MCBSP_WRITE(io_base, SPCR1, w | rx); |
361 | 539 | ||
362 | udelay(100); | 540 | /* |
541 | * Worst case: CLKSRG*2 = 8000khz: (1/8000) * 2 * 2 usec | ||
542 | * REVISIT: 100us may give enough time for two CLKSRG, however | ||
543 | * due to some unknown PM related, clock gating etc. reason it | ||
544 | * is now at 500us. | ||
545 | */ | ||
546 | udelay(500); | ||
363 | 547 | ||
364 | /* Start frame sync */ | 548 | if (idle) { |
365 | w = OMAP_MCBSP_READ(io_base, SPCR2); | 549 | /* Start frame sync */ |
366 | OMAP_MCBSP_WRITE(io_base, SPCR2, w | (1 << 7)); | 550 | w = OMAP_MCBSP_READ(io_base, SPCR2); |
551 | OMAP_MCBSP_WRITE(io_base, SPCR2, w | (1 << 7)); | ||
552 | } | ||
553 | |||
554 | if (cpu_is_omap2430() || cpu_is_omap34xx()) { | ||
555 | /* Release the transmitter and receiver */ | ||
556 | w = OMAP_MCBSP_READ(io_base, XCCR); | ||
557 | w &= ~(tx ? XDISABLE : 0); | ||
558 | OMAP_MCBSP_WRITE(io_base, XCCR, w); | ||
559 | w = OMAP_MCBSP_READ(io_base, RCCR); | ||
560 | w &= ~(rx ? RDISABLE : 0); | ||
561 | OMAP_MCBSP_WRITE(io_base, RCCR, w); | ||
562 | } | ||
367 | 563 | ||
368 | /* Dump McBSP Regs */ | 564 | /* Dump McBSP Regs */ |
369 | omap_mcbsp_dump_reg(id); | 565 | omap_mcbsp_dump_reg(id); |
370 | } | 566 | } |
371 | EXPORT_SYMBOL(omap_mcbsp_start); | 567 | EXPORT_SYMBOL(omap_mcbsp_start); |
372 | 568 | ||
373 | void omap_mcbsp_stop(unsigned int id) | 569 | void omap_mcbsp_stop(unsigned int id, int tx, int rx) |
374 | { | 570 | { |
375 | struct omap_mcbsp *mcbsp; | 571 | struct omap_mcbsp *mcbsp; |
376 | void __iomem *io_base; | 572 | void __iomem *io_base; |
573 | int idle; | ||
377 | u16 w; | 574 | u16 w; |
378 | 575 | ||
379 | if (!omap_mcbsp_check_valid_id(id)) { | 576 | if (!omap_mcbsp_check_valid_id(id)) { |
@@ -385,16 +582,33 @@ void omap_mcbsp_stop(unsigned int id) | |||
385 | io_base = mcbsp->io_base; | 582 | io_base = mcbsp->io_base; |
386 | 583 | ||
387 | /* Reset transmitter */ | 584 | /* Reset transmitter */ |
585 | tx &= 1; | ||
586 | if (cpu_is_omap2430() || cpu_is_omap34xx()) { | ||
587 | w = OMAP_MCBSP_READ(io_base, XCCR); | ||
588 | w |= (tx ? XDISABLE : 0); | ||
589 | OMAP_MCBSP_WRITE(io_base, XCCR, w); | ||
590 | } | ||
388 | w = OMAP_MCBSP_READ(io_base, SPCR2); | 591 | w = OMAP_MCBSP_READ(io_base, SPCR2); |
389 | OMAP_MCBSP_WRITE(io_base, SPCR2, w & ~(1)); | 592 | OMAP_MCBSP_WRITE(io_base, SPCR2, w & ~tx); |
390 | 593 | ||
391 | /* Reset receiver */ | 594 | /* Reset receiver */ |
595 | rx &= 1; | ||
596 | if (cpu_is_omap2430() || cpu_is_omap34xx()) { | ||
597 | w = OMAP_MCBSP_READ(io_base, RCCR); | ||
598 | w |= (tx ? RDISABLE : 0); | ||
599 | OMAP_MCBSP_WRITE(io_base, RCCR, w); | ||
600 | } | ||
392 | w = OMAP_MCBSP_READ(io_base, SPCR1); | 601 | w = OMAP_MCBSP_READ(io_base, SPCR1); |
393 | OMAP_MCBSP_WRITE(io_base, SPCR1, w & ~(1)); | 602 | OMAP_MCBSP_WRITE(io_base, SPCR1, w & ~rx); |
394 | 603 | ||
395 | /* Reset the sample rate generator */ | 604 | idle = !((OMAP_MCBSP_READ(io_base, SPCR2) | |
396 | w = OMAP_MCBSP_READ(io_base, SPCR2); | 605 | OMAP_MCBSP_READ(io_base, SPCR1)) & 1); |
397 | OMAP_MCBSP_WRITE(io_base, SPCR2, w & ~(1 << 6)); | 606 | |
607 | if (idle) { | ||
608 | /* Reset the sample rate generator */ | ||
609 | w = OMAP_MCBSP_READ(io_base, SPCR2); | ||
610 | OMAP_MCBSP_WRITE(io_base, SPCR2, w & ~(1 << 6)); | ||
611 | } | ||
398 | } | 612 | } |
399 | EXPORT_SYMBOL(omap_mcbsp_stop); | 613 | EXPORT_SYMBOL(omap_mcbsp_stop); |
400 | 614 | ||
@@ -883,6 +1097,149 @@ void omap_mcbsp_set_spi_mode(unsigned int id, | |||
883 | } | 1097 | } |
884 | EXPORT_SYMBOL(omap_mcbsp_set_spi_mode); | 1098 | EXPORT_SYMBOL(omap_mcbsp_set_spi_mode); |
885 | 1099 | ||
1100 | #ifdef CONFIG_ARCH_OMAP34XX | ||
1101 | #define max_thres(m) (mcbsp->pdata->buffer_size) | ||
1102 | #define valid_threshold(m, val) ((val) <= max_thres(m)) | ||
1103 | #define THRESHOLD_PROP_BUILDER(prop) \ | ||
1104 | static ssize_t prop##_show(struct device *dev, \ | ||
1105 | struct device_attribute *attr, char *buf) \ | ||
1106 | { \ | ||
1107 | struct omap_mcbsp *mcbsp = dev_get_drvdata(dev); \ | ||
1108 | \ | ||
1109 | return sprintf(buf, "%u\n", mcbsp->prop); \ | ||
1110 | } \ | ||
1111 | \ | ||
1112 | static ssize_t prop##_store(struct device *dev, \ | ||
1113 | struct device_attribute *attr, \ | ||
1114 | const char *buf, size_t size) \ | ||
1115 | { \ | ||
1116 | struct omap_mcbsp *mcbsp = dev_get_drvdata(dev); \ | ||
1117 | unsigned long val; \ | ||
1118 | int status; \ | ||
1119 | \ | ||
1120 | status = strict_strtoul(buf, 0, &val); \ | ||
1121 | if (status) \ | ||
1122 | return status; \ | ||
1123 | \ | ||
1124 | if (!valid_threshold(mcbsp, val)) \ | ||
1125 | return -EDOM; \ | ||
1126 | \ | ||
1127 | mcbsp->prop = val; \ | ||
1128 | return size; \ | ||
1129 | } \ | ||
1130 | \ | ||
1131 | static DEVICE_ATTR(prop, 0644, prop##_show, prop##_store); | ||
1132 | |||
1133 | THRESHOLD_PROP_BUILDER(max_tx_thres); | ||
1134 | THRESHOLD_PROP_BUILDER(max_rx_thres); | ||
1135 | |||
1136 | static const char *dma_op_modes[] = { | ||
1137 | "element", "threshold", "frame", | ||
1138 | }; | ||
1139 | |||
1140 | static ssize_t dma_op_mode_show(struct device *dev, | ||
1141 | struct device_attribute *attr, char *buf) | ||
1142 | { | ||
1143 | struct omap_mcbsp *mcbsp = dev_get_drvdata(dev); | ||
1144 | int dma_op_mode, i = 0; | ||
1145 | ssize_t len = 0; | ||
1146 | const char * const *s; | ||
1147 | |||
1148 | spin_lock_irq(&mcbsp->lock); | ||
1149 | dma_op_mode = mcbsp->dma_op_mode; | ||
1150 | spin_unlock_irq(&mcbsp->lock); | ||
1151 | |||
1152 | for (s = &dma_op_modes[i]; i < ARRAY_SIZE(dma_op_modes); s++, i++) { | ||
1153 | if (dma_op_mode == i) | ||
1154 | len += sprintf(buf + len, "[%s] ", *s); | ||
1155 | else | ||
1156 | len += sprintf(buf + len, "%s ", *s); | ||
1157 | } | ||
1158 | len += sprintf(buf + len, "\n"); | ||
1159 | |||
1160 | return len; | ||
1161 | } | ||
1162 | |||
1163 | static ssize_t dma_op_mode_store(struct device *dev, | ||
1164 | struct device_attribute *attr, | ||
1165 | const char *buf, size_t size) | ||
1166 | { | ||
1167 | struct omap_mcbsp *mcbsp = dev_get_drvdata(dev); | ||
1168 | const char * const *s; | ||
1169 | int i = 0; | ||
1170 | |||
1171 | for (s = &dma_op_modes[i]; i < ARRAY_SIZE(dma_op_modes); s++, i++) | ||
1172 | if (sysfs_streq(buf, *s)) | ||
1173 | break; | ||
1174 | |||
1175 | if (i == ARRAY_SIZE(dma_op_modes)) | ||
1176 | return -EINVAL; | ||
1177 | |||
1178 | spin_lock_irq(&mcbsp->lock); | ||
1179 | if (!mcbsp->free) { | ||
1180 | size = -EBUSY; | ||
1181 | goto unlock; | ||
1182 | } | ||
1183 | mcbsp->dma_op_mode = i; | ||
1184 | |||
1185 | unlock: | ||
1186 | spin_unlock_irq(&mcbsp->lock); | ||
1187 | |||
1188 | return size; | ||
1189 | } | ||
1190 | |||
1191 | static DEVICE_ATTR(dma_op_mode, 0644, dma_op_mode_show, dma_op_mode_store); | ||
1192 | |||
1193 | static const struct attribute *additional_attrs[] = { | ||
1194 | &dev_attr_max_tx_thres.attr, | ||
1195 | &dev_attr_max_rx_thres.attr, | ||
1196 | &dev_attr_dma_op_mode.attr, | ||
1197 | NULL, | ||
1198 | }; | ||
1199 | |||
1200 | static const struct attribute_group additional_attr_group = { | ||
1201 | .attrs = (struct attribute **)additional_attrs, | ||
1202 | }; | ||
1203 | |||
1204 | static inline int __devinit omap_additional_add(struct device *dev) | ||
1205 | { | ||
1206 | return sysfs_create_group(&dev->kobj, &additional_attr_group); | ||
1207 | } | ||
1208 | |||
1209 | static inline void __devexit omap_additional_remove(struct device *dev) | ||
1210 | { | ||
1211 | sysfs_remove_group(&dev->kobj, &additional_attr_group); | ||
1212 | } | ||
1213 | |||
1214 | static inline void __devinit omap34xx_device_init(struct omap_mcbsp *mcbsp) | ||
1215 | { | ||
1216 | mcbsp->dma_op_mode = MCBSP_DMA_MODE_ELEMENT; | ||
1217 | if (cpu_is_omap34xx()) { | ||
1218 | mcbsp->max_tx_thres = max_thres(mcbsp); | ||
1219 | mcbsp->max_rx_thres = max_thres(mcbsp); | ||
1220 | /* | ||
1221 | * REVISIT: Set dmap_op_mode to THRESHOLD as default | ||
1222 | * for mcbsp2 instances. | ||
1223 | */ | ||
1224 | if (omap_additional_add(mcbsp->dev)) | ||
1225 | dev_warn(mcbsp->dev, | ||
1226 | "Unable to create additional controls\n"); | ||
1227 | } else { | ||
1228 | mcbsp->max_tx_thres = -EINVAL; | ||
1229 | mcbsp->max_rx_thres = -EINVAL; | ||
1230 | } | ||
1231 | } | ||
1232 | |||
1233 | static inline void __devexit omap34xx_device_exit(struct omap_mcbsp *mcbsp) | ||
1234 | { | ||
1235 | if (cpu_is_omap34xx()) | ||
1236 | omap_additional_remove(mcbsp->dev); | ||
1237 | } | ||
1238 | #else | ||
1239 | static inline void __devinit omap34xx_device_init(struct omap_mcbsp *mcbsp) {} | ||
1240 | static inline void __devexit omap34xx_device_exit(struct omap_mcbsp *mcbsp) {} | ||
1241 | #endif /* CONFIG_ARCH_OMAP34XX */ | ||
1242 | |||
886 | /* | 1243 | /* |
887 | * McBSP1 and McBSP3 are directly mapped on 1610 and 1510. | 1244 | * McBSP1 and McBSP3 are directly mapped on 1610 and 1510. |
888 | * 730 has only 2 McBSP, and both of them are MPU peripherals. | 1245 | * 730 has only 2 McBSP, and both of them are MPU peripherals. |
@@ -953,6 +1310,10 @@ static int __devinit omap_mcbsp_probe(struct platform_device *pdev) | |||
953 | mcbsp->dev = &pdev->dev; | 1310 | mcbsp->dev = &pdev->dev; |
954 | mcbsp_ptr[id] = mcbsp; | 1311 | mcbsp_ptr[id] = mcbsp; |
955 | platform_set_drvdata(pdev, mcbsp); | 1312 | platform_set_drvdata(pdev, mcbsp); |
1313 | |||
1314 | /* Initialize mcbsp properties for OMAP34XX if needed / applicable */ | ||
1315 | omap34xx_device_init(mcbsp); | ||
1316 | |||
956 | return 0; | 1317 | return 0; |
957 | 1318 | ||
958 | err_fclk: | 1319 | err_fclk: |
@@ -976,6 +1337,8 @@ static int __devexit omap_mcbsp_remove(struct platform_device *pdev) | |||
976 | mcbsp->pdata->ops->free) | 1337 | mcbsp->pdata->ops->free) |
977 | mcbsp->pdata->ops->free(mcbsp->id); | 1338 | mcbsp->pdata->ops->free(mcbsp->id); |
978 | 1339 | ||
1340 | omap34xx_device_exit(mcbsp); | ||
1341 | |||
979 | clk_disable(mcbsp->fclk); | 1342 | clk_disable(mcbsp->fclk); |
980 | clk_disable(mcbsp->iclk); | 1343 | clk_disable(mcbsp->iclk); |
981 | clk_put(mcbsp->fclk); | 1344 | clk_put(mcbsp->fclk); |
diff --git a/arch/arm/plat-s3c/include/plat/audio-simtec.h b/arch/arm/plat-s3c/include/plat/audio-simtec.h new file mode 100644 index 000000000000..0f440b9168db --- /dev/null +++ b/arch/arm/plat-s3c/include/plat/audio-simtec.h | |||
@@ -0,0 +1,37 @@ | |||
1 | /* arch/arm/plat-s3c/include/plat/audio-simtec.h | ||
2 | * | ||
3 | * Copyright 2008 Simtec Electronics | ||
4 | * http://armlinux.simtec.co.uk/ | ||
5 | * Ben Dooks <ben@simtec.co.uk> | ||
6 | * | ||
7 | * This program is free software; you can redistribute it and/or modify | ||
8 | * it under the terms of the GNU General Public License version 2 as | ||
9 | * published by the Free Software Foundation. | ||
10 | * | ||
11 | * Simtec Audio support. | ||
12 | */ | ||
13 | |||
14 | /** | ||
15 | * struct s3c24xx_audio_simtec_pdata - platform data for simtec audio | ||
16 | * @use_mpllin: Select codec clock from MPLLin | ||
17 | * @output_cdclk: Need to output CDCLK to the codec | ||
18 | * @have_mic: Set if we have a MIC socket | ||
19 | * @have_lout: Set if we have a LineOut socket | ||
20 | * @amp_gpio: GPIO pin to enable the AMP | ||
21 | * @amp_gain: Option GPIO to control AMP gain | ||
22 | */ | ||
23 | struct s3c24xx_audio_simtec_pdata { | ||
24 | unsigned int use_mpllin:1; | ||
25 | unsigned int output_cdclk:1; | ||
26 | |||
27 | unsigned int have_mic:1; | ||
28 | unsigned int have_lout:1; | ||
29 | |||
30 | int amp_gpio; | ||
31 | int amp_gain[2]; | ||
32 | |||
33 | void (*startup)(void); | ||
34 | }; | ||
35 | |||
36 | extern int simtec_audio_add(const char *codec_name, | ||
37 | struct s3c24xx_audio_simtec_pdata *pdata); | ||
diff --git a/arch/arm/plat-s3c/include/plat/regs-s3c2412-iis.h b/arch/arm/plat-s3c/include/plat/regs-s3c2412-iis.h index 0fad7571030e..07659dad1748 100644 --- a/arch/arm/plat-s3c/include/plat/regs-s3c2412-iis.h +++ b/arch/arm/plat-s3c/include/plat/regs-s3c2412-iis.h | |||
@@ -33,6 +33,11 @@ | |||
33 | #define S3C2412_IISCON_RXDMA_ACTIVE (1 << 1) | 33 | #define S3C2412_IISCON_RXDMA_ACTIVE (1 << 1) |
34 | #define S3C2412_IISCON_IIS_ACTIVE (1 << 0) | 34 | #define S3C2412_IISCON_IIS_ACTIVE (1 << 0) |
35 | 35 | ||
36 | #define S3C64XX_IISMOD_BLC_16BIT (0 << 13) | ||
37 | #define S3C64XX_IISMOD_BLC_8BIT (1 << 13) | ||
38 | #define S3C64XX_IISMOD_BLC_24BIT (2 << 13) | ||
39 | #define S3C64XX_IISMOD_BLC_MASK (3 << 13) | ||
40 | |||
36 | #define S3C64XX_IISMOD_IMS_PCLK (0 << 10) | 41 | #define S3C64XX_IISMOD_IMS_PCLK (0 << 10) |
37 | #define S3C64XX_IISMOD_IMS_SYSMUX (1 << 10) | 42 | #define S3C64XX_IISMOD_IMS_SYSMUX (1 << 10) |
38 | 43 | ||