2 * pisound Linux kernel module.
3 * Copyright (C) 2016 Vilniaus Blokas UAB, http://blokas.io/pisound
5 * This program is free software; you can redistribute it and/or
6 * modify it under the terms of the GNU General Public License
7 * as published by the Free Software Foundation; version 2 of the
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
15 * You should have received a copy of the GNU General Public License
16 * along with this program; if not, write to the Free Software
17 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
21 #include <linux/init.h>
22 #include <linux/module.h>
23 #include <linux/platform_device.h>
24 #include <linux/gpio.h>
25 #include <linux/kobject.h>
26 #include <linux/sysfs.h>
27 #include <linux/delay.h>
28 #include <linux/spi/spi.h>
29 #include <linux/interrupt.h>
30 #include <linux/kfifo.h>
32 #include <sound/core.h>
33 #include <sound/pcm.h>
34 #include <sound/pcm_params.h>
35 #include <sound/soc.h>
36 #include <sound/jack.h>
37 #include <sound/rawmidi.h>
38 #include <sound/asequencer.h>
40 static int pisnd_spi_init(struct device
*dev
);
41 static void pisnd_spi_uninit(void);
43 static void pisnd_spi_send(uint8_t val
);
44 static uint8_t pisnd_spi_recv(uint8_t *buffer
, uint8_t length
);
46 typedef void (*pisnd_spi_recv_cb
)(void *data
);
47 static void pisnd_spi_set_callback(pisnd_spi_recv_cb cb
, void *data
);
49 static const char *pisnd_spi_get_serial(void);
50 static const char *pisnd_spi_get_id(void);
51 static const char *pisnd_spi_get_version(void);
53 static int pisnd_midi_init(struct snd_card
*card
);
54 static void pisnd_midi_uninit(void);
56 #define PISOUND_LOG_PREFIX "pisound: "
59 # define printd(...) pr_alert(PISOUND_LOG_PREFIX __VA_ARGS__)
61 # define printd(...) do {} while (0)
64 #define printe(...) pr_err(PISOUND_LOG_PREFIX __VA_ARGS__)
65 #define printi(...) pr_info(PISOUND_LOG_PREFIX __VA_ARGS__)
67 static int pisnd_output_open(struct snd_rawmidi_substream
*substream
)
72 static int pisnd_output_close(struct snd_rawmidi_substream
*substream
)
77 static void pisnd_output_trigger(
78 struct snd_rawmidi_substream
*substream
,
87 while (snd_rawmidi_transmit_peek(substream
, &data
, 1)) {
89 snd_rawmidi_transmit_ack(substream
, 1);
93 static void pisnd_output_drain(struct snd_rawmidi_substream
*substream
)
97 while (snd_rawmidi_transmit_peek(substream
, &data
, 1)) {
100 snd_rawmidi_transmit_ack(substream
, 1);
104 static int pisnd_input_open(struct snd_rawmidi_substream
*substream
)
109 static int pisnd_input_close(struct snd_rawmidi_substream
*substream
)
114 static void pisnd_midi_recv_callback(void *substream
)
119 while ((n
= pisnd_spi_recv(data
, sizeof(data
)))) {
120 int res
= snd_rawmidi_receive(substream
, data
, n
);
122 printd("midi recv 0x%02x, res = %d\n", data
, res
);
126 static void pisnd_input_trigger(struct snd_rawmidi_substream
*substream
, int up
)
129 pisnd_spi_set_callback(pisnd_midi_recv_callback
, substream
);
130 pisnd_midi_recv_callback(substream
);
132 pisnd_spi_set_callback(NULL
, NULL
);
136 static struct snd_rawmidi
*g_rmidi
;
138 static struct snd_rawmidi_ops pisnd_output_ops
= {
139 .open
= pisnd_output_open
,
140 .close
= pisnd_output_close
,
141 .trigger
= pisnd_output_trigger
,
142 .drain
= pisnd_output_drain
,
145 static struct snd_rawmidi_ops pisnd_input_ops
= {
146 .open
= pisnd_input_open
,
147 .close
= pisnd_input_close
,
148 .trigger
= pisnd_input_trigger
,
151 static void pisnd_get_port_info(
152 struct snd_rawmidi
*rmidi
,
154 struct snd_seq_port_info
*seq_port_info
157 seq_port_info
->type
=
158 SNDRV_SEQ_PORT_TYPE_MIDI_GENERIC
|
159 SNDRV_SEQ_PORT_TYPE_HARDWARE
|
160 SNDRV_SEQ_PORT_TYPE_PORT
;
161 seq_port_info
->midi_voices
= 0;
164 static struct snd_rawmidi_global_ops pisnd_global_ops
= {
165 .get_port_info
= pisnd_get_port_info
,
168 static int pisnd_midi_init(struct snd_card
*card
)
170 int err
= snd_rawmidi_new(card
, "pisound MIDI", 0, 1, 1, &g_rmidi
);
173 printe("snd_rawmidi_new failed: %d\n", err
);
177 strcpy(g_rmidi
->name
, "pisound MIDI ");
178 strcat(g_rmidi
->name
, pisnd_spi_get_serial());
180 g_rmidi
->info_flags
=
181 SNDRV_RAWMIDI_INFO_OUTPUT
|
182 SNDRV_RAWMIDI_INFO_INPUT
|
183 SNDRV_RAWMIDI_INFO_DUPLEX
;
185 g_rmidi
->ops
= &pisnd_global_ops
;
187 g_rmidi
->private_data
= (void *)0;
191 SNDRV_RAWMIDI_STREAM_OUTPUT
,
197 SNDRV_RAWMIDI_STREAM_INPUT
,
204 static void pisnd_midi_uninit(void)
208 static void *g_recvData
;
209 static pisnd_spi_recv_cb g_recvCallback
;
211 #define FIFO_SIZE 512
213 static char g_serial_num
[11];
214 static char g_id
[25];
215 static char g_version
[5];
217 DEFINE_KFIFO(spi_fifo_in
, uint8_t, FIFO_SIZE
);
218 DEFINE_KFIFO(spi_fifo_out
, uint8_t, FIFO_SIZE
);
220 static struct gpio_desc
*data_available
;
221 static struct gpio_desc
*spi_reset
;
223 static struct spi_device
*pisnd_spi_device
;
225 static struct workqueue_struct
*pisnd_workqueue
;
226 static struct work_struct pisnd_work_process
;
228 static void pisnd_work_handler(struct work_struct
*work
);
230 static uint16_t spi_transfer16(uint16_t val
);
232 static int pisnd_init_workqueues(void)
234 pisnd_workqueue
= create_singlethread_workqueue("pisnd_workqueue");
235 INIT_WORK(&pisnd_work_process
, pisnd_work_handler
);
240 static void pisnd_uninit_workqueues(void)
242 flush_workqueue(pisnd_workqueue
);
243 destroy_workqueue(pisnd_workqueue
);
245 pisnd_workqueue
= NULL
;
248 static bool pisnd_spi_has_more(void)
250 return gpiod_get_value(data_available
);
257 static void pisnd_schedule_process(enum task_e task
)
259 if (pisnd_spi_device
!= NULL
&&
260 pisnd_workqueue
!= NULL
&&
261 !work_pending(&pisnd_work_process
)
263 printd("schedule: has more = %d\n", pisnd_spi_has_more());
264 if (task
== TASK_PROCESS
)
265 queue_work(pisnd_workqueue
, &pisnd_work_process
);
269 static irqreturn_t
data_available_interrupt_handler(int irq
, void *dev_id
)
271 if (irq
== gpiod_to_irq(data_available
) && pisnd_spi_has_more()) {
272 printd("schedule from irq\n");
273 pisnd_schedule_process(TASK_PROCESS
);
279 static DEFINE_SPINLOCK(spilock
);
280 static unsigned long spilockflags
;
282 static uint16_t spi_transfer16(uint16_t val
)
285 struct spi_transfer transfer
;
286 struct spi_message msg
;
290 if (!pisnd_spi_device
) {
291 printe("pisnd_spi_device null, returning\n");
295 spi_message_init(&msg
);
297 memset(&transfer
, 0, sizeof(transfer
));
298 memset(&rxbuf
, 0, sizeof(rxbuf
));
301 txbuf
[1] = val
& 0xff;
303 transfer
.tx_buf
= &txbuf
;
304 transfer
.rx_buf
= &rxbuf
;
305 transfer
.len
= sizeof(txbuf
);
306 transfer
.speed_hz
= 125000;
307 transfer
.delay_usecs
= 100;
308 spi_message_add_tail(&transfer
, &msg
);
310 spin_lock_irqsave(&spilock
, spilockflags
);
311 err
= spi_sync(pisnd_spi_device
, &msg
);
312 spin_unlock_irqrestore(&spilock
, spilockflags
);
315 printe("spi_sync error %d\n", err
);
319 printd("received: %02x%02x\n", rxbuf
[0], rxbuf
[1]);
320 printd("hasMore %d\n", pisnd_spi_has_more());
322 return (rxbuf
[0] << 8) | rxbuf
[1];
325 static int spi_read_bytes(char *dst
, size_t length
, uint8_t *bytesRead
)
331 memset(dst
, 0, length
);
334 rx
= spi_transfer16(0);
343 for (i
= 0; i
< size
; ++i
) {
344 rx
= spi_transfer16(0);
356 static int spi_device_match(struct device
*dev
, void *data
)
358 struct spi_device
*spi
= container_of(dev
, struct spi_device
, dev
);
360 printd(" %s %s %dkHz %d bits mode=0x%02X\n",
361 spi
->modalias
, dev_name(dev
), spi
->max_speed_hz
/1000,
362 spi
->bits_per_word
, spi
->mode
);
364 if (strcmp("pisound-spi", spi
->modalias
) == 0) {
365 printi("\tFound!\n");
369 printe("\tNot found!\n");
373 static struct spi_device
*pisnd_spi_find_device(void)
377 printi("Searching for spi device...\n");
378 dev
= bus_find_device(&spi_bus_type
, NULL
, NULL
, spi_device_match
);
380 return container_of(dev
, struct spi_device
, dev
);
385 static void pisnd_work_handler(struct work_struct
*work
)
391 if (work
== &pisnd_work_process
) {
392 if (pisnd_spi_device
== NULL
)
399 if (kfifo_get(&spi_fifo_out
, &val
))
402 rx
= spi_transfer16(tx
);
405 kfifo_put(&spi_fifo_in
, rx
& 0xff);
406 if (kfifo_len(&spi_fifo_in
) > 16
408 g_recvCallback(g_recvData
);
411 || !kfifo_is_empty(&spi_fifo_out
)
412 || pisnd_spi_has_more()
415 if (!kfifo_is_empty(&spi_fifo_in
) && g_recvCallback
)
416 g_recvCallback(g_recvData
);
420 static int pisnd_spi_gpio_init(struct device
*dev
)
422 spi_reset
= gpiod_get_index(dev
, "reset", 1, GPIOD_ASIS
);
423 data_available
= gpiod_get_index(dev
, "data_available", 0, GPIOD_ASIS
);
425 gpiod_direction_output(spi_reset
, 1);
426 gpiod_direction_input(data_available
);
428 /* Reset the slave. */
429 gpiod_set_value(spi_reset
, false);
431 gpiod_set_value(spi_reset
, true);
433 /* Give time for spi slave to start. */
439 static void pisnd_spi_gpio_uninit(void)
441 gpiod_set_value(spi_reset
, false);
442 gpiod_put(spi_reset
);
445 gpiod_put(data_available
);
446 data_available
= NULL
;
449 static int pisnd_spi_gpio_irq_init(struct device
*dev
)
452 gpiod_to_irq(data_available
),
453 data_available_interrupt_handler
,
454 IRQF_TIMER
| IRQF_TRIGGER_RISING
,
455 "data_available_int",
460 static void pisnd_spi_gpio_irq_uninit(void)
462 free_irq(gpiod_to_irq(data_available
), NULL
);
465 static int spi_read_info(void)
476 memset(g_serial_num
, 0, sizeof(g_serial_num
));
477 memset(g_version
, 0, sizeof(g_version
));
478 memset(g_id
, 0, sizeof(g_id
));
480 tmp
= spi_transfer16(0);
487 for (i
= 0; i
< count
; ++i
) {
488 memset(buffer
, 0, sizeof(buffer
));
489 ret
= spi_read_bytes(buffer
, sizeof(buffer
)-1, &n
);
508 if (n
>= sizeof(g_serial_num
))
511 memcpy(g_serial_num
, buffer
, sizeof(g_serial_num
));
515 if (n
>= sizeof(g_id
))
519 for (j
= 0; j
< n
; ++j
)
520 p
+= sprintf(p
, "%02x", buffer
[j
]);
531 static int pisnd_spi_init(struct device
*dev
)
534 struct spi_device
*spi
;
536 memset(g_serial_num
, 0, sizeof(g_serial_num
));
537 memset(g_id
, 0, sizeof(g_id
));
538 memset(g_version
, 0, sizeof(g_version
));
540 spi
= pisnd_spi_find_device();
543 printd("initializing spi!\n");
544 pisnd_spi_device
= spi
;
545 ret
= spi_setup(pisnd_spi_device
);
547 printe("SPI device not found, deferring!\n");
548 return -EPROBE_DEFER
;
551 ret
= pisnd_spi_gpio_init(dev
);
554 printe("SPI GPIO init failed: %d\n", ret
);
555 spi_dev_put(pisnd_spi_device
);
556 pisnd_spi_device
= NULL
;
557 pisnd_spi_gpio_uninit();
561 ret
= spi_read_info();
564 printe("Reading card info failed: %d\n", ret
);
565 spi_dev_put(pisnd_spi_device
);
566 pisnd_spi_device
= NULL
;
567 pisnd_spi_gpio_uninit();
571 /* Flash the LEDs. */
572 spi_transfer16(0xf000);
574 ret
= pisnd_spi_gpio_irq_init(dev
);
576 printe("SPI irq request failed: %d\n", ret
);
577 spi_dev_put(pisnd_spi_device
);
578 pisnd_spi_device
= NULL
;
579 pisnd_spi_gpio_irq_uninit();
580 pisnd_spi_gpio_uninit();
583 ret
= pisnd_init_workqueues();
585 printe("Workqueue initialization failed: %d\n", ret
);
586 spi_dev_put(pisnd_spi_device
);
587 pisnd_spi_device
= NULL
;
588 pisnd_spi_gpio_irq_uninit();
589 pisnd_spi_gpio_uninit();
590 pisnd_uninit_workqueues();
594 if (pisnd_spi_has_more()) {
595 printd("data is available, scheduling from init\n");
596 pisnd_schedule_process(TASK_PROCESS
);
602 static void pisnd_spi_uninit(void)
604 pisnd_uninit_workqueues();
606 spi_dev_put(pisnd_spi_device
);
607 pisnd_spi_device
= NULL
;
609 pisnd_spi_gpio_irq_uninit();
610 pisnd_spi_gpio_uninit();
613 static void pisnd_spi_send(uint8_t val
)
615 kfifo_put(&spi_fifo_out
, val
);
616 printd("schedule from spi_send\n");
617 pisnd_schedule_process(TASK_PROCESS
);
620 static uint8_t pisnd_spi_recv(uint8_t *buffer
, uint8_t length
)
622 return kfifo_out(&spi_fifo_in
, buffer
, length
);
625 static void pisnd_spi_set_callback(pisnd_spi_recv_cb cb
, void *data
)
631 static const char *pisnd_spi_get_serial(void)
633 if (strlen(g_serial_num
))
639 static const char *pisnd_spi_get_id(void)
647 static const char *pisnd_spi_get_version(void)
649 if (strlen(g_version
))
655 static const struct of_device_id pisound_of_match
[] = {
656 { .compatible
= "blokaslabs,pisound", },
657 { .compatible
= "blokaslabs,pisound-spi", },
661 static struct gpio_desc
*osr0
, *osr1
, *osr2
;
662 static struct gpio_desc
*reset
;
663 static struct gpio_desc
*button
;
665 static int pisnd_hw_params(
666 struct snd_pcm_substream
*substream
,
667 struct snd_pcm_hw_params
*params
670 printd("rate = %d\n", params_rate(params
));
671 printd("ch = %d\n", params_channels(params
));
672 printd("bits = %u\n",
673 snd_pcm_format_physical_width(params_format(params
)));
674 printd("format = %d\n", params_format(params
));
676 gpiod_set_value(reset
, false);
678 switch (params_rate(params
)) {
680 gpiod_set_value(osr0
, true);
681 gpiod_set_value(osr1
, false);
682 gpiod_set_value(osr2
, false);
685 gpiod_set_value(osr0
, true);
686 gpiod_set_value(osr1
, true);
687 gpiod_set_value(osr2
, false);
690 gpiod_set_value(osr0
, true);
691 gpiod_set_value(osr1
, true);
692 gpiod_set_value(osr2
, true);
695 printe("Unsupported rate %u!\n", params_rate(params
));
699 gpiod_set_value(reset
, true);
704 static unsigned int rates
[3] = {
708 static struct snd_pcm_hw_constraint_list constraints_rates
= {
709 .count
= ARRAY_SIZE(rates
),
714 static unsigned int sample_bits
[] = {
718 static struct snd_pcm_hw_constraint_list constraints_sample_bits
= {
719 .count
= ARRAY_SIZE(sample_bits
),
724 static int pisnd_startup(struct snd_pcm_substream
*substream
)
726 int err
= snd_pcm_hw_constraint_list(
729 SNDRV_PCM_HW_PARAM_RATE
,
736 err
= snd_pcm_hw_constraint_list(
739 SNDRV_PCM_HW_PARAM_SAMPLE_BITS
,
740 &constraints_sample_bits
749 static struct snd_soc_ops pisnd_ops
= {
750 .startup
= pisnd_startup
,
751 .hw_params
= pisnd_hw_params
,
754 static struct snd_soc_dai_link pisnd_dai
[] = {
757 .stream_name
= "pisound",
758 .cpu_dai_name
= "bcm2708-i2s.0",
759 .codec_dai_name
= "snd-soc-dummy-dai",
760 .platform_name
= "bcm2708-i2s.0",
761 .codec_name
= "snd-soc-dummy",
764 SND_SOC_DAIFMT_NB_NF
|
765 SND_SOC_DAIFMT_CBM_CFM
,
770 static int pisnd_card_probe(struct snd_soc_card
*card
)
772 int err
= pisnd_midi_init(card
->snd_card
);
775 printe("pisnd_midi_init failed: %d\n", err
);
780 static int pisnd_card_remove(struct snd_soc_card
*card
)
786 static struct snd_soc_card pisnd_card
= {
788 .owner
= THIS_MODULE
,
789 .dai_link
= pisnd_dai
,
790 .num_links
= ARRAY_SIZE(pisnd_dai
),
791 .probe
= pisnd_card_probe
,
792 .remove
= pisnd_card_remove
,
795 static int pisnd_init_gpio(struct device
*dev
)
797 osr0
= gpiod_get_index(dev
, "osr", 0, GPIOD_ASIS
);
798 osr1
= gpiod_get_index(dev
, "osr", 1, GPIOD_ASIS
);
799 osr2
= gpiod_get_index(dev
, "osr", 2, GPIOD_ASIS
);
801 reset
= gpiod_get_index(dev
, "reset", 0, GPIOD_ASIS
);
803 button
= gpiod_get_index(dev
, "button", 0, GPIOD_ASIS
);
805 gpiod_direction_output(osr0
, 1);
806 gpiod_direction_output(osr1
, 1);
807 gpiod_direction_output(osr2
, 1);
808 gpiod_direction_output(reset
, 1);
810 gpiod_set_value(reset
, false);
811 gpiod_set_value(osr0
, true);
812 gpiod_set_value(osr1
, false);
813 gpiod_set_value(osr2
, false);
814 gpiod_set_value(reset
, true);
816 gpiod_export(button
, false);
821 static int pisnd_uninit_gpio(void)
825 struct gpio_desc
**gpios
[] = {
826 &osr0
, &osr1
, &osr2
, &reset
, &button
,
829 gpiod_unexport(button
);
831 for (i
= 0; i
< ARRAY_SIZE(gpios
); ++i
) {
832 if (*gpios
[i
] == NULL
) {
833 printd("weird, GPIO[%d] is NULL already\n", i
);
837 gpiod_put(*gpios
[i
]);
844 static struct kobject
*pisnd_kobj
;
846 static ssize_t
pisnd_serial_show(
847 struct kobject
*kobj
,
848 struct kobj_attribute
*attr
,
852 return sprintf(buf
, "%s\n", pisnd_spi_get_serial());
855 static ssize_t
pisnd_id_show(
856 struct kobject
*kobj
,
857 struct kobj_attribute
*attr
,
861 return sprintf(buf
, "%s\n", pisnd_spi_get_id());
864 static ssize_t
pisnd_version_show(
865 struct kobject
*kobj
,
866 struct kobj_attribute
*attr
,
870 return sprintf(buf
, "%s\n", pisnd_spi_get_version());
873 static struct kobj_attribute pisnd_serial_attribute
=
874 __ATTR(serial
, 0644, pisnd_serial_show
, NULL
);
875 static struct kobj_attribute pisnd_id_attribute
=
876 __ATTR(id
, 0644, pisnd_id_show
, NULL
);
877 static struct kobj_attribute pisnd_version_attribute
=
878 __ATTR(version
, 0644, pisnd_version_show
, NULL
);
880 static struct attribute
*attrs
[] = {
881 &pisnd_serial_attribute
.attr
,
882 &pisnd_id_attribute
.attr
,
883 &pisnd_version_attribute
.attr
,
887 static struct attribute_group attr_group
= { .attrs
= attrs
};
889 static int pisnd_probe(struct platform_device
*pdev
)
894 ret
= pisnd_spi_init(&pdev
->dev
);
896 printe("pisnd_spi_init failed: %d\n", ret
);
900 printi("Detected pisound card:\n");
901 printi("\tSerial: %s\n", pisnd_spi_get_serial());
902 printi("\tVersion: %s\n", pisnd_spi_get_version());
903 printi("\tId: %s\n", pisnd_spi_get_id());
905 pisnd_kobj
= kobject_create_and_add("pisound", kernel_kobj
);
911 ret
= sysfs_create_group(pisnd_kobj
, &attr_group
);
914 kobject_put(pisnd_kobj
);
918 pisnd_init_gpio(&pdev
->dev
);
919 pisnd_card
.dev
= &pdev
->dev
;
921 if (pdev
->dev
.of_node
) {
922 struct device_node
*i2s_node
;
924 i2s_node
= of_parse_phandle(
930 for (i
= 0; i
< pisnd_card
.num_links
; ++i
) {
931 struct snd_soc_dai_link
*dai
= &pisnd_dai
[i
];
934 dai
->cpu_dai_name
= NULL
;
935 dai
->cpu_of_node
= i2s_node
;
936 dai
->platform_name
= NULL
;
937 dai
->platform_of_node
= i2s_node
;
938 dai
->stream_name
= pisnd_spi_get_serial();
943 ret
= snd_soc_register_card(&pisnd_card
);
946 printe("snd_soc_register_card() failed: %d\n", ret
);
948 kobject_put(pisnd_kobj
);
955 static int pisnd_remove(struct platform_device
*pdev
)
957 printi("Unloading.\n");
960 kobject_put(pisnd_kobj
);
967 gpiod_set_value(reset
, false);
970 return snd_soc_unregister_card(&pisnd_card
);
973 MODULE_DEVICE_TABLE(of
, pisound_of_match
);
975 static struct platform_driver pisnd_driver
= {
977 .name
= "snd-rpi-pisound",
978 .owner
= THIS_MODULE
,
979 .of_match_table
= pisound_of_match
,
981 .probe
= pisnd_probe
,
982 .remove
= pisnd_remove
,
985 module_platform_driver(pisnd_driver
);
987 MODULE_AUTHOR("Giedrius Trainavicius <giedrius@blokas.io>");
988 MODULE_DESCRIPTION("ASoC Driver for pisound, http://blokas.io/pisound");
989 MODULE_LICENSE("GPL v2");