diff options
Diffstat (limited to 'firmware/target')
19 files changed, 2013 insertions, 0 deletions
diff --git a/firmware/target/hosted/pcm-alsa.c b/firmware/target/hosted/pcm-alsa.c new file mode 100644 index 0000000000..928187993e --- /dev/null +++ b/firmware/target/hosted/pcm-alsa.c | |||
@@ -0,0 +1,518 @@ | |||
1 | /*************************************************************************** | ||
2 | * __________ __ ___. | ||
3 | * Open \______ \ ____ ____ | | _\_ |__ _______ ___ | ||
4 | * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ / | ||
5 | * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < < | ||
6 | * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \ | ||
7 | * \/ \/ \/ \/ \/ | ||
8 | * $Id$ | ||
9 | * | ||
10 | * Copyright (C) 2010 Thomas Martitz | ||
11 | * | ||
12 | * This program is free software; you can redistribute it and/or | ||
13 | * modify it under the terms of the GNU General Public License | ||
14 | * as published by the Free Software Foundation; either version 2 | ||
15 | * of the License, or (at your option) any later version. | ||
16 | * | ||
17 | * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY | ||
18 | * KIND, either express or implied. | ||
19 | * | ||
20 | ****************************************************************************/ | ||
21 | |||
22 | |||
23 | /* | ||
24 | * Based, but heavily modified, on the example given at | ||
25 | * http://www.alsa-project.org/alsa-doc/alsa-lib/_2test_2pcm_8c-example.html | ||
26 | * | ||
27 | * This driver uses the so-called unsafe async callback method and hardcoded device | ||
28 | * names. It fails when the audio device is busy by other apps. | ||
29 | * | ||
30 | * TODO: Rewrite this to do it properly with multithreading | ||
31 | * | ||
32 | * Alternatively, a version using polling in a tick task is provided. While | ||
33 | * supposedly safer, it appears to use more CPU (however I didn't measure it | ||
34 | * accurately, only looked at htop). At least, in this mode the "default" | ||
35 | * device works which doesnt break with other apps running. | ||
36 | * device works which doesnt break with other apps running. | ||
37 | */ | ||
38 | |||
39 | |||
40 | #include "autoconf.h" | ||
41 | |||
42 | #include <stdlib.h> | ||
43 | #include <stdbool.h> | ||
44 | #include <alsa/asoundlib.h> | ||
45 | #include "system.h" | ||
46 | #include "debug.h" | ||
47 | #include "kernel.h" | ||
48 | |||
49 | #include "pcm.h" | ||
50 | #include "pcm-internal.h" | ||
51 | #include "pcm_mixer.h" | ||
52 | #include "pcm_sampr.h" | ||
53 | |||
54 | #include <pthread.h> | ||
55 | #include <signal.h> | ||
56 | |||
57 | #define USE_ASYNC_CALLBACK | ||
58 | /* plughw:0,0 works with both, however "default" is recommended. | ||
59 | * default doesnt seem to work with async callback but doesn't break | ||
60 | * with multple applications running */ | ||
61 | static char device[] = "plughw:0,0"; /* playback device */ | ||
62 | static const snd_pcm_access_t access_ = SND_PCM_ACCESS_RW_INTERLEAVED; /* access mode */ | ||
63 | static const snd_pcm_format_t format = SND_PCM_FORMAT_S16; /* sample format */ | ||
64 | static const int channels = 2; /* count of channels */ | ||
65 | static unsigned int rate = 44100; /* stream rate */ | ||
66 | |||
67 | static snd_pcm_t *handle; | ||
68 | static snd_pcm_sframes_t buffer_size = MIX_FRAME_SAMPLES * 32; /* ~16k */ | ||
69 | static snd_pcm_sframes_t period_size = MIX_FRAME_SAMPLES * 4; /* ~4k */ | ||
70 | static short *frames; | ||
71 | |||
72 | static const char *pcm_data = 0; | ||
73 | static size_t pcm_size = 0; | ||
74 | |||
75 | #ifdef USE_ASYNC_CALLBACK | ||
76 | static snd_async_handler_t *ahandler; | ||
77 | static pthread_mutex_t pcm_mtx; | ||
78 | #else | ||
79 | static int recursion; | ||
80 | #endif | ||
81 | |||
82 | static int set_hwparams(snd_pcm_t *handle, unsigned sample_rate) | ||
83 | { | ||
84 | unsigned int rrate; | ||
85 | int err; | ||
86 | snd_pcm_hw_params_t *params; | ||
87 | snd_pcm_hw_params_alloca(¶ms); | ||
88 | |||
89 | |||
90 | /* choose all parameters */ | ||
91 | err = snd_pcm_hw_params_any(handle, params); | ||
92 | if (err < 0) | ||
93 | { | ||
94 | printf("Broken configuration for playback: no configurations available: %s\n", snd_strerror(err)); | ||
95 | return err; | ||
96 | } | ||
97 | /* set the interleaved read/write format */ | ||
98 | err = snd_pcm_hw_params_set_access(handle, params, access_); | ||
99 | if (err < 0) | ||
100 | { | ||
101 | printf("Access type not available for playback: %s\n", snd_strerror(err)); | ||
102 | return err; | ||
103 | } | ||
104 | /* set the sample format */ | ||
105 | err = snd_pcm_hw_params_set_format(handle, params, format); | ||
106 | if (err < 0) | ||
107 | { | ||
108 | printf("Sample format not available for playback: %s\n", snd_strerror(err)); | ||
109 | return err; | ||
110 | } | ||
111 | /* set the count of channels */ | ||
112 | err = snd_pcm_hw_params_set_channels(handle, params, channels); | ||
113 | if (err < 0) | ||
114 | { | ||
115 | printf("Channels count (%i) not available for playbacks: %s\n", channels, snd_strerror(err)); | ||
116 | return err; | ||
117 | } | ||
118 | /* set the stream rate */ | ||
119 | rrate = sample_rate; | ||
120 | err = snd_pcm_hw_params_set_rate_near(handle, params, &rrate, 0); | ||
121 | if (err < 0) | ||
122 | { | ||
123 | printf("Rate %iHz not available for playback: %s\n", rate, snd_strerror(err)); | ||
124 | return err; | ||
125 | } | ||
126 | if (rrate != sample_rate) | ||
127 | { | ||
128 | printf("Rate doesn't match (requested %iHz, get %iHz)\n", sample_rate, err); | ||
129 | return -EINVAL; | ||
130 | } | ||
131 | |||
132 | /* set the buffer size */ | ||
133 | err = snd_pcm_hw_params_set_buffer_size_near(handle, params, &buffer_size); | ||
134 | if (err < 0) | ||
135 | { | ||
136 | printf("Unable to set buffer size %i for playback: %s\n", buffer_size, snd_strerror(err)); | ||
137 | return err; | ||
138 | } | ||
139 | |||
140 | /* set the period size */ | ||
141 | err = snd_pcm_hw_params_set_period_size_near (handle, params, &period_size, NULL); | ||
142 | if (err < 0) | ||
143 | { | ||
144 | printf("Unable to set period size %i for playback: %s\n", period_size, snd_strerror(err)); | ||
145 | return err; | ||
146 | } | ||
147 | if (!frames) | ||
148 | frames = malloc(period_size * channels * sizeof(short)); | ||
149 | |||
150 | /* write the parameters to device */ | ||
151 | err = snd_pcm_hw_params(handle, params); | ||
152 | if (err < 0) | ||
153 | { | ||
154 | printf("Unable to set hw params for playback: %s\n", snd_strerror(err)); | ||
155 | return err; | ||
156 | } | ||
157 | return 0; | ||
158 | } | ||
159 | |||
160 | /* Set sw params: playback start threshold and low buffer watermark */ | ||
161 | static int set_swparams(snd_pcm_t *handle) | ||
162 | { | ||
163 | int err; | ||
164 | |||
165 | snd_pcm_sw_params_t *swparams; | ||
166 | snd_pcm_sw_params_alloca(&swparams); | ||
167 | |||
168 | /* get the current swparams */ | ||
169 | err = snd_pcm_sw_params_current(handle, swparams); | ||
170 | if (err < 0) | ||
171 | { | ||
172 | printf("Unable to determine current swparams for playback: %s\n", snd_strerror(err)); | ||
173 | return err; | ||
174 | } | ||
175 | /* start the transfer when the buffer is haalmost full */ | ||
176 | err = snd_pcm_sw_params_set_start_threshold(handle, swparams, buffer_size / 2); | ||
177 | if (err < 0) | ||
178 | { | ||
179 | printf("Unable to set start threshold mode for playback: %s\n", snd_strerror(err)); | ||
180 | return err; | ||
181 | } | ||
182 | /* allow the transfer when at least period_size samples can be processed */ | ||
183 | err = snd_pcm_sw_params_set_avail_min(handle, swparams, period_size); | ||
184 | if (err < 0) | ||
185 | { | ||
186 | printf("Unable to set avail min for playback: %s\n", snd_strerror(err)); | ||
187 | return err; | ||
188 | } | ||
189 | /* write the parameters to the playback device */ | ||
190 | err = snd_pcm_sw_params(handle, swparams); | ||
191 | if (err < 0) | ||
192 | { | ||
193 | printf("Unable to set sw params for playback: %s\n", snd_strerror(err)); | ||
194 | return err; | ||
195 | } | ||
196 | return 0; | ||
197 | } | ||
198 | |||
199 | /* copy pcm samples to a spare buffer, suitable for snd_pcm_writei() */ | ||
200 | static bool fill_frames(void) | ||
201 | { | ||
202 | ssize_t copy_n, frames_left = period_size; | ||
203 | bool new_buffer = false; | ||
204 | |||
205 | while (frames_left > 0) | ||
206 | { | ||
207 | if (!pcm_size) | ||
208 | { | ||
209 | new_buffer = true; | ||
210 | pcm_play_get_more_callback((void **)&pcm_data, &pcm_size); | ||
211 | if (!pcm_size || !pcm_data) | ||
212 | return false; | ||
213 | } | ||
214 | copy_n = MIN((ssize_t)pcm_size, frames_left*4); | ||
215 | memcpy(&frames[2*(period_size-frames_left)], pcm_data, copy_n); | ||
216 | |||
217 | pcm_data += copy_n; | ||
218 | pcm_size -= copy_n; | ||
219 | frames_left -= copy_n/4; | ||
220 | |||
221 | if (new_buffer) | ||
222 | { | ||
223 | new_buffer = false; | ||
224 | pcm_play_dma_started_callback(); | ||
225 | } | ||
226 | } | ||
227 | return true; | ||
228 | } | ||
229 | |||
230 | #ifdef USE_ASYNC_CALLBACK | ||
231 | static void async_callback(snd_async_handler_t *ahandler) | ||
232 | { | ||
233 | snd_pcm_t *handle = snd_async_handler_get_pcm(ahandler); | ||
234 | |||
235 | if (pthread_mutex_trylock(&pcm_mtx) != 0) | ||
236 | return; | ||
237 | #else | ||
238 | static void pcm_tick(void) | ||
239 | { | ||
240 | if (snd_pcm_state(handle) != SND_PCM_STATE_RUNNING) | ||
241 | return; | ||
242 | #endif | ||
243 | |||
244 | while (snd_pcm_avail_update(handle) >= period_size) | ||
245 | { | ||
246 | if (fill_frames()) | ||
247 | { | ||
248 | int err = snd_pcm_writei(handle, frames, period_size); | ||
249 | if (err < 0 && err != period_size && err != -EAGAIN) | ||
250 | { | ||
251 | printf("Write error: written %i expected %li\n", err, period_size); | ||
252 | break; | ||
253 | } | ||
254 | } | ||
255 | else | ||
256 | { | ||
257 | DEBUGF("%s: No Data.\n", __func__); | ||
258 | break; | ||
259 | } | ||
260 | } | ||
261 | #ifdef USE_ASYNC_CALLBACK | ||
262 | pthread_mutex_unlock(&pcm_mtx); | ||
263 | #endif | ||
264 | } | ||
265 | |||
266 | static int async_rw(snd_pcm_t *handle) | ||
267 | { | ||
268 | int err; | ||
269 | snd_pcm_sframes_t sample_size; | ||
270 | short *samples; | ||
271 | |||
272 | #ifdef USE_ASYNC_CALLBACK | ||
273 | err = snd_async_add_pcm_handler(&ahandler, handle, async_callback, NULL); | ||
274 | if (err < 0) | ||
275 | { | ||
276 | DEBUGF("Unable to register async handler: %s\n", snd_strerror(err)); | ||
277 | return err; | ||
278 | } | ||
279 | #endif | ||
280 | |||
281 | /* fill buffer with silence to initiate playback without noisy click */ | ||
282 | sample_size = buffer_size; | ||
283 | samples = malloc(sample_size * channels * sizeof(short)); | ||
284 | |||
285 | snd_pcm_format_set_silence(format, samples, sample_size); | ||
286 | err = snd_pcm_writei(handle, samples, sample_size); | ||
287 | free(samples); | ||
288 | |||
289 | if (err < 0) | ||
290 | { | ||
291 | DEBUGF("Initial write error: %s\n", snd_strerror(err)); | ||
292 | return err; | ||
293 | } | ||
294 | if (err != (ssize_t)sample_size) | ||
295 | { | ||
296 | DEBUGF("Initial write error: written %i expected %li\n", err, sample_size); | ||
297 | return err; | ||
298 | } | ||
299 | if (snd_pcm_state(handle) == SND_PCM_STATE_PREPARED) | ||
300 | { | ||
301 | err = snd_pcm_start(handle); | ||
302 | if (err < 0) | ||
303 | { | ||
304 | DEBUGF("Start error: %s\n", snd_strerror(err)); | ||
305 | return err; | ||
306 | } | ||
307 | } | ||
308 | return 0; | ||
309 | } | ||
310 | |||
311 | |||
312 | void cleanup(void) | ||
313 | { | ||
314 | free(frames); | ||
315 | frames = NULL; | ||
316 | snd_pcm_close(handle); | ||
317 | } | ||
318 | |||
319 | |||
320 | void pcm_play_dma_init(void) | ||
321 | { | ||
322 | int err; | ||
323 | |||
324 | |||
325 | if ((err = snd_pcm_open(&handle, device, SND_PCM_STREAM_PLAYBACK, 0)) < 0) | ||
326 | { | ||
327 | printf("%s(): Cannot open device %s: %s\n", __func__, device, snd_strerror(err)); | ||
328 | exit(EXIT_FAILURE); | ||
329 | return; | ||
330 | } | ||
331 | |||
332 | if ((err = snd_pcm_nonblock(handle, 1))) | ||
333 | printf("Could not set non-block mode: %s\n", snd_strerror(err)); | ||
334 | |||
335 | if ((err = set_hwparams(handle, rate)) < 0) | ||
336 | { | ||
337 | printf("Setting of hwparams failed: %s\n", snd_strerror(err)); | ||
338 | exit(EXIT_FAILURE); | ||
339 | } | ||
340 | if ((err = set_swparams(handle)) < 0) | ||
341 | { | ||
342 | printf("Setting of swparams failed: %s\n", snd_strerror(err)); | ||
343 | exit(EXIT_FAILURE); | ||
344 | } | ||
345 | |||
346 | #ifdef USE_ASYNC_CALLBACK | ||
347 | pthread_mutexattr_t attr; | ||
348 | pthread_mutexattr_init(&attr); | ||
349 | pthread_mutexattr_settype(&attr, PTHREAD_MUTEX_RECURSIVE); | ||
350 | pthread_mutex_init(&pcm_mtx, &attr); | ||
351 | #else | ||
352 | tick_add_task(pcm_tick); | ||
353 | #endif | ||
354 | |||
355 | |||
356 | atexit(cleanup); | ||
357 | return; | ||
358 | } | ||
359 | |||
360 | |||
361 | void pcm_play_lock(void) | ||
362 | { | ||
363 | #ifdef USE_ASYNC_CALLBACK | ||
364 | pthread_mutex_lock(&pcm_mtx); | ||
365 | #else | ||
366 | if (recursion++ == 0) | ||
367 | tick_remove_task(pcm_tick); | ||
368 | #endif | ||
369 | } | ||
370 | |||
371 | void pcm_play_unlock(void) | ||
372 | { | ||
373 | #ifdef USE_ASYNC_CALLBACK | ||
374 | pthread_mutex_unlock(&pcm_mtx); | ||
375 | #else | ||
376 | if (--recursion == 0) | ||
377 | tick_add_task(pcm_tick); | ||
378 | #endif | ||
379 | } | ||
380 | |||
381 | static void pcm_dma_apply_settings_nolock(void) | ||
382 | { | ||
383 | snd_pcm_drop(handle); | ||
384 | set_hwparams(handle, pcm_sampr); | ||
385 | } | ||
386 | |||
387 | void pcm_dma_apply_settings(void) | ||
388 | { | ||
389 | pcm_play_lock(); | ||
390 | pcm_dma_apply_settings_nolock(); | ||
391 | pcm_play_unlock(); | ||
392 | } | ||
393 | |||
394 | |||
395 | void pcm_play_dma_pause(bool pause) | ||
396 | { | ||
397 | snd_pcm_pause(handle, pause); | ||
398 | } | ||
399 | |||
400 | |||
401 | void pcm_play_dma_stop(void) | ||
402 | { | ||
403 | snd_pcm_drain(handle); | ||
404 | } | ||
405 | |||
406 | void pcm_play_dma_start(const void *addr, size_t size) | ||
407 | { | ||
408 | pcm_dma_apply_settings_nolock(); | ||
409 | |||
410 | pcm_data = addr; | ||
411 | pcm_size = size; | ||
412 | |||
413 | while (1) | ||
414 | { | ||
415 | snd_pcm_state_t state = snd_pcm_state(handle); | ||
416 | switch (state) | ||
417 | { | ||
418 | case SND_PCM_STATE_RUNNING: | ||
419 | return; | ||
420 | case SND_PCM_STATE_XRUN: | ||
421 | { | ||
422 | DEBUGF("Trying to recover from error\n"); | ||
423 | int err = snd_pcm_recover(handle, -EPIPE, 0); | ||
424 | if (err < 0) | ||
425 | DEBUGF("Recovery failed: %s\n", snd_strerror(err)); | ||
426 | continue; | ||
427 | } | ||
428 | case SND_PCM_STATE_SETUP: | ||
429 | { | ||
430 | int err = snd_pcm_prepare(handle); | ||
431 | if (err < 0) | ||
432 | printf("Prepare error: %s\n", snd_strerror(err)); | ||
433 | /* fall through */ | ||
434 | } | ||
435 | case SND_PCM_STATE_PREPARED: | ||
436 | { /* prepared state, we need to fill the buffer with silence before | ||
437 | * starting */ | ||
438 | int err = async_rw(handle); | ||
439 | if (err < 0) | ||
440 | printf("Start error: %s\n", snd_strerror(err)); | ||
441 | return; | ||
442 | } | ||
443 | case SND_PCM_STATE_PAUSED: | ||
444 | { /* paused, simply resume */ | ||
445 | pcm_play_dma_pause(0); | ||
446 | return; | ||
447 | } | ||
448 | case SND_PCM_STATE_DRAINING: | ||
449 | /* run until drained */ | ||
450 | continue; | ||
451 | default: | ||
452 | DEBUGF("Unhandled state: %s\n", snd_pcm_state_name(state)); | ||
453 | return; | ||
454 | } | ||
455 | } | ||
456 | } | ||
457 | |||
458 | size_t pcm_get_bytes_waiting(void) | ||
459 | { | ||
460 | return pcm_size; | ||
461 | } | ||
462 | |||
463 | const void * pcm_play_dma_get_peak_buffer(int *count) | ||
464 | { | ||
465 | uintptr_t addr = (uintptr_t)pcm_data; | ||
466 | *count = pcm_size / 4; | ||
467 | return (void *)((addr + 3) & ~3); | ||
468 | } | ||
469 | |||
470 | void pcm_play_dma_postinit(void) | ||
471 | { | ||
472 | } | ||
473 | |||
474 | |||
475 | void pcm_set_mixer_volume(int volume) | ||
476 | { | ||
477 | (void)volume; | ||
478 | } | ||
479 | #ifdef HAVE_RECORDING | ||
480 | void pcm_rec_lock(void) | ||
481 | { | ||
482 | } | ||
483 | |||
484 | void pcm_rec_unlock(void) | ||
485 | { | ||
486 | } | ||
487 | |||
488 | void pcm_rec_dma_init(void) | ||
489 | { | ||
490 | } | ||
491 | |||
492 | void pcm_rec_dma_close(void) | ||
493 | { | ||
494 | } | ||
495 | |||
496 | void pcm_rec_dma_start(void *start, size_t size) | ||
497 | { | ||
498 | (void)start; | ||
499 | (void)size; | ||
500 | } | ||
501 | |||
502 | void pcm_rec_dma_stop(void) | ||
503 | { | ||
504 | } | ||
505 | |||
506 | const void * pcm_rec_dma_get_peak_buffer(void) | ||
507 | { | ||
508 | return NULL; | ||
509 | } | ||
510 | |||
511 | void audiohw_set_recvol(int left, int right, int type) | ||
512 | { | ||
513 | (void)left; | ||
514 | (void)right; | ||
515 | (void)type; | ||
516 | } | ||
517 | |||
518 | #endif /* HAVE_RECORDING */ | ||
diff --git a/firmware/target/hosted/ypr0/adc-target.h b/firmware/target/hosted/ypr0/adc-target.h new file mode 100644 index 0000000000..bdbc4cfabd --- /dev/null +++ b/firmware/target/hosted/ypr0/adc-target.h | |||
@@ -0,0 +1,25 @@ | |||
1 | /*************************************************************************** | ||
2 | * __________ __ ___. | ||
3 | * Open \______ \ ____ ____ | | _\_ |__ _______ ___ | ||
4 | * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ / | ||
5 | * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < < | ||
6 | * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \ | ||
7 | * \/ \/ \/ \/ \/ | ||
8 | * $Id: adc-target.h 29516 2011-03-05 15:31:52Z thomasjfox $ | ||
9 | * | ||
10 | * Copyright (C) 2011 by Lorenzo Miori | ||
11 | * | ||
12 | * This program is free software; you can redistribute it and/or | ||
13 | * modify it under the terms of the GNU General Public License | ||
14 | * as published by the Free Software Foundation; either version 2 | ||
15 | * of the License, or (at your option) any later version. | ||
16 | * | ||
17 | * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY | ||
18 | * KIND, either express or implied. | ||
19 | * | ||
20 | ****************************************************************************/ | ||
21 | |||
22 | #ifndef __ADC_TARGET_H__ | ||
23 | #define __ADC_TARGET_H__ | ||
24 | |||
25 | #endif /* __ADC_TARGET_H__ */ | ||
diff --git a/firmware/target/hosted/ypr0/ascodec-target.h b/firmware/target/hosted/ypr0/ascodec-target.h new file mode 100644 index 0000000000..f4ecf20a1b --- /dev/null +++ b/firmware/target/hosted/ypr0/ascodec-target.h | |||
@@ -0,0 +1,92 @@ | |||
1 | /*************************************************************************** | ||
2 | * __________ __ ___. | ||
3 | * Open \______ \ ____ ____ | | _\_ |__ _______ ___ | ||
4 | * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ / | ||
5 | * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < < | ||
6 | * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \ | ||
7 | * \/ \/ \/ \/ \/ | ||
8 | * $Id: ascodec-target.h 26116 2010-05-17 20:53:25Z funman $ | ||
9 | * | ||
10 | * Module wrapper for AS3543 audio codec, using /dev/afe (afe.ko) of Samsung YP-R0 | ||
11 | * | ||
12 | * Copyright (c) 2011 Lorenzo Miori | ||
13 | * | ||
14 | * This program is free software; you can redistribute it and/or | ||
15 | * modify it under the terms of the GNU General Public License | ||
16 | * as published by the Free Software Foundation; either version 2 | ||
17 | * of the License, or (at your option) any later version. | ||
18 | * | ||
19 | * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY | ||
20 | * KIND, either express or implied. | ||
21 | * | ||
22 | ****************************************************************************/ | ||
23 | |||
24 | #ifndef _ASCODEC_TARGET_H | ||
25 | #define _ASCODEC_TARGET_H | ||
26 | |||
27 | #include "as3514.h" | ||
28 | #include "kernel.h" | ||
29 | #include "adc.h" | ||
30 | #include "ascodec.h" | ||
31 | |||
32 | /* ioctl parameter struct */ | ||
33 | |||
34 | struct codec_req_struct { | ||
35 | /* This works for every kind of afe.ko module requests */ | ||
36 | unsigned char reg; /* Main register address */ | ||
37 | unsigned char subreg; /* Set this only if you are reading/writing a PMU register*/ | ||
38 | unsigned char value; /* To be read if reading a register; to be set if writing to a register */ | ||
39 | }; | ||
40 | |||
41 | int ascodec_init(void); | ||
42 | void ascodec_close(void); | ||
43 | int ascodec_write(unsigned int reg, unsigned int value); | ||
44 | int ascodec_read(unsigned int reg); | ||
45 | void ascodec_write_pmu(unsigned int index, unsigned int subreg, unsigned int value); | ||
46 | int ascodec_read_pmu(unsigned int index, unsigned int subreg); | ||
47 | void ascodec_set(unsigned int reg, unsigned int bits); | ||
48 | void ascodec_clear(unsigned int reg, unsigned int bits); | ||
49 | void ascodec_write_masked(unsigned int reg, unsigned int bits, unsigned int mask); | ||
50 | int ascodec_readbytes(unsigned int index, unsigned int len, unsigned char *data); | ||
51 | unsigned short adc_read(int channel); | ||
52 | void ascodec_lock(void); | ||
53 | void ascodec_unlock(void); | ||
54 | |||
55 | static inline bool ascodec_chg_status(void) | ||
56 | { | ||
57 | return ascodec_read(AS3514_IRQ_ENRD0) & CHG_STATUS; | ||
58 | } | ||
59 | |||
60 | static inline bool ascodec_endofch(void) | ||
61 | { | ||
62 | return ascodec_read(AS3514_IRQ_ENRD0) & CHG_ENDOFCH; | ||
63 | } | ||
64 | |||
65 | static inline void ascodec_monitor_endofch(void) | ||
66 | { | ||
67 | ascodec_write(AS3514_IRQ_ENRD0, IRQ_ENDOFCH); | ||
68 | } | ||
69 | |||
70 | static inline void ascodec_wait_adc_finished(void) | ||
71 | { | ||
72 | /* | ||
73 | * FIXME: not implemented | ||
74 | * | ||
75 | * If irqs are not available on the target platform, | ||
76 | * this should be most likely implemented by polling | ||
77 | * AS3514_IRQ_ENRD2 in the same way powermgmt-ascodec.c | ||
78 | * is polling IRQ_ENDOFCH. | ||
79 | */ | ||
80 | } | ||
81 | |||
82 | static inline void ascodec_write_charger(int value) | ||
83 | { | ||
84 | ascodec_write_pmu(AS3543_CHARGER, 1, value); | ||
85 | } | ||
86 | |||
87 | static inline int ascodec_read_charger(void) | ||
88 | { | ||
89 | return ascodec_read_pmu(AS3543_CHARGER, 1); | ||
90 | } | ||
91 | |||
92 | #endif /* !_ASCODEC_TARGET_H */ | ||
diff --git a/firmware/target/hosted/ypr0/ascodec-ypr0.c b/firmware/target/hosted/ypr0/ascodec-ypr0.c new file mode 100644 index 0000000000..a4e92e6f6b --- /dev/null +++ b/firmware/target/hosted/ypr0/ascodec-ypr0.c | |||
@@ -0,0 +1,206 @@ | |||
1 | /*************************************************************************** | ||
2 | * __________ __ ___. | ||
3 | * Open \______ \ ____ ____ | | _\_ |__ _______ ___ | ||
4 | * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ / | ||
5 | * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < < | ||
6 | * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \ | ||
7 | * \/ \/ \/ \/ \/ | ||
8 | * $Id: ascodec-target.h 26116 2010-05-17 20:53:25Z funman $ | ||
9 | * | ||
10 | * Module wrapper for AS3543 audio codec, using /dev/afe (afe.ko) of Samsung YP-R0 | ||
11 | * | ||
12 | * Copyright (c) 2011 Lorenzo Miori | ||
13 | * | ||
14 | * This program is free software; you can redistribute it and/or | ||
15 | * modify it under the terms of the GNU General Public License | ||
16 | * as published by the Free Software Foundation; either version 2 | ||
17 | * of the License, or (at your option) any later version. | ||
18 | * | ||
19 | * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY | ||
20 | * KIND, either express or implied. | ||
21 | * | ||
22 | ****************************************************************************/ | ||
23 | |||
24 | #include "fcntl.h" | ||
25 | #include "unistd.h" | ||
26 | #include "stdio.h" | ||
27 | #include "string.h" | ||
28 | #include "sys/ioctl.h" | ||
29 | #include "stdlib.h" | ||
30 | |||
31 | #include "ascodec-target.h" | ||
32 | |||
33 | int afe_dev = -1; | ||
34 | |||
35 | /* Write to a normal register */ | ||
36 | #define IOCTL_REG_WRITE 0x40034101 | ||
37 | /* Write to a PMU register */ | ||
38 | #define IOCTL_SUBREG_WRITE 0x40034103 | ||
39 | /* Read from a normal register */ | ||
40 | #define IOCTL_REG_READ 0x80034102 | ||
41 | /* Read from a PMU register */ | ||
42 | #define IOCTL_SUBREG_READ 0x80034103 | ||
43 | |||
44 | static struct mutex as_mtx; | ||
45 | |||
46 | int ascodec_init(void) { | ||
47 | |||
48 | afe_dev = open("/dev/afe", O_RDWR); | ||
49 | |||
50 | mutex_init(&as_mtx); | ||
51 | |||
52 | return afe_dev; | ||
53 | |||
54 | } | ||
55 | |||
56 | void ascodec_close(void) { | ||
57 | |||
58 | if (afe_dev >= 0) { | ||
59 | close(afe_dev); | ||
60 | } | ||
61 | |||
62 | } | ||
63 | |||
64 | /* Read functions returns -1 if fail, otherwise the register's value if success */ | ||
65 | /* Write functions return >= 0 if success, otherwise -1 if fail */ | ||
66 | |||
67 | int ascodec_write(unsigned int reg, unsigned int value) | ||
68 | { | ||
69 | struct codec_req_struct y; | ||
70 | struct codec_req_struct *p; | ||
71 | p = &y; | ||
72 | p->reg = reg; | ||
73 | p->value = value; | ||
74 | return ioctl(afe_dev, IOCTL_REG_WRITE, p); | ||
75 | } | ||
76 | |||
77 | int ascodec_read(unsigned int reg) | ||
78 | { | ||
79 | int retval = -1; | ||
80 | struct codec_req_struct y; | ||
81 | struct codec_req_struct *p; | ||
82 | p = &y; | ||
83 | p->reg = reg; | ||
84 | retval = ioctl(afe_dev, IOCTL_REG_READ, p); | ||
85 | if (retval >= 0) | ||
86 | return p->value; | ||
87 | else | ||
88 | return retval; | ||
89 | } | ||
90 | |||
91 | void ascodec_write_pmu(unsigned int index, unsigned int subreg, | ||
92 | unsigned int value) | ||
93 | { | ||
94 | struct codec_req_struct y; | ||
95 | struct codec_req_struct *p; | ||
96 | p = &y; | ||
97 | p->reg = index; | ||
98 | p->subreg = subreg; | ||
99 | p->value = value; | ||
100 | ioctl(afe_dev, IOCTL_SUBREG_WRITE, p); | ||
101 | } | ||
102 | |||
103 | int ascodec_read_pmu(unsigned int index, unsigned int subreg) | ||
104 | { | ||
105 | int retval = -1; | ||
106 | struct codec_req_struct y; | ||
107 | struct codec_req_struct *p; | ||
108 | p = &y; | ||
109 | p->reg = index; | ||
110 | p->subreg = subreg; | ||
111 | retval = ioctl(afe_dev, IOCTL_SUBREG_READ, p); | ||
112 | if (retval >= 0) | ||
113 | return p->value; | ||
114 | else | ||
115 | return retval; | ||
116 | } | ||
117 | |||
118 | /* Helpers to set/clear bits */ | ||
119 | void ascodec_set(unsigned int reg, unsigned int bits) | ||
120 | { | ||
121 | ascodec_write(reg, ascodec_read(reg) | bits); | ||
122 | } | ||
123 | |||
124 | void ascodec_clear(unsigned int reg, unsigned int bits) | ||
125 | { | ||
126 | ascodec_write(reg, ascodec_read(reg) & ~bits); | ||
127 | } | ||
128 | |||
129 | void ascodec_write_masked(unsigned int reg, unsigned int bits, | ||
130 | unsigned int mask) | ||
131 | { | ||
132 | ascodec_write(reg, (ascodec_read(reg) & ~mask) | (bits & mask)); | ||
133 | } | ||
134 | |||
135 | /*FIXME: doesn't work */ | ||
136 | int ascodec_readbytes(unsigned int index, unsigned int len, unsigned char *data) | ||
137 | { | ||
138 | unsigned int i; | ||
139 | |||
140 | for (i=index; i<len; i++) { | ||
141 | data[i] = ascodec_read(i); | ||
142 | printf("Register %i: value=%i\n",index,data[i]); | ||
143 | } | ||
144 | |||
145 | printf("TOTAL: %i\n", i); | ||
146 | |||
147 | return i; | ||
148 | } | ||
149 | |||
150 | /* | ||
151 | * NOTE: | ||
152 | * After the conversion to interrupts, ascodec_(lock|unlock) are only used by | ||
153 | * adc-as3514.c to protect against other threads corrupting the result by using | ||
154 | * the ADC at the same time. | ||
155 | * | ||
156 | * Concurrent ascodec_(async_)?(read|write) calls are instead protected | ||
157 | * by the R0's Kernel I2C driver for ascodec (mutexed), so it's automatically safe | ||
158 | */ | ||
159 | |||
160 | void ascodec_lock(void) | ||
161 | { | ||
162 | mutex_lock(&as_mtx); | ||
163 | } | ||
164 | |||
165 | void ascodec_unlock(void) | ||
166 | { | ||
167 | mutex_unlock(&as_mtx); | ||
168 | } | ||
169 | |||
170 | /* Read 10-bit channel data */ | ||
171 | unsigned short adc_read(int channel) | ||
172 | { | ||
173 | unsigned short data = 0; | ||
174 | |||
175 | if ((unsigned)channel >= NUM_ADC_CHANNELS) | ||
176 | return 0; | ||
177 | |||
178 | ascodec_lock(); | ||
179 | |||
180 | /* Select channel */ | ||
181 | ascodec_write(AS3514_ADC_0, (channel << 4)); | ||
182 | unsigned char buf[2]; | ||
183 | |||
184 | /* | ||
185 | * The AS3514 ADC will trigger an interrupt when the conversion | ||
186 | * is finished, if the corresponding enable bit in IRQ_ENRD2 | ||
187 | * is set. | ||
188 | * Previously the code did not wait and this apparently did | ||
189 | * not pose any problems, but this should be more correct. | ||
190 | * Without the wait the data read back may be completely or | ||
191 | * partially (first one of the two bytes) stale. | ||
192 | */ | ||
193 | /*FIXME: not implemented*/ | ||
194 | ascodec_wait_adc_finished(); | ||
195 | |||
196 | /* Read data */ | ||
197 | ascodec_readbytes(AS3514_ADC_0, 2, buf); | ||
198 | data = (((buf[0] & 0x3) << 8) | buf[1]); | ||
199 | |||
200 | ascodec_unlock(); | ||
201 | return data; | ||
202 | } | ||
203 | |||
204 | void adc_init(void) | ||
205 | { | ||
206 | } | ||
diff --git a/firmware/target/hosted/ypr0/backlight-target.h b/firmware/target/hosted/ypr0/backlight-target.h new file mode 100644 index 0000000000..561e159e8c --- /dev/null +++ b/firmware/target/hosted/ypr0/backlight-target.h | |||
@@ -0,0 +1,29 @@ | |||
1 | /*************************************************************************** | ||
2 | * __________ __ ___. | ||
3 | * Open \______ \ ____ ____ | | _\_ |__ _______ ___ | ||
4 | * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ / | ||
5 | * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < < | ||
6 | * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \ | ||
7 | * \/ \/ \/ \/ \/ | ||
8 | * $Id: backlight-target.h 19322 2008-12-04 04:16:53Z jethead71 $ | ||
9 | * | ||
10 | * Copyright (C) 2011 by Lorenzo Miori | ||
11 | * | ||
12 | * This program is free software; you can redistribute it and/or | ||
13 | * modify it under the terms of the GNU General Public License | ||
14 | * as published by the Free Software Foundation; either version 2 | ||
15 | * of the License, or (at your option) any later version. | ||
16 | * | ||
17 | * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY | ||
18 | * KIND, either express or implied. | ||
19 | * | ||
20 | ****************************************************************************/ | ||
21 | #ifndef BACKLIGHT_TARGET_H | ||
22 | #define BACKLIGHT_TARGET_H | ||
23 | |||
24 | bool _backlight_init(void); | ||
25 | void _backlight_on(void); | ||
26 | void _backlight_off(void); | ||
27 | void _backlight_set_brightness(int brightness); | ||
28 | |||
29 | #endif /* BACKLIGHT_TARGET_H */ | ||
diff --git a/firmware/target/hosted/ypr0/backlight-ypr0.c b/firmware/target/hosted/ypr0/backlight-ypr0.c new file mode 100644 index 0000000000..930b56be2e --- /dev/null +++ b/firmware/target/hosted/ypr0/backlight-ypr0.c | |||
@@ -0,0 +1,89 @@ | |||
1 | /*************************************************************************** | ||
2 | * __________ __ ___. | ||
3 | * Open \______ \ ____ ____ | | _\_ |__ _______ ___ | ||
4 | * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ / | ||
5 | * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < < | ||
6 | * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \ | ||
7 | * \/ \/ \/ \/ \/ | ||
8 | * $Id: backlight-gigabeat-s.c 25800 2010-05-04 10:07:53Z jethead71 $ | ||
9 | * | ||
10 | * Copyright (C) 2011 by Lorenzo Miori | ||
11 | * | ||
12 | * This program is free software; you can redistribute it and/or | ||
13 | * modify it under the terms of the GNU General Public License | ||
14 | * as published by the Free Software Foundation; either version 2 | ||
15 | * of the License, or (at your option) any later version. | ||
16 | * | ||
17 | * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY | ||
18 | * KIND, either express or implied. | ||
19 | * | ||
20 | ****************************************************************************/ | ||
21 | #include "config.h" | ||
22 | #include "system.h" | ||
23 | #include "backlight.h" | ||
24 | #include "backlight-target.h" | ||
25 | #include "lcd.h" | ||
26 | #include "as3514.h" | ||
27 | #include "ascodec-target.h" | ||
28 | #include <fcntl.h> | ||
29 | #include "unistd.h" | ||
30 | |||
31 | static bool backlight_on_status = true; /* Is on or off? */ | ||
32 | |||
33 | /*TODO: see if LCD sleep could be implemented in a better way -> ie using a rockbox feature */ | ||
34 | /* Turn off LCD power supply */ | ||
35 | static void _backlight_lcd_sleep(void) | ||
36 | { | ||
37 | int fp = open("/sys/class/graphics/fb0/blank", O_RDWR); | ||
38 | write(fp, "1", 1); | ||
39 | close(fp); | ||
40 | } | ||
41 | /* Turn on LCD screen */ | ||
42 | static void _backlight_lcd_power(void) | ||
43 | { | ||
44 | int fp = open("/sys/class/graphics/fb0/blank", O_RDWR); | ||
45 | write(fp, "0", 1); | ||
46 | close(fp); | ||
47 | } | ||
48 | |||
49 | bool _backlight_init(void) | ||
50 | { | ||
51 | /* We have nothing to do */ | ||
52 | return true; | ||
53 | } | ||
54 | |||
55 | void _backlight_on(void) | ||
56 | { | ||
57 | if (!backlight_on_status) | ||
58 | { | ||
59 | /* Turn on lcd power before backlight */ | ||
60 | _backlight_lcd_power(); | ||
61 | /* Original app sets this to 0xb1 when backlight is on... */ | ||
62 | ascodec_write_pmu(AS3543_BACKLIGHT, 0x1, 0xb1); | ||
63 | } | ||
64 | |||
65 | backlight_on_status = true; | ||
66 | |||
67 | } | ||
68 | |||
69 | void _backlight_off(void) | ||
70 | { | ||
71 | if (backlight_on_status) { | ||
72 | /* Disabling the DCDC15 completely, keeps brightness register value */ | ||
73 | ascodec_write_pmu(AS3543_BACKLIGHT, 0x1, 0x00); | ||
74 | /* Turn off lcd power then */ | ||
75 | _backlight_lcd_sleep(); | ||
76 | } | ||
77 | |||
78 | backlight_on_status = false; | ||
79 | } | ||
80 | |||
81 | void _backlight_set_brightness(int brightness) | ||
82 | { | ||
83 | /* Just another check... */ | ||
84 | if (brightness > MAX_BRIGHTNESS_SETTING) | ||
85 | brightness = MAX_BRIGHTNESS_SETTING; | ||
86 | if (brightness < MIN_BRIGHTNESS_SETTING) | ||
87 | brightness = MIN_BRIGHTNESS_SETTING; | ||
88 | ascodec_write_pmu(AS3543_BACKLIGHT, 0x3, brightness << 3 & 0xf8); | ||
89 | } | ||
diff --git a/firmware/target/hosted/ypr0/button-target.h b/firmware/target/hosted/ypr0/button-target.h new file mode 100644 index 0000000000..5d65d97607 --- /dev/null +++ b/firmware/target/hosted/ypr0/button-target.h | |||
@@ -0,0 +1,53 @@ | |||
1 | /*************************************************************************** | ||
2 | * __________ __ ___. | ||
3 | * Open \______ \ ____ ____ | | _\_ |__ _______ ___ | ||
4 | * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ / | ||
5 | * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < < | ||
6 | * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \ | ||
7 | * \/ \/ \/ \/ \/ | ||
8 | * $Id: button-target.h 29248 2011-02-08 20:05:25Z thomasjfox $ | ||
9 | * | ||
10 | * Copyright (C) 2011 by Lorenzo Miori | ||
11 | * | ||
12 | * This program is free software; you can redistribute it and/or | ||
13 | * modify it under the terms of the GNU General Public License | ||
14 | * as published by the Free Software Foundation; either version 2 | ||
15 | * of the License, or (at your option) any later version. | ||
16 | * | ||
17 | * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY | ||
18 | * KIND, either express or implied. | ||
19 | * | ||
20 | ****************************************************************************/ | ||
21 | |||
22 | #ifndef _BUTTON_TARGET_H_ | ||
23 | #define _BUTTON_TARGET_H_ | ||
24 | |||
25 | #include <stdbool.h> | ||
26 | #include "config.h" | ||
27 | |||
28 | void button_init_device(void); | ||
29 | void button_close_device(void); | ||
30 | int button_read_device(void); | ||
31 | |||
32 | /* Logical buttons key codes */ | ||
33 | #define BUTTON_UP 0x00000001 | ||
34 | #define BUTTON_DOWN 0x00000002 | ||
35 | #define BUTTON_LEFT 0x00000004 | ||
36 | #define BUTTON_RIGHT 0x00000008 | ||
37 | #define BUTTON_USER 0x00000010 | ||
38 | #define BUTTON_MENU 0x00000020 | ||
39 | #define BUTTON_BACK 0x00000040 | ||
40 | #define BUTTON_POWER 0x00000080 | ||
41 | #define BUTTON_SELECT 0x00000100 | ||
42 | |||
43 | #define BUTTON_MAIN 0x1FF /* all buttons */ | ||
44 | |||
45 | /* No remote */ | ||
46 | #define BUTTON_REMOTE 0 | ||
47 | |||
48 | /* Software power-off */ | ||
49 | #define POWEROFF_BUTTON BUTTON_POWER | ||
50 | /* About 3 seconds */ | ||
51 | #define POWEROFF_COUNT 10 | ||
52 | |||
53 | #endif /* _BUTTON_TARGET_H_ */ | ||
diff --git a/firmware/target/hosted/ypr0/button-ypr0.c b/firmware/target/hosted/ypr0/button-ypr0.c new file mode 100644 index 0000000000..4298410161 --- /dev/null +++ b/firmware/target/hosted/ypr0/button-ypr0.c | |||
@@ -0,0 +1,103 @@ | |||
1 | /*************************************************************************** | ||
2 | * __________ __ ___. | ||
3 | * Open \______ \ ____ ____ | | _\_ |__ _______ ___ | ||
4 | * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ / | ||
5 | * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < < | ||
6 | * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \ | ||
7 | * \/ \/ \/ \/ \/ | ||
8 | * $Id: button-sdl.c 30482 2011-09-08 14:53:28Z kugel $ | ||
9 | * | ||
10 | * Copyright (C) 2011 Lorenzo Miori | ||
11 | * | ||
12 | * This program is free software; you can redistribute it and/or | ||
13 | * modify it under the terms of the GNU General Public License | ||
14 | * as published by the Free Software Foundation; either version 2 | ||
15 | * of the License, or (at your option) any later version. | ||
16 | * | ||
17 | * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY | ||
18 | * KIND, either express or implied. | ||
19 | * | ||
20 | ****************************************************************************/ | ||
21 | |||
22 | #include <stdio.h> | ||
23 | #include <unistd.h> | ||
24 | #include <fcntl.h> | ||
25 | #include <stdlib.h> /* EXIT_SUCCESS */ | ||
26 | #include "config.h" | ||
27 | #include "button.h" | ||
28 | #include "kernel.h" | ||
29 | #include "system.h" | ||
30 | #include "button-target.h" | ||
31 | |||
32 | /* R0 physical key codes */ | ||
33 | enum ypr0_buttons { | ||
34 | R0BTN_NONE = BUTTON_NONE, | ||
35 | R0BTN_POWER = 1, | ||
36 | R0BTN_UP, | ||
37 | R0BTN_DOWN, | ||
38 | R0BTN_RIGHT, | ||
39 | R0BTN_LEFT, | ||
40 | R0BTN_CENTRAL, | ||
41 | R0BTN_MENU, | ||
42 | R0BTN_BACK, | ||
43 | R0BTN_3DOTS = 11, | ||
44 | }; | ||
45 | |||
46 | |||
47 | static int r0_btn_fd = 0; | ||
48 | /* Samsung keypad driver doesn't allow multiple key combinations :( */ | ||
49 | static enum ypr0_buttons r0_read_key(void) | ||
50 | { | ||
51 | unsigned char keys; | ||
52 | |||
53 | if (r0_btn_fd < 0) | ||
54 | return 0; | ||
55 | |||
56 | if (read(r0_btn_fd, &keys, 1)) | ||
57 | return keys; | ||
58 | |||
59 | return 0; | ||
60 | } | ||
61 | |||
62 | /* Conversion from physical keypress code to logic key code */ | ||
63 | static int key_to_button(enum ypr0_buttons keyboard_button) | ||
64 | { | ||
65 | switch (keyboard_button) | ||
66 | { | ||
67 | default: return BUTTON_NONE; | ||
68 | case R0BTN_POWER: return BUTTON_POWER; | ||
69 | case R0BTN_UP: return BUTTON_UP; | ||
70 | case R0BTN_DOWN: return BUTTON_DOWN; | ||
71 | case R0BTN_RIGHT: return BUTTON_RIGHT; | ||
72 | case R0BTN_LEFT: return BUTTON_LEFT; | ||
73 | case R0BTN_CENTRAL: return BUTTON_SELECT; | ||
74 | case R0BTN_MENU: return BUTTON_MENU; | ||
75 | case R0BTN_BACK: return BUTTON_BACK; | ||
76 | case R0BTN_3DOTS: return BUTTON_USER; | ||
77 | } | ||
78 | } | ||
79 | |||
80 | int button_read_device(void) | ||
81 | { | ||
82 | return key_to_button(r0_read_key()); | ||
83 | } | ||
84 | |||
85 | |||
86 | /* Open the keypad device: it is offered by r0Btn.ko module */ | ||
87 | void button_init_device(void) | ||
88 | { | ||
89 | r0_btn_fd = open("/dev/r0Btn", O_RDONLY); | ||
90 | if (r0_btn_fd < 0) | ||
91 | printf("/dev/r0Btn open error!"); | ||
92 | } | ||
93 | |||
94 | #ifdef BUTTON_DRIVER_CLOSE | ||
95 | /* I'm not sure it's called at shutdown...give a check! */ | ||
96 | void button_close_device(void) | ||
97 | { | ||
98 | if (r0_btn_fd >= 0) { | ||
99 | close(r0_btn_fd); | ||
100 | printf("/dev/r0Btn closed!"); | ||
101 | } | ||
102 | } | ||
103 | #endif /* BUTTON_DRIVER_CLOSE */ | ||
diff --git a/firmware/target/hosted/ypr0/dir-target.h b/firmware/target/hosted/ypr0/dir-target.h new file mode 100644 index 0000000000..48859526df --- /dev/null +++ b/firmware/target/hosted/ypr0/dir-target.h | |||
@@ -0,0 +1,56 @@ | |||
1 | /*************************************************************************** | ||
2 | * __________ __ ___. | ||
3 | * Open \______ \ ____ ____ | | _\_ |__ _______ ___ | ||
4 | * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ / | ||
5 | * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < < | ||
6 | * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \ | ||
7 | * \/ \/ \/ \/ \/ | ||
8 | * $Id$ | ||
9 | * | ||
10 | * Copyright (C) 2010 by Thomas Martitz | ||
11 | * | ||
12 | * This program is free software; you can redistribute it and/or | ||
13 | * modify it under the terms of the GNU General Public License | ||
14 | * as published by the Free Software Foundation; either version 2 | ||
15 | * of the License, or (at your option) any later version. | ||
16 | * | ||
17 | * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY | ||
18 | * KIND, either express or implied. | ||
19 | * | ||
20 | ****************************************************************************/ | ||
21 | |||
22 | #ifndef __DIR_TARGET_H__ | ||
23 | #define __DIR_TARGET_H__ | ||
24 | |||
25 | #include <dirent.h> | ||
26 | /* including unistd.h is too noisy */ | ||
27 | extern int rmdir(const char* name); | ||
28 | |||
29 | |||
30 | #define dirent_uncached dirent | ||
31 | #define DIR_UNCACHED DIR | ||
32 | #define opendir_uncached _opendir | ||
33 | #define readdir_uncached _readdir | ||
34 | #define closedir_uncached _closedir | ||
35 | #define mkdir_uncached _mkdir | ||
36 | #define rmdir_uncached rmdir | ||
37 | |||
38 | #define dirent_ypr0 dirent | ||
39 | #define DIR_ypr0 DIR | ||
40 | #define opendir_ypr0 _opendir | ||
41 | #define readdir_ypr0 _readdir | ||
42 | #define closedir_ypr0 _closedir | ||
43 | #define mkdir_ypr0 _mkdir | ||
44 | #define rmdir_ypr0 rmdir | ||
45 | |||
46 | extern DIR* _opendir(const char* name); | ||
47 | extern int _mkdir(const char* name); | ||
48 | extern int _closedir(DIR* dir); | ||
49 | extern struct dirent *_readdir(DIR* dir); | ||
50 | extern void fat_size(unsigned long *size, unsigned long *free); | ||
51 | |||
52 | #define DIRFUNCTIONS_DEFINED | ||
53 | #define DIRENT_DEFINED | ||
54 | #define DIR_DEFINED | ||
55 | |||
56 | #endif /* __DIR_TARGET_H__ */ | ||
diff --git a/firmware/target/hosted/ypr0/fs-ypr0.c b/firmware/target/hosted/ypr0/fs-ypr0.c new file mode 100644 index 0000000000..7f49a5f91a --- /dev/null +++ b/firmware/target/hosted/ypr0/fs-ypr0.c | |||
@@ -0,0 +1,141 @@ | |||
1 | /*************************************************************************** | ||
2 | * __________ __ ___. | ||
3 | * Open \______ \ ____ ____ | | _\_ |__ _______ ___ | ||
4 | * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ / | ||
5 | * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < < | ||
6 | * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \ | ||
7 | * \/ \/ \/ \/ \/ | ||
8 | * $Id$ | ||
9 | * | ||
10 | * Copyright (C) 2010 by Thomas Martitz | ||
11 | * | ||
12 | * This program is free software; you can redistribute it and/or | ||
13 | * modify it under the terms of the GNU General Public License | ||
14 | * as published by the Free Software Foundation; either version 2 | ||
15 | * of the License, or (at your option) any later version. | ||
16 | * | ||
17 | * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY | ||
18 | * KIND, either express or implied. | ||
19 | * | ||
20 | ****************************************************************************/ | ||
21 | |||
22 | #include <stdlib.h> | ||
23 | #include <sys/stat.h> /* stat() */ | ||
24 | #include <stdio.h> /* snprintf */ | ||
25 | #include <string.h> /* size_t */ | ||
26 | #include <dirent.h> | ||
27 | #include <time.h> /* localtime() */ | ||
28 | #include "system-target.h" | ||
29 | #include "dir-target.h" | ||
30 | #include "file.h" | ||
31 | #include "dir.h" | ||
32 | #include "rbpaths.h" | ||
33 | |||
34 | |||
35 | long filesize(int fd) | ||
36 | { | ||
37 | struct stat buf; | ||
38 | |||
39 | if (!fstat(fd, &buf)) | ||
40 | return buf.st_size; | ||
41 | else | ||
42 | return -1; | ||
43 | } | ||
44 | |||
45 | /* do we really need this in the app? */ | ||
46 | void fat_size(unsigned long* size, unsigned long* free) | ||
47 | { | ||
48 | *size = *free = 0; | ||
49 | } | ||
50 | |||
51 | #undef opendir | ||
52 | #undef closedir | ||
53 | #undef mkdir | ||
54 | #undef readdir | ||
55 | |||
56 | /* need to wrap around DIR* because we need to save the parent's | ||
57 | * directory path in order to determine dirinfo */ | ||
58 | struct __dir { | ||
59 | DIR *dir; | ||
60 | char *path; | ||
61 | }; | ||
62 | |||
63 | DIR* _opendir(const char *name) | ||
64 | { | ||
65 | char *buf = malloc(sizeof(struct __dir) + strlen(name)+1); | ||
66 | if (!buf) | ||
67 | return NULL; | ||
68 | |||
69 | struct __dir *this = (struct __dir*)buf; | ||
70 | |||
71 | this->path = buf+sizeof(struct __dir); | ||
72 | /* definitely fits due to strlen() */ | ||
73 | strcpy(this->path, name); | ||
74 | |||
75 | this->dir = opendir(name); | ||
76 | |||
77 | if (!this->dir) | ||
78 | { | ||
79 | free(buf); | ||
80 | return NULL; | ||
81 | } | ||
82 | return (DIR*)this; | ||
83 | } | ||
84 | |||
85 | int _mkdir(const char *name) | ||
86 | { | ||
87 | return mkdir(name, 0777); | ||
88 | } | ||
89 | |||
90 | int _closedir(DIR *dir) | ||
91 | { | ||
92 | struct __dir *this = (struct __dir*)dir; | ||
93 | int ret = closedir(this->dir); | ||
94 | free(this); | ||
95 | return ret; | ||
96 | } | ||
97 | |||
98 | struct dirent* _readdir(DIR* dir) | ||
99 | { | ||
100 | struct __dir *d = (struct __dir*)dir; | ||
101 | return readdir(d->dir); | ||
102 | } | ||
103 | |||
104 | struct dirinfo dir_get_info(DIR* _parent, struct dirent *dir) | ||
105 | { | ||
106 | struct __dir *parent = (struct __dir*)_parent; | ||
107 | struct stat s; | ||
108 | struct tm *tm = NULL; | ||
109 | struct dirinfo ret; | ||
110 | char path[MAX_PATH]; | ||
111 | |||
112 | snprintf(path, sizeof(path), "%s/%s", parent->path, dir->d_name); | ||
113 | memset(&ret, 0, sizeof(ret)); | ||
114 | |||
115 | if (!stat(path, &s)) | ||
116 | { | ||
117 | if (S_ISDIR(s.st_mode)) | ||
118 | { | ||
119 | ret.attribute = ATTR_DIRECTORY; | ||
120 | } | ||
121 | ret.size = s.st_size; | ||
122 | tm = localtime(&(s.st_mtime)); | ||
123 | } | ||
124 | |||
125 | if (!lstat(path, &s) && S_ISLNK(s.st_mode)) | ||
126 | { | ||
127 | ret.attribute |= ATTR_LINK; | ||
128 | } | ||
129 | |||
130 | if (tm) | ||
131 | { | ||
132 | ret.wrtdate = ((tm->tm_year - 80) << 9) | | ||
133 | ((tm->tm_mon + 1) << 5) | | ||
134 | tm->tm_mday; | ||
135 | ret.wrttime = (tm->tm_hour << 11) | | ||
136 | (tm->tm_min << 5) | | ||
137 | (tm->tm_sec >> 1); | ||
138 | } | ||
139 | |||
140 | return ret; | ||
141 | } | ||
diff --git a/firmware/target/hosted/ypr0/i2c-target.h b/firmware/target/hosted/ypr0/i2c-target.h new file mode 100644 index 0000000000..3b046bba96 --- /dev/null +++ b/firmware/target/hosted/ypr0/i2c-target.h | |||
@@ -0,0 +1,25 @@ | |||
1 | /*************************************************************************** | ||
2 | * __________ __ ___. | ||
3 | * Open \______ \ ____ ____ | | _\_ |__ _______ ___ | ||
4 | * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ / | ||
5 | * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < < | ||
6 | * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \ | ||
7 | * \/ \/ \/ \/ \/ | ||
8 | * $Id: i2c-target.h 29516 2011-03-05 15:31:52Z thomasjfox $ | ||
9 | * | ||
10 | * Copyright (C) 2010 by Thomas Martitz | ||
11 | * | ||
12 | * This program is free software; you can redistribute it and/or | ||
13 | * modify it under the terms of the GNU General Public License | ||
14 | * as published by the Free Software Foundation; either version 2 | ||
15 | * of the License, or (at your option) any later version. | ||
16 | * | ||
17 | * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY | ||
18 | * KIND, either express or implied. | ||
19 | * | ||
20 | ****************************************************************************/ | ||
21 | |||
22 | #ifndef __I2C_TARGET_H__ | ||
23 | #define __I2C_TARGET_H__ | ||
24 | |||
25 | #endif /* __I2C_TARGET_H__ */ | ||
diff --git a/firmware/target/hosted/ypr0/kernel-ypr0.c b/firmware/target/hosted/ypr0/kernel-ypr0.c new file mode 100644 index 0000000000..bcf2cee583 --- /dev/null +++ b/firmware/target/hosted/ypr0/kernel-ypr0.c | |||
@@ -0,0 +1,163 @@ | |||
1 | /*************************************************************************** | ||
2 | * __________ __ ___. | ||
3 | * Open \______ \ ____ ____ | | _\_ |__ _______ ___ | ||
4 | * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ / | ||
5 | * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < < | ||
6 | * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \ | ||
7 | * \/ \/ \/ \/ \/ | ||
8 | * $Id$ | ||
9 | * | ||
10 | * Copyright (c) 2010 Thomas Martitz | ||
11 | * | ||
12 | * This program is free software; you can redistribute it and/or | ||
13 | * modify it under the terms of the GNU General Public License | ||
14 | * as published by the Free Software Foundation; either version 2 | ||
15 | * of the License, or (at your option) any later version. | ||
16 | * | ||
17 | * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY | ||
18 | * KIND, either express or implied. | ||
19 | * | ||
20 | ****************************************************************************/ | ||
21 | |||
22 | |||
23 | #include <time.h> | ||
24 | #include <signal.h> | ||
25 | #include <errno.h> | ||
26 | #include <unistd.h> | ||
27 | #include <pthread.h> | ||
28 | #include "config.h" | ||
29 | #include "system.h" | ||
30 | #include "button.h" | ||
31 | #include "audio.h" | ||
32 | #include "panic.h" | ||
33 | #include "timer.h" | ||
34 | |||
35 | |||
36 | static pthread_cond_t wfi_cond = PTHREAD_COND_INITIALIZER; | ||
37 | static pthread_mutex_t wfi_mtx = PTHREAD_MUTEX_INITIALIZER; | ||
38 | /* | ||
39 | * call tick tasks and wake the scheduler up */ | ||
40 | void timer_signal(union sigval arg) | ||
41 | { | ||
42 | (void)arg; | ||
43 | call_tick_tasks(); | ||
44 | interrupt(); | ||
45 | } | ||
46 | |||
47 | /* | ||
48 | * wait on the sem which the signal handler posts to save cpu time (aka sleep) | ||
49 | * | ||
50 | * other mechanisms could use them as well */ | ||
51 | void wait_for_interrupt(void) | ||
52 | { | ||
53 | pthread_cond_wait(&wfi_cond, &wfi_mtx); | ||
54 | } | ||
55 | |||
56 | /* | ||
57 | * Wakeup the kernel, if sleeping (shall not be called from a signal handler) */ | ||
58 | void interrupt(void) | ||
59 | { | ||
60 | pthread_cond_signal(&wfi_cond); | ||
61 | } | ||
62 | |||
63 | |||
64 | /* | ||
65 | * setup a hrtimer to send a signal to our process every tick | ||
66 | */ | ||
67 | union sigval tick_arg = { | ||
68 | .sival_int = 0, | ||
69 | }; | ||
70 | |||
71 | void tick_start(unsigned int interval_in_ms) | ||
72 | { | ||
73 | int ret = 0; | ||
74 | timer_t timerid; | ||
75 | struct itimerspec ts; | ||
76 | sigevent_t sigev; | ||
77 | |||
78 | /* initializing in the declaration causes some weird warnings */ | ||
79 | memset(&sigev, 0, sizeof(sigevent_t)); | ||
80 | sigev.sigev_notify = SIGEV_THREAD, | ||
81 | sigev.sigev_notify_function = timer_signal; | ||
82 | |||
83 | ts.it_value.tv_sec = ts.it_interval.tv_sec = 0; | ||
84 | ts.it_value.tv_nsec = ts.it_interval.tv_nsec = interval_in_ms*1000*1000; | ||
85 | |||
86 | /* add the timer */ | ||
87 | ret |= timer_create(CLOCK_REALTIME, &sigev, &timerid); | ||
88 | ret |= timer_settime(timerid, 0, &ts, NULL); | ||
89 | |||
90 | /* Grab the mutex already now and leave it to this thread. We don't | ||
91 | * care about race conditions when signaling the condition (because | ||
92 | * they are not critical), but a mutex is necessary due to the API */ | ||
93 | pthread_mutex_lock(&wfi_mtx); | ||
94 | |||
95 | if (ret != 0) | ||
96 | panicf("%s(): %s\n", __func__, strerror(errno)); | ||
97 | } | ||
98 | |||
99 | #define cycles_to_microseconds(cycles) \ | ||
100 | ((int)((1000000*cycles)/TIMER_FREQ)) | ||
101 | |||
102 | |||
103 | static timer_t timer_tid; | ||
104 | static int timer_prio = -1; | ||
105 | void (*global_unreg_callback)(void); | ||
106 | void (*global_timer_callback)(void); | ||
107 | |||
108 | static void timer_cb(union sigval arg) | ||
109 | { | ||
110 | (void)arg; | ||
111 | if (global_timer_callback) | ||
112 | global_timer_callback(); | ||
113 | } | ||
114 | |||
115 | bool timer_register(int reg_prio, void (*unregister_callback)(void), | ||
116 | long cycles, void (*timer_callback)(void)) | ||
117 | { | ||
118 | int ret = 0; | ||
119 | struct itimerspec ts; | ||
120 | sigevent_t sigev; | ||
121 | long in_us = cycles_to_microseconds(cycles); | ||
122 | |||
123 | if (reg_prio <= timer_prio || in_us <= 0) | ||
124 | return false; | ||
125 | |||
126 | if (timer_prio >= 0 && global_unreg_callback) | ||
127 | global_unreg_callback(); | ||
128 | |||
129 | /* initializing in the declaration causes some weird warnings */ | ||
130 | memset(&sigev, 0, sizeof(sigevent_t)); | ||
131 | sigev.sigev_notify = SIGEV_THREAD, | ||
132 | sigev.sigev_notify_function = timer_cb; | ||
133 | |||
134 | ts.it_value.tv_sec = ts.it_interval.tv_sec = in_us / 1000000; | ||
135 | ts.it_value.tv_nsec = ts.it_interval.tv_nsec = (in_us%1000000)*1000; | ||
136 | |||
137 | /* add the timer */ | ||
138 | ret |= timer_create(CLOCK_REALTIME, &sigev, &timer_tid); | ||
139 | ret |= timer_settime(timer_tid, 0, &ts, NULL); | ||
140 | |||
141 | global_timer_callback = timer_callback; | ||
142 | global_unreg_callback = unregister_callback; | ||
143 | timer_prio = reg_prio; | ||
144 | |||
145 | return ret == 0; | ||
146 | } | ||
147 | |||
148 | bool timer_set_period(long cycles) | ||
149 | { | ||
150 | struct itimerspec ts; | ||
151 | long in_us = cycles_to_microseconds(cycles); | ||
152 | ts.it_value.tv_sec = ts.it_interval.tv_sec = in_us / 1000000; | ||
153 | ts.it_value.tv_nsec = ts.it_interval.tv_nsec = (in_us%1000000)*1000; | ||
154 | |||
155 | return timer_settime(timer_tid, 0, &ts, NULL) == 0; | ||
156 | } | ||
157 | |||
158 | void timer_unregister(void) | ||
159 | { | ||
160 | timer_delete(timer_tid); | ||
161 | timer_prio = -1; | ||
162 | } | ||
163 | |||
diff --git a/firmware/target/hosted/ypr0/lc-ypr0.c b/firmware/target/hosted/ypr0/lc-ypr0.c new file mode 100644 index 0000000000..434e901a56 --- /dev/null +++ b/firmware/target/hosted/ypr0/lc-ypr0.c | |||
@@ -0,0 +1,40 @@ | |||
1 | /*************************************************************************** | ||
2 | * __________ __ ___. | ||
3 | * Open \______ \ ____ ____ | | _\_ |__ _______ ___ | ||
4 | * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ / | ||
5 | * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < < | ||
6 | * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \ | ||
7 | * \/ \/ \/ \/ \/ | ||
8 | * $Id$ | ||
9 | * | ||
10 | * Copyright (C) 2010 by Thomas Martitz | ||
11 | * | ||
12 | * This program is free software; you can redistribute it and/or | ||
13 | * modify it under the terms of the GNU General Public License | ||
14 | * as published by the Free Software Foundation; either version 2 | ||
15 | * of the License, or (at your option) any later version. | ||
16 | * | ||
17 | * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY | ||
18 | * KIND, either express or implied. | ||
19 | * | ||
20 | ****************************************************************************/ | ||
21 | |||
22 | #include <string.h> /* size_t */ | ||
23 | #include "load_code.h" | ||
24 | |||
25 | /* the load_code wrappers simply wrap, nothing to do */ | ||
26 | void *lc_open(const char *filename, unsigned char *buf, size_t buf_size) | ||
27 | { | ||
28 | return _lc_open(filename, buf, buf_size); | ||
29 | } | ||
30 | |||
31 | void *lc_get_header(void *handle) | ||
32 | { | ||
33 | return _lc_get_header(handle); | ||
34 | } | ||
35 | |||
36 | void lc_close(void *handle) | ||
37 | { | ||
38 | _lc_close(handle); | ||
39 | } | ||
40 | |||
diff --git a/firmware/target/hosted/ypr0/lcd-ypr0.c b/firmware/target/hosted/ypr0/lcd-ypr0.c new file mode 100644 index 0000000000..f0565ae2d4 --- /dev/null +++ b/firmware/target/hosted/ypr0/lcd-ypr0.c | |||
@@ -0,0 +1,147 @@ | |||
1 | /*************************************************************************** | ||
2 | * __________ __ ___. | ||
3 | * Open \______ \ ____ ____ | | _\_ |__ _______ ___ | ||
4 | * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ / | ||
5 | * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < < | ||
6 | * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \ | ||
7 | * \/ \/ \/ \/ \/ | ||
8 | * $Id: lcd-bitmap.c 29248 2011-02-08 20:05:25Z thomasjfox $ | ||
9 | * | ||
10 | * Copyright (C) 2011 Lorenzo Miori, Thomas Martitz | ||
11 | * | ||
12 | * This program is free software; you can redistribute it and/or | ||
13 | * modify it under the terms of the GNU General Public License | ||
14 | * as published by the Free Software Foundation; either version 2 | ||
15 | * of the License, or (at your option) any later version. | ||
16 | * | ||
17 | * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY | ||
18 | * KIND, either express or implied. | ||
19 | * | ||
20 | ****************************************************************************/ | ||
21 | |||
22 | #include <stdlib.h> | ||
23 | #include <unistd.h> | ||
24 | #include <stdio.h> | ||
25 | #include "string.h" | ||
26 | #include <linux/fb.h> | ||
27 | #include <sys/mman.h> | ||
28 | #include <sys/ioctl.h> | ||
29 | |||
30 | #include "file.h" | ||
31 | #include "debug.h" | ||
32 | #include "system.h" | ||
33 | #include "screendump.h" | ||
34 | #include "lcd.h" | ||
35 | |||
36 | /* eqivalent to fb + y*width + x */ | ||
37 | #define LCDADDR(x, y) (&lcd_framebuffer[(y)][(x)]) | ||
38 | |||
39 | static int dev_fd = 0; | ||
40 | static fb_data *dev_fb = 0; | ||
41 | |||
42 | void lcd_update(void) | ||
43 | { | ||
44 | /* update the entire display */ | ||
45 | memcpy(dev_fb, lcd_framebuffer, sizeof(lcd_framebuffer)); | ||
46 | } | ||
47 | |||
48 | /* Copy Rockbox frame buffer to the mmapped lcd device */ | ||
49 | void lcd_update_rect(int x, int y, int width, int height) | ||
50 | { | ||
51 | /* nothing to draw? */ | ||
52 | if ((width <= 0) || (height <= 0) || (x >= LCD_WIDTH) || | ||
53 | (y >= LCD_HEIGHT) || (x + width <= 0) || (y + height <= 0)) | ||
54 | return; | ||
55 | |||
56 | /* do the necessary clipping */ | ||
57 | if (x < 0) | ||
58 | { /* clip left */ | ||
59 | width += x; | ||
60 | x = 0; | ||
61 | } | ||
62 | if (y < 0) | ||
63 | { /* clip top */ | ||
64 | height += y; | ||
65 | y = 0; | ||
66 | } | ||
67 | if (x + width > LCD_WIDTH) | ||
68 | width = LCD_WIDTH - x; /* clip right */ | ||
69 | if (y + height > LCD_HEIGHT) | ||
70 | height = LCD_HEIGHT - y; /* clip bottom */ | ||
71 | |||
72 | fb_data* src = LCDADDR(x, y); | ||
73 | fb_data* dst = dev_fb + y*LCD_WIDTH + x; | ||
74 | |||
75 | if (LCD_WIDTH == width) | ||
76 | { /* optimized full-width update */ | ||
77 | memcpy(dst, src, width * height * sizeof(fb_data)); | ||
78 | } | ||
79 | else | ||
80 | { /* row by row */ | ||
81 | do | ||
82 | { | ||
83 | memcpy(dst, src, width * sizeof(fb_data)); | ||
84 | src += LCD_WIDTH; | ||
85 | dst += LCD_WIDTH; | ||
86 | } while(--height > 0); | ||
87 | } | ||
88 | } | ||
89 | |||
90 | void lcd_shutdown(void) | ||
91 | { | ||
92 | printf("FB closed."); | ||
93 | munmap(dev_fb, sizeof(lcd_framebuffer)); | ||
94 | close(dev_fd); | ||
95 | } | ||
96 | |||
97 | void lcd_init_device(void) | ||
98 | { | ||
99 | size_t screensize; | ||
100 | struct fb_var_screeninfo vinfo; | ||
101 | struct fb_fix_screeninfo finfo; | ||
102 | |||
103 | /* Open the framebuffer device */ | ||
104 | dev_fd = open("/dev/fb0", O_RDWR); | ||
105 | if (dev_fd == -1) { | ||
106 | perror("Error: cannot open framebuffer device"); | ||
107 | exit(1); | ||
108 | } | ||
109 | printf("The framebuffer device was opened successfully.\n"); | ||
110 | |||
111 | /* Get the fixed properties */ | ||
112 | if (ioctl(dev_fd, FBIOGET_FSCREENINFO, &finfo) == -1) { | ||
113 | perror("Error reading fixed information"); | ||
114 | exit(2); | ||
115 | } | ||
116 | |||
117 | /* Now we get the settable settings, and we set 16 bit bpp */ | ||
118 | if (ioctl(dev_fd, FBIOGET_VSCREENINFO, &vinfo) == -1) { | ||
119 | perror("Error reading variable information"); | ||
120 | exit(3); | ||
121 | } | ||
122 | |||
123 | vinfo.bits_per_pixel = 16; | ||
124 | |||
125 | if (ioctl(dev_fd, FBIOPUT_VSCREENINFO, &vinfo)) { | ||
126 | perror("fbset(ioctl)"); | ||
127 | exit(4); | ||
128 | } | ||
129 | |||
130 | printf("%dx%d, %dbpp\n", vinfo.xres, vinfo.yres, vinfo.bits_per_pixel); | ||
131 | |||
132 | /* Figure out the size of the screen in bytes */ | ||
133 | screensize = vinfo.xres * vinfo.yres * vinfo.bits_per_pixel / 8; | ||
134 | if (screensize != sizeof(lcd_framebuffer)) | ||
135 | { | ||
136 | exit(4); | ||
137 | perror("Display and framebuffer mismatch!\n"); | ||
138 | } | ||
139 | |||
140 | /* Map the device to memory */ | ||
141 | dev_fb = mmap(0, screensize, PROT_READ | PROT_WRITE, MAP_SHARED, dev_fd, 0); | ||
142 | if ((int)dev_fb == -1) { | ||
143 | perror("Error: failed to map framebuffer device to memory"); | ||
144 | exit(4); | ||
145 | } | ||
146 | printf("The framebuffer device was mapped to memory successfully.\n"); | ||
147 | } | ||
diff --git a/firmware/target/hosted/ypr0/powermgmt-ypr0.c b/firmware/target/hosted/ypr0/powermgmt-ypr0.c new file mode 100644 index 0000000000..5701e9f02f --- /dev/null +++ b/firmware/target/hosted/ypr0/powermgmt-ypr0.c | |||
@@ -0,0 +1,133 @@ | |||
1 | /*************************************************************************** | ||
2 | * __________ __ ___. | ||
3 | * Open \______ \ ____ ____ | | _\_ |__ _______ ___ | ||
4 | * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ / | ||
5 | * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < < | ||
6 | * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \ | ||
7 | * \/ \/ \/ \/ \/ | ||
8 | * $Id: powermgmt-sim.c 29543 2011-03-08 19:33:30Z thomasjfox $ | ||
9 | * | ||
10 | * This program is free software; you can redistribute it and/or | ||
11 | * modify it under the terms of the GNU General Public License | ||
12 | * as published by the Free Software Foundation; either version 2 | ||
13 | * of the License, or (at your option) any later version. | ||
14 | * | ||
15 | * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY | ||
16 | * KIND, either express or implied. | ||
17 | * | ||
18 | ****************************************************************************/ | ||
19 | #include "config.h" | ||
20 | #include "system.h" | ||
21 | #include <time.h> | ||
22 | #include "kernel.h" | ||
23 | #include "powermgmt.h" | ||
24 | #include "ascodec-target.h" | ||
25 | #include "stdio.h" | ||
26 | |||
27 | #if 0 /*still unused*/ | ||
28 | /* The battery manufacturer's website shows discharge curves down to 3.0V, | ||
29 | so 'dangerous' and 'shutoff' levels of 3.4V and 3.3V should be safe. | ||
30 | */ | ||
31 | const unsigned short battery_level_dangerous[BATTERY_TYPES_COUNT] = | ||
32 | { | ||
33 | 3550 | ||
34 | }; | ||
35 | |||
36 | const unsigned short battery_level_shutoff[BATTERY_TYPES_COUNT] = | ||
37 | { | ||
38 | 3450 | ||
39 | }; | ||
40 | |||
41 | /* voltages (millivolt) of 0%, 10%, ... 100% when charging disabled */ | ||
42 | const unsigned short percent_to_volt_discharge[BATTERY_TYPES_COUNT][11] = | ||
43 | { | ||
44 | { 3300, 3692, 3740, 3772, 3798, 3828, 3876, 3943, 4013, 4094, 4194 } | ||
45 | }; | ||
46 | |||
47 | #if CONFIG_CHARGING | ||
48 | /* voltages (millivolt) of 0%, 10%, ... 100% when charging enabled */ | ||
49 | const unsigned short percent_to_volt_charge[11] = | ||
50 | { | ||
51 | 3417, 3802, 3856, 3888, 3905, 3931, 3973, 4025, 4084, 4161, 4219 | ||
52 | }; | ||
53 | #endif /* CONFIG_CHARGING */ | ||
54 | #endif | ||
55 | |||
56 | #define BATT_MINMVOLT 3450 /* minimum millivolts of battery */ | ||
57 | #define BATT_MAXMVOLT 4150 /* maximum millivolts of battery */ | ||
58 | #define BATT_MAXRUNTIME (10 * 60) /* maximum runtime with full battery in | ||
59 | minutes */ | ||
60 | |||
61 | extern void send_battery_level_event(void); | ||
62 | extern int last_sent_battery_level; | ||
63 | extern int battery_percent; | ||
64 | |||
65 | static unsigned int battery_millivolts = BATT_MAXMVOLT; | ||
66 | /* estimated remaining time in minutes */ | ||
67 | static int powermgmt_est_runningtime_min = BATT_MAXRUNTIME; | ||
68 | |||
69 | static void battery_status_update(void) | ||
70 | { | ||
71 | static time_t last_change = 0; | ||
72 | time_t now; | ||
73 | |||
74 | time(&now); | ||
75 | |||
76 | if (last_change < now) { | ||
77 | last_change = now; | ||
78 | |||
79 | battery_percent = 100 * (battery_millivolts - BATT_MINMVOLT) / | ||
80 | (BATT_MAXMVOLT - BATT_MINMVOLT); | ||
81 | |||
82 | powermgmt_est_runningtime_min = | ||
83 | battery_percent * BATT_MAXRUNTIME / 100; | ||
84 | } | ||
85 | |||
86 | send_battery_level_event(); | ||
87 | } | ||
88 | |||
89 | void battery_read_info(int *voltage, int *level) | ||
90 | { | ||
91 | battery_status_update(); | ||
92 | |||
93 | if (voltage) | ||
94 | *voltage = battery_millivolts; | ||
95 | |||
96 | if (level) | ||
97 | *level = battery_percent; | ||
98 | } | ||
99 | |||
100 | unsigned int battery_voltage(void) | ||
101 | { | ||
102 | battery_status_update(); | ||
103 | return battery_millivolts; | ||
104 | } | ||
105 | |||
106 | int battery_level(void) | ||
107 | { | ||
108 | battery_status_update(); | ||
109 | return battery_percent; | ||
110 | } | ||
111 | |||
112 | int battery_time(void) | ||
113 | { | ||
114 | battery_status_update(); | ||
115 | return powermgmt_est_runningtime_min; | ||
116 | } | ||
117 | |||
118 | bool battery_level_safe(void) | ||
119 | { | ||
120 | return battery_level() >= 10; | ||
121 | } | ||
122 | |||
123 | void set_battery_capacity(int capacity) | ||
124 | { | ||
125 | (void)capacity; | ||
126 | } | ||
127 | |||
128 | #if BATTERY_TYPES_COUNT > 1 | ||
129 | void set_battery_type(int type) | ||
130 | { | ||
131 | (void)type; | ||
132 | } | ||
133 | #endif | ||
diff --git a/firmware/target/hosted/ypr0/system-target.h b/firmware/target/hosted/ypr0/system-target.h new file mode 100644 index 0000000000..07a3163ea9 --- /dev/null +++ b/firmware/target/hosted/ypr0/system-target.h | |||
@@ -0,0 +1,37 @@ | |||
1 | /*************************************************************************** | ||
2 | * __________ __ ___. | ||
3 | * Open \______ \ ____ ____ | | _\_ |__ _______ ___ | ||
4 | * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ / | ||
5 | * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < < | ||
6 | * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \ | ||
7 | * \/ \/ \/ \/ \/ | ||
8 | * $Id$ | ||
9 | * | ||
10 | * Copyright (C) 2010 by Thomas Martitz | ||
11 | * | ||
12 | * This program is free software; you can redistribute it and/or | ||
13 | * modify it under the terms of the GNU General Public License | ||
14 | * as published by the Free Software Foundation; either version 2 | ||
15 | * of the License, or (at your option) any later version. | ||
16 | * | ||
17 | * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY | ||
18 | * KIND, either express or implied. | ||
19 | * | ||
20 | ****************************************************************************/ | ||
21 | #ifndef __SYSTEM_TARGET_H__ | ||
22 | #define __SYSTEM_TARGET_H__ | ||
23 | |||
24 | #define disable_irq() | ||
25 | #define enable_irq() | ||
26 | #define disable_irq_save() 0 | ||
27 | #define restore_irq(level) (void)level | ||
28 | |||
29 | void wait_for_interrupt(void); | ||
30 | void interrupt(void); | ||
31 | |||
32 | static inline void commit_dcache(void) {} | ||
33 | static inline void commit_discard_dcache(void) {} | ||
34 | static inline void commit_discard_idcache(void) {} | ||
35 | |||
36 | #define NEED_GENERIC_BYTESWAPS | ||
37 | #endif /* __SYSTEM_TARGET_H__ */ | ||
diff --git a/firmware/target/hosted/ypr0/system-ypr0.c b/firmware/target/hosted/ypr0/system-ypr0.c new file mode 100644 index 0000000000..3a2b30339f --- /dev/null +++ b/firmware/target/hosted/ypr0/system-ypr0.c | |||
@@ -0,0 +1,106 @@ | |||
1 | /*************************************************************************** | ||
2 | * __________ __ ___. | ||
3 | * Open \______ \ ____ ____ | | _\_ |__ _______ ___ | ||
4 | * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ / | ||
5 | * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < < | ||
6 | * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \ | ||
7 | * \/ \/ \/ \/ \/ | ||
8 | * $Id: system-sdl.c 29925 2011-05-25 20:11:03Z thomasjfox $ | ||
9 | * | ||
10 | * Copyright (C) 2006 by Daniel Everton <dan@iocaine.org> | ||
11 | * | ||
12 | * This program is free software; you can redistribute it and/or | ||
13 | * modify it under the terms of the GNU General Public License | ||
14 | * as published by the Free Software Foundation; either version 2 | ||
15 | * of the License, or (at your option) any later version. | ||
16 | * | ||
17 | * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY | ||
18 | * KIND, either express or implied. | ||
19 | * | ||
20 | ****************************************************************************/ | ||
21 | |||
22 | #include <stdlib.h> | ||
23 | #include <string.h> | ||
24 | #include <inttypes.h> | ||
25 | #include "system.h" | ||
26 | #include "panic.h" | ||
27 | #include "debug.h" | ||
28 | |||
29 | #if defined(HAVE_SDL_AUDIO) || defined(HAVE_SDL_THREADS) || defined(HAVE_SDL) | ||
30 | #include <SDL.h> | ||
31 | #endif | ||
32 | |||
33 | #include "ascodec-target.h" | ||
34 | |||
35 | void sim_do_exit(void) | ||
36 | { | ||
37 | exit(EXIT_SUCCESS); | ||
38 | } | ||
39 | |||
40 | void shutdown_hw(void) | ||
41 | { | ||
42 | /* Something that we need to do before exit on our platform YPR0 */ | ||
43 | ascodec_close(); | ||
44 | sim_do_exit(); | ||
45 | } | ||
46 | |||
47 | uintptr_t *stackbegin; | ||
48 | uintptr_t *stackend; | ||
49 | void system_init(void) | ||
50 | { | ||
51 | int *s; | ||
52 | /* fake stack, OS manages size (and growth) */ | ||
53 | stackbegin = stackend = (uintptr_t*)&s; | ||
54 | |||
55 | #if defined(HAVE_SDL_AUDIO) || defined(HAVE_SDL_THREADS) || defined(HAVE_SDL) | ||
56 | SDL_Init(0); /* need this if using any SDL subsystem */ | ||
57 | #endif | ||
58 | /* Here begins our platform specific initilization for various things */ | ||
59 | ascodec_init(); | ||
60 | } | ||
61 | |||
62 | |||
63 | void system_reboot(void) | ||
64 | { | ||
65 | sim_do_exit(); | ||
66 | } | ||
67 | |||
68 | void system_exception_wait(void) | ||
69 | { | ||
70 | system_reboot(); | ||
71 | } | ||
72 | |||
73 | #ifdef HAVE_ADJUSTABLE_CPU_FREQ | ||
74 | #include <stdio.h> | ||
75 | #include "file.h" | ||
76 | /* This is the Linux Kernel CPU governor... */ | ||
77 | static void set_cpu_freq(int speed) | ||
78 | { | ||
79 | char temp[10]; | ||
80 | int cpu_dev; | ||
81 | cpu_dev = open("/sys/devices/system/cpu/cpu0/cpufreq/scaling_setspeed", O_WRONLY); | ||
82 | if (cpu_dev < 0) | ||
83 | return; | ||
84 | write(cpu_dev, temp, sprintf(temp, "%d", speed) + 1); | ||
85 | close(cpu_dev); | ||
86 | } | ||
87 | |||
88 | void set_cpu_frequency(long frequency) | ||
89 | { | ||
90 | switch (frequency) | ||
91 | { | ||
92 | case CPUFREQ_MAX: | ||
93 | set_cpu_freq(532000); | ||
94 | cpu_frequency = CPUFREQ_MAX; | ||
95 | break; | ||
96 | case CPUFREQ_NORMAL: | ||
97 | set_cpu_freq(400000); | ||
98 | cpu_frequency = CPUFREQ_NORMAL; | ||
99 | break; | ||
100 | default: | ||
101 | set_cpu_freq(200000); | ||
102 | cpu_frequency = CPUFREQ_DEFAULT; | ||
103 | break; | ||
104 | } | ||
105 | } | ||
106 | #endif | ||
diff --git a/firmware/target/hosted/ypr0/usb-target.h b/firmware/target/hosted/ypr0/usb-target.h new file mode 100644 index 0000000000..237d179775 --- /dev/null +++ b/firmware/target/hosted/ypr0/usb-target.h | |||
@@ -0,0 +1,25 @@ | |||
1 | /*************************************************************************** | ||
2 | * __________ __ ___. | ||
3 | * Open \______ \ ____ ____ | | _\_ |__ _______ ___ | ||
4 | * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ / | ||
5 | * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < < | ||
6 | * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \ | ||
7 | * \/ \/ \/ \/ \/ | ||
8 | * $Id: usb-target.h 29516 2011-03-05 15:31:52Z thomasjfox $ | ||
9 | * | ||
10 | * Copyright (C) 2010 by Thomas Martitz | ||
11 | * | ||
12 | * This program is free software; you can redistribute it and/or | ||
13 | * modify it under the terms of the GNU General Public License | ||
14 | * as published by the Free Software Foundation; either version 2 | ||
15 | * of the License, or (at your option) any later version. | ||
16 | * | ||
17 | * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY | ||
18 | * KIND, either express or implied. | ||
19 | * | ||
20 | ****************************************************************************/ | ||
21 | |||
22 | #ifndef __USB_TARGET_H__ | ||
23 | #define __USB_TARGET_H__ | ||
24 | |||
25 | #endif /* __USB_TARGET_H__ */ | ||
diff --git a/firmware/target/hosted/ypr0/ypr0.make b/firmware/target/hosted/ypr0/ypr0.make new file mode 100644 index 0000000000..c2114878db --- /dev/null +++ b/firmware/target/hosted/ypr0/ypr0.make | |||
@@ -0,0 +1,25 @@ | |||
1 | # __________ __ ___. | ||
2 | # Open \______ \ ____ ____ | | _\_ |__ _______ ___ | ||
3 | # Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ / | ||
4 | # Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < < | ||
5 | # Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \ | ||
6 | # \/ \/ \/ \/ \/ | ||
7 | # $Id$ | ||
8 | # | ||
9 | |||
10 | INCLUDES += -I$(FIRMDIR)/include -I$(FIRMDIR)/export $(TARGET_INC) -I$(BUILDDIR) -I$(APPSDIR) | ||
11 | |||
12 | SIMFLAGS += $(INCLUDES) $(DEFINES) -DHAVE_CONFIG_H $(GCCOPTS) | ||
13 | |||
14 | .SECONDEXPANSION: # $$(OBJ) is not populated until after this | ||
15 | |||
16 | |||
17 | $(BUILDDIR)/rockbox.elf : $$(OBJ) $$(FIRMLIB) $$(VOICESPEEXLIB) $$(SKINLIB) | ||
18 | $(call PRINTS,LD $(@F))$(CC) $(GCCOPTS) -Os -o $@ $(OBJ) \ | ||
19 | -L$(BUILDDIR)/firmware -lfirmware \ | ||
20 | -L$(BUILDDIR)/apps/codecs $(VOICESPEEXLIB:lib%.a=-l%) \ | ||
21 | -L$(BUILDDIR)/lib -lskin_parser \ | ||
22 | $(LDOPTS) $(GLOBAL_LDOPTS) -Wl,-Map,$(BUILDDIR)/rockbox.map | ||
23 | |||
24 | $(BUILDDIR)/rockbox : $(BUILDDIR)/rockbox.elf | ||
25 | $(call PRINTS,OC $(@F))$(OC) -S -x $< $@ | ||