summaryrefslogtreecommitdiff
path: root/firmware
diff options
context:
space:
mode:
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