2 * Copyright (C) 2012 Paul Kocialkowski <contact@paulk.fr>
4 * This program is free software: you can redistribute it and/or modify
5 * it under the terms of the GNU General Public License as published by
6 * the Free Software Foundation, either version 3 of the License, or
7 * (at your option) any later version.
9 * This program is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 * GNU General Public License for more details.
14 * You should have received a copy of the GNU General Public License
15 * along with this program. If not, see <http://www.gnu.org/licenses/>.
22 #include <sys/types.h>
26 #include <linux/ioctl.h>
28 #define LOG_TAG "Yamaha-MC1N2-Audio"
29 #include <cutils/log.h>
31 #include <system/audio.h>
33 #include <yamaha-mc1n2-audio.h>
35 struct yamaha_mc1n2_audio_pdata *yamaha_mc1n2_audio_platforms[] = {
39 int yamaha_mc1n2_audio_platforms_count = sizeof(yamaha_mc1n2_audio_platforms) /
40 sizeof(struct yamaha_mc1n2_audio_pdata *);
46 int yamaha_mc1n2_audio_ioctl(struct yamaha_mc1n2_audio_pdata *pdata,
47 int command, struct mc1n2_ctrl_args *hw_ctrl)
53 if(pdata == NULL || pdata->ops == NULL)
56 hw_node = pdata->ops->hw_node;
58 LOGE("%s: error, missing hw_node!", __func__);
62 if(pdata->ops->hw_fd <= 0) {
63 hw_fd = open(hw_node, O_RDWR);
65 LOGE("%s: error, unable to open hw_node (fd is %d)!", __func__, hw_fd);
69 pdata->ops->hw_fd = hw_fd;
72 rc = ioctl(pdata->ops->hw_fd, command, hw_ctrl);
74 LOGE("%s: error, ioctl on hw_node failed (rc is %d)!", __func__, rc);
81 int yamaha_mc1n2_audio_ioctl_set_ctrl(struct yamaha_mc1n2_audio_pdata *pdata,
82 unsigned long command, void *data, unsigned long update_info)
84 struct mc1n2_ctrl_args hw_ctrl;
89 memset(&hw_ctrl, 0, sizeof(hw_ctrl));
90 hw_ctrl.dCmd = command;
92 hw_ctrl.dPrm = update_info;
94 return yamaha_mc1n2_audio_ioctl(pdata, MC1N2_IOCTL_SET_CTRL, &hw_ctrl);
97 int yamaha_mc1n2_audio_ioctl_notify(struct yamaha_mc1n2_audio_pdata *pdata,
98 unsigned long command)
100 struct mc1n2_ctrl_args hw_ctrl;
105 memset(&hw_ctrl, 0, sizeof(hw_ctrl));
106 hw_ctrl.dCmd = command;
108 return yamaha_mc1n2_audio_ioctl(pdata, MC1N2_IOCTL_NOTIFY, &hw_ctrl);
115 int yamaha_mc1n2_audio_init(struct yamaha_mc1n2_audio_pdata *pdata)
117 struct yamaha_mc1n2_audio_params_init *params = NULL;
120 if(pdata == NULL || pdata->ops == NULL)
123 params = pdata->ops->params.init;
127 rc = yamaha_mc1n2_audio_ioctl_set_ctrl(pdata, MCDRV_SET_DAC,
128 ¶ms->dac_info, 0x07);
130 LOGE("SET_DAC IOCTL failed, aborting!");
134 rc = yamaha_mc1n2_audio_ioctl_set_ctrl(pdata, MCDRV_SET_ADC,
135 ¶ms->adc_info, 0x07);
137 LOGE("SET_ADC IOCTL failed, aborting!");
141 rc = yamaha_mc1n2_audio_ioctl_set_ctrl(pdata, MCDRV_SET_SP,
142 ¶ms->sp_info, 0x00);
144 LOGE("SET_SP IOCTL failed, aborting!");
148 rc = yamaha_mc1n2_audio_ioctl_set_ctrl(pdata, MCDRV_SET_PDM,
149 ¶ms->pdm_info, 0x7f);
151 LOGE("SET_PDM IOCTL failed, aborting!");
155 rc = yamaha_mc1n2_audio_ioctl_set_ctrl(pdata, MCDRV_SET_DNG,
156 ¶ms->dng_info, 0x3f3f3f);
158 LOGE("SET_DNG IOCTL failed, aborting!");
162 rc = yamaha_mc1n2_audio_ioctl_set_ctrl(pdata, MCDRV_SET_SYSEQ,
163 ¶ms->syseq_info, 0x03);
165 LOGE("SET_SYSEQ IOCTL failed, aborting!");
172 struct yamaha_mc1n2_audio_params_route *
173 yamaha_mc1n2_audio_params_route_find(struct yamaha_mc1n2_audio_pdata *pdata,
174 audio_devices_t device, enum yamaha_mc1n2_audio_direction direction)
176 struct yamaha_mc1n2_audio_params_route *params = NULL;
177 int params_count = 0;
180 if(pdata == NULL || pdata->ops == NULL)
183 params = pdata->ops->params.routes;
184 params_count = pdata->ops->params.routes_count;
185 if(params == NULL || params_count <= 0)
188 for(i=0 ; i < params_count ; i++) {
189 if(params[i].device == device && params[i].direction == direction)
196 int yamaha_mc1n2_audio_params_route_simple_array_merge(int length,
197 unsigned char *array_src, unsigned char *array_dst)
201 if(length <= 0 || array_src == NULL || array_dst == NULL)
204 for(i=0 ; i < length ; i++) {
205 if(array_dst[i] == 0)
206 array_dst[i] = array_src[i];
212 int yamaha_mc1n2_audio_params_route_path_array_merge(int length,
213 unsigned char *array_src, unsigned char *array_dst)
218 if(length <= 0 || array_src == NULL || array_dst == NULL)
221 for(i=0 ; i < length ; i++) {
222 if(array_dst[i] == 0) {
223 array_dst[i] = array_src[i];
227 for(j=0; j < 8 ; j++) {
228 if((1 << j) & array_dst[i]) {
245 int yamaha_mc1n2_audio_params_route_merge(
246 struct yamaha_mc1n2_audio_params_route *params_src,
247 struct yamaha_mc1n2_audio_params_route *params_dst)
249 if(params_src == NULL || params_dst == NULL)
253 yamaha_mc1n2_audio_params_route_simple_array_merge(sizeof(params_src->ae_info.bOnOff),
254 ¶ms_src->ae_info.bOnOff, ¶ms_dst->ae_info.bOnOff);
255 yamaha_mc1n2_audio_params_route_simple_array_merge(sizeof(params_src->ae_info.abBex),
256 params_src->ae_info.abBex, params_dst->ae_info.abBex);
257 yamaha_mc1n2_audio_params_route_simple_array_merge(sizeof(params_src->ae_info.abWide),
258 params_src->ae_info.abWide, params_dst->ae_info.abWide);
259 yamaha_mc1n2_audio_params_route_simple_array_merge(sizeof(params_src->ae_info.abDrc),
260 params_src->ae_info.abDrc, params_dst->ae_info.abDrc);
261 yamaha_mc1n2_audio_params_route_simple_array_merge(sizeof(params_src->ae_info.abEq5),
262 params_src->ae_info.abEq5, params_dst->ae_info.abEq5);
263 yamaha_mc1n2_audio_params_route_simple_array_merge(sizeof(params_src->ae_info.abEq3),
264 params_src->ae_info.abEq3, params_dst->ae_info.abEq3);
267 yamaha_mc1n2_audio_params_route_path_array_merge(sizeof(params_src->path_info.asHpOut[0].abSrcOnOff),
268 params_src->path_info.asHpOut[0].abSrcOnOff, params_dst->path_info.asHpOut[0].abSrcOnOff);
269 yamaha_mc1n2_audio_params_route_path_array_merge(sizeof(params_src->path_info.asHpOut[1].abSrcOnOff),
270 params_src->path_info.asHpOut[1].abSrcOnOff, params_dst->path_info.asHpOut[1].abSrcOnOff);
271 yamaha_mc1n2_audio_params_route_path_array_merge(sizeof(params_src->path_info.asSpOut[0].abSrcOnOff),
272 params_src->path_info.asSpOut[0].abSrcOnOff, params_dst->path_info.asSpOut[0].abSrcOnOff);
273 yamaha_mc1n2_audio_params_route_path_array_merge(sizeof(params_src->path_info.asSpOut[1].abSrcOnOff),
274 params_src->path_info.asSpOut[1].abSrcOnOff, params_dst->path_info.asSpOut[1].abSrcOnOff);
275 yamaha_mc1n2_audio_params_route_path_array_merge(sizeof(params_src->path_info.asRcOut[0].abSrcOnOff),
276 params_src->path_info.asRcOut[0].abSrcOnOff, params_dst->path_info.asRcOut[0].abSrcOnOff);
277 yamaha_mc1n2_audio_params_route_path_array_merge(sizeof(params_src->path_info.asLout1[0].abSrcOnOff),
278 params_src->path_info.asLout1[0].abSrcOnOff, params_dst->path_info.asLout1[0].abSrcOnOff);
279 yamaha_mc1n2_audio_params_route_path_array_merge(sizeof(params_src->path_info.asLout1[1].abSrcOnOff),
280 params_src->path_info.asLout1[1].abSrcOnOff, params_dst->path_info.asLout1[1].abSrcOnOff);
281 yamaha_mc1n2_audio_params_route_path_array_merge(sizeof(params_src->path_info.asLout2[0].abSrcOnOff),
282 params_src->path_info.asLout2[0].abSrcOnOff, params_dst->path_info.asLout2[0].abSrcOnOff);
283 yamaha_mc1n2_audio_params_route_path_array_merge(sizeof(params_src->path_info.asLout2[1].abSrcOnOff),
284 params_src->path_info.asLout2[1].abSrcOnOff, params_dst->path_info.asLout2[1].abSrcOnOff);
285 yamaha_mc1n2_audio_params_route_path_array_merge(sizeof(params_src->path_info.asPeak[0].abSrcOnOff),
286 params_src->path_info.asPeak[0].abSrcOnOff, params_dst->path_info.asPeak[0].abSrcOnOff);
287 yamaha_mc1n2_audio_params_route_path_array_merge(sizeof(params_src->path_info.asDit0[0].abSrcOnOff),
288 params_src->path_info.asDit0[0].abSrcOnOff, params_dst->path_info.asDit0[0].abSrcOnOff);
289 yamaha_mc1n2_audio_params_route_path_array_merge(sizeof(params_src->path_info.asDit1[0].abSrcOnOff),
290 params_src->path_info.asDit1[0].abSrcOnOff, params_dst->path_info.asDit1[0].abSrcOnOff);
291 yamaha_mc1n2_audio_params_route_path_array_merge(sizeof(params_src->path_info.asDit2[0].abSrcOnOff),
292 params_src->path_info.asDit2[0].abSrcOnOff, params_dst->path_info.asDit2[0].abSrcOnOff);
293 yamaha_mc1n2_audio_params_route_path_array_merge(sizeof(params_src->path_info.asDac[0].abSrcOnOff),
294 params_src->path_info.asDac[0].abSrcOnOff, params_dst->path_info.asDac[0].abSrcOnOff);
295 yamaha_mc1n2_audio_params_route_path_array_merge(sizeof(params_src->path_info.asDac[1].abSrcOnOff),
296 params_src->path_info.asDac[1].abSrcOnOff, params_dst->path_info.asDac[1].abSrcOnOff);
297 yamaha_mc1n2_audio_params_route_path_array_merge(sizeof(params_src->path_info.asAe[0].abSrcOnOff),
298 params_src->path_info.asAe[0].abSrcOnOff, params_dst->path_info.asAe[0].abSrcOnOff);
299 yamaha_mc1n2_audio_params_route_path_array_merge(sizeof(params_src->path_info.asCdsp[0].abSrcOnOff),
300 params_src->path_info.asCdsp[0].abSrcOnOff, params_dst->path_info.asCdsp[0].abSrcOnOff);
301 yamaha_mc1n2_audio_params_route_path_array_merge(sizeof(params_src->path_info.asCdsp[1].abSrcOnOff),
302 params_src->path_info.asCdsp[1].abSrcOnOff, params_dst->path_info.asCdsp[1].abSrcOnOff);
303 yamaha_mc1n2_audio_params_route_path_array_merge(sizeof(params_src->path_info.asCdsp[2].abSrcOnOff),
304 params_src->path_info.asCdsp[2].abSrcOnOff, params_dst->path_info.asCdsp[2].abSrcOnOff);
305 yamaha_mc1n2_audio_params_route_path_array_merge(sizeof(params_src->path_info.asCdsp[3].abSrcOnOff),
306 params_src->path_info.asCdsp[3].abSrcOnOff, params_dst->path_info.asCdsp[3].abSrcOnOff);
307 yamaha_mc1n2_audio_params_route_path_array_merge(sizeof(params_src->path_info.asAdc0[0].abSrcOnOff),
308 params_src->path_info.asAdc0[0].abSrcOnOff, params_dst->path_info.asAdc0[0].abSrcOnOff);
309 yamaha_mc1n2_audio_params_route_path_array_merge(sizeof(params_src->path_info.asAdc0[1].abSrcOnOff),
310 params_src->path_info.asAdc0[1].abSrcOnOff, params_dst->path_info.asAdc0[1].abSrcOnOff);
311 yamaha_mc1n2_audio_params_route_path_array_merge(sizeof(params_src->path_info.asAdc1[0].abSrcOnOff),
312 params_src->path_info.asAdc1[0].abSrcOnOff, params_dst->path_info.asAdc1[0].abSrcOnOff);
313 yamaha_mc1n2_audio_params_route_path_array_merge(sizeof(params_src->path_info.asMix[0].abSrcOnOff),
314 params_src->path_info.asMix[0].abSrcOnOff, params_dst->path_info.asMix[0].abSrcOnOff);
315 yamaha_mc1n2_audio_params_route_path_array_merge(sizeof(params_src->path_info.asBias[0].abSrcOnOff),
316 params_src->path_info.asBias[0].abSrcOnOff, params_dst->path_info.asBias[0].abSrcOnOff);
319 yamaha_mc1n2_audio_params_route_simple_array_merge(sizeof(params_src->dac_info.bMasterSwap),
320 ¶ms_src->dac_info.bMasterSwap, ¶ms_dst->dac_info.bMasterSwap);
321 yamaha_mc1n2_audio_params_route_simple_array_merge(sizeof(params_src->dac_info.bVoiceSwap),
322 ¶ms_src->dac_info.bVoiceSwap, ¶ms_dst->dac_info.bVoiceSwap);
323 yamaha_mc1n2_audio_params_route_simple_array_merge(sizeof(params_src->dac_info.bDcCut),
324 ¶ms_src->dac_info.bDcCut, ¶ms_dst->dac_info.bDcCut);
329 int yamaha_mc1n2_audio_route_start(struct yamaha_mc1n2_audio_pdata *pdata)
331 struct yamaha_mc1n2_audio_params_route *params_route = NULL;
332 struct yamaha_mc1n2_audio_params_init *params_init = NULL;
333 struct yamaha_mc1n2_audio_params_route *params = NULL;
334 struct yamaha_mc1n2_audio_params_route params_src;
335 struct yamaha_mc1n2_audio_params_route params_dst;
339 LOGD("%s()", __func__);
341 if(pdata == NULL || pdata->ops == NULL)
344 params_init = pdata->ops->params.init;
345 if(params_init == NULL)
348 // Copy the init params
349 memcpy(¶ms_src.ae_info, ¶ms_init->ae_info, sizeof(params_src.ae_info));
350 memcpy(¶ms_src.path_info, ¶ms_init->path_info, sizeof(params_src.path_info));
351 memcpy(¶ms_src.dac_info, ¶ms_init->dac_info, sizeof(params_src.dac_info));
354 if(pdata->output_state) {
355 params_route = yamaha_mc1n2_audio_params_route_find(pdata,
356 pdata->output_device, YAMAHA_MC1N2_AUDIO_DIRECTION_OUTPUT);
357 if(params_route == NULL)
360 memcpy(¶ms_dst, params_route, sizeof(params_dst));
361 yamaha_mc1n2_audio_params_route_merge(¶ms_src, ¶ms_dst);
362 memcpy(¶ms_src, ¶ms_dst, sizeof(params_src));
366 if(pdata->input_state) {
367 params_route = yamaha_mc1n2_audio_params_route_find(pdata,
368 pdata->input_device, YAMAHA_MC1N2_AUDIO_DIRECTION_INPUT);
369 if(params_route == NULL)
372 memcpy(¶ms_dst, params_route, sizeof(params_dst));
373 yamaha_mc1n2_audio_params_route_merge(¶ms_src, ¶ms_dst);
374 memcpy(¶ms_src, ¶ms_dst, sizeof(params_src));
378 if(pdata->modem_state) {
379 params_route = yamaha_mc1n2_audio_params_route_find(pdata,
380 pdata->output_device, YAMAHA_MC1N2_AUDIO_DIRECTION_MODEM);
381 if(params_route == NULL)
384 memcpy(¶ms_dst, params_route, sizeof(params_dst));
385 yamaha_mc1n2_audio_params_route_merge(¶ms_src, ¶ms_dst);
386 memcpy(¶ms_src, ¶ms_dst, sizeof(params_src));
390 params = &(params_src);
392 rc = yamaha_mc1n2_audio_ioctl_set_ctrl(pdata, MCDRV_SET_AUDIOENGINE,
393 ¶ms->ae_info, 0x0f);
395 LOGE("SET_AUDIOENGINE IOCTL failed, aborting!");
399 rc = yamaha_mc1n2_audio_ioctl_set_ctrl(pdata, MCDRV_SET_PATH,
400 ¶ms->path_info, 0x00);
402 LOGE("SET_PATH IOCTL failed, aborting!");
406 rc = yamaha_mc1n2_audio_ioctl_set_ctrl(pdata, MCDRV_SET_DAC,
407 ¶ms->dac_info, 0x07);
409 LOGE("SET_DAC IOCTL failed, aborting!");
416 int yamaha_mc1n2_audio_output_start(struct yamaha_mc1n2_audio_pdata *pdata)
420 LOGD("%s()", __func__);
422 if(pdata == NULL || pdata->ops == NULL)
425 pdata->output_state = 1;
427 rc = yamaha_mc1n2_audio_route_start(pdata);
429 LOGE("Route start failed, aborting!");
433 rc = yamaha_mc1n2_audio_ioctl_notify(pdata, MCDRV_NOTIFY_MEDIA_PLAY_START);
435 LOGE("NOTIFY_MEDIA_PLAY_START IOCTL failed, aborting!");
442 int yamaha_mc1n2_audio_output_stop(struct yamaha_mc1n2_audio_pdata *pdata)
446 LOGD("%s()", __func__);
448 if(pdata == NULL || pdata->ops == NULL)
451 pdata->output_state = 0;
453 rc = yamaha_mc1n2_audio_route_start(pdata);
455 LOGE("Route start failed, aborting!");
459 rc = yamaha_mc1n2_audio_ioctl_notify(pdata, MCDRV_NOTIFY_MEDIA_PLAY_STOP);
461 LOGE("NOTIFY_MEDIA_PLAY_STOP IOCTL failed, aborting!");
468 int yamaha_mc1n2_audio_input_start(struct yamaha_mc1n2_audio_pdata *pdata)
472 LOGD("%s()", __func__);
474 if(pdata == NULL || pdata->ops == NULL)
477 pdata->input_state = 1;
479 rc = yamaha_mc1n2_audio_route_start(pdata);
481 LOGE("Route start failed, aborting!");
485 rc = yamaha_mc1n2_audio_ioctl_notify(pdata, MCDRV_NOTIFY_VOICE_REC_START);
487 LOGE("NOTIFY_VOICE_REC_START IOCTL failed, aborting!");
494 int yamaha_mc1n2_audio_input_stop(struct yamaha_mc1n2_audio_pdata *pdata)
498 LOGD("%s()", __func__);
500 if(pdata == NULL || pdata->ops == NULL)
503 pdata->input_state = 0;
505 rc = yamaha_mc1n2_audio_route_start(pdata);
507 LOGE("Route start failed, aborting!");
511 rc = yamaha_mc1n2_audio_ioctl_notify(pdata, MCDRV_NOTIFY_VOICE_REC_STOP);
513 LOGE("NOTIFY_VOICE_REC_START IOCTL failed, aborting!");
520 int yamaha_mc1n2_audio_modem_start(struct yamaha_mc1n2_audio_pdata *pdata)
524 LOGD("%s()", __func__);
526 if(pdata == NULL || pdata->ops == NULL)
529 pdata->modem_state = 1;
531 rc = yamaha_mc1n2_audio_route_start(pdata);
533 LOGE("Route start failed, aborting!");
537 rc = yamaha_mc1n2_audio_ioctl_notify(pdata, MCDRV_NOTIFY_CALL_START);
539 LOGE("NOTIFY_CALL_START IOCTL failed, aborting!");
546 int yamaha_mc1n2_audio_modem_stop(struct yamaha_mc1n2_audio_pdata *pdata)
550 LOGD("%s()", __func__);
552 if(pdata == NULL || pdata->ops == NULL)
555 pdata->modem_state = 0;
557 rc = yamaha_mc1n2_audio_route_start(pdata);
559 LOGE("Route start failed, aborting!");
563 rc = yamaha_mc1n2_audio_ioctl_notify(pdata, MCDRV_NOTIFY_CALL_STOP);
565 LOGE("NOTIFY_CALL_START IOCTL failed, aborting!");
573 * Values configuration
576 int yamaha_mc1n2_audio_set_route(struct yamaha_mc1n2_audio_pdata *pdata,
577 audio_devices_t device)
581 LOGD("%s(%x)", __func__, device);
586 if(audio_is_output_device(device) && pdata->output_device != device) {
587 pdata->output_device = device;
589 } else if(audio_is_input_device(device) && pdata->input_device != device) {
590 pdata->input_device = device;
594 if(changed && (pdata->output_state || pdata->input_state || pdata->modem_state))
595 return yamaha_mc1n2_audio_route_start(pdata);
600 char *yamaha_mc1n2_audio_get_hw_node(struct yamaha_mc1n2_audio_pdata *pdata)
605 return pdata->ops->hw_node;
612 struct yamaha_mc1n2_audio_pdata *yamaha_mc1n2_audio_platform_get(
617 if(device_name == NULL)
620 LOGD("Found %d registered platforms",
621 yamaha_mc1n2_audio_platforms_count);
623 for(i=0 ; i < yamaha_mc1n2_audio_platforms_count ; i++) {
624 if(yamaha_mc1n2_audio_platforms[i] != NULL &&
625 yamaha_mc1n2_audio_platforms[i]->name != NULL) {
626 if(strcmp(yamaha_mc1n2_audio_platforms[i]->name, device_name) == 0) {
627 return yamaha_mc1n2_audio_platforms[i];
636 int yamaha_mc1n2_audio_start(struct yamaha_mc1n2_audio_pdata **pdata_p,
639 struct yamaha_mc1n2_audio_pdata *pdata = NULL;
642 LOGD("%s(%s)", __func__, device_name);
644 if(pdata_p == NULL || device_name == NULL)
647 pdata = yamaha_mc1n2_audio_platform_get(device_name);
648 if(pdata == NULL || pdata->ops == NULL) {
649 LOGE("Unable to find requested platform: %s", device_name);
653 pdata->ops->hw_fd = -1;
660 int yamaha_mc1n2_audio_stop(struct yamaha_mc1n2_audio_pdata *pdata)
662 LOGD("%s()", __func__);
664 if(pdata == NULL || pdata->ops == NULL)
667 if(pdata->ops->hw_fd >= 0) {
668 close(pdata->ops->hw_fd);