0a00c144ed01967478b5b4ee853625d2c55d24fb
[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 <yamaha-mc1n2-audio.h>
32
33 struct yamaha_mc1n2_audio_pdata *yamaha_mc1n2_audio_platforms[] = {
34         &galaxys2_pdata,
35 };
36
37 int yamaha_mc1n2_audio_platforms_count = sizeof(yamaha_mc1n2_audio_platforms) /
38         sizeof(struct yamaha_mc1n2_audio_pdata *);
39
40 /*
41  * IOCTL
42  */
43
44 int yamaha_mc1n2_audio_ioctl(struct yamaha_mc1n2_audio_pdata *pdata,
45         int command, struct mc1n2_ctrl_args *hw_ctrl)
46 {
47         char *hw_node = NULL;
48         int hw_fd = -1;
49         int rc = -1;
50
51         if(pdata == NULL)
52                 return -1;
53
54         hw_node = yamaha_mc1n2_audio_get_hw_node(pdata);
55         if(hw_node == NULL) {
56                 LOGE("%s: error, missing hw_node!", __func__);
57                 return -1;
58         }
59
60         hw_fd = open(hw_node, O_RDWR);
61         if(hw_fd < 0) {
62                 LOGE("%s: error, unable to open hw_node (fd is %d)!", __func__, hw_fd);
63                 return -1;
64         }
65
66         rc = ioctl(hw_fd, command, hw_ctrl);
67         if(rc < 0) {
68                 LOGE("%s: error, ioctl on hw_node failed (rc is %d)!", __func__, rc);
69                 return -1;
70         }
71
72         close(hw_fd);
73
74         return rc;
75 }
76
77 int yamaha_mc1n2_audio_ioctl_set_ctrl(struct yamaha_mc1n2_audio_pdata *pdata,
78         unsigned long command, void *data, unsigned long update_info)
79 {
80         struct mc1n2_ctrl_args hw_ctrl;
81
82         if(pdata == NULL)
83                 return -1;
84
85         memset(&hw_ctrl, 0, sizeof(hw_ctrl));
86         hw_ctrl.dCmd = command;
87         hw_ctrl.pvPrm = data;
88         hw_ctrl.dPrm = update_info;
89
90         return yamaha_mc1n2_audio_ioctl(pdata, MC1N2_IOCTL_SET_CTRL, &hw_ctrl);
91 }
92
93 int yamaha_mc1n2_audio_ioctl_notify(struct yamaha_mc1n2_audio_pdata *pdata,
94         unsigned long command)
95 {
96         struct mc1n2_ctrl_args hw_ctrl;
97
98         if(pdata == NULL)
99                 return -1;
100
101         memset(&hw_ctrl, 0, sizeof(hw_ctrl));
102         hw_ctrl.dCmd = command;
103
104         return yamaha_mc1n2_audio_ioctl(pdata, MC1N2_IOCTL_NOTIFY, &hw_ctrl);
105 }
106
107 /*
108  * Routines
109  */
110
111 int yamaha_mc1n2_audio_routine_init(struct yamaha_mc1n2_audio_pdata *pdata)
112 {
113         struct yamaha_mc1n2_audio_routine_init *routine = NULL;
114         int rc = -1;
115
116         if(pdata == NULL || pdata->ops == NULL)
117                 return -1;
118
119         routine = pdata->ops->routine.init;
120         if(routine == NULL)
121                 return -1;
122
123         rc = yamaha_mc1n2_audio_ioctl_set_ctrl(pdata, MCDRV_SET_DAC,
124                 &routine->dac_info, 0x07);
125         if(rc < 0) {
126                 LOGE("SET_DAC IOCTL failed, aborting!");
127                 return -1;
128         }
129
130         rc = yamaha_mc1n2_audio_ioctl_set_ctrl(pdata, MCDRV_SET_ADC,
131                 &routine->adc_info, 0x07);
132         if(rc < 0) {
133                 LOGE("SET_ADC IOCTL failed, aborting!");
134                 return -1;
135         }
136
137         rc = yamaha_mc1n2_audio_ioctl_set_ctrl(pdata, MCDRV_SET_SP,
138                 &routine->sp_info, 0x00);
139         if(rc < 0) {
140                 LOGE("SET_SP IOCTL failed, aborting!");
141                 return -1;
142         }
143
144         rc = yamaha_mc1n2_audio_ioctl_set_ctrl(pdata, MCDRV_SET_PDM,
145                 &routine->pdm_info, 0x7f);
146         if(rc < 0) {
147                 LOGE("SET_PDM IOCTL failed, aborting!");
148                 return -1;
149         }
150
151         rc = yamaha_mc1n2_audio_ioctl_set_ctrl(pdata, MCDRV_SET_DNG,
152                 &routine->dng_info, 0x3f3f3f);
153         if(rc < 0) {
154                 LOGE("SET_DNG IOCTL failed, aborting!");
155                 return -1;
156         }
157
158         rc = yamaha_mc1n2_audio_ioctl_set_ctrl(pdata, MCDRV_SET_SYSEQ,
159                 &routine->syseq_info, 0x03);
160         if(rc < 0) {
161                 LOGE("SET_SYSEQ IOCTL failed, aborting!");
162                 return -1;
163         }
164
165         return 0;
166 }
167
168 int yamaha_mc1n2_audio_routine_route_init(struct yamaha_mc1n2_audio_pdata *pdata)
169 {
170         struct yamaha_mc1n2_audio_routine_route_init *routine = NULL;
171         int rc = -1;
172
173         if(pdata == NULL || pdata->ops == NULL)
174                 return -1;
175
176         routine = pdata->ops->routine.route_init;
177         if(routine == NULL)
178                 return -1;
179
180         rc = yamaha_mc1n2_audio_ioctl_set_ctrl(pdata, MCDRV_SET_PATH,
181                 &routine->path_info, 0x00);
182         if(rc < 0) {
183                 LOGE("SET_PATH IOCTL failed, aborting!");
184                 return -1;
185         }
186
187         rc = yamaha_mc1n2_audio_ioctl_set_ctrl(pdata, MCDRV_SET_DAC,
188                 &routine->dac_info, 0x07);
189         if(rc < 0) {
190                 LOGE("SET_DAC IOCTL failed, aborting!");
191                 return -1;
192         }
193
194         return 0;
195 }
196
197 /*
198  * Values configuration
199  */
200
201 char *yamaha_mc1n2_audio_get_hw_node(struct yamaha_mc1n2_audio_pdata *pdata)
202 {
203         if(pdata == NULL)
204                 return NULL;
205
206         return pdata->ops->hw_node;
207 }
208
209 /*
210  * Init/Deinit
211  */
212
213 struct yamaha_mc1n2_audio_pdata *yamaha_mc1n2_audio_platform_get(
214         char *device_name)
215 {
216         int i;
217
218         if(device_name == NULL)
219                 return NULL;
220
221         LOGD("Found %d registered platforms",
222                 yamaha_mc1n2_audio_platforms_count);
223
224         for(i=0 ; i < yamaha_mc1n2_audio_platforms_count ; i++) {
225                 if(yamaha_mc1n2_audio_platforms[i] != NULL &&
226                         yamaha_mc1n2_audio_platforms[i]->name != NULL) {
227                         if(strcmp(yamaha_mc1n2_audio_platforms[i]->name, device_name) == 0) {
228                                 return yamaha_mc1n2_audio_platforms[i];
229                         }
230                 }
231         }
232
233         return NULL;
234 }
235
236
237 int yamaha_mc1n2_audio_start(struct yamaha_mc1n2_audio_pdata **pdata_p,
238         char *device_name)
239 {
240         struct yamaha_mc1n2_audio_pdata *pdata = NULL;
241         int rc;
242
243         if(pdata_p == NULL || device_name == NULL)
244                 return -1;
245
246         pdata = yamaha_mc1n2_audio_platform_get(device_name);
247         if(pdata == NULL) {
248                 LOGE("Unable to find requested platform: %s", device_name);
249                 return -1;
250         }
251
252         *pdata_p = pdata;
253
254         return 0;
255 }
256
257 int yamaha_mc1n2_audio_stop(struct yamaha_mc1n2_audio_pdata *pdata)
258 {
259         if(pdata == NULL)
260                 return -1;
261
262         return 0;
263 }