]> git.karo-electronics.de Git - karo-tx-linux.git/blob - drivers/staging/greybus/audio.c
greybus: audio: Drop get_version support
[karo-tx-linux.git] / drivers / staging / greybus / audio.c
1 /*
2  * Greybus audio driver
3  *
4  * Copyright 2015 Google Inc.
5  * Copyright 2015 Linaro Ltd.
6  *
7  * Released under the GPLv2 only.
8  */
9
10 #include <linux/kernel.h>
11 #include <linux/device.h>
12 #include <linux/interrupt.h>
13 #include <linux/module.h>
14 #include <linux/platform_device.h>
15 #include <linux/workqueue.h>
16 #include <sound/core.h>
17 #include <sound/pcm.h>
18 #include <sound/pcm_params.h>
19 #include <sound/soc.h>
20 #include <sound/dmaengine_pcm.h>
21 #include <sound/simple_card.h>
22
23 #include "greybus.h"
24 #include "audio.h"
25
26
27 #define GB_AUDIO_DATA_DRIVER_NAME               "gb_audio_data"
28 #define GB_AUDIO_MGMT_DRIVER_NAME               "gb_audio_mgmt"
29
30 #define RT5647_I2C_ADAPTER_NR                   6
31 #define RT5647_I2C_ADDR                         0x1b
32
33 /*
34  * gb_snd management functions
35  */
36 static DEFINE_SPINLOCK(gb_snd_list_lock);
37 static LIST_HEAD(gb_snd_list);
38 static int device_count;
39
40 static struct gb_snd *gb_find_snd(int bundle_id)
41 {
42         struct gb_snd *tmp, *ret = NULL;
43         unsigned long flags;
44
45         spin_lock_irqsave(&gb_snd_list_lock, flags);
46         list_for_each_entry(tmp, &gb_snd_list, list)
47                 if (tmp->gb_bundle_id == bundle_id) {
48                         ret = tmp;
49                         break;
50                 }
51         spin_unlock_irqrestore(&gb_snd_list_lock, flags);
52         return ret;
53 }
54
55 static struct gb_snd *gb_get_snd(int bundle_id)
56 {
57         struct gb_snd *snd_dev;
58         unsigned long flags;
59
60         snd_dev = gb_find_snd(bundle_id);
61         if (snd_dev)
62                 return snd_dev;
63
64         snd_dev = kzalloc(sizeof(*snd_dev), GFP_KERNEL);
65         if (!snd_dev)
66                 return NULL;
67
68         spin_lock_init(&snd_dev->lock);
69         snd_dev->device_count = device_count++;
70         snd_dev->gb_bundle_id = bundle_id;
71         spin_lock_irqsave(&gb_snd_list_lock, flags);
72         list_add(&snd_dev->list, &gb_snd_list);
73         spin_unlock_irqrestore(&gb_snd_list_lock, flags);
74         return snd_dev;
75 }
76
77 static void gb_free_snd(struct gb_snd *snd)
78 {
79         unsigned long flags;
80
81         spin_lock_irqsave(&gb_snd_list_lock, flags);
82         if (!snd->i2s_tx_connection &&
83                         !snd->mgmt_connection) {
84                 list_del(&snd->list);
85                 spin_unlock_irqrestore(&gb_snd_list_lock, flags);
86                 kfree(snd);
87         } else {
88                 spin_unlock_irqrestore(&gb_snd_list_lock, flags);
89         }
90 }
91
92
93
94
95 /*
96  * This is the ASoC simple card binds the platform codec,
97  * cpu-dai and codec-dai togheter
98  */
99 struct gb_card_info_object {
100         struct asoc_simple_card_info card_info;
101         char codec_name[255];
102         char platform_name[255];
103         char dai_name[255];
104 };
105
106
107 static struct asoc_simple_card_info *setup_card_info(int device_count)
108 {
109         struct gb_card_info_object *obj;
110
111         obj = kzalloc(sizeof(struct gb_card_info_object), GFP_KERNEL);
112         if (!obj)
113                 return NULL;
114
115         obj->card_info.name             = "Greybus Audio Module";
116         obj->card_info.card             = "gb-card";
117         obj->card_info.codec            = obj->codec_name;
118         obj->card_info.platform         = obj->platform_name;
119         obj->card_info.cpu_dai.name     = obj->dai_name;
120 #if LINUX_VERSION_CODE < KERNEL_VERSION(4, 1, 0)
121         obj->card_info.cpu_dai.fmt      = SND_SOC_DAIFMT_CBM_CFM;
122 #endif
123 #if USE_RT5645
124         obj->card_info.daifmt           = SND_SOC_DAIFMT_NB_NF |
125                                           SND_SOC_DAIFMT_I2S;
126         sprintf(obj->codec_name, "rt5645.%d-%04x", RT5647_I2C_ADAPTER_NR,
127                 RT5647_I2C_ADDR);
128         obj->card_info.codec_dai.name   = "rt5645-aif1";
129 #if LINUX_VERSION_CODE < KERNEL_VERSION(4, 1, 0)
130         obj->card_info.codec_dai.fmt    = SND_SOC_DAIFMT_CBS_CFS;
131 #endif
132         obj->card_info.codec_dai.sysclk = 12288000;
133 #else
134         sprintf(obj->codec_name, "spdif-dit");
135         obj->card_info.codec_dai.name = "dit-hifi";
136 #endif
137         sprintf(obj->platform_name, "gb-pcm-audio.%i", device_count);
138         sprintf(obj->dai_name, "gb-dai-audio.%i", device_count);
139
140         return &obj->card_info;
141 }
142
143 static void free_card_info(struct asoc_simple_card_info *ci)
144 {
145         struct gb_card_info_object *obj;
146
147         obj = container_of(ci, struct gb_card_info_object, card_info);
148         kfree(obj);
149 }
150
151
152 /*
153  * XXX this is sort of cruddy but I get warnings if
154  * we don't have dev.release handler set.
155  */
156 static void default_release(struct device *dev)
157 {
158 }
159
160 /*
161  * GB connection hooks
162  */
163 static int gb_i2s_transmitter_connection_init(struct gb_connection *connection)
164 {
165         struct gb_snd *snd_dev;
166         struct platform_device *codec, *dai;
167         struct asoc_simple_card_info *simple_card;
168 #if USE_RT5645
169         struct i2c_board_info rt5647_info;
170         struct i2c_adapter *i2c_adap;
171 #endif
172         unsigned long flags;
173         int ret;
174
175         snd_dev = gb_get_snd(connection->bundle->id);
176         if (!snd_dev)
177                 return -ENOMEM;
178
179         codec = platform_device_register_simple("spdif-dit", -1, NULL, 0);
180         if (!codec) {
181                 ret = -ENOMEM;
182                 goto out;
183         }
184
185         dai = platform_device_register_simple("gb-pcm-audio", snd_dev->device_count, NULL, 0);
186         if (!dai) {
187                 ret = -ENOMEM;
188                 goto out;
189         }
190
191         simple_card = setup_card_info(snd_dev->device_count);
192         if (!simple_card) {
193                 ret = -ENOMEM;
194                 goto out;
195         }
196
197         spin_lock_irqsave(&snd_dev->lock, flags);
198         snd_dev->card.name = "asoc-simple-card";
199         snd_dev->card.id = snd_dev->device_count;
200         snd_dev->card.dev.release = default_release; /* XXX - suspicious */
201
202         snd_dev->cpu_dai.name = "gb-dai-audio";
203         snd_dev->cpu_dai.id = snd_dev->device_count;
204         snd_dev->cpu_dai.dev.release = default_release; /* XXX - suspicious */
205
206
207         snd_dev->simple_card_info = simple_card;
208         snd_dev->card.dev.platform_data = simple_card;
209
210         snd_dev->codec = codec;
211         snd_dev->i2s_tx_connection = connection;
212         snd_dev->cpu_dai.dev.platform_data = snd_dev;
213         snd_dev->i2s_tx_connection->private = snd_dev;
214         spin_unlock_irqrestore(&snd_dev->lock, flags);
215
216         ret = platform_device_register(&snd_dev->cpu_dai);
217         if (ret) {
218                 pr_err("cpu_dai platform_device register failed\n");
219                 goto out_dai;
220         }
221
222         ret = platform_device_register(&snd_dev->card);
223         if (ret) {
224                 pr_err("card platform_device register failed\n");
225                 goto out_card;
226         }
227
228 #if USE_RT5645
229         rt5647_info.addr = RT5647_I2C_ADDR;
230         strlcpy(rt5647_info.type, "rt5647", I2C_NAME_SIZE);
231
232         i2c_adap = i2c_get_adapter(RT5647_I2C_ADAPTER_NR);
233         if (!i2c_adap) {
234                 pr_err("codec unavailable\n");
235                 ret = -ENODEV;
236                 goto out_get_ver;
237         }
238
239         snd_dev->rt5647 = i2c_new_device(i2c_adap, &rt5647_info);
240         if (!snd_dev->rt5647) {
241                 pr_err("can't create rt5647 i2c device\n");
242                 goto out_get_ver;
243         }
244 #endif
245
246         return 0;
247
248 #if USE_RT5645
249 out_get_ver:
250         platform_device_unregister(&snd_dev->card);
251 #endif
252 out_card:
253         platform_device_unregister(&snd_dev->cpu_dai);
254 out_dai:
255         platform_device_unregister(codec);
256 out:
257         gb_free_snd(snd_dev);
258         return ret;
259 }
260
261 static void gb_i2s_transmitter_connection_exit(struct gb_connection *connection)
262 {
263         struct gb_snd *snd_dev;
264
265         snd_dev = (struct gb_snd *)connection->private;
266
267 #if USE_RT5645
268         i2c_unregister_device(snd_dev->rt5647);
269 #endif
270
271         platform_device_unregister(&snd_dev->card);
272         platform_device_unregister(&snd_dev->cpu_dai);
273         platform_device_unregister(snd_dev->codec);
274
275         free_card_info(snd_dev->simple_card_info);
276         snd_dev->i2s_tx_connection = NULL;
277         gb_free_snd(snd_dev);
278 }
279
280 static int gb_i2s_mgmt_connection_init(struct gb_connection *connection)
281 {
282         struct gb_snd *snd_dev;
283         unsigned long flags;
284         int ret;
285
286         snd_dev = gb_get_snd(connection->bundle->id);
287         if (!snd_dev)
288                 return -ENOMEM;
289
290         spin_lock_irqsave(&snd_dev->lock, flags);
291         snd_dev->mgmt_connection = connection;
292         connection->private = snd_dev;
293         spin_unlock_irqrestore(&snd_dev->lock, flags);
294
295         ret = gb_i2s_mgmt_get_cfgs(snd_dev, connection);
296         if (ret) {
297                 pr_err("can't get i2s configurations: %d\n", ret);
298                 goto err_free_snd_dev;
299         }
300
301         ret = gb_i2s_mgmt_set_samples_per_message(snd_dev->mgmt_connection,
302                                                   CONFIG_SAMPLES_PER_MSG);
303         if (ret) {
304                 pr_err("set_samples_per_msg failed: %d\n", ret);
305                 goto err_free_i2s_configs;
306         }
307
308         snd_dev->send_data_req_buf = kzalloc(SEND_DATA_BUF_LEN, GFP_KERNEL);
309
310         if (!snd_dev->send_data_req_buf) {
311                 ret = -ENOMEM;
312                 goto err_free_i2s_configs;
313         }
314
315         return 0;
316
317 err_free_i2s_configs:
318         gb_i2s_mgmt_free_cfgs(snd_dev);
319 err_free_snd_dev:
320         gb_free_snd(snd_dev);
321         return ret;
322 }
323
324 static void gb_i2s_mgmt_connection_exit(struct gb_connection *connection)
325 {
326         struct gb_snd *snd_dev = (struct gb_snd *)connection->private;
327
328         gb_i2s_mgmt_free_cfgs(snd_dev);
329
330         kfree(snd_dev->send_data_req_buf);
331         snd_dev->send_data_req_buf = NULL;
332
333         snd_dev->mgmt_connection = NULL;
334         gb_free_snd(snd_dev);
335 }
336
337 static int gb_i2s_mgmt_report_event_recv(u8 type, struct gb_operation *op)
338 {
339         struct gb_connection *connection = op->connection;
340         struct gb_i2s_mgmt_report_event_request *req = op->request->payload;
341         char *event_name;
342
343         if (type != GB_I2S_MGMT_TYPE_REPORT_EVENT) {
344                 dev_err(&connection->dev, "Invalid request type: %d\n",
345                         type);
346                 return -EINVAL;
347         }
348
349         if (op->request->payload_size < sizeof(*req)) {
350                 dev_err(&connection->dev, "Short request received (%zu < %zu)\n",
351                         op->request->payload_size, sizeof(*req));
352                 return -EINVAL;
353         }
354
355         switch (req->event) {
356         case GB_I2S_MGMT_EVENT_UNSPECIFIED:
357                 event_name = "UNSPECIFIED";
358                 break;
359         case GB_I2S_MGMT_EVENT_HALT:
360                 /* XXX Should stop streaming now */
361                 event_name = "HALT";
362                 break;
363         case GB_I2S_MGMT_EVENT_INTERNAL_ERROR:
364                 event_name = "INTERNAL_ERROR";
365                 break;
366         case GB_I2S_MGMT_EVENT_PROTOCOL_ERROR:
367                 event_name = "PROTOCOL_ERROR";
368                 break;
369         case GB_I2S_MGMT_EVENT_FAILURE:
370                 event_name = "FAILURE";
371                 break;
372         case GB_I2S_MGMT_EVENT_OUT_OF_SEQUENCE:
373                 event_name = "OUT_OF_SEQUENCE";
374                 break;
375         case GB_I2S_MGMT_EVENT_UNDERRUN:
376                 event_name = "UNDERRUN";
377                 break;
378         case GB_I2S_MGMT_EVENT_OVERRUN:
379                 event_name = "OVERRUN";
380                 break;
381         case GB_I2S_MGMT_EVENT_CLOCKING:
382                 event_name = "CLOCKING";
383                 break;
384         case GB_I2S_MGMT_EVENT_DATA_LEN:
385                 event_name = "DATA_LEN";
386                 break;
387         default:
388                 dev_warn(&connection->dev, "Unknown I2S Event received: %d\n",
389                          req->event);
390                 return -EINVAL;
391         }
392
393         dev_warn(&connection->dev, "I2S Event received: %d - '%s'\n",
394                  req->event, event_name);
395
396         return 0;
397 }
398
399 static struct gb_protocol gb_i2s_receiver_protocol = {
400         .name                   = GB_AUDIO_DATA_DRIVER_NAME,
401         .id                     = GREYBUS_PROTOCOL_I2S_RECEIVER,
402         .major                  = 0,
403         .minor                  = 1,
404         .connection_init        = gb_i2s_transmitter_connection_init,
405         .connection_exit        = gb_i2s_transmitter_connection_exit,
406         .request_recv           = NULL,
407 };
408
409 static struct gb_protocol gb_i2s_mgmt_protocol = {
410         .name                   = GB_AUDIO_MGMT_DRIVER_NAME,
411         .id                     = GREYBUS_PROTOCOL_I2S_MGMT,
412         .major                  = 0,
413         .minor                  = 1,
414         .connection_init        = gb_i2s_mgmt_connection_init,
415         .connection_exit        = gb_i2s_mgmt_connection_exit,
416         .request_recv           = gb_i2s_mgmt_report_event_recv,
417 };
418
419
420 /*
421  * This is the basic hook get things initialized and registered w/ gb
422  */
423
424 int gb_audio_protocol_init(void)
425 {
426         int err;
427
428         err = gb_protocol_register(&gb_i2s_mgmt_protocol);
429         if (err) {
430                 pr_err("Can't register i2s mgmt protocol driver: %d\n", -err);
431                 return err;
432         }
433
434         err = gb_protocol_register(&gb_i2s_receiver_protocol);
435         if (err) {
436                 pr_err("Can't register Audio protocol driver: %d\n", -err);
437                 goto err_unregister_i2s_mgmt;
438         }
439
440         err = platform_driver_register(&gb_audio_plat_driver);
441         if (err) {
442                 pr_err("Can't register platform driver: %d\n", -err);
443                 goto err_unregister_plat;
444         }
445
446         err = platform_driver_register(&gb_audio_pcm_driver);
447         if (err) {
448                 pr_err("Can't register pcm driver: %d\n", -err);
449                 goto err_unregister_pcm;
450         }
451
452         return 0;
453
454 err_unregister_pcm:
455         platform_driver_unregister(&gb_audio_plat_driver);
456 err_unregister_plat:
457         gb_protocol_deregister(&gb_i2s_receiver_protocol);
458 err_unregister_i2s_mgmt:
459         gb_protocol_deregister(&gb_i2s_mgmt_protocol);
460         return err;
461 }
462
463 void gb_audio_protocol_exit(void)
464 {
465         platform_driver_unregister(&gb_audio_pcm_driver);
466         platform_driver_unregister(&gb_audio_plat_driver);
467         gb_protocol_deregister(&gb_i2s_receiver_protocol);
468         gb_protocol_deregister(&gb_i2s_mgmt_protocol);
469 }