Avoid opening and closing hw_node everytime on ioctl
[yamaha-mc1n2-audio.git] / yamaha-mc1n2-audio.c
1 /*
2  * Copyright (C) 2012 Paul Kocialkowski <contact@paulk.fr>
3  *
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.
8  *
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.
13  *
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/>.
16  */
17
18 #include <stdio.h>
19 #include <stdlib.h>
20 #include <unistd.h>
21
22 #include <sys/types.h>
23 #include <sys/stat.h>
24 #include <fcntl.h>
25
26 #include <linux/ioctl.h>
27
28 #define LOG_TAG "Yamaha-MC1N2-Audio"
29 #include <cutils/log.h>
30
31 #include <system/audio.h>
32
33 #include <yamaha-mc1n2-audio.h>
34
35 struct yamaha_mc1n2_audio_pdata *yamaha_mc1n2_audio_platforms[] = {
36         &galaxys2_pdata,
37 };
38
39 int yamaha_mc1n2_audio_platforms_count = sizeof(yamaha_mc1n2_audio_platforms) /
40         sizeof(struct yamaha_mc1n2_audio_pdata *);
41
42 /*
43  * IOCTL
44  */
45
46 int yamaha_mc1n2_audio_ioctl(struct yamaha_mc1n2_audio_pdata *pdata,
47         int command, struct mc1n2_ctrl_args *hw_ctrl)
48 {
49         char *hw_node = NULL;
50         int hw_fd = -1;
51         int rc = -1;
52
53         if(pdata == NULL || pdata->ops == NULL)
54                 return -1;
55
56         hw_node = pdata->ops->hw_node;
57         if(hw_node == NULL) {
58                 LOGE("%s: error, missing hw_node!", __func__);
59                 return -1;
60         }
61
62         if(pdata->ops->hw_fd <= 0) {
63                 hw_fd = open(hw_node, O_RDWR);
64                 if(hw_fd < 0) {
65                         LOGE("%s: error, unable to open hw_node (fd is %d)!", __func__, hw_fd);
66                         return -1;
67                 }
68
69                 pdata->ops->hw_fd = hw_fd;
70         }
71
72         rc = ioctl(pdata->ops->hw_fd, command, hw_ctrl);
73         if(rc < 0) {
74                 LOGE("%s: error, ioctl on hw_node failed (rc is %d)!", __func__, rc);
75                 return -1;
76         }
77
78         return rc;
79 }
80
81 int yamaha_mc1n2_audio_ioctl_set_ctrl(struct yamaha_mc1n2_audio_pdata *pdata,
82         unsigned long command, void *data, unsigned long update_info)
83 {
84         struct mc1n2_ctrl_args hw_ctrl;
85
86         if(pdata == NULL)
87                 return -1;
88
89         memset(&hw_ctrl, 0, sizeof(hw_ctrl));
90         hw_ctrl.dCmd = command;
91         hw_ctrl.pvPrm = data;
92         hw_ctrl.dPrm = update_info;
93
94         return yamaha_mc1n2_audio_ioctl(pdata, MC1N2_IOCTL_SET_CTRL, &hw_ctrl);
95 }
96
97 int yamaha_mc1n2_audio_ioctl_notify(struct yamaha_mc1n2_audio_pdata *pdata,
98         unsigned long command)
99 {
100         struct mc1n2_ctrl_args hw_ctrl;
101
102         if(pdata == NULL)
103                 return -1;
104
105         memset(&hw_ctrl, 0, sizeof(hw_ctrl));
106         hw_ctrl.dCmd = command;
107
108         return yamaha_mc1n2_audio_ioctl(pdata, MC1N2_IOCTL_NOTIFY, &hw_ctrl);
109 }
110
111 /*
112  * Routines
113  */
114
115 int yamaha_mc1n2_audio_init(struct yamaha_mc1n2_audio_pdata *pdata)
116 {
117         struct yamaha_mc1n2_audio_params_init *params = NULL;
118         int rc = -1;
119
120         if(pdata == NULL || pdata->ops == NULL)
121                 return -1;
122
123         params = pdata->ops->params.init;
124         if(params == NULL)
125                 return -1;
126
127         rc = yamaha_mc1n2_audio_ioctl_set_ctrl(pdata, MCDRV_SET_DAC,
128                 &params->dac_info, 0x07);
129         if(rc < 0) {
130                 LOGE("SET_DAC IOCTL failed, aborting!");
131                 return -1;
132         }
133
134         rc = yamaha_mc1n2_audio_ioctl_set_ctrl(pdata, MCDRV_SET_ADC,
135                 &params->adc_info, 0x07);
136         if(rc < 0) {
137                 LOGE("SET_ADC IOCTL failed, aborting!");
138                 return -1;
139         }
140
141         rc = yamaha_mc1n2_audio_ioctl_set_ctrl(pdata, MCDRV_SET_SP,
142                 &params->sp_info, 0x00);
143         if(rc < 0) {
144                 LOGE("SET_SP IOCTL failed, aborting!");
145                 return -1;
146         }
147
148         rc = yamaha_mc1n2_audio_ioctl_set_ctrl(pdata, MCDRV_SET_PDM,
149                 &params->pdm_info, 0x7f);
150         if(rc < 0) {
151                 LOGE("SET_PDM IOCTL failed, aborting!");
152                 return -1;
153         }
154
155         rc = yamaha_mc1n2_audio_ioctl_set_ctrl(pdata, MCDRV_SET_DNG,
156                 &params->dng_info, 0x3f3f3f);
157         if(rc < 0) {
158                 LOGE("SET_DNG IOCTL failed, aborting!");
159                 return -1;
160         }
161
162         rc = yamaha_mc1n2_audio_ioctl_set_ctrl(pdata, MCDRV_SET_SYSEQ,
163                 &params->syseq_info, 0x03);
164         if(rc < 0) {
165                 LOGE("SET_SYSEQ IOCTL failed, aborting!");
166                 return -1;
167         }
168
169         return 0;
170 }
171
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)
175 {
176         struct yamaha_mc1n2_audio_params_route *params = NULL;
177         int params_count = 0;
178         int i;
179
180         if(pdata == NULL || pdata->ops == NULL)
181                 return NULL;
182
183         params = pdata->ops->params.routes;
184         params_count = pdata->ops->params.routes_count;
185         if(params == NULL || params_count <= 0)
186                 return NULL;
187
188         for(i=0 ; i < params_count ; i++) {
189                 if(params[i].device == device && params[i].direction == direction)
190                         return &params[i];
191         }
192
193         return NULL;
194 }
195
196 int yamaha_mc1n2_audio_params_route_simple_array_merge(int length,
197         unsigned char *array_src, unsigned char *array_dst)
198 {
199         int i;
200
201         if(length <= 0 || array_src == NULL || array_dst == NULL)
202                 return -1;
203
204         for(i=0 ; i < length ; i++) {
205                 if(array_dst[i] == 0)
206                         array_dst[i] = array_src[i];
207         }
208
209         return 0;
210 }
211
212 int yamaha_mc1n2_audio_params_route_path_array_merge(int length,
213         unsigned char *array_src, unsigned char *array_dst)
214 {
215         int i, j;
216         unsigned char v;
217
218         if(length <= 0 || array_src == NULL || array_dst == NULL)
219                 return -1;
220
221         for(i=0 ; i < length ; i++) {
222                 if(array_dst[i] == 0) {
223                         array_dst[i] = array_src[i];
224                 } else {
225                         v = array_src[i];
226
227                         for(j=0; j < 8 ; j++) {
228                                 if((1 << j) & array_dst[i]) {
229                                         if(j % 2 == 0)
230                                                 v &= ~(1 << (j+1));
231                                         else
232                                                 v &= ~(1 << (j-1));
233
234                                         v |= (1 << j);
235                                 }
236                         }
237
238                         array_dst[i] = v;
239                 }
240         }
241
242         return 0;
243 }
244
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)
248 {
249         if(params_src == NULL || params_dst == NULL)
250                 return -1;
251
252         // ae_info
253         yamaha_mc1n2_audio_params_route_simple_array_merge(sizeof(params_src->ae_info.bOnOff),
254                 &params_src->ae_info.bOnOff, &params_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);
265
266         // path_info
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);
317
318         // dac_info
319         yamaha_mc1n2_audio_params_route_simple_array_merge(sizeof(params_src->dac_info.bMasterSwap),
320                 &params_src->dac_info.bMasterSwap, &params_dst->dac_info.bMasterSwap);
321         yamaha_mc1n2_audio_params_route_simple_array_merge(sizeof(params_src->dac_info.bVoiceSwap),
322                 &params_src->dac_info.bVoiceSwap, &params_dst->dac_info.bVoiceSwap);
323         yamaha_mc1n2_audio_params_route_simple_array_merge(sizeof(params_src->dac_info.bDcCut),
324                 &params_src->dac_info.bDcCut, &params_dst->dac_info.bDcCut);
325
326         return 0;
327 }
328
329 int yamaha_mc1n2_audio_route_start(struct yamaha_mc1n2_audio_pdata *pdata)
330 {
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;
336
337         int rc;
338
339         LOGD("%s()", __func__);
340
341         if(pdata == NULL || pdata->ops == NULL)
342                 return -1;
343
344         params_init = pdata->ops->params.init;
345         if(params_init == NULL)
346                 return -1;
347
348         // Copy the init params
349         memcpy(&params_src.ae_info, &params_init->ae_info, sizeof(params_src.ae_info));
350         memcpy(&params_src.path_info, &params_init->path_info, sizeof(params_src.path_info));
351         memcpy(&params_src.dac_info, &params_init->dac_info, sizeof(params_src.dac_info));
352
353 output_merge:
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)
358                         goto input_merge;
359
360                 memcpy(&params_dst, params_route, sizeof(params_dst));
361                 yamaha_mc1n2_audio_params_route_merge(&params_src, &params_dst);
362                 memcpy(&params_src, &params_dst, sizeof(params_src));
363         }
364
365 input_merge:
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)
370                         goto modem_merge;
371
372                 memcpy(&params_dst, params_route, sizeof(params_dst));
373                 yamaha_mc1n2_audio_params_route_merge(&params_src, &params_dst);
374                 memcpy(&params_src, &params_dst, sizeof(params_src));
375         }
376
377 modem_merge:
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)
382                         goto route_start;
383
384                 memcpy(&params_dst, params_route, sizeof(params_dst));
385                 yamaha_mc1n2_audio_params_route_merge(&params_src, &params_dst);
386                 memcpy(&params_src, &params_dst, sizeof(params_src));
387         }
388
389 route_start:
390         params = &(params_src);
391
392         rc = yamaha_mc1n2_audio_ioctl_set_ctrl(pdata, MCDRV_SET_AUDIOENGINE,
393                 &params->ae_info, 0x0f);
394         if(rc < 0) {
395                 LOGE("SET_AUDIOENGINE IOCTL failed, aborting!");
396                 return -1;
397         }
398
399         rc = yamaha_mc1n2_audio_ioctl_set_ctrl(pdata, MCDRV_SET_PATH,
400                 &params->path_info, 0x00);
401         if(rc < 0) {
402                 LOGE("SET_PATH IOCTL failed, aborting!");
403                 return -1;
404         }
405
406         rc = yamaha_mc1n2_audio_ioctl_set_ctrl(pdata, MCDRV_SET_DAC,
407                 &params->dac_info, 0x07);
408         if(rc < 0) {
409                 LOGE("SET_DAC IOCTL failed, aborting!");
410                 return -1;
411         }
412
413         return 0;
414 }
415
416 int yamaha_mc1n2_audio_output_start(struct yamaha_mc1n2_audio_pdata *pdata)
417 {
418         int rc;
419
420         LOGD("%s()", __func__);
421
422         if(pdata == NULL || pdata->ops == NULL)
423                 return -1;
424
425         pdata->output_state = 1;
426
427         rc = yamaha_mc1n2_audio_route_start(pdata);
428         if(rc < 0) {
429                 LOGE("Route start failed, aborting!");
430                 return -1;
431         }
432
433         rc = yamaha_mc1n2_audio_ioctl_notify(pdata, MCDRV_NOTIFY_MEDIA_PLAY_START);
434         if(rc < 0) {
435                 LOGE("NOTIFY_MEDIA_PLAY_START IOCTL failed, aborting!");
436                 return -1;
437         }
438
439         return 0;
440 }
441
442 int yamaha_mc1n2_audio_output_stop(struct yamaha_mc1n2_audio_pdata *pdata)
443 {
444         int rc;
445
446         LOGD("%s()", __func__);
447
448         if(pdata == NULL || pdata->ops == NULL)
449                 return -1;
450
451         pdata->output_state = 0;
452
453         rc = yamaha_mc1n2_audio_route_start(pdata);
454         if(rc < 0) {
455                 LOGE("Route start failed, aborting!");
456                 return -1;
457         }
458
459         rc = yamaha_mc1n2_audio_ioctl_notify(pdata, MCDRV_NOTIFY_MEDIA_PLAY_STOP);
460         if(rc < 0) {
461                 LOGE("NOTIFY_MEDIA_PLAY_STOP IOCTL failed, aborting!");
462                 return -1;
463         }
464
465         return 0;
466 }
467
468 int yamaha_mc1n2_audio_input_start(struct yamaha_mc1n2_audio_pdata *pdata)
469 {
470         int rc;
471
472         LOGD("%s()", __func__);
473
474         if(pdata == NULL || pdata->ops == NULL)
475                 return -1;
476
477         pdata->input_state = 1;
478
479         rc = yamaha_mc1n2_audio_route_start(pdata);
480         if(rc < 0) {
481                 LOGE("Route start failed, aborting!");
482                 return -1;
483         }
484
485         rc = yamaha_mc1n2_audio_ioctl_notify(pdata, MCDRV_NOTIFY_VOICE_REC_START);
486         if(rc < 0) {
487                 LOGE("NOTIFY_VOICE_REC_START IOCTL failed, aborting!");
488                 return -1;
489         }
490
491         return 0;
492 }
493
494 int yamaha_mc1n2_audio_input_stop(struct yamaha_mc1n2_audio_pdata *pdata)
495 {
496         int rc;
497
498         LOGD("%s()", __func__);
499
500         if(pdata == NULL || pdata->ops == NULL)
501                 return -1;
502
503         pdata->input_state = 0;
504
505         rc = yamaha_mc1n2_audio_route_start(pdata);
506         if(rc < 0) {
507                 LOGE("Route start failed, aborting!");
508                 return -1;
509         }
510
511         rc = yamaha_mc1n2_audio_ioctl_notify(pdata, MCDRV_NOTIFY_VOICE_REC_STOP);
512         if(rc < 0) {
513                 LOGE("NOTIFY_VOICE_REC_START IOCTL failed, aborting!");
514                 return -1;
515         }
516
517         return 0;
518 }
519
520 int yamaha_mc1n2_audio_modem_start(struct yamaha_mc1n2_audio_pdata *pdata)
521 {
522         int rc;
523
524         LOGD("%s()", __func__);
525
526         if(pdata == NULL || pdata->ops == NULL)
527                 return -1;
528
529         pdata->modem_state = 1;
530
531         rc = yamaha_mc1n2_audio_route_start(pdata);
532         if(rc < 0) {
533                 LOGE("Route start failed, aborting!");
534                 return -1;
535         }
536
537         rc = yamaha_mc1n2_audio_ioctl_notify(pdata, MCDRV_NOTIFY_CALL_START);
538         if(rc < 0) {
539                 LOGE("NOTIFY_CALL_START IOCTL failed, aborting!");
540                 return -1;
541         }
542
543         return 0;
544 }
545
546 int yamaha_mc1n2_audio_modem_stop(struct yamaha_mc1n2_audio_pdata *pdata)
547 {
548         int rc;
549
550         LOGD("%s()", __func__);
551
552         if(pdata == NULL || pdata->ops == NULL)
553                 return -1;
554
555         pdata->modem_state = 0;
556
557         rc = yamaha_mc1n2_audio_route_start(pdata);
558         if(rc < 0) {
559                 LOGE("Route start failed, aborting!");
560                 return -1;
561         }
562
563         rc = yamaha_mc1n2_audio_ioctl_notify(pdata, MCDRV_NOTIFY_CALL_STOP);
564         if(rc < 0) {
565                 LOGE("NOTIFY_CALL_START IOCTL failed, aborting!");
566                 return -1;
567         }
568
569         return 0;
570 }
571
572 /*
573  * Values configuration
574  */
575
576 int yamaha_mc1n2_audio_set_route(struct yamaha_mc1n2_audio_pdata *pdata,
577         audio_devices_t device)
578 {
579         int changed = 0;
580
581         LOGD("%s(%x)", __func__, device);
582
583         if(pdata == NULL)
584                 return -1;
585
586         if(audio_is_output_device(device) && pdata->output_device != device) {
587                 pdata->output_device = device;
588                 changed = 1;
589         } else if(audio_is_input_device(device) && pdata->input_device != device) {
590                 pdata->input_device = device;
591                 changed = 1;
592         }
593
594         if(changed && (pdata->output_state || pdata->input_state || pdata->modem_state))
595                 return yamaha_mc1n2_audio_route_start(pdata);
596
597         return 0;
598 }
599
600 char *yamaha_mc1n2_audio_get_hw_node(struct yamaha_mc1n2_audio_pdata *pdata)
601 {
602         if(pdata == NULL)
603                 return NULL;
604
605         return pdata->ops->hw_node;
606 }
607
608 /*
609  * Init/Deinit
610  */
611
612 struct yamaha_mc1n2_audio_pdata *yamaha_mc1n2_audio_platform_get(
613         char *device_name)
614 {
615         int i;
616
617         if(device_name == NULL)
618                 return NULL;
619
620         LOGD("Found %d registered platforms",
621                 yamaha_mc1n2_audio_platforms_count);
622
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];
628                         }
629                 }
630         }
631
632         return NULL;
633 }
634
635
636 int yamaha_mc1n2_audio_start(struct yamaha_mc1n2_audio_pdata **pdata_p,
637         char *device_name)
638 {
639         struct yamaha_mc1n2_audio_pdata *pdata = NULL;
640         int rc;
641
642         LOGD("%s(%s)", __func__, device_name);
643
644         if(pdata_p == NULL || device_name == NULL)
645                 return -1;
646
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);
650                 return -1;
651         }
652
653         pdata->ops->hw_fd = -1;
654
655         *pdata_p = pdata;
656
657         return 0;
658 }
659
660 int yamaha_mc1n2_audio_stop(struct yamaha_mc1n2_audio_pdata *pdata)
661 {
662         LOGD("%s()", __func__);
663
664         if(pdata == NULL || pdata->ops == NULL)
665                 return -1;
666
667         if(pdata->ops->hw_fd >= 0) {
668                 close(pdata->ops->hw_fd);
669         }
670
671         return 0;
672 }