summaryrefslogtreecommitdiff
path: root/firmware
diff options
context:
space:
mode:
authorSimon Rothen <rothen@gmx.net>2014-08-30 13:15:53 +0200
committerMichael Giacomelli <giac2000@hotmail.com>2014-09-18 18:19:01 +0200
commit0b5ad60c26f30dc5363c21e436b73292c09ac567 (patch)
tree2d7cee2b2133218d59e0f462c9dbdbec8e88b2e2 /firmware
parent1f0fa0546647a191c52784a4a225982ffbd1af11 (diff)
downloadrockbox-0b5ad60c26f30dc5363c21e436b73292c09ac567.tar.gz
rockbox-0b5ad60c26f30dc5363c21e436b73292c09ac567.zip
Introducing Targets iBasso DX50 & iBasso DX90
The port to for this two targets has been entirely developped by Ilia Sergachev (alias Il or xzcc). His source can be found at https://bitbucket.org/isergachev/rockbox . The few necesary modifications for the DX90 port was done by headwhacker form head-fi.org. Unfortunately i could not try out the final state of the DX90 port. The port is hosted on android (without java) as standalone app. The official Firmware is required to run this port. Ilia did modify the source files for the "android" target in the rockbox source to make the DX port work. The work I did was to separate the code for DX50 (&DX90) from the android target. On this Target Ilia used source from tinyalsa from AOSP. I did not touch that part of the code because I do not understand it. What else I changed from Ilias sources besides the separation from the target "android": * removed a dirty hack to keep backlight off * changed value battery meter to voltage battery meter * made all plugins compile (named target as "standalone") and added keymaps * i added the graphics for the manual but did not do anything else for the manual yet * minor optimizations known bugs: * timers are slowed donw when playback is active (tinyalsa related?) * some minor bugs Things to do: * The main prolem will be how to install the app correctly. A guy called DOC2008 added a CWM (by androtab.info) to the official firmware and Ilia made a CWM installation script and a dualboot selector (rbutils/ibassoboot, build with ndk-build). We will have to find a way to install rockbox in a proper way without breaking any copyrights. Maybe ADB is an option but it is not enable with OF by default. Patching the OF is probably the way to go. * All the wiki and manual to build: needed: android ndk installed, android sdk installed with additional build-tools 19.1.0 installed ./tools/configure select iBasso DX50 or iBasso DX90 make -j apk the content of rockbox.zip/.rockbox needs to be copied to /system/rockbox/app_rockbox/rockbox/ (rockbox app not needed) the content of libs/armeabi to /system/rockbox/lib/ (rockbox app needed) The boot selector is needed as /system/bin/MangoPlayer and the iBasso app as /system/bin/MangoPlayer_original. There is also the "vold" file. The one from OF does not work with DX50 rockbox (DX90 works!?), the one from Ilia is necessary. Until we have found a proper way to install it, it can only be installed following the instructions of Ilia on his bitbucket page, using the CWM-OF and his installation script package. Change-Id: Ic4faaf84824c162aabcc08e492cee6e0068719d0 Reviewed-on: http://gerrit.rockbox.org/941 Tested: Chiwen Chang <rock1104.tw@yahoo.com.tw> Reviewed-by: Michael Giacomelli <giac2000@hotmail.com>
Diffstat (limited to 'firmware')
-rw-r--r--firmware/SOURCES18
-rw-r--r--firmware/asm/SOURCES2
-rw-r--r--firmware/asm/arm/thread.h4
-rw-r--r--firmware/drivers/audio/android.c24
-rw-r--r--firmware/drivers/touchscreen.c2
-rw-r--r--firmware/export/config.h5
-rw-r--r--firmware/export/config/ibassodx50.h136
-rw-r--r--firmware/export/config/ibassodx90.h136
-rw-r--r--firmware/export/hosted_codec.h4
-rw-r--r--firmware/powermgmt.c2
-rw-r--r--firmware/target/hosted/android/dx50/adc-target.h0
-rw-r--r--firmware/target/hosted/android/dx50/backlight-dx50.c76
-rw-r--r--firmware/target/hosted/android/dx50/backlight-target.h31
-rw-r--r--firmware/target/hosted/android/dx50/button-dx50.c314
-rw-r--r--firmware/target/hosted/android/dx50/button-target.h72
-rw-r--r--firmware/target/hosted/android/dx50/lcd-dx50.c120
-rw-r--r--firmware/target/hosted/android/dx50/lcd-target.h29
-rw-r--r--firmware/target/hosted/android/dx50/pcm-dx50.c364
-rw-r--r--firmware/target/hosted/android/dx50/powermgmt-dx50.c72
-rw-r--r--firmware/target/hosted/android/dx50/tinyalsa/asound.h821
-rw-r--r--firmware/target/hosted/android/dx50/tinyalsa/asoundlib.h257
-rw-r--r--firmware/target/hosted/android/dx50/tinyalsa/mixer.c497
-rw-r--r--firmware/target/hosted/android/dx50/tinyalsa/pcm.c973
-rw-r--r--firmware/target/hosted/android/system-android.c54
-rw-r--r--firmware/target/hosted/filesystem-app.c1
25 files changed, 4005 insertions, 9 deletions
diff --git a/firmware/SOURCES b/firmware/SOURCES
index 070f0d4a62..950e4f2bcf 100644
--- a/firmware/SOURCES
+++ b/firmware/SOURCES
@@ -1811,18 +1811,28 @@ target/arm/rk27xx/ihifi/powermgmt-ihifi960.c
1811target/hosted/kernel-unix.c 1811target/hosted/kernel-unix.c
1812target/hosted/filesystem-unix.c 1812target/hosted/filesystem-unix.c
1813target/hosted/lc-unix.c 1813target/hosted/lc-unix.c
1814#if !defined(DX50) && !defined(DX90)
1814target/hosted/android/lcd-android.c 1815target/hosted/android/lcd-android.c
1815target/hosted/android/button-android.c 1816target/hosted/android/button-android.c
1816#ifdef DEBUG
1817target/hosted/android/debug-android.c
1818#endif
1819target/hosted/android/pcm-android.c 1817target/hosted/android/pcm-android.c
1820target/hosted/android/powermgmt-android.c 1818target/hosted/android/powermgmt-android.c
1821target/hosted/android/system-android.c
1822target/hosted/android/telephony-android.c 1819target/hosted/android/telephony-android.c
1823#ifdef APPLICATION 1820#ifdef APPLICATION
1824target/hosted/android/app/button-application.c 1821target/hosted/android/app/button-application.c
1825#endif 1822#endif
1823#else
1824drivers/lcd-memframe.c
1825target/hosted/android/dx50/pcm-dx50.c
1826target/hosted/android/dx50/tinyalsa/pcm.c
1827target/hosted/android/dx50/powermgmt-dx50.c
1828target/hosted/android/dx50/backlight-dx50.c
1829target/hosted/android/dx50/button-dx50.c
1830target/hosted/android/dx50/lcd-dx50.c
1831#endif
1832#ifdef DEBUG
1833target/hosted/android/debug-android.c
1834#endif
1835target/hosted/android/system-android.c
1826drivers/audio/android.c 1836drivers/audio/android.c
1827#endif 1837#endif
1828 1838
diff --git a/firmware/asm/SOURCES b/firmware/asm/SOURCES
index ebb6951071..f16285e623 100644
--- a/firmware/asm/SOURCES
+++ b/firmware/asm/SOURCES
@@ -14,7 +14,7 @@ mempcpy.c
14#if (defined(SANSA_E200) || defined(GIGABEAT_F) || defined(GIGABEAT_S) || \ 14#if (defined(SANSA_E200) || defined(GIGABEAT_F) || defined(GIGABEAT_S) || \
15 defined(CREATIVE_ZVx) || defined(SANSA_CONNECT) || defined(SANSA_FUZEPLUS) || \ 15 defined(CREATIVE_ZVx) || defined(SANSA_CONNECT) || defined(SANSA_FUZEPLUS) || \
16 defined(COWON_D2) || defined(MINI2440) || defined(SAMSUNG_YPR0) || \ 16 defined(COWON_D2) || defined(MINI2440) || defined(SAMSUNG_YPR0) || \
17 defined(SAMSUNG_YPR1) || (defined(MROBE_500) && !defined(LCD_USE_DMA)) || \ 17 defined(SAMSUNG_YPR1) || defined(DX50) || defined(DX90) || (defined(MROBE_500) && !defined(LCD_USE_DMA)) || \
18 defined(CREATIVE_ZEN) || defined(CREATIVE_ZENXFI)) && \ 18 defined(CREATIVE_ZEN) || defined(CREATIVE_ZENXFI)) && \
19 !defined(SIMULATOR) 19 !defined(SIMULATOR)
20#if LCD_DEPTH == 24 20#if LCD_DEPTH == 24
diff --git a/firmware/asm/arm/thread.h b/firmware/asm/arm/thread.h
index 7b8ebc2041..533a088979 100644
--- a/firmware/asm/arm/thread.h
+++ b/firmware/asm/arm/thread.h
@@ -31,7 +31,11 @@ struct regs
31 31
32#if (CONFIG_PLATFORM & PLATFORM_HOSTED) 32#if (CONFIG_PLATFORM & PLATFORM_HOSTED)
33 #include <errno.h> 33 #include <errno.h>
34#if defined(DX50) || defined (DX90)
35 #define DEFAULT_STACK_SIZE 0x2000 /* Bytes */
36#else
34 #define DEFAULT_STACK_SIZE 0x1000 /* Bytes */ 37 #define DEFAULT_STACK_SIZE 0x1000 /* Bytes */
38#endif
35#else 39#else
36 #define DEFAULT_STACK_SIZE 0x400 /* Bytes */ 40 #define DEFAULT_STACK_SIZE 0x400 /* Bytes */
37#endif 41#endif
diff --git a/firmware/drivers/audio/android.c b/firmware/drivers/audio/android.c
index 7a5f34ea48..f26087470b 100644
--- a/firmware/drivers/audio/android.c
+++ b/firmware/drivers/audio/android.c
@@ -22,12 +22,34 @@
22 22
23#include "config.h" 23#include "config.h"
24#include "audiohw.h" 24#include "audiohw.h"
25#if defined(DX50) || defined(DX90)
26#include "system.h"
27#include "pcm_sw_volume.h"
28#endif
25 29
30#if defined(DX50) || defined(DX90)
31void audiohw_set_volume(int vol_l, int vol_r)
32{
33 int hw_volume;
34 hw_volume = MAX(vol_l, vol_r);
35
36#ifdef HAVE_SW_VOLUME_CONTROL
37 vol_l-=hw_volume;
38 vol_r-=hw_volume;
39 pcm_set_master_volume(vol_l, vol_r);
40#endif
41
42 extern void pcm_set_mixer_volume(int);
43 pcm_set_mixer_volume(hw_volume);
44
45}
46#else
26void audiohw_set_volume(int volume) 47void audiohw_set_volume(int volume)
27{ 48{
28 extern void pcm_set_mixer_volume(int); 49 extern void pcm_set_mixer_volume(int);
29 pcm_set_mixer_volume(volume); 50 pcm_set_mixer_volume(volume);
30} 51}
52#endif
31 53
32void audiohw_set_balance(int balance) 54void audiohw_set_balance(int balance)
33{ 55{
@@ -36,6 +58,8 @@ void audiohw_set_balance(int balance)
36 58
37void audiohw_close(void) 59void audiohw_close(void)
38{ 60{
61#if !defined(DX50) && !defined(DX90)
39 extern void pcm_shutdown(void); 62 extern void pcm_shutdown(void);
40 pcm_shutdown(); 63 pcm_shutdown();
64#endif
41} 65}
diff --git a/firmware/drivers/touchscreen.c b/firmware/drivers/touchscreen.c
index 42ddf7ec47..572f05ab7f 100644
--- a/firmware/drivers/touchscreen.c
+++ b/firmware/drivers/touchscreen.c
@@ -188,7 +188,7 @@ bool touchscreen_is_enabled(void)
188} 188}
189#endif 189#endif
190 190
191#if ((CONFIG_PLATFORM & PLATFORM_ANDROID) == 0) 191#if ((CONFIG_PLATFORM & PLATFORM_ANDROID) == 0) || defined(DX50) || defined(DX90)
192/* android has an API for this */ 192/* android has an API for this */
193 193
194#define TOUCH_SLOP 16u 194#define TOUCH_SLOP 16u
diff --git a/firmware/export/config.h b/firmware/export/config.h
index a56dd32303..bf95dc4c09 100644
--- a/firmware/export/config.h
+++ b/firmware/export/config.h
@@ -164,6 +164,7 @@
164#define IHIFI_PAD 60 164#define IHIFI_PAD 60
165#define SAMSUNG_YPR1_PAD 61 165#define SAMSUNG_YPR1_PAD 61
166#define SAMSUNG_YH920_PAD 62 166#define SAMSUNG_YH920_PAD 62
167#define DX50_PAD 63
167 168
168/* CONFIG_REMOTE_KEYPAD */ 169/* CONFIG_REMOTE_KEYPAD */
169#define H100_REMOTE 1 170#define H100_REMOTE 1
@@ -575,6 +576,10 @@ Lyre prototype 1 */
575#include "config/creativezenxfistyle.h" 576#include "config/creativezenxfistyle.h"
576#elif defined(SAMSUNG_YPR1) 577#elif defined(SAMSUNG_YPR1)
577#include "config/samsungypr1.h" 578#include "config/samsungypr1.h"
579#elif defined(DX50)
580#include "config/ibassodx50.h"
581#elif defined(DX90)
582#include "config/ibassodx90.h"
578#else 583#else
579/* no known platform */ 584/* no known platform */
580#endif 585#endif
diff --git a/firmware/export/config/ibassodx50.h b/firmware/export/config/ibassodx50.h
new file mode 100644
index 0000000000..652377cc6c
--- /dev/null
+++ b/firmware/export/config/ibassodx50.h
@@ -0,0 +1,136 @@
1/*
2 * This config file is for Rockbox as an application on Android
3 */
4
5/* We don't run on hardware directly */
6#define CONFIG_PLATFORM (PLATFORM_HOSTED|PLATFORM_ANDROID)
7
8/* For Rolo and boot loader */
9#define MODEL_NUMBER 94
10
11#define MODEL_NAME "iBasso DX50"
12
13#define USB_NONE
14
15/* define this if you have a bitmap LCD display */
16#define HAVE_LCD_BITMAP
17
18/* define this if you have a colour LCD */
19#define HAVE_LCD_COLOR
20
21/* define this if you want album art for this target */
22#define HAVE_ALBUMART
23
24/* define this to enable bitmap scaling */
25#define HAVE_BMP_SCALING
26
27/* define this to enable JPEG decoding */
28#define HAVE_JPEG
29
30/* define this if you have access to the quickscreen */
31#define HAVE_QUICKSCREEN
32
33/* define this if you would like tagcache to build on this target */
34#define HAVE_TAGCACHE
35
36/* LCD dimensions */
37#define LCD_WIDTH 320
38#define LCD_HEIGHT 240
39#define LCD_DPI 166
40#define LCD_DEPTH 16
41#define LCD_PIXELFORMAT RGB565
42
43#define HAVE_LCD_ENABLE
44
45/* define this to indicate your device's keypad */
46#define HAVE_TOUCHSCREEN
47#define HAVE_BUTTON_DATA
48
49/* define this if you have RTC RAM available for settings */
50//#define HAVE_RTC_RAM
51
52/* define this if you have a real-time clock */
53//#define CONFIG_RTC APPLICATION
54
55/* Define this if you have a software controlled poweroff */
56#define HAVE_SW_POWEROFF
57
58/* The number of bytes reserved for loadable codecs */
59#define CODEC_SIZE 0x100000
60
61/* The number of bytes reserved for loadable plugins */
62#define PLUGIN_BUFFER_SIZE 0x160000
63
64#define AB_REPEAT_ENABLE
65
66/* Define this for LCD backlight available */
67#define HAVE_BACKLIGHT
68#define HAVE_BACKLIGHT_BRIGHTNESS
69
70/* Main LCD backlight brightness range and defaults */
71#define MIN_BRIGHTNESS_SETTING 4
72#define MAX_BRIGHTNESS_SETTING 255
73#define DEFAULT_BRIGHTNESS_SETTING 255
74
75/* Which backlight fading type? */
76#define CONFIG_BACKLIGHT_FADING BACKLIGHT_FADING_SW_SETTING
77
78/* Define this if you do software codec */
79#define CONFIG_CODEC SWCODEC
80
81//#define HAVE_MULTIMEDIA_KEYS
82#define CONFIG_KEYPAD DX50_PAD
83
84/* define this if the target has volume keys which can be used in the lists */
85#define HAVE_VOLUME_IN_LIST
86
87/* define this if the host platform can change volume outside of rockbox */
88//#define PLATFORM_HAS_VOLUME_CHANGE
89
90#define HAVE_SW_TONE_CONTROLS
91
92#define HAVE_SW_VOLUME_CONTROL
93
94#define BATTERY_CAPACITY_DEFAULT 2100 /* default battery capacity */
95#define BATTERY_CAPACITY_MIN 1700 /* min. capacity selectable */
96#define BATTERY_CAPACITY_MAX 3200 /* max. capacity selectable */
97#define BATTERY_CAPACITY_INC 50 /* capacity increment */
98#define BATTERY_TYPES_COUNT 1 /* only one type */
99
100#define CONFIG_BATTERY_MEASURE VOLTAGE_MEASURE
101
102#define CONFIG_CHARGING CHARGING_SIMPLE
103
104#define NO_LOW_BATTERY_SHUTDOWN
105
106/* Define current usage levels. */
107#define CURRENT_NORMAL 210 /* 10 hours from a 2100 mAh battery */
108#define CURRENT_BACKLIGHT 30 /* TBD */
109#define CURRENT_RECORD 0 /* no recording */
110
111/* Define this to the CPU frequency */
112/*
113#define CPU_FREQ 48000000
114*/
115
116/* define this if the hardware can be powered off while charging */
117#define HAVE_POWEROFF_WHILE_CHARGING
118
119
120/* Offset ( in the firmware file's header ) to the file CRC */
121#define FIRMWARE_OFFSET_FILE_CRC 0
122
123/* Offset ( in the firmware file's header ) to the real data */
124#define FIRMWARE_OFFSET_FILE_DATA 8
125
126#define CONFIG_LCD LCD_COWOND2
127
128/* Define this if a programmable hotkey is mapped */
129#define HAVE_HOTKEY
130
131#define BOOTDIR "/.rockbox"
132
133/* No special storage */
134#define CONFIG_STORAGE STORAGE_HOSTFS
135#define HAVE_STORAGE_FLUSH
136
diff --git a/firmware/export/config/ibassodx90.h b/firmware/export/config/ibassodx90.h
new file mode 100644
index 0000000000..d560f3e10b
--- /dev/null
+++ b/firmware/export/config/ibassodx90.h
@@ -0,0 +1,136 @@
1/*
2 * This config file is for Rockbox as an application on Android
3 */
4
5/* We don't run on hardware directly */
6#define CONFIG_PLATFORM (PLATFORM_HOSTED|PLATFORM_ANDROID)
7
8/* For Rolo and boot loader */
9#define MODEL_NUMBER 95
10
11#define MODEL_NAME "iBasso DX90"
12
13#define USB_NONE
14
15/* define this if you have a bitmap LCD display */
16#define HAVE_LCD_BITMAP
17
18/* define this if you have a colour LCD */
19#define HAVE_LCD_COLOR
20
21/* define this if you want album art for this target */
22#define HAVE_ALBUMART
23
24/* define this to enable bitmap scaling */
25#define HAVE_BMP_SCALING
26
27/* define this to enable JPEG decoding */
28#define HAVE_JPEG
29
30/* define this if you have access to the quickscreen */
31#define HAVE_QUICKSCREEN
32
33/* define this if you would like tagcache to build on this target */
34#define HAVE_TAGCACHE
35
36/* LCD dimensions */
37#define LCD_WIDTH 320
38#define LCD_HEIGHT 240
39#define LCD_DPI 166
40#define LCD_DEPTH 16
41#define LCD_PIXELFORMAT RGB565
42
43#define HAVE_LCD_ENABLE
44
45/* define this to indicate your device's keypad */
46#define HAVE_TOUCHSCREEN
47#define HAVE_BUTTON_DATA
48
49/* define this if you have RTC RAM available for settings */
50//#define HAVE_RTC_RAM
51
52/* define this if you have a real-time clock */
53//#define CONFIG_RTC APPLICATION
54
55/* Define this if you have a software controlled poweroff */
56#define HAVE_SW_POWEROFF
57
58/* The number of bytes reserved for loadable codecs */
59#define CODEC_SIZE 0x100000
60
61/* The number of bytes reserved for loadable plugins */
62#define PLUGIN_BUFFER_SIZE 0x160000
63
64#define AB_REPEAT_ENABLE
65
66/* Define this for LCD backlight available */
67#define HAVE_BACKLIGHT
68#define HAVE_BACKLIGHT_BRIGHTNESS
69
70/* Main LCD backlight brightness range and defaults */
71#define MIN_BRIGHTNESS_SETTING 4
72#define MAX_BRIGHTNESS_SETTING 255
73#define DEFAULT_BRIGHTNESS_SETTING 255
74
75/* Which backlight fading type? */
76#define CONFIG_BACKLIGHT_FADING BACKLIGHT_FADING_SW_SETTING
77
78/* Define this if you do software codec */
79#define CONFIG_CODEC SWCODEC
80
81//#define HAVE_MULTIMEDIA_KEYS
82#define CONFIG_KEYPAD DX50_PAD
83
84/* define this if the target has volume keys which can be used in the lists */
85#define HAVE_VOLUME_IN_LIST
86
87/* define this if the host platform can change volume outside of rockbox */
88//#define PLATFORM_HAS_VOLUME_CHANGE
89
90#define HAVE_SW_TONE_CONTROLS
91
92#define HAVE_SW_VOLUME_CONTROL
93
94#define BATTERY_CAPACITY_DEFAULT 2100 /* default battery capacity */
95#define BATTERY_CAPACITY_MIN 1700 /* min. capacity selectable */
96#define BATTERY_CAPACITY_MAX 3200 /* max. capacity selectable */
97#define BATTERY_CAPACITY_INC 50 /* capacity increment */
98#define BATTERY_TYPES_COUNT 1 /* only one type */
99
100#define CONFIG_BATTERY_MEASURE VOLTAGE_MEASURE
101
102#define CONFIG_CHARGING CHARGING_SIMPLE
103
104#define NO_LOW_BATTERY_SHUTDOWN
105
106/* Define current usage levels. */
107#define CURRENT_NORMAL 210 /* 10 hours from a 2100 mAh battery */
108#define CURRENT_BACKLIGHT 30 /* TBD */
109#define CURRENT_RECORD 0 /* no recording */
110
111/* Define this to the CPU frequency */
112/*
113#define CPU_FREQ 48000000
114*/
115
116/* define this if the hardware can be powered off while charging */
117#define HAVE_POWEROFF_WHILE_CHARGING
118
119
120/* Offset ( in the firmware file's header ) to the file CRC */
121#define FIRMWARE_OFFSET_FILE_CRC 0
122
123/* Offset ( in the firmware file's header ) to the real data */
124#define FIRMWARE_OFFSET_FILE_DATA 8
125
126#define CONFIG_LCD LCD_COWOND2
127
128/* Define this if a programmable hotkey is mapped */
129#define HAVE_HOTKEY
130
131#define BOOTDIR "/.rockbox"
132
133/* No special storage */
134#define CONFIG_STORAGE STORAGE_HOSTFS
135#define HAVE_STORAGE_FLUSH
136
diff --git a/firmware/export/hosted_codec.h b/firmware/export/hosted_codec.h
index f5e92ed297..00ab099772 100644
--- a/firmware/export/hosted_codec.h
+++ b/firmware/export/hosted_codec.h
@@ -25,7 +25,9 @@
25 && !(CONFIG_PLATFORM & PLATFORM_MAEMO5) 25 && !(CONFIG_PLATFORM & PLATFORM_MAEMO5)
26AUDIOHW_SETTING(VOLUME, "dB", 0, 1, -80, 0, 0) 26AUDIOHW_SETTING(VOLUME, "dB", 0, 1, -80, 0, 0)
27#else 27#else
28#if !defined(DX50) && !defined(DX90)
28#define AUDIOHW_CAPS (MONO_VOL_CAP) 29#define AUDIOHW_CAPS (MONO_VOL_CAP)
30#endif
29AUDIOHW_SETTING(VOLUME, "dB", 0, 1, -99, 0, 0) 31AUDIOHW_SETTING(VOLUME, "dB", 0, 1, -99, 0, 0)
30#endif /* CONFIG_PLATFORM & PLATFORM_SDL */ 32#endif /* CONFIG_PLATFORM & PLATFORM_SDL */
31 33
@@ -50,4 +52,4 @@ AUDIOHW_SETTING(TREBLE_CUTOFF, "", 0, 1, 1, 4, 1)
50#endif 52#endif
51#endif /* CONFIG_PLATFORM & PLATFORM_ANDROID */ 53#endif /* CONFIG_PLATFORM & PLATFORM_ANDROID */
52 54
53#endif /* HOSTED_CODEC_H */ \ No newline at end of file 55#endif /* HOSTED_CODEC_H */
diff --git a/firmware/powermgmt.c b/firmware/powermgmt.c
index b6d4b9f66e..a4b260b315 100644
--- a/firmware/powermgmt.c
+++ b/firmware/powermgmt.c
@@ -679,6 +679,8 @@ static void power_thread(void)
679 /* Delay reading the first battery level */ 679 /* Delay reading the first battery level */
680#ifdef MROBE_100 680#ifdef MROBE_100
681 while (_battery_voltage() > 4200) /* gives false readings initially */ 681 while (_battery_voltage() > 4200) /* gives false readings initially */
682#elif defined(DX50) || defined(DX90)
683 while (_battery_voltage() < 1) /* can give false readings initially */
682#endif 684#endif
683 { 685 {
684 sleep(HZ/100); 686 sleep(HZ/100);
diff --git a/firmware/target/hosted/android/dx50/adc-target.h b/firmware/target/hosted/android/dx50/adc-target.h
new file mode 100644
index 0000000000..e69de29bb2
--- /dev/null
+++ b/firmware/target/hosted/android/dx50/adc-target.h
diff --git a/firmware/target/hosted/android/dx50/backlight-dx50.c b/firmware/target/hosted/android/dx50/backlight-dx50.c
new file mode 100644
index 0000000000..98dbcb8abe
--- /dev/null
+++ b/firmware/target/hosted/android/dx50/backlight-dx50.c
@@ -0,0 +1,76 @@
1/***************************************************************************
2 * __________ __ ___.
3 * Open \______ \ ____ ____ | | _\_ |__ _______ ___
4 * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
5 * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
6 * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
7 * \/ \/ \/ \/ \/
8 *
9 * Copyright (C) 2011 by Lorenzo Miori
10 *
11 * This program is free software; you can redistribute it and/or
12 * modify it under the terms of the GNU General Public License
13 * as published by the Free Software Foundation; either version 2
14 * of the License, or (at your option) any later version.
15 *
16 * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
17 * KIND, either express or implied.
18 *
19 ****************************************************************************/
20#include "config.h"
21#include "system.h"
22#include "backlight.h"
23#include "backlight-target.h"
24#include "lcd.h"
25#include "lcd-target.h"
26#include <fcntl.h>
27#include <stdio.h>
28#include "unistd.h"
29
30bool _backlight_init(void)
31{
32 /* We have nothing to do */
33 return true;
34}
35
36void _backlight_on(void)
37{
38 FILE *f = fopen("/sys/power/state", "w");
39 fputs("on", f);
40 fclose(f);
41 lcd_enable(true);
42}
43
44void _backlight_off(void)
45{
46 FILE * f;
47
48 /* deny the player to sleep deep */
49 f = fopen("/sys/power/wake_lock", "w");
50 fputs("player", f);
51 fclose(f);
52
53 /* deny the player to mute */
54 f = fopen("/sys/class/codec/wm8740_mute", "w");
55 fputc(0, f);
56 fclose(f);
57
58 /* turn off backlight */
59 f = fopen("/sys/power/state", "w");
60 fputs("mem", f);
61 fclose(f);
62
63}
64
65void _backlight_set_brightness(int brightness)
66{
67 /* Just another check... */
68 if (brightness > MAX_BRIGHTNESS_SETTING)
69 brightness = MAX_BRIGHTNESS_SETTING;
70 if (brightness < MIN_BRIGHTNESS_SETTING)
71 brightness = MIN_BRIGHTNESS_SETTING;
72
73 FILE *f = fopen("/sys/devices/platform/rk29_backlight/backlight/rk28_bl/brightness", "w");
74 fprintf(f, "%d", brightness);
75 fclose(f);
76}
diff --git a/firmware/target/hosted/android/dx50/backlight-target.h b/firmware/target/hosted/android/dx50/backlight-target.h
new file mode 100644
index 0000000000..67836aa790
--- /dev/null
+++ b/firmware/target/hosted/android/dx50/backlight-target.h
@@ -0,0 +1,31 @@
1/***************************************************************************
2 * __________ __ ___.
3 * Open \______ \ ____ ____ | | _\_ |__ _______ ___
4 * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
5 * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
6 * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
7 * \/ \/ \/ \/ \/
8 * $Id$
9 *
10 * Copyright (C) 2008 by Maurus Cuelenaere
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#include <stdbool.h>
25
26bool _backlight_init(void);
27void _backlight_on(void);
28void _backlight_off(void);
29void _backlight_set_brightness(int brightness);
30
31#endif /* BACKLIGHT_TARGET_H */
diff --git a/firmware/target/hosted/android/dx50/button-dx50.c b/firmware/target/hosted/android/dx50/button-dx50.c
new file mode 100644
index 0000000000..5ab58ce420
--- /dev/null
+++ b/firmware/target/hosted/android/dx50/button-dx50.c
@@ -0,0 +1,314 @@
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 <stdbool.h>
24#include "button.h"
25#include "buttonmap.h"
26#include "config.h"
27#include "kernel.h"
28#include "system.h"
29#include "touchscreen.h"
30#include "powermgmt.h"
31#include "backlight.h"
32
33#include <linux/input.h>
34#include <stdio.h>
35#include <stdlib.h>
36#include <string.h>
37#include <stdint.h>
38#include <dirent.h>
39#include <fcntl.h>
40#include <sys/ioctl.h>
41#include <sys/inotify.h>
42#include <sys/limits.h>
43#include <sys/poll.h>
44#include <errno.h>
45
46
47static struct pollfd *ufds;
48static char **device_names;
49static int nfds;
50
51enum {
52 PRINT_DEVICE_ERRORS = 1U << 0,
53 PRINT_DEVICE = 1U << 1,
54 PRINT_DEVICE_NAME = 1U << 2,
55 PRINT_DEVICE_INFO = 1U << 3,
56 PRINT_VERSION = 1U << 4,
57 PRINT_POSSIBLE_EVENTS = 1U << 5,
58 PRINT_INPUT_PROPS = 1U << 6,
59 PRINT_HID_DESCRIPTOR = 1U << 7,
60
61 PRINT_ALL_INFO = (1U << 8) - 1,
62
63 PRINT_LABELS = 1U << 16,
64};
65
66static int last_y, last_x;
67static int last_btns;
68
69static enum {
70 STATE_UNKNOWN,
71 STATE_UP,
72 STATE_DOWN
73} last_touch_state = STATE_UNKNOWN;
74
75
76static int open_device(const char *device, int print_flags)
77{
78 int fd;
79 struct pollfd *new_ufds;
80 char **new_device_names;
81
82 fd = open(device, O_RDWR);
83 if(fd < 0) {
84 if(print_flags & PRINT_DEVICE_ERRORS)
85 fprintf(stderr, "could not open %s, %s\n", device, strerror(errno));
86 return -1;
87 }
88
89 new_ufds = realloc(ufds, sizeof(ufds[0]) * (nfds + 1));
90 if(new_ufds == NULL) {
91 fprintf(stderr, "out of memory\n");
92 return -1;
93 }
94 ufds = new_ufds;
95 new_device_names = realloc(device_names, sizeof(device_names[0]) * (nfds + 1));
96 if(new_device_names == NULL) {
97 fprintf(stderr, "out of memory\n");
98 return -1;
99 }
100 device_names = new_device_names;
101
102 ufds[nfds].fd = fd;
103 ufds[nfds].events = POLLIN;
104 device_names[nfds] = strdup(device);
105 nfds++;
106
107 return 0;
108}
109
110
111
112static int scan_dir(const char *dirname, int print_flags)
113{
114 char devname[PATH_MAX];
115 char *filename;
116 DIR *dir;
117 struct dirent *de;
118 dir = opendir(dirname);
119 if(dir == NULL)
120 return -1;
121 strcpy(devname, dirname);
122 filename = devname + strlen(devname);
123 *filename++ = '/';
124 while((de = readdir(dir))) {
125 if(de->d_name[0] == '.' &&
126 (de->d_name[1] == '\0' ||
127 (de->d_name[1] == '.' && de->d_name[2] == '\0')))
128 continue;
129 strcpy(filename, de->d_name);
130 open_device(devname, print_flags);
131 }
132 closedir(dir);
133 return 0;
134}
135
136bool _hold;
137
138bool button_hold()
139{
140 FILE *f = fopen("/sys/class/axppower/holdkey", "r");
141 char x;
142 fscanf(f, "%c", &x);
143 fclose(f);
144 _hold = !(x&STATE_UNLOCKED);
145 return _hold;
146}
147
148
149void button_init_device(void)
150{
151 int res;
152 int print_flags = 0;
153 const char *device = NULL;
154 const char *device_path = "/dev/input";
155
156 nfds = 1;
157 ufds = calloc(1, sizeof(ufds[0]));
158 ufds[0].fd = inotify_init();
159 ufds[0].events = POLLIN;
160 if(device) {
161 res = open_device(device, print_flags);
162 if(res < 0) {
163 // return 1;
164 }
165 } else {
166 res = inotify_add_watch(ufds[0].fd, device_path, IN_DELETE | IN_CREATE);
167 if(res < 0) {
168 fprintf(stderr, "could not add watch for %s, %s\n", device_path, strerror(errno));
169 // return 1;
170 }
171 res = scan_dir(device_path, print_flags);
172 if(res < 0) {
173 fprintf(stderr, "scan dir failed for %s\n", device_path);
174 // return 1;
175 }
176 }
177
178 button_hold(); //store state
179
180 set_rockbox_ready();
181}
182
183void touchscreen_enable_device(bool en)
184{
185 (void)en; /* FIXME: do something smart */
186}
187
188
189int keycode_to_button(int keyboard_key)
190{
191 switch(keyboard_key){
192 case KEYCODE_PWR:
193 return BUTTON_POWER;
194
195 case KEYCODE_PWR_LONG:
196 return BUTTON_POWER_LONG;
197
198 case KEYCODE_VOLPLUS:
199 return BUTTON_VOL_UP;
200
201 case KEYCODE_VOLMINUS:
202 return BUTTON_VOL_DOWN;
203
204 case KEYCODE_PREV:
205 return BUTTON_LEFT;
206
207 case KEYCODE_NEXT:
208 return BUTTON_RIGHT;
209
210 case KEYCODE_PLAY:
211 return BUTTON_PLAY;
212
213 case KEYCODE_HOLD:
214 button_hold(); /* store state */
215 backlight_hold_changed(_hold);
216 return BUTTON_NONE;
217
218 default:
219 return BUTTON_NONE;
220 }
221}
222
223
224int button_read_device(int *data)
225{
226 int i;
227 int res;
228 struct input_event event;
229 int read_more;
230 unsigned button = 0;
231
232 if(last_btns & BUTTON_POWER_LONG)
233 {
234 return last_btns; /* simulate repeat */
235 }
236
237 do {
238 read_more = 0;
239 poll(ufds, nfds, 10);
240 for(i = 1; i < nfds; i++) {
241 if(ufds[i].revents & POLLIN) {
242 res = read(ufds[i].fd, &event, sizeof(event));
243 if(res < (int)sizeof(event)) {
244 fprintf(stderr, "could not get event\n");
245 }
246
247 switch(event.type)
248 {
249 case 1: /* HW-Button */
250 button = keycode_to_button(event.code);
251 if (_hold) /* we have to wait for keycode_to_button() first to maybe clear hold state */
252 break;
253 if (button == BUTTON_NONE)
254 {
255 last_btns = button;
256 break;
257 }
258/* workaround for a wrong feedback, only present with DX90 */
259#if defined(DX90)
260 if (button == BUTTON_RIGHT && (last_btns & BUTTON_LEFT == BUTTON_LEFT) && !event.value)
261 {
262 button = BUTTON_LEFT;
263 }
264#endif
265 if (event.value)
266 last_btns |= button;
267 else
268 last_btns &= (~button);
269
270 break;
271
272 case 3: /* Touchscreen */
273 if(_hold)
274 break;
275
276 switch(event.code)
277 {
278 case 53: /* x -> next will be y */
279 last_x = event.value;
280 read_more = 1;
281 break;
282 case 54: /* y */
283 last_y = event.value;
284 break;
285 case 57: /* press -> next will be x */
286 if(event.value==1)
287 {
288 last_touch_state = STATE_DOWN;
289 read_more = 1;
290 }
291 else
292 last_touch_state = STATE_UP;
293 break;
294 }
295 break;
296 }
297 }
298 }
299 } while(read_more);
300
301
302 /* Get grid button/coordinates based on the current touchscreen mode
303 *
304 * Caveat: the caller seemingly depends on *data always being filled with
305 * the last known touchscreen position, so always call
306 * touchscreen_to_pixels() */
307 int touch = touchscreen_to_pixels(last_x, last_y, data);
308
309 if (last_touch_state == STATE_DOWN)
310 return last_btns | touch;
311
312 return last_btns;
313}
314
diff --git a/firmware/target/hosted/android/dx50/button-target.h b/firmware/target/hosted/android/dx50/button-target.h
new file mode 100644
index 0000000000..adc9cf6bfd
--- /dev/null
+++ b/firmware/target/hosted/android/dx50/button-target.h
@@ -0,0 +1,72 @@
1/***************************************************************************
2 * __________ __ ___.
3 * Open \______ \ ____ ____ | | _\_ |__ _______ ___
4 * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
5 * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
6 * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
7 * \/ \/ \/ \/ \/
8 * $Id$
9 *
10 * Copyright (C) 2007 by Rob Purchase
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.r
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
27#define HAS_BUTTON_HOLD
28
29/* Main unit's buttons */
30#define BUTTON_LEFT 0x00000001
31#define BUTTON_RIGHT 0x00000002
32#define BUTTON_PLAY 0x00000004
33#define BUTTON_POWER 0x00000008
34#define BUTTON_VOL_UP 0x00000010
35#define BUTTON_VOL_DOWN 0x00000020
36#define BUTTON_POWER_LONG 0x00000040
37
38#define BUTTON_MAIN (BUTTON_LEFT|BUTTON_VOL_UP|BUTTON_VOL_DOWN\
39 |BUTTON_RIGHT|BUTTON_PLAY|BUTTON_POWER|BUTTON_POWER_LONG)
40
41#define KEYCODE_LINEOUT 113
42#define KEYCODE_SPDIF 114
43#define KEYCODE_HOLD 115
44#define KEYCODE_PWR 116
45#define KEYCODE_PWR_LONG 117
46#define KEYCODE_SD 143
47#define KEYCODE_VOLPLUS 158
48#define KEYCODE_VOLMINUS 159
49#define KEYCODE_PREV 160
50#define KEYCODE_NEXT 162
51#define KEYCODE_PLAY 161
52#define STATE_UNLOCKED 16
53#define STATE_SPDIF_UNPLUGGED 32
54#define STATE_LINEOUT_UNPLUGGED 64
55
56/* Touch Screen Area Buttons */
57#define BUTTON_TOPLEFT 0x00001000
58#define BUTTON_TOPMIDDLE 0x00002000
59#define BUTTON_TOPRIGHT 0x00004000
60#define BUTTON_MIDLEFT 0x00008000
61#define BUTTON_CENTER 0x00010000
62#define BUTTON_MIDRIGHT 0x00020000
63#define BUTTON_BOTTOMLEFT 0x00040000
64#define BUTTON_BOTTOMMIDDLE 0x00080000
65#define BUTTON_BOTTOMRIGHT 0x00100000
66
67
68/* Software power-off */
69#define POWEROFF_BUTTON BUTTON_POWER_LONG
70#define POWEROFF_COUNT 0
71
72#endif /* _BUTTON_TARGET_H_ */
diff --git a/firmware/target/hosted/android/dx50/lcd-dx50.c b/firmware/target/hosted/android/dx50/lcd-dx50.c
new file mode 100644
index 0000000000..4d78baaf00
--- /dev/null
+++ b/firmware/target/hosted/android/dx50/lcd-dx50.c
@@ -0,0 +1,120 @@
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 * Copyright (C) 2013 Lorenzo Miori
12 *
13 * This program is free software; you can redistribute it and/or
14 * modify it under the terms of the GNU General Public License
15 * as published by the Free Software Foundation; either version 2
16 * of the License, or (at your option) any later version.
17 *
18 * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
19 * KIND, either express or implied.
20 *
21 ****************************************************************************/
22
23#include <stdlib.h>
24#include <unistd.h>
25#include <stdio.h>
26#include <linux/fb.h>
27#include <sys/mman.h>
28#include <sys/ioctl.h>
29#include "config.h"
30#include "file.h"
31#include "debug.h"
32#include "system.h"
33#include "screendump.h"
34#include "lcd.h"
35#include "lcd-target.h"
36
37static int dev_fd = 0;
38fb_data *dev_fb = 0;
39
40#ifdef HAVE_LCD_SHUTDOWN
41void lcd_shutdown(void)
42{
43 printf("FB closed.");
44 munmap(dev_fb, FRAMEBUFFER_SIZE);
45 close(dev_fd);
46}
47#endif
48
49void lcd_init_device(void)
50{
51 size_t screensize;
52 struct fb_var_screeninfo vinfo;
53 struct fb_fix_screeninfo finfo;
54
55 /* Open the framebuffer device */
56 dev_fd = open("/dev/graphics/fb0", O_RDWR);
57 if (dev_fd == -1) {
58 perror("Error: cannot open framebuffer device");
59 exit(1);
60 }
61
62 /* Get the fixed properties */
63 if (ioctl(dev_fd, FBIOGET_FSCREENINFO, &finfo) == -1) {
64 perror("Error reading fixed information");
65 exit(2);
66 }
67
68
69 /* Now we get the settable settings, and we set 16 bit bpp */
70 if (ioctl(dev_fd, FBIOGET_VSCREENINFO, &vinfo) == -1) {
71 perror("Error reading variable information");
72 exit(3);
73 }
74 /* framebuffer does not fit the screen, a bug of iBassos Firmware, not rockbox.
75 cannot be solved with parameters */
76 vinfo.bits_per_pixel = LCD_DEPTH;
77 vinfo.xres = vinfo.xres_virtual = vinfo.width = LCD_WIDTH;
78 vinfo.yres = vinfo.yres_virtual = vinfo.height = LCD_HEIGHT;
79
80 if (ioctl(dev_fd, FBIOPUT_VSCREENINFO, &vinfo)) {
81 perror("fbset(ioctl)");
82 exit(4);
83 }
84
85 /* Figure out the size of the screen in bytes */
86 screensize = vinfo.xres * vinfo.yres * vinfo.bits_per_pixel / 8;
87 if (screensize != FRAMEBUFFER_SIZE) {
88 exit(4);
89 perror("Display and framebuffer mismatch!\n");
90 }
91
92 /* Map the device to memory */
93 dev_fb = mmap(0, screensize, PROT_READ | PROT_WRITE, MAP_SHARED, dev_fd, 0);
94 if ((int)dev_fb == -1) {
95 perror("Error: failed to map framebuffer device to memory");
96 exit(4);
97 }
98
99 /* Be sure to turn on display at startup */
100 ioctl(dev_fd, FBIOBLANK, VESA_NO_BLANKING);
101#ifdef HAVE_LCD_ENABLE
102 lcd_set_active(true);
103#endif
104}
105
106#ifdef HAVE_LCD_ENABLE
107void lcd_enable(bool enable)
108 {
109 if (lcd_active() == enable)
110 return;
111
112 lcd_set_active(enable);
113
114 /* Turn on or off the display using Linux interface */
115 ioctl(dev_fd, FBIOBLANK, enable ? VESA_NO_BLANKING : VESA_POWERDOWN);
116
117 if (enable)
118 send_event(LCD_EVENT_ACTIVATION, NULL);
119}
120#endif
diff --git a/firmware/target/hosted/android/dx50/lcd-target.h b/firmware/target/hosted/android/dx50/lcd-target.h
new file mode 100644
index 0000000000..900350eca2
--- /dev/null
+++ b/firmware/target/hosted/android/dx50/lcd-target.h
@@ -0,0 +1,29 @@
1/***************************************************************************
2 * __________ __ ___.
3 * Open \______ \ ____ ____ | | _\_ |__ _______ ___
4 * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
5 * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
6 * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
7 * \/ \/ \/ \/ \/
8 * $Id$
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
20#ifndef __LCD_TARGET_H__
21#define __LCD_TARGET_H__
22
23extern fb_data *dev_fb;
24#define LCD_FRAMEBUF_ADDR(col, row) (dev_fb + row*LCD_WIDTH + col)
25#ifdef HAVE_LCD_ENABLE
26extern void lcd_set_active(bool active);
27extern void lcd_enable(bool enable);
28#endif
29#endif
diff --git a/firmware/target/hosted/android/dx50/pcm-dx50.c b/firmware/target/hosted/android/dx50/pcm-dx50.c
new file mode 100644
index 0000000000..e7695873a0
--- /dev/null
+++ b/firmware/target/hosted/android/dx50/pcm-dx50.c
@@ -0,0 +1,364 @@
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 * To make the async callback safer, an alternative stack is installed, since
31 * it's run from a signal hanlder (which otherwise uses the user stack). If
32 * tick tasks are run from a signal handler too, please install
33 * an alternative stack for it too.
34 *
35 * TODO: Rewrite this to do it properly with multithreading
36 *
37 * Alternatively, a version using polling in a tick task is provided. While
38 * supposedly safer, it appears to use more CPU (however I didn't measure it
39 * accurately, only looked at htop). At least, in this mode the "default"
40 * device works which doesnt break with other apps running.
41 */
42
43
44#include "autoconf.h"
45
46#include <stdlib.h>
47#include <stdbool.h>
48#include <stdio.h>
49#include <errno.h>
50#include "tinyalsa/asoundlib.h"
51#include "tinyalsa/asound.h"
52#include "system.h"
53#include "debug.h"
54#include "kernel.h"
55
56#include "pcm.h"
57#include "pcm-internal.h"
58#include "pcm_mixer.h"
59#include "pcm_sampr.h"
60#include "audiohw.h"
61
62#include <pthread.h>
63#include <signal.h>
64
65static const snd_pcm_format_t format = PCM_FORMAT_S16_LE; /* sample format */
66static const int channels = 2; /* count of channels */
67static unsigned int rate = 44100; /* stream rate */
68
69typedef struct pcm snd_pcm_t;
70static snd_pcm_t *handle;
71struct pcm_config config;
72
73static snd_pcm_sframes_t period_size = 512; /* if set to >= 1024, all timers become even slower */
74static char *frames;
75
76static const void *pcm_data = 0;
77static size_t pcm_size = 0;
78
79static int recursion;
80
81static int set_hwparams(snd_pcm_t *handle)
82{
83 int err;
84 if (!frames)
85 frames = malloc(pcm_frames_to_bytes(handle, pcm_get_buffer_size(handle)));
86 err = 0; /* success */
87 return err;
88}
89
90
91/* copy pcm samples to a spare buffer, suitable for snd_pcm_writei() */
92static bool fill_frames(void)
93{
94 size_t copy_n, frames_left = period_size;
95 bool new_buffer = false;
96
97 while (frames_left > 0)
98 {
99 if (!pcm_size)
100 {
101 new_buffer = true;
102 if (!pcm_play_dma_complete_callback(PCM_DMAST_OK, &pcm_data,
103 &pcm_size))
104 {
105 return false;
106 }
107 }
108 copy_n = MIN((size_t)pcm_size, pcm_frames_to_bytes(handle, frames_left));
109 memcpy(&frames[pcm_frames_to_bytes(handle, period_size-frames_left)], pcm_data, copy_n);
110
111 pcm_data += copy_n;
112 pcm_size -= copy_n;
113 frames_left -= pcm_bytes_to_frames(handle, copy_n);
114
115 if (new_buffer)
116 {
117 new_buffer = false;
118 pcm_play_dma_status_callback(PCM_DMAST_STARTED);
119 }
120 }
121 return true;
122}
123
124
125static void pcm_tick(void)
126{
127 if (fill_frames())
128 {
129 if (pcm_write(handle, frames, pcm_frames_to_bytes(handle, period_size))) {
130 printf("Error playing sample\n");
131 return;//break;
132 }
133
134 }
135 else
136 {
137 DEBUGF("%s: No Data.\n", __func__);
138 return;//break;
139 }
140}
141
142static int async_rw(snd_pcm_t *handle)
143{
144 int err;
145 snd_pcm_sframes_t sample_size;
146 char *samples;
147
148 /* fill buffer with silence to initiate playback without noisy click */
149 sample_size = pcm_frames_to_bytes(handle, pcm_get_buffer_size(handle));
150 samples = malloc(sample_size);
151
152 memset(samples, 0, sample_size);
153
154 err = pcm_write(handle, samples, sample_size);
155 free(samples);
156
157 if (err != 0)
158 {
159 DEBUGF("Initial write error: %d\n", err);
160 return err;
161 }
162 if (pcm_state(handle) == PCM_STATE_PREPARED)
163 {
164 err = pcm_start(handle);
165 if (err < 0)
166 {
167 DEBUGF("Start error: %d\n", err);
168 return err;
169 }
170 }
171 return 0;
172}
173
174void cleanup(void)
175{
176 free(frames);
177 frames = NULL;
178 pcm_close(handle);
179}
180
181void pcm_play_dma_init(void)
182{
183 config.channels = channels;
184 config.rate = rate;
185 config.period_size = period_size;
186 config.period_count = 4;
187 config.format = format;
188 config.start_threshold = 0;
189 config.stop_threshold = 0;
190 config.silence_threshold = 0;
191
192
193 handle = pcm_open(0, 0, PCM_OUT, &config);
194 if (!handle || !pcm_is_ready(handle)) {
195 printf("Unable to open PCM device: %s\n", pcm_get_error(handle));
196 return;
197 }
198
199 pcm_dma_apply_settings();
200
201 tick_add_task(pcm_tick);
202
203 atexit(cleanup);
204 return;
205}
206
207
208void pcm_play_lock(void)
209{
210 if (recursion++ == 0)
211 tick_remove_task(pcm_tick);
212}
213
214void pcm_play_unlock(void)
215{
216 if (--recursion == 0)
217 tick_add_task(pcm_tick);
218}
219
220static void pcm_dma_apply_settings_nolock(void)
221{
222 set_hwparams(handle);
223}
224
225void pcm_dma_apply_settings(void)
226{
227 pcm_play_lock();
228 pcm_dma_apply_settings_nolock();
229 pcm_play_unlock();
230}
231
232
233void pcm_play_dma_pause(bool pause)
234{
235 (void)pause;
236}
237
238
239void pcm_play_dma_stop(void)
240{
241 pcm_stop(handle);
242}
243
244void pcm_play_dma_start(const void *addr, size_t size)
245{
246#if defined(DX50) || defined(DX90)
247 /* headphone output relay: if this is done at startup already, a loud click is audible on headphones. Here, some time later,
248 the output caps are charged a bit and the click is much softer */
249 system("/system/bin/muteopen");
250#endif
251 pcm_dma_apply_settings_nolock();
252
253 pcm_data = addr;
254 pcm_size = size;
255
256 while (1)
257 {
258 snd_pcm_state_t state = pcm_state(handle);
259 switch (state)
260 {
261 case PCM_STATE_RUNNING:
262 return;
263 case PCM_STATE_XRUN:
264 {
265 printf("No handler for STATE_XRUN!\n");
266 continue;
267 }
268 case PCM_STATE_PREPARED:
269 { /* prepared state, we need to fill the buffer with silence before
270 * starting */
271 int err = async_rw(handle);
272 if (err < 0)
273 printf("Start error: %d\n", err);
274 return;
275 }
276 case PCM_STATE_PAUSED:
277 { /* paused, simply resume */
278 pcm_play_dma_pause(0);
279 return;
280 }
281 case PCM_STATE_DRAINING:
282 /* run until drained */
283 continue;
284 default:
285 DEBUGF("Unhandled state: %d\n", state);
286 return;
287 }
288 }
289}
290
291size_t pcm_get_bytes_waiting(void)
292{
293 return pcm_size;
294}
295
296const void * pcm_play_dma_get_peak_buffer(int *count)
297{
298 uintptr_t addr = (uintptr_t)pcm_data;
299 *count = pcm_size / 4;
300 return (void *)((addr + 3) & ~3);
301}
302
303void pcm_play_dma_postinit(void)
304{
305 return;
306}
307
308void pcm_set_mixer_volume(int volume)
309{
310#if defined(DX50) || defined(DX90)
311 /* -990 to 0 -> 0 to 255 */
312 int val = (volume+990)*255/990;
313#if defined(DX50)
314 FILE *f = fopen("/dev/codec_volume", "w");
315#else /* DX90 */
316 FILE *f = fopen("/sys/class/codec/es9018_volume", "w");
317#endif /* DX50 */
318 fprintf(f, "%d", val);
319 fclose(f);
320#else
321 (void)volume;
322#endif /* DX50 || DX90 */
323}
324
325#ifdef HAVE_RECORDING
326void pcm_rec_lock(void)
327{
328}
329
330void pcm_rec_unlock(void)
331{
332}
333
334void pcm_rec_dma_init(void)
335{
336}
337
338void pcm_rec_dma_close(void)
339{
340}
341
342void pcm_rec_dma_start(void *start, size_t size)
343{
344 (void)start;
345 (void)size;
346}
347
348void pcm_rec_dma_stop(void)
349{
350}
351
352const void * pcm_rec_dma_get_peak_buffer(void)
353{
354 return NULL;
355}
356
357void audiohw_set_recvol(int left, int right, int type)
358{
359 (void)left;
360 (void)right;
361 (void)type;
362}
363
364#endif /* HAVE_RECORDING */
diff --git a/firmware/target/hosted/android/dx50/powermgmt-dx50.c b/firmware/target/hosted/android/dx50/powermgmt-dx50.c
new file mode 100644
index 0000000000..45756cb8e8
--- /dev/null
+++ b/firmware/target/hosted/android/dx50/powermgmt-dx50.c
@@ -0,0 +1,72 @@
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 <stdbool.h>
23#include <stdio.h>
24#include "config.h"
25#include "power.h"
26#include "powermgmt.h"
27
28unsigned int power_input_status(void)
29{
30 int val;
31 FILE *f = fopen("/sys/class/power_supply/ac/present", "r");
32 fscanf(f, "%d", &val);
33 fclose(f);
34 return val?POWER_INPUT_MAIN_CHARGER:POWER_INPUT_NONE;
35}
36
37/* Values for stock PISEN battery. TODO: Needs optimization */
38
39const unsigned short battery_level_dangerous[BATTERY_TYPES_COUNT] =
40{
41 3380
42};
43
44const unsigned short battery_level_shutoff[BATTERY_TYPES_COUNT] =
45{
46 3100
47};
48
49/* voltages (millivolt) of 0%, 10%, ... 100% when charging disabled */
50const unsigned short percent_to_volt_discharge[BATTERY_TYPES_COUNT][11] =
51{
52 { 3370, 3650, 3700, 3740, 3780, 3820, 3870, 3930, 4000, 4090, 4190 }
53};
54
55/* voltages (millivolt) of 0%, 10%, ... 100% when charging enabled */
56const unsigned short percent_to_volt_charge[11] =
57{
58 3540, 3860, 3930, 3980, 4000, 4020, 4040, 4080, 4130, 4180, 4220 /* LiPo */
59};
60
61
62/* Returns battery voltage from android measurement [millivolts] */
63int _battery_voltage(void)
64{
65 int val;
66 FILE *f = fopen("/sys/class/power_supply/battery/voltage_now", "r");
67 fscanf(f, "%d", &val);
68 fclose(f);
69 return (val/1000);
70}
71
72
diff --git a/firmware/target/hosted/android/dx50/tinyalsa/asound.h b/firmware/target/hosted/android/dx50/tinyalsa/asound.h
new file mode 100644
index 0000000000..fc1e4f6d67
--- /dev/null
+++ b/firmware/target/hosted/android/dx50/tinyalsa/asound.h
@@ -0,0 +1,821 @@
1/****************************************************************************
2 ****************************************************************************
3 ***
4 *** This header was automatically generated from a Linux kernel header
5 *** of the same name, to make information necessary for userspace to
6 *** call into the kernel available to libc. It contains only constants,
7 *** structures, and macros generated from the original header, and thus,
8 *** contains no copyrightable information.
9 ***
10 ****************************************************************************
11 ****************************************************************************/
12#ifndef __SOUND_ASOUND_H
13#define __SOUND_ASOUND_H
14
15#include <linux/types.h>
16
17#define SNDRV_PROTOCOL_VERSION(major, minor, subminor) (((major)<<16)|((minor)<<8)|(subminor))
18#define SNDRV_PROTOCOL_MAJOR(version) (((version)>>16)&0xffff)
19#define SNDRV_PROTOCOL_MINOR(version) (((version)>>8)&0xff)
20#define SNDRV_PROTOCOL_MICRO(version) ((version)&0xff)
21#define SNDRV_PROTOCOL_INCOMPATIBLE(kversion, uversion) (SNDRV_PROTOCOL_MAJOR(kversion) != SNDRV_PROTOCOL_MAJOR(uversion) || (SNDRV_PROTOCOL_MAJOR(kversion) == SNDRV_PROTOCOL_MAJOR(uversion) && SNDRV_PROTOCOL_MINOR(kversion) != SNDRV_PROTOCOL_MINOR(uversion)))
22
23struct snd_aes_iec958 {
24 unsigned char status[24];
25 unsigned char subcode[147];
26 unsigned char pad;
27 unsigned char dig_subframe[4];
28};
29
30#define SNDRV_HWDEP_VERSION SNDRV_PROTOCOL_VERSION(1, 0, 1)
31
32enum {
33 SNDRV_HWDEP_IFACE_OPL2 = 0,
34 SNDRV_HWDEP_IFACE_OPL3,
35 SNDRV_HWDEP_IFACE_OPL4,
36 SNDRV_HWDEP_IFACE_SB16CSP,
37 SNDRV_HWDEP_IFACE_EMU10K1,
38 SNDRV_HWDEP_IFACE_YSS225,
39 SNDRV_HWDEP_IFACE_ICS2115,
40 SNDRV_HWDEP_IFACE_SSCAPE,
41 SNDRV_HWDEP_IFACE_VX,
42 SNDRV_HWDEP_IFACE_MIXART,
43 SNDRV_HWDEP_IFACE_USX2Y,
44 SNDRV_HWDEP_IFACE_EMUX_WAVETABLE,
45 SNDRV_HWDEP_IFACE_BLUETOOTH,
46 SNDRV_HWDEP_IFACE_USX2Y_PCM,
47 SNDRV_HWDEP_IFACE_PCXHR,
48 SNDRV_HWDEP_IFACE_SB_RC,
49 SNDRV_HWDEP_IFACE_HDA,
50 SNDRV_HWDEP_IFACE_USB_STREAM,
51
52 SNDRV_HWDEP_IFACE_LAST = SNDRV_HWDEP_IFACE_USB_STREAM
53};
54
55struct snd_hwdep_info {
56 unsigned int device;
57 int card;
58 unsigned char id[64];
59 unsigned char name[80];
60 int iface;
61 unsigned char reserved[64];
62};
63
64struct snd_hwdep_dsp_status {
65 unsigned int version;
66 unsigned char id[32];
67 unsigned int num_dsps;
68 unsigned int dsp_loaded;
69 unsigned int chip_ready;
70 unsigned char reserved[16];
71};
72
73struct snd_hwdep_dsp_image {
74 unsigned int index;
75 unsigned char name[64];
76 unsigned char __user *image;
77 size_t length;
78 unsigned long driver_data;
79};
80
81#define SNDRV_HWDEP_IOCTL_PVERSION _IOR ('H', 0x00, int)
82#define SNDRV_HWDEP_IOCTL_INFO _IOR ('H', 0x01, struct snd_hwdep_info)
83#define SNDRV_HWDEP_IOCTL_DSP_STATUS _IOR('H', 0x02, struct snd_hwdep_dsp_status)
84#define SNDRV_HWDEP_IOCTL_DSP_LOAD _IOW('H', 0x03, struct snd_hwdep_dsp_image)
85
86#define SNDRV_PCM_VERSION SNDRV_PROTOCOL_VERSION(2, 0, 10)
87
88typedef unsigned long snd_pcm_uframes_t;
89typedef signed long snd_pcm_sframes_t;
90
91enum {
92 SNDRV_PCM_CLASS_GENERIC = 0,
93 SNDRV_PCM_CLASS_MULTI,
94 SNDRV_PCM_CLASS_MODEM,
95 SNDRV_PCM_CLASS_DIGITIZER,
96
97 SNDRV_PCM_CLASS_LAST = SNDRV_PCM_CLASS_DIGITIZER,
98};
99
100enum {
101 SNDRV_PCM_SUBCLASS_GENERIC_MIX = 0,
102 SNDRV_PCM_SUBCLASS_MULTI_MIX,
103
104 SNDRV_PCM_SUBCLASS_LAST = SNDRV_PCM_SUBCLASS_MULTI_MIX,
105};
106
107enum {
108 SNDRV_PCM_STREAM_PLAYBACK = 0,
109 SNDRV_PCM_STREAM_CAPTURE,
110 SNDRV_PCM_STREAM_LAST = SNDRV_PCM_STREAM_CAPTURE,
111};
112
113typedef int __bitwise snd_pcm_access_t;
114#define SNDRV_PCM_ACCESS_MMAP_INTERLEAVED ((__force snd_pcm_access_t) 0)
115#define SNDRV_PCM_ACCESS_MMAP_NONINTERLEAVED ((__force snd_pcm_access_t) 1)
116#define SNDRV_PCM_ACCESS_MMAP_COMPLEX ((__force snd_pcm_access_t) 2)
117#define SNDRV_PCM_ACCESS_RW_INTERLEAVED ((__force snd_pcm_access_t) 3)
118#define SNDRV_PCM_ACCESS_RW_NONINTERLEAVED ((__force snd_pcm_access_t) 4)
119#define SNDRV_PCM_ACCESS_LAST SNDRV_PCM_ACCESS_RW_NONINTERLEAVED
120
121typedef int __bitwise snd_pcm_format_t;
122#define SNDRV_PCM_FORMAT_S8 ((__force snd_pcm_format_t) 0)
123#define SNDRV_PCM_FORMAT_U8 ((__force snd_pcm_format_t) 1)
124#define SNDRV_PCM_FORMAT_S16_LE ((__force snd_pcm_format_t) 2)
125#define SNDRV_PCM_FORMAT_S16_BE ((__force snd_pcm_format_t) 3)
126#define SNDRV_PCM_FORMAT_U16_LE ((__force snd_pcm_format_t) 4)
127#define SNDRV_PCM_FORMAT_U16_BE ((__force snd_pcm_format_t) 5)
128#define SNDRV_PCM_FORMAT_S24_LE ((__force snd_pcm_format_t) 6)
129#define SNDRV_PCM_FORMAT_S24_BE ((__force snd_pcm_format_t) 7)
130#define SNDRV_PCM_FORMAT_U24_LE ((__force snd_pcm_format_t) 8)
131#define SNDRV_PCM_FORMAT_U24_BE ((__force snd_pcm_format_t) 9)
132#define SNDRV_PCM_FORMAT_S32_LE ((__force snd_pcm_format_t) 10)
133#define SNDRV_PCM_FORMAT_S32_BE ((__force snd_pcm_format_t) 11)
134#define SNDRV_PCM_FORMAT_U32_LE ((__force snd_pcm_format_t) 12)
135#define SNDRV_PCM_FORMAT_U32_BE ((__force snd_pcm_format_t) 13)
136#define SNDRV_PCM_FORMAT_FLOAT_LE ((__force snd_pcm_format_t) 14)
137#define SNDRV_PCM_FORMAT_FLOAT_BE ((__force snd_pcm_format_t) 15)
138#define SNDRV_PCM_FORMAT_FLOAT64_LE ((__force snd_pcm_format_t) 16)
139#define SNDRV_PCM_FORMAT_FLOAT64_BE ((__force snd_pcm_format_t) 17)
140#define SNDRV_PCM_FORMAT_IEC958_SUBFRAME_LE ((__force snd_pcm_format_t) 18)
141#define SNDRV_PCM_FORMAT_IEC958_SUBFRAME_BE ((__force snd_pcm_format_t) 19)
142#define SNDRV_PCM_FORMAT_MU_LAW ((__force snd_pcm_format_t) 20)
143#define SNDRV_PCM_FORMAT_A_LAW ((__force snd_pcm_format_t) 21)
144#define SNDRV_PCM_FORMAT_IMA_ADPCM ((__force snd_pcm_format_t) 22)
145#define SNDRV_PCM_FORMAT_MPEG ((__force snd_pcm_format_t) 23)
146#define SNDRV_PCM_FORMAT_GSM ((__force snd_pcm_format_t) 24)
147#define SNDRV_PCM_FORMAT_SPECIAL ((__force snd_pcm_format_t) 31)
148#define SNDRV_PCM_FORMAT_S24_3LE ((__force snd_pcm_format_t) 32)
149#define SNDRV_PCM_FORMAT_S24_3BE ((__force snd_pcm_format_t) 33)
150#define SNDRV_PCM_FORMAT_U24_3LE ((__force snd_pcm_format_t) 34)
151#define SNDRV_PCM_FORMAT_U24_3BE ((__force snd_pcm_format_t) 35)
152#define SNDRV_PCM_FORMAT_S20_3LE ((__force snd_pcm_format_t) 36)
153#define SNDRV_PCM_FORMAT_S20_3BE ((__force snd_pcm_format_t) 37)
154#define SNDRV_PCM_FORMAT_U20_3LE ((__force snd_pcm_format_t) 38)
155#define SNDRV_PCM_FORMAT_U20_3BE ((__force snd_pcm_format_t) 39)
156#define SNDRV_PCM_FORMAT_S18_3LE ((__force snd_pcm_format_t) 40)
157#define SNDRV_PCM_FORMAT_S18_3BE ((__force snd_pcm_format_t) 41)
158#define SNDRV_PCM_FORMAT_U18_3LE ((__force snd_pcm_format_t) 42)
159#define SNDRV_PCM_FORMAT_U18_3BE ((__force snd_pcm_format_t) 43)
160#define SNDRV_PCM_FORMAT_G723_24 ((__force snd_pcm_format_t) 44)
161#define SNDRV_PCM_FORMAT_G723_24_1B ((__force snd_pcm_format_t) 45)
162#define SNDRV_PCM_FORMAT_G723_40 ((__force snd_pcm_format_t) 46)
163#define SNDRV_PCM_FORMAT_G723_40_1B ((__force snd_pcm_format_t) 47)
164#define SNDRV_PCM_FORMAT_LAST SNDRV_PCM_FORMAT_G723_40_1B
165
166#ifdef SNDRV_LITTLE_ENDIAN
167#define SNDRV_PCM_FORMAT_S16 SNDRV_PCM_FORMAT_S16_LE
168#define SNDRV_PCM_FORMAT_U16 SNDRV_PCM_FORMAT_U16_LE
169#define SNDRV_PCM_FORMAT_S24 SNDRV_PCM_FORMAT_S24_LE
170#define SNDRV_PCM_FORMAT_U24 SNDRV_PCM_FORMAT_U24_LE
171#define SNDRV_PCM_FORMAT_S32 SNDRV_PCM_FORMAT_S32_LE
172#define SNDRV_PCM_FORMAT_U32 SNDRV_PCM_FORMAT_U32_LE
173#define SNDRV_PCM_FORMAT_FLOAT SNDRV_PCM_FORMAT_FLOAT_LE
174#define SNDRV_PCM_FORMAT_FLOAT64 SNDRV_PCM_FORMAT_FLOAT64_LE
175#define SNDRV_PCM_FORMAT_IEC958_SUBFRAME SNDRV_PCM_FORMAT_IEC958_SUBFRAME_LE
176#endif
177#ifdef SNDRV_BIG_ENDIAN
178#define SNDRV_PCM_FORMAT_S16 SNDRV_PCM_FORMAT_S16_BE
179#define SNDRV_PCM_FORMAT_U16 SNDRV_PCM_FORMAT_U16_BE
180#define SNDRV_PCM_FORMAT_S24 SNDRV_PCM_FORMAT_S24_BE
181#define SNDRV_PCM_FORMAT_U24 SNDRV_PCM_FORMAT_U24_BE
182#define SNDRV_PCM_FORMAT_S32 SNDRV_PCM_FORMAT_S32_BE
183#define SNDRV_PCM_FORMAT_U32 SNDRV_PCM_FORMAT_U32_BE
184#define SNDRV_PCM_FORMAT_FLOAT SNDRV_PCM_FORMAT_FLOAT_BE
185#define SNDRV_PCM_FORMAT_FLOAT64 SNDRV_PCM_FORMAT_FLOAT64_BE
186#define SNDRV_PCM_FORMAT_IEC958_SUBFRAME SNDRV_PCM_FORMAT_IEC958_SUBFRAME_BE
187#endif
188
189typedef int __bitwise snd_pcm_subformat_t;
190#define SNDRV_PCM_SUBFORMAT_STD ((__force snd_pcm_subformat_t) 0)
191#define SNDRV_PCM_SUBFORMAT_LAST SNDRV_PCM_SUBFORMAT_STD
192
193#define SNDRV_PCM_INFO_MMAP 0x00000001
194#define SNDRV_PCM_INFO_MMAP_VALID 0x00000002
195#define SNDRV_PCM_INFO_DOUBLE 0x00000004
196#define SNDRV_PCM_INFO_BATCH 0x00000010
197#define SNDRV_PCM_INFO_INTERLEAVED 0x00000100
198#define SNDRV_PCM_INFO_NONINTERLEAVED 0x00000200
199#define SNDRV_PCM_INFO_COMPLEX 0x00000400
200#define SNDRV_PCM_INFO_BLOCK_TRANSFER 0x00010000
201#define SNDRV_PCM_INFO_OVERRANGE 0x00020000
202#define SNDRV_PCM_INFO_RESUME 0x00040000
203#define SNDRV_PCM_INFO_PAUSE 0x00080000
204#define SNDRV_PCM_INFO_HALF_DUPLEX 0x00100000
205#define SNDRV_PCM_INFO_JOINT_DUPLEX 0x00200000
206#define SNDRV_PCM_INFO_SYNC_START 0x00400000
207#define SNDRV_PCM_INFO_NO_PERIOD_WAKEUP 0x00800000
208#define SNDRV_PCM_INFO_FIFO_IN_FRAMES 0x80000000
209
210typedef int __bitwise snd_pcm_state_t;
211#define SNDRV_PCM_STATE_OPEN ((__force snd_pcm_state_t) 0)
212#define SNDRV_PCM_STATE_SETUP ((__force snd_pcm_state_t) 1)
213#define SNDRV_PCM_STATE_PREPARED ((__force snd_pcm_state_t) 2)
214#define SNDRV_PCM_STATE_RUNNING ((__force snd_pcm_state_t) 3)
215#define SNDRV_PCM_STATE_XRUN ((__force snd_pcm_state_t) 4)
216#define SNDRV_PCM_STATE_DRAINING ((__force snd_pcm_state_t) 5)
217#define SNDRV_PCM_STATE_PAUSED ((__force snd_pcm_state_t) 6)
218#define SNDRV_PCM_STATE_SUSPENDED ((__force snd_pcm_state_t) 7)
219#define SNDRV_PCM_STATE_DISCONNECTED ((__force snd_pcm_state_t) 8)
220#define SNDRV_PCM_STATE_LAST SNDRV_PCM_STATE_DISCONNECTED
221
222enum {
223 SNDRV_PCM_MMAP_OFFSET_DATA = 0x00000000,
224 SNDRV_PCM_MMAP_OFFSET_STATUS = 0x80000000,
225 SNDRV_PCM_MMAP_OFFSET_CONTROL = 0x81000000,
226};
227
228union snd_pcm_sync_id {
229 unsigned char id[16];
230 unsigned short id16[8];
231 unsigned int id32[4];
232};
233
234struct snd_pcm_info {
235 unsigned int device;
236 unsigned int subdevice;
237 int stream;
238 int card;
239 unsigned char id[64];
240 unsigned char name[80];
241 unsigned char subname[32];
242 int dev_class;
243 int dev_subclass;
244 unsigned int subdevices_count;
245 unsigned int subdevices_avail;
246 union snd_pcm_sync_id sync;
247 unsigned char reserved[64];
248};
249
250typedef int snd_pcm_hw_param_t;
251#define SNDRV_PCM_HW_PARAM_ACCESS 0
252#define SNDRV_PCM_HW_PARAM_FORMAT 1
253#define SNDRV_PCM_HW_PARAM_SUBFORMAT 2
254#define SNDRV_PCM_HW_PARAM_FIRST_MASK SNDRV_PCM_HW_PARAM_ACCESS
255#define SNDRV_PCM_HW_PARAM_LAST_MASK SNDRV_PCM_HW_PARAM_SUBFORMAT
256
257#define SNDRV_PCM_HW_PARAM_SAMPLE_BITS 8
258#define SNDRV_PCM_HW_PARAM_FRAME_BITS 9
259#define SNDRV_PCM_HW_PARAM_CHANNELS 10
260#define SNDRV_PCM_HW_PARAM_RATE 11
261#define SNDRV_PCM_HW_PARAM_PERIOD_TIME 12
262#define SNDRV_PCM_HW_PARAM_PERIOD_SIZE 13
263#define SNDRV_PCM_HW_PARAM_PERIOD_BYTES 14
264#define SNDRV_PCM_HW_PARAM_PERIODS 15
265#define SNDRV_PCM_HW_PARAM_BUFFER_TIME 16
266#define SNDRV_PCM_HW_PARAM_BUFFER_SIZE 17
267#define SNDRV_PCM_HW_PARAM_BUFFER_BYTES 18
268#define SNDRV_PCM_HW_PARAM_TICK_TIME 19
269#define SNDRV_PCM_HW_PARAM_FIRST_INTERVAL SNDRV_PCM_HW_PARAM_SAMPLE_BITS
270#define SNDRV_PCM_HW_PARAM_LAST_INTERVAL SNDRV_PCM_HW_PARAM_TICK_TIME
271
272#define SNDRV_PCM_HW_PARAMS_NORESAMPLE (1<<0)
273#define SNDRV_PCM_HW_PARAMS_EXPORT_BUFFER (1<<1)
274#define SNDRV_PCM_HW_PARAMS_NO_PERIOD_WAKEUP (1<<2)
275
276struct snd_interval {
277 unsigned int min, max;
278 unsigned int openmin:1,
279 openmax:1,
280 integer:1,
281 empty:1;
282};
283
284#define SNDRV_MASK_MAX 256
285
286struct snd_mask {
287 __u32 bits[(SNDRV_MASK_MAX+31)/32];
288};
289
290struct snd_pcm_hw_params {
291 unsigned int flags;
292 struct snd_mask masks[SNDRV_PCM_HW_PARAM_LAST_MASK -
293 SNDRV_PCM_HW_PARAM_FIRST_MASK + 1];
294 struct snd_mask mres[5];
295 struct snd_interval intervals[SNDRV_PCM_HW_PARAM_LAST_INTERVAL -
296 SNDRV_PCM_HW_PARAM_FIRST_INTERVAL + 1];
297 struct snd_interval ires[9];
298 unsigned int rmask;
299 unsigned int cmask;
300 unsigned int info;
301 unsigned int msbits;
302 unsigned int rate_num;
303 unsigned int rate_den;
304 snd_pcm_uframes_t fifo_size;
305 unsigned char reserved[64];
306};
307
308enum {
309 SNDRV_PCM_TSTAMP_NONE = 0,
310 SNDRV_PCM_TSTAMP_ENABLE,
311 SNDRV_PCM_TSTAMP_LAST = SNDRV_PCM_TSTAMP_ENABLE,
312};
313
314struct snd_pcm_sw_params {
315 int tstamp_mode;
316 unsigned int period_step;
317 unsigned int sleep_min;
318 snd_pcm_uframes_t avail_min;
319 snd_pcm_uframes_t xfer_align;
320 snd_pcm_uframes_t start_threshold;
321 snd_pcm_uframes_t stop_threshold;
322 snd_pcm_uframes_t silence_threshold;
323 snd_pcm_uframes_t silence_size;
324 snd_pcm_uframes_t boundary;
325 unsigned char reserved[64];
326};
327
328struct snd_pcm_channel_info {
329 unsigned int channel;
330 __kernel_off_t offset;
331 unsigned int first;
332 unsigned int step;
333};
334
335struct snd_pcm_status {
336 snd_pcm_state_t state;
337 struct timespec trigger_tstamp;
338 struct timespec tstamp;
339 snd_pcm_uframes_t appl_ptr;
340 snd_pcm_uframes_t hw_ptr;
341 snd_pcm_sframes_t delay;
342 snd_pcm_uframes_t avail;
343 snd_pcm_uframes_t avail_max;
344 snd_pcm_uframes_t overrange;
345 snd_pcm_state_t suspended_state;
346 unsigned char reserved[60];
347};
348
349struct snd_pcm_mmap_status {
350 snd_pcm_state_t state;
351 int pad1;
352 snd_pcm_uframes_t hw_ptr;
353 struct timespec tstamp;
354 snd_pcm_state_t suspended_state;
355};
356
357struct snd_pcm_mmap_control {
358 snd_pcm_uframes_t appl_ptr;
359 snd_pcm_uframes_t avail_min;
360};
361
362#define SNDRV_PCM_SYNC_PTR_HWSYNC (1<<0)
363#define SNDRV_PCM_SYNC_PTR_APPL (1<<1)
364#define SNDRV_PCM_SYNC_PTR_AVAIL_MIN (1<<2)
365
366struct snd_pcm_sync_ptr {
367 unsigned int flags;
368 union {
369 struct snd_pcm_mmap_status status;
370 unsigned char reserved[64];
371 } s;
372 union {
373 struct snd_pcm_mmap_control control;
374 unsigned char reserved[64];
375 } c;
376};
377
378struct snd_xferi {
379 snd_pcm_sframes_t result;
380 void __user *buf;
381 snd_pcm_uframes_t frames;
382};
383
384struct snd_xfern {
385 snd_pcm_sframes_t result;
386 void __user * __user *bufs;
387 snd_pcm_uframes_t frames;
388};
389
390enum {
391 SNDRV_PCM_TSTAMP_TYPE_GETTIMEOFDAY = 0,
392 SNDRV_PCM_TSTAMP_TYPE_MONOTONIC,
393 SNDRV_PCM_TSTAMP_TYPE_LAST = SNDRV_PCM_TSTAMP_TYPE_MONOTONIC,
394};
395
396#define SNDRV_PCM_IOCTL_PVERSION _IOR('A', 0x00, int)
397#define SNDRV_PCM_IOCTL_INFO _IOR('A', 0x01, struct snd_pcm_info)
398#define SNDRV_PCM_IOCTL_TSTAMP _IOW('A', 0x02, int)
399#define SNDRV_PCM_IOCTL_TTSTAMP _IOW('A', 0x03, int)
400#define SNDRV_PCM_IOCTL_HW_REFINE _IOWR('A', 0x10, struct snd_pcm_hw_params)
401#define SNDRV_PCM_IOCTL_HW_PARAMS _IOWR('A', 0x11, struct snd_pcm_hw_params)
402#define SNDRV_PCM_IOCTL_HW_FREE _IO('A', 0x12)
403#define SNDRV_PCM_IOCTL_SW_PARAMS _IOWR('A', 0x13, struct snd_pcm_sw_params)
404#define SNDRV_PCM_IOCTL_STATUS _IOR('A', 0x20, struct snd_pcm_status)
405#define SNDRV_PCM_IOCTL_DELAY _IOR('A', 0x21, snd_pcm_sframes_t)
406#define SNDRV_PCM_IOCTL_HWSYNC _IO('A', 0x22)
407#define SNDRV_PCM_IOCTL_SYNC_PTR _IOWR('A', 0x23, struct snd_pcm_sync_ptr)
408#define SNDRV_PCM_IOCTL_CHANNEL_INFO _IOR('A', 0x32, struct snd_pcm_channel_info)
409#define SNDRV_PCM_IOCTL_PREPARE _IO('A', 0x40)
410#define SNDRV_PCM_IOCTL_RESET _IO('A', 0x41)
411#define SNDRV_PCM_IOCTL_START _IO('A', 0x42)
412#define SNDRV_PCM_IOCTL_DROP _IO('A', 0x43)
413#define SNDRV_PCM_IOCTL_DRAIN _IO('A', 0x44)
414#define SNDRV_PCM_IOCTL_PAUSE _IOW('A', 0x45, int)
415#define SNDRV_PCM_IOCTL_REWIND _IOW('A', 0x46, snd_pcm_uframes_t)
416#define SNDRV_PCM_IOCTL_RESUME _IO('A', 0x47)
417#define SNDRV_PCM_IOCTL_XRUN _IO('A', 0x48)
418#define SNDRV_PCM_IOCTL_FORWARD _IOW('A', 0x49, snd_pcm_uframes_t)
419#define SNDRV_PCM_IOCTL_WRITEI_FRAMES _IOW('A', 0x50, struct snd_xferi)
420#define SNDRV_PCM_IOCTL_READI_FRAMES _IOR('A', 0x51, struct snd_xferi)
421#define SNDRV_PCM_IOCTL_WRITEN_FRAMES _IOW('A', 0x52, struct snd_xfern)
422#define SNDRV_PCM_IOCTL_READN_FRAMES _IOR('A', 0x53, struct snd_xfern)
423#define SNDRV_PCM_IOCTL_LINK _IOW('A', 0x60, int)
424#define SNDRV_PCM_IOCTL_UNLINK _IO('A', 0x61)
425
426#define SNDRV_RAWMIDI_VERSION SNDRV_PROTOCOL_VERSION(2, 0, 0)
427
428enum {
429 SNDRV_RAWMIDI_STREAM_OUTPUT = 0,
430 SNDRV_RAWMIDI_STREAM_INPUT,
431 SNDRV_RAWMIDI_STREAM_LAST = SNDRV_RAWMIDI_STREAM_INPUT,
432};
433
434#define SNDRV_RAWMIDI_INFO_OUTPUT 0x00000001
435#define SNDRV_RAWMIDI_INFO_INPUT 0x00000002
436#define SNDRV_RAWMIDI_INFO_DUPLEX 0x00000004
437
438struct snd_rawmidi_info {
439 unsigned int device;
440 unsigned int subdevice;
441 int stream;
442 int card;
443 unsigned int flags;
444 unsigned char id[64];
445 unsigned char name[80];
446 unsigned char subname[32];
447 unsigned int subdevices_count;
448 unsigned int subdevices_avail;
449 unsigned char reserved[64];
450};
451
452struct snd_rawmidi_params {
453 int stream;
454 size_t buffer_size;
455 size_t avail_min;
456 unsigned int no_active_sensing: 1;
457 unsigned char reserved[16];
458};
459
460struct snd_rawmidi_status {
461 int stream;
462 struct timespec tstamp;
463 size_t avail;
464 size_t xruns;
465 unsigned char reserved[16];
466};
467
468#define SNDRV_RAWMIDI_IOCTL_PVERSION _IOR('W', 0x00, int)
469#define SNDRV_RAWMIDI_IOCTL_INFO _IOR('W', 0x01, struct snd_rawmidi_info)
470#define SNDRV_RAWMIDI_IOCTL_PARAMS _IOWR('W', 0x10, struct snd_rawmidi_params)
471#define SNDRV_RAWMIDI_IOCTL_STATUS _IOWR('W', 0x20, struct snd_rawmidi_status)
472#define SNDRV_RAWMIDI_IOCTL_DROP _IOW('W', 0x30, int)
473#define SNDRV_RAWMIDI_IOCTL_DRAIN _IOW('W', 0x31, int)
474
475#define SNDRV_TIMER_VERSION SNDRV_PROTOCOL_VERSION(2, 0, 6)
476
477enum {
478 SNDRV_TIMER_CLASS_NONE = -1,
479 SNDRV_TIMER_CLASS_SLAVE = 0,
480 SNDRV_TIMER_CLASS_GLOBAL,
481 SNDRV_TIMER_CLASS_CARD,
482 SNDRV_TIMER_CLASS_PCM,
483 SNDRV_TIMER_CLASS_LAST = SNDRV_TIMER_CLASS_PCM,
484};
485
486enum {
487 SNDRV_TIMER_SCLASS_NONE = 0,
488 SNDRV_TIMER_SCLASS_APPLICATION,
489 SNDRV_TIMER_SCLASS_SEQUENCER,
490 SNDRV_TIMER_SCLASS_OSS_SEQUENCER,
491 SNDRV_TIMER_SCLASS_LAST = SNDRV_TIMER_SCLASS_OSS_SEQUENCER,
492};
493
494#define SNDRV_TIMER_GLOBAL_SYSTEM 0
495#define SNDRV_TIMER_GLOBAL_RTC 1
496#define SNDRV_TIMER_GLOBAL_HPET 2
497#define SNDRV_TIMER_GLOBAL_HRTIMER 3
498
499#define SNDRV_TIMER_FLG_SLAVE (1<<0)
500
501struct snd_timer_id {
502 int dev_class;
503 int dev_sclass;
504 int card;
505 int device;
506 int subdevice;
507};
508
509struct snd_timer_ginfo {
510 struct snd_timer_id tid;
511 unsigned int flags;
512 int card;
513 unsigned char id[64];
514 unsigned char name[80];
515 unsigned long reserved0;
516 unsigned long resolution;
517 unsigned long resolution_min;
518 unsigned long resolution_max;
519 unsigned int clients;
520 unsigned char reserved[32];
521};
522
523struct snd_timer_gparams {
524 struct snd_timer_id tid;
525 unsigned long period_num;
526 unsigned long period_den;
527 unsigned char reserved[32];
528};
529
530struct snd_timer_gstatus {
531 struct snd_timer_id tid;
532 unsigned long resolution;
533 unsigned long resolution_num;
534 unsigned long resolution_den;
535 unsigned char reserved[32];
536};
537
538struct snd_timer_select {
539 struct snd_timer_id id;
540 unsigned char reserved[32];
541};
542
543struct snd_timer_info {
544 unsigned int flags;
545 int card;
546 unsigned char id[64];
547 unsigned char name[80];
548 unsigned long reserved0;
549 unsigned long resolution;
550 unsigned char reserved[64];
551};
552
553#define SNDRV_TIMER_PSFLG_AUTO (1<<0)
554#define SNDRV_TIMER_PSFLG_EXCLUSIVE (1<<1)
555#define SNDRV_TIMER_PSFLG_EARLY_EVENT (1<<2)
556
557struct snd_timer_params {
558 unsigned int flags;
559 unsigned int ticks;
560 unsigned int queue_size;
561 unsigned int reserved0;
562 unsigned int filter;
563 unsigned char reserved[60];
564};
565
566struct snd_timer_status {
567 struct timespec tstamp;
568 unsigned int resolution;
569 unsigned int lost;
570 unsigned int overrun;
571 unsigned int queue;
572 unsigned char reserved[64];
573};
574
575#define SNDRV_TIMER_IOCTL_PVERSION _IOR('T', 0x00, int)
576#define SNDRV_TIMER_IOCTL_NEXT_DEVICE _IOWR('T', 0x01, struct snd_timer_id)
577#define SNDRV_TIMER_IOCTL_TREAD _IOW('T', 0x02, int)
578#define SNDRV_TIMER_IOCTL_GINFO _IOWR('T', 0x03, struct snd_timer_ginfo)
579#define SNDRV_TIMER_IOCTL_GPARAMS _IOW('T', 0x04, struct snd_timer_gparams)
580#define SNDRV_TIMER_IOCTL_GSTATUS _IOWR('T', 0x05, struct snd_timer_gstatus)
581#define SNDRV_TIMER_IOCTL_SELECT _IOW('T', 0x10, struct snd_timer_select)
582#define SNDRV_TIMER_IOCTL_INFO _IOR('T', 0x11, struct snd_timer_info)
583#define SNDRV_TIMER_IOCTL_PARAMS _IOW('T', 0x12, struct snd_timer_params)
584#define SNDRV_TIMER_IOCTL_STATUS _IOR('T', 0x14, struct snd_timer_status)
585
586#define SNDRV_TIMER_IOCTL_START _IO('T', 0xa0)
587#define SNDRV_TIMER_IOCTL_STOP _IO('T', 0xa1)
588#define SNDRV_TIMER_IOCTL_CONTINUE _IO('T', 0xa2)
589#define SNDRV_TIMER_IOCTL_PAUSE _IO('T', 0xa3)
590
591struct snd_timer_read {
592 unsigned int resolution;
593 unsigned int ticks;
594};
595
596enum {
597 SNDRV_TIMER_EVENT_RESOLUTION = 0,
598 SNDRV_TIMER_EVENT_TICK,
599 SNDRV_TIMER_EVENT_START,
600 SNDRV_TIMER_EVENT_STOP,
601 SNDRV_TIMER_EVENT_CONTINUE,
602 SNDRV_TIMER_EVENT_PAUSE,
603 SNDRV_TIMER_EVENT_EARLY,
604 SNDRV_TIMER_EVENT_SUSPEND,
605 SNDRV_TIMER_EVENT_RESUME,
606
607 SNDRV_TIMER_EVENT_MSTART = SNDRV_TIMER_EVENT_START + 10,
608 SNDRV_TIMER_EVENT_MSTOP = SNDRV_TIMER_EVENT_STOP + 10,
609 SNDRV_TIMER_EVENT_MCONTINUE = SNDRV_TIMER_EVENT_CONTINUE + 10,
610 SNDRV_TIMER_EVENT_MPAUSE = SNDRV_TIMER_EVENT_PAUSE + 10,
611 SNDRV_TIMER_EVENT_MSUSPEND = SNDRV_TIMER_EVENT_SUSPEND + 10,
612 SNDRV_TIMER_EVENT_MRESUME = SNDRV_TIMER_EVENT_RESUME + 10,
613};
614
615struct snd_timer_tread {
616 int event;
617 struct timespec tstamp;
618 unsigned int val;
619};
620
621#define SNDRV_CTL_VERSION SNDRV_PROTOCOL_VERSION(2, 0, 6)
622
623struct snd_ctl_card_info {
624 int card;
625 int pad;
626 unsigned char id[16];
627 unsigned char driver[16];
628 unsigned char name[32];
629 unsigned char longname[80];
630 unsigned char reserved_[16];
631 unsigned char mixername[80];
632 unsigned char components[128];
633};
634
635typedef int __bitwise snd_ctl_elem_type_t;
636#define SNDRV_CTL_ELEM_TYPE_NONE ((__force snd_ctl_elem_type_t) 0)
637#define SNDRV_CTL_ELEM_TYPE_BOOLEAN ((__force snd_ctl_elem_type_t) 1)
638#define SNDRV_CTL_ELEM_TYPE_INTEGER ((__force snd_ctl_elem_type_t) 2)
639#define SNDRV_CTL_ELEM_TYPE_ENUMERATED ((__force snd_ctl_elem_type_t) 3)
640#define SNDRV_CTL_ELEM_TYPE_BYTES ((__force snd_ctl_elem_type_t) 4)
641#define SNDRV_CTL_ELEM_TYPE_IEC958 ((__force snd_ctl_elem_type_t) 5)
642#define SNDRV_CTL_ELEM_TYPE_INTEGER64 ((__force snd_ctl_elem_type_t) 6)
643#define SNDRV_CTL_ELEM_TYPE_LAST SNDRV_CTL_ELEM_TYPE_INTEGER64
644
645typedef int __bitwise snd_ctl_elem_iface_t;
646#define SNDRV_CTL_ELEM_IFACE_CARD ((__force snd_ctl_elem_iface_t) 0)
647#define SNDRV_CTL_ELEM_IFACE_HWDEP ((__force snd_ctl_elem_iface_t) 1)
648#define SNDRV_CTL_ELEM_IFACE_MIXER ((__force snd_ctl_elem_iface_t) 2)
649#define SNDRV_CTL_ELEM_IFACE_PCM ((__force snd_ctl_elem_iface_t) 3)
650#define SNDRV_CTL_ELEM_IFACE_RAWMIDI ((__force snd_ctl_elem_iface_t) 4)
651#define SNDRV_CTL_ELEM_IFACE_TIMER ((__force snd_ctl_elem_iface_t) 5)
652#define SNDRV_CTL_ELEM_IFACE_SEQUENCER ((__force snd_ctl_elem_iface_t) 6)
653#define SNDRV_CTL_ELEM_IFACE_LAST SNDRV_CTL_ELEM_IFACE_SEQUENCER
654
655#define SNDRV_CTL_ELEM_ACCESS_READ (1<<0)
656#define SNDRV_CTL_ELEM_ACCESS_WRITE (1<<1)
657#define SNDRV_CTL_ELEM_ACCESS_READWRITE (SNDRV_CTL_ELEM_ACCESS_READ|SNDRV_CTL_ELEM_ACCESS_WRITE)
658#define SNDRV_CTL_ELEM_ACCESS_VOLATILE (1<<2)
659#define SNDRV_CTL_ELEM_ACCESS_TIMESTAMP (1<<3)
660#define SNDRV_CTL_ELEM_ACCESS_TLV_READ (1<<4)
661#define SNDRV_CTL_ELEM_ACCESS_TLV_WRITE (1<<5)
662#define SNDRV_CTL_ELEM_ACCESS_TLV_READWRITE (SNDRV_CTL_ELEM_ACCESS_TLV_READ|SNDRV_CTL_ELEM_ACCESS_TLV_WRITE)
663#define SNDRV_CTL_ELEM_ACCESS_TLV_COMMAND (1<<6)
664#define SNDRV_CTL_ELEM_ACCESS_INACTIVE (1<<8)
665#define SNDRV_CTL_ELEM_ACCESS_LOCK (1<<9)
666#define SNDRV_CTL_ELEM_ACCESS_OWNER (1<<10)
667#define SNDRV_CTL_ELEM_ACCESS_TLV_CALLBACK (1<<28)
668#define SNDRV_CTL_ELEM_ACCESS_USER (1<<29)
669
670#define SNDRV_CTL_POWER_D0 0x0000
671#define SNDRV_CTL_POWER_D1 0x0100
672#define SNDRV_CTL_POWER_D2 0x0200
673#define SNDRV_CTL_POWER_D3 0x0300
674#define SNDRV_CTL_POWER_D3hot (SNDRV_CTL_POWER_D3|0x0000)
675#define SNDRV_CTL_POWER_D3cold (SNDRV_CTL_POWER_D3|0x0001)
676
677struct snd_ctl_elem_id {
678 unsigned int numid;
679 snd_ctl_elem_iface_t iface;
680 unsigned int device;
681 unsigned int subdevice;
682 unsigned char name[44];
683 unsigned int index;
684};
685
686struct snd_ctl_elem_list {
687 unsigned int offset;
688 unsigned int space;
689 unsigned int used;
690 unsigned int count;
691 struct snd_ctl_elem_id __user *pids;
692 unsigned char reserved[50];
693};
694
695struct snd_ctl_elem_info {
696 struct snd_ctl_elem_id id;
697 snd_ctl_elem_type_t type;
698 unsigned int access;
699 unsigned int count;
700 __kernel_pid_t owner;
701 union {
702 struct {
703 long min;
704 long max;
705 long step;
706 } integer;
707 struct {
708 long long min;
709 long long max;
710 long long step;
711 } integer64;
712 struct {
713 unsigned int items;
714 unsigned int item;
715 char name[64];
716 } enumerated;
717 unsigned char reserved[128];
718 } value;
719 union {
720 unsigned short d[4];
721 unsigned short *d_ptr;
722 } dimen;
723 unsigned char reserved[64-4*sizeof(unsigned short)];
724};
725
726struct snd_ctl_elem_value {
727 struct snd_ctl_elem_id id;
728 unsigned int indirect: 1;
729 union {
730 union {
731 long value[128];
732 long *value_ptr;
733 } integer;
734 union {
735 long long value[64];
736 long long *value_ptr;
737 } integer64;
738 union {
739 unsigned int item[128];
740 unsigned int *item_ptr;
741 } enumerated;
742 union {
743 unsigned char data[512];
744 unsigned char *data_ptr;
745 } bytes;
746 struct snd_aes_iec958 iec958;
747 } value;
748 struct timespec tstamp;
749 unsigned char reserved[128-sizeof(struct timespec)];
750};
751
752struct snd_ctl_tlv {
753 unsigned int numid;
754 unsigned int length;
755 unsigned int tlv[0];
756};
757
758#define SNDRV_CTL_IOCTL_PVERSION _IOR('U', 0x00, int)
759#define SNDRV_CTL_IOCTL_CARD_INFO _IOR('U', 0x01, struct snd_ctl_card_info)
760#define SNDRV_CTL_IOCTL_ELEM_LIST _IOWR('U', 0x10, struct snd_ctl_elem_list)
761#define SNDRV_CTL_IOCTL_ELEM_INFO _IOWR('U', 0x11, struct snd_ctl_elem_info)
762#define SNDRV_CTL_IOCTL_ELEM_READ _IOWR('U', 0x12, struct snd_ctl_elem_value)
763#define SNDRV_CTL_IOCTL_ELEM_WRITE _IOWR('U', 0x13, struct snd_ctl_elem_value)
764#define SNDRV_CTL_IOCTL_ELEM_LOCK _IOW('U', 0x14, struct snd_ctl_elem_id)
765#define SNDRV_CTL_IOCTL_ELEM_UNLOCK _IOW('U', 0x15, struct snd_ctl_elem_id)
766#define SNDRV_CTL_IOCTL_SUBSCRIBE_EVENTS _IOWR('U', 0x16, int)
767#define SNDRV_CTL_IOCTL_ELEM_ADD _IOWR('U', 0x17, struct snd_ctl_elem_info)
768#define SNDRV_CTL_IOCTL_ELEM_REPLACE _IOWR('U', 0x18, struct snd_ctl_elem_info)
769#define SNDRV_CTL_IOCTL_ELEM_REMOVE _IOWR('U', 0x19, struct snd_ctl_elem_id)
770#define SNDRV_CTL_IOCTL_TLV_READ _IOWR('U', 0x1a, struct snd_ctl_tlv)
771#define SNDRV_CTL_IOCTL_TLV_WRITE _IOWR('U', 0x1b, struct snd_ctl_tlv)
772#define SNDRV_CTL_IOCTL_TLV_COMMAND _IOWR('U', 0x1c, struct snd_ctl_tlv)
773#define SNDRV_CTL_IOCTL_HWDEP_NEXT_DEVICE _IOWR('U', 0x20, int)
774#define SNDRV_CTL_IOCTL_HWDEP_INFO _IOR('U', 0x21, struct snd_hwdep_info)
775#define SNDRV_CTL_IOCTL_PCM_NEXT_DEVICE _IOR('U', 0x30, int)
776#define SNDRV_CTL_IOCTL_PCM_INFO _IOWR('U', 0x31, struct snd_pcm_info)
777#define SNDRV_CTL_IOCTL_PCM_PREFER_SUBDEVICE _IOW('U', 0x32, int)
778#define SNDRV_CTL_IOCTL_RAWMIDI_NEXT_DEVICE _IOWR('U', 0x40, int)
779#define SNDRV_CTL_IOCTL_RAWMIDI_INFO _IOWR('U', 0x41, struct snd_rawmidi_info)
780#define SNDRV_CTL_IOCTL_RAWMIDI_PREFER_SUBDEVICE _IOW('U', 0x42, int)
781#define SNDRV_CTL_IOCTL_POWER _IOWR('U', 0xd0, int)
782#define SNDRV_CTL_IOCTL_POWER_STATE _IOR('U', 0xd1, int)
783
784enum sndrv_ctl_event_type {
785 SNDRV_CTL_EVENT_ELEM = 0,
786 SNDRV_CTL_EVENT_LAST = SNDRV_CTL_EVENT_ELEM,
787};
788
789#define SNDRV_CTL_EVENT_MASK_VALUE (1<<0)
790#define SNDRV_CTL_EVENT_MASK_INFO (1<<1)
791#define SNDRV_CTL_EVENT_MASK_ADD (1<<2)
792#define SNDRV_CTL_EVENT_MASK_TLV (1<<3)
793#define SNDRV_CTL_EVENT_MASK_REMOVE (~0U)
794
795struct snd_ctl_event {
796 int type;
797 union {
798 struct {
799 unsigned int mask;
800 struct snd_ctl_elem_id id;
801 } elem;
802 unsigned char data8[60];
803 } data;
804};
805
806#define SNDRV_CTL_NAME_NONE ""
807#define SNDRV_CTL_NAME_PLAYBACK "Playback "
808#define SNDRV_CTL_NAME_CAPTURE "Capture "
809
810#define SNDRV_CTL_NAME_IEC958_NONE ""
811#define SNDRV_CTL_NAME_IEC958_SWITCH "Switch"
812#define SNDRV_CTL_NAME_IEC958_VOLUME "Volume"
813#define SNDRV_CTL_NAME_IEC958_DEFAULT "Default"
814#define SNDRV_CTL_NAME_IEC958_MASK "Mask"
815#define SNDRV_CTL_NAME_IEC958_CON_MASK "Con Mask"
816#define SNDRV_CTL_NAME_IEC958_PRO_MASK "Pro Mask"
817#define SNDRV_CTL_NAME_IEC958_PCM_STREAM "PCM Stream"
818#define SNDRV_CTL_NAME_IEC958(expl,direction,what) "IEC958 " expl SNDRV_CTL_NAME_##direction SNDRV_CTL_NAME_IEC958_##what
819
820#endif
821
diff --git a/firmware/target/hosted/android/dx50/tinyalsa/asoundlib.h b/firmware/target/hosted/android/dx50/tinyalsa/asoundlib.h
new file mode 100644
index 0000000000..6aacae46d6
--- /dev/null
+++ b/firmware/target/hosted/android/dx50/tinyalsa/asoundlib.h
@@ -0,0 +1,257 @@
1/* asoundlib.h
2**
3** Copyright 2011, The Android Open Source Project
4**
5** Redistribution and use in source and binary forms, with or without
6** modification, are permitted provided that the following conditions are met:
7** * Redistributions of source code must retain the above copyright
8** notice, this list of conditions and the following disclaimer.
9** * Redistributions in binary form must reproduce the above copyright
10** notice, this list of conditions and the following disclaimer in the
11** documentation and/or other materials provided with the distribution.
12** * Neither the name of The Android Open Source Project nor the names of
13** its contributors may be used to endorse or promote products derived
14** from this software without specific prior written permission.
15**
16** THIS SOFTWARE IS PROVIDED BY The Android Open Source Project ``AS IS'' AND
17** ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
18** IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
19** ARE DISCLAIMED. IN NO EVENT SHALL The Android Open Source Project BE LIABLE
20** FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
21** DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
22** SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
23** CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
24** LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
25** OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
26** DAMAGE.
27*/
28
29#ifndef ASOUNDLIB_H
30#define ASOUNDLIB_H
31
32#include <sys/time.h>
33#include <stddef.h>
34
35#if defined(__cplusplus)
36extern "C" {
37#endif
38
39/*
40 * PCM API
41 */
42
43struct pcm;
44
45#define PCM_OUT 0x00000000
46#define PCM_IN 0x10000000
47#define PCM_MMAP 0x00000001
48#define PCM_NOIRQ 0x00000002
49#define PCM_NORESTART 0x00000004 /* PCM_NORESTART - when set, calls to
50 * pcm_write for a playback stream will not
51 * attempt to restart the stream in the case
52 * of an underflow, but will return -EPIPE
53 * instead. After the first -EPIPE error, the
54 * stream is considered to be stopped, and a
55 * second call to pcm_write will attempt to
56 * restart the stream.
57 */
58
59/* PCM runtime states */
60#define PCM_STATE_OPEN 0
61#define PCM_STATE_SETUP 1
62#define PCM_STATE_PREPARED 2
63#define PCM_STATE_RUNNING 3
64#define PCM_STATE_XRUN 4
65#define PCM_STATE_DRAINING 5
66#define PCM_STATE_PAUSED 6
67#define PCM_STATE_SUSPENDED 7
68#define PCM_STATE_DISCONNECTED 8
69
70/* Bit formats */
71enum pcm_format {
72 PCM_FORMAT_S16_LE = 0,
73 PCM_FORMAT_S32_LE,
74 PCM_FORMAT_S8,
75 PCM_FORMAT_S24_LE,
76
77 PCM_FORMAT_MAX,
78};
79
80/* Configuration for a stream */
81struct pcm_config {
82 unsigned int channels;
83 unsigned int rate;
84 unsigned int period_size;
85 unsigned int period_count;
86 enum pcm_format format;
87
88 /* Values to use for the ALSA start, stop and silence thresholds. Setting
89 * any one of these values to 0 will cause the default tinyalsa values to be
90 * used instead. Tinyalsa defaults are as follows.
91 *
92 * start_threshold : period_count * period_size
93 * stop_threshold : period_count * period_size
94 * silence_threshold : 0
95 */
96 unsigned int start_threshold;
97 unsigned int stop_threshold;
98 unsigned int silence_threshold;
99};
100
101/* PCM parameters */
102enum pcm_param
103{
104 PCM_PARAM_SAMPLE_BITS,
105 PCM_PARAM_FRAME_BITS,
106 PCM_PARAM_CHANNELS,
107 PCM_PARAM_RATE,
108 PCM_PARAM_PERIOD_TIME,
109 PCM_PARAM_PERIOD_SIZE,
110 PCM_PARAM_PERIOD_BYTES,
111 PCM_PARAM_PERIODS,
112 PCM_PARAM_BUFFER_TIME,
113 PCM_PARAM_BUFFER_SIZE,
114 PCM_PARAM_BUFFER_BYTES,
115 PCM_PARAM_TICK_TIME,
116};
117
118/* Mixer control types */
119enum mixer_ctl_type {
120 MIXER_CTL_TYPE_BOOL,
121 MIXER_CTL_TYPE_INT,
122 MIXER_CTL_TYPE_ENUM,
123 MIXER_CTL_TYPE_BYTE,
124 MIXER_CTL_TYPE_IEC958,
125 MIXER_CTL_TYPE_INT64,
126 MIXER_CTL_TYPE_UNKNOWN,
127
128 MIXER_CTL_TYPE_MAX,
129};
130
131/* Open and close a stream */
132struct pcm *pcm_open(unsigned int card, unsigned int device,
133 unsigned int flags, struct pcm_config *config);
134int pcm_close(struct pcm *pcm);
135int pcm_is_ready(struct pcm *pcm);
136
137/* Obtain the parameters for a PCM */
138struct pcm_params *pcm_params_get(unsigned int card, unsigned int device,
139 unsigned int flags);
140void pcm_params_free(struct pcm_params *pcm_params);
141unsigned int pcm_params_get_min(struct pcm_params *pcm_params,
142 enum pcm_param param);
143unsigned int pcm_params_get_max(struct pcm_params *pcm_params,
144 enum pcm_param param);
145
146/* Set and get config */
147int pcm_get_config(struct pcm *pcm, struct pcm_config *config);
148int pcm_set_config(struct pcm *pcm, struct pcm_config *config);
149
150/* Returns a human readable reason for the last error */
151const char *pcm_get_error(struct pcm *pcm);
152
153/* Returns the sample size in bits for a PCM format.
154 * As with ALSA formats, this is the storage size for the format, whereas the
155 * format represents the number of significant bits. For example,
156 * PCM_FORMAT_S24_LE uses 32 bits of storage.
157 */
158unsigned int pcm_format_to_bits(enum pcm_format format);
159
160/* Returns the buffer size (int frames) that should be used for pcm_write. */
161unsigned int pcm_get_buffer_size(struct pcm *pcm);
162unsigned int pcm_frames_to_bytes(struct pcm *pcm, unsigned int frames);
163unsigned int pcm_bytes_to_frames(struct pcm *pcm, unsigned int bytes);
164
165/* Returns the pcm latency in ms */
166unsigned int pcm_get_latency(struct pcm *pcm);
167
168/* Returns available frames in pcm buffer and corresponding time stamp.
169 * For an input stream, frames available are frames ready for the
170 * application to read.
171 * For an output stream, frames available are the number of empty frames available
172 * for the application to write.
173 */
174int pcm_get_htimestamp(struct pcm *pcm, unsigned int *avail,
175 struct timespec *tstamp);
176
177/* Write data to the fifo.
178 * Will start playback on the first write or on a write that
179 * occurs after a fifo underrun.
180 */
181int pcm_write(struct pcm *pcm, const void *data, unsigned int count);
182int pcm_read(struct pcm *pcm, void *data, unsigned int count);
183
184/*
185 * mmap() support.
186 */
187int pcm_mmap_write(struct pcm *pcm, const void *data, unsigned int count);
188int pcm_mmap_begin(struct pcm *pcm, void **areas, unsigned int *offset,
189 unsigned int *frames);
190int pcm_mmap_commit(struct pcm *pcm, unsigned int offset, unsigned int frames);
191
192
193/* Start and stop a PCM channel that doesn't transfer data */
194int pcm_start(struct pcm *pcm);
195int pcm_stop(struct pcm *pcm);
196
197/* Interrupt driven API */
198int pcm_wait(struct pcm *pcm, int timeout);
199
200int pcm_avail_update(struct pcm *pcm);
201
202int pcm_state(struct pcm *pcm);
203
204
205/*
206 * MIXER API
207 */
208
209struct mixer;
210struct mixer_ctl;
211
212/* Open and close a mixer */
213struct mixer *mixer_open(unsigned int card);
214void mixer_close(struct mixer *mixer);
215
216/* Get info about a mixer */
217const char *mixer_get_name(struct mixer *mixer);
218
219/* Obtain mixer controls */
220unsigned int mixer_get_num_ctls(struct mixer *mixer);
221struct mixer_ctl *mixer_get_ctl(struct mixer *mixer, unsigned int id);
222struct mixer_ctl *mixer_get_ctl_by_name(struct mixer *mixer, const char *name);
223
224/* Get info about mixer controls */
225const char *mixer_ctl_get_name(struct mixer_ctl *ctl);
226enum mixer_ctl_type mixer_ctl_get_type(struct mixer_ctl *ctl);
227const char *mixer_ctl_get_type_string(struct mixer_ctl *ctl);
228unsigned int mixer_ctl_get_num_values(struct mixer_ctl *ctl);
229unsigned int mixer_ctl_get_num_enums(struct mixer_ctl *ctl);
230const char *mixer_ctl_get_enum_string(struct mixer_ctl *ctl,
231 unsigned int enum_id);
232
233/* Some sound cards update their controls due to external events,
234 * such as HDMI EDID byte data changing when an HDMI cable is
235 * connected. This API allows the count of elements to be updated.
236 */
237void mixer_ctl_update(struct mixer_ctl *ctl);
238
239/* Set and get mixer controls */
240int mixer_ctl_get_percent(struct mixer_ctl *ctl, unsigned int id);
241int mixer_ctl_set_percent(struct mixer_ctl *ctl, unsigned int id, int percent);
242
243int mixer_ctl_get_value(struct mixer_ctl *ctl, unsigned int id);
244int mixer_ctl_get_array(struct mixer_ctl *ctl, void *array, size_t count);
245int mixer_ctl_set_value(struct mixer_ctl *ctl, unsigned int id, int value);
246int mixer_ctl_set_array(struct mixer_ctl *ctl, const void *array, size_t count);
247int mixer_ctl_set_enum_by_string(struct mixer_ctl *ctl, const char *string);
248
249/* Determe range of integer mixer controls */
250int mixer_ctl_get_range_min(struct mixer_ctl *ctl);
251int mixer_ctl_get_range_max(struct mixer_ctl *ctl);
252
253#if defined(__cplusplus)
254} /* extern "C" */
255#endif
256
257#endif
diff --git a/firmware/target/hosted/android/dx50/tinyalsa/mixer.c b/firmware/target/hosted/android/dx50/tinyalsa/mixer.c
new file mode 100644
index 0000000000..f75dec488a
--- /dev/null
+++ b/firmware/target/hosted/android/dx50/tinyalsa/mixer.c
@@ -0,0 +1,497 @@
1/* mixer.c
2**
3** Copyright 2011, The Android Open Source Project
4**
5** Redistribution and use in source and binary forms, with or without
6** modification, are permitted provided that the following conditions are met:
7** * Redistributions of source code must retain the above copyright
8** notice, this list of conditions and the following disclaimer.
9** * Redistributions in binary form must reproduce the above copyright
10** notice, this list of conditions and the following disclaimer in the
11** documentation and/or other materials provided with the distribution.
12** * Neither the name of The Android Open Source Project nor the names of
13** its contributors may be used to endorse or promote products derived
14** from this software without specific prior written permission.
15**
16** THIS SOFTWARE IS PROVIDED BY The Android Open Source Project ``AS IS'' AND
17** ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
18** IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
19** ARE DISCLAIMED. IN NO EVENT SHALL The Android Open Source Project BE LIABLE
20** FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
21** DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
22** SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
23** CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
24** LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
25** OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
26** DAMAGE.
27*/
28
29#include <stdio.h>
30#include <stdlib.h>
31#include <string.h>
32#include <unistd.h>
33#include <fcntl.h>
34#include <errno.h>
35#include <ctype.h>
36
37#include <sys/ioctl.h>
38
39#include <linux/ioctl.h>
40#define __force
41#define __bitwise
42#define __user
43#include <tinyalsa/asound.h>
44
45#include <tinyalsa/asoundlib.h>
46
47struct mixer_ctl {
48 struct mixer *mixer;
49 struct snd_ctl_elem_info *info;
50 char **ename;
51};
52
53struct mixer {
54 int fd;
55 struct snd_ctl_card_info card_info;
56 struct snd_ctl_elem_info *elem_info;
57 struct mixer_ctl *ctl;
58 unsigned int count;
59};
60
61void mixer_close(struct mixer *mixer)
62{
63 unsigned int n,m;
64
65 if (!mixer)
66 return;
67
68 if (mixer->fd >= 0)
69 close(mixer->fd);
70
71 if (mixer->ctl) {
72 for (n = 0; n < mixer->count; n++) {
73 if (mixer->ctl[n].ename) {
74 unsigned int max = mixer->ctl[n].info->value.enumerated.items;
75 for (m = 0; m < max; m++)
76 free(mixer->ctl[n].ename[m]);
77 free(mixer->ctl[n].ename);
78 }
79 }
80 free(mixer->ctl);
81 }
82
83 if (mixer->elem_info)
84 free(mixer->elem_info);
85
86 free(mixer);
87
88 /* TODO: verify frees */
89}
90
91struct mixer *mixer_open(unsigned int card)
92{
93 struct snd_ctl_elem_list elist;
94 struct snd_ctl_elem_info tmp;
95 struct snd_ctl_elem_id *eid = NULL;
96 struct mixer *mixer = NULL;
97 unsigned int n, m;
98 int fd;
99 char fn[256];
100
101 snprintf(fn, sizeof(fn), "/dev/snd/controlC%u", card);
102 fd = open(fn, O_RDWR);
103 if (fd < 0)
104 return 0;
105
106 memset(&elist, 0, sizeof(elist));
107 if (ioctl(fd, SNDRV_CTL_IOCTL_ELEM_LIST, &elist) < 0)
108 goto fail;
109
110 mixer = calloc(1, sizeof(*mixer));
111 if (!mixer)
112 goto fail;
113
114 mixer->ctl = calloc(elist.count, sizeof(struct mixer_ctl));
115 mixer->elem_info = calloc(elist.count, sizeof(struct snd_ctl_elem_info));
116 if (!mixer->ctl || !mixer->elem_info)
117 goto fail;
118
119 if (ioctl(fd, SNDRV_CTL_IOCTL_CARD_INFO, &mixer->card_info) < 0)
120 goto fail;
121
122 eid = calloc(elist.count, sizeof(struct snd_ctl_elem_id));
123 if (!eid)
124 goto fail;
125
126 mixer->count = elist.count;
127 mixer->fd = fd;
128 elist.space = mixer->count;
129 elist.pids = eid;
130 if (ioctl(fd, SNDRV_CTL_IOCTL_ELEM_LIST, &elist) < 0)
131 goto fail;
132
133 for (n = 0; n < mixer->count; n++) {
134 struct snd_ctl_elem_info *ei = mixer->elem_info + n;
135 ei->id.numid = eid[n].numid;
136 if (ioctl(fd, SNDRV_CTL_IOCTL_ELEM_INFO, ei) < 0)
137 goto fail;
138 mixer->ctl[n].info = ei;
139 mixer->ctl[n].mixer = mixer;
140 if (ei->type == SNDRV_CTL_ELEM_TYPE_ENUMERATED) {
141 char **enames = calloc(ei->value.enumerated.items, sizeof(char*));
142 if (!enames)
143 goto fail;
144 mixer->ctl[n].ename = enames;
145 for (m = 0; m < ei->value.enumerated.items; m++) {
146 memset(&tmp, 0, sizeof(tmp));
147 tmp.id.numid = ei->id.numid;
148 tmp.value.enumerated.item = m;
149 if (ioctl(fd, SNDRV_CTL_IOCTL_ELEM_INFO, &tmp) < 0)
150 goto fail;
151 enames[m] = strdup(tmp.value.enumerated.name);
152 if (!enames[m])
153 goto fail;
154 }
155 }
156 }
157
158 free(eid);
159 return mixer;
160
161fail:
162 /* TODO: verify frees in failure case */
163 if (eid)
164 free(eid);
165 if (mixer)
166 mixer_close(mixer);
167 else if (fd >= 0)
168 close(fd);
169 return 0;
170}
171
172const char *mixer_get_name(struct mixer *mixer)
173{
174 return (const char *)mixer->card_info.name;
175}
176
177unsigned int mixer_get_num_ctls(struct mixer *mixer)
178{
179 if (!mixer)
180 return 0;
181
182 return mixer->count;
183}
184
185struct mixer_ctl *mixer_get_ctl(struct mixer *mixer, unsigned int id)
186{
187 if (mixer && (id < mixer->count))
188 return mixer->ctl + id;
189
190 return NULL;
191}
192
193struct mixer_ctl *mixer_get_ctl_by_name(struct mixer *mixer, const char *name)
194{
195 unsigned int n;
196
197 if (!mixer)
198 return NULL;
199
200 for (n = 0; n < mixer->count; n++)
201 if (!strcmp(name, (char*) mixer->elem_info[n].id.name))
202 return mixer->ctl + n;
203
204 return NULL;
205}
206
207void mixer_ctl_update(struct mixer_ctl *ctl)
208{
209 ioctl(ctl->mixer->fd, SNDRV_CTL_IOCTL_ELEM_INFO, ctl->info);
210}
211
212const char *mixer_ctl_get_name(struct mixer_ctl *ctl)
213{
214 if (!ctl)
215 return NULL;
216
217 return (const char *)ctl->info->id.name;
218}
219
220enum mixer_ctl_type mixer_ctl_get_type(struct mixer_ctl *ctl)
221{
222 if (!ctl)
223 return MIXER_CTL_TYPE_UNKNOWN;
224
225 switch (ctl->info->type) {
226 case SNDRV_CTL_ELEM_TYPE_BOOLEAN: return MIXER_CTL_TYPE_BOOL;
227 case SNDRV_CTL_ELEM_TYPE_INTEGER: return MIXER_CTL_TYPE_INT;
228 case SNDRV_CTL_ELEM_TYPE_ENUMERATED: return MIXER_CTL_TYPE_ENUM;
229 case SNDRV_CTL_ELEM_TYPE_BYTES: return MIXER_CTL_TYPE_BYTE;
230 case SNDRV_CTL_ELEM_TYPE_IEC958: return MIXER_CTL_TYPE_IEC958;
231 case SNDRV_CTL_ELEM_TYPE_INTEGER64: return MIXER_CTL_TYPE_INT64;
232 default: return MIXER_CTL_TYPE_UNKNOWN;
233 };
234}
235
236const char *mixer_ctl_get_type_string(struct mixer_ctl *ctl)
237{
238 if (!ctl)
239 return "";
240
241 switch (ctl->info->type) {
242 case SNDRV_CTL_ELEM_TYPE_BOOLEAN: return "BOOL";
243 case SNDRV_CTL_ELEM_TYPE_INTEGER: return "INT";
244 case SNDRV_CTL_ELEM_TYPE_ENUMERATED: return "ENUM";
245 case SNDRV_CTL_ELEM_TYPE_BYTES: return "BYTE";
246 case SNDRV_CTL_ELEM_TYPE_IEC958: return "IEC958";
247 case SNDRV_CTL_ELEM_TYPE_INTEGER64: return "INT64";
248 default: return "Unknown";
249 };
250}
251
252unsigned int mixer_ctl_get_num_values(struct mixer_ctl *ctl)
253{
254 if (!ctl)
255 return 0;
256
257 return ctl->info->count;
258}
259
260static int percent_to_int(struct snd_ctl_elem_info *ei, int percent)
261{
262 int range;
263
264 if (percent > 100)
265 percent = 100;
266 else if (percent < 0)
267 percent = 0;
268
269 range = (ei->value.integer.max - ei->value.integer.min);
270
271 return ei->value.integer.min + (range * percent) / 100;
272}
273
274static int int_to_percent(struct snd_ctl_elem_info *ei, int value)
275{
276 int range = (ei->value.integer.max - ei->value.integer.min);
277
278 if (range == 0)
279 return 0;
280
281 return ((value - ei->value.integer.min) / range) * 100;
282}
283
284int mixer_ctl_get_percent(struct mixer_ctl *ctl, unsigned int id)
285{
286 if (!ctl || (ctl->info->type != SNDRV_CTL_ELEM_TYPE_INTEGER))
287 return -EINVAL;
288
289 return int_to_percent(ctl->info, mixer_ctl_get_value(ctl, id));
290}
291
292int mixer_ctl_set_percent(struct mixer_ctl *ctl, unsigned int id, int percent)
293{
294 if (!ctl || (ctl->info->type != SNDRV_CTL_ELEM_TYPE_INTEGER))
295 return -EINVAL;
296
297 return mixer_ctl_set_value(ctl, id, percent_to_int(ctl->info, percent));
298}
299
300int mixer_ctl_get_value(struct mixer_ctl *ctl, unsigned int id)
301{
302 struct snd_ctl_elem_value ev;
303 int ret;
304
305 if (!ctl || (id >= ctl->info->count))
306 return -EINVAL;
307
308 memset(&ev, 0, sizeof(ev));
309 ev.id.numid = ctl->info->id.numid;
310 ret = ioctl(ctl->mixer->fd, SNDRV_CTL_IOCTL_ELEM_READ, &ev);
311 if (ret < 0)
312 return ret;
313
314 switch (ctl->info->type) {
315 case SNDRV_CTL_ELEM_TYPE_BOOLEAN:
316 return !!ev.value.integer.value[id];
317
318 case SNDRV_CTL_ELEM_TYPE_INTEGER:
319 return ev.value.integer.value[id];
320
321 case SNDRV_CTL_ELEM_TYPE_ENUMERATED:
322 return ev.value.enumerated.item[id];
323
324 case SNDRV_CTL_ELEM_TYPE_BYTES:
325 return ev.value.bytes.data[id];
326
327 default:
328 return -EINVAL;
329 }
330
331 return 0;
332}
333
334int mixer_ctl_get_array(struct mixer_ctl *ctl, void *array, size_t count)
335{
336 struct snd_ctl_elem_value ev;
337 int ret;
338 size_t size;
339 void *source;
340
341 if (!ctl || (count > ctl->info->count) || !count || !array)
342 return -EINVAL;
343
344 memset(&ev, 0, sizeof(ev));
345 ev.id.numid = ctl->info->id.numid;
346
347 ret = ioctl(ctl->mixer->fd, SNDRV_CTL_IOCTL_ELEM_READ, &ev);
348 if (ret < 0)
349 return ret;
350
351 switch (ctl->info->type) {
352 case SNDRV_CTL_ELEM_TYPE_BOOLEAN:
353 case SNDRV_CTL_ELEM_TYPE_INTEGER:
354 size = sizeof(ev.value.integer.value[0]);
355 source = ev.value.integer.value;
356 break;
357
358 case SNDRV_CTL_ELEM_TYPE_BYTES:
359 size = sizeof(ev.value.bytes.data[0]);
360 source = ev.value.bytes.data;
361 break;
362
363 default:
364 return -EINVAL;
365 }
366
367 memcpy(array, source, size * count);
368
369 return 0;
370}
371
372int mixer_ctl_set_value(struct mixer_ctl *ctl, unsigned int id, int value)
373{
374 struct snd_ctl_elem_value ev;
375 int ret;
376
377 if (!ctl || (id >= ctl->info->count))
378 return -EINVAL;
379
380 memset(&ev, 0, sizeof(ev));
381 ev.id.numid = ctl->info->id.numid;
382 ret = ioctl(ctl->mixer->fd, SNDRV_CTL_IOCTL_ELEM_READ, &ev);
383 if (ret < 0)
384 return ret;
385
386 switch (ctl->info->type) {
387 case SNDRV_CTL_ELEM_TYPE_BOOLEAN:
388 ev.value.integer.value[id] = !!value;
389 break;
390
391 case SNDRV_CTL_ELEM_TYPE_INTEGER:
392 ev.value.integer.value[id] = value;
393 break;
394
395 case SNDRV_CTL_ELEM_TYPE_ENUMERATED:
396 ev.value.enumerated.item[id] = value;
397 break;
398
399 default:
400 return -EINVAL;
401 }
402
403 return ioctl(ctl->mixer->fd, SNDRV_CTL_IOCTL_ELEM_WRITE, &ev);
404}
405
406int mixer_ctl_set_array(struct mixer_ctl *ctl, const void *array, size_t count)
407{
408 struct snd_ctl_elem_value ev;
409 size_t size;
410 void *dest;
411
412 if (!ctl || (count > ctl->info->count) || !count || !array)
413 return -EINVAL;
414
415 memset(&ev, 0, sizeof(ev));
416 ev.id.numid = ctl->info->id.numid;
417
418 switch (ctl->info->type) {
419 case SNDRV_CTL_ELEM_TYPE_BOOLEAN:
420 case SNDRV_CTL_ELEM_TYPE_INTEGER:
421 size = sizeof(ev.value.integer.value[0]);
422 dest = ev.value.integer.value;
423 break;
424
425 case SNDRV_CTL_ELEM_TYPE_BYTES:
426 size = sizeof(ev.value.bytes.data[0]);
427 dest = ev.value.bytes.data;
428 break;
429
430 default:
431 return -EINVAL;
432 }
433
434 memcpy(dest, array, size * count);
435
436 return ioctl(ctl->mixer->fd, SNDRV_CTL_IOCTL_ELEM_WRITE, &ev);
437}
438
439int mixer_ctl_get_range_min(struct mixer_ctl *ctl)
440{
441 if (!ctl || (ctl->info->type != SNDRV_CTL_ELEM_TYPE_INTEGER))
442 return -EINVAL;
443
444 return ctl->info->value.integer.min;
445}
446
447int mixer_ctl_get_range_max(struct mixer_ctl *ctl)
448{
449 if (!ctl || (ctl->info->type != SNDRV_CTL_ELEM_TYPE_INTEGER))
450 return -EINVAL;
451
452 return ctl->info->value.integer.max;
453}
454
455unsigned int mixer_ctl_get_num_enums(struct mixer_ctl *ctl)
456{
457 if (!ctl)
458 return 0;
459
460 return ctl->info->value.enumerated.items;
461}
462
463const char *mixer_ctl_get_enum_string(struct mixer_ctl *ctl,
464 unsigned int enum_id)
465{
466 if (!ctl || (ctl->info->type != SNDRV_CTL_ELEM_TYPE_ENUMERATED) ||
467 (enum_id >= ctl->info->value.enumerated.items))
468 return NULL;
469
470 return (const char *)ctl->ename[enum_id];
471}
472
473int mixer_ctl_set_enum_by_string(struct mixer_ctl *ctl, const char *string)
474{
475 unsigned int i, num_enums;
476 struct snd_ctl_elem_value ev;
477 int ret;
478
479 if (!ctl || (ctl->info->type != SNDRV_CTL_ELEM_TYPE_ENUMERATED))
480 return -EINVAL;
481
482 num_enums = ctl->info->value.enumerated.items;
483 for (i = 0; i < num_enums; i++) {
484 if (!strcmp(string, ctl->ename[i])) {
485 memset(&ev, 0, sizeof(ev));
486 ev.value.enumerated.item[0] = i;
487 ev.id.numid = ctl->info->id.numid;
488 ret = ioctl(ctl->mixer->fd, SNDRV_CTL_IOCTL_ELEM_WRITE, &ev);
489 if (ret < 0)
490 return ret;
491 return 0;
492 }
493 }
494
495 return -EINVAL;
496}
497
diff --git a/firmware/target/hosted/android/dx50/tinyalsa/pcm.c b/firmware/target/hosted/android/dx50/tinyalsa/pcm.c
new file mode 100644
index 0000000000..bd44dce52f
--- /dev/null
+++ b/firmware/target/hosted/android/dx50/tinyalsa/pcm.c
@@ -0,0 +1,973 @@
1/* pcm.c
2**
3** Copyright 2011, The Android Open Source Project
4**
5** Redistribution and use in source and binary forms, with or without
6** modification, are permitted provided that the following conditions are met:
7** * Redistributions of source code must retain the above copyright
8** notice, this list of conditions and the following disclaimer.
9** * Redistributions in binary form must reproduce the above copyright
10** notice, this list of conditions and the following disclaimer in the
11** documentation and/or other materials provided with the distribution.
12** * Neither the name of The Android Open Source Project nor the names of
13** its contributors may be used to endorse or promote products derived
14** from this software without specific prior written permission.
15**
16** THIS SOFTWARE IS PROVIDED BY The Android Open Source Project ``AS IS'' AND
17** ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
18** IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
19** ARE DISCLAIMED. IN NO EVENT SHALL The Android Open Source Project BE LIABLE
20** FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
21** DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
22** SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
23** CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
24** LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
25** OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
26** DAMAGE.
27*/
28
29#include <stdio.h>
30#include <stdlib.h>
31#include <fcntl.h>
32#include <stdarg.h>
33#include <string.h>
34#include <errno.h>
35#include <unistd.h>
36#include <poll.h>
37
38#include <sys/ioctl.h>
39#include <sys/mman.h>
40#include <sys/time.h>
41#include <limits.h>
42
43#include <linux/ioctl.h>
44#define __force
45#define __bitwise
46#define __user
47#include <tinyalsa/asound.h>
48
49#include <tinyalsa/asoundlib.h>
50
51#define PARAM_MAX SNDRV_PCM_HW_PARAM_LAST_INTERVAL
52#define SNDRV_PCM_HW_PARAMS_NO_PERIOD_WAKEUP (1<<2)
53
54static inline int param_is_mask(int p)
55{
56 return (p >= SNDRV_PCM_HW_PARAM_FIRST_MASK) &&
57 (p <= SNDRV_PCM_HW_PARAM_LAST_MASK);
58}
59
60static inline int param_is_interval(int p)
61{
62 return (p >= SNDRV_PCM_HW_PARAM_FIRST_INTERVAL) &&
63 (p <= SNDRV_PCM_HW_PARAM_LAST_INTERVAL);
64}
65
66static inline struct snd_interval *param_to_interval(struct snd_pcm_hw_params *p, int n)
67{
68 return &(p->intervals[n - SNDRV_PCM_HW_PARAM_FIRST_INTERVAL]);
69}
70
71static inline struct snd_mask *param_to_mask(struct snd_pcm_hw_params *p, int n)
72{
73 return &(p->masks[n - SNDRV_PCM_HW_PARAM_FIRST_MASK]);
74}
75
76static void param_set_mask(struct snd_pcm_hw_params *p, int n, unsigned int bit)
77{
78 if (bit >= SNDRV_MASK_MAX)
79 return;
80 if (param_is_mask(n)) {
81 struct snd_mask *m = param_to_mask(p, n);
82 m->bits[0] = 0;
83 m->bits[1] = 0;
84 m->bits[bit >> 5] |= (1 << (bit & 31));
85 }
86}
87
88static void param_set_min(struct snd_pcm_hw_params *p, int n, unsigned int val)
89{
90 if (param_is_interval(n)) {
91 struct snd_interval *i = param_to_interval(p, n);
92 i->min = val;
93 }
94}
95
96static unsigned int param_get_min(struct snd_pcm_hw_params *p, int n)
97{
98 if (param_is_interval(n)) {
99 struct snd_interval *i = param_to_interval(p, n);
100 return i->min;
101 }
102 return 0;
103}
104
105static unsigned int param_get_max(struct snd_pcm_hw_params *p, int n)
106{
107 if (param_is_interval(n)) {
108 struct snd_interval *i = param_to_interval(p, n);
109 return i->max;
110 }
111 return 0;
112}
113
114static void param_set_int(struct snd_pcm_hw_params *p, int n, unsigned int val)
115{
116 if (param_is_interval(n)) {
117 struct snd_interval *i = param_to_interval(p, n);
118 i->min = val;
119 i->max = val;
120 i->integer = 1;
121 }
122}
123
124static unsigned int param_get_int(struct snd_pcm_hw_params *p, int n)
125{
126 if (param_is_interval(n)) {
127 struct snd_interval *i = param_to_interval(p, n);
128 if (i->integer)
129 return i->max;
130 }
131 return 0;
132}
133
134static void param_init(struct snd_pcm_hw_params *p)
135{
136 int n;
137
138 memset(p, 0, sizeof(*p));
139 for (n = SNDRV_PCM_HW_PARAM_FIRST_MASK;
140 n <= SNDRV_PCM_HW_PARAM_LAST_MASK; n++) {
141 struct snd_mask *m = param_to_mask(p, n);
142 m->bits[0] = ~0;
143 m->bits[1] = ~0;
144 }
145 for (n = SNDRV_PCM_HW_PARAM_FIRST_INTERVAL;
146 n <= SNDRV_PCM_HW_PARAM_LAST_INTERVAL; n++) {
147 struct snd_interval *i = param_to_interval(p, n);
148 i->min = 0;
149 i->max = ~0;
150 }
151 p->rmask = ~0U;
152 p->cmask = 0;
153 p->info = ~0U;
154}
155
156#define PCM_ERROR_MAX 128
157
158struct pcm {
159 int fd;
160 unsigned int flags;
161 int running:1;
162 int underruns;
163 unsigned int buffer_size;
164 unsigned int boundary;
165 char error[PCM_ERROR_MAX];
166 struct pcm_config config;
167 struct snd_pcm_mmap_status *mmap_status;
168 struct snd_pcm_mmap_control *mmap_control;
169 struct snd_pcm_sync_ptr *sync_ptr;
170 void *mmap_buffer;
171 unsigned int noirq_frames_per_msec;
172};
173
174unsigned int pcm_get_buffer_size(struct pcm *pcm)
175{
176 return pcm->buffer_size;
177}
178
179const char* pcm_get_error(struct pcm *pcm)
180{
181 return pcm->error;
182}
183
184static int oops(struct pcm *pcm, int e, const char *fmt, ...)
185{
186 va_list ap;
187 int sz;
188
189 va_start(ap, fmt);
190 vsnprintf(pcm->error, PCM_ERROR_MAX, fmt, ap);
191 va_end(ap);
192 sz = strlen(pcm->error);
193
194 if (errno)
195 snprintf(pcm->error + sz, PCM_ERROR_MAX - sz,
196 ": %s", strerror(e));
197 return -1;
198}
199
200static unsigned int pcm_format_to_alsa(enum pcm_format format)
201{
202 switch (format) {
203 case PCM_FORMAT_S32_LE:
204 return SNDRV_PCM_FORMAT_S32_LE;
205 case PCM_FORMAT_S8:
206 return SNDRV_PCM_FORMAT_S8;
207 case PCM_FORMAT_S24_LE:
208 return SNDRV_PCM_FORMAT_S24_LE;
209 default:
210 case PCM_FORMAT_S16_LE:
211 return SNDRV_PCM_FORMAT_S16_LE;
212 };
213}
214
215unsigned int pcm_format_to_bits(enum pcm_format format)
216{
217 switch (format) {
218 case PCM_FORMAT_S32_LE:
219 case PCM_FORMAT_S24_LE:
220 return 32;
221 default:
222 case PCM_FORMAT_S16_LE:
223 return 16;
224 };
225}
226
227unsigned int pcm_bytes_to_frames(struct pcm *pcm, unsigned int bytes)
228{
229 return bytes / (pcm->config.channels *
230 (pcm_format_to_bits(pcm->config.format) >> 3));
231}
232
233unsigned int pcm_frames_to_bytes(struct pcm *pcm, unsigned int frames)
234{
235 return frames * pcm->config.channels *
236 (pcm_format_to_bits(pcm->config.format) >> 3);
237}
238
239static int pcm_sync_ptr(struct pcm *pcm, int flags) {
240 if (pcm->sync_ptr) {
241 pcm->sync_ptr->flags = flags;
242 if (ioctl(pcm->fd, SNDRV_PCM_IOCTL_SYNC_PTR, pcm->sync_ptr) < 0)
243 return -1;
244 }
245 return 0;
246}
247
248static int pcm_hw_mmap_status(struct pcm *pcm) {
249
250 if (pcm->sync_ptr)
251 return 0;
252
253 int page_size = sysconf(_SC_PAGE_SIZE);
254 pcm->mmap_status = mmap(NULL, page_size, PROT_READ, MAP_FILE | MAP_SHARED,
255 pcm->fd, SNDRV_PCM_MMAP_OFFSET_STATUS);
256 if (pcm->mmap_status == MAP_FAILED)
257 pcm->mmap_status = NULL;
258 if (!pcm->mmap_status)
259 goto mmap_error;
260
261 pcm->mmap_control = mmap(NULL, page_size, PROT_READ | PROT_WRITE,
262 MAP_FILE | MAP_SHARED, pcm->fd, SNDRV_PCM_MMAP_OFFSET_CONTROL);
263 if (pcm->mmap_control == MAP_FAILED)
264 pcm->mmap_control = NULL;
265 if (!pcm->mmap_control) {
266 munmap(pcm->mmap_status, page_size);
267 pcm->mmap_status = NULL;
268 goto mmap_error;
269 }
270 pcm->mmap_control->avail_min = 1;
271
272 return 0;
273
274mmap_error:
275
276 pcm->sync_ptr = calloc(1, sizeof(*pcm->sync_ptr));
277 if (!pcm->sync_ptr)
278 return -ENOMEM;
279 pcm->mmap_status = &pcm->sync_ptr->s.status;
280 pcm->mmap_control = &pcm->sync_ptr->c.control;
281 pcm->mmap_control->avail_min = 1;
282 pcm_sync_ptr(pcm, 0);
283
284 return 0;
285}
286
287static void pcm_hw_munmap_status(struct pcm *pcm) {
288 if (pcm->sync_ptr) {
289 free(pcm->sync_ptr);
290 pcm->sync_ptr = NULL;
291 } else {
292 int page_size = sysconf(_SC_PAGE_SIZE);
293 if (pcm->mmap_status)
294 munmap(pcm->mmap_status, page_size);
295 if (pcm->mmap_control)
296 munmap(pcm->mmap_control, page_size);
297 }
298 pcm->mmap_status = NULL;
299 pcm->mmap_control = NULL;
300}
301
302static int pcm_areas_copy(struct pcm *pcm, unsigned int pcm_offset,
303 const char *src, unsigned int src_offset,
304 unsigned int frames)
305{
306 int size_bytes = pcm_frames_to_bytes(pcm, frames);
307 int pcm_offset_bytes = pcm_frames_to_bytes(pcm, pcm_offset);
308 int src_offset_bytes = pcm_frames_to_bytes(pcm, src_offset);
309
310 /* interleaved only atm */
311 memcpy((char*)pcm->mmap_buffer + pcm_offset_bytes,
312 src + src_offset_bytes, size_bytes);
313 return 0;
314}
315
316static int pcm_mmap_write_areas(struct pcm *pcm, const char *src,
317 unsigned int offset, unsigned int size)
318{
319 void *pcm_areas;
320 int commit;
321 unsigned int pcm_offset, frames, count = 0;
322
323 while (size > 0) {
324 frames = size;
325 pcm_mmap_begin(pcm, &pcm_areas, &pcm_offset, &frames);
326 pcm_areas_copy(pcm, pcm_offset, src, offset, frames);
327 commit = pcm_mmap_commit(pcm, pcm_offset, frames);
328 if (commit < 0) {
329 oops(pcm, commit, "failed to commit %d frames\n", frames);
330 return commit;
331 }
332
333 offset += commit;
334 count += commit;
335 size -= commit;
336 }
337 return count;
338}
339
340int pcm_get_htimestamp(struct pcm *pcm, unsigned int *avail,
341 struct timespec *tstamp)
342{
343 int frames;
344 int rc;
345 snd_pcm_uframes_t hw_ptr;
346
347 if (!pcm_is_ready(pcm))
348 return -1;
349
350 rc = pcm_sync_ptr(pcm, SNDRV_PCM_SYNC_PTR_APPL|SNDRV_PCM_SYNC_PTR_HWSYNC);
351 if (rc < 0)
352 return -1;
353
354 if ((pcm->mmap_status->state != PCM_STATE_RUNNING) &&
355 (pcm->mmap_status->state != PCM_STATE_DRAINING))
356 return -1;
357
358 *tstamp = pcm->mmap_status->tstamp;
359 if (tstamp->tv_sec == 0 && tstamp->tv_nsec == 0)
360 return -1;
361
362 hw_ptr = pcm->mmap_status->hw_ptr;
363 if (pcm->flags & PCM_IN)
364 frames = hw_ptr - pcm->mmap_control->appl_ptr;
365 else
366 frames = hw_ptr + pcm->buffer_size - pcm->mmap_control->appl_ptr;
367
368 if (frames < 0)
369 return -1;
370
371 *avail = (unsigned int)frames;
372
373 return 0;
374}
375
376int pcm_write(struct pcm *pcm, const void *data, unsigned int count)
377{
378 struct snd_xferi x;
379
380 if (pcm->flags & PCM_IN)
381 return -EINVAL;
382
383 x.buf = (void*)data;
384 x.frames = count / (pcm->config.channels *
385 pcm_format_to_bits(pcm->config.format) / 8);
386
387 for (;;) {
388 if (!pcm->running) {
389 if (ioctl(pcm->fd, SNDRV_PCM_IOCTL_PREPARE))
390 return oops(pcm, errno, "cannot prepare channel");
391 if (ioctl(pcm->fd, SNDRV_PCM_IOCTL_WRITEI_FRAMES, &x))
392 return oops(pcm, errno, "cannot write initial data");
393 pcm->running = 1;
394 return 0;
395 }
396 if (ioctl(pcm->fd, SNDRV_PCM_IOCTL_WRITEI_FRAMES, &x)) {
397 pcm->running = 0;
398 if (errno == EPIPE) {
399 /* we failed to make our window -- try to restart if we are
400 * allowed to do so. Otherwise, simply allow the EPIPE error to
401 * propagate up to the app level */
402 pcm->underruns++;
403 if (pcm->flags & PCM_NORESTART)
404 return -EPIPE;
405 continue;
406 }
407 return oops(pcm, errno, "cannot write stream data");
408 }
409 return 0;
410 }
411}
412
413int pcm_read(struct pcm *pcm, void *data, unsigned int count)
414{
415 struct snd_xferi x;
416
417 if (!(pcm->flags & PCM_IN))
418 return -EINVAL;
419
420 x.buf = data;
421 x.frames = count / (pcm->config.channels *
422 pcm_format_to_bits(pcm->config.format) / 8);
423
424 for (;;) {
425 if (!pcm->running) {
426 if (pcm_start(pcm) < 0) {
427 fprintf(stderr, "start error");
428 return -errno;
429 }
430 }
431 if (ioctl(pcm->fd, SNDRV_PCM_IOCTL_READI_FRAMES, &x)) {
432 pcm->running = 0;
433 if (errno == EPIPE) {
434 /* we failed to make our window -- try to restart */
435 pcm->underruns++;
436 continue;
437 }
438 return oops(pcm, errno, "cannot read stream data");
439 }
440 return 0;
441 }
442}
443
444static struct pcm bad_pcm = {
445 .fd = -1,
446};
447
448struct pcm_params *pcm_params_get(unsigned int card, unsigned int device,
449 unsigned int flags)
450{
451 struct snd_pcm_hw_params *params;
452 char fn[256];
453 int fd;
454
455 snprintf(fn, sizeof(fn), "/dev/snd/pcmC%uD%u%c", card, device,
456 flags & PCM_IN ? 'c' : 'p');
457
458 fd = open(fn, O_RDWR);
459 if (fd < 0) {
460 fprintf(stderr, "cannot open device '%s'\n", fn);
461 goto err_open;
462 }
463
464 params = calloc(1, sizeof(struct snd_pcm_hw_params));
465 if (!params)
466 goto err_calloc;
467
468 param_init(params);
469 if (ioctl(fd, SNDRV_PCM_IOCTL_HW_REFINE, params)) {
470 fprintf(stderr, "SNDRV_PCM_IOCTL_HW_REFINE error (%d)\n", errno);
471 goto err_hw_refine;
472 }
473
474 close(fd);
475
476 return (struct pcm_params *)params;
477
478err_hw_refine:
479 free(params);
480err_calloc:
481 close(fd);
482err_open:
483 return NULL;
484}
485
486void pcm_params_free(struct pcm_params *pcm_params)
487{
488 struct snd_pcm_hw_params *params = (struct snd_pcm_hw_params *)pcm_params;
489
490 if (params)
491 free(params);
492}
493
494static int pcm_param_to_alsa(enum pcm_param param)
495{
496 switch (param) {
497 case PCM_PARAM_SAMPLE_BITS:
498 return SNDRV_PCM_HW_PARAM_SAMPLE_BITS;
499 break;
500 case PCM_PARAM_FRAME_BITS:
501 return SNDRV_PCM_HW_PARAM_FRAME_BITS;
502 break;
503 case PCM_PARAM_CHANNELS:
504 return SNDRV_PCM_HW_PARAM_CHANNELS;
505 break;
506 case PCM_PARAM_RATE:
507 return SNDRV_PCM_HW_PARAM_RATE;
508 break;
509 case PCM_PARAM_PERIOD_TIME:
510 return SNDRV_PCM_HW_PARAM_PERIOD_TIME;
511 break;
512 case PCM_PARAM_PERIOD_SIZE:
513 return SNDRV_PCM_HW_PARAM_PERIOD_SIZE;
514 break;
515 case PCM_PARAM_PERIOD_BYTES:
516 return SNDRV_PCM_HW_PARAM_PERIOD_BYTES;
517 break;
518 case PCM_PARAM_PERIODS:
519 return SNDRV_PCM_HW_PARAM_PERIODS;
520 break;
521 case PCM_PARAM_BUFFER_TIME:
522 return SNDRV_PCM_HW_PARAM_BUFFER_TIME;
523 break;
524 case PCM_PARAM_BUFFER_SIZE:
525 return SNDRV_PCM_HW_PARAM_BUFFER_SIZE;
526 break;
527 case PCM_PARAM_BUFFER_BYTES:
528 return SNDRV_PCM_HW_PARAM_BUFFER_BYTES;
529 break;
530 case PCM_PARAM_TICK_TIME:
531 return SNDRV_PCM_HW_PARAM_TICK_TIME;
532 break;
533
534 default:
535 return -1;
536 }
537}
538
539unsigned int pcm_params_get_min(struct pcm_params *pcm_params,
540 enum pcm_param param)
541{
542 struct snd_pcm_hw_params *params = (struct snd_pcm_hw_params *)pcm_params;
543 int p;
544
545 if (!params)
546 return 0;
547
548 p = pcm_param_to_alsa(param);
549 if (p < 0)
550 return 0;
551
552 return param_get_min(params, p);
553}
554
555unsigned int pcm_params_get_max(struct pcm_params *pcm_params,
556 enum pcm_param param)
557{
558 struct snd_pcm_hw_params *params = (struct snd_pcm_hw_params *)pcm_params;
559 int p;
560
561 if (!params)
562 return 0;
563
564 p = pcm_param_to_alsa(param);
565 if (p < 0)
566 return 0;
567
568 return param_get_max(params, p);
569}
570
571int pcm_close(struct pcm *pcm)
572{
573 if (pcm == &bad_pcm)
574 return 0;
575
576 pcm_hw_munmap_status(pcm);
577
578 if (pcm->flags & PCM_MMAP) {
579 pcm_stop(pcm);
580 munmap(pcm->mmap_buffer, pcm_frames_to_bytes(pcm, pcm->buffer_size));
581 }
582
583 if (pcm->fd >= 0)
584 close(pcm->fd);
585 pcm->running = 0;
586 pcm->buffer_size = 0;
587 pcm->fd = -1;
588 free(pcm);
589 return 0;
590}
591
592struct pcm *pcm_open(unsigned int card, unsigned int device,
593 unsigned int flags, struct pcm_config *config)
594{
595 struct pcm *pcm;
596 struct snd_pcm_info info;
597 struct snd_pcm_hw_params params;
598 struct snd_pcm_sw_params sparams;
599 char fn[256];
600 int rc;
601
602 pcm = calloc(1, sizeof(struct pcm));
603 if (!pcm || !config)
604 return &bad_pcm; /* TODO: could support default config here */
605
606 pcm->config = *config;
607
608 snprintf(fn, sizeof(fn), "/dev/snd/pcmC%uD%u%c", card, device,
609 flags & PCM_IN ? 'c' : 'p');
610
611 pcm->flags = flags;
612 pcm->fd = open(fn, O_RDWR);
613 if (pcm->fd < 0) {
614 oops(pcm, errno, "cannot open device '%s'", fn);
615 return pcm;
616 }
617
618 if (ioctl(pcm->fd, SNDRV_PCM_IOCTL_INFO, &info)) {
619 oops(pcm, errno, "cannot get info");
620 goto fail_close;
621 }
622
623 param_init(&params);
624 param_set_mask(&params, SNDRV_PCM_HW_PARAM_FORMAT,
625 pcm_format_to_alsa(config->format));
626 param_set_mask(&params, SNDRV_PCM_HW_PARAM_SUBFORMAT,
627 SNDRV_PCM_SUBFORMAT_STD);
628 param_set_min(&params, SNDRV_PCM_HW_PARAM_PERIOD_SIZE, config->period_size);
629 param_set_int(&params, SNDRV_PCM_HW_PARAM_SAMPLE_BITS,
630 pcm_format_to_bits(config->format));
631 param_set_int(&params, SNDRV_PCM_HW_PARAM_FRAME_BITS,
632 pcm_format_to_bits(config->format) * config->channels);
633 param_set_int(&params, SNDRV_PCM_HW_PARAM_CHANNELS,
634 config->channels);
635 param_set_int(&params, SNDRV_PCM_HW_PARAM_PERIODS, config->period_count);
636 param_set_int(&params, SNDRV_PCM_HW_PARAM_RATE, config->rate);
637
638 if (flags & PCM_NOIRQ) {
639
640 if (!(flags & PCM_MMAP)) {
641 oops(pcm, -EINVAL, "noirq only currently supported with mmap().");
642 goto fail;
643 }
644
645 params.flags |= SNDRV_PCM_HW_PARAMS_NO_PERIOD_WAKEUP;
646 pcm->noirq_frames_per_msec = config->rate / 1000;
647 }
648
649 if (flags & PCM_MMAP)
650 param_set_mask(&params, SNDRV_PCM_HW_PARAM_ACCESS,
651 SNDRV_PCM_ACCESS_MMAP_INTERLEAVED);
652 else
653 param_set_mask(&params, SNDRV_PCM_HW_PARAM_ACCESS,
654 SNDRV_PCM_ACCESS_RW_INTERLEAVED);
655
656 if (ioctl(pcm->fd, SNDRV_PCM_IOCTL_HW_PARAMS, &params)) {
657 oops(pcm, errno, "cannot set hw params");
658 goto fail_close;
659 }
660
661 /* get our refined hw_params */
662 config->period_size = param_get_int(&params, SNDRV_PCM_HW_PARAM_PERIOD_SIZE);
663 config->period_count = param_get_int(&params, SNDRV_PCM_HW_PARAM_PERIODS);
664 pcm->buffer_size = config->period_count * config->period_size;
665
666 if (flags & PCM_MMAP) {
667 pcm->mmap_buffer = mmap(NULL, pcm_frames_to_bytes(pcm, pcm->buffer_size),
668 PROT_READ | PROT_WRITE, MAP_FILE | MAP_SHARED, pcm->fd, 0);
669 if (pcm->mmap_buffer == MAP_FAILED) {
670 oops(pcm, -errno, "failed to mmap buffer %d bytes\n",
671 pcm_frames_to_bytes(pcm, pcm->buffer_size));
672 goto fail_close;
673 }
674 }
675
676
677 memset(&sparams, 0, sizeof(sparams));
678 sparams.tstamp_mode = SNDRV_PCM_TSTAMP_ENABLE;
679 sparams.period_step = 1;
680 sparams.avail_min = 1;
681
682 if (!config->start_threshold) {
683 if (pcm->flags & PCM_IN)
684 pcm->config.start_threshold = sparams.start_threshold = 1;
685 else
686 pcm->config.start_threshold = sparams.start_threshold =
687 config->period_count * config->period_size / 2;
688 } else
689 sparams.start_threshold = config->start_threshold;
690
691 /* pick a high stop threshold - todo: does this need further tuning */
692 if (!config->stop_threshold) {
693 if (pcm->flags & PCM_IN)
694 pcm->config.stop_threshold = sparams.stop_threshold =
695 config->period_count * config->period_size * 10;
696 else
697 pcm->config.stop_threshold = sparams.stop_threshold =
698 config->period_count * config->period_size;
699 }
700 else
701 sparams.stop_threshold = config->stop_threshold;
702
703 sparams.xfer_align = config->period_size / 2; /* needed for old kernels */
704 sparams.silence_size = 0;
705 sparams.silence_threshold = config->silence_threshold;
706 pcm->boundary = sparams.boundary = pcm->buffer_size;
707
708 while (pcm->boundary * 2 <= INT_MAX - pcm->buffer_size)
709 pcm->boundary *= 2;
710
711 if (ioctl(pcm->fd, SNDRV_PCM_IOCTL_SW_PARAMS, &sparams)) {
712 oops(pcm, errno, "cannot set sw params");
713 goto fail;
714 }
715
716 rc = pcm_hw_mmap_status(pcm);
717 if (rc < 0) {
718 oops(pcm, rc, "mmap status failed");
719 goto fail;
720 }
721
722 pcm->underruns = 0;
723 return pcm;
724
725fail:
726 if (flags & PCM_MMAP)
727 munmap(pcm->mmap_buffer, pcm_frames_to_bytes(pcm, pcm->buffer_size));
728fail_close:
729 close(pcm->fd);
730 pcm->fd = -1;
731 return pcm;
732}
733
734int pcm_is_ready(struct pcm *pcm)
735{
736 return pcm->fd >= 0;
737}
738
739int pcm_start(struct pcm *pcm)
740{
741 if (ioctl(pcm->fd, SNDRV_PCM_IOCTL_PREPARE) < 0)
742 return oops(pcm, errno, "cannot prepare channel");
743
744 if (pcm->flags & PCM_MMAP)
745 pcm_sync_ptr(pcm, 0);
746
747 if (ioctl(pcm->fd, SNDRV_PCM_IOCTL_START) < 0)
748 return oops(pcm, errno, "cannot start channel");
749
750 pcm->running = 1;
751 return 0;
752}
753
754int pcm_stop(struct pcm *pcm)
755{
756 if (ioctl(pcm->fd, SNDRV_PCM_IOCTL_DROP) < 0)
757 return oops(pcm, errno, "cannot stop channel");
758
759 pcm->running = 0;
760 return 0;
761}
762
763static inline int pcm_mmap_playback_avail(struct pcm *pcm)
764{
765 int avail;
766
767 avail = pcm->mmap_status->hw_ptr + pcm->buffer_size - pcm->mmap_control->appl_ptr;
768
769 if (avail < 0)
770 avail += pcm->boundary;
771 else if (avail > (int)pcm->boundary)
772 avail -= pcm->boundary;
773
774 return avail;
775}
776
777static inline int pcm_mmap_capture_avail(struct pcm *pcm)
778{
779 int avail = pcm->mmap_status->hw_ptr - pcm->mmap_control->appl_ptr;
780 if (avail < 0)
781 avail += pcm->boundary;
782 return avail;
783}
784
785static inline int pcm_mmap_avail(struct pcm *pcm)
786{
787 pcm_sync_ptr(pcm, SNDRV_PCM_SYNC_PTR_HWSYNC);
788 if (pcm->flags & PCM_IN)
789 return pcm_mmap_capture_avail(pcm);
790 else
791 return pcm_mmap_playback_avail(pcm);
792}
793
794static void pcm_mmap_appl_forward(struct pcm *pcm, int frames)
795{
796 unsigned int appl_ptr = pcm->mmap_control->appl_ptr;
797 appl_ptr += frames;
798
799 /* check for boundary wrap */
800 if (appl_ptr > pcm->boundary)
801 appl_ptr -= pcm->boundary;
802 pcm->mmap_control->appl_ptr = appl_ptr;
803}
804
805int pcm_mmap_begin(struct pcm *pcm, void **areas, unsigned int *offset,
806 unsigned int *frames)
807{
808 unsigned int continuous, copy_frames, avail;
809
810 /* return the mmap buffer */
811 *areas = pcm->mmap_buffer;
812
813 /* and the application offset in frames */
814 *offset = pcm->mmap_control->appl_ptr % pcm->buffer_size;
815
816 avail = pcm_mmap_avail(pcm);
817 if (avail > pcm->buffer_size)
818 avail = pcm->buffer_size;
819 continuous = pcm->buffer_size - *offset;
820
821 /* we can only copy frames if the are availabale and continuos */
822 copy_frames = *frames;
823 if (copy_frames > avail)
824 copy_frames = avail;
825 if (copy_frames > continuous)
826 copy_frames = continuous;
827 *frames = copy_frames;
828
829 return 0;
830}
831
832int pcm_mmap_commit(struct pcm *pcm, unsigned int offset, unsigned int frames)
833{
834 (void)offset;
835 /* update the application pointer in userspace and kernel */
836 pcm_mmap_appl_forward(pcm, frames);
837 pcm_sync_ptr(pcm, 0);
838
839 return frames;
840}
841
842int pcm_avail_update(struct pcm *pcm)
843{
844 pcm_sync_ptr(pcm, 0);
845 return pcm_mmap_avail(pcm);
846}
847
848int pcm_state(struct pcm *pcm)
849{
850 int err = pcm_sync_ptr(pcm, 0);
851 if (err < 0)
852 return err;
853
854 return pcm->mmap_status->state;
855}
856
857int pcm_wait(struct pcm *pcm, int timeout)
858{
859 struct pollfd pfd;
860 int err;
861
862 pfd.fd = pcm->fd;
863 pfd.events = POLLOUT | POLLERR | POLLNVAL;
864
865 do {
866 /* let's wait for avail or timeout */
867 err = poll(&pfd, 1, timeout);
868 if (err < 0)
869 return -errno;
870
871 /* timeout ? */
872 if (err == 0)
873 return 0;
874
875 /* have we been interrupted ? */
876 if (errno == -EINTR)
877 continue;
878
879 /* check for any errors */
880 if (pfd.revents & (POLLERR | POLLNVAL)) {
881 switch (pcm_state(pcm)) {
882 case PCM_STATE_XRUN:
883 return -EPIPE;
884 case PCM_STATE_SUSPENDED:
885 return -ESTRPIPE;
886 case PCM_STATE_DISCONNECTED:
887 return -ENODEV;
888 default:
889 return -EIO;
890 }
891 }
892 /* poll again if fd not ready for IO */
893 } while (!(pfd.revents & (POLLIN | POLLOUT)));
894
895 return 1;
896}
897
898int pcm_mmap_write(struct pcm *pcm, const void *buffer, unsigned int bytes)
899{
900 int err = 0, frames, avail;
901 unsigned int offset = 0, count;
902
903 if (bytes == 0)
904 return 0;
905
906 count = pcm_bytes_to_frames(pcm, bytes);
907
908 while (count > 0) {
909
910 /* get the available space for writing new frames */
911 avail = pcm_avail_update(pcm);
912 if (avail < 0) {
913 fprintf(stderr, "cannot determine available mmap frames");
914 return err;
915 }
916
917 /* start the audio if we reach the threshold */
918 if (!pcm->running &&
919 (pcm->buffer_size - avail) >= pcm->config.start_threshold) {
920 if (pcm_start(pcm) < 0) {
921 fprintf(stderr, "start error: hw 0x%x app 0x%x avail 0x%x\n",
922 (unsigned int)pcm->mmap_status->hw_ptr,
923 (unsigned int)pcm->mmap_control->appl_ptr,
924 avail);
925 return -errno;
926 }
927 }
928
929 /* sleep until we have space to write new frames */
930 if (pcm->running &&
931 (unsigned int)avail < pcm->mmap_control->avail_min) {
932 int time = -1;
933
934 if (pcm->flags & PCM_NOIRQ)
935 time = (pcm->buffer_size - avail - pcm->mmap_control->avail_min)
936 / pcm->noirq_frames_per_msec;
937
938 err = pcm_wait(pcm, time);
939 if (err < 0) {
940 pcm->running = 0;
941 fprintf(stderr, "wait error: hw 0x%x app 0x%x avail 0x%x\n",
942 (unsigned int)pcm->mmap_status->hw_ptr,
943 (unsigned int)pcm->mmap_control->appl_ptr,
944 avail);
945 pcm->mmap_control->appl_ptr = 0;
946 return err;
947 }
948 continue;
949 }
950
951 frames = count;
952 if (frames > avail)
953 frames = avail;
954
955 if (!frames)
956 break;
957
958 /* copy frames from buffer */
959 frames = pcm_mmap_write_areas(pcm, buffer, offset, frames);
960 if (frames < 0) {
961 fprintf(stderr, "write error: hw 0x%x app 0x%x avail 0x%x\n",
962 (unsigned int)pcm->mmap_status->hw_ptr,
963 (unsigned int)pcm->mmap_control->appl_ptr,
964 avail);
965 return frames;
966 }
967
968 offset += frames;
969 count -= frames;
970 }
971
972 return 0;
973}
diff --git a/firmware/target/hosted/android/system-android.c b/firmware/target/hosted/android/system-android.c
index d13b8d6462..6279504e48 100644
--- a/firmware/target/hosted/android/system-android.c
+++ b/firmware/target/hosted/android/system-android.c
@@ -23,6 +23,12 @@
23#include <setjmp.h> 23#include <setjmp.h>
24#include <jni.h> 24#include <jni.h>
25#include <pthread.h> 25#include <pthread.h>
26#if defined(DX50) || defined(DX90)
27#include <stdlib.h>
28#include <sys/reboot.h>
29#include <sys/stat.h>
30#include <stdio.h>
31#endif /* DX50 || DX90 */
26#include <unistd.h> 32#include <unistd.h>
27#include "config.h" 33#include "config.h"
28#include "system.h" 34#include "system.h"
@@ -31,40 +37,83 @@
31 37
32 38
33 39
40#if !defined(DX50) && !defined(DX90)
34/* global fields for use with various JNI calls */ 41/* global fields for use with various JNI calls */
35static JavaVM *vm_ptr; 42static JavaVM *vm_ptr;
36JNIEnv *env_ptr; 43JNIEnv *env_ptr;
37jobject RockboxService_instance; 44jobject RockboxService_instance;
38jclass RockboxService_class; 45jclass RockboxService_class;
46#endif /* !DX50 && !DX90 */
39 47
40uintptr_t *stackbegin; 48uintptr_t *stackbegin;
41uintptr_t *stackend; 49uintptr_t *stackend;
42 50
43extern int main(void); 51extern int main(void);
52#if !defined(DX50) && !defined(DX90)
44extern void telephony_init_device(void); 53extern void telephony_init_device(void);
45 54#endif
46void system_exception_wait(void) 55void system_exception_wait(void)
47{ 56{
57#if defined(DX50) || defined(DX90)
58 while(1);
59#else
48 intptr_t dummy = 0; 60 intptr_t dummy = 0;
49 while(button_read_device(&dummy) != BUTTON_BACK); 61 while(button_read_device(&dummy) != BUTTON_BACK);
62#endif /* DX50 || DX90 */
50} 63}
51 64
52void system_reboot(void) 65void system_reboot(void)
53{ 66{
67#if defined(DX50) || defined(DX90)
68 reboot(RB_AUTOBOOT);
69#else
54 power_off(); 70 power_off();
71#endif /* DX50 || DX90 */
55} 72}
56 73
74#if !defined(DX50) && !defined(DX90)
57/* this is used to return from the entry point of the native library. */ 75/* this is used to return from the entry point of the native library. */
58static jmp_buf poweroff_buf; 76static jmp_buf poweroff_buf;
77#endif
78
59void power_off(void) 79void power_off(void)
60{ 80{
81#if defined(DX50) || defined(DX90)
82 reboot(RB_POWER_OFF);
83#else
61 longjmp(poweroff_buf, 1); 84 longjmp(poweroff_buf, 1);
85#endif /* DX50 || DX90 */
62} 86}
63 87
64void system_init(void) 88void system_init(void)
65{ 89{
90#if defined(DX50) || defined(DX90)
91 volatile uintptr_t stack = 0;
92 stackbegin = stackend = (uintptr_t*) &stack;
93
94 struct stat m1, m2;
95 stat("/mnt/", &m1);
96 do
97 {
98 /* waiting for storage to get mounted */
99 stat("/sdcard/", &m2);
100 usleep(100000);
101 }
102 while(m1.st_dev == m2.st_dev);
103/* here would be the correct place for 'system("/system/bin/muteopen");' (headphone-out relay) but in pcm-dx50.c, pcm_play_dma_start()
104 the output capacitors are charged already a bit and the click of the headphone-connection-relay is softer */
105
106#if defined(DX90)
107 /* DAC needs to be unmuted on DX90 */
108 FILE * f = fopen("/sys/class/codec/wm8740_mute", "w");
109 fputc(0, f);
110 fclose(f);
111#endif /* DX90 */
112
113#else
66 /* no better place yet */ 114 /* no better place yet */
67 telephony_init_device(); 115 telephony_init_device();
116#endif /* DX50 || DX90 */
68} 117}
69 118
70int hostfs_init(void) 119int hostfs_init(void)
@@ -79,6 +128,7 @@ int hostfs_flush(void)
79 return 0; 128 return 0;
80} 129}
81 130
131#if !defined(DX50) && !defined(DX90)
82JNIEXPORT jint JNICALL 132JNIEXPORT jint JNICALL
83JNI_OnLoad(JavaVM *vm, void* reserved) 133JNI_OnLoad(JavaVM *vm, void* reserved)
84{ 134{
@@ -119,7 +169,7 @@ Java_org_rockbox_RockboxService_main(JNIEnv *env, jobject this)
119 /* simply return here. this will allow the VM to clean up objects and do 169 /* simply return here. this will allow the VM to clean up objects and do
120 * garbage collection */ 170 * garbage collection */
121} 171}
122 172#endif /* !DX50 && !DX90 */
123 173
124/* below is the facility for external (from other java threads) to safely call 174/* below is the facility for external (from other java threads) to safely call
125 * into our snative code. When extracting rockbox.zip the main function is 175 * into our snative code. When extracting rockbox.zip the main function is
diff --git a/firmware/target/hosted/filesystem-app.c b/firmware/target/hosted/filesystem-app.c
index a4730a07d9..93fadc6d6e 100644
--- a/firmware/target/hosted/filesystem-app.c
+++ b/firmware/target/hosted/filesystem-app.c
@@ -104,6 +104,7 @@ void paths_init(void)
104#if (CONFIG_PLATFORM & PLATFORM_ANDROID) 104#if (CONFIG_PLATFORM & PLATFORM_ANDROID)
105 os_mkdir("/sdcard/rockbox" __MKDIR_MODE_ARG); 105 os_mkdir("/sdcard/rockbox" __MKDIR_MODE_ARG);
106 os_mkdir("/sdcard/rockbox/rocks.data" __MKDIR_MODE_ARG); 106 os_mkdir("/sdcard/rockbox/rocks.data" __MKDIR_MODE_ARG);
107 os_mkdir("/sdcard/rockbox/eqs" __MKDIR_MODE_ARG);
107#else 108#else
108 char config_dir[MAX_PATH]; 109 char config_dir[MAX_PATH];
109 110