Add support for radio
[platform/adaptation/spreadtrum/audio-hal-sc7727.git] / tizen-audio-stream.c
1 /*
2  * audio-hal
3  *
4  * Copyright (c) 2016 Samsung Electronics Co., Ltd. All rights reserved.
5  *
6  * Licensed under the Apache License, Version 2.0 (the "License");
7  * you may not use this file except in compliance with the License.
8  * You may obtain a copy of the License at
9  *
10  * http://www.apache.org/licenses/LICENSE-2.0
11  *
12  * Unless required by applicable law or agreed to in writing, software
13  * distributed under the License is distributed on an "AS IS" BASIS,
14  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15  * See the License for the specific language governing permissions and
16  * limitations under the License.
17  *
18  */
19
20 #ifdef HAVE_CONFIG_H
21 #include <config.h>
22 #endif
23
24 #include <stdio.h>
25 #include <stdlib.h>
26 #include <string.h>
27 #include <stdbool.h>
28
29 #include "tizen-audio-internal.h"
30 #include "tizen-audio-impl.h"
31
32 /* Audio latency */
33 static const char* AUDIO_LATENCY_LOW  = "low";
34 static const char* AUDIO_LATENCY_MID  = "mid";
35 static const char* AUDIO_LATENCY_HIGH = "high";
36 static const char* AUDIO_LATENCY_VOIP = "voip";
37
38 /* Latency msec */
39 static const unsigned int PERIOD_TIME_FOR_ULOW_LATENCY_MSEC  = 20;
40 static const unsigned int PERIOD_TIME_FOR_LOW_LATENCY_MSEC   = 25;
41 static const unsigned int PERIOD_TIME_FOR_MID_LATENCY_MSEC   = 50;
42 static const unsigned int PERIOD_TIME_FOR_HIGH_LATENCY_MSEC  = 75;
43 static const unsigned int PERIOD_TIME_FOR_UHIGH_LATENCY_MSEC = 150;
44 static const unsigned int PERIOD_TIME_FOR_VOIP_LATENCY_MSEC  = 20;
45
46 static const uint32_t g_size_table[] = {
47     [AUDIO_SAMPLE_U8]        = 1,
48     [AUDIO_SAMPLE_ULAW]      = 1,
49     [AUDIO_SAMPLE_ALAW]      = 1,
50     [AUDIO_SAMPLE_S16LE]     = 2,
51     [AUDIO_SAMPLE_S16BE]     = 2,
52     [AUDIO_SAMPLE_FLOAT32LE] = 4,
53     [AUDIO_SAMPLE_FLOAT32BE] = 4,
54     [AUDIO_SAMPLE_S32LE]     = 4,
55     [AUDIO_SAMPLE_S32BE]     = 4,
56     [AUDIO_SAMPLE_S24LE]     = 3,
57     [AUDIO_SAMPLE_S24BE]     = 3,
58     [AUDIO_SAMPLE_S24_32LE]  = 4,
59     [AUDIO_SAMPLE_S24_32BE]  = 4
60 };
61
62 static int __sample_spec_valid(uint32_t rate, audio_sample_format_t format, uint32_t channels)
63 {
64     if ((rate <= 0                 ||
65         rate > (48000U*4U)         ||
66         channels <= 0              ||
67         channels > 32U             ||
68         format >= AUDIO_SAMPLE_MAX ||
69         format <  AUDIO_SAMPLE_U8))
70         return 0;
71
72     AUDIO_LOG_ERROR("hal-latency - __sample_spec_valid() -> return true");
73
74     return 1;
75 }
76
77 static uint32_t __usec_to_bytes(uint64_t t, uint32_t rate, audio_sample_format_t format, uint32_t channels)
78 {
79     uint32_t ret = (uint32_t) (((t * rate) / 1000000ULL)) * (g_size_table[format] * channels);
80     AUDIO_LOG_DEBUG("hal-latency - return %d", ret);
81     return ret;
82 }
83
84 static uint32_t __sample_size(audio_sample_format_t format)
85 {
86     return g_size_table[format];
87 }
88
89 audio_return_t _audio_stream_init(audio_hal_t *ah)
90 {
91     AUDIO_RETURN_VAL_IF_FAIL(ah, AUDIO_ERR_PARAMETER);
92
93     return AUDIO_RET_OK;
94 }
95
96 audio_return_t _audio_stream_deinit(audio_hal_t *ah)
97 {
98     AUDIO_RETURN_VAL_IF_FAIL(ah, AUDIO_ERR_PARAMETER);
99
100     return AUDIO_RET_OK;
101 }
102
103 audio_return_t audio_notify_stream_connection_changed(void *audio_handle, audio_stream_info_t *info, uint32_t is_connected)
104 {
105     audio_return_t audio_ret = AUDIO_RET_OK;
106     audio_hal_t *ah = (audio_hal_t *)audio_handle;
107
108     AUDIO_RETURN_VAL_IF_FAIL(ah, AUDIO_ERR_PARAMETER);
109     AUDIO_RETURN_VAL_IF_FAIL(info, AUDIO_ERR_PARAMETER);
110
111     AUDIO_LOG_INFO("role:%s, direction:%u, idx:%u, is_connected:%d", info->role, info->direction, info->idx, is_connected);
112     if (streq(info->role, "radio")) {
113         if (is_connected)
114             ah->device.is_radio_on = 1;
115         else
116             ah->device.is_radio_on = 0;
117     }
118
119     return audio_ret;
120 }
121
122 audio_return_t audio_get_buffer_attr(void                  *audio_handle,
123                                      uint32_t              direction,
124                                      const char            *latency,
125                                      uint32_t              samplerate,
126                                      audio_sample_format_t format,
127                                      uint32_t              channels,
128                                      uint32_t              *maxlength,
129                                      uint32_t              *tlength,
130                                      uint32_t              *prebuf,
131                                      uint32_t              *minreq,
132                                      uint32_t              *fragsize)
133 {
134     AUDIO_RETURN_VAL_IF_FAIL(audio_handle, AUDIO_ERR_PARAMETER);
135     AUDIO_RETURN_VAL_IF_FAIL(latency, AUDIO_ERR_PARAMETER);
136     AUDIO_RETURN_VAL_IF_FAIL(maxlength, AUDIO_ERR_PARAMETER);
137     AUDIO_RETURN_VAL_IF_FAIL(tlength, AUDIO_ERR_PARAMETER);
138     AUDIO_RETURN_VAL_IF_FAIL(prebuf, AUDIO_ERR_PARAMETER);
139     AUDIO_RETURN_VAL_IF_FAIL(minreq, AUDIO_ERR_PARAMETER);
140     AUDIO_RETURN_VAL_IF_FAIL(fragsize, AUDIO_ERR_PARAMETER);
141
142     AUDIO_LOG_DEBUG("hal-latency - audio_get_buffer_attr(direction:%d, latency:%s, samplerate:%d, format:%d, channels:%d)", direction, latency, samplerate, format, channels);
143
144     uint32_t period_time        = 0,
145              sample_per_period  = 0;
146
147     if (__sample_spec_valid(samplerate, format, channels) == 0) {
148         return AUDIO_ERR_PARAMETER;
149     }
150
151     if (direction == AUDIO_DIRECTION_IN) {
152         if (!strcmp(latency, AUDIO_LATENCY_LOW)) {
153             AUDIO_LOG_DEBUG("AUDIO_DIRECTION_IN, AUDIO_LATENCY_LOW");
154             period_time        = PERIOD_TIME_FOR_LOW_LATENCY_MSEC;
155             sample_per_period  = (samplerate * period_time) / 1000;
156             *prebuf            = 0;
157             *minreq            = -1;
158             *tlength           = -1;
159             *maxlength         = -1;
160             *fragsize          = sample_per_period * __sample_size(format);
161         } else if (!strcmp(latency, AUDIO_LATENCY_MID)) {
162             AUDIO_LOG_DEBUG("AUDIO_DIRECTION_IN, AUDIO_LATENCY_MID");
163             period_time        = PERIOD_TIME_FOR_MID_LATENCY_MSEC;
164             sample_per_period  = (samplerate * period_time) / 1000;
165             *prebuf            = 0;
166             *minreq            = -1;
167             *tlength           = -1;
168             *maxlength         = -1;
169             *fragsize          = sample_per_period * __sample_size(format);
170         } else if (!strcmp(latency, AUDIO_LATENCY_HIGH)) {
171             AUDIO_LOG_DEBUG("AUDIO_DIRECTION_IN, AUDIO_LATENCY_HIGH");
172             period_time        = PERIOD_TIME_FOR_HIGH_LATENCY_MSEC;
173             sample_per_period  = (samplerate * period_time) / 1000;
174             *prebuf            = 0;
175             *minreq            = -1;
176             *tlength           = -1;
177             *maxlength         = -1;
178             *fragsize          = sample_per_period * __sample_size(format);
179         } else if (!strcmp(latency, AUDIO_LATENCY_VOIP)) {
180             AUDIO_LOG_DEBUG("AUDIO_DIRECTION_IN, AUDIO_LATENCY_VOIP");
181             period_time        = PERIOD_TIME_FOR_VOIP_LATENCY_MSEC;
182             sample_per_period  = (samplerate * period_time) / 1000;
183             *prebuf            = 0;
184             *minreq            = -1;
185             *tlength           = -1;
186             *maxlength         = -1;
187             *fragsize          = sample_per_period * __sample_size(format);
188         } else {
189             AUDIO_LOG_ERROR("hal-latency - The latency(%s) is undefined", latency);
190             return AUDIO_ERR_UNDEFINED;
191         }
192     } else {  /* AUDIO_DIRECTION_OUT */
193         if (!strcmp(latency, AUDIO_LATENCY_LOW)) {
194             AUDIO_LOG_DEBUG("AUDIO_DIRECTION_OUT, AUDIO_LATENCY_LOW");
195             period_time        = PERIOD_TIME_FOR_LOW_LATENCY_MSEC;
196             sample_per_period  = (samplerate * period_time) / 1000;
197             *prebuf            = 0;
198             *minreq            = -1;
199             *tlength           = (samplerate / 10) * __sample_size(format) * channels;  /* 100ms */
200             *maxlength         = -1;
201             *fragsize          = 0;
202         } else if (!strcmp(latency, AUDIO_LATENCY_MID)) {
203             AUDIO_LOG_DEBUG("AUDIO_DIRECTION_OUT, AUDIO_LATENCY_MID");
204             period_time        = PERIOD_TIME_FOR_MID_LATENCY_MSEC;
205             sample_per_period  = (samplerate * period_time) / 1000;
206             *prebuf            = 0;
207             *minreq            = -1;
208             *tlength           = (uint32_t) __usec_to_bytes(200000, samplerate, format, channels);
209             *maxlength         = -1;
210             *fragsize          = -1;
211         } else if (!strcmp(latency, AUDIO_LATENCY_HIGH)) {
212             AUDIO_LOG_DEBUG("AUDIO_DIRECTION_OUT, AUDIO_LATENCY_HIGH");
213             period_time        = PERIOD_TIME_FOR_HIGH_LATENCY_MSEC;
214             sample_per_period  = (samplerate * period_time) / 1000;
215             *prebuf            = 0;
216             *minreq            = -1;
217             *tlength           = (uint32_t) __usec_to_bytes(400000, samplerate, format, channels);
218             *maxlength         = -1;
219             *fragsize          = -1;
220         } else if (!strcmp(latency, AUDIO_LATENCY_VOIP)) {
221             AUDIO_LOG_DEBUG("AUDIO_DIRECTION_OUT, AUDIO_LATENCY_VOIP");
222             period_time        = PERIOD_TIME_FOR_VOIP_LATENCY_MSEC;
223             sample_per_period  = (samplerate * period_time) / 1000;
224             *prebuf            = 0;
225             *minreq            = __usec_to_bytes(20000, samplerate, format, channels);
226             *tlength           = __usec_to_bytes(100000, samplerate, format, channels);
227             *maxlength         = -1;
228             *fragsize          = 0;
229         } else {
230             AUDIO_LOG_ERROR("hal-latency - The latency(%s) is undefined", latency);
231             return AUDIO_ERR_UNDEFINED;
232         }
233     }
234
235     AUDIO_LOG_INFO("hal-latency - return attr --> prebuf:%d, minreq:%d, tlength:%d, maxlength:%d, fragsize:%d", *prebuf, *minreq, *tlength, *maxlength, *fragsize);
236     return AUDIO_RET_OK;
237 }