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)
56 hw_node = yamaha_mc1n2_audio_get_hw_node(pdata);
58 LOGE("%s: error, missing hw_node!", __func__);
62 hw_fd = open(hw_node, O_RDWR);
64 LOGE("%s: error, unable to open hw_node (fd is %d)!", __func__, hw_fd);
68 rc = ioctl(hw_fd, command, hw_ctrl);
70 LOGE("%s: error, ioctl on hw_node failed (rc is %d)!", __func__, rc);
79 int yamaha_mc1n2_audio_ioctl_set_ctrl(struct yamaha_mc1n2_audio_pdata *pdata,
80 unsigned long command, void *data, unsigned long update_info)
82 struct mc1n2_ctrl_args hw_ctrl;
87 memset(&hw_ctrl, 0, sizeof(hw_ctrl));
88 hw_ctrl.dCmd = command;
90 hw_ctrl.dPrm = update_info;
92 return yamaha_mc1n2_audio_ioctl(pdata, MC1N2_IOCTL_SET_CTRL, &hw_ctrl);
95 int yamaha_mc1n2_audio_ioctl_notify(struct yamaha_mc1n2_audio_pdata *pdata,
96 unsigned long command)
98 struct mc1n2_ctrl_args hw_ctrl;
103 memset(&hw_ctrl, 0, sizeof(hw_ctrl));
104 hw_ctrl.dCmd = command;
106 return yamaha_mc1n2_audio_ioctl(pdata, MC1N2_IOCTL_NOTIFY, &hw_ctrl);
113 int yamaha_mc1n2_audio_init(struct yamaha_mc1n2_audio_pdata *pdata)
115 struct yamaha_mc1n2_audio_params_init *params = NULL;
118 if(pdata == NULL || pdata->ops == NULL)
121 params = pdata->ops->params.init;
125 rc = yamaha_mc1n2_audio_ioctl_set_ctrl(pdata, MCDRV_SET_DAC,
126 ¶ms->dac_info, 0x07);
128 LOGE("SET_DAC IOCTL failed, aborting!");
132 rc = yamaha_mc1n2_audio_ioctl_set_ctrl(pdata, MCDRV_SET_ADC,
133 ¶ms->adc_info, 0x07);
135 LOGE("SET_ADC IOCTL failed, aborting!");
139 rc = yamaha_mc1n2_audio_ioctl_set_ctrl(pdata, MCDRV_SET_SP,
140 ¶ms->sp_info, 0x00);
142 LOGE("SET_SP IOCTL failed, aborting!");
146 rc = yamaha_mc1n2_audio_ioctl_set_ctrl(pdata, MCDRV_SET_PDM,
147 ¶ms->pdm_info, 0x7f);
149 LOGE("SET_PDM IOCTL failed, aborting!");
153 rc = yamaha_mc1n2_audio_ioctl_set_ctrl(pdata, MCDRV_SET_DNG,
154 ¶ms->dng_info, 0x3f3f3f);
156 LOGE("SET_DNG IOCTL failed, aborting!");
160 rc = yamaha_mc1n2_audio_ioctl_set_ctrl(pdata, MCDRV_SET_SYSEQ,
161 ¶ms->syseq_info, 0x03);
163 LOGE("SET_SYSEQ IOCTL failed, aborting!");
170 struct yamaha_mc1n2_audio_params_route *
171 yamaha_mc1n2_audio_params_route_find(struct yamaha_mc1n2_audio_pdata *pdata,
172 audio_devices_t device, audio_mode_t mode)
174 struct yamaha_mc1n2_audio_params_route *params = NULL;
175 int params_count = 0;
178 if(pdata == NULL || pdata->ops == NULL)
181 params = pdata->ops->params.routes;
182 params_count = pdata->ops->params.routes_count;
183 if(params == NULL || params_count <= 0)
186 for(i=0 ; i < params_count ; i++) {
187 if(params[i].device == device && params[i].mode == mode)
194 int yamaha_mc1n2_audio_params_route_simple_array_merge(int length,
195 unsigned char *array_src, unsigned char *array_dst)
199 if(length <= 0 || array_src == NULL || array_dst == NULL)
202 for(i=0 ; i < length ; i++) {
203 if(array_dst[i] == 0)
204 array_dst[i] = array_src[i];
210 int yamaha_mc1n2_audio_params_route_path_array_merge(int length,
211 unsigned char *array_src, unsigned char *array_dst)
216 if(length <= 0 || array_src == NULL || array_dst == NULL)
219 for(i=0 ; i < length ; i++) {
220 if(array_dst[i] == 0) {
221 array_dst[i] = array_src[i];
225 for(j=0; j < 8 ; j++) {
226 if((1 << j) & array_dst[i]) {
243 int yamaha_mc1n2_audio_params_route_merge(
244 struct yamaha_mc1n2_audio_params_route *params_src,
245 struct yamaha_mc1n2_audio_params_route *params_dst)
247 if(params_src == NULL || params_dst == NULL)
251 yamaha_mc1n2_audio_params_route_simple_array_merge(sizeof(params_src->ae_info.bOnOff),
252 ¶ms_src->ae_info.bOnOff, ¶ms_dst->ae_info.bOnOff);
253 yamaha_mc1n2_audio_params_route_simple_array_merge(sizeof(params_src->ae_info.abBex),
254 params_src->ae_info.abBex, params_dst->ae_info.abBex);
255 yamaha_mc1n2_audio_params_route_simple_array_merge(sizeof(params_src->ae_info.abWide),
256 params_src->ae_info.abWide, params_dst->ae_info.abWide);
257 yamaha_mc1n2_audio_params_route_simple_array_merge(sizeof(params_src->ae_info.abDrc),
258 params_src->ae_info.abDrc, params_dst->ae_info.abDrc);
259 yamaha_mc1n2_audio_params_route_simple_array_merge(sizeof(params_src->ae_info.abEq5),
260 params_src->ae_info.abEq5, params_dst->ae_info.abEq5);
261 yamaha_mc1n2_audio_params_route_simple_array_merge(sizeof(params_src->ae_info.abEq3),
262 params_src->ae_info.abEq3, params_dst->ae_info.abEq3);
265 yamaha_mc1n2_audio_params_route_path_array_merge(sizeof(params_src->path_info.asHpOut[0].abSrcOnOff),
266 params_src->path_info.asHpOut[0].abSrcOnOff, params_dst->path_info.asHpOut[0].abSrcOnOff);
267 yamaha_mc1n2_audio_params_route_path_array_merge(sizeof(params_src->path_info.asHpOut[1].abSrcOnOff),
268 params_src->path_info.asHpOut[1].abSrcOnOff, params_dst->path_info.asHpOut[1].abSrcOnOff);
269 yamaha_mc1n2_audio_params_route_path_array_merge(sizeof(params_src->path_info.asSpOut[0].abSrcOnOff),
270 params_src->path_info.asSpOut[0].abSrcOnOff, params_dst->path_info.asSpOut[0].abSrcOnOff);
271 yamaha_mc1n2_audio_params_route_path_array_merge(sizeof(params_src->path_info.asSpOut[1].abSrcOnOff),
272 params_src->path_info.asSpOut[1].abSrcOnOff, params_dst->path_info.asSpOut[1].abSrcOnOff);
273 yamaha_mc1n2_audio_params_route_path_array_merge(sizeof(params_src->path_info.asRcOut[0].abSrcOnOff),
274 params_src->path_info.asRcOut[0].abSrcOnOff, params_dst->path_info.asRcOut[0].abSrcOnOff);
275 yamaha_mc1n2_audio_params_route_path_array_merge(sizeof(params_src->path_info.asLout1[0].abSrcOnOff),
276 params_src->path_info.asLout1[0].abSrcOnOff, params_dst->path_info.asLout1[0].abSrcOnOff);
277 yamaha_mc1n2_audio_params_route_path_array_merge(sizeof(params_src->path_info.asLout1[1].abSrcOnOff),
278 params_src->path_info.asLout1[1].abSrcOnOff, params_dst->path_info.asLout1[1].abSrcOnOff);
279 yamaha_mc1n2_audio_params_route_path_array_merge(sizeof(params_src->path_info.asLout2[0].abSrcOnOff),
280 params_src->path_info.asLout2[0].abSrcOnOff, params_dst->path_info.asLout2[0].abSrcOnOff);
281 yamaha_mc1n2_audio_params_route_path_array_merge(sizeof(params_src->path_info.asLout2[1].abSrcOnOff),
282 params_src->path_info.asLout2[1].abSrcOnOff, params_dst->path_info.asLout2[1].abSrcOnOff);
283 yamaha_mc1n2_audio_params_route_path_array_merge(sizeof(params_src->path_info.asPeak[0].abSrcOnOff),
284 params_src->path_info.asPeak[0].abSrcOnOff, params_dst->path_info.asPeak[0].abSrcOnOff);
285 yamaha_mc1n2_audio_params_route_path_array_merge(sizeof(params_src->path_info.asDit0[0].abSrcOnOff),
286 params_src->path_info.asDit0[0].abSrcOnOff, params_dst->path_info.asDit0[0].abSrcOnOff);
287 yamaha_mc1n2_audio_params_route_path_array_merge(sizeof(params_src->path_info.asDit1[0].abSrcOnOff),
288 params_src->path_info.asDit1[0].abSrcOnOff, params_dst->path_info.asDit1[0].abSrcOnOff);
289 yamaha_mc1n2_audio_params_route_path_array_merge(sizeof(params_src->path_info.asDit2[0].abSrcOnOff),
290 params_src->path_info.asDit2[0].abSrcOnOff, params_dst->path_info.asDit2[0].abSrcOnOff);
291 yamaha_mc1n2_audio_params_route_path_array_merge(sizeof(params_src->path_info.asDac[0].abSrcOnOff),
292 params_src->path_info.asDac[0].abSrcOnOff, params_dst->path_info.asDac[0].abSrcOnOff);
293 yamaha_mc1n2_audio_params_route_path_array_merge(sizeof(params_src->path_info.asDac[1].abSrcOnOff),
294 params_src->path_info.asDac[1].abSrcOnOff, params_dst->path_info.asDac[1].abSrcOnOff);
295 yamaha_mc1n2_audio_params_route_path_array_merge(sizeof(params_src->path_info.asAe[0].abSrcOnOff),
296 params_src->path_info.asAe[0].abSrcOnOff, params_dst->path_info.asAe[0].abSrcOnOff);
297 yamaha_mc1n2_audio_params_route_path_array_merge(sizeof(params_src->path_info.asCdsp[0].abSrcOnOff),
298 params_src->path_info.asCdsp[0].abSrcOnOff, params_dst->path_info.asCdsp[0].abSrcOnOff);
299 yamaha_mc1n2_audio_params_route_path_array_merge(sizeof(params_src->path_info.asCdsp[1].abSrcOnOff),
300 params_src->path_info.asCdsp[1].abSrcOnOff, params_dst->path_info.asCdsp[1].abSrcOnOff);
301 yamaha_mc1n2_audio_params_route_path_array_merge(sizeof(params_src->path_info.asCdsp[2].abSrcOnOff),
302 params_src->path_info.asCdsp[2].abSrcOnOff, params_dst->path_info.asCdsp[2].abSrcOnOff);
303 yamaha_mc1n2_audio_params_route_path_array_merge(sizeof(params_src->path_info.asCdsp[3].abSrcOnOff),
304 params_src->path_info.asCdsp[3].abSrcOnOff, params_dst->path_info.asCdsp[3].abSrcOnOff);
305 yamaha_mc1n2_audio_params_route_path_array_merge(sizeof(params_src->path_info.asAdc0[0].abSrcOnOff),
306 params_src->path_info.asAdc0[0].abSrcOnOff, params_dst->path_info.asAdc0[0].abSrcOnOff);
307 yamaha_mc1n2_audio_params_route_path_array_merge(sizeof(params_src->path_info.asAdc0[1].abSrcOnOff),
308 params_src->path_info.asAdc0[1].abSrcOnOff, params_dst->path_info.asAdc0[1].abSrcOnOff);
309 yamaha_mc1n2_audio_params_route_path_array_merge(sizeof(params_src->path_info.asAdc1[0].abSrcOnOff),
310 params_src->path_info.asAdc1[0].abSrcOnOff, params_dst->path_info.asAdc1[0].abSrcOnOff);
311 yamaha_mc1n2_audio_params_route_path_array_merge(sizeof(params_src->path_info.asMix[0].abSrcOnOff),
312 params_src->path_info.asMix[0].abSrcOnOff, params_dst->path_info.asMix[0].abSrcOnOff);
313 yamaha_mc1n2_audio_params_route_path_array_merge(sizeof(params_src->path_info.asBias[0].abSrcOnOff),
314 params_src->path_info.asBias[0].abSrcOnOff, params_dst->path_info.asBias[0].abSrcOnOff);
317 yamaha_mc1n2_audio_params_route_simple_array_merge(sizeof(params_src->dac_info.bMasterSwap),
318 ¶ms_src->dac_info.bMasterSwap, ¶ms_dst->dac_info.bMasterSwap);
319 yamaha_mc1n2_audio_params_route_simple_array_merge(sizeof(params_src->dac_info.bVoiceSwap),
320 ¶ms_src->dac_info.bVoiceSwap, ¶ms_dst->dac_info.bVoiceSwap);
321 yamaha_mc1n2_audio_params_route_simple_array_merge(sizeof(params_src->dac_info.bDcCut),
322 ¶ms_src->dac_info.bDcCut, ¶ms_dst->dac_info.bDcCut);
327 int yamaha_mc1n2_audio_route_start(struct yamaha_mc1n2_audio_pdata *pdata)
329 struct yamaha_mc1n2_audio_params_route *params_route = NULL;
330 struct yamaha_mc1n2_audio_params_init *params_init = NULL;
331 struct yamaha_mc1n2_audio_params_route *params = NULL;
332 struct yamaha_mc1n2_audio_params_route params_src;
333 struct yamaha_mc1n2_audio_params_route params_dst;
337 if(pdata == NULL || pdata->ops == NULL)
340 params_init = pdata->ops->params.init;
341 if(params_init == NULL)
344 // Copy the init params
345 memcpy(¶ms_src.ae_info, ¶ms_init->ae_info, sizeof(params_src.ae_info));
346 memcpy(¶ms_src.path_info, ¶ms_init->path_info, sizeof(params_src.path_info));
347 memcpy(¶ms_src.dac_info, ¶ms_init->dac_info, sizeof(params_src.dac_info));
350 if(pdata->output_state) {
351 params_route = yamaha_mc1n2_audio_params_route_find(pdata,
352 pdata->output_device, pdata->mode);
353 if(params_route == NULL)
356 memcpy(¶ms_dst, params_route, sizeof(params_dst));
357 yamaha_mc1n2_audio_params_route_merge(¶ms_src, ¶ms_dst);
358 memcpy(¶ms_src, ¶ms_dst, sizeof(params_src));
362 if(pdata->input_state) {
363 params_route = yamaha_mc1n2_audio_params_route_find(pdata,
364 pdata->input_device, pdata->mode);
365 if(params_route == NULL)
368 memcpy(¶ms_dst, params_route, sizeof(params_dst));
369 yamaha_mc1n2_audio_params_route_merge(¶ms_src, ¶ms_dst);
370 memcpy(¶ms_src, ¶ms_dst, sizeof(params_src));
374 params = &(params_src);
376 rc = yamaha_mc1n2_audio_ioctl_set_ctrl(pdata, MCDRV_SET_AUDIOENGINE,
377 ¶ms->ae_info, 0x0f);
379 LOGE("SET_AUDIOENGINE IOCTL failed, aborting!");
383 rc = yamaha_mc1n2_audio_ioctl_set_ctrl(pdata, MCDRV_SET_PATH,
384 ¶ms->path_info, 0x00);
386 LOGE("SET_PATH IOCTL failed, aborting!");
390 rc = yamaha_mc1n2_audio_ioctl_set_ctrl(pdata, MCDRV_SET_DAC,
391 ¶ms->dac_info, 0x07);
393 LOGE("SET_DAC IOCTL failed, aborting!");
400 int yamaha_mc1n2_audio_output_start(struct yamaha_mc1n2_audio_pdata *pdata)
404 if(pdata == NULL || pdata->ops == NULL)
407 pdata->output_state = 1;
409 rc = yamaha_mc1n2_audio_route_start(pdata);
411 LOGE("Route start failed, aborting!");
415 rc = yamaha_mc1n2_audio_ioctl_notify(pdata, MCDRV_NOTIFY_MEDIA_PLAY_START);
417 LOGE("NOTIFY_MEDIA_PLAY_START IOCTL failed, aborting!");
424 int yamaha_mc1n2_audio_output_stop(struct yamaha_mc1n2_audio_pdata *pdata)
428 if(pdata == NULL || pdata->ops == NULL)
431 pdata->output_state = 0;
433 rc = yamaha_mc1n2_audio_route_start(pdata);
435 LOGE("Route start failed, aborting!");
439 rc = yamaha_mc1n2_audio_ioctl_notify(pdata, MCDRV_NOTIFY_MEDIA_PLAY_STOP);
441 LOGE("NOTIFY_MEDIA_PLAY_STOP IOCTL failed, aborting!");
449 * Values configuration
452 int yamaha_mc1n2_audio_set_route(struct yamaha_mc1n2_audio_pdata *pdata,
453 audio_devices_t device, audio_mode_t mode)
460 if(audio_is_output_device(device) && pdata->output_device != device) {
461 pdata->output_device = device;
463 } else if(audio_is_input_device(device) && pdata->input_device != device) {
464 pdata->input_device = device;
468 if(pdata->mode != mode) {
473 if(changed && (pdata->output_state || pdata->input_state))
474 return yamaha_mc1n2_audio_route_start(pdata);
479 char *yamaha_mc1n2_audio_get_hw_node(struct yamaha_mc1n2_audio_pdata *pdata)
484 return pdata->ops->hw_node;
491 struct yamaha_mc1n2_audio_pdata *yamaha_mc1n2_audio_platform_get(
496 if(device_name == NULL)
499 LOGD("Found %d registered platforms",
500 yamaha_mc1n2_audio_platforms_count);
502 for(i=0 ; i < yamaha_mc1n2_audio_platforms_count ; i++) {
503 if(yamaha_mc1n2_audio_platforms[i] != NULL &&
504 yamaha_mc1n2_audio_platforms[i]->name != NULL) {
505 if(strcmp(yamaha_mc1n2_audio_platforms[i]->name, device_name) == 0) {
506 return yamaha_mc1n2_audio_platforms[i];
515 int yamaha_mc1n2_audio_start(struct yamaha_mc1n2_audio_pdata **pdata_p,
518 struct yamaha_mc1n2_audio_pdata *pdata = NULL;
521 if(pdata_p == NULL || device_name == NULL)
524 pdata = yamaha_mc1n2_audio_platform_get(device_name);
526 LOGE("Unable to find requested platform: %s", device_name);
535 int yamaha_mc1n2_audio_stop(struct yamaha_mc1n2_audio_pdata *pdata)