Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Submit feedback
Contribute to GitLab
Sign in / Register
Toggle navigation
T
test_webhook
Project
Project
Details
Activity
Releases
Cycle Analytics
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Charts
Issues
0
Issues
0
List
Board
Labels
Milestones
Merge Requests
1
Merge Requests
1
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Charts
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Charts
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
时海鑫
test_webhook
Commits
cfc02459
Commit
cfc02459
authored
Sep 28, 2025
by
时海鑫
Browse files
Options
Browse Files
Download
Plain Diff
Merge branch 'dev' into 'master'
test2 See merge request
!11
parents
a87e2203
52000fbc
Changes
2
Hide whitespace changes
Inline
Side-by-side
Showing
2 changed files
with
2844 additions
and
0 deletions
+2844
-0
audio_hw.c
audio_hw.c
+2567
-0
audio_hw.h
audio_hw.h
+277
-0
No files found.
audio_hw.c
0 → 100644
View file @
cfc02459
/*
* Copyright (C) 2011 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#define LOG_TAG "audio_hw_primary"
#define LOG_NDEBUG 0
#include <errno.h>
#include <pthread.h>
#include <stdint.h>
#include <sys/time.h>
#include <stdlib.h>
#include <log/log.h>
#include <cutils/str_parms.h>
#include <cutils/properties.h>
#include <hardware/hardware.h>
#include <system/audio.h>
#include <hardware/audio.h>
#include <audio_route/audio_route.h>
#include <tinyalsa/asoundlib.h>
#include <audio_utils/resampler.h>
#include <hardware/audio_effect.h>
#include <audio_effects/effect_aec.h>
#include <fcntl.h>
#include <unistd.h>
#include <cutils/properties.h>
#include "audio_hw.h"
#define UNUSED(x) (void)(x)
// Enable bluetooth call support
#define call_button_voice 1
#define AUDIO_CODEC_XML_PATH "/vendor/etc/auto_codec_paths.xml"
#define AUDIO_AHUB_XML_PATH "/vendor/etc/auto_ahub_paths.xml"
typedef
struct
route_map_t
{
int
id
;
char
open
[
128
];
char
close
[
128
];
}
route_map
;
enum
{
OUT_DEVICE_LINEOUT
,
OUT_DEVICE_HDMI
,
OUT_DEVICE_I2S2
,
OUT_DEVICE_I2S3
,
OUT_DEVICE_SNDBT936B
,
IN_DEVICE_AC107
,
IN_DEVICE_TD100
,
IN_DEVICE_I2S2
,
IN_DEVICE_I2S3
,
IN_DEVICE_SNDES7210
,
IN_DEVICE_SNDBT936B
,
AA_LINEIN_LINEOUT
,
AA_FMIN_LINEOUT
,
VOL_LINEOUT
,
VOL_LINEIN_OMIX
,
VOL_FMIN_OMIX
,
VOL_AC107_C1_PGA
,
VOL_AC107_C2_PGA
,
VOL_AC107_C1_DIGITAL
,
VOL_AC107_C2_DIGITAL
,
VOL_TD100_MIC1
,
VOL_TD100_MIC2
,
VOL_TD100_MIC3
,
VOL_TD100_LINEIN
,
DVOL_TD100_ADC1
,
DVOL_TD100_ADC2
,
CH1_TD100_SELECT
,
CH2_TD100_SELECT
,
DEVICE_TAB_SIZE
,
};
static
route_map
route_configs
[
DEVICE_TAB_SIZE
]
=
{
{
OUT_DEVICE_LINEOUT
,
"codec-lineout"
,
"codec-lineout-close"
},
{
OUT_DEVICE_HDMI
,
"ahub-daudio1-output"
,
"ahub-daudio1-output-close"
},
{
OUT_DEVICE_I2S2
,
"ahub-daudio2-output"
,
"ahub-daudio2-output-close"
},
{
OUT_DEVICE_I2S3
,
"ahub-daudio3-output"
,
"ahub-daudio3-output-close"
},
{
OUT_DEVICE_SNDBT936B
,
"ahub-daudio0-output"
,
"ahub-daudio0-output-close"
},
{
IN_DEVICE_AC107
,
"ahub-daudio0-input"
,
"ahub-daudio0-input-close"
},
{
IN_DEVICE_TD100
,
"ahub-daudio0-input"
,
"ahub-daudio0-input-close"
},
{
IN_DEVICE_I2S2
,
"ahub-daudio2-input"
,
"ahub-daudio2-input-close"
},
{
IN_DEVICE_I2S3
,
"ahub-daudio3-input"
,
"ahub-daudio3-input-close"
},
{
IN_DEVICE_SNDES7210
,
"ahub-daudio2-input"
,
"ahub-daudio2-input-close"
},
{
IN_DEVICE_SNDBT936B
,
"ahub-daudio0-input"
,
"ahub-daudio0-input-close"
},
{
AA_LINEIN_LINEOUT
,
"codec-linein-lineout"
,
"codec-linein-lineout-close"
},
{
AA_FMIN_LINEOUT
,
"codec-fmin-lineout"
,
"codec-fmin-lineout-close"
},
{
VOL_LINEOUT
,
"LINEOUT volume"
,
""
},
{
VOL_LINEIN_OMIX
,
"LINEIN to output mixer gain control"
,
""
},
{
VOL_FMIN_OMIX
,
"FMIN to output mixer gain control"
,
""
},
{
VOL_AC107_C1_PGA
,
"Channel 1 PGA Gain"
,
""
},
{
VOL_AC107_C2_PGA
,
"Channel 2 PGA Gain"
,
""
},
{
VOL_AC107_C1_DIGITAL
,
"Channel 1 Digital Volume"
,
""
},
{
VOL_AC107_C2_DIGITAL
,
"Channel 2 Digital Volume"
,
""
},
{
VOL_TD100_MIC1
,
"MIC1 Gain"
,
""
},
{
VOL_TD100_MIC2
,
"MIC2 Gain"
,
""
},
{
VOL_TD100_MIC3
,
"MIC3 Gain"
,
""
},
{
VOL_TD100_LINEIN
,
"LINEIN Gain"
,
""
},
{
DVOL_TD100_ADC1
,
"ADC1 Digital Volume"
,
""
},
{
DVOL_TD100_ADC2
,
"ADC2 Digital Volume"
,
""
},
{
CH1_TD100_SELECT
,
"I2S TX CH1 MUX"
,
""
},
{
CH2_TD100_SELECT
,
"I2S TX CH2 MUX"
,
""
},
};
struct
pcm_config
pcm_config_out
=
{
.
channels
=
DEFAULT_CHANNEL_COUNT
,
.
rate
=
DEFAULT_SAMPLING_RATE
,
.
period_size
=
DEFAULT_OUTPUT_PERIOD_SIZE
,
.
period_count
=
DEFAULT_OUTPUT_PERIOD_COUNT
,
.
format
=
PCM_FORMAT_S16_LE
,
};
// struct pcm_config pcm_config_in = {
// .channels = DEFAULT_CHANNEL_COUNT,
// .rate = DEFAULT_SAMPLING_RATE,
// .period_size = DEFAULT_INPUT_PERIOD_SIZE,
// .period_count = DEFAULT_INPUT_PERIOD_COUNT,
// .format = PCM_FORMAT_S16_LE,
// };
struct
pcm_config
pcm_config_in
=
{
.
channels
=
1
,
.
rate
=
DEFAULT_SAMPLING_RATE
,
.
period_size
=
DEFAULT_INPUT_PERIOD_SIZE
,
.
period_count
=
DEFAULT_INPUT_PERIOD_COUNT
,
.
format
=
PCM_FORMAT_S16_LE
,
};
typedef
struct
name_map_t
{
char
name_linux
[
32
];
char
name_android
[
32
];
}
name_map
;
static
name_map
audio_name_map
[
MAX_AUDIO_DEVICES
]
=
{
{
"audiocodec"
,
AUDIO_NAME_CODEC
},
//inside codec
{
"snddaudio2"
,
AUDIO_NAME_I2S2
},
//daudio2
{
"snddaudio3"
,
AUDIO_NAME_I2S3
},
//daudio3
{
"sndahub"
,
AUDIO_NAME_AHUB
},
//ahub
{
"sndac10730036"
,
AUDIO_NAME_AC107
},
//ac107
{
"sndtd100codec0"
,
AUDIO_NAME_TD100
},
//td100
{
"sndhdmi"
,
AUDIO_NAME_HDMI
},
{
"sndspdif"
,
AUDIO_NAME_SPDIF
},
{
AUDIO_NAME_SNDES7210_LINUX
,
AUDIO_NAME_SNDES7210
},
{
AUDIO_NAME_SNDBT936B_LINUX
,
AUDIO_NAME_SNDBT936B
},
};
static
void
set_audio_path
(
struct
sunxi_audio_device
*
adev
,
int
device_path
,
int
status
);
static
int
do_input_standby
(
struct
sunxi_stream_in
*
in
);
static
int
do_output_standby
(
struct
sunxi_stream_out
*
out
);
static
int
set_audio_devices_active
(
struct
sunxi_audio_device
*
adev
,
int
in_out
);
static
int
set_mixer_value
(
struct
mixer
*
mixer
,
const
char
*
name
,
int
value
)
{
struct
mixer_ctl
*
ctl
=
NULL
;
ctl
=
mixer_get_ctl_by_name
(
mixer
,
name
);
if
(
ctl
==
NULL
)
{
ALOGE
(
"Control '%s' doesn't exist "
,
name
);
return
-
1
;
}
return
mixer_ctl_set_value
(
ctl
,
0
,
value
);
}
static
int
find_name_map
(
struct
sunxi_audio_device
*
adev
,
char
*
in
,
char
*
out
)
{
UNUSED
(
adev
);
int
index
=
0
;
if
(
in
==
0
||
out
==
0
)
{
ALOGE
(
"error params"
);
return
-
1
;
}
for
(;
index
<
MAX_AUDIO_DEVICES
;
index
++
)
{
if
(
strlen
(
audio_name_map
[
index
].
name_linux
)
==
0
)
{
//sprintf(out, "AUDIO_USB%d", adev->usb_audio_cnt++);
sprintf
(
out
,
"AUDIO_USB_%s"
,
in
);
strcpy
(
audio_name_map
[
index
].
name_linux
,
in
);
strcpy
(
audio_name_map
[
index
].
name_android
,
out
);
ALOGD
(
"linux name = %s, android name = %s"
,
audio_name_map
[
index
].
name_linux
,
audio_name_map
[
index
].
name_android
);
return
0
;
}
if
(
!
strcmp
(
in
,
audio_name_map
[
index
].
name_linux
))
{
strcpy
(
out
,
audio_name_map
[
index
].
name_android
);
ALOGD
(
"linux name = %s, android name = %s"
,
audio_name_map
[
index
].
name_linux
,
audio_name_map
[
index
].
name_android
);
return
0
;
}
}
return
0
;
}
static
int
do_init_audio_card
(
struct
sunxi_audio_device
*
adev
,
int
card
)
{
int
ret
=
-
1
;
int
fd
=
0
;
char
*
snd_path
=
"/sys/class/sound"
;
char
snd_card
[
128
],
snd_node
[
128
];
char
snd_id
[
32
],
snd_name
[
32
];
memset
(
snd_card
,
0
,
sizeof
(
snd_card
));
memset
(
snd_node
,
0
,
sizeof
(
snd_node
));
memset
(
snd_id
,
0
,
sizeof
(
snd_id
));
memset
(
snd_name
,
0
,
sizeof
(
snd_name
));
sprintf
(
snd_card
,
"%s/card%d"
,
snd_path
,
card
);
ret
=
access
(
snd_card
,
F_OK
);
if
(
ret
==
0
)
{
// id / name
sprintf
(
snd_node
,
"%s/card%d/id"
,
snd_path
,
card
);
ALOGD
(
"read card %s/card%d/id"
,
snd_path
,
card
);
fd
=
open
(
snd_node
,
O_RDONLY
);
if
(
fd
>
0
)
{
ret
=
read
(
fd
,
snd_id
,
sizeof
(
snd_id
));
if
(
ret
>
0
)
{
snd_id
[
ret
-
1
]
=
0
;
ALOGD
(
"%s, %s, len: %d"
,
snd_node
,
snd_id
,
ret
);
}
close
(
fd
);
}
else
{
return
-
1
;
}
strcpy
(
adev
->
dev_manager
[
card
].
card_id
,
snd_id
);
find_name_map
(
adev
,
snd_id
,
snd_name
);
strcpy
(
adev
->
dev_manager
[
card
].
name
,
snd_name
);
ALOGD
(
"find name map, card_id = %s, card_name = %s "
,
adev
->
dev_manager
[
card
].
card_id
,
adev
->
dev_manager
[
card
].
name
);
adev
->
dev_manager
[
card
].
card
=
card
;
adev
->
dev_manager
[
card
].
port
=
0
;
adev
->
dev_manager
[
card
].
flag_exist
=
true
;
adev
->
dev_manager
[
card
].
flag_out
=
AUDIO_NONE
;
adev
->
dev_manager
[
card
].
flag_in
=
AUDIO_NONE
;
adev
->
dev_manager
[
card
].
flag_out_active
=
0
;
adev
->
dev_manager
[
card
].
flag_in_active
=
0
;
if
(
!
strcmp
(
adev
->
dev_manager
[
card
].
name
,
AUDIO_NAME_CODEC
)){
adev
->
dev_manager
[
card
].
port
=
0
;
adev
->
dev_manager
[
card
].
ahub_device
=
0
;
adev
->
card_codec
=
card
;
adev
->
ar_codec
=
audio_route_init
(
adev
->
card_codec
,
AUDIO_CODEC_XML_PATH
);
}
else
if
(
!
strcmp
(
adev
->
dev_manager
[
card
].
name
,
AUDIO_NAME_AHUB
)){
adev
->
card_ahub
=
card
;
adev
->
ar_ahub
=
audio_route_init
(
adev
->
card_ahub
,
AUDIO_AHUB_XML_PATH
);
return
0
;
}
else
if
(
!
strcmp
(
adev
->
dev_manager
[
card
].
name
,
AUDIO_NAME_AC107
)){
adev
->
dev_manager
[
card
].
port
=
PORT_AC107
;
adev
->
dev_manager
[
card
].
ahub_device
=
1
;
adev
->
card_ac107
=
card
;
adev
->
mixer_ac107
=
mixer_open
(
adev
->
card_ac107
);
}
else
if
(
!
strcmp
(
adev
->
dev_manager
[
card
].
name
,
AUDIO_NAME_TD100
)){
adev
->
dev_manager
[
card
].
port
=
PORT_TD100
;
adev
->
dev_manager
[
card
].
ahub_device
=
1
;
adev
->
card_td100
=
card
;
adev
->
mixer_td100
=
mixer_open
(
adev
->
card_td100
);
}
else
if
(
!
strcmp
(
adev
->
dev_manager
[
card
].
name
,
AUDIO_NAME_HDMI
)){
adev
->
dev_manager
[
card
].
port
=
PORT_HDMI
;
adev
->
dev_manager
[
card
].
ahub_device
=
1
;
}
else
if
(
!
strcmp
(
adev
->
dev_manager
[
card
].
name
,
AUDIO_NAME_I2S2
)){
adev
->
dev_manager
[
card
].
port
=
PORT_I2S2
;
adev
->
dev_manager
[
card
].
ahub_device
=
1
;
}
else
if
(
!
strcmp
(
adev
->
dev_manager
[
card
].
name
,
AUDIO_NAME_I2S3
)){
adev
->
dev_manager
[
card
].
port
=
PORT_I2S3
;
adev
->
dev_manager
[
card
].
ahub_device
=
1
;
}
else
if
(
!
strcmp
(
adev
->
dev_manager
[
card
].
name
,
AUDIO_NAME_SNDES7210
)){
adev
->
dev_manager
[
card
].
port
=
PORT_I2S2
;
adev
->
dev_manager
[
card
].
ahub_device
=
1
;
adev
->
card_sndes7210
=
card
;
}
else
if
(
!
strcmp
(
adev
->
dev_manager
[
card
].
name
,
AUDIO_NAME_SNDBT936B
)){
adev
->
dev_manager
[
card
].
port
=
PORT_I2S0
;
adev
->
dev_manager
[
card
].
ahub_device
=
1
;
adev
->
card_sndbt936b
=
card
;
}
else
{
adev
->
dev_manager
[
card
].
ahub_device
=
0
;
adev
->
dev_manager
[
card
].
port
=
0
;
}
if
(
strcmp
(
adev
->
dev_manager
[
card
].
name
,
AUDIO_NAME_AC107
)
||
strcmp
(
adev
->
dev_manager
[
card
].
name
,
AUDIO_NAME_TD100
)){
// playback device
sprintf
(
snd_node
,
"%s/card%d/pcmC%dD0p"
,
snd_path
,
card
,
card
);
ret
=
access
(
snd_node
,
F_OK
);
if
(
ret
==
0
)
{
// there is a playback device
adev
->
dev_manager
[
card
].
flag_out
=
AUDIO_OUT
;
adev
->
dev_manager
[
card
].
flag_out_active
=
0
;
}
}
if
(
strcmp
(
adev
->
dev_manager
[
card
].
name
,
AUDIO_NAME_HDMI
)
||
strcmp
(
adev
->
dev_manager
[
card
].
name
,
AUDIO_NAME_CODEC
)){
// capture device
sprintf
(
snd_node
,
"%s/card%d/pcmC%dD0c"
,
snd_path
,
card
,
card
);
ret
=
access
(
snd_node
,
F_OK
);
if
(
ret
==
0
)
{
// there is a capture device
adev
->
dev_manager
[
card
].
flag_in
=
AUDIO_IN
;
adev
->
dev_manager
[
card
].
flag_in_active
=
0
;
}
}
}
else
{
return
-
1
;
}
return
0
;
}
static
void
init_td100_devices
(
struct
sunxi_audio_device
*
adev
)
{
if
(
!
adev
->
mixer_td100
)
return
;
set_mixer_value
(
adev
->
mixer_td100
,
route_configs
[
VOL_TD100_MIC1
].
open
,
adev
->
vol_td100_mic1_val
);
set_mixer_value
(
adev
->
mixer_td100
,
route_configs
[
VOL_TD100_MIC2
].
open
,
adev
->
vol_td100_mic2_val
);
set_mixer_value
(
adev
->
mixer_td100
,
route_configs
[
VOL_TD100_MIC3
].
open
,
adev
->
vol_td100_mic3_val
);
set_mixer_value
(
adev
->
mixer_td100
,
route_configs
[
VOL_TD100_LINEIN
].
open
,
adev
->
vol_td100_linein_val
);
set_mixer_value
(
adev
->
mixer_td100
,
route_configs
[
DVOL_TD100_ADC1
].
open
,
adev
->
dvol_td100_adc1_val
);
set_mixer_value
(
adev
->
mixer_td100
,
route_configs
[
DVOL_TD100_ADC2
].
open
,
adev
->
dvol_td100_adc2_val
);
set_mixer_value
(
adev
->
mixer_td100
,
route_configs
[
CH1_TD100_SELECT
].
open
,
adev
->
ch1_td100_select_val
);
set_mixer_value
(
adev
->
mixer_td100
,
route_configs
[
CH2_TD100_SELECT
].
open
,
adev
->
ch2_td100_select_val
);
}
static
void
init_ac107_devices
(
struct
sunxi_audio_device
*
adev
)
{
if
(
!
adev
->
mixer_ac107
)
return
;
set_mixer_value
(
adev
->
mixer_ac107
,
route_configs
[
VOL_AC107_C2_PGA
].
open
,
12
);
set_mixer_value
(
adev
->
mixer_ac107
,
route_configs
[
VOL_AC107_C1_PGA
].
open
,
29
);
}
static
void
init_audio_devices
(
struct
sunxi_audio_device
*
adev
)
{
int
card
=
0
;
F_LOG
;
memset
(
adev
->
dev_manager
,
0
,
sizeof
(
adev
->
dev_manager
));
for
(
card
=
0
;
card
<
MAX_AUDIO_DEVICES
;
card
++
)
{
if
(
do_init_audio_card
(
adev
,
card
)
==
0
)
{
// break;
ALOGV
(
"card: %d, name: %s, capture: %d, playback: %d"
,
card
,
adev
->
dev_manager
[
card
].
name
,
adev
->
dev_manager
[
card
].
flag_in
==
AUDIO_IN
,
adev
->
dev_manager
[
card
].
flag_out
==
AUDIO_OUT
);
}
}
if
(
adev
->
ar_codec
){
audio_route_reset
(
adev
->
ar_codec
);
}
if
(
adev
->
ar_ahub
){
audio_route_reset
(
adev
->
ar_ahub
);
}
}
static
void
init_audio_devices_active
(
struct
sunxi_audio_device
*
adev
)
{
int
card
=
0
;
int
flag_active
=
0
;
F_LOG
;
if
(
set_audio_devices_active
(
adev
,
AUDIO_IN
)
==
0
)
{
flag_active
|=
AUDIO_IN
;
}
if
(
set_audio_devices_active
(
adev
,
AUDIO_OUT
)
==
0
)
{
flag_active
|=
AUDIO_OUT
;
}
if
((
flag_active
&
AUDIO_IN
)
&&
(
flag_active
&
AUDIO_OUT
)){
return
;
}
ALOGV
(
"midle priority, use codec & ac107"
);
for
(
card
=
0
;
card
<
MAX_AUDIO_DEVICES
;
card
++
)
{
// default use auido codec out, ac107 in.
if
((
!
strcmp
(
adev
->
dev_manager
[
card
].
name
,
AUDIO_NAME_AC107
))
&&
(
adev
->
dev_manager
[
card
].
flag_in
==
AUDIO_IN
))
{
ALOGV
(
"OK, default use %s capture"
,
adev
->
dev_manager
[
card
].
name
);
adev
->
dev_manager
[
card
].
flag_in_active
=
1
;
flag_active
|=
AUDIO_IN
;
}
if
((
!
strcmp
(
adev
->
dev_manager
[
card
].
name
,
AUDIO_NAME_TD100
))
&&
(
adev
->
dev_manager
[
card
].
flag_in
==
AUDIO_IN
))
{
ALOGV
(
"OK, default use %s capture"
,
adev
->
dev_manager
[
card
].
name
);
adev
->
dev_manager
[
card
].
flag_in_active
=
1
;
flag_active
|=
AUDIO_IN
;
}
if
((
!
strcmp
(
adev
->
dev_manager
[
card
].
name
,
AUDIO_NAME_SNDES7210
))
&&
(
adev
->
dev_manager
[
card
].
flag_in
==
AUDIO_IN
))
{
ALOGV
(
"OK, default use %s capture"
,
adev
->
dev_manager
[
card
].
name
);
adev
->
dev_manager
[
card
].
flag_in_active
=
1
;
adev
->
input_active_cards
|=
AUDIO_CARD_SNDES7210
;
flag_active
|=
AUDIO_IN
;
}
if
(
(
!
strcmp
(
adev
->
dev_manager
[
card
].
name
,
AUDIO_NAME_CODEC
))
&&
(
adev
->
dev_manager
[
card
].
flag_out
==
AUDIO_OUT
))
{
ALOGV
(
"OK, default use %s playback"
,
adev
->
dev_manager
[
card
].
name
);
adev
->
dev_manager
[
card
].
flag_out_active
=
1
;
flag_active
|=
AUDIO_OUT
;
}
if
((
flag_active
&
AUDIO_IN
)
&&
(
flag_active
&
AUDIO_OUT
))
{
return
;
}
}
ALOGV
(
"low priority, chose any device"
);
for
(
card
=
0
;
card
<
MAX_AUDIO_DEVICES
;
card
++
)
{
if
(
!
adev
->
dev_manager
[
card
].
flag_exist
)
{
break
;
}
// there is no auido codec in
if
(
!
(
flag_active
&
AUDIO_IN
))
{
if
(
adev
->
dev_manager
[
card
].
flag_in
==
AUDIO_IN
)
{
ALOGV
(
"OK, default use %s capture"
,
adev
->
dev_manager
[
card
].
name
);
adev
->
dev_manager
[
card
].
flag_in_active
=
1
;
flag_active
|=
AUDIO_IN
;
}
}
// there is no auido codec out
if
(
!
(
flag_active
&
AUDIO_OUT
))
{
if
(
adev
->
dev_manager
[
card
].
flag_out
==
AUDIO_OUT
)
{
ALOGV
(
"OK, default use %s playback"
,
adev
->
dev_manager
[
card
].
name
);
adev
->
dev_manager
[
card
].
flag_out_active
=
1
;
flag_active
|=
AUDIO_OUT
;
}
}
}
return
;
}
static
int
update_audio_devices
(
struct
sunxi_audio_device
*
adev
)
{
int
card
=
0
;
int
ret
=
-
1
;
char
*
snd_path
=
"/sys/class/sound"
;
char
snd_card
[
128
];
memset
(
snd_card
,
0
,
sizeof
(
snd_card
));
for
(
card
=
0
;
card
<
MAX_AUDIO_DEVICES
;
card
++
)
{
sprintf
(
snd_card
,
"%s/card%d"
,
snd_path
,
card
);
ret
=
access
(
snd_card
,
F_OK
);
if
(
ret
==
0
)
{
if
(
adev
->
dev_manager
[
card
].
flag_exist
==
true
)
{
continue
;
// no changes
}
else
{
// plug-in
ALOGD
(
"do init audio card"
);
do_init_audio_card
(
adev
,
card
);
}
}
else
{
if
(
adev
->
dev_manager
[
card
].
flag_exist
==
false
)
{
continue
;
// no changes
}
else
{
// plug-out
adev
->
dev_manager
[
card
].
flag_exist
=
false
;
adev
->
dev_manager
[
card
].
flag_in
=
0
;
adev
->
dev_manager
[
card
].
flag_out
=
0
;
}
}
}
return
0
;
}
static
char
*
get_audio_devices
(
struct
sunxi_audio_device
*
adev
,
int
in_out
)
{
char
*
in_devices
=
adev
->
in_devices
;
char
*
out_devices
=
adev
->
out_devices
;
update_audio_devices
(
adev
);
memset
(
in_devices
,
0
,
128
);
memset
(
out_devices
,
0
,
128
);
ALOGD
(
"getAudioDevices()"
);
int
card
=
0
;
for
(
card
=
0
;
card
<
MAX_AUDIO_DEVICES
;
card
++
)
{
if
(
adev
->
dev_manager
[
card
].
flag_exist
==
true
)
{
// device in
if
(
adev
->
dev_manager
[
card
].
flag_in
==
AUDIO_IN
)
{
strcat
(
in_devices
,
adev
->
dev_manager
[
card
].
name
);
strcat
(
in_devices
,
","
);
ALOGD
(
"in dev:%s"
,
adev
->
dev_manager
[
card
].
name
);
}
// device out
if
(
adev
->
dev_manager
[
card
].
flag_out
==
AUDIO_OUT
)
{
strcat
(
out_devices
,
adev
->
dev_manager
[
card
].
name
);
strcat
(
out_devices
,
","
);
ALOGD
(
"out dev:%s"
,
adev
->
dev_manager
[
card
].
name
);
}
}
}
in_devices
[
strlen
(
in_devices
)
-
1
]
=
0
;
out_devices
[
strlen
(
out_devices
)
-
1
]
=
0
;
//
if
(
in_out
&
AUDIO_IN
)
{
ALOGD
(
"in capture: %s"
,
in_devices
);
return
in_devices
;
}
else
if
(
in_out
&
AUDIO_OUT
)
{
ALOGD
(
"out playback: %s"
,
out_devices
);
return
out_devices
;
}
else
{
ALOGE
(
"unknown in/out flag"
);
return
0
;
}
}
#if USE_INPUT_RESAMPLER
static
int
get_next_buffer
(
struct
resampler_buffer_provider
*
buffer_provider
,
struct
resampler_buffer
*
buffer
)
{
struct
sunxi_stream_in
*
in
;
if
(
buffer_provider
==
NULL
||
buffer
==
NULL
)
return
-
EINVAL
;
in
=
(
struct
sunxi_stream_in
*
)((
char
*
)
buffer_provider
-
offsetof
(
struct
sunxi_stream_in
,
buf_provider
));
if
(
in
->
pcm
==
NULL
)
{
buffer
->
raw
=
NULL
;
buffer
->
frame_count
=
0
;
in
->
read_status
=
-
ENODEV
;
return
-
ENODEV
;
}
if
(
in
->
frames_in
==
0
)
{
in
->
read_status
=
pcm_read
(
in
->
pcm
,
(
void
*
)
in
->
buffer
,
in
->
config
.
period_size
*
audio_stream_in_frame_size
(
&
in
->
stream
));
if
(
in
->
read_status
!=
0
)
{
ALOGE
(
"get_next_buffer() pcm_read error %d, %s"
,
in
->
read_status
,
strerror
(
errno
));
buffer
->
raw
=
NULL
;
buffer
->
frame_count
=
0
;
return
in
->
read_status
;
}
in
->
frames_in
=
in
->
config
.
period_size
;
}
buffer
->
frame_count
=
(
buffer
->
frame_count
>
in
->
frames_in
)
?
in
->
frames_in
:
buffer
->
frame_count
;
buffer
->
i16
=
in
->
buffer
+
(
in
->
config
.
period_size
-
in
->
frames_in
)
*
in
->
config
.
channels
;
return
in
->
read_status
;
}
static
void
release_buffer
(
struct
resampler_buffer_provider
*
buffer_provider
,
struct
resampler_buffer
*
buffer
)
{
struct
sunxi_stream_in
*
in
;
if
(
buffer_provider
==
NULL
||
buffer
==
NULL
)
return
;
in
=
(
struct
sunxi_stream_in
*
)((
char
*
)
buffer_provider
-
offsetof
(
struct
sunxi_stream_in
,
buf_provider
));
in
->
frames_in
-=
buffer
->
frame_count
;
}
#endif
static
int
get_hdmi_status
()
{
int
fd
=
0
;
char
hdmi_status
[
32
]
=
{
0
};
int
ret
;
int
hdmi_state
=
0
;
fd
=
open
(
"/sys/class/switch/hdmi/state"
,
O_RDONLY
);
if
(
fd
>
0
)
{
ret
=
read
(
fd
,
hdmi_status
,
sizeof
(
hdmi_status
));
if
(
ret
>
0
)
{
hdmi_status
[
ret
-
1
]
=
0
;
ALOGD
(
"hdmi_status : %s"
,
hdmi_status
);
}
sscanf
(
hdmi_status
,
"HDMI=%d"
,
&
hdmi_state
);
close
(
fd
);
}
else
{
return
-
1
;
}
return
hdmi_state
;
}
static
void
select_output_cards
(
struct
sunxi_audio_device
*
adev
)
{
if
(
adev
->
output_active_cards
&
EXTERNAL_OUTPUT_ACTIVE_CARD
){
adev
->
output_active_cards
&=
(
~
EXTERNAL_OUTPUT_ACTIVE_CARD
);
ALOGW
(
"card %#x used by external output, ignore it in primary output."
,
EXTERNAL_OUTPUT_ACTIVE_CARD
);
}
if
(
adev
->
output_active_cards
&
DSP_OUTPUT_ACTIVE_CARD
){
adev
->
output_active_cards
&=
(
~
DSP_OUTPUT_ACTIVE_CARD
);
ALOGW
(
"card %#x used by dsp output, ignore it in primary output."
,
DSP_OUTPUT_ACTIVE_CARD
);
}
if
(
adev
->
input_active_cards
&
DSP_INPUT_ACTIVE_CARD
){
adev
->
input_active_cards
&=
(
~
DSP_INPUT_ACTIVE_CARD
);
ALOGW
(
"card %#x used by dsp input, ignore it in primary input."
,
DSP_INPUT_ACTIVE_CARD
);
}
}
static
int
set_audio_devices_active
(
struct
sunxi_audio_device
*
adev
,
int
in_out
)
{
int
card
=
0
,
i
=
0
;
char
name
[
8
][
32
];
int
cnt
=
0
;
select_output_cards
(
adev
);
if
(
in_out
&
AUDIO_OUT
)
ALOGV
(
"output active = %#x"
,
adev
->
output_active_cards
);
if
(
in_out
&
AUDIO_IN
)
ALOGV
(
"input active = %#x"
,
adev
->
input_active_cards
);
if
(
in_out
&
AUDIO_OUT
){
if
(
adev
->
output_active_cards
&
AUDIO_CARD_CODEC
){
strcpy
(
name
[
cnt
++
],
AUDIO_NAME_CODEC
);
set_audio_path
(
adev
,
OUT_DEVICE_LINEOUT
,
1
);
}
if
(
adev
->
output_active_cards
&
AUDIO_CARD_HDMI
){
set_audio_path
(
adev
,
OUT_DEVICE_HDMI
,
1
);
strcpy
(
name
[
cnt
++
],
AUDIO_NAME_HDMI
);
}
if
(
adev
->
output_active_cards
&
AUDIO_CARD_I2S2
){
strcpy
(
name
[
cnt
++
],
AUDIO_NAME_I2S2
);
set_audio_path
(
adev
,
OUT_DEVICE_I2S2
,
1
);
}
if
(
adev
->
output_active_cards
&
AUDIO_CARD_I2S3
){
strcpy
(
name
[
cnt
++
],
AUDIO_NAME_I2S3
);
set_audio_path
(
adev
,
OUT_DEVICE_I2S3
,
1
);
}
if
(
adev
->
output_active_cards
&
AUDIO_CARD_SNDBT936B
){
strcpy
(
name
[
cnt
++
],
AUDIO_NAME_SNDBT936B
);
set_audio_path
(
adev
,
OUT_DEVICE_SNDBT936B
,
1
);
}
if
(
adev
->
output_active_cards
&
AUDIO_CARD_SPDIF
){
strcpy
(
name
[
cnt
++
],
AUDIO_NAME_SPDIF
);
}
}
if
(
in_out
&
AUDIO_IN
){
if
(
adev
->
input_active_cards
&
AUDIO_CARD_AC107
){
strcpy
(
name
[
cnt
++
],
AUDIO_NAME_AC107
);
set_audio_path
(
adev
,
IN_DEVICE_AC107
,
1
);
}
else
if
(
adev
->
input_active_cards
&
AUDIO_CARD_TD100
){
strcpy
(
name
[
cnt
++
],
AUDIO_NAME_TD100
);
set_audio_path
(
adev
,
IN_DEVICE_TD100
,
1
);
}
else
if
(
adev
->
input_active_cards
&
AUDIO_CARD_SNDES7210
){
strcpy
(
name
[
cnt
++
],
AUDIO_NAME_SNDES7210
);
set_audio_path
(
adev
,
IN_DEVICE_SNDES7210
,
1
);
}
else
if
(
adev
->
input_active_cards
&
AUDIO_CARD_SNDBT936B
){
strcpy
(
name
[
cnt
++
],
AUDIO_NAME_SNDBT936B
);
set_audio_path
(
adev
,
IN_DEVICE_SNDBT936B
,
1
);
}
else
if
(
adev
->
input_active_cards
&
AUDIO_CARD_I2S2
){
strcpy
(
name
[
cnt
++
],
AUDIO_NAME_I2S2
);
set_audio_path
(
adev
,
IN_DEVICE_I2S2
,
1
);
}
else
if
(
adev
->
input_active_cards
&
AUDIO_CARD_I2S3
){
strcpy
(
name
[
cnt
++
],
AUDIO_NAME_I2S3
);
set_audio_path
(
adev
,
IN_DEVICE_I2S3
,
1
);
}
}
for
(
card
=
0
;
card
<
MAX_AUDIO_DEVICES
;
card
++
)
{
if
(
in_out
&
AUDIO_IN
)
{
adev
->
dev_manager
[
card
].
flag_in_active
=
0
;
}
else
{
adev
->
dev_manager
[
card
].
flag_out_active
=
0
;
}
}
for
(
i
=
0
;
i
<
cnt
;
i
++
)
{
for
(
card
=
0
;
card
<
MAX_AUDIO_DEVICES
;
card
++
)
{
if
(
in_out
&
AUDIO_IN
)
{
if
((
adev
->
dev_manager
[
card
].
flag_in
==
in_out
)
&&
(
strcmp
(
adev
->
dev_manager
[
card
].
name
,
name
[
i
])
==
0
))
{
ALOGV
(
"%s %s device will be active"
,
name
[
i
],
"input"
);
adev
->
dev_manager
[
card
].
flag_in_active
=
1
;
// only one capture device can be active
return
0
;
}
}
else
if
((
adev
->
dev_manager
[
card
].
flag_out
==
in_out
)
&&
(
strcmp
(
adev
->
dev_manager
[
card
].
name
,
name
[
i
])
==
0
))
{
ALOGV
(
"%s %s card %d device will be active"
,
name
[
i
],
"output"
,
card
);
adev
->
dev_manager
[
card
].
flag_out_active
=
1
;
break
;
}
}
if
(
card
==
MAX_AUDIO_DEVICES
&&
i
>
cnt
)
{
if
(
in_out
&
AUDIO_IN
)
{
ALOGE
(
"can not set %s active device"
,
(
in_out
&
AUDIO_IN
)
?
"input"
:
"ouput"
);
adev
->
dev_manager
[
adev
->
card_codec
].
flag_in_active
=
1
;
ALOGE
(
"but %s %s will be active"
,
adev
->
dev_manager
[
adev
->
card_codec
].
name
,
(
in_out
&
AUDIO_IN
)
?
"input"
:
"ouput"
);
return
0
;
}
else
{
ALOGE
(
"can not set %s active device"
,
(
in_out
&
AUDIO_IN
)
?
"input"
:
"ouput"
);
adev
->
dev_manager
[
adev
->
card_ac107
].
flag_out_active
=
1
;
ALOGE
(
"but %s %s will be active"
,
adev
->
dev_manager
[
adev
->
card_ac107
].
name
,(
in_out
&
AUDIO_IN
)
?
"input"
:
"ouput"
);
return
-
1
;
}
return
-
1
;
}
}
return
0
;
}
static
int
get_audio_devices_active
(
struct
sunxi_audio_device
*
adev
,
int
in_out
,
char
*
devices
)
{
ALOGD
(
"get_audio_devices_active: %s"
,
devices
);
int
card
=
0
;
if
(
devices
==
0
)
return
-
1
;
for
(
card
=
0
;
card
<
MAX_AUDIO_DEVICES
;
card
++
)
{
if
(
in_out
&
AUDIO_IN
)
{
if
((
adev
->
dev_manager
[
card
].
flag_in
==
in_out
)
&&
(
adev
->
dev_manager
[
card
].
flag_in_active
==
1
))
{
strcat
(
devices
,
adev
->
dev_manager
[
card
].
name
);
strcat
(
devices
,
","
);
}
}
else
{
if
((
adev
->
dev_manager
[
card
].
flag_out
==
in_out
)
&&
(
adev
->
dev_manager
[
card
].
flag_out_active
==
1
))
{
strcat
(
devices
,
adev
->
dev_manager
[
card
].
name
);
strcat
(
devices
,
","
);
}
}
}
devices
[
strlen
(
devices
)
-
1
]
=
0
;
ALOGD
(
"get_audio_devices_active: %s"
,
devices
);
return
0
;
}
static
void
force_all_standby
(
struct
sunxi_audio_device
*
adev
)
{
struct
sunxi_stream_in
*
in
;
struct
sunxi_stream_out
*
out
;
if
(
adev
->
active_output
)
{
out
=
adev
->
active_output
;
pthread_mutex_lock
(
&
out
->
lock
);
do_output_standby
(
out
);
pthread_mutex_unlock
(
&
out
->
lock
);
}
if
(
adev
->
active_input
)
{
in
=
adev
->
active_input
;
pthread_mutex_lock
(
&
in
->
lock
);
do_input_standby
(
in
);
pthread_mutex_unlock
(
&
in
->
lock
);
}
}
static
void
select_mode
(
struct
sunxi_audio_device
*
adev
)
{
if
(
adev
->
mode
==
AUDIO_MODE_IN_CALL
)
{
ALOGV
(
"Entering IN_CALL state, in_call=%d"
,
adev
->
in_call
);
if
(
!
adev
->
in_call
)
{
force_all_standby
(
adev
);
adev
->
in_call
=
1
;
}
}
else
{
ALOGV
(
"Leaving IN_CALL state, in_call=%d, mode=%d"
,
adev
->
in_call
,
adev
->
mode
);
if
(
adev
->
in_call
)
{
adev
->
in_call
=
0
;
force_all_standby
(
adev
);
}
}
}
static
void
set_audio_path
(
struct
sunxi_audio_device
*
adev
,
int
device_path
,
int
status
)
{
const
char
*
name
=
NULL
;
struct
audio_route
*
ar
=
NULL
;
if
(
device_path
==
OUT_DEVICE_LINEOUT
||
device_path
==
AA_LINEIN_LINEOUT
||
device_path
==
AA_FMIN_LINEOUT
){
ar
=
adev
->
ar_codec
;
}
else
{
ar
=
adev
->
ar_ahub
;
}
if
(
!
ar
)
{
ALOGE
(
"FUNC: %s, LINE: %d, audio route is not init"
,
__FUNCTION__
,
__LINE__
);
return
;
}
//audio_route_reset(ar);
if
(
status
){
name
=
route_configs
[
device_path
].
open
;
}
else
{
name
=
route_configs
[
device_path
].
close
;
}
if
(
name
){
audio_route_apply_path
(
ar
,
name
);
audio_route_update_mixer
(
ar
);
}
else
{
ALOGE
(
"FUNC: %s, LINE: %d, cannot find path for %d"
,
__FUNCTION__
,
__LINE__
,
device_path
);
}
}
static
void
reset_audio_path
(
struct
sunxi_audio_device
*
adev
)
{
if
(
adev
->
stanby
)
{
if
(
adev
->
ar_ahub
)
{
audio_route_free
(
adev
->
ar_ahub
);
adev
->
ar_ahub
=
NULL
;
}
if
(
adev
->
ar_codec
)
{
audio_route_free
(
adev
->
ar_codec
);
adev
->
ar_codec
=
NULL
;
}
if
(
adev
->
ar_ahub
==
NULL
)
{
ALOGD
(
"reset_audio_path card %d, init ahub route ......"
,
adev
->
card_ahub
);
adev
->
ar_ahub
=
audio_route_init
(
adev
->
card_ahub
,
AUDIO_AHUB_XML_PATH
);
}
if
(
adev
->
ar_codec
==
NULL
)
{
ALOGD
(
"reset_audio_path card %d, init codec route ......"
,
adev
->
card_codec
);
adev
->
ar_codec
=
audio_route_init
(
adev
->
card_codec
,
AUDIO_CODEC_XML_PATH
);
}
adev
->
stanby
=
false
;
}
if
(
adev
->
output_active_cards
&
AUDIO_CARD_CODEC
){
set_audio_path
(
adev
,
OUT_DEVICE_LINEOUT
,
1
);
}
if
(
adev
->
output_active_cards
&
AUDIO_CARD_I2S2
){
set_audio_path
(
adev
,
OUT_DEVICE_I2S2
,
1
);
}
if
(
adev
->
output_active_cards
&
AUDIO_CARD_I2S3
){
set_audio_path
(
adev
,
OUT_DEVICE_I2S3
,
1
);
}
if
(
adev
->
output_active_cards
&
AUDIO_CARD_SNDBT936B
){
set_audio_path
(
adev
,
OUT_DEVICE_SNDBT936B
,
1
);
}
if
(
adev
->
input_active_cards
&
AUDIO_CARD_AC107
){
set_audio_path
(
adev
,
IN_DEVICE_AC107
,
1
);
init_ac107_devices
(
adev
);
}
else
if
(
adev
->
input_active_cards
&
AUDIO_CARD_TD100
){
set_audio_path
(
adev
,
IN_DEVICE_TD100
,
1
);
init_td100_devices
(
adev
);
}
else
if
(
adev
->
input_active_cards
&
AUDIO_CARD_SNDES7210
){
set_audio_path
(
adev
,
IN_DEVICE_SNDES7210
,
1
);
}
else
if
(
adev
->
input_active_cards
&
AUDIO_CARD_SNDBT936B
){
set_audio_path
(
adev
,
IN_DEVICE_SNDBT936B
,
1
);
}
else
if
(
adev
->
input_active_cards
&
AUDIO_CARD_I2S2
){
set_audio_path
(
adev
,
IN_DEVICE_I2S2
,
1
);
}
else
if
(
adev
->
input_active_cards
&
AUDIO_CARD_I2S3
){
set_audio_path
(
adev
,
IN_DEVICE_I2S3
,
1
);
}
}
static
void
select_output_device
(
struct
sunxi_audio_device
*
adev
)
{
ALOGD
(
"line:%d,%s,adev->mode:%d"
,
__LINE__
,
__FUNCTION__
,
adev
->
mode
);
}
static
void
select_input_device
(
struct
sunxi_audio_device
*
adev
)
{
ALOGD
(
"line:%d,%s,adev->mode:%d"
,
__LINE__
,
__FUNCTION__
,
adev
->
mode
);
}
/* must be called with hw device and output stream mutexes locked */
static
int
start_output_stream
(
struct
sunxi_stream_out
*
out
)
{
struct
sunxi_audio_device
*
adev
=
out
->
dev
;
unsigned
int
card
=
0
;
unsigned
int
port
=
0
;
unsigned
int
index
=
0
;
int
ret
;
if
(
adev
->
mode
==
AUDIO_MODE_IN_CALL
)
{
#if call_button_voice
// if (out->device == AUDIO_DEVICE_OUT_BLUETOOTH_SCO ||
// out->device == AUDIO_DEVICE_OUT_BLUETOOTH_SCO_HEADSET ||
// out->device == AUDIO_DEVICE_OUT_BLUETOOTH_SCO_CARKIT) {
// ALOGD("[SCO] start_output_stream: device=0x%x", out->device);
// out->config.rate = 8000;
// out->config.channels = 1;
// out->config.format = PCM_FORMAT_S16_LE;
// out->config.period_size = 160;
// out->config.period_count = 4;
// } else
if
(
out
->
device
==
AUDIO_DEVICE_OUT_SPEAKER
)
{
ALOGD
(
"[SPEAKER] start_output_stream: device=0x%x"
,
out
->
device
);
// Use default config for speaker in call mode
// Keep the default configuration from pcm_config_out
}
#else
ALOGW
(
"mode in call, do not start stream"
);
return
0
;
#endif
}
adev
->
active_output
=
out
;
reset_audio_path
(
adev
);
for
(
index
=
0
;
index
<
MAX_AUDIO_DEVICES
;
index
++
)
{
if
(
adev
->
dev_manager
[
index
].
flag_exist
&&
(
adev
->
dev_manager
[
index
].
flag_out
==
AUDIO_OUT
)
&&
adev
->
dev_manager
[
index
].
flag_out_active
)
{
card
=
index
;
port
=
0
;
ALOGV
(
"use %s to playback audio"
,
adev
->
dev_manager
[
index
].
name
);
out
->
multi_config
[
index
]
=
pcm_config_out
;
out
->
multi_config
[
index
].
start_threshold
=
DEFAULT_OUTPUT_PERIOD_SIZE
*
2
;
if
(
adev
->
dev_manager
[
index
].
ahub_device
){
#if ENABLE_SUB_PCM_DEVICE
if
(
strcmp
(
adev
->
dev_manager
[
index
].
name
,
SUB_PCM_DEVICE
)){
out
->
sub_pcm
[
index
]
=
pcm_open
(
index
,
port
,
PCM_OUT
,
&
out
->
multi_config
[
index
]);
}
#else
out
->
sub_pcm
[
index
]
=
pcm_open
(
index
,
port
,
PCM_OUT
,
&
out
->
multi_config
[
index
]);
#endif
if
(
!
pcm_is_ready
(
out
->
sub_pcm
[
index
]))
{
ALOGE
(
"cannot open pcm driver: %s"
,
pcm_get_error
(
out
->
sub_pcm
[
index
]));
pcm_close
(
out
->
sub_pcm
[
index
]);
out
->
sub_pcm
[
index
]
=
NULL
;
adev
->
active_output
=
NULL
;
return
-
ENOMEM
;
}
card
=
adev
->
card_ahub
;
port
=
adev
->
dev_manager
[
index
].
port
;
pcm_start
(
out
->
sub_pcm
[
index
]);
}
out
->
multi_pcm
[
index
]
=
pcm_open
(
card
,
port
,
PCM_OUT
,
&
out
->
multi_config
[
index
]);
if
(
!
pcm_is_ready
(
out
->
multi_pcm
[
index
]))
{
ALOGE
(
"cannot open pcm driver: %s"
,
pcm_get_error
(
out
->
multi_pcm
[
index
]));
pcm_close
(
out
->
multi_pcm
[
index
]);
out
->
multi_pcm
[
index
]
=
NULL
;
adev
->
active_output
=
NULL
;
return
-
ENOMEM
;
}
if
(
DEFAULT_SAMPLING_RATE
!=
out
->
multi_config
[
index
].
rate
)
{
ret
=
create_resampler
(
DEFAULT_SAMPLING_RATE
,
out
->
multi_config
[
index
].
rate
,
2
,
RESAMPLER_QUALITY_DEFAULT
,
NULL
,
&
out
->
multi_resampler
[
index
]);
if
(
ret
!=
0
)
{
ALOGE
(
"create out resampler failed, %d -> %d"
,
DEFAULT_SAMPLING_RATE
,
out
->
multi_config
[
index
].
rate
);
return
ret
;
}
ALOGV
(
"create out resampler OK, %d -> %d"
,
DEFAULT_SAMPLING_RATE
,
out
->
multi_config
[
index
].
rate
);
}
else
ALOGV
(
"play audio with %d Hz serial sample rate."
,
DEFAULT_SAMPLING_RATE
);
if
(
out
->
multi_resampler
[
index
])
{
out
->
multi_resampler
[
index
]
->
reset
(
out
->
multi_resampler
[
index
]);
}
}
}
return
0
;
}
static
int
check_input_parameters
(
uint32_t
sample_rate
,
int
format
,
int
channel_count
)
{
if
(
format
!=
AUDIO_FORMAT_PCM_16_BIT
)
return
-
EINVAL
;
if
((
channel_count
<
1
)
||
(
channel_count
>
2
))
return
-
EINVAL
;
switch
(
sample_rate
)
{
case
8000
:
case
11025
:
case
12000
:
case
16000
:
case
22050
:
case
24000
:
case
32000
:
case
44100
:
case
48000
:
break
;
default:
return
-
EINVAL
;
}
return
0
;
}
static
size_t
get_input_buffer_size
(
uint32_t
sample_rate
,
int
format
,
int
channel_count
)
{
size_t
size
;
if
(
check_input_parameters
(
sample_rate
,
format
,
channel_count
)
!=
0
)
return
0
;
/* take resampling into account and return the closest majoring
multiple of 16 frames, as audioflinger expects audio buffers to
be a multiple of 16 frames */
size
=
(
pcm_config_in
.
period_size
*
sample_rate
)
/
pcm_config_in
.
rate
;
size
=
((
size
+
15
)
/
16
)
*
16
;
return
size
*
channel_count
*
sizeof
(
short
);
}
static
uint32_t
out_get_sample_rate
(
const
struct
audio_stream
*
stream
)
{
UNUSED
(
stream
);
return
DEFAULT_SAMPLING_RATE
;
}
static
int
out_set_sample_rate
(
struct
audio_stream
*
stream
,
uint32_t
rate
)
{
UNUSED
(
stream
);
UNUSED
(
rate
);
return
0
;
}
static
size_t
out_get_buffer_size
(
const
struct
audio_stream
*
stream
)
{
struct
sunxi_stream_out
*
out
=
(
struct
sunxi_stream_out
*
)
stream
;
/* take resampling into account and return the closest majoring
multiple of 16 frames, as audioflinger expects audio buffers to
be a multiple of 16 frames */
size_t
size
=
((
DEFAULT_OUTPUT_PERIOD_SIZE
+
15
)
/
16
)
*
16
;
return
size
*
audio_stream_out_frame_size
(
&
out
->
stream
);
}
static
audio_channel_mask_t
out_get_channels
(
const
struct
audio_stream
*
stream
)
{
UNUSED
(
stream
);
return
AUDIO_CHANNEL_OUT_STEREO
;
}
static
audio_format_t
out_get_format
(
const
struct
audio_stream
*
stream
)
{
UNUSED
(
stream
);
struct
sunxi_stream_out
*
out
=
(
struct
sunxi_stream_out
*
)
stream
;
audio_format_t
outformat
=
AUDIO_FORMAT_PCM_16_BIT
;
if
(
out
->
format
!=
AUDIO_FORMAT_DEFAULT
)
outformat
=
out
->
format
;
return
outformat
;
}
static
int
out_set_format
(
struct
audio_stream
*
stream
,
audio_format_t
format
)
{
UNUSED
(
stream
);
UNUSED
(
format
);
return
0
;
}
/* must be called with hw device and output stream mutexes locked */
static
int
do_output_standby
(
struct
sunxi_stream_out
*
out
)
{
int
index
=
0
;
#if ENABLE_SUB_PCM_DEVICE
struct
sunxi_audio_device
*
adev
=
out
->
dev
;
#endif
if
(
!
out
->
standby
)
{
for
(
index
=
0
;
index
<
MAX_AUDIO_DEVICES
;
index
++
)
{
if
(
out
->
multi_pcm
[
index
])
{
pcm_close
(
out
->
multi_pcm
[
index
]);
out
->
multi_pcm
[
index
]
=
NULL
;
}
if
(
out
->
sub_pcm
[
index
])
{
#if ENABLE_SUB_PCM_DEVICE
if
(
strcmp
(
adev
->
dev_manager
[
index
].
name
,
SUB_PCM_DEVICE
)){
pcm_close
(
out
->
sub_pcm
[
index
]);
out
->
sub_pcm
[
index
]
=
NULL
;
}
#else
pcm_close
(
out
->
sub_pcm
[
index
]);
out
->
sub_pcm
[
index
]
=
NULL
;
#endif
}
if
(
out
->
multi_resampler
[
index
])
{
release_resampler
(
out
->
multi_resampler
[
index
]);
out
->
multi_resampler
[
index
]
=
NULL
;
}
}
//adev->active_output = 0;
out
->
standby
=
1
;
}
return
0
;
}
static
int
out_standby
(
struct
audio_stream
*
stream
)
{
struct
sunxi_stream_out
*
out
=
(
struct
sunxi_stream_out
*
)
stream
;
int
status
;
ALOGD
(
"out_standby"
);
pthread_mutex_lock
(
&
out
->
lock
);
status
=
do_output_standby
(
out
);
pthread_mutex_unlock
(
&
out
->
lock
);
return
status
;
}
static
int
out_dump
(
const
struct
audio_stream
*
stream
,
int
fd
)
{
UNUSED
(
stream
);
UNUSED
(
fd
);
return
0
;
}
static
int
out_set_parameters
(
struct
audio_stream
*
stream
,
const
char
*
kvpairs
)
{
struct
sunxi_stream_out
*
out
=
(
struct
sunxi_stream_out
*
)
stream
;
struct
str_parms
*
parms
;
char
value
[
128
];
int
ret
,
val
=
0
;
parms
=
str_parms_create_str
(
kvpairs
);
ALOGV
(
"out_set_parameters: %s"
,
kvpairs
);
ret
=
str_parms_get_str
(
parms
,
AUDIO_PARAMETER_STREAM_ROUTING
,
value
,
sizeof
(
value
));
if
(
ret
>=
0
)
{
val
=
atoi
(
value
);
out
->
device
=
val
;
ALOGD
(
"out_set_parameters: routing=%d (0x%x)"
,
val
,
val
);
// Log if this is a Bluetooth SCO device
if
(
val
==
AUDIO_DEVICE_OUT_BLUETOOTH_SCO
||
val
==
AUDIO_DEVICE_OUT_BLUETOOTH_SCO_HEADSET
||
val
==
AUDIO_DEVICE_OUT_BLUETOOTH_SCO_CARKIT
)
{
ALOGD
(
"out_set_parameters: Bluetooth SCO output device set (0x%x)"
,
val
);
}
}
str_parms_destroy
(
parms
);
return
ret
;
}
static
char
*
out_get_parameters
(
const
struct
audio_stream
*
stream
,
const
char
*
keys
)
{
UNUSED
(
stream
);
UNUSED
(
keys
);
return
strdup
(
""
);
}
static
uint32_t
out_get_latency
(
const
struct
audio_stream_out
*
stream
)
{
UNUSED
(
stream
);
return
(
DEFAULT_OUTPUT_PERIOD_SIZE
*
DEFAULT_OUTPUT_PERIOD_COUNT
*
1000
)
/
DEFAULT_SAMPLING_RATE
;
}
static
int
out_set_volume
(
struct
audio_stream_out
*
stream
,
float
left
,
float
right
)
{
UNUSED
(
stream
);
UNUSED
(
left
);
UNUSED
(
right
);
return
-
ENOSYS
;
}
static
ssize_t
out_write
(
struct
audio_stream_out
*
stream
,
const
void
*
buffer
,
size_t
bytes
)
{
int
ret
;
struct
sunxi_stream_out
*
out
=
(
struct
sunxi_stream_out
*
)
stream
;
struct
sunxi_audio_device
*
adev
=
out
->
dev
;
size_t
frame_size
=
audio_stream_out_frame_size
(
&
out
->
stream
);
size_t
in_frames
=
bytes
/
frame_size
;
size_t
out_frames
=
RESAMPLER_BUFFER_SIZE
/
frame_size
;
void
*
buf
;
int
index
;
int
card
;
char
prop_value
[
128
];
if
(
adev
->
mode
==
AUDIO_MODE_IN_CALL
)
{
#if call_button_voice
if
(
out
->
device
!=
AUDIO_DEVICE_OUT_BLUETOOTH_SCO
&&
out
->
device
!=
AUDIO_DEVICE_OUT_BLUETOOTH_SCO_HEADSET
&&
out
->
device
!=
AUDIO_DEVICE_OUT_BLUETOOTH_SCO_CARKIT
&&
out
->
device
!=
AUDIO_DEVICE_OUT_SPEAKER
)
{
ALOGD
(
"in call mode, not BT SCO or speaker, skip out_write (device=0x%x)"
,
out
->
device
);
int
time
=
bytes
*
1000000
/
4
/
DEFAULT_SAMPLING_RATE
;
usleep
(
time
);
return
bytes
;
}
if
(
out
->
device
==
AUDIO_DEVICE_OUT_SPEAKER
)
{
// ALOGD("Speaker call mode, allow out_write (device=0x%x)", out->device);
}
else
{
ALOGD
(
"Bluetooth SCO call mode, allow out_write (device=0x%x)"
,
out
->
device
);
}
#else
ALOGD
(
"mode in call, do not out_write"
);
int
time
=
bytes
*
1000
*
1000
/
4
/
DEFAULT_SAMPLING_RATE
;
usleep
(
time
);
return
bytes
;
#endif
}
ret
=
property_get
(
PROP_RAWDATA_OUTPUT
,
prop_value
,
""
);
if
(
ret
>
0
){
adev
->
raw_enable
=
atoi
(
prop_value
);
}
else
{
adev
->
raw_enable
=
false
;
}
if
(
adev
->
raw_enable
){
ALOGW
(
"rawdata output mode, do not write pcm data"
);
if
(
!
out
->
standby
){
pthread_mutex_lock
(
&
adev
->
lock
);
pthread_mutex_lock
(
&
out
->
lock
);
do_output_standby
(
out
);
pthread_mutex_unlock
(
&
out
->
lock
);
pthread_mutex_unlock
(
&
adev
->
lock
);
}
int
time
=
bytes
*
1000
*
1000
/
4
/
DEFAULT_SAMPLING_RATE
;
usleep
(
time
);
return
bytes
;
}
/* acquiring hw device mutex systematically is useful if a low priority thread is waiting
* on the output stream mutex - e.g. executing select_mode() while holding the hw device
* mutex
*/
pthread_mutex_lock
(
&
adev
->
lock
);
pthread_mutex_lock
(
&
out
->
lock
);
if
(
out
->
standby
)
{
ret
=
start_output_stream
(
out
);
if
(
ret
!=
0
)
{
pthread_mutex_unlock
(
&
out
->
lock
);
pthread_mutex_unlock
(
&
adev
->
lock
);
goto
exit
;
}
out
->
standby
=
0
;
}
for
(
index
=
MAX_AUDIO_DEVICES
;
index
>=
0
;
index
--
)
{
if
(
adev
->
dev_manager
[
index
].
flag_exist
&&
(
adev
->
dev_manager
[
index
].
flag_out
==
AUDIO_OUT
)
&&
adev
->
dev_manager
[
index
].
flag_out_active
)
{
card
=
index
;
if
(
out
->
multi_resampler
[
card
])
{
out
->
multi_resampler
[
card
]
->
resample_from_input
(
out
->
multi_resampler
[
card
],
(
int16_t
*
)
buffer
,
&
in_frames
,
(
int16_t
*
)
out
->
buffer
,
&
out_frames
);
buf
=
out
->
buffer
;
}
else
{
out_frames
=
in_frames
;
buf
=
(
void
*
)
buffer
;
}
if
(
out
->
multi_config
[
card
].
channels
==
2
)
{
ret
=
pcm_write
(
out
->
multi_pcm
[
card
],
(
void
*
)
buf
,
out_frames
*
frame_size
);
}
else
{
size_t
i
;
char
*
pcm_buf
=
(
char
*
)
buf
;
for
(
i
=
0
;
i
<
out_frames
;
i
++
)
{
pcm_buf
[
2
*
i
+
2
]
=
pcm_buf
[
4
*
i
+
4
];
pcm_buf
[
2
*
i
+
3
]
=
pcm_buf
[
4
*
i
+
5
];
}
ret
=
pcm_write
(
out
->
multi_pcm
[
card
],
(
void
*
)
buf
,
out_frames
*
frame_size
/
2
);
}
if
(
ret
!=
0
)
{
ALOGE
(
"##############out_write() Warning:write fail, reopen it ret = %d #######################"
,
ret
);
do_output_standby
(
out
);
usleep
(
30000
);
break
;
}
}
}
pthread_mutex_unlock
(
&
out
->
lock
);
pthread_mutex_unlock
(
&
adev
->
lock
);
exit:
if
(
ret
!=
0
)
{
usleep
(
bytes
*
1000000
/
audio_stream_out_frame_size
(
stream
)
/
out_get_sample_rate
(
&
stream
->
common
));
}
return
bytes
;
}
static
int
out_get_render_position
(
const
struct
audio_stream_out
*
stream
,
uint32_t
*
dsp_frames
)
{
UNUSED
(
stream
);
UNUSED
(
dsp_frames
);
return
-
EINVAL
;
}
static
int
out_add_audio_effect
(
const
struct
audio_stream
*
stream
,
effect_handle_t
effect
)
{
UNUSED
(
stream
);
UNUSED
(
effect
);
return
0
;
}
static
int
out_remove_audio_effect
(
const
struct
audio_stream
*
stream
,
effect_handle_t
effect
)
{
UNUSED
(
stream
);
UNUSED
(
effect
);
return
0
;
}
static
int
out_get_next_write_timestamp
(
const
struct
audio_stream_out
*
stream
,
int64_t
*
timestamp
)
{
UNUSED
(
stream
);
UNUSED
(
timestamp
);
return
-
EINVAL
;
}
/* must be called with hw device and input stream mutexes locked */
static
int
start_input_stream
(
struct
sunxi_stream_in
*
in
)
{
int
index
=
0
;
int
card
=
0
;
int
port
=
0
;
struct
sunxi_audio_device
*
adev
=
in
->
dev
;
adev
->
active_input
=
in
;
if
(
adev
->
mode
==
AUDIO_MODE_IN_CALL
)
{
#if call_button_voice
// if (in->device == AUDIO_DEVICE_IN_BLUETOOTH_SCO_HEADSET) {
// ALOGD("[SCO] start_input_stream: device=0x%x", in->device);
// in->config.rate = 8000;
// in->config.channels = 1;
// in->config.format = PCM_FORMAT_S16_LE;
// in->config.period_size = 160;
// in->config.period_count = 4;
// } else
if
(
in
->
device
==
AUDIO_DEVICE_IN_BUILTIN_MIC
)
{
ALOGD
(
"[BUILTIN_MIC] start_input_stream: device=0x%x"
,
in
->
device
);
// Use default config for builtin mic in call mode
// Keep the default configuration from pcm_config_in
}
#else
ALOGD
(
"in call mode , start_input_stream, return"
);
return
0
;
#endif
}
else
{
ALOGD
(
"[IN_DEVICE] start_input_stream: device=0x%x, module = 0x%x"
,
in
->
device
,
adev
->
mode
);
}
reset_audio_path
(
adev
);
ALOGV
(
"catpure audio with %d Hz serial sample rate."
,
in
->
config
.
rate
);
for
(
index
=
0
;
index
<
MAX_AUDIO_DEVICES
;
index
++
)
{
ALOGD
(
"====> index:%d[%s/%s], flag_exist:%d, flang_in:%d, flag_in_active:%d"
,
index
,
adev
->
dev_manager
[
index
].
name
,
adev
->
dev_manager
[
index
].
card_id
,
adev
->
dev_manager
[
index
].
flag_exist
,
adev
->
dev_manager
[
index
].
flag_in
,
adev
->
dev_manager
[
index
].
flag_in_active
);
if
(
adev
->
dev_manager
[
index
].
flag_exist
&&
(
adev
->
dev_manager
[
index
].
flag_in
==
AUDIO_IN
)
&&
adev
->
dev_manager
[
index
].
flag_in_active
)
{
ALOGD
(
"use %s to capture audio"
,
adev
->
dev_manager
[
index
].
name
);
break
;
}
}
card
=
index
;
port
=
0
;
if
(
adev
->
dev_manager
[
index
].
ahub_device
){
in
->
sub_pcm
=
pcm_open
(
index
,
port
,
PCM_IN
,
&
in
->
config
);
// in->sub_pcm = pcm_open(3, 0, PCM_IN, &in->config);
ALOGE
(
"============> %s:%d, pcmopen, %d, %d"
,
__FILE__
,
__LINE__
,
index
,
port
)
;
if
(
!
pcm_is_ready
(
in
->
sub_pcm
))
{
ALOGE
(
"cannot open pcm_in driver: %s"
,
pcm_get_error
(
in
->
sub_pcm
));
pcm_close
(
in
->
sub_pcm
);
adev
->
active_input
=
NULL
;
return
-
ENOMEM
;
}
card
=
adev
->
card_ahub
;
port
=
adev
->
dev_manager
[
index
].
port
;
ALOGD
(
"ahub card port : %d"
,
port
);
pcm_start
(
in
->
sub_pcm
);
}
in
->
pcm
=
pcm_open
(
card
,
port
,
PCM_IN
,
&
in
->
config
);
// in->pcm = pcm_open(3, 0, PCM_IN, &in->config);
ALOGE
(
"============> %s:%d, pcmopen, %d, %d"
,
__FILE__
,
__LINE__
,
card
,
port
)
;
if
(
!
pcm_is_ready
(
in
->
pcm
))
{
ALOGE
(
"cannot open pcm_in driver: %s"
,
pcm_get_error
(
in
->
pcm
));
pcm_close
(
in
->
pcm
);
adev
->
active_input
=
NULL
;
return
-
ENOMEM
;
}
#if USE_INPUT_RESAMPLER
int
ret
=
0
;
if
(
in
->
requested_rate
!=
in
->
config
.
rate
)
{
in
->
buf_provider
.
get_next_buffer
=
get_next_buffer
;
in
->
buf_provider
.
release_buffer
=
release_buffer
;
ret
=
create_resampler
(
in
->
config
.
rate
,
in
->
requested_rate
,
in
->
config
.
channels
,
RESAMPLER_QUALITY_DEFAULT
,
&
in
->
buf_provider
,
&
in
->
resampler
);
if
(
ret
!=
0
)
{
ALOGE
(
"create in resampler failed, %d -> %d"
,
in
->
config
.
rate
,
in
->
requested_rate
);
ret
=
-
EINVAL
;
goto
err
;
}
ALOGV
(
"create in resampler OK, %d -> %d"
,
in
->
config
.
rate
,
in
->
requested_rate
);
}
else
ALOGV
(
"do not use in resampler"
);
/* if no supported sample rate is available, use the resampler */
if
(
in
->
resampler
)
{
in
->
resampler
->
reset
(
in
->
resampler
);
in
->
frames_in
=
0
;
}
return
0
;
err:
if
(
in
->
resampler
)
release_resampler
(
in
->
resampler
);
return
-
1
;
#else
return
0
;
#endif
}
static
uint32_t
in_get_sample_rate
(
const
struct
audio_stream
*
stream
)
{
struct
sunxi_stream_in
*
in
=
(
struct
sunxi_stream_in
*
)
stream
;
return
in
->
requested_rate
;
}
static
int
in_set_sample_rate
(
struct
audio_stream
*
stream
,
uint32_t
rate
)
{
UNUSED
(
stream
);
UNUSED
(
rate
);
return
0
;
}
static
size_t
in_get_buffer_size
(
const
struct
audio_stream
*
stream
)
{
struct
sunxi_stream_in
*
in
=
(
struct
sunxi_stream_in
*
)
stream
;
return
get_input_buffer_size
(
in
->
requested_rate
,
AUDIO_FORMAT_PCM_16_BIT
,
in
->
config
.
channels
);
}
static
audio_channel_mask_t
in_get_channels
(
const
struct
audio_stream
*
stream
)
{
struct
sunxi_stream_in
*
in
=
(
struct
sunxi_stream_in
*
)
stream
;
if
(
in
->
config
.
channels
==
1
)
{
return
AUDIO_CHANNEL_IN_MONO
;
}
else
{
return
AUDIO_CHANNEL_IN_STEREO
;
}
}
static
audio_format_t
in_get_format
(
const
struct
audio_stream
*
stream
)
{
UNUSED
(
stream
);
return
AUDIO_FORMAT_PCM_16_BIT
;
}
static
int
in_set_format
(
struct
audio_stream
*
stream
,
audio_format_t
format
)
{
UNUSED
(
stream
);
UNUSED
(
format
);
return
0
;
}
/* must be called with hw device and input stream mutexes locked */
static
int
do_input_standby
(
struct
sunxi_stream_in
*
in
)
{
struct
sunxi_audio_device
*
adev
=
in
->
dev
;
if
(
!
in
->
standby
)
{
if
(
in
->
pcm
){
pcm_close
(
in
->
pcm
);
in
->
pcm
=
NULL
;
}
if
(
in
->
sub_pcm
){
pcm_close
(
in
->
sub_pcm
);
in
->
sub_pcm
=
NULL
;
}
adev
->
active_input
=
0
;
#if USE_INPUT_RESAMPLER
if
(
in
->
resampler
)
{
release_resampler
(
in
->
resampler
);
in
->
resampler
=
NULL
;
}
#endif
in
->
standby
=
1
;
}
return
0
;
}
static
int
in_standby
(
struct
audio_stream
*
stream
)
{
struct
sunxi_stream_in
*
in
=
(
struct
sunxi_stream_in
*
)
stream
;
int
status
;
pthread_mutex_lock
(
&
in
->
dev
->
lock
);
pthread_mutex_lock
(
&
in
->
lock
);
status
=
do_input_standby
(
in
);
pthread_mutex_unlock
(
&
in
->
lock
);
pthread_mutex_unlock
(
&
in
->
dev
->
lock
);
return
status
;
}
static
int
in_dump
(
const
struct
audio_stream
*
stream
,
int
fd
)
{
UNUSED
(
stream
);
UNUSED
(
fd
);
return
0
;
}
static
int
in_set_parameters
(
struct
audio_stream
*
stream
,
const
char
*
kvpairs
)
{
struct
sunxi_stream_in
*
in
=
(
struct
sunxi_stream_in
*
)
stream
;
struct
str_parms
*
parms
;
char
value
[
128
];
int
ret
,
val
=
0
;
parms
=
str_parms_create_str
(
kvpairs
);
ALOGV
(
"in_set_parameters: %s"
,
kvpairs
);
ret
=
str_parms_get_str
(
parms
,
AUDIO_PARAMETER_STREAM_ROUTING
,
value
,
sizeof
(
value
));
if
(
ret
>=
0
)
{
val
=
atoi
(
value
);
in
->
device
=
val
;
ALOGD
(
"in_set_parameters: routing=%d (0x%x)"
,
val
,
val
);
// Log if this is a Bluetooth SCO device
if
(
val
==
AUDIO_DEVICE_IN_BLUETOOTH_SCO_HEADSET
)
{
ALOGD
(
"in_set_parameters: Bluetooth SCO headset input device set"
);
}
}
str_parms_destroy
(
parms
);
return
ret
;
}
static
char
*
in_get_parameters
(
const
struct
audio_stream
*
stream
,
const
char
*
keys
)
{
UNUSED
(
stream
);
UNUSED
(
keys
);
return
strdup
(
""
);
}
static
int
in_set_gain
(
struct
audio_stream_in
*
stream
,
float
gain
)
{
UNUSED
(
stream
);
UNUSED
(
gain
);
return
0
;
}
#if USE_INPUT_RESAMPLER
/* read_frames() reads frames from kernel driver, down samples to capture rate
* if necessary and output the number of frames requested to the buffer specified */
static
ssize_t
read_frames
(
struct
sunxi_stream_in
*
in
,
void
*
buffer
,
ssize_t
frames
)
{
ssize_t
frames_wr
=
0
;
while
(
frames_wr
<
frames
)
{
size_t
frames_rd
=
frames
-
frames_wr
;
if
(
in
->
resampler
!=
NULL
)
{
in
->
resampler
->
resample_from_provider
(
in
->
resampler
,
(
int16_t
*
)((
char
*
)
buffer
+
frames_wr
*
audio_stream_in_frame_size
(
&
in
->
stream
)),
&
frames_rd
);
}
else
{
struct
resampler_buffer
buf
=
{
{
.
raw
=
NULL
,
},
.
frame_count
=
frames_rd
,
};
get_next_buffer
(
&
in
->
buf_provider
,
&
buf
);
if
(
buf
.
raw
!=
NULL
)
{
memcpy
((
char
*
)
buffer
+
frames_wr
*
audio_stream_in_frame_size
(
&
in
->
stream
),
buf
.
raw
,
buf
.
frame_count
*
audio_stream_in_frame_size
(
&
in
->
stream
));
frames_rd
=
buf
.
frame_count
;
}
release_buffer
(
&
in
->
buf_provider
,
&
buf
);
}
/* in->read_status is updated by getNextBuffer() also called by
* in->resampler->resample_from_provider() */
if
(
in
->
read_status
!=
0
)
return
in
->
read_status
;
frames_wr
+=
frames_rd
;
}
return
frames_wr
;
}
#endif
static
ssize_t
in_read
(
struct
audio_stream_in
*
stream
,
void
*
buffer
,
size_t
bytes
)
{
int
ret
=
0
;
struct
sunxi_stream_in
*
in
=
(
struct
sunxi_stream_in
*
)
stream
;
struct
sunxi_audio_device
*
adev
=
in
->
dev
;
size_t
frames_rq
=
0
;
if
(
adev
->
mode
==
AUDIO_MODE_IN_CALL
)
{
#if call_button_voice
if
(
in
->
device
!=
AUDIO_DEVICE_IN_BLUETOOTH_SCO_HEADSET
&&
in
->
device
!=
AUDIO_DEVICE_IN_BUILTIN_MIC
)
{
ALOGD
(
"in call mode, not BT SCO or builtin mic, skip in_read (device=0x%x)"
,
in
->
device
);
usleep
(
10000
);
return
1
;
}
if
(
in
->
device
==
AUDIO_DEVICE_IN_BLUETOOTH_SCO_HEADSET
)
{
ALOGD
(
"Bluetooth SCO call mode, allow in_read (device=0x%x)"
,
in
->
device
);
}
else
if
(
in
->
device
==
AUDIO_DEVICE_IN_BUILTIN_MIC
)
{
// ALOGD("Builtin mic call mode, allow in_read (device=0x%x)", in->device);
}
else
{
ALOGD
(
"Bluetooth SCO call mode, allow in_read (device=0x%x)"
,
in
->
device
);
}
#else
ALOGD
(
"in call mode, in_read, return ;"
);
usleep
(
10000
);
return
1
;
#endif
}
pthread_mutex_lock
(
&
adev
->
lock
);
pthread_mutex_lock
(
&
in
->
lock
);
if
(
in
->
standby
)
{
ret
=
start_input_stream
(
in
);
if
(
ret
==
0
)
in
->
standby
=
0
;
}
if
(
ret
<
0
)
goto
exit
;
/* place after start_input_stream, because start_input_stream() change frame size */
frames_rq
=
bytes
/
audio_stream_in_frame_size
(
stream
);
#if USE_INPUT_RESAMPLER
if
(
in
->
resampler
!=
NULL
)
{
ret
=
read_frames
(
in
,
buffer
,
frames_rq
);
}
else
#endif
{
ret
=
pcm_read
(
in
->
pcm
,
buffer
,
bytes
);
}
if
(
ret
>
0
)
ret
=
0
;
if
(
ret
==
0
&&
adev
->
mic_mute
)
memset
(
buffer
,
0
,
bytes
);
exit:
pthread_mutex_unlock
(
&
in
->
lock
);
pthread_mutex_unlock
(
&
adev
->
lock
);
if
(
ret
<
0
)
usleep
(
bytes
*
1000000
/
audio_stream_in_frame_size
(
stream
)
/
in_get_sample_rate
(
&
stream
->
common
));
return
bytes
;
}
static
uint32_t
in_get_input_frames_lost
(
struct
audio_stream_in
*
stream
)
{
UNUSED
(
stream
);
return
0
;
}
static
int
in_add_audio_effect
(
const
struct
audio_stream
*
stream
,
effect_handle_t
effect
)
{
UNUSED
(
stream
);
UNUSED
(
effect
);
return
0
;
}
static
int
in_remove_audio_effect
(
const
struct
audio_stream
*
stream
,
effect_handle_t
effect
)
{
UNUSED
(
stream
);
UNUSED
(
effect
);
return
0
;
}
#if ENABLE_SUB_PCM_DEVICE
static
int
set_sub_pcm_output_status
(
struct
sunxi_stream_out
*
out
,
bool
open
)
{
if
(
!
out
){
ALOGE
(
"output device is not inited"
);
return
-
ENOMEM
;
}
int
card
;
struct
sunxi_audio_device
*
adev
=
out
->
dev
;
for
(
card
=
0
;
card
<
MAX_AUDIO_DEVICES
;
card
++
){
if
(
!
strcmp
(
adev
->
dev_manager
[
card
].
name
,
SUB_PCM_DEVICE
)){
if
(
open
){
out
->
multi_config
[
card
]
=
pcm_config_out
;
out
->
multi_config
[
card
].
start_threshold
=
DEFAULT_OUTPUT_PERIOD_SIZE
*
2
;
out
->
sub_pcm
[
card
]
=
pcm_open
(
card
,
0
,
PCM_OUT
,
&
out
->
multi_config
[
card
]);
if
(
!
pcm_is_ready
(
out
->
sub_pcm
[
card
]))
{
ALOGE
(
"cannot open pcm driver: %s"
,
pcm_get_error
(
out
->
sub_pcm
[
card
]));
pcm_close
(
out
->
sub_pcm
[
card
]);
out
->
sub_pcm
[
card
]
=
NULL
;
return
-
ENOMEM
;
}
pcm_start
(
out
->
sub_pcm
[
card
]);
}
else
{
if
(
out
->
sub_pcm
[
card
]){
ALOGD
(
"close sub pcm %s"
,
SUB_PCM_DEVICE
);
pcm_close
(
out
->
sub_pcm
[
card
]);
out
->
sub_pcm
[
card
]
=
NULL
;
}
}
break
;
}
}
return
0
;
}
#endif
static
int
adev_open_output_stream
(
struct
audio_hw_device
*
dev
,
audio_io_handle_t
handle
,
audio_devices_t
devices
,
audio_output_flags_t
flags
,
struct
audio_config
*
config
,
struct
audio_stream_out
**
stream_out
,
const
char
*
address
)
{
struct
sunxi_audio_device
*
ladev
=
(
struct
sunxi_audio_device
*
)
dev
;
struct
sunxi_stream_out
*
out
;
UNUSED
(
handle
);
// UNUSED(devices);
UNUSED
(
address
);
ALOGV
(
"adev_open_output_stream, flags: %x"
,
flags
);
out
=
(
struct
sunxi_stream_out
*
)
calloc
(
1
,
sizeof
(
struct
sunxi_stream_out
));
if
(
!
out
)
return
-
ENOMEM
;
out
->
buffer
=
malloc
(
RESAMPLER_BUFFER_SIZE
);
/* todo: allow for reallocing */
out
->
stream
.
common
.
get_sample_rate
=
out_get_sample_rate
;
out
->
stream
.
common
.
set_sample_rate
=
out_set_sample_rate
;
out
->
stream
.
common
.
get_buffer_size
=
out_get_buffer_size
;
out
->
stream
.
common
.
get_channels
=
out_get_channels
;
out
->
stream
.
common
.
get_format
=
out_get_format
;
out
->
stream
.
common
.
set_format
=
out_set_format
;
out
->
stream
.
common
.
standby
=
out_standby
;
out
->
stream
.
common
.
dump
=
out_dump
;
out
->
stream
.
common
.
set_parameters
=
out_set_parameters
;
out
->
stream
.
common
.
get_parameters
=
out_get_parameters
;
out
->
stream
.
common
.
add_audio_effect
=
out_add_audio_effect
;
out
->
stream
.
common
.
remove_audio_effect
=
out_remove_audio_effect
;
out
->
stream
.
get_latency
=
out_get_latency
;
out
->
stream
.
set_volume
=
out_set_volume
;
out
->
stream
.
write
=
out_write
;
out
->
stream
.
get_render_position
=
out_get_render_position
;
out
->
stream
.
get_next_write_timestamp
=
out_get_next_write_timestamp
;
out
->
dev
=
ladev
;
out
->
standby
=
1
;
out
->
device
=
devices
;
ALOGV
(
"+++++++++++++++ adev_open_output_stream: req_sample_rate: %d, fmt: %x, channel_count: %d"
,
config
->
sample_rate
,
config
->
format
,
config
->
channel_mask
);
out
->
config
=
pcm_config_out
;
config
->
format
=
out_get_format
(
&
out
->
stream
.
common
);
config
->
channel_mask
=
out_get_channels
(
&
out
->
stream
.
common
);
config
->
sample_rate
=
out_get_sample_rate
(
&
out
->
stream
.
common
);
out
->
flags
=
flags
;
*
stream_out
=
&
out
->
stream
;
ladev
->
active_output
=
out
;
#if ENABLE_SUB_PCM_DEVICE
set_sub_pcm_output_status
(
out
,
true
);
#endif
select_output_device
(
ladev
);
return
0
;
}
static
void
adev_close_output_stream
(
struct
audio_hw_device
*
dev
,
struct
audio_stream_out
*
stream
)
{
struct
sunxi_stream_out
*
out
=
(
struct
sunxi_stream_out
*
)
stream
;
struct
sunxi_audio_device
*
adev
=
out
->
dev
;
UNUSED
(
dev
);
if
(
adev
->
mode
==
AUDIO_MODE_IN_CALL
)
{
ALOGW
(
"mode in call, do not adev_close_output_stream"
);
return
;
}
out_standby
(
&
stream
->
common
);
if
(
out
->
buffer
)
free
(
out
->
buffer
);
free
(
stream
);
}
static
int
adev_set_parameters
(
struct
audio_hw_device
*
dev
,
const
char
*
kvpairs
)
{
struct
sunxi_audio_device
*
adev
=
(
struct
sunxi_audio_device
*
)
dev
;
struct
str_parms
*
parms
;
char
value
[
32
];
int
ret
;
char
value2
[
32
];
int
val
=
0
;
int8_t
enable
;
ALOGV
(
"adev_set_parameters, %s"
,
kvpairs
);
parms
=
str_parms_create_str
(
kvpairs
);
ret
=
str_parms_get_str
(
parms
,
AUDIO_HAL_PARAM_OUTPUT_DEVICES
,
value
,
sizeof
(
value
));
if
(
ret
>=
0
)
{
ret
=
str_parms_get_str
(
parms
,
AUDIO_HAL_PARAM_OUTPUT_DEVICES_IS_ACTIVE
,
value2
,
sizeof
(
value2
));
if
(
ret
>=
0
){
val
=
atoi
(
value2
);
if
(
val
){
if
(
strcmp
(
value
,
AUDIO_HAL_PARAM_OUTPUT_DEVICES_AUDIO_CODEC
)
==
0
){
adev
->
output_active_cards
=
AUDIO_CARD_CODEC
;
}
else
if
(
strcmp
(
value
,
AUDIO_HAL_PARAM_OUTPUT_DEVICES_SNDBT936B
)
==
0
)
{
adev
->
output_active_cards
=
AUDIO_CARD_SNDBT936B
;
}
else
{
ALOGE
(
"known output device %s"
,
value
);
}
}
else
{
if
(
strcmp
(
value
,
AUDIO_HAL_PARAM_OUTPUT_DEVICES_AUDIO_CODEC
)
==
0
){
adev
->
output_active_cards
&=
~
AUDIO_CARD_CODEC
;
}
else
if
(
strcmp
(
value
,
AUDIO_HAL_PARAM_OUTPUT_DEVICES_SNDBT936B
)
==
0
)
{
adev
->
output_active_cards
&=
~
AUDIO_CARD_SNDBT936B
;
}
else
{
ALOGE
(
"known output device %s"
,
value
);
}
}
}
// 确保至少有一个输入设备激活
if
(
adev
->
output_active_cards
==
0
){
adev
->
output_active_cards
=
AUDIO_CARD_CODEC
;
}
pthread_mutex_lock
(
&
adev
->
lock
);
set_audio_devices_active
(
adev
,
AUDIO_OUT
);
if
(
adev
->
active_output
)
{
pthread_mutex_lock
(
&
adev
->
active_output
->
lock
);
do_output_standby
(
adev
->
active_output
);
pthread_mutex_unlock
(
&
adev
->
active_output
->
lock
);
}
pthread_mutex_unlock
(
&
adev
->
lock
);
}
ret
=
str_parms_get_str
(
parms
,
AUDIO_HAL_PARAM_INPUT_DEVICES
,
value
,
sizeof
(
value
));
if
(
ret
>=
0
)
{
ret
=
str_parms_get_str
(
parms
,
AUDIO_HAL_PARAM_INPUT_DEVICES_IS_ACTIVE
,
value2
,
sizeof
(
value2
));
if
(
ret
>=
0
){
val
=
atoi
(
value2
);
if
(
val
){
// 输入设备是互斥的,一次只能激活一个
if
(
strcmp
(
value
,
AUDIO_HAL_PARAM_INPUT_DEVICES_SNDBT936B
)
==
0
)
{
adev
->
input_active_cards
=
AUDIO_CARD_SNDBT936B
;
}
else
if
(
strcmp
(
value
,
AUDIO_HAL_PARAM_INPUT_DEVICES_SNDES7210
)
==
0
)
{
adev
->
input_active_cards
=
AUDIO_CARD_SNDES7210
;
}
else
{
ALOGE
(
"unknown input device %s"
,
value
);
}
}
else
{
if
(
strcmp
(
value
,
AUDIO_HAL_PARAM_INPUT_DEVICES_SNDBT936B
)
==
0
)
{
if
(
adev
->
input_active_cards
==
AUDIO_CARD_SNDBT936B
)
{
adev
->
input_active_cards
&=
~
AUDIO_CARD_SNDBT936B
;
}
}
else
if
(
strcmp
(
value
,
AUDIO_HAL_PARAM_INPUT_DEVICES_SNDES7210
)
==
0
)
{
if
(
adev
->
input_active_cards
==
AUDIO_CARD_SNDES7210
)
{
adev
->
input_active_cards
&=
~
AUDIO_CARD_SNDES7210
;
}
}
else
{
ALOGE
(
"unknown input device %s"
,
value
);
}
}
// 确保至少有一个输入设备激活
if
(
adev
->
input_active_cards
==
0
){
adev
->
input_active_cards
=
AUDIO_CARD_SNDES7210
;
}
}
pthread_mutex_lock
(
&
adev
->
lock
);
set_audio_devices_active
(
adev
,
AUDIO_IN
);
if
(
adev
->
active_input
)
{
pthread_mutex_lock
(
&
adev
->
active_input
->
lock
);
do_input_standby
(
adev
->
active_input
);
pthread_mutex_unlock
(
&
adev
->
active_input
->
lock
);
}
pthread_mutex_unlock
(
&
adev
->
lock
);
}
ret
=
str_parms_get_str
(
parms
,
AUDIO_PARAMETER_KEY_HFP_ENABLE
,
value
,
sizeof
(
value
));
if
(
ret
>=
0
)
{
enable
=
atoi
(
value
);
snprintf
(
value
,
sizeof
(
value
),
"/system/bin/bt936b_route.sh %d"
,
enable
+
1
);
ALOGD
(
"hfp_enbale cmd: [%s]
\n
"
,
value
);
// int sys_ret = system(value);
// ALOGD("change 936b audroute by [%s], sys_ret: %d\n", value, sys_ret);
}
ret
=
str_parms_get_str
(
parms
,
AUDIO_HAL_PARAM_TYW_SWITCH
,
value
,
sizeof
(
value
));
if
(
ret
>=
0
)
{
// 耳机模式
if
(
0
==
strcmp
(
value
,
AUDIO_HAL_PARAM_TYW_SWITCH_HEADSET
))
{
adev
->
input_active_cards
=
AUDIO_CARD_SNDBT936B
;
adev
->
output_active_cards
=
AUDIO_CARD_SNDBT936B
;
}
// 扬声器模式
else
if
(
0
==
strcmp
(
value
,
AUDIO_HAL_PARAM_TYW_SWITCH_SPEAKER
))
{
adev
->
input_active_cards
=
AUDIO_CARD_SNDES7210
;
adev
->
output_active_cards
=
AUDIO_CARD_CODEC
;
}
pthread_mutex_lock
(
&
adev
->
lock
);
set_audio_devices_active
(
adev
,
AUDIO_IN
);
set_audio_devices_active
(
adev
,
AUDIO_OUT
);
force_all_standby
(
adev
);
pthread_mutex_unlock
(
&
adev
->
lock
);
}
ret
=
str_parms_get_str
(
parms
,
AUDIO_HAL_PARAM_ROUTE
,
value
,
sizeof
(
value
));
if
(
ret
>=
0
)
{
ret
=
str_parms_get_str
(
parms
,
AUDIO_HAL_PARAM_ROUTE_VALUE
,
value2
,
sizeof
(
value2
));
if
(
ret
>=
0
){
val
=
atoi
(
value2
);
ALOGD
(
"route value = %d"
,
val
);
}
if
(
strcmp
(
value
,
AUDIO_HAL_PARAM_ROUTE_LINEOUT
)
==
0
){
set_audio_path
(
adev
,
OUT_DEVICE_LINEOUT
,
val
);
}
else
if
(
strcmp
(
value
,
AUDIO_HAL_PARAM_ROUTE_LINEIN_LINEOUT
)
==
0
){
set_audio_path
(
adev
,
AA_LINEIN_LINEOUT
,
val
);
}
else
if
(
strcmp
(
value
,
AUDIO_HAL_PARAM_ROUTE_FMIN_LINEOUT
)
==
0
){
set_audio_path
(
adev
,
AA_FMIN_LINEOUT
,
val
);
}
else
if
(
strcmp
(
value
,
AUDIO_HAL_PARAM_ROUTE_HDMI_OUT
)
==
0
){
set_audio_path
(
adev
,
OUT_DEVICE_HDMI
,
val
);
}
else
if
(
strcmp
(
value
,
AUDIO_HAL_PARAM_ROUTE_AC107_IN
)
==
0
){
set_audio_path
(
adev
,
IN_DEVICE_AC107
,
val
);
}
else
if
(
strcmp
(
value
,
AUDIO_HAL_PARAM_ROUTE_I2S2_OUT
)
==
0
){
set_audio_path
(
adev
,
OUT_DEVICE_I2S2
,
val
);
}
else
if
(
strcmp
(
value
,
AUDIO_HAL_PARAM_ROUTE_I2S2_IN
)
==
0
){
set_audio_path
(
adev
,
IN_DEVICE_I2S2
,
val
);
}
else
if
(
strcmp
(
value
,
AUDIO_HAL_PARAM_ROUTE_I2S3_OUT
)
==
0
){
set_audio_path
(
adev
,
OUT_DEVICE_I2S3
,
val
);
}
else
if
(
strcmp
(
value
,
AUDIO_HAL_PARAM_ROUTE_I2S3_IN
)
==
0
){
set_audio_path
(
adev
,
IN_DEVICE_I2S3
,
val
);
}
else
if
(
strcmp
(
value
,
AUDIO_HAL_PARAM_ROUTE_SNDES7210_IN
)
==
0
)
{
set_audio_path
(
adev
,
IN_DEVICE_SNDES7210
,
val
);
}
else
if
(
strcmp
(
value
,
AUDIO_HAL_PARAM_ROUTE_SNDBT936B_OUT
)
==
0
)
{
set_audio_path
(
adev
,
OUT_DEVICE_SNDBT936B
,
val
);
}
else
if
(
strcmp
(
value
,
AUDIO_HAL_PARAM_ROUTE_SNDBT936B_IN
)
==
0
){
set_audio_path
(
adev
,
IN_DEVICE_SNDBT936B
,
val
);
}
else
if
(
strcmp
(
value
,
AUDIO_HAL_PARAM_ROUTE_SPDIF
)
==
0
){
set_audio_path
(
adev
,
VOL_LINEOUT
,
val
);
}
else
if
(
strcmp
(
value
,
AUDIO_HAL_PARAM_VOL_LINEOUT
)
==
0
){
set_mixer_value
(
adev
->
mixer_ac107
,
route_configs
[
VOL_LINEOUT
].
open
,
val
);
}
else
if
(
strcmp
(
value
,
AUDIO_HAL_PARAM_VOL_LINEIN
)
==
0
){
set_mixer_value
(
adev
->
mixer_ac107
,
route_configs
[
VOL_LINEIN_OMIX
].
open
,
val
);
}
else
if
(
strcmp
(
value
,
AUDIO_HAL_PARAM_VOL_FMIN
)
==
0
){
set_mixer_value
(
adev
->
mixer_ac107
,
route_configs
[
VOL_FMIN_OMIX
].
open
,
val
);
}
else
if
(
strcmp
(
value
,
AUDIO_HAL_PARAM_VOL_AC107_C1_PGA
)
==
0
){
set_mixer_value
(
adev
->
mixer_ac107
,
route_configs
[
VOL_AC107_C1_PGA
].
open
,
val
);
}
else
if
(
strcmp
(
value
,
AUDIO_HAL_PARAM_VOL_AC107_C2_PGA
)
==
0
){
set_mixer_value
(
adev
->
mixer_ac107
,
route_configs
[
VOL_AC107_C2_PGA
].
open
,
val
);
}
else
if
(
strcmp
(
value
,
AUDIO_HAL_PARAM_VOL_AC107_C1_DIGITAL
)
==
0
){
set_mixer_value
(
adev
->
mixer_ac107
,
route_configs
[
VOL_AC107_C1_DIGITAL
].
open
,
val
);
}
else
if
(
strcmp
(
value
,
AUDIO_HAL_PARAM_VOL_AC107_C2_DIGITAL
)
==
0
){
set_mixer_value
(
adev
->
mixer_ac107
,
route_configs
[
VOL_AC107_C2_DIGITAL
].
open
,
val
);
}
else
if
(
strcmp
(
value
,
AUDIO_HAL_PARAM_VOL_TD100_MIC1
)
==
0
){
adev
->
vol_td100_mic1_val
=
val
;
set_mixer_value
(
adev
->
mixer_td100
,
route_configs
[
VOL_TD100_MIC1
].
open
,
val
);
}
else
if
(
strcmp
(
value
,
AUDIO_HAL_PARAM_VOL_TD100_MIC2
)
==
0
){
adev
->
vol_td100_mic2_val
=
val
;
set_mixer_value
(
adev
->
mixer_td100
,
route_configs
[
VOL_TD100_MIC2
].
open
,
val
);
}
else
if
(
strcmp
(
value
,
AUDIO_HAL_PARAM_VOL_TD100_MIC3
)
==
0
){
adev
->
vol_td100_mic3_val
=
val
;
set_mixer_value
(
adev
->
mixer_td100
,
route_configs
[
VOL_TD100_MIC3
].
open
,
val
);
}
else
if
(
strcmp
(
value
,
AUDIO_HAL_PARAM_VOL_TD100_LINEIN
)
==
0
){
adev
->
vol_td100_linein_val
=
val
;
set_mixer_value
(
adev
->
mixer_td100
,
route_configs
[
VOL_TD100_LINEIN
].
open
,
val
);
}
else
if
(
strcmp
(
value
,
AUDIO_HAL_PARAM_DVOL_TD100_ADC1
)
==
0
){
adev
->
dvol_td100_adc1_val
=
val
;
set_mixer_value
(
adev
->
mixer_td100
,
route_configs
[
DVOL_TD100_ADC1
].
open
,
val
);
}
else
if
(
strcmp
(
value
,
AUDIO_HAL_PARAM_DVOL_TD100_ADC2
)
==
0
){
adev
->
dvol_td100_adc2_val
=
val
;
set_mixer_value
(
adev
->
mixer_td100
,
route_configs
[
DVOL_TD100_ADC2
].
open
,
val
);
}
else
if
(
strcmp
(
value
,
AUDIO_HAL_PARAM_CH1_TD100_SELECT
)
==
0
){
adev
->
ch1_td100_select_val
=
val
;
set_mixer_value
(
adev
->
mixer_td100
,
route_configs
[
CH1_TD100_SELECT
].
open
,
val
);
}
else
if
(
strcmp
(
value
,
AUDIO_HAL_PARAM_CH2_TD100_SELECT
)
==
0
){
adev
->
ch2_td100_select_val
=
val
;
set_mixer_value
(
adev
->
mixer_td100
,
route_configs
[
CH2_TD100_SELECT
].
open
,
val
);
}
}
ret
=
str_parms_get_str
(
parms
,
AUDIO_PARAMETER_KEY_SCREEN_STATE
,
value
,
sizeof
(
value
));
if
(
ret
>=
0
)
{
pthread_mutex_lock
(
&
adev
->
lock
);
if
(
strcmp
(
value
,
AUDIO_PARAMETER_VALUE_ON
)
==
0
)
{
adev
->
stanby
=
true
;
#if ENABLE_SUB_PCM_DEVICE
set_sub_pcm_output_status
(
adev
->
active_output
,
true
);
#endif
}
else
if
(
strcmp
(
value
,
AUDIO_PARAMETER_VALUE_OFF
)
==
0
)
{
adev
->
stanby
=
false
;
#if ENABLE_SUB_PCM_DEVICE
set_sub_pcm_output_status
(
adev
->
active_output
,
false
);
#endif
}
pthread_mutex_unlock
(
&
adev
->
lock
);
}
ret
=
str_parms_get_str
(
parms
,
AUDIO_PARAMETER_DEVICE_CONNECT
,
value
,
sizeof
(
value
));
if
(
ret
>=
0
)
{
int
val
=
atoi
(
value
);
pthread_mutex_lock
(
&
adev
->
lock
);
if
(
adev
->
output_active_cards
&
AUDIO_CARD_AUTO_DEC
){
if
(
val
==
AUDIO_DEVICE_OUT_AUX_DIGITAL
){
adev
->
output_active_cards
&=
~
AUDIO_CARD_CODEC
;
adev
->
output_active_cards
|=
AUDIO_CARD_HDMI
;
}
else
if
(
val
==
AUDIO_DEVICE_OUT_DGTL_DOCK_HEADSET
){
adev
->
output_active_cards
|=
AUDIO_CARD_SPDIF
;
}
}
set_audio_devices_active
(
adev
,
AUDIO_OUT
);
pthread_mutex_unlock
(
&
adev
->
lock
);
}
ret
=
str_parms_get_str
(
parms
,
AUDIO_PARAMETER_DEVICE_DISCONNECT
,
value
,
sizeof
(
value
));
if
(
ret
>=
0
)
{
int
val
=
atoi
(
value
);
pthread_mutex_lock
(
&
adev
->
lock
);
if
(
adev
->
output_active_cards
&
AUDIO_CARD_AUTO_DEC
){
if
(
val
==
AUDIO_DEVICE_OUT_AUX_DIGITAL
){
adev
->
output_active_cards
&=
~
AUDIO_CARD_HDMI
;
adev
->
output_active_cards
|=
AUDIO_CARD_CODEC
;
}
else
if
(
val
==
AUDIO_DEVICE_OUT_DGTL_DOCK_HEADSET
){
adev
->
output_active_cards
&=
~
AUDIO_CARD_SPDIF
;
}
}
set_audio_devices_active
(
adev
,
AUDIO_OUT
);
pthread_mutex_unlock
(
&
adev
->
lock
);
}
ret
=
str_parms_get_str
(
parms
,
"mediasw.sft.rawdata"
,
value
,
sizeof
(
value
));
if
(
ret
>=
0
)
{
property_set
(
PROP_RAWDATA_KEY
,
value
);
}
str_parms_destroy
(
parms
);
return
ret
;
}
static
char
*
adev_get_parameters
(
const
struct
audio_hw_device
*
dev
,
const
char
*
keys
)
{
struct
sunxi_audio_device
*
adev
=
(
struct
sunxi_audio_device
*
)
dev
;
ALOGV
(
"adev_get_parameters, %s"
,
keys
);
char
devices
[
128
];
memset
(
devices
,
0
,
sizeof
(
devices
));
if
(
0
==
strcmp
(
keys
,
AUDIO_HAL_PARAM_TYW_SWITCH
))
{
pthread_mutex_lock
(
&
adev
->
lock
);
strcpy
(
devices
,
AUDIO_HAL_PARAM_TYW_SWITCH
);
strcat
(
devices
,
"="
);
if
((
adev
->
output_active_cards
&
AUDIO_CARD_CODEC
)
&&
(
adev
->
input_active_cards
&
AUDIO_CARD_SNDES7210
))
{
strcat
(
devices
,
AUDIO_HAL_PARAM_TYW_SWITCH_SPEAKER
);
}
else
if
((
adev
->
output_active_cards
&
AUDIO_CARD_SNDBT936B
)
&&
(
adev
->
input_active_cards
&
AUDIO_CARD_SNDBT936B
))
{
strcat
(
devices
,
AUDIO_HAL_PARAM_TYW_SWITCH_HEADSET
);
}
else
{
strcat
(
devices
,
"invalid state"
);
}
pthread_mutex_unlock
(
&
adev
->
lock
);
ALOGD
(
"get_parameters for '%s', returning: '%s'"
,
keys
,
devices
);
return
strdup
(
devices
);
}
if
(
!
strcmp
(
keys
,
AUDIO_HAL_PARAM_OUTPUT_DEVICES
)){
strcpy
(
devices
,
AUDIO_HAL_PARAM_OUTPUT_DEVICES
);
strcat
(
devices
,
" :"
);
if
(
adev
->
output_active_cards
&
AUDIO_CARD_CODEC
){
strcat
(
devices
,
" "
);
strcat
(
devices
,
AUDIO_HAL_PARAM_OUTPUT_DEVICES_AUDIO_CODEC
);
}
if
(
adev
->
output_active_cards
&
AUDIO_CARD_HDMI
){
strcat
(
devices
,
" "
);
strcat
(
devices
,
AUDIO_HAL_PARAM_OUTPUT_DEVICES_HDMI
);
}
if
(
adev
->
output_active_cards
&
AUDIO_CARD_SPDIF
){
strcat
(
devices
,
" "
);
strcat
(
devices
,
AUDIO_HAL_PARAM_OUTPUT_DEVICES_SPDIF
);
}
if
(
adev
->
output_active_cards
&
AUDIO_CARD_SNDBT936B
){
strcat
(
devices
,
" "
);
strcat
(
devices
,
AUDIO_HAL_PARAM_OUTPUT_DEVICES_SNDBT936B
);
}
ALOGD
(
"%s"
,
devices
);
return
strdup
(
devices
);
}
if
(
!
strcmp
(
keys
,
AUDIO_PARAMETER_STREAM_ROUTING
))
{
char
prop_value
[
512
];
int
ret
=
property_get
(
"audio.routing"
,
prop_value
,
""
);
if
(
ret
>
0
)
{
return
strdup
(
prop_value
);
}
}
if
(
!
strcmp
(
keys
,
AUDIO_PARAMETER_DEVICES_IN
))
return
strdup
(
get_audio_devices
(
adev
,
AUDIO_IN
));
if
(
!
strcmp
(
keys
,
AUDIO_PARAMETER_DEVICES_OUT
))
return
strdup
(
get_audio_devices
(
adev
,
AUDIO_OUT
));
if
(
!
strcmp
(
keys
,
AUDIO_PARAMETER_DEVICES_IN_ACTIVE
))
if
(
!
get_audio_devices_active
(
adev
,
AUDIO_IN
,
devices
))
return
strdup
(
devices
);
if
(
!
strcmp
(
keys
,
AUDIO_PARAMETER_DEVICES_OUT_ACTIVE
))
if
(
!
get_audio_devices_active
(
adev
,
AUDIO_OUT
,
devices
))
return
strdup
(
devices
);
return
strdup
(
""
);
}
static
int
adev_init_check
(
const
struct
audio_hw_device
*
dev
)
{
UNUSED
(
dev
);
return
0
;
}
static
int
adev_set_voice_volume
(
struct
audio_hw_device
*
dev
,
float
volume
)
{
UNUSED
(
dev
);
ALOGV
(
"adev_set_voice_volume, volume: %f"
,
volume
);
return
0
;
}
static
int
adev_set_master_volume
(
struct
audio_hw_device
*
dev
,
float
volume
)
{
UNUSED
(
dev
);
UNUSED
(
volume
);
F_LOG
;
return
-
ENOSYS
;
}
static
int
adev_get_master_volume
(
struct
audio_hw_device
*
dev
,
float
*
volume
)
{
UNUSED
(
dev
);
UNUSED
(
volume
);
F_LOG
;
return
-
ENOSYS
;
}
static
int
adev_set_mode
(
struct
audio_hw_device
*
dev
,
audio_mode_t
mode
)
{
struct
sunxi_audio_device
*
adev
=
(
struct
sunxi_audio_device
*
)
dev
;
pthread_mutex_lock
(
&
adev
->
lock
);
if
(
adev
->
mode
!=
mode
)
{
adev
->
mode
=
mode
;
select_mode
(
adev
);
}
pthread_mutex_unlock
(
&
adev
->
lock
);
return
0
;
}
static
int
adev_set_mic_mute
(
struct
audio_hw_device
*
dev
,
bool
state
)
{
struct
sunxi_audio_device
*
adev
=
(
struct
sunxi_audio_device
*
)
dev
;
adev
->
mic_mute
=
state
;
return
0
;
}
static
int
adev_get_mic_mute
(
const
struct
audio_hw_device
*
dev
,
bool
*
state
)
{
struct
sunxi_audio_device
*
adev
=
(
struct
sunxi_audio_device
*
)
dev
;
*
state
=
adev
->
mic_mute
;
return
0
;
}
static
size_t
adev_get_input_buffer_size
(
const
struct
audio_hw_device
*
dev
,
const
struct
audio_config
*
config
)
{
UNUSED
(
dev
);
int
channel_count
=
popcount
(
config
->
channel_mask
);
if
(
check_input_parameters
(
config
->
sample_rate
,
config
->
format
,
channel_count
)
!=
0
)
return
0
;
return
get_input_buffer_size
(
config
->
sample_rate
,
config
->
format
,
channel_count
);
}
static
int
adev_open_input_stream
(
struct
audio_hw_device
*
dev
,
audio_io_handle_t
handle
,
audio_devices_t
devices
,
struct
audio_config
*
config
,
struct
audio_stream_in
**
stream_in
,
audio_input_flags_t
flags
,
const
char
*
address
,
audio_source_t
source
)
{
UNUSED
(
handle
);
UNUSED
(
flags
);
UNUSED
(
address
);
UNUSED
(
source
);
// UNUSED(devices);
struct
sunxi_audio_device
*
ladev
=
(
struct
sunxi_audio_device
*
)
dev
;
struct
sunxi_stream_in
*
in
;
int
ret
;
int
channel_count
=
popcount
(
config
->
channel_mask
);
*
stream_in
=
NULL
;
if
(
check_input_parameters
(
config
->
sample_rate
,
config
->
format
,
channel_count
)
!=
0
)
return
-
EINVAL
;
in
=
(
struct
sunxi_stream_in
*
)
calloc
(
1
,
sizeof
(
struct
sunxi_stream_in
));
if
(
!
in
)
return
-
ENOMEM
;
in
->
stream
.
common
.
get_sample_rate
=
in_get_sample_rate
;
in
->
stream
.
common
.
set_sample_rate
=
in_set_sample_rate
;
in
->
stream
.
common
.
get_buffer_size
=
in_get_buffer_size
;
in
->
stream
.
common
.
get_channels
=
in_get_channels
;
in
->
stream
.
common
.
get_format
=
in_get_format
;
in
->
stream
.
common
.
set_format
=
in_set_format
;
in
->
stream
.
common
.
standby
=
in_standby
;
in
->
stream
.
common
.
dump
=
in_dump
;
in
->
stream
.
common
.
set_parameters
=
in_set_parameters
;
in
->
stream
.
common
.
get_parameters
=
in_get_parameters
;
in
->
stream
.
common
.
add_audio_effect
=
in_add_audio_effect
;
in
->
stream
.
common
.
remove_audio_effect
=
in_remove_audio_effect
;
in
->
stream
.
set_gain
=
in_set_gain
;
in
->
stream
.
read
=
in_read
;
in
->
stream
.
get_input_frames_lost
=
in_get_input_frames_lost
;
in
->
device
=
devices
;
// default config
memcpy
(
&
in
->
config
,
&
pcm_config_in
,
sizeof
(
pcm_config_in
));
#if USE_INPUT_RESAMPLER
in
->
requested_rate
=
config
->
sample_rate
;
in
->
config
.
channels
=
channel_count
;
#else
in
->
requested_rate
=
DEFAULT_SAMPLING_RATE
;
in
->
config
.
channels
=
DEFAULT_CHANNEL_COUNT
;
#endif
ALOGV
(
"to malloc in-buffer: period_size: %d, frame_size: %zu"
,
in
->
config
.
period_size
,
audio_stream_in_frame_size
(
&
in
->
stream
));
in
->
buffer
=
malloc
(
in
->
config
.
period_size
*
audio_stream_in_frame_size
(
&
in
->
stream
)
*
8
);
if
(
!
in
->
buffer
)
{
ret
=
-
ENOMEM
;
goto
err
;
}
in
->
dev
=
ladev
;
in
->
standby
=
1
;
*
stream_in
=
&
in
->
stream
;
select_input_device
(
ladev
);
return
0
;
err:
#if USE_INPUT_RESAMPLER
if
(
in
->
resampler
)
release_resampler
(
in
->
resampler
);
#endif
free
(
in
);
return
ret
;
}
static
void
adev_close_input_stream
(
struct
audio_hw_device
*
dev
,
struct
audio_stream_in
*
stream
)
{
UNUSED
(
dev
);
struct
sunxi_stream_in
*
in
=
(
struct
sunxi_stream_in
*
)
stream
;
in_standby
(
&
stream
->
common
);
if
(
in
->
buffer
)
{
free
(
in
->
buffer
);
in
->
buffer
=
0
;
}
#if USE_INPUT_RESAMPLER
if
(
in
->
resampler
)
{
release_resampler
(
in
->
resampler
);
}
#endif
free
(
stream
);
ALOGD
(
"adev_close_input_stream set voice record status"
);
return
;
}
static
int
adev_dump
(
const
audio_hw_device_t
*
device
,
int
fd
)
{
UNUSED
(
device
);
UNUSED
(
fd
);
return
0
;
}
static
int
adev_close
(
hw_device_t
*
device
)
{
struct
sunxi_audio_device
*
adev
=
(
struct
sunxi_audio_device
*
)
device
;
// free audio route
if
(
adev
->
ar_ahub
)
{
audio_route_free
(
adev
->
ar_ahub
);
adev
->
ar_ahub
=
NULL
;
}
if
(
adev
->
ar_codec
)
{
audio_route_free
(
adev
->
ar_codec
);
adev
->
ar_codec
=
NULL
;
}
if
(
adev
->
mixer_ac107
)
{
mixer_close
(
adev
->
mixer_ac107
);
adev
->
mixer_ac107
=
NULL
;
}
if
(
adev
->
mixer_td100
)
{
mixer_close
(
adev
->
mixer_td100
);
adev
->
mixer_td100
=
NULL
;
}
free
(
device
);
return
0
;
}
static
int
adev_open
(
const
hw_module_t
*
module
,
const
char
*
name
,
hw_device_t
**
device
)
{
struct
sunxi_audio_device
*
adev
;
int
hdmi_status
;
if
(
strcmp
(
name
,
AUDIO_HARDWARE_INTERFACE
)
!=
0
)
return
-
EINVAL
;
adev
=
calloc
(
1
,
sizeof
(
struct
sunxi_audio_device
));
if
(
!
adev
)
return
-
ENOMEM
;
adev
->
hw_device
.
common
.
tag
=
HARDWARE_DEVICE_TAG
;
adev
->
hw_device
.
common
.
version
=
AUDIO_DEVICE_API_VERSION_2_0
;
adev
->
hw_device
.
common
.
module
=
(
struct
hw_module_t
*
)
module
;
adev
->
hw_device
.
common
.
close
=
adev_close
;
adev
->
hw_device
.
init_check
=
adev_init_check
;
adev
->
hw_device
.
set_voice_volume
=
adev_set_voice_volume
;
adev
->
hw_device
.
set_master_volume
=
adev_set_master_volume
;
adev
->
hw_device
.
get_master_volume
=
adev_get_master_volume
;
adev
->
hw_device
.
set_mode
=
adev_set_mode
;
adev
->
hw_device
.
set_mic_mute
=
adev_set_mic_mute
;
adev
->
hw_device
.
get_mic_mute
=
adev_get_mic_mute
;
adev
->
hw_device
.
set_parameters
=
adev_set_parameters
;
adev
->
hw_device
.
get_parameters
=
adev_get_parameters
;
adev
->
hw_device
.
get_input_buffer_size
=
adev_get_input_buffer_size
;
adev
->
hw_device
.
open_output_stream
=
adev_open_output_stream
;
adev
->
hw_device
.
close_output_stream
=
adev_close_output_stream
;
adev
->
hw_device
.
open_input_stream
=
adev_open_input_stream
;
adev
->
hw_device
.
close_input_stream
=
adev_close_input_stream
;
adev
->
hw_device
.
dump
=
adev_dump
;
adev
->
stanby
=
false
;
adev
->
output_active_cards
=
OUTPUT_ACTIVE_CARDS
;
adev
->
input_active_cards
=
INPUT_ACTIVE_CARDS
;
adev
->
card_ac107
=
adev
->
card_td100
=
adev
->
card_sndes7210
=
adev
->
card_sndbt936b
=
adev
->
card_ahub
=
adev
->
card_codec
=
-
1
;
hdmi_status
=
get_hdmi_status
();
if
(
hdmi_status
<
0
){
ALOGE
(
"get hdmi status error"
);
}
else
if
(
hdmi_status
==
1
){
adev
->
output_active_cards
|=
AUDIO_CARD_HDMI
;
}
init_audio_devices
(
adev
);
init_audio_devices_active
(
adev
);
if
(
adev
->
input_active_cards
==
AUDIO_CARD_AC107
){
if
(
!
adev
->
mixer_ac107
){
free
(
adev
);
ALOGE
(
"Unable to open ac107 mixer, aborting."
);
return
-
EINVAL
;
}
else
{
init_ac107_devices
(
adev
);
}
}
if
(
adev
->
input_active_cards
==
AUDIO_CARD_TD100
){
if
(
!
adev
->
mixer_td100
){
free
(
adev
);
ALOGE
(
"Unable to open td100 mixer, aborting."
);
return
-
EINVAL
;
}
else
{
adev
->
vol_td100_mic1_val
=
5
;
adev
->
vol_td100_mic2_val
=
5
;
adev
->
vol_td100_mic3_val
=
5
;
adev
->
vol_td100_linein_val
=
4
;
adev
->
dvol_td100_adc1_val
=
170
;
adev
->
dvol_td100_adc2_val
=
170
;
adev
->
ch1_td100_select_val
=
0
;
adev
->
ch2_td100_select_val
=
1
;
init_td100_devices
(
adev
);
}
}
if
(
adev
->
input_active_cards
==
AUDIO_CARD_SNDES7210
){
ALOGD
(
"SNDES7210 SPECIAL SOUNDCARD input device initialized"
);
// SNDES7210 CAPTURE SOUNDCARD doesn't need mixer initialization like AC107/TD100
// It uses I2S2 interface through AHUB
}
if
(
adev
->
input_active_cards
==
AUDIO_CARD_SNDBT936B
){
ALOGD
(
"SNDBT936B SOUNDCARD input/output device initialized"
);
// SNDBT936B doesn't need mixer initialization like AC107/TD100
// It uses I2S0 interface through AHUB
}
/* Set the default route before the PCM stream is opened */
pthread_mutex_lock
(
&
adev
->
lock
);
adev
->
mode
=
AUDIO_MODE_NORMAL
;
// init T501 audio input and output path
// set_audio_path(adev, AA_LINEIN_LINEOUT); //default open linein to lineout path
//set_mixer_value(adev->mixer_ac107, route_configs[VOL_AC107_C2_PGA].open, 12);
pthread_mutex_unlock
(
&
adev
->
lock
);
*
device
=
&
adev
->
hw_device
.
common
;
ALOGD
(
"adev_open success ,LINE:%d,FUNC:%s"
,
__LINE__
,
__FUNCTION__
);
return
0
;
}
static
struct
hw_module_methods_t
hal_module_methods
=
{
.
open
=
adev_open
,
};
struct
audio_module
HAL_MODULE_INFO_SYM
=
{
.
common
=
{
.
tag
=
HARDWARE_MODULE_TAG
,
.
module_api_version
=
AUDIO_MODULE_API_VERSION_0_1
,
.
hal_api_version
=
HARDWARE_HAL_API_VERSION
,
.
id
=
AUDIO_HARDWARE_MODULE_ID
,
.
name
=
"sunxi audio HW HAL"
,
.
author
=
"author"
,
.
methods
=
&
hal_module_methods
,
},
};
audio_hw.h
0 → 100644
View file @
cfc02459
/*
* Copyright (C) 2011 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#ifndef __AUDIO_HW__
#define __AUDIO_HW__
#define F_LOG ALOGV("%s, line: %d", __FUNCTION__, __LINE__);
#define DEFAULT_SAMPLING_RATE RATE_48K
#define OUTPUT_ACTIVE_CARDS AUDIO_CARD_CODEC
#ifndef TD100
#define INPUT_ACTIVE_CARDS AUDIO_CARD_SNDES7210 //// only one capture device can be active
#else
#define INPUT_ACTIVE_CARDS AUDIO_CARD_TD100 //// only one capture device can be active
#endif
#define EXTERNAL_OUTPUT_ACTIVE_CARD AUDIO_CARD_SPDIF
#define DSP_OUTPUT_ACTIVE_CARD AUDIO_CARD_I2S2
#define DSP_INPUT_ACTIVE_CARD AUDIO_CARD_I2S2
#define ENABLE_SUB_PCM_DEVICE 0
#define USE_INPUT_RESAMPLER 0
#if ENABLE_SUB_PCM_DEVICE
#define SUB_PCM_DEVICE AUDIO_NAME_I2S2
#endif
#define AUDIO_CARD_AUTO_DEC 0x01
#define AUDIO_CARD_CODEC 0x02
#define AUDIO_CARD_HDMI 0x04
#define AUDIO_CARD_SPDIF 0x08
#define AUDIO_CARD_I2S2 0x10
#define AUDIO_CARD_I2S3 0x20
#define AUDIO_CARD_AC107 0x40
#define AUDIO_CARD_AHUB 0x80
#define AUDIO_CARD_TD100 0x100
#define AUDIO_CARD_SNDES7210 0x200
#define AUDIO_CARD_SNDBT936B 0x400
#define AUDIO_CARD_NONE 0x1000
#define AUDIO_NONE 0x00
#define AUDIO_IN 0x01
#define AUDIO_OUT 0x02
#define PORT_AC107 0
#define PORT_TD100 0
#define PORT_HDMI 0
#define PORT_I2S0 0
#define PORT_I2S2 2
#define PORT_I2S3 1
#define AUDIO_NAME_CODEC "AUDIO_CODEC"
#define AUDIO_NAME_AHUB "AUDIO_AHUB"
#define AUDIO_NAME_HDMI "AUDIO_HDMI"
#define AUDIO_NAME_SPDIF "AUDIO_SPDIF"
#define AUDIO_NAME_AC107 "AUDIO_AC107"
#define AUDIO_NAME_TD100 "AUDIO_TD100"
#define AUDIO_NAME_I2S2 "AUDIO_I2S2"
#define AUDIO_NAME_I2S3 "AUDIO_I2S3"
#define AUDIO_NAME_SNDES7210 "AUDIO_SND_ES7210" // 使用i2s2
#define AUDIO_NAME_SNDBT936B "AUDIO_SND_BT936B" // 使用i2s0
// 此名称对应linux驱动注册的声卡名称, 可以通过 "cat /proc/asound/cards" 查看
#define AUDIO_NAME_SNDES7210_LINUX "sndes721010043"
#define AUDIO_NAME_SNDBT936B_LINUX "sndbt936b"
#define RATE_8K 8000
#define RATE_11K 11025
#define RATE_12K 12000
#define RATE_16K 16000
#define RATE_22K 22050
#define RATE_24K 24000
#define RATE_32K 32000
#define RATE_44K 44100
#define RATE_48K 48000
#define RATE_96K 96000
#define RATE_192K 192000
#define DEFAULT_CHANNEL_COUNT 2
#define DEFAULT_OUTPUT_PERIOD_SIZE (1360*2)
#define DEFAULT_OUTPUT_PERIOD_COUNT 2
#define DEFAULT_INPUT_PERIOD_SIZE 1024
#define DEFAULT_INPUT_PERIOD_COUNT 2
#define RESAMPLER_BUFFER_FRAMES (DEFAULT_OUTPUT_PERIOD_SIZE * 2)
#define RESAMPLER_BUFFER_SIZE (4 * RESAMPLER_BUFFER_FRAMES)
#define MAX_AUDIO_DEVICES 16
#define AUDIO_HAL_PARAM_OUTPUT_DEVICES "output devices"
#define AUDIO_HAL_PARAM_OUTPUT_DEVICES_IS_ACTIVE "is active"
#define AUDIO_HAL_PARAM_OUTPUT_DEVICES_AUDIO_CODEC "codec"
#define AUDIO_HAL_PARAM_OUTPUT_DEVICES_SNDBT936B "sndbt936b"
#define AUDIO_HAL_PARAM_OUTPUT_DEVICES_HDMI "hdmi"
#define AUDIO_HAL_PARAM_OUTPUT_DEVICES_SPDIF "spdif"
#define AUDIO_HAL_PARAM_INPUT_DEVICES "input devices"
#define AUDIO_HAL_PARAM_INPUT_DEVICES_IS_ACTIVE "is active"
#define AUDIO_HAL_PARAM_INPUT_DEVICES_SNDBT936B "sndbt936b"
#define AUDIO_HAL_PARAM_INPUT_DEVICES_SNDES7210 "sndes7210"
#define AUDIO_HAL_PARAM_TYW_SWITCH "tyw switch"
#define AUDIO_HAL_PARAM_TYW_SWITCH_HEADSET "headset"
#define AUDIO_HAL_PARAM_TYW_SWITCH_SPEAKER "speaker"
#define AUDIO_HAL_PARAM_ROUTE "audio-route"
#define AUDIO_HAL_PARAM_ROUTE_VALUE "value"
#define AUDIO_HAL_PARAM_ROUTE_LINEOUT "lineout"
#define AUDIO_HAL_PARAM_ROUTE_LINEIN_LINEOUT "linein-lineout"
#define AUDIO_HAL_PARAM_ROUTE_FMIN_LINEOUT "fmin-lineout"
#define AUDIO_HAL_PARAM_ROUTE_HDMI_OUT "hdmi out"
#define AUDIO_HAL_PARAM_ROUTE_AC107_IN "ac107 in"
#define AUDIO_HAL_PARAM_ROUTE_I2S2_OUT "i2s2 out"
#define AUDIO_HAL_PARAM_ROUTE_I2S2_IN "i2s2 in"
#define AUDIO_HAL_PARAM_ROUTE_I2S3_OUT "i2s3 out"
#define AUDIO_HAL_PARAM_ROUTE_I2S3_IN "i2s3 out"
#define AUDIO_HAL_PARAM_ROUTE_SNDES7210_IN "sndes7210 in"
#define AUDIO_HAL_PARAM_ROUTE_SNDBT936B_OUT "sndbt936b out"
#define AUDIO_HAL_PARAM_ROUTE_SNDBT936B_IN "sndbt936b in"
#define AUDIO_HAL_PARAM_ROUTE_SPDIF "spdif"
#define AUDIO_HAL_PARAM_VOL_LINEOUT "lineout vol"
#define AUDIO_HAL_PARAM_VOL_LINEIN "linein vol"
#define AUDIO_HAL_PARAM_VOL_FMIN "fmin vol"
#define AUDIO_HAL_PARAM_VOL_AC107_C1_PGA "ac107 c1 pga vol"
#define AUDIO_HAL_PARAM_VOL_AC107_C2_PGA "ac107 c2 pga vol"
#define AUDIO_HAL_PARAM_VOL_AC107_C1_DIGITAL "ac107 c1 digital vol"
#define AUDIO_HAL_PARAM_VOL_AC107_C2_DIGITAL "ac107 c2 digital vol"
#define AUDIO_HAL_PARAM_VOL_TD100_MIC1 "td100 mic1 vol"
#define AUDIO_HAL_PARAM_VOL_TD100_MIC2 "td100 mic2 vol"
#define AUDIO_HAL_PARAM_VOL_TD100_MIC3 "td100 mic3 vol"
#define AUDIO_HAL_PARAM_VOL_TD100_LINEIN "td100 linein vol"
#define AUDIO_HAL_PARAM_DVOL_TD100_ADC1 "td100 adc1 dvol"
#define AUDIO_HAL_PARAM_DVOL_TD100_ADC2 "td100 adc2 dvol"
#define AUDIO_HAL_PARAM_CH1_TD100_SELECT "td100 ch1 select"
#define AUDIO_HAL_PARAM_CH2_TD100_SELECT "td100 ch2 select"
/* Power state */
#define AUDIO_HAL_PARAM_KEY_POWER_STATE "power_state"
#define PROP_RAWDATA_KEY "vendor.mediasw.sft.rawdata"
#define PROP_RAWDATA_MODE "rawdata-mode"
#define PROP_RAWDATA_MODE_PCM "PCM"
#define PROP_RAWDATA_MODE_HDMI_RAW "HDMI_RAW"
#define PROP_RAWDATA_MODE_SPDIF_RAW "SPDIF_RAW"
#define PROP_RAWDATA_DEFAULT_VALUE PROP_RAWDATA_MODE_PCM
#define PROP_RAWDATA_PORT "rawdata-port"
#define PROP_RAWDATA_PORT_HDMI "hdmi"
#define PROP_RAWDATA_PORT_SPDIF "spdif"
#define AUX_DIGITAL_MULTI_PERIOD_SIZE 2048
#define AUX_DIGITAL_MULTI_PERIOD_COUNT 4
#define AUX_DIGITAL_MULTI_DEFAULT_CHANNEL_COUNT 2
#define AUX_DIGITAL_MULTI_PERIOD_BYTES (AUX_DIGITAL_MULTI_PERIOD_SIZE * AUX_DIGITAL_MULTI_DEFAULT_CHANNEL_COUNT * 2)
#define PROP_RAWDATA_OUTPUT "vendor.rawdata.output"
#define PROP_RAWDATA_OUTPUT_ON "1"
#define PROP_RAWDATA_OUTPUT_OFF "0"
typedef
struct
sunxi_audio_device_manager
{
char
name
[
32
];
char
card_id
[
32
];
int
card
;
int
port
;
int
flag_in
;
//
int
flag_in_active
;
// 0: not used, 1: used to caputre
int
flag_out
;
int
flag_out_active
;
// 0: not used, 1: used to playback
bool
flag_exist
;
// for hot-plugging
bool
ahub_device
;
}
sunxi_audio_device_manager
;
struct
sunxi_stream_in
{
struct
audio_stream_in
stream
;
pthread_mutex_t
lock
;
/* see note below on mutex acquisition order */
struct
pcm_config
config
;
struct
pcm
*
pcm
;
struct
pcm
*
sub_pcm
;
struct
pcm
*
ext_pcm
;
struct
pcm
*
ext_sub_pcm
;
struct
pcm_config
ext_config
;
#if USE_INPUT_RESAMPLER
struct
resampler_itfe
*
resampler
;
struct
resampler_buffer_provider
buf_provider
;
#endif
int16_t
*
buffer
;
size_t
frames_in
;
unsigned
int
requested_rate
;
int
standby
;
int
source
;
int
read_status
;
struct
sunxi_audio_device
*
dev
;
FILE
*
dump_pcm
;
audio_devices_t
device
;
};
struct
sunxi_stream_out
{
struct
audio_stream_out
stream
;
pthread_mutex_t
lock
;
/* see note below on mutex acquisition order */
struct
pcm_config
config
;
struct
pcm_config
multi_config
[
MAX_AUDIO_DEVICES
];
struct
pcm
*
multi_pcm
[
MAX_AUDIO_DEVICES
];
struct
pcm
*
sub_pcm
[
MAX_AUDIO_DEVICES
];
struct
resampler_itfe
*
multi_resampler
[
MAX_AUDIO_DEVICES
];
struct
pcm_config
ext_config
;
struct
pcm
*
ext_pcm
;
struct
pcm
*
ext_sub_pcm
;
struct
resampler_itfe
*
ext_resampler
;
char
*
buffer
;
int
standby
;
audio_format_t
format
;
audio_output_flags_t
flags
;
struct
sunxi_audio_device
*
dev
;
FILE
*
dump_pcm
;
audio_devices_t
device
;
};
struct
sunxi_audio_device
{
struct
audio_hw_device
hw_device
;
pthread_mutex_t
lock
;
/* see note below on mutex acquisition order */
struct
mixer
*
mixer_codec
;
struct
mixer
*
mixer_ahub
;
struct
mixer
*
mixer_ac107
;
struct
mixer
*
mixer_td100
;
int
mode
;
int
in_call
;
struct
sunxi_stream_in
*
active_input
;
struct
sunxi_stream_out
*
active_output
;
bool
mic_mute
;
struct
sunxi_audio_device_manager
dev_manager
[
MAX_AUDIO_DEVICES
];
struct
audio_route
*
ar_codec
;
struct
audio_route
*
ar_ahub
;
bool
stanby
;
int
card_codec
;
int
card_ahub
;
int
card_ac107
;
int
card_td100
;
int
card_sndes7210
;
int
card_sndbt936b
;
int
card_hdmi
;
int
card_spdif
;
int
output_active_cards
;
int
input_active_cards
;
bool
raw_flag
;
// flag for raw data
bool
raw_enable
;
char
in_devices
[
128
],
out_devices
[
128
];
//td100 ctrl val
int
vol_td100_mic1_val
;
int
vol_td100_mic2_val
;
int
vol_td100_mic3_val
;
int
vol_td100_linein_val
;
int
dvol_td100_adc1_val
;
int
dvol_td100_adc2_val
;
int
ch1_td100_select_val
;
int
ch2_td100_select_val
;
};
#endif
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment