bcm27xx: update patches from RPi foundation
[oweals/openwrt.git] / target / linux / bcm27xx / patches-5.4 / 950-0071-Support-for-Blokas-Labs-pisound-board.patch
1 From ed992c4a8392b757e54b60bf2390015b72e3e947 Mon Sep 17 00:00:00 2001
2 From: gtrainavicius <gtrainavicius@users.noreply.github.com>
3 Date: Sun, 23 Oct 2016 12:06:53 +0300
4 Subject: [PATCH] Support for Blokas Labs pisound board
5
6 Pisound dynamic overlay (#1760)
7
8 Restructuring pisound-overlay.dts, so it can be loaded and unloaded dynamically using dtoverlay.
9
10 Print a logline when the kernel module is removed.
11
12 pisound improvements:
13
14 * Added a writable sysfs object to enable scripts / user space software
15 to blink MIDI activity LEDs for variable duration.
16 * Improved hw_param constraints setting.
17 * Added compatibility with S16_LE sample format.
18 * Exposed some simple placeholder volume controls, so the card appears
19 in volumealsa widget.
20
21 Add missing SND_PISOUND selects dependency to SND_RAWMIDI
22
23 Without it the Pisound module fails to compile.
24 See https://github.com/raspberrypi/linux/issues/2366
25
26 Updates for Pisound module code:
27
28         * Merged 'Fix a warning in DEBUG builds' (1c8b82b).
29         * Updating some strings and copyright information.
30         * Fix for handling high load of MIDI input and output.
31         * Use dual rate oversampling ratio for 96kHz instead of single
32           rate one.
33
34 Signed-off-by: Giedrius Trainavicius <giedrius@blokas.io>
35
36 Fixing memset call in pisound.c
37
38 Signed-off-by: Giedrius Trainavicius <giedrius@blokas.io>
39
40 Fix for Pisound's MIDI Input getting blocked for a while in rare cases.
41
42 There was a possible race condition which could lead to Input's FIFO queue
43 to be underflown, causing high amount of processing in the worker thread for
44 some period of time.
45
46 Signed-off-by: Giedrius Trainavicius <giedrius@blokas.io>
47
48 Fix for Pisound kernel module in Real Time kernel configuration.
49
50 When handler of data_available interrupt is fired, queue_work ends up
51 getting called and it can block on a spin lock which is not allowed in
52 interrupt context. The fix was to run the handler from a thread context
53 instead.
54
55 Pisound: Remove spinlock usage around spi_sync
56
57 ASoC: pisound: use modern dai_link style
58
59 Signed-off-by: Hui Wang <hui.wang@canonical.com>
60
61 ASoC: pisound: fix the parameter for spi_device_match
62
63 Signed-off-by: Hui Wang <hui.wang@canonical.com>
64 ---
65  .../devicetree/bindings/vendor-prefixes.txt   |  463 +++++++
66  .../devicetree/bindings/vendor-prefixes.yaml  |    2 +
67  sound/soc/bcm/pisound.c                       | 1201 +++++++++++++++++
68  3 files changed, 1666 insertions(+)
69  create mode 100644 Documentation/devicetree/bindings/vendor-prefixes.txt
70  create mode 100644 sound/soc/bcm/pisound.c
71
72 --- /dev/null
73 +++ b/Documentation/devicetree/bindings/vendor-prefixes.txt
74 @@ -0,0 +1,463 @@
75 +Device tree binding vendor prefix registry.  Keep list in alphabetical order.
76 +
77 +This isn't an exhaustive list, but you should add new prefixes to it before
78 +using them to avoid name-space collisions.
79 +
80 +abilis Abilis Systems
81 +abracon        Abracon Corporation
82 +actions        Actions Semiconductor Co., Ltd.
83 +active-semi    Active-Semi International Inc
84 +ad     Avionic Design GmbH
85 +adafruit       Adafruit Industries, LLC
86 +adapteva       Adapteva, Inc.
87 +adaptrum       Adaptrum, Inc.
88 +adh    AD Holdings Plc.
89 +adi    Analog Devices, Inc.
90 +advantech      Advantech Corporation
91 +aeroflexgaisler        Aeroflex Gaisler AB
92 +al     Annapurna Labs
93 +allo   Allo.com
94 +allwinner      Allwinner Technology Co., Ltd.
95 +alphascale     AlphaScale Integrated Circuits Systems, Inc.
96 +altr   Altera Corp.
97 +amarula        Amarula Solutions
98 +amazon Amazon.com, Inc.
99 +amcc   Applied Micro Circuits Corporation (APM, formally AMCC)
100 +amd    Advanced Micro Devices (AMD), Inc.
101 +amediatech     Shenzhen Amediatech Technology Co., Ltd
102 +amlogic        Amlogic, Inc.
103 +ampire Ampire Co., Ltd.
104 +ams    AMS AG
105 +amstaos        AMS-Taos Inc.
106 +analogix       Analogix Semiconductor, Inc.
107 +andestech      Andes Technology Corporation
108 +apm    Applied Micro Circuits Corporation (APM)
109 +aptina Aptina Imaging
110 +arasan Arasan Chip Systems
111 +archermind ArcherMind Technology (Nanjing) Co., Ltd.
112 +arctic Arctic Sand
113 +aries  Aries Embedded GmbH
114 +arm    ARM Ltd.
115 +armadeus       ARMadeus Systems SARL
116 +arrow  Arrow Electronics
117 +artesyn        Artesyn Embedded Technologies Inc.
118 +asahi-kasei    Asahi Kasei Corp.
119 +aspeed ASPEED Technology Inc.
120 +asus   AsusTek Computer Inc.
121 +atlas  Atlas Scientific LLC
122 +atmel  Atmel Corporation
123 +auo    AU Optronics Corporation
124 +auvidea Auvidea GmbH
125 +avago  Avago Technologies
126 +avia   avia semiconductor
127 +avic   Shanghai AVIC Optoelectronics Co., Ltd.
128 +avnet  Avnet, Inc.
129 +axentia        Axentia Technologies AB
130 +axis   Axis Communications AB
131 +bananapi BIPAI KEJI LIMITED
132 +bhf    Beckhoff Automation GmbH & Co. KG
133 +bitmain        Bitmain Technologies
134 +blokaslabs     Vilniaus Blokas UAB
135 +boe    BOE Technology Group Co., Ltd.
136 +bosch  Bosch Sensortec GmbH
137 +boundary       Boundary Devices Inc.
138 +brcm   Broadcom Corporation
139 +buffalo        Buffalo, Inc.
140 +bticino Bticino International
141 +calxeda        Calxeda
142 +capella        Capella Microsystems, Inc
143 +cascoda        Cascoda, Ltd.
144 +catalyst       Catalyst Semiconductor, Inc.
145 +cavium Cavium, Inc.
146 +cdns   Cadence Design Systems Inc.
147 +cdtech CDTech(H.K.) Electronics Limited
148 +ceva   Ceva, Inc.
149 +chipidea       Chipidea, Inc
150 +chipone                ChipOne
151 +chipspark      ChipSPARK
152 +chrp   Common Hardware Reference Platform
153 +chunghwa       Chunghwa Picture Tubes Ltd.
154 +ciaa   Computadora Industrial Abierta Argentina
155 +cirrus Cirrus Logic, Inc.
156 +cloudengines   Cloud Engines, Inc.
157 +cnm    Chips&Media, Inc.
158 +cnxt   Conexant Systems, Inc.
159 +compulab       CompuLab Ltd.
160 +cortina        Cortina Systems, Inc.
161 +cosmic Cosmic Circuits
162 +crane  Crane Connectivity Solutions
163 +creative       Creative Technology Ltd
164 +crystalfontz   Crystalfontz America, Inc.
165 +csky   Hangzhou C-SKY Microsystems Co., Ltd
166 +cubietech      Cubietech, Ltd.
167 +cypress        Cypress Semiconductor Corporation
168 +cznic  CZ.NIC, z.s.p.o.
169 +dallas Maxim Integrated Products (formerly Dallas Semiconductor)
170 +dataimage      DataImage, Inc.
171 +davicom        DAVICOM Semiconductor, Inc.
172 +delta  Delta Electronics, Inc.
173 +denx   Denx Software Engineering
174 +devantech      Devantech, Ltd.
175 +dh     DH electronics GmbH
176 +digi   Digi International Inc.
177 +digilent       Diglent, Inc.
178 +dioo   Dioo Microcircuit Co., Ltd
179 +dlc    DLC Display Co., Ltd.
180 +dlg    Dialog Semiconductor
181 +dlink  D-Link Corporation
182 +dmo    Data Modul AG
183 +domintech      Domintech Co., Ltd.
184 +dongwoon       Dongwoon Anatech
185 +dptechnics     DPTechnics
186 +dragino        Dragino Technology Co., Limited
187 +ea     Embedded Artists AB
188 +ebs-systart EBS-SYSTART GmbH
189 +ebv    EBV Elektronik
190 +eckelmann      Eckelmann AG
191 +edt    Emerging Display Technologies
192 +eeti   eGalax_eMPIA Technology Inc
193 +elan   Elan Microelectronic Corp.
194 +elgin  Elgin S/A.
195 +embest Shenzhen Embest Technology Co., Ltd.
196 +emlid  Emlid, Ltd.
197 +emmicro        EM Microelectronic
198 +emtrion        emtrion GmbH
199 +endless        Endless Mobile, Inc.
200 +energymicro    Silicon Laboratories (formerly Energy Micro AS)
201 +engicam        Engicam S.r.l.
202 +epcos  EPCOS AG
203 +epfl   Ecole Polytechnique Fédérale de Lausanne
204 +epson  Seiko Epson Corp.
205 +est    ESTeem Wireless Modems
206 +ettus  NI Ettus Research
207 +eukrea  Eukréa Electromatique
208 +everest        Everest Semiconductor Co. Ltd.
209 +everspin       Everspin Technologies, Inc.
210 +exar   Exar Corporation
211 +excito Excito
212 +ezchip EZchip Semiconductor
213 +facebook       Facebook
214 +fairphone      Fairphone B.V.
215 +faraday        Faraday Technology Corporation
216 +fastrax        Fastrax Oy
217 +fcs    Fairchild Semiconductor
218 +feiyang        Shenzhen Fly Young Technology Co.,LTD.
219 +firefly        Firefly
220 +focaltech      FocalTech Systems Co.,Ltd
221 +friendlyarm    Guangzhou FriendlyARM Computer Tech Co., Ltd
222 +fsl    Freescale Semiconductor
223 +fujitsu        Fujitsu Ltd.
224 +gateworks      Gateworks Corporation
225 +gcw Game Consoles Worldwide
226 +ge     General Electric Company
227 +geekbuying     GeekBuying
228 +gef    GE Fanuc Intelligent Platforms Embedded Systems, Inc.
229 +GEFanuc        GE Fanuc Intelligent Platforms Embedded Systems, Inc.
230 +geniatech      Geniatech, Inc.
231 +giantec        Giantec Semiconductor, Inc.
232 +giantplus      Giantplus Technology Co., Ltd.
233 +globalscale    Globalscale Technologies, Inc.
234 +globaltop      GlobalTop Technology, Inc.
235 +gmt    Global Mixed-mode Technology, Inc.
236 +goodix Shenzhen Huiding Technology Co., Ltd.
237 +google Google, Inc.
238 +grinn  Grinn
239 +grmn   Garmin Limited
240 +gumstix        Gumstix, Inc.
241 +gw     Gateworks Corporation
242 +hannstar       HannStar Display Corporation
243 +haoyu  Haoyu Microelectronic Co. Ltd.
244 +hardkernel     Hardkernel Co., Ltd
245 +hideep HiDeep Inc.
246 +himax  Himax Technologies, Inc.
247 +hisilicon      Hisilicon Limited.
248 +hit    Hitachi Ltd.
249 +hitex  Hitex Development Tools
250 +holt   Holt Integrated Circuits, Inc.
251 +honeywell      Honeywell
252 +hp     Hewlett Packard
253 +holtek Holtek Semiconductor, Inc.
254 +hwacom HwaCom Systems Inc.
255 +i2se   I2SE GmbH
256 +ibm    International Business Machines (IBM)
257 +icplus IC Plus Corp.
258 +idt    Integrated Device Technologies, Inc.
259 +ifi    Ingenieurburo Fur Ic-Technologie (I/F/I)
260 +ilitek ILI Technology Corporation (ILITEK)
261 +img    Imagination Technologies Ltd.
262 +infineon Infineon Technologies
263 +inforce        Inforce Computing
264 +ingenic        Ingenic Semiconductor
265 +innolux        Innolux Corporation
266 +inside-secure  INSIDE Secure
267 +intel  Intel Corporation
268 +intercontrol   Inter Control Group
269 +invensense     InvenSense Inc.
270 +inversepath    Inverse Path
271 +iom    Iomega Corporation
272 +isee   ISEE 2007 S.L.
273 +isil   Intersil
274 +issi   Integrated Silicon Solutions Inc.
275 +itead  ITEAD Intelligent Systems Co.Ltd
276 +iwave  iWave Systems Technologies Pvt. Ltd.
277 +jdi    Japan Display Inc.
278 +jedec  JEDEC Solid State Technology Association
279 +jianda Jiandangjing Technology Co., Ltd.
280 +karo   Ka-Ro electronics GmbH
281 +keithkoep      Keith & Koep GmbH
282 +keymile        Keymile GmbH
283 +khadas Khadas
284 +kiebackpeter    Kieback & Peter GmbH
285 +kinetic Kinetic Technologies
286 +kingdisplay    King & Display Technology Co., Ltd.
287 +kingnovel      Kingnovel Technology Co., Ltd.
288 +koe    Kaohsiung Opto-Electronics Inc.
289 +kosagi Sutajio Ko-Usagi PTE Ltd.
290 +kyo    Kyocera Corporation
291 +lacie  LaCie
292 +laird  Laird PLC
293 +lantiq Lantiq Semiconductor
294 +lattice        Lattice Semiconductor
295 +lego   LEGO Systems A/S
296 +lemaker        Shenzhen LeMaker Technology Co., Ltd.
297 +lenovo Lenovo Group Ltd.
298 +lg     LG Corporation
299 +libretech      Shenzhen Libre Technology Co., Ltd
300 +licheepi       Lichee Pi
301 +linaro Linaro Limited
302 +linksys        Belkin International, Inc. (Linksys)
303 +linux  Linux-specific binding
304 +linx   Linx Technologies
305 +lltc   Linear Technology Corporation
306 +logicpd        Logic PD, Inc.
307 +lsi    LSI Corp. (LSI Logic)
308 +lwn    Liebherr-Werk Nenzing GmbH
309 +macnica        Macnica Americas
310 +marvell        Marvell Technology Group Ltd.
311 +maxim  Maxim Integrated Products
312 +mbvl   Mobiveil Inc.
313 +mcube  mCube
314 +meas   Measurement Specialties
315 +mediatek       MediaTek Inc.
316 +megachips      MegaChips
317 +mele   Shenzhen MeLE Digital Technology Ltd.
318 +melexis        Melexis N.V.
319 +melfas MELFAS Inc.
320 +mellanox       Mellanox Technologies
321 +memsic MEMSIC Inc.
322 +merrii Merrii Technology Co., Ltd.
323 +micrel Micrel Inc.
324 +microchip      Microchip Technology Inc.
325 +microcrystal   Micro Crystal AG
326 +micron Micron Technology Inc.
327 +mikroe         MikroElektronika d.o.o.
328 +minix  MINIX Technology Ltd.
329 +miramems       MiraMEMS Sensing Technology Co., Ltd.
330 +mitsubishi     Mitsubishi Electric Corporation
331 +mosaixtech     Mosaix Technologies, Inc.
332 +motorola       Motorola, Inc.
333 +moxa   Moxa Inc.
334 +mpl    MPL AG
335 +mqmaker        mqmaker Inc.
336 +mscc   Microsemi Corporation
337 +msi    Micro-Star International Co. Ltd.
338 +mti    Imagination Technologies Ltd. (formerly MIPS Technologies Inc.)
339 +multi-inno     Multi-Inno Technology Co.,Ltd
340 +mundoreader    Mundo Reader S.L.
341 +murata Murata Manufacturing Co., Ltd.
342 +mxicy  Macronix International Co., Ltd.
343 +myir   MYIR Tech Limited
344 +national       National Semiconductor
345 +nec    NEC LCD Technologies, Ltd.
346 +neonode                Neonode Inc.
347 +netgear        NETGEAR
348 +netlogic       Broadcom Corporation (formerly NetLogic Microsystems)
349 +netron-dy      Netron DY
350 +netxeon                Shenzhen Netxeon Technology CO., LTD
351 +nexbox Nexbox
352 +nextthing      Next Thing Co.
353 +newhaven       Newhaven Display International
354 +ni     National Instruments
355 +nintendo       Nintendo
356 +nlt    NLT Technologies, Ltd.
357 +nokia  Nokia
358 +nordic Nordic Semiconductor
359 +novtech NovTech, Inc.
360 +nutsboard      NutsBoard
361 +nuvoton        Nuvoton Technology Corporation
362 +nvd    New Vision Display
363 +nvidia NVIDIA
364 +nxp    NXP Semiconductors
365 +okaya  Okaya Electric America, Inc.
366 +oki    Oki Electric Industry Co., Ltd.
367 +olimex OLIMEX Ltd.
368 +olpc   One Laptop Per Child
369 +onion  Onion Corporation
370 +onnn   ON Semiconductor Corp.
371 +ontat  On Tat Industrial Company
372 +opalkelly      Opal Kelly Incorporated
373 +opencores      OpenCores.org
374 +openrisc       OpenRISC.io
375 +option Option NV
376 +oranth Shenzhen Oranth Technology Co., Ltd.
377 +ORCL   Oracle Corporation
378 +orisetech      Orise Technology
379 +ortustech      Ortus Technology Co., Ltd.
380 +ovti   OmniVision Technologies
381 +oxsemi Oxford Semiconductor, Ltd.
382 +panasonic      Panasonic Corporation
383 +parade Parade Technologies Inc.
384 +pda    Precision Design Associates, Inc.
385 +pericom        Pericom Technology Inc.
386 +pervasive      Pervasive Displays, Inc.
387 +phicomm PHICOMM Co., Ltd.
388 +phytec PHYTEC Messtechnik GmbH
389 +picochip       Picochip Ltd
390 +pine64 Pine64
391 +pixcir  PIXCIR MICROELECTRONICS Co., Ltd
392 +plantower Plantower Co., Ltd
393 +plathome       Plat'Home Co., Ltd.
394 +plda   PLDA
395 +plx    Broadcom Corporation (formerly PLX Technology)
396 +pni    PNI Sensor Corporation
397 +portwell       Portwell Inc.
398 +poslab Poslab Technology Co., Ltd.
399 +powervr        PowerVR (deprecated, use img)
400 +probox2        PROBOX2 (by W2COMP Co., Ltd.)
401 +pulsedlight    PulsedLight, Inc
402 +qca    Qualcomm Atheros, Inc.
403 +qcom   Qualcomm Technologies, Inc
404 +qemu   QEMU, a generic and open source machine emulator and virtualizer
405 +qi     Qi Hardware
406 +qiaodian       QiaoDian XianShi Corporation
407 +qnap   QNAP Systems, Inc.
408 +radxa  Radxa
409 +raidsonic      RaidSonic Technology GmbH
410 +ralink Mediatek/Ralink Technology Corp.
411 +ramtron        Ramtron International
412 +raspberrypi    Raspberry Pi Foundation
413 +raydium        Raydium Semiconductor Corp.
414 +rda    Unisoc Communications, Inc.
415 +realtek Realtek Semiconductor Corp.
416 +renesas        Renesas Electronics Corporation
417 +richtek        Richtek Technology Corporation
418 +ricoh  Ricoh Co. Ltd.
419 +rikomagic      Rikomagic Tech Corp. Ltd
420 +riscv  RISC-V Foundation
421 +rockchip       Fuzhou Rockchip Electronics Co., Ltd
422 +rohm   ROHM Semiconductor Co., Ltd
423 +roofull        Shenzhen Roofull Technology Co, Ltd
424 +samsung        Samsung Semiconductor
425 +samtec Samtec/Softing company
426 +sancloud       Sancloud Ltd
427 +sandisk        Sandisk Corporation
428 +sbs    Smart Battery System
429 +schindler      Schindler
430 +seagate        Seagate Technology PLC
431 +semtech        Semtech Corporation
432 +sensirion      Sensirion AG
433 +sff    Small Form Factor Committee
434 +sgd    Solomon Goldentek Display Corporation
435 +sgx    SGX Sensortech
436 +sharp  Sharp Corporation
437 +shimafuji      Shimafuji Electric, Inc.
438 +si-en  Si-En Technology Ltd.
439 +sifive SiFive, Inc.
440 +sigma  Sigma Designs, Inc.
441 +sii    Seiko Instruments, Inc.
442 +sil    Silicon Image
443 +silabs Silicon Laboratories
444 +silead Silead Inc.
445 +silergy        Silergy Corp.
446 +siliconmitus   Silicon Mitus, Inc.
447 +simtek
448 +sirf   SiRF Technology, Inc.
449 +sis    Silicon Integrated Systems Corp.
450 +sitronix       Sitronix Technology Corporation
451 +skyworks       Skyworks Solutions, Inc.
452 +smsc   Standard Microsystems Corporation
453 +snps   Synopsys, Inc.
454 +socionext      Socionext Inc.
455 +solidrun       SolidRun
456 +solomon        Solomon Systech Limited
457 +sony   Sony Corporation
458 +spansion       Spansion Inc.
459 +sprd   Spreadtrum Communications Inc.
460 +sst    Silicon Storage Technology, Inc.
461 +st     STMicroelectronics
462 +starry Starry Electronic Technology (ShenZhen) Co., LTD
463 +startek        Startek
464 +ste    ST-Ericsson
465 +stericsson     ST-Ericsson
466 +summit Summit microelectronics
467 +sunchip        Shenzhen Sunchip Technology Co., Ltd
468 +SUNW   Sun Microsystems, Inc
469 +swir   Sierra Wireless
470 +syna   Synaptics Inc.
471 +synology       Synology, Inc.
472 +tbs    TBS Technologies
473 +tbs-biometrics Touchless Biometric Systems AG
474 +tcg    Trusted Computing Group
475 +tcl    Toby Churchill Ltd.
476 +technexion     TechNexion
477 +technologic    Technologic Systems
478 +tempo  Tempo Semiconductor
479 +techstar       Shenzhen Techstar Electronics Co., Ltd.
480 +terasic        Terasic Inc.
481 +thine  THine Electronics, Inc.
482 +ti     Texas Instruments
483 +tianma Tianma Micro-electronics Co., Ltd.
484 +tlm    Trusted Logic Mobility
485 +tmt    Tecon Microprocessor Technologies, LLC.
486 +topeet  Topeet
487 +toradex        Toradex AG
488 +toshiba        Toshiba Corporation
489 +toumaz Toumaz
490 +tpk    TPK U.S.A. LLC
491 +tplink TP-LINK Technologies Co., Ltd.
492 +tpo    TPO
493 +tronfy Tronfy
494 +tronsmart      Tronsmart
495 +truly  Truly Semiconductors Limited
496 +tsd    Theobroma Systems Design und Consulting GmbH
497 +tyan   Tyan Computer Corporation
498 +u-blox u-blox
499 +ucrobotics     uCRobotics
500 +ubnt   Ubiquiti Networks
501 +udoo   Udoo
502 +uniwest        United Western Technologies Corp (UniWest)
503 +upisemi        uPI Semiconductor Corp.
504 +urt    United Radiant Technology Corporation
505 +usi    Universal Scientific Industrial Co., Ltd.
506 +v3     V3 Semiconductor
507 +vamrs  Vamrs Ltd.
508 +variscite      Variscite Ltd.
509 +via    VIA Technologies, Inc.
510 +virtio Virtual I/O Device Specification, developed by the OASIS consortium
511 +vishay Vishay Intertechnology, Inc
512 +vitesse        Vitesse Semiconductor Corporation
513 +vivante        Vivante Corporation
514 +vocore VoCore Studio
515 +voipac Voipac Technologies s.r.o.
516 +vot    Vision Optical Technology Co., Ltd.
517 +wd     Western Digital Corp.
518 +wetek  WeTek Electronics, limited.
519 +wexler Wexler
520 +whwave  Shenzhen whwave Electronics, Inc.
521 +wi2wi  Wi2Wi, Inc.
522 +winbond Winbond Electronics corp.
523 +winstar        Winstar Display Corp.
524 +wlf    Wolfson Microelectronics
525 +wm     Wondermedia Technologies, Inc.
526 +x-powers       X-Powers
527 +xes    Extreme Engineering Solutions (X-ES)
528 +xillybus       Xillybus Ltd.
529 +xlnx   Xilinx
530 +xunlong        Shenzhen Xunlong Software CO.,Limited
531 +ysoft  Y Soft Corporation a.s.
532 +zarlink        Zarlink Semiconductor
533 +zeitec ZEITEC Semiconductor Co., LTD.
534 +zidoo  Shenzhen Zidoo Technology Co., Ltd.
535 +zii    Zodiac Inflight Innovations
536 +zte    ZTE Corp.
537 +zyxel  ZyXEL Communications Corp.
538 --- a/Documentation/devicetree/bindings/vendor-prefixes.yaml
539 +++ b/Documentation/devicetree/bindings/vendor-prefixes.yaml
540 @@ -143,6 +143,8 @@ patternProperties:
541      description: Beckhoff Automation GmbH & Co. KG
542    "^bitmain,.*":
543      description: Bitmain Technologies
544 +  "^blokaslabs,.*":
545 +    description: Vilniaus Blokas UAB
546    "^boe,.*":
547      description: BOE Technology Group Co., Ltd.
548    "^bosch,.*":
549 --- /dev/null
550 +++ b/sound/soc/bcm/pisound.c
551 @@ -0,0 +1,1201 @@
552 +/*
553 + * Pisound Linux kernel module.
554 + * Copyright (C) 2016-2019  Vilniaus Blokas UAB, https://blokas.io/pisound
555 + *
556 + * This program is free software; you can redistribute it and/or
557 + * modify it under the terms of the GNU General Public License
558 + * as published by the Free Software Foundation; version 2 of the
559 + * License.
560 + *
561 + * This program is distributed in the hope that it will be useful,
562 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
563 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
564 + * GNU General Public License for more details.
565 + *
566 + * You should have received a copy of the GNU General Public License
567 + * along with this program; if not, write to the Free Software
568 + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
569 + * MA  02110-1301, USA.
570 + */
571 +
572 +#include <linux/init.h>
573 +#include <linux/module.h>
574 +#include <linux/platform_device.h>
575 +#include <linux/gpio.h>
576 +#include <linux/kobject.h>
577 +#include <linux/sysfs.h>
578 +#include <linux/delay.h>
579 +#include <linux/spi/spi.h>
580 +#include <linux/interrupt.h>
581 +#include <linux/kfifo.h>
582 +#include <linux/jiffies.h>
583 +
584 +#include <sound/core.h>
585 +#include <sound/pcm.h>
586 +#include <sound/pcm_params.h>
587 +#include <sound/soc.h>
588 +#include <sound/jack.h>
589 +#include <sound/rawmidi.h>
590 +#include <sound/asequencer.h>
591 +#include <sound/control.h>
592 +
593 +static int pisnd_spi_init(struct device *dev);
594 +static void pisnd_spi_uninit(void);
595 +
596 +static void pisnd_spi_flush(void);
597 +static void pisnd_spi_start(void);
598 +static uint8_t pisnd_spi_recv(uint8_t *buffer, uint8_t length);
599 +
600 +typedef void (*pisnd_spi_recv_cb)(void *data);
601 +static void pisnd_spi_set_callback(pisnd_spi_recv_cb cb, void *data);
602 +
603 +static const char *pisnd_spi_get_serial(void);
604 +static const char *pisnd_spi_get_id(void);
605 +static const char *pisnd_spi_get_version(void);
606 +
607 +static int pisnd_midi_init(struct snd_card *card);
608 +static void pisnd_midi_uninit(void);
609 +
610 +enum task_e {
611 +       TASK_PROCESS = 0,
612 +};
613 +
614 +static void pisnd_schedule_process(enum task_e task);
615 +
616 +#define PISOUND_LOG_PREFIX "pisound: "
617 +
618 +#ifdef PISOUND_DEBUG
619 +#      define printd(...) pr_alert(PISOUND_LOG_PREFIX __VA_ARGS__)
620 +#else
621 +#      define printd(...) do {} while (0)
622 +#endif
623 +
624 +#define printe(...) pr_err(PISOUND_LOG_PREFIX __VA_ARGS__)
625 +#define printi(...) pr_info(PISOUND_LOG_PREFIX __VA_ARGS__)
626 +
627 +static struct snd_rawmidi *g_rmidi;
628 +static struct snd_rawmidi_substream *g_midi_output_substream;
629 +
630 +static int pisnd_output_open(struct snd_rawmidi_substream *substream)
631 +{
632 +       g_midi_output_substream = substream;
633 +       return 0;
634 +}
635 +
636 +static int pisnd_output_close(struct snd_rawmidi_substream *substream)
637 +{
638 +       g_midi_output_substream = NULL;
639 +       return 0;
640 +}
641 +
642 +static void pisnd_output_trigger(
643 +       struct snd_rawmidi_substream *substream,
644 +       int up
645 +       )
646 +{
647 +       if (substream != g_midi_output_substream) {
648 +               printe("MIDI output trigger called for an unexpected stream!");
649 +               return;
650 +       }
651 +
652 +       if (!up)
653 +               return;
654 +
655 +       pisnd_spi_start();
656 +}
657 +
658 +static void pisnd_output_drain(struct snd_rawmidi_substream *substream)
659 +{
660 +       pisnd_spi_flush();
661 +}
662 +
663 +static int pisnd_input_open(struct snd_rawmidi_substream *substream)
664 +{
665 +       return 0;
666 +}
667 +
668 +static int pisnd_input_close(struct snd_rawmidi_substream *substream)
669 +{
670 +       return 0;
671 +}
672 +
673 +static void pisnd_midi_recv_callback(void *substream)
674 +{
675 +       uint8_t data[128];
676 +       uint8_t n = 0;
677 +
678 +       while ((n = pisnd_spi_recv(data, sizeof(data)))) {
679 +               int res = snd_rawmidi_receive(substream, data, n);
680 +               (void)res;
681 +               printd("midi recv %u bytes, res = %d\n", n, res);
682 +       }
683 +}
684 +
685 +static void pisnd_input_trigger(struct snd_rawmidi_substream *substream, int up)
686 +{
687 +       if (up) {
688 +               pisnd_spi_set_callback(pisnd_midi_recv_callback, substream);
689 +               pisnd_schedule_process(TASK_PROCESS);
690 +       } else {
691 +               pisnd_spi_set_callback(NULL, NULL);
692 +       }
693 +}
694 +
695 +static struct snd_rawmidi_ops pisnd_output_ops = {
696 +       .open = pisnd_output_open,
697 +       .close = pisnd_output_close,
698 +       .trigger = pisnd_output_trigger,
699 +       .drain = pisnd_output_drain,
700 +};
701 +
702 +static struct snd_rawmidi_ops pisnd_input_ops = {
703 +       .open = pisnd_input_open,
704 +       .close = pisnd_input_close,
705 +       .trigger = pisnd_input_trigger,
706 +};
707 +
708 +static void pisnd_get_port_info(
709 +       struct snd_rawmidi *rmidi,
710 +       int number,
711 +       struct snd_seq_port_info *seq_port_info
712 +       )
713 +{
714 +       seq_port_info->type =
715 +               SNDRV_SEQ_PORT_TYPE_MIDI_GENERIC |
716 +               SNDRV_SEQ_PORT_TYPE_HARDWARE |
717 +               SNDRV_SEQ_PORT_TYPE_PORT;
718 +       seq_port_info->midi_voices = 0;
719 +}
720 +
721 +static struct snd_rawmidi_global_ops pisnd_global_ops = {
722 +       .get_port_info = pisnd_get_port_info,
723 +};
724 +
725 +static int pisnd_midi_init(struct snd_card *card)
726 +{
727 +       int err;
728 +
729 +       g_midi_output_substream = NULL;
730 +
731 +       err = snd_rawmidi_new(card, "pisound MIDI", 0, 1, 1, &g_rmidi);
732 +
733 +       if (err < 0) {
734 +               printe("snd_rawmidi_new failed: %d\n", err);
735 +               return err;
736 +       }
737 +
738 +       strcpy(g_rmidi->name, "pisound MIDI ");
739 +       strcat(g_rmidi->name, pisnd_spi_get_serial());
740 +
741 +       g_rmidi->info_flags =
742 +               SNDRV_RAWMIDI_INFO_OUTPUT |
743 +               SNDRV_RAWMIDI_INFO_INPUT |
744 +               SNDRV_RAWMIDI_INFO_DUPLEX;
745 +
746 +       g_rmidi->ops = &pisnd_global_ops;
747 +
748 +       g_rmidi->private_data = (void *)0;
749 +
750 +       snd_rawmidi_set_ops(
751 +               g_rmidi,
752 +               SNDRV_RAWMIDI_STREAM_OUTPUT,
753 +               &pisnd_output_ops
754 +               );
755 +
756 +       snd_rawmidi_set_ops(
757 +               g_rmidi,
758 +               SNDRV_RAWMIDI_STREAM_INPUT,
759 +               &pisnd_input_ops
760 +               );
761 +
762 +       return 0;
763 +}
764 +
765 +static void pisnd_midi_uninit(void)
766 +{
767 +}
768 +
769 +static void *g_recvData;
770 +static pisnd_spi_recv_cb g_recvCallback;
771 +
772 +#define FIFO_SIZE 4096
773 +
774 +static char g_serial_num[11];
775 +static char g_id[25];
776 +static char g_version[5];
777 +
778 +static uint8_t g_ledFlashDuration;
779 +static bool    g_ledFlashDurationChanged;
780 +
781 +DEFINE_KFIFO(spi_fifo_in,  uint8_t, FIFO_SIZE);
782 +DEFINE_KFIFO(spi_fifo_out, uint8_t, FIFO_SIZE);
783 +
784 +static struct gpio_desc *data_available;
785 +static struct gpio_desc *spi_reset;
786 +
787 +static struct spi_device *pisnd_spi_device;
788 +
789 +static struct workqueue_struct *pisnd_workqueue;
790 +static struct work_struct pisnd_work_process;
791 +
792 +static void pisnd_work_handler(struct work_struct *work);
793 +
794 +static void spi_transfer(const uint8_t *txbuf, uint8_t *rxbuf, int len);
795 +static uint16_t spi_transfer16(uint16_t val);
796 +
797 +static int pisnd_init_workqueues(void)
798 +{
799 +       pisnd_workqueue = create_singlethread_workqueue("pisnd_workqueue");
800 +       INIT_WORK(&pisnd_work_process, pisnd_work_handler);
801 +
802 +       return 0;
803 +}
804 +
805 +static void pisnd_uninit_workqueues(void)
806 +{
807 +       flush_workqueue(pisnd_workqueue);
808 +       destroy_workqueue(pisnd_workqueue);
809 +
810 +       pisnd_workqueue = NULL;
811 +}
812 +
813 +static bool pisnd_spi_has_more(void)
814 +{
815 +       return gpiod_get_value(data_available);
816 +}
817 +
818 +static void pisnd_schedule_process(enum task_e task)
819 +{
820 +       if (pisnd_spi_device != NULL &&
821 +               pisnd_workqueue != NULL &&
822 +               !work_pending(&pisnd_work_process)
823 +               ) {
824 +               printd("schedule: has more = %d\n", pisnd_spi_has_more());
825 +               if (task == TASK_PROCESS)
826 +                       queue_work(pisnd_workqueue, &pisnd_work_process);
827 +       }
828 +}
829 +
830 +static irqreturn_t data_available_interrupt_handler(int irq, void *dev_id)
831 +{
832 +       if (irq == gpiod_to_irq(data_available) && pisnd_spi_has_more()) {
833 +               printd("schedule from irq\n");
834 +               pisnd_schedule_process(TASK_PROCESS);
835 +       }
836 +
837 +       return IRQ_HANDLED;
838 +}
839 +
840 +static uint16_t spi_transfer16(uint16_t val)
841 +{
842 +       uint8_t txbuf[2];
843 +       uint8_t rxbuf[2];
844 +
845 +       if (!pisnd_spi_device) {
846 +               printe("pisnd_spi_device null, returning\n");
847 +               return 0;
848 +       }
849 +
850 +       txbuf[0] = val >> 8;
851 +       txbuf[1] = val & 0xff;
852 +
853 +       spi_transfer(txbuf, rxbuf, sizeof(txbuf));
854 +
855 +       printd("received: %02x%02x\n", rxbuf[0], rxbuf[1]);
856 +
857 +       return (rxbuf[0] << 8) | rxbuf[1];
858 +}
859 +
860 +static void spi_transfer(const uint8_t *txbuf, uint8_t *rxbuf, int len)
861 +{
862 +       int err;
863 +       struct spi_transfer transfer;
864 +       struct spi_message msg;
865 +
866 +       memset(rxbuf, 0, len);
867 +
868 +       if (!pisnd_spi_device) {
869 +               printe("pisnd_spi_device null, returning\n");
870 +               return;
871 +       }
872 +
873 +       spi_message_init(&msg);
874 +
875 +       memset(&transfer, 0, sizeof(transfer));
876 +
877 +       transfer.tx_buf = txbuf;
878 +       transfer.rx_buf = rxbuf;
879 +       transfer.len = len;
880 +       transfer.speed_hz = 100000;
881 +       transfer.delay_usecs = 10;
882 +       spi_message_add_tail(&transfer, &msg);
883 +
884 +       err = spi_sync(pisnd_spi_device, &msg);
885 +
886 +       if (err < 0) {
887 +               printe("spi_sync error %d\n", err);
888 +               return;
889 +       }
890 +
891 +       printd("hasMore %d\n", pisnd_spi_has_more());
892 +}
893 +
894 +static int spi_read_bytes(char *dst, size_t length, uint8_t *bytesRead)
895 +{
896 +       uint16_t rx;
897 +       uint8_t size;
898 +       uint8_t i;
899 +
900 +       memset(dst, 0, length);
901 +       *bytesRead = 0;
902 +
903 +       rx = spi_transfer16(0);
904 +       if (!(rx >> 8))
905 +               return -EINVAL;
906 +
907 +       size = rx & 0xff;
908 +
909 +       if (size > length)
910 +               return -EINVAL;
911 +
912 +       for (i = 0; i < size; ++i) {
913 +               rx = spi_transfer16(0);
914 +               if (!(rx >> 8))
915 +                       return -EINVAL;
916 +
917 +               dst[i] = rx & 0xff;
918 +       }
919 +
920 +       *bytesRead = i;
921 +
922 +       return 0;
923 +}
924 +
925 +static int spi_device_match(struct device *dev, const void *data)
926 +{
927 +       struct spi_device *spi = container_of(dev, struct spi_device, dev);
928 +
929 +       printd("      %s %s %dkHz %d bits mode=0x%02X\n",
930 +               spi->modalias, dev_name(dev), spi->max_speed_hz/1000,
931 +               spi->bits_per_word, spi->mode);
932 +
933 +       if (strcmp("pisound-spi", spi->modalias) == 0) {
934 +               printi("\tFound!\n");
935 +               return 1;
936 +       }
937 +
938 +       printe("\tNot found!\n");
939 +       return 0;
940 +}
941 +
942 +static struct spi_device *pisnd_spi_find_device(void)
943 +{
944 +       struct device *dev;
945 +
946 +       printi("Searching for spi device...\n");
947 +       dev = bus_find_device(&spi_bus_type, NULL, NULL, spi_device_match);
948 +       if (dev != NULL)
949 +               return container_of(dev, struct spi_device, dev);
950 +       else
951 +               return NULL;
952 +}
953 +
954 +static void pisnd_work_handler(struct work_struct *work)
955 +{
956 +       enum { TRANSFER_SIZE = 4 };
957 +       enum { PISOUND_OUTPUT_BUFFER_SIZE = 128 };
958 +       enum { MIDI_BYTES_PER_SECOND = 3125 };
959 +       int out_buffer_used = 0;
960 +       unsigned long now;
961 +       uint8_t val;
962 +       uint8_t txbuf[TRANSFER_SIZE];
963 +       uint8_t rxbuf[TRANSFER_SIZE];
964 +       uint8_t midibuf[TRANSFER_SIZE];
965 +       int i, n;
966 +       bool had_data;
967 +
968 +       unsigned long last_transfer_at = jiffies;
969 +
970 +       if (work == &pisnd_work_process) {
971 +               if (pisnd_spi_device == NULL)
972 +                       return;
973 +
974 +               do {
975 +                       if (g_midi_output_substream &&
976 +                               kfifo_avail(&spi_fifo_out) >= sizeof(midibuf)) {
977 +
978 +                               n = snd_rawmidi_transmit_peek(
979 +                                       g_midi_output_substream,
980 +                                       midibuf, sizeof(midibuf)
981 +                               );
982 +
983 +                               if (n > 0) {
984 +                                       for (i = 0; i < n; ++i)
985 +                                               kfifo_put(
986 +                                                       &spi_fifo_out,
987 +                                                       midibuf[i]
988 +                                                       );
989 +                                       snd_rawmidi_transmit_ack(
990 +                                               g_midi_output_substream,
991 +                                               i
992 +                                               );
993 +                               }
994 +                       }
995 +
996 +                       had_data = false;
997 +                       memset(txbuf, 0, sizeof(txbuf));
998 +                       for (i = 0; i < sizeof(txbuf) &&
999 +                               out_buffer_used < PISOUND_OUTPUT_BUFFER_SIZE;
1000 +                               i += 2) {
1001 +
1002 +                               val = 0;
1003 +
1004 +                               if (g_ledFlashDurationChanged) {
1005 +                                       txbuf[i+0] = 0xf0;
1006 +                                       txbuf[i+1] = g_ledFlashDuration;
1007 +                                       g_ledFlashDuration = 0;
1008 +                                       g_ledFlashDurationChanged = false;
1009 +                               } else if (kfifo_get(&spi_fifo_out, &val)) {
1010 +                                       txbuf[i+0] = 0x0f;
1011 +                                       txbuf[i+1] = val;
1012 +                                       ++out_buffer_used;
1013 +                               }
1014 +                       }
1015 +
1016 +                       spi_transfer(txbuf, rxbuf, sizeof(txbuf));
1017 +                       /* Estimate the Pisound's MIDI output buffer usage, so
1018 +                        * that we don't overflow it. Space in the buffer should
1019 +                        * be becoming available at the UART MIDI byte transfer
1020 +                        * rate.
1021 +                        */
1022 +                       now = jiffies;
1023 +                       out_buffer_used -=
1024 +                               (MIDI_BYTES_PER_SECOND / HZ) /
1025 +                               (now - last_transfer_at);
1026 +                       if (out_buffer_used < 0)
1027 +                               out_buffer_used = 0;
1028 +                       last_transfer_at = now;
1029 +
1030 +                       for (i = 0; i < sizeof(rxbuf); i += 2) {
1031 +                               if (rxbuf[i]) {
1032 +                                       kfifo_put(&spi_fifo_in, rxbuf[i+1]);
1033 +                                       if (kfifo_len(&spi_fifo_in) > 16 &&
1034 +                                               g_recvCallback)
1035 +                                               g_recvCallback(g_recvData);
1036 +                                       had_data = true;
1037 +                               }
1038 +                       }
1039 +               } while (had_data
1040 +                       || !kfifo_is_empty(&spi_fifo_out)
1041 +                       || pisnd_spi_has_more()
1042 +                       || g_ledFlashDurationChanged
1043 +                       );
1044 +
1045 +               if (!kfifo_is_empty(&spi_fifo_in) && g_recvCallback)
1046 +                       g_recvCallback(g_recvData);
1047 +       }
1048 +}
1049 +
1050 +static int pisnd_spi_gpio_init(struct device *dev)
1051 +{
1052 +       spi_reset = gpiod_get_index(dev, "reset", 1, GPIOD_ASIS);
1053 +       data_available = gpiod_get_index(dev, "data_available", 0, GPIOD_ASIS);
1054 +
1055 +       gpiod_direction_output(spi_reset, 1);
1056 +       gpiod_direction_input(data_available);
1057 +
1058 +       /* Reset the slave. */
1059 +       gpiod_set_value(spi_reset, false);
1060 +       mdelay(1);
1061 +       gpiod_set_value(spi_reset, true);
1062 +
1063 +       /* Give time for spi slave to start. */
1064 +       mdelay(64);
1065 +
1066 +       return 0;
1067 +}
1068 +
1069 +static void pisnd_spi_gpio_uninit(void)
1070 +{
1071 +       gpiod_set_value(spi_reset, false);
1072 +       gpiod_put(spi_reset);
1073 +       spi_reset = NULL;
1074 +
1075 +       gpiod_put(data_available);
1076 +       data_available = NULL;
1077 +}
1078 +
1079 +static int pisnd_spi_gpio_irq_init(struct device *dev)
1080 +{
1081 +       return request_threaded_irq(
1082 +               gpiod_to_irq(data_available), NULL,
1083 +               data_available_interrupt_handler,
1084 +               IRQF_TIMER | IRQF_TRIGGER_RISING | IRQF_ONESHOT,
1085 +               "data_available_int",
1086 +               NULL
1087 +               );
1088 +}
1089 +
1090 +static void pisnd_spi_gpio_irq_uninit(void)
1091 +{
1092 +       free_irq(gpiod_to_irq(data_available), NULL);
1093 +}
1094 +
1095 +static int spi_read_info(void)
1096 +{
1097 +       uint16_t tmp;
1098 +       uint8_t count;
1099 +       uint8_t n;
1100 +       uint8_t i;
1101 +       uint8_t j;
1102 +       char buffer[257];
1103 +       int ret;
1104 +       char *p;
1105 +
1106 +       memset(g_serial_num, 0, sizeof(g_serial_num));
1107 +       memset(g_version, 0, sizeof(g_version));
1108 +       memset(g_id, 0, sizeof(g_id));
1109 +
1110 +       tmp = spi_transfer16(0);
1111 +
1112 +       if (!(tmp >> 8))
1113 +               return -EINVAL;
1114 +
1115 +       count = tmp & 0xff;
1116 +
1117 +       for (i = 0; i < count; ++i) {
1118 +               memset(buffer, 0, sizeof(buffer));
1119 +               ret = spi_read_bytes(buffer, sizeof(buffer)-1, &n);
1120 +
1121 +               if (ret < 0)
1122 +                       return ret;
1123 +
1124 +               switch (i) {
1125 +               case 0:
1126 +                       if (n != 2)
1127 +                               return -EINVAL;
1128 +
1129 +                       snprintf(
1130 +                               g_version,
1131 +                               sizeof(g_version),
1132 +                               "%x.%02x",
1133 +                               buffer[0],
1134 +                               buffer[1]
1135 +                               );
1136 +                       break;
1137 +               case 1:
1138 +                       if (n >= sizeof(g_serial_num))
1139 +                               return -EINVAL;
1140 +
1141 +                       memcpy(g_serial_num, buffer, sizeof(g_serial_num));
1142 +                       break;
1143 +               case 2:
1144 +                       {
1145 +                               if (n >= sizeof(g_id))
1146 +                                       return -EINVAL;
1147 +
1148 +                               p = g_id;
1149 +                               for (j = 0; j < n; ++j)
1150 +                                       p += sprintf(p, "%02x", buffer[j]);
1151 +                       }
1152 +                       break;
1153 +               default:
1154 +                       break;
1155 +               }
1156 +       }
1157 +
1158 +       return 0;
1159 +}
1160 +
1161 +static int pisnd_spi_init(struct device *dev)
1162 +{
1163 +       int ret;
1164 +       struct spi_device *spi;
1165 +
1166 +       memset(g_serial_num, 0, sizeof(g_serial_num));
1167 +       memset(g_id, 0, sizeof(g_id));
1168 +       memset(g_version, 0, sizeof(g_version));
1169 +
1170 +       spi = pisnd_spi_find_device();
1171 +
1172 +       if (spi != NULL) {
1173 +               printd("initializing spi!\n");
1174 +               pisnd_spi_device = spi;
1175 +               ret = spi_setup(pisnd_spi_device);
1176 +       } else {
1177 +               printe("SPI device not found, deferring!\n");
1178 +               return -EPROBE_DEFER;
1179 +       }
1180 +
1181 +       ret = pisnd_spi_gpio_init(dev);
1182 +
1183 +       if (ret < 0) {
1184 +               printe("SPI GPIO init failed: %d\n", ret);
1185 +               spi_dev_put(pisnd_spi_device);
1186 +               pisnd_spi_device = NULL;
1187 +               pisnd_spi_gpio_uninit();
1188 +               return ret;
1189 +       }
1190 +
1191 +       ret = spi_read_info();
1192 +
1193 +       if (ret < 0) {
1194 +               printe("Reading card info failed: %d\n", ret);
1195 +               spi_dev_put(pisnd_spi_device);
1196 +               pisnd_spi_device = NULL;
1197 +               pisnd_spi_gpio_uninit();
1198 +               return ret;
1199 +       }
1200 +
1201 +       /* Flash the LEDs. */
1202 +       spi_transfer16(0xf008);
1203 +
1204 +       ret = pisnd_spi_gpio_irq_init(dev);
1205 +       if (ret < 0) {
1206 +               printe("SPI irq request failed: %d\n", ret);
1207 +               spi_dev_put(pisnd_spi_device);
1208 +               pisnd_spi_device = NULL;
1209 +               pisnd_spi_gpio_irq_uninit();
1210 +               pisnd_spi_gpio_uninit();
1211 +       }
1212 +
1213 +       ret = pisnd_init_workqueues();
1214 +       if (ret != 0) {
1215 +               printe("Workqueue initialization failed: %d\n", ret);
1216 +               spi_dev_put(pisnd_spi_device);
1217 +               pisnd_spi_device = NULL;
1218 +               pisnd_spi_gpio_irq_uninit();
1219 +               pisnd_spi_gpio_uninit();
1220 +               pisnd_uninit_workqueues();
1221 +               return ret;
1222 +       }
1223 +
1224 +       if (pisnd_spi_has_more()) {
1225 +               printd("data is available, scheduling from init\n");
1226 +               pisnd_schedule_process(TASK_PROCESS);
1227 +       }
1228 +
1229 +       return 0;
1230 +}
1231 +
1232 +static void pisnd_spi_uninit(void)
1233 +{
1234 +       pisnd_uninit_workqueues();
1235 +
1236 +       spi_dev_put(pisnd_spi_device);
1237 +       pisnd_spi_device = NULL;
1238 +
1239 +       pisnd_spi_gpio_irq_uninit();
1240 +       pisnd_spi_gpio_uninit();
1241 +}
1242 +
1243 +static void pisnd_spi_flash_leds(uint8_t duration)
1244 +{
1245 +       g_ledFlashDuration = duration;
1246 +       g_ledFlashDurationChanged = true;
1247 +       printd("schedule from spi_flash_leds\n");
1248 +       pisnd_schedule_process(TASK_PROCESS);
1249 +}
1250 +
1251 +static void pisnd_spi_flush(void)
1252 +{
1253 +       while (!kfifo_is_empty(&spi_fifo_out)) {
1254 +               pisnd_spi_start();
1255 +               flush_workqueue(pisnd_workqueue);
1256 +       }
1257 +}
1258 +
1259 +static void pisnd_spi_start(void)
1260 +{
1261 +       printd("schedule from spi_start\n");
1262 +       pisnd_schedule_process(TASK_PROCESS);
1263 +}
1264 +
1265 +static uint8_t pisnd_spi_recv(uint8_t *buffer, uint8_t length)
1266 +{
1267 +       return kfifo_out(&spi_fifo_in, buffer, length);
1268 +}
1269 +
1270 +static void pisnd_spi_set_callback(pisnd_spi_recv_cb cb, void *data)
1271 +{
1272 +       g_recvData = data;
1273 +       g_recvCallback = cb;
1274 +}
1275 +
1276 +static const char *pisnd_spi_get_serial(void)
1277 +{
1278 +       if (strlen(g_serial_num))
1279 +               return g_serial_num;
1280 +
1281 +       return "";
1282 +}
1283 +
1284 +static const char *pisnd_spi_get_id(void)
1285 +{
1286 +       if (strlen(g_id))
1287 +               return g_id;
1288 +
1289 +       return "";
1290 +}
1291 +
1292 +static const char *pisnd_spi_get_version(void)
1293 +{
1294 +       if (strlen(g_version))
1295 +               return g_version;
1296 +
1297 +       return "";
1298 +}
1299 +
1300 +static const struct of_device_id pisound_of_match[] = {
1301 +       { .compatible = "blokaslabs,pisound", },
1302 +       { .compatible = "blokaslabs,pisound-spi", },
1303 +       {},
1304 +};
1305 +
1306 +enum {
1307 +       SWITCH = 0,
1308 +       VOLUME = 1,
1309 +};
1310 +
1311 +static int pisnd_ctl_info(struct snd_kcontrol *kcontrol,
1312 +       struct snd_ctl_elem_info *uinfo)
1313 +{
1314 +       if (kcontrol->private_value == SWITCH) {
1315 +               uinfo->type = SNDRV_CTL_ELEM_TYPE_BOOLEAN;
1316 +               uinfo->count = 1;
1317 +               uinfo->value.integer.min = 0;
1318 +               uinfo->value.integer.max = 1;
1319 +               return 0;
1320 +       } else if (kcontrol->private_value == VOLUME) {
1321 +               uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER;
1322 +               uinfo->count = 1;
1323 +               uinfo->value.integer.min = 0;
1324 +               uinfo->value.integer.max = 100;
1325 +               return 0;
1326 +       }
1327 +       return -EINVAL;
1328 +}
1329 +
1330 +static int pisnd_ctl_get(struct snd_kcontrol *kcontrol,
1331 +       struct snd_ctl_elem_value *ucontrol)
1332 +{
1333 +       if (kcontrol->private_value == SWITCH) {
1334 +               ucontrol->value.integer.value[0] = 1;
1335 +               return 0;
1336 +       } else if (kcontrol->private_value == VOLUME) {
1337 +               ucontrol->value.integer.value[0] = 100;
1338 +               return 0;
1339 +       }
1340 +
1341 +       return -EINVAL;
1342 +}
1343 +
1344 +static struct snd_kcontrol_new pisnd_ctl[] = {
1345 +       {
1346 +               .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
1347 +               .name = "PCM Playback Switch",
1348 +               .index = 0,
1349 +               .private_value = SWITCH,
1350 +               .access = SNDRV_CTL_ELEM_ACCESS_READ,
1351 +               .info = pisnd_ctl_info,
1352 +               .get = pisnd_ctl_get,
1353 +       },
1354 +       {
1355 +               .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
1356 +               .name = "PCM Playback Volume",
1357 +               .index = 0,
1358 +               .private_value = VOLUME,
1359 +               .access = SNDRV_CTL_ELEM_ACCESS_READ,
1360 +               .info = pisnd_ctl_info,
1361 +               .get = pisnd_ctl_get,
1362 +       },
1363 +};
1364 +
1365 +static int pisnd_ctl_init(struct snd_card *card)
1366 +{
1367 +       int err, i;
1368 +
1369 +       for (i = 0; i < ARRAY_SIZE(pisnd_ctl); ++i) {
1370 +               err = snd_ctl_add(card, snd_ctl_new1(&pisnd_ctl[i], NULL));
1371 +               if (err < 0)
1372 +                       return err;
1373 +       }
1374 +
1375 +       return 0;
1376 +}
1377 +
1378 +static int pisnd_ctl_uninit(void)
1379 +{
1380 +       return 0;
1381 +}
1382 +
1383 +static struct gpio_desc *osr0, *osr1, *osr2;
1384 +static struct gpio_desc *reset;
1385 +static struct gpio_desc *button;
1386 +
1387 +static int pisnd_hw_params(
1388 +       struct snd_pcm_substream *substream,
1389 +       struct snd_pcm_hw_params *params
1390 +       )
1391 +{
1392 +       struct snd_soc_pcm_runtime *rtd = substream->private_data;
1393 +       struct snd_soc_dai *cpu_dai = rtd->cpu_dai;
1394 +
1395 +       /* Pisound runs on fixed 32 clock counts per channel,
1396 +        * as generated by the master ADC.
1397 +        */
1398 +       snd_soc_dai_set_bclk_ratio(cpu_dai, 32*2);
1399 +
1400 +       printd("rate   = %d\n", params_rate(params));
1401 +       printd("ch     = %d\n", params_channels(params));
1402 +       printd("bits   = %u\n",
1403 +               snd_pcm_format_physical_width(params_format(params)));
1404 +       printd("format = %d\n", params_format(params));
1405 +
1406 +       gpiod_set_value(reset, false);
1407 +
1408 +       switch (params_rate(params)) {
1409 +       case 48000:
1410 +               gpiod_set_value(osr0, true);
1411 +               gpiod_set_value(osr1, false);
1412 +               gpiod_set_value(osr2, false);
1413 +               break;
1414 +       case 96000:
1415 +               gpiod_set_value(osr0, true);
1416 +               gpiod_set_value(osr1, false);
1417 +               gpiod_set_value(osr2, true);
1418 +               break;
1419 +       case 192000:
1420 +               gpiod_set_value(osr0, true);
1421 +               gpiod_set_value(osr1, true);
1422 +               gpiod_set_value(osr2, true);
1423 +               break;
1424 +       default:
1425 +               printe("Unsupported rate %u!\n", params_rate(params));
1426 +               return -EINVAL;
1427 +       }
1428 +
1429 +       gpiod_set_value(reset, true);
1430 +
1431 +       return 0;
1432 +}
1433 +
1434 +static unsigned int rates[3] = {
1435 +       48000, 96000, 192000
1436 +};
1437 +
1438 +static struct snd_pcm_hw_constraint_list constraints_rates = {
1439 +       .count = ARRAY_SIZE(rates),
1440 +       .list = rates,
1441 +       .mask = 0,
1442 +};
1443 +
1444 +static int pisnd_startup(struct snd_pcm_substream *substream)
1445 +{
1446 +       int err = snd_pcm_hw_constraint_list(
1447 +               substream->runtime,
1448 +               0,
1449 +               SNDRV_PCM_HW_PARAM_RATE,
1450 +               &constraints_rates
1451 +               );
1452 +
1453 +       if (err < 0)
1454 +               return err;
1455 +
1456 +       err = snd_pcm_hw_constraint_single(
1457 +               substream->runtime,
1458 +               SNDRV_PCM_HW_PARAM_CHANNELS,
1459 +               2
1460 +               );
1461 +
1462 +       if (err < 0)
1463 +               return err;
1464 +
1465 +       err = snd_pcm_hw_constraint_mask64(
1466 +               substream->runtime,
1467 +               SNDRV_PCM_HW_PARAM_FORMAT,
1468 +               SNDRV_PCM_FMTBIT_S16_LE |
1469 +               SNDRV_PCM_FMTBIT_S24_LE |
1470 +               SNDRV_PCM_FMTBIT_S32_LE
1471 +               );
1472 +
1473 +       if (err < 0)
1474 +               return err;
1475 +
1476 +       return 0;
1477 +}
1478 +
1479 +static struct snd_soc_ops pisnd_ops = {
1480 +       .startup = pisnd_startup,
1481 +       .hw_params = pisnd_hw_params,
1482 +};
1483 +
1484 +SND_SOC_DAILINK_DEFS(pisnd,
1485 +       DAILINK_COMP_ARRAY(COMP_CPU("bcm2708-i2s.0")),
1486 +       DAILINK_COMP_ARRAY(COMP_DUMMY()),
1487 +       DAILINK_COMP_ARRAY(COMP_PLATFORM("bcm2708-i2s.0")));
1488 +
1489 +static struct snd_soc_dai_link pisnd_dai[] = {
1490 +       {
1491 +               .name           = "pisound",
1492 +               .stream_name    = "pisound",
1493 +               .dai_fmt        =
1494 +                       SND_SOC_DAIFMT_I2S |
1495 +                       SND_SOC_DAIFMT_NB_NF |
1496 +                       SND_SOC_DAIFMT_CBM_CFM,
1497 +               .ops            = &pisnd_ops,
1498 +               SND_SOC_DAILINK_REG(pisnd),
1499 +       },
1500 +};
1501 +
1502 +static int pisnd_card_probe(struct snd_soc_card *card)
1503 +{
1504 +       int err = pisnd_midi_init(card->snd_card);
1505 +
1506 +       if (err < 0) {
1507 +               printe("pisnd_midi_init failed: %d\n", err);
1508 +               return err;
1509 +       }
1510 +
1511 +       err = pisnd_ctl_init(card->snd_card);
1512 +       if (err < 0) {
1513 +               printe("pisnd_ctl_init failed: %d\n", err);
1514 +               return err;
1515 +       }
1516 +
1517 +       return 0;
1518 +}
1519 +
1520 +static int pisnd_card_remove(struct snd_soc_card *card)
1521 +{
1522 +       pisnd_ctl_uninit();
1523 +       pisnd_midi_uninit();
1524 +       return 0;
1525 +}
1526 +
1527 +static struct snd_soc_card pisnd_card = {
1528 +       .name         = "pisound",
1529 +       .owner        = THIS_MODULE,
1530 +       .dai_link     = pisnd_dai,
1531 +       .num_links    = ARRAY_SIZE(pisnd_dai),
1532 +       .probe        = pisnd_card_probe,
1533 +       .remove       = pisnd_card_remove,
1534 +};
1535 +
1536 +static int pisnd_init_gpio(struct device *dev)
1537 +{
1538 +       osr0 = gpiod_get_index(dev, "osr", 0, GPIOD_ASIS);
1539 +       osr1 = gpiod_get_index(dev, "osr", 1, GPIOD_ASIS);
1540 +       osr2 = gpiod_get_index(dev, "osr", 2, GPIOD_ASIS);
1541 +
1542 +       reset = gpiod_get_index(dev, "reset", 0, GPIOD_ASIS);
1543 +
1544 +       button = gpiod_get_index(dev, "button", 0, GPIOD_ASIS);
1545 +
1546 +       gpiod_direction_output(osr0,  1);
1547 +       gpiod_direction_output(osr1,  1);
1548 +       gpiod_direction_output(osr2,  1);
1549 +       gpiod_direction_output(reset, 1);
1550 +
1551 +       gpiod_set_value(reset, false);
1552 +       gpiod_set_value(osr0,   true);
1553 +       gpiod_set_value(osr1,  false);
1554 +       gpiod_set_value(osr2,  false);
1555 +       gpiod_set_value(reset,  true);
1556 +
1557 +       gpiod_export(button, false);
1558 +
1559 +       return 0;
1560 +}
1561 +
1562 +static int pisnd_uninit_gpio(void)
1563 +{
1564 +       int i;
1565 +
1566 +       struct gpio_desc **gpios[] = {
1567 +               &osr0, &osr1, &osr2, &reset, &button,
1568 +       };
1569 +
1570 +       gpiod_unexport(button);
1571 +
1572 +       for (i = 0; i < ARRAY_SIZE(gpios); ++i) {
1573 +               if (*gpios[i] == NULL) {
1574 +                       printd("weird, GPIO[%d] is NULL already\n", i);
1575 +                       continue;
1576 +               }
1577 +
1578 +               gpiod_put(*gpios[i]);
1579 +               *gpios[i] = NULL;
1580 +       }
1581 +
1582 +       return 0;
1583 +}
1584 +
1585 +static struct kobject *pisnd_kobj;
1586 +
1587 +static ssize_t pisnd_serial_show(
1588 +       struct kobject *kobj,
1589 +       struct kobj_attribute *attr,
1590 +       char *buf
1591 +       )
1592 +{
1593 +       return sprintf(buf, "%s\n", pisnd_spi_get_serial());
1594 +}
1595 +
1596 +static ssize_t pisnd_id_show(
1597 +       struct kobject *kobj,
1598 +       struct kobj_attribute *attr,
1599 +       char *buf
1600 +       )
1601 +{
1602 +       return sprintf(buf, "%s\n", pisnd_spi_get_id());
1603 +}
1604 +
1605 +static ssize_t pisnd_version_show(
1606 +       struct kobject *kobj,
1607 +       struct kobj_attribute *attr,
1608 +       char *buf
1609 +       )
1610 +{
1611 +       return sprintf(buf, "%s\n", pisnd_spi_get_version());
1612 +}
1613 +
1614 +static ssize_t pisnd_led_store(
1615 +       struct kobject *kobj,
1616 +       struct kobj_attribute *attr,
1617 +       const char *buf,
1618 +       size_t length
1619 +       )
1620 +{
1621 +       uint32_t timeout;
1622 +       int err;
1623 +
1624 +       err = kstrtou32(buf, 10, &timeout);
1625 +
1626 +       if (err == 0 && timeout <= 255)
1627 +               pisnd_spi_flash_leds(timeout);
1628 +
1629 +       return length;
1630 +}
1631 +
1632 +static struct kobj_attribute pisnd_serial_attribute =
1633 +       __ATTR(serial, 0444, pisnd_serial_show, NULL);
1634 +static struct kobj_attribute pisnd_id_attribute =
1635 +       __ATTR(id, 0444, pisnd_id_show, NULL);
1636 +static struct kobj_attribute pisnd_version_attribute =
1637 +       __ATTR(version, 0444, pisnd_version_show, NULL);
1638 +static struct kobj_attribute pisnd_led_attribute =
1639 +       __ATTR(led, 0644, NULL, pisnd_led_store);
1640 +
1641 +static struct attribute *attrs[] = {
1642 +       &pisnd_serial_attribute.attr,
1643 +       &pisnd_id_attribute.attr,
1644 +       &pisnd_version_attribute.attr,
1645 +       &pisnd_led_attribute.attr,
1646 +       NULL
1647 +};
1648 +
1649 +static struct attribute_group attr_group = { .attrs = attrs };
1650 +
1651 +static int pisnd_probe(struct platform_device *pdev)
1652 +{
1653 +       int ret = 0;
1654 +       int i;
1655 +
1656 +       ret = pisnd_spi_init(&pdev->dev);
1657 +       if (ret < 0) {
1658 +               printe("pisnd_spi_init failed: %d\n", ret);
1659 +               return ret;
1660 +       }
1661 +
1662 +       printi("Detected Pisound card:\n");
1663 +       printi("\tSerial:  %s\n", pisnd_spi_get_serial());
1664 +       printi("\tVersion: %s\n", pisnd_spi_get_version());
1665 +       printi("\tId:      %s\n", pisnd_spi_get_id());
1666 +
1667 +       pisnd_kobj = kobject_create_and_add("pisound", kernel_kobj);
1668 +       if (!pisnd_kobj) {
1669 +               pisnd_spi_uninit();
1670 +               return -ENOMEM;
1671 +       }
1672 +
1673 +       ret = sysfs_create_group(pisnd_kobj, &attr_group);
1674 +       if (ret < 0) {
1675 +               pisnd_spi_uninit();
1676 +               kobject_put(pisnd_kobj);
1677 +               return -ENOMEM;
1678 +       }
1679 +
1680 +       pisnd_init_gpio(&pdev->dev);
1681 +       pisnd_card.dev = &pdev->dev;
1682 +
1683 +       if (pdev->dev.of_node) {
1684 +               struct device_node *i2s_node;
1685 +
1686 +               i2s_node = of_parse_phandle(
1687 +                       pdev->dev.of_node,
1688 +                       "i2s-controller",
1689 +                       0
1690 +                       );
1691 +
1692 +               for (i = 0; i < pisnd_card.num_links; ++i) {
1693 +                       struct snd_soc_dai_link *dai = &pisnd_dai[i];
1694 +
1695 +                       if (i2s_node) {
1696 +                               dai->cpus->dai_name = NULL;
1697 +                               dai->cpus->of_node = i2s_node;
1698 +                               dai->platforms->name = NULL;
1699 +                               dai->platforms->of_node = i2s_node;
1700 +                               dai->stream_name = pisnd_spi_get_serial();
1701 +                       }
1702 +               }
1703 +       }
1704 +
1705 +       ret = snd_soc_register_card(&pisnd_card);
1706 +
1707 +       if (ret < 0) {
1708 +               if (ret != -EPROBE_DEFER)
1709 +                       printe("snd_soc_register_card() failed: %d\n", ret);
1710 +               pisnd_uninit_gpio();
1711 +               kobject_put(pisnd_kobj);
1712 +               pisnd_spi_uninit();
1713 +       }
1714 +
1715 +       return ret;
1716 +}
1717 +
1718 +static int pisnd_remove(struct platform_device *pdev)
1719 +{
1720 +       printi("Unloading.\n");
1721 +
1722 +       if (pisnd_kobj) {
1723 +               kobject_put(pisnd_kobj);
1724 +               pisnd_kobj = NULL;
1725 +       }
1726 +
1727 +       pisnd_spi_uninit();
1728 +
1729 +       /* Turn off */
1730 +       gpiod_set_value(reset, false);
1731 +       pisnd_uninit_gpio();
1732 +
1733 +       return snd_soc_unregister_card(&pisnd_card);
1734 +}
1735 +
1736 +MODULE_DEVICE_TABLE(of, pisound_of_match);
1737 +
1738 +static struct platform_driver pisnd_driver = {
1739 +       .driver = {
1740 +               .name           = "snd-rpi-pisound",
1741 +               .owner          = THIS_MODULE,
1742 +               .of_match_table = pisound_of_match,
1743 +       },
1744 +       .probe              = pisnd_probe,
1745 +       .remove             = pisnd_remove,
1746 +};
1747 +
1748 +module_platform_driver(pisnd_driver);
1749 +
1750 +MODULE_AUTHOR("Giedrius Trainavicius <giedrius@blokas.io>");
1751 +MODULE_DESCRIPTION("ASoC Driver for Pisound, https://blokas.io/pisound");
1752 +MODULE_LICENSE("GPL v2");