1 // SPDX-License-Identifier: GPL-2.0-or-later 2 /* 3 * Driver for generic Bluetooth SCO link 4 * Copyright 2011 Lars-Peter Clausen <lars@metafoo.de> 5 */ 6 7 #include <linux/init.h> 8 #include <linux/module.h> 9 #include <linux/platform_device.h> 10 11 #include <sound/soc.h> 12 13 static const struct snd_soc_dapm_widget bt_sco_widgets[] = { 14 SND_SOC_DAPM_INPUT("RX"), 15 SND_SOC_DAPM_OUTPUT("TX"), 16 SND_SOC_DAPM_AIF_IN("BT_SCO_RX", "Playback", 0, 17 SND_SOC_NOPM, 0, 0), 18 SND_SOC_DAPM_AIF_OUT("BT_SCO_TX", "Capture", 0, 19 SND_SOC_NOPM, 0, 0), 20 SND_SOC_DAPM_AIF_IN("BT_SCO_RX_WB", "WB Playback", 0, 21 SND_SOC_NOPM, 0, 0), 22 SND_SOC_DAPM_AIF_OUT("BT_SCO_TX_WB", "WB Capture", 0, 23 SND_SOC_NOPM, 0, 0), 24 }; 25 26 static const struct snd_soc_dapm_route bt_sco_routes[] = { 27 { "BT_SCO_TX", NULL, "RX" }, 28 { "TX", NULL, "BT_SCO_RX" }, 29 { "BT_SCO_TX_WB", NULL, "RX" }, 30 { "TX", NULL, "BT_SCO_RX_WB" }, 31 }; 32 33 static struct snd_soc_dai_driver bt_sco_dai[] = { 34 { 35 .name = "bt-sco-pcm", 36 .playback = { 37 .stream_name = "Playback", 38 .channels_min = 1, 39 .channels_max = 1, 40 .rates = SNDRV_PCM_RATE_8000, 41 .formats = SNDRV_PCM_FMTBIT_S16_LE, 42 }, 43 .capture = { 44 .stream_name = "Capture", 45 .channels_min = 1, 46 .channels_max = 1, 47 .rates = SNDRV_PCM_RATE_8000, 48 .formats = SNDRV_PCM_FMTBIT_S16_LE, 49 }, 50 }, 51 { 52 .name = "bt-sco-pcm-wb", 53 .playback = { 54 .stream_name = "WB Playback", 55 .channels_min = 1, 56 .channels_max = 1, 57 .rates = SNDRV_PCM_RATE_8000 | SNDRV_PCM_RATE_16000, 58 .formats = SNDRV_PCM_FMTBIT_S16_LE, 59 }, 60 .capture = { 61 .stream_name = "WB Capture", 62 .channels_min = 1, 63 .channels_max = 1, 64 .rates = SNDRV_PCM_RATE_8000 | SNDRV_PCM_RATE_16000, 65 .formats = SNDRV_PCM_FMTBIT_S16_LE, 66 }, 67 } 68 }; 69 70 static const struct snd_soc_component_driver soc_component_dev_bt_sco = { 71 .dapm_widgets = bt_sco_widgets, 72 .num_dapm_widgets = ARRAY_SIZE(bt_sco_widgets), 73 .dapm_routes = bt_sco_routes, 74 .num_dapm_routes = ARRAY_SIZE(bt_sco_routes), 75 .idle_bias_on = 1, 76 .use_pmdown_time = 1, 77 .endianness = 1, 78 }; 79 80 static int bt_sco_probe(struct platform_device *pdev) 81 { 82 return devm_snd_soc_register_component(&pdev->dev, 83 &soc_component_dev_bt_sco, 84 bt_sco_dai, ARRAY_SIZE(bt_sco_dai)); 85 } 86 87 static const struct platform_device_id bt_sco_driver_ids[] = { 88 { 89 .name = "dfbmcs320", 90 }, 91 { 92 .name = "bt-sco", 93 }, 94 {}, 95 }; 96 MODULE_DEVICE_TABLE(platform, bt_sco_driver_ids); 97 98 #if defined(CONFIG_OF) 99 static const struct of_device_id bt_sco_codec_of_match[] = { 100 { .compatible = "delta,dfbmcs320", }, 101 { .compatible = "linux,bt-sco", }, 102 {}, 103 }; 104 MODULE_DEVICE_TABLE(of, bt_sco_codec_of_match); 105 #endif 106 107 static struct platform_driver bt_sco_driver = { 108 .driver = { 109 .name = "bt-sco", 110 .of_match_table = of_match_ptr(bt_sco_codec_of_match), 111 }, 112 .probe = bt_sco_probe, 113 .id_table = bt_sco_driver_ids, 114 }; 115 116 module_platform_driver(bt_sco_driver); 117 118 MODULE_AUTHOR("Lars-Peter Clausen <lars@metafoo.de>"); 119 MODULE_DESCRIPTION("ASoC generic bluetooth sco link driver"); 120 MODULE_LICENSE("GPL"); 121