|
|
- /*
- * =====================================================================================
- *
- * Filename: snd-i2smic-rpi
- *
- * Description: I2S microphone kernel module
- *
- * Version: 0.1.0
- * Created: 2020-04-14
- * Revision: none
- * Compiler: gcc
- *
- * Pi4 Mods: Carter Nelson
- * Orig Author: Huan Truong (htruong@tnhh.net), originally written by Paul Creaser
- *
- * =====================================================================================
- */
- #include <linux/module.h>
- #include <linux/moduleparam.h>
- #include <linux/kernel.h>
- #include <linux/kmod.h>
- #include <linux/platform_device.h>
- #include <sound/simple_card.h>
- #include <linux/delay.h>
- #include "snd-i2smic-rpi.h"
-
- /*
- * modified for linux 4.1.5
- * inspired by https://github.com/msperl/spi-config
- * with thanks for https://github.com/notro/rpi-source/wiki
- * as well as Florian Meier for the rpi i2s and dma drivers
- *
- * to use a differant (simple-card compatible) codec
- * change the codec name string in two places and the
- * codec_dai name string. (see codec's source file)
- *
- *
- * N.B. playback vs capture is determined by the codec choice
- * */
-
- static struct asoc_simple_card_info card_info;
- static struct platform_device card_device;
-
- /*
- * Setup command line parameter
- */
- static short rpi_platform_generation;
- module_param(rpi_platform_generation, short, 0);
- MODULE_PARM_DESC(rpi_platform_generation, "Raspberry Pi generation: 0=Pi0, 1=Pi2/3, 2=Pi4");
-
- /*
- * Dummy callback for release
- */
- void device_release_callback(struct device *dev) { /* do nothing */ };
-
- /*
- * Setup the card info
- */
- static struct asoc_simple_card_info default_card_info = {
- .card = "snd_rpi_i2s_card", // -> snd_soc_card.name
- .name = "simple-card_codec_link", // -> snd_soc_dai_link.name
- .codec = "snd-soc-dummy", // "dmic-codec", // -> snd_soc_dai_link.codec_name
- .platform = "not-set.i2s",
- .daifmt = SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_NB_NF | SND_SOC_DAIFMT_CBS_CFS,
- .cpu_dai = {
- .name = "not-set.i2s", // -> snd_soc_dai_link.cpu_dai_name
- .sysclk = 0
- },
- .codec_dai = {
- .name = "snd-soc-dummy-dai", //"dmic-codec", // -> snd_soc_dai_link.codec_dai_name
- .sysclk = 0
- },
- };
-
- /*
- * Setup the card device
- */
- static struct platform_device default_card_device = {
- .name = "asoc-simple-card", //module alias
- .id = 0,
- .num_resources = 0,
- .dev = {
- .release = &device_release_callback,
- .platform_data = &default_card_info, // *HACK ALERT*
- },
- };
-
- /*
- * Callback for module initialization
- */
- int i2s_mic_rpi_init(void)
- {
- const char *dmaengine = "bcm2708-dmaengine"; //module name
- static char *card_platform;
- int ret;
-
- printk(KERN_INFO "snd-i2smic-rpi: Version %s\n", SND_I2SMIC_RPI_VERSION);
-
- // Set platform
- switch (rpi_platform_generation) {
- case 0:
- // Pi Zero
- card_platform = "20203000.i2s";
- break;
- case 1:
- // Pi 2 and 3
- card_platform = "3f203000.i2s";
- break;
- case 2:
- default:
- // Pi 4
- card_platform = "fe203000.i2s";
- break;
- }
-
- printk(KERN_INFO "snd-i2smic-rpi: Setting platform to %s\n", card_platform);
-
- // request DMA engine module
- ret = request_module(dmaengine);
- pr_alert("request module load '%s': %d\n",dmaengine, ret);
-
- // update info
- card_info = default_card_info;
- card_info.platform = card_platform;
- card_info.cpu_dai.name = card_platform;
-
- card_device = default_card_device;
- card_device.dev.platform_data = &card_info;
-
- // register the card device
- ret = platform_device_register(&card_device);
- pr_alert("register platform device '%s': %d\n",card_device.name, ret);
-
- return 0;
- }
-
- /*
- * Callback for module exit
- */
- void i2s_mic_rpi_exit(void)
- {
- platform_device_unregister(&card_device);
- pr_alert("i2s mic module unloaded\n");
- }
-
- // Plumb it up
- module_init(i2s_mic_rpi_init);
- module_exit(i2s_mic_rpi_exit);
- MODULE_DESCRIPTION("ASoC simple-card I2S Microphone");
- MODULE_AUTHOR("Carter Nelson");
- MODULE_LICENSE("GPL v2");
|