diff options
Diffstat (limited to 'firmware/target/arm')
-rw-r--r-- | firmware/target/arm/s5l8702/debug-s5l8702.c | 5 | ||||
-rw-r--r-- | firmware/target/arm/s5l8702/gpio-s5l8702.c | 39 | ||||
-rw-r--r-- | firmware/target/arm/s5l8702/ipod6g/audio-ipod6g.c | 32 | ||||
-rw-r--r-- | firmware/target/arm/s5l8702/pcm-s5l8702.c | 176 | ||||
-rw-r--r-- | firmware/target/arm/s5l8702/system-s5l8702.c | 2 |
5 files changed, 242 insertions, 12 deletions
diff --git a/firmware/target/arm/s5l8702/debug-s5l8702.c b/firmware/target/arm/s5l8702/debug-s5l8702.c index 74f765e447..c49737756c 100644 --- a/firmware/target/arm/s5l8702/debug-s5l8702.c +++ b/firmware/target/arm/s5l8702/debug-s5l8702.c | |||
@@ -39,6 +39,8 @@ | |||
39 | #define _DEBUG_PRINTF(a, varargs...) lcd_putsf(0, line++, (a), ##varargs); | 39 | #define _DEBUG_PRINTF(a, varargs...) lcd_putsf(0, line++, (a), ##varargs); |
40 | 40 | ||
41 | extern int lcd_type; | 41 | extern int lcd_type; |
42 | extern int rec_hw_ver; | ||
43 | |||
42 | bool dbg_hw_info(void) | 44 | bool dbg_hw_info(void) |
43 | { | 45 | { |
44 | int line; | 46 | int line; |
@@ -70,6 +72,9 @@ bool dbg_hw_info(void) | |||
70 | 72 | ||
71 | _DEBUG_PRINTF("LCD type: %d", lcd_type); | 73 | _DEBUG_PRINTF("LCD type: %d", lcd_type); |
72 | line++; | 74 | line++; |
75 | |||
76 | _DEBUG_PRINTF("capture HW: %d", rec_hw_ver); | ||
77 | line++; | ||
73 | } | 78 | } |
74 | else if(state==1) | 79 | else if(state==1) |
75 | { | 80 | { |
diff --git a/firmware/target/arm/s5l8702/gpio-s5l8702.c b/firmware/target/arm/s5l8702/gpio-s5l8702.c index d3ccb032bc..bd87005ad8 100644 --- a/firmware/target/arm/s5l8702/gpio-s5l8702.c +++ b/firmware/target/arm/s5l8702/gpio-s5l8702.c | |||
@@ -26,6 +26,40 @@ | |||
26 | #include "gpio-s5l8702.h" | 26 | #include "gpio-s5l8702.h" |
27 | #include "panic.h" | 27 | #include "panic.h" |
28 | 28 | ||
29 | int rec_hw_ver; | ||
30 | |||
31 | void INIT_ATTR gpio_init(void) | ||
32 | { | ||
33 | /* Capture hardware versions: | ||
34 | * | ||
35 | * HW version 1 includes an amplifier for the jack plug | ||
36 | * microphone, it is activated configuring GPIO E7 as output | ||
37 | * high. It is posible to detect capture HW version (even | ||
38 | * when HP are not plugged) reading GPIO E7: | ||
39 | * | ||
40 | * Ver GPIO E7 models capture support | ||
41 | * --- ------- ------ --------------- | ||
42 | * 0 1 80/160fat dock line-in | ||
43 | * 1 0 120/160slim dock line-in + jack mic | ||
44 | */ | ||
45 | GPIOCMD = 0xe0700; | ||
46 | rec_hw_ver = (PDAT(14) & (1 << 7)) ? 0 : 1; | ||
47 | |||
48 | /* default GPIO configuration */ | ||
49 | GPIOCMD = 0xe070e; | ||
50 | if (rec_hw_ver == 0) { | ||
51 | GPIOCMD = 0xe060e; | ||
52 | } | ||
53 | else { | ||
54 | /* GPIO E6 is connected to mikey IRQ line (active low), | ||
55 | configure it as pull-up input */ | ||
56 | GPIOCMD = 0xe0600; | ||
57 | PUNB(14) |= (1 << 6); | ||
58 | } | ||
59 | |||
60 | /* TODO: initialize GPIO ports for minimum power consumption */ | ||
61 | } | ||
62 | |||
29 | 63 | ||
30 | /* | 64 | /* |
31 | * XXX: disabled, not used and never tested! | 65 | * XXX: disabled, not used and never tested! |
@@ -47,11 +81,6 @@ static int n_handlers = 0; | |||
47 | 81 | ||
48 | 82 | ||
49 | /* API */ | 83 | /* API */ |
50 | void INIT_ATTR gpio_init(void) | ||
51 | { | ||
52 | /* TODO: initialize GPIO ports for minimum power consumption */ | ||
53 | } | ||
54 | |||
55 | uint32_t gpio_group_get(int group) | 84 | uint32_t gpio_group_get(int group) |
56 | { | 85 | { |
57 | uint32_t pcon = PCON(group); | 86 | uint32_t pcon = PCON(group); |
diff --git a/firmware/target/arm/s5l8702/ipod6g/audio-ipod6g.c b/firmware/target/arm/s5l8702/ipod6g/audio-ipod6g.c index 6ede3d0c30..6a3bab06d6 100644 --- a/firmware/target/arm/s5l8702/ipod6g/audio-ipod6g.c +++ b/firmware/target/arm/s5l8702/ipod6g/audio-ipod6g.c | |||
@@ -22,6 +22,9 @@ | |||
22 | #include "cpu.h" | 22 | #include "cpu.h" |
23 | #include "audio.h" | 23 | #include "audio.h" |
24 | #include "sound.h" | 24 | #include "sound.h" |
25 | #include "pmu-target.h" | ||
26 | |||
27 | extern int rec_hw_ver; | ||
25 | 28 | ||
26 | #if INPUT_SRC_CAPS != 0 | 29 | #if INPUT_SRC_CAPS != 0 |
27 | void audio_set_output_source(int source) | 30 | void audio_set_output_source(int source) |
@@ -46,13 +49,42 @@ void audio_input_mux(int source, unsigned flags) | |||
46 | { | 49 | { |
47 | audiohw_set_monitor(false); | 50 | audiohw_set_monitor(false); |
48 | audiohw_disable_recording(); | 51 | audiohw_disable_recording(); |
52 | |||
53 | /* Vcodec = 1800mV (900mV + value*100mV) */ | ||
54 | pmu_ldo_set_voltage(3, 0x9); | ||
55 | |||
56 | if (rec_hw_ver == 1) | ||
57 | GPIOCMD = 0xe070e; | ||
49 | } | 58 | } |
50 | #endif | 59 | #endif |
51 | break; | 60 | break; |
61 | |||
62 | #ifdef HAVE_MIC_REC | ||
63 | case AUDIO_SRC_MIC: /* recording only */ | ||
64 | if (source != last_source) | ||
65 | { | ||
66 | if (rec_hw_ver == 1) | ||
67 | GPIOCMD = 0xe070f; | ||
68 | |||
69 | /* Vcodec = 2400mV (900mV + value*100mV) */ | ||
70 | pmu_ldo_set_voltage(3, 0xf); | ||
71 | |||
72 | audiohw_set_monitor(false); | ||
73 | audiohw_enable_recording(true); /* source mic */ | ||
74 | } | ||
75 | break; | ||
76 | #endif | ||
77 | |||
52 | #ifdef HAVE_LINE_REC | 78 | #ifdef HAVE_LINE_REC |
53 | case AUDIO_SRC_LINEIN: /* recording only */ | 79 | case AUDIO_SRC_LINEIN: /* recording only */ |
54 | if (source != last_source) | 80 | if (source != last_source) |
55 | { | 81 | { |
82 | if (rec_hw_ver == 1) | ||
83 | GPIOCMD = 0xe070e; | ||
84 | |||
85 | /* Vcodec = 2400mV (900mV + value*100mV) */ | ||
86 | pmu_ldo_set_voltage(3, 0xf); | ||
87 | |||
56 | audiohw_set_monitor(false); | 88 | audiohw_set_monitor(false); |
57 | audiohw_enable_recording(false); /* source line */ | 89 | audiohw_enable_recording(false); /* source line */ |
58 | } | 90 | } |
diff --git a/firmware/target/arm/s5l8702/pcm-s5l8702.c b/firmware/target/arm/s5l8702/pcm-s5l8702.c index a4ea56edce..446be24008 100644 --- a/firmware/target/arm/s5l8702/pcm-s5l8702.c +++ b/firmware/target/arm/s5l8702/pcm-s5l8702.c | |||
@@ -250,37 +250,201 @@ void * pcm_dma_addr(void *addr) | |||
250 | ** Recording DMA transfer | 250 | ** Recording DMA transfer |
251 | **/ | 251 | **/ |
252 | #ifdef HAVE_RECORDING | 252 | #ifdef HAVE_RECORDING |
253 | static volatile int rec_locked = 0; | ||
254 | static void *rec_dma_addr; | ||
255 | static size_t rec_dma_size; | ||
256 | static bool pcm_rec_initialized = false; | ||
257 | static int completed_task; | ||
258 | |||
259 | /* ahead capture buffer */ | ||
260 | #define PCM_AHEADBUF_SAMPLES 128 | ||
261 | #define AHEADBUF_SZ (PCM_AHEADBUF_SAMPLES * 4) | ||
262 | static unsigned char ahead_buf[AHEADBUF_SZ] CACHEALIGN_ATTR; | ||
263 | |||
264 | /* DMA configuration */ | ||
265 | static void dma_rec_callback(void *cb_data) ICODE_ATTR; | ||
266 | |||
267 | enum { /* cb_data */ | ||
268 | TASK_AHEADBUF, | ||
269 | TASK_RECBUF | ||
270 | }; | ||
271 | |||
272 | #define DMA_REC_TSKBUF_SZ 2 /* N tasks, MUST be pow2 */ | ||
273 | #define DMA_REC_LLIBUF_SZ 8 /* N LLIs, MUST be pow2 */ | ||
274 | static struct dmac_tsk dma_rec_tskbuf[DMA_REC_TSKBUF_SZ]; | ||
275 | static struct dmac_lli volatile \ | ||
276 | dma_rec_llibuf[DMA_REC_LLIBUF_SZ] CACHEALIGN_ATTR; | ||
277 | |||
278 | static struct dmac_ch dma_rec_ch = { | ||
279 | .dmac = &s5l8702_dmac0, | ||
280 | .prio = DMAC_CH_PRIO(1), | ||
281 | .cb_fn = dma_rec_callback, | ||
282 | |||
283 | .llibuf = dma_rec_llibuf, | ||
284 | .llibuf_mask = DMA_REC_LLIBUF_SZ - 1, | ||
285 | .llibuf_bus = DMAC_MASTER_AHB1, | ||
286 | |||
287 | .tskbuf = dma_rec_tskbuf, | ||
288 | .tskbuf_mask = DMA_REC_TSKBUF_SZ - 1, | ||
289 | .queue_mode = QUEUE_LINK, | ||
290 | }; | ||
291 | |||
292 | static struct dmac_ch_cfg dma_rec_ch_cfg = { | ||
293 | .srcperi = S5L8702_DMAC0_PERI_IIS0_RX, | ||
294 | .dstperi = S5L8702_DMAC0_PERI_MEM, | ||
295 | .sbsize = DMACCxCONTROL_BSIZE_4, | ||
296 | .dbsize = DMACCxCONTROL_BSIZE_4, | ||
297 | .swidth = DMACCxCONTROL_WIDTH_16, | ||
298 | .dwidth = DMACCxCONTROL_WIDTH_16, | ||
299 | .sbus = DMAC_MASTER_AHB1, | ||
300 | .dbus = DMAC_MASTER_AHB1, | ||
301 | .sinc = DMACCxCONTROL_INC_DISABLE, | ||
302 | .dinc = DMACCxCONTROL_INC_ENABLE, | ||
303 | .prot = DMAC_PROT_CACH | DMAC_PROT_BUFF | DMAC_PROT_PRIV, | ||
304 | /* align LLI transfers to L-R pairs (samples) */ | ||
305 | .lli_xfer_max_count = DMAC_LLI_MAX_COUNT & ~1, | ||
306 | }; | ||
307 | |||
308 | /* maximum and minimum supported block sizes in bytes */ | ||
309 | #define MIN_SIZE ((size_t) (AHEADBUF_SZ * 2)) | ||
310 | #define MAX_SIZE ((size_t) (AHEADBUF_SZ + ((DMA_REC_LLIBUF_SZ - 1) * \ | ||
311 | (dma_rec_ch_cfg.lli_xfer_max_count << dma_rec_ch_cfg.swidth)))) | ||
312 | |||
313 | #if 0 | ||
314 | #define SIZE_PANIC(sz) { \ | ||
315 | if (((sz) < MIN_SIZE) || ((sz) > MAX_SIZE)) \ | ||
316 | panicf("pcm record: unsupported size: %d", (sz)); \ | ||
317 | } | ||
318 | #else | ||
319 | #define SIZE_PANIC(sz) {} | ||
320 | #endif | ||
321 | |||
322 | |||
323 | static void rec_dmac_ch_queue(void *addr, size_t size, int cb_data) | ||
324 | { | ||
325 | discard_dcache_range(addr, size); | ||
326 | dmac_ch_queue(&dma_rec_ch, (void*)S5L8702_DADDR_PERI_IIS0_RX, | ||
327 | addr, size, (void *)cb_data); | ||
328 | } | ||
329 | |||
330 | static void dma_rec_callback(void *cb_data) | ||
331 | { | ||
332 | completed_task = (int)cb_data; | ||
333 | |||
334 | if (completed_task == TASK_AHEADBUF) | ||
335 | { | ||
336 | /* safety check */ | ||
337 | if (rec_dma_addr == NULL) | ||
338 | return; /* capture finished */ | ||
339 | |||
340 | /* move ahead buffer to record buffer and queue | ||
341 | next capture-ahead task */ | ||
342 | memcpy(rec_dma_addr, ahead_buf, AHEADBUF_SZ); | ||
343 | rec_dmac_ch_queue(ahead_buf, AHEADBUF_SZ, TASK_AHEADBUF); | ||
344 | } | ||
345 | else /* TASK_RECBUF */ | ||
346 | { | ||
347 | /* Inform middle layer */ | ||
348 | if (pcm_rec_dma_complete_callback( | ||
349 | PCM_DMAST_OK, &rec_dma_addr, &rec_dma_size)) | ||
350 | { | ||
351 | SIZE_PANIC(rec_dma_size); | ||
352 | rec_dmac_ch_queue(rec_dma_addr + AHEADBUF_SZ, | ||
353 | rec_dma_size - AHEADBUF_SZ, TASK_RECBUF); | ||
354 | pcm_rec_dma_status_callback(PCM_DMAST_STARTED); | ||
355 | } | ||
356 | } | ||
357 | } | ||
358 | |||
253 | void pcm_rec_lock(void) | 359 | void pcm_rec_lock(void) |
254 | { | 360 | { |
361 | if ((rec_locked++ == 0) && pcm_rec_initialized) | ||
362 | dmac_ch_lock_int(&dma_rec_ch); | ||
255 | } | 363 | } |
256 | 364 | ||
257 | void pcm_rec_unlock(void) | 365 | void pcm_rec_unlock(void) |
258 | { | 366 | { |
367 | if ((--rec_locked == 0) && pcm_rec_initialized) | ||
368 | dmac_ch_unlock_int(&dma_rec_ch); | ||
259 | } | 369 | } |
260 | 370 | ||
261 | void pcm_rec_dma_stop(void) | 371 | void pcm_rec_dma_stop(void) |
262 | { | 372 | { |
373 | if (!pcm_rec_initialized) | ||
374 | return; | ||
375 | |||
376 | dmac_ch_stop(&dma_rec_ch); | ||
377 | |||
378 | I2SRXCOM = 0x2; /* stop Rx I2S */ | ||
263 | } | 379 | } |
264 | 380 | ||
265 | void pcm_rec_dma_start(void *addr, size_t size) | 381 | void pcm_rec_dma_start(void *addr, size_t size) |
266 | { | 382 | { |
267 | (void)addr; | 383 | SIZE_PANIC(size); |
268 | (void)size; | 384 | |
385 | pcm_rec_dma_stop(); | ||
386 | |||
387 | rec_dma_addr = addr; | ||
388 | rec_dma_size = size; | ||
389 | completed_task = -1; | ||
390 | |||
391 | /* launch first DMA transfer to capture into ahead buffer, | ||
392 | link the second task to capture into record buffer */ | ||
393 | rec_dmac_ch_queue(ahead_buf, AHEADBUF_SZ, TASK_AHEADBUF); | ||
394 | rec_dmac_ch_queue(addr + AHEADBUF_SZ, size - AHEADBUF_SZ, TASK_RECBUF); | ||
395 | |||
396 | I2SRXCOM = 0x6; /* start Rx I2S */ | ||
269 | } | 397 | } |
270 | 398 | ||
271 | void pcm_rec_dma_close(void) | 399 | void pcm_rec_dma_close(void) |
272 | { | 400 | { |
401 | pcm_rec_dma_stop(); | ||
273 | } | 402 | } |
274 | 403 | ||
275 | |||
276 | void pcm_rec_dma_init(void) | 404 | void pcm_rec_dma_init(void) |
277 | { | 405 | { |
278 | } | 406 | if (pcm_rec_initialized) |
407 | return; | ||
279 | 408 | ||
409 | PWRCON(0) &= ~(1 << 4); | ||
410 | PWRCON(0) &= ~(1 << 7); | ||
411 | |||
412 | dmac_ch_init(&dma_rec_ch, &dma_rec_ch_cfg); | ||
413 | |||
414 | /* synchronize lock status */ | ||
415 | if (rec_locked) | ||
416 | dmac_ch_lock_int(&dma_rec_ch); | ||
417 | |||
418 | I2SRXCON = 0x1000; | ||
419 | I2SCLKCON = 1; | ||
420 | |||
421 | pcm_rec_initialized = true; | ||
422 | } | ||
280 | 423 | ||
281 | const void * pcm_rec_dma_get_peak_buffer(void) | 424 | const void * pcm_rec_dma_get_peak_buffer(void) |
282 | { | 425 | { |
283 | return NULL; | 426 | void *dstaddr; |
284 | } | 427 | |
428 | pcm_rec_lock(); | ||
285 | 429 | ||
430 | if (completed_task == TASK_AHEADBUF) { | ||
431 | dstaddr = dmac_ch_get_info(&dma_rec_ch, NULL, NULL); | ||
432 | |||
433 | if ((dstaddr < rec_dma_addr) || | ||
434 | (dstaddr > rec_dma_addr + rec_dma_size)) | ||
435 | /* At this moment, interrupt for TASK_RECBUF is waiting to | ||
436 | be handled. TASK_RECBUF is already finished and HW is | ||
437 | transfering next TASK_AHEADBUF. Return whole block. */ | ||
438 | dstaddr = rec_dma_addr + rec_dma_size; | ||
439 | } | ||
440 | else { | ||
441 | /* Ahead buffer not yet captured _and_ moved to | ||
442 | record buffer. Return nothing. */ | ||
443 | dstaddr = rec_dma_addr; | ||
444 | } | ||
445 | |||
446 | pcm_rec_unlock(); | ||
447 | |||
448 | return CACHEALIGN_DOWN(dstaddr); | ||
449 | } | ||
286 | #endif /* HAVE_RECORDING */ | 450 | #endif /* HAVE_RECORDING */ |
diff --git a/firmware/target/arm/s5l8702/system-s5l8702.c b/firmware/target/arm/s5l8702/system-s5l8702.c index 6a06c29694..a9db7e1b8d 100644 --- a/firmware/target/arm/s5l8702/system-s5l8702.c +++ b/firmware/target/arm/s5l8702/system-s5l8702.c | |||
@@ -182,7 +182,7 @@ void fiq_dummy(void) | |||
182 | 182 | ||
183 | void system_init(void) | 183 | void system_init(void) |
184 | { | 184 | { |
185 | /*gpio_init();*/ | 185 | gpio_init(); |
186 | pmu_init(); | 186 | pmu_init(); |
187 | dma_init(); | 187 | dma_init(); |
188 | VIC0INTENABLE = 1 << IRQ_WHEEL; | 188 | VIC0INTENABLE = 1 << IRQ_WHEEL; |