1/* 2 * linux/sound/soc/pxa/ttc_dkb.c 3 * 4 * Copyright (C) 2012 Marvell International Ltd. 5 * 6 * This program is free software; you can redistribute it and/or modify 7 * it under the terms of the GNU General Public License as published by 8 * the Free Software Foundation; either version 2 of the License, or 9 * (at your option) any later version. 10 * 11 * This program is distributed in the hope that it will be useful, 12 * but WITHOUT ANY WARRANTY; without even the implied warranty of 13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 * GNU General Public License for more details. 15 * 16 * You should have received a copy of the GNU General Public License 17 * along with this program; if not, write to the Free Software 18 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 19 * 20 */ 21#include <linux/module.h> 22#include <linux/moduleparam.h> 23#include <sound/core.h> 24#include <sound/pcm.h> 25#include <sound/soc.h> 26#include <sound/jack.h> 27#include <asm/mach-types.h> 28#include <sound/pcm_params.h> 29#include "../codecs/88pm860x-codec.h" 30 31static struct snd_soc_jack hs_jack, mic_jack; 32 33static struct snd_soc_jack_pin hs_jack_pins[] = { 34 { .pin = "Headset Stereophone", .mask = SND_JACK_HEADPHONE, }, 35}; 36 37static struct snd_soc_jack_pin mic_jack_pins[] = { 38 { .pin = "Headset Mic 2", .mask = SND_JACK_MICROPHONE, }, 39}; 40 41/* ttc machine dapm widgets */ 42static const struct snd_soc_dapm_widget ttc_dapm_widgets[] = { 43 SND_SOC_DAPM_HP("Headset Stereophone", NULL), 44 SND_SOC_DAPM_LINE("Lineout Out 1", NULL), 45 SND_SOC_DAPM_LINE("Lineout Out 2", NULL), 46 SND_SOC_DAPM_SPK("Ext Speaker", NULL), 47 SND_SOC_DAPM_MIC("Ext Mic 1", NULL), 48 SND_SOC_DAPM_MIC("Headset Mic 2", NULL), 49 SND_SOC_DAPM_MIC("Ext Mic 3", NULL), 50}; 51 52/* ttc machine audio map */ 53static const struct snd_soc_dapm_route ttc_audio_map[] = { 54 {"Headset Stereophone", NULL, "HS1"}, 55 {"Headset Stereophone", NULL, "HS2"}, 56 57 {"Ext Speaker", NULL, "LSP"}, 58 {"Ext Speaker", NULL, "LSN"}, 59 60 {"Lineout Out 1", NULL, "LINEOUT1"}, 61 {"Lineout Out 2", NULL, "LINEOUT2"}, 62 63 {"MIC1P", NULL, "Mic1 Bias"}, 64 {"MIC1N", NULL, "Mic1 Bias"}, 65 {"Mic1 Bias", NULL, "Ext Mic 1"}, 66 67 {"MIC2P", NULL, "Mic1 Bias"}, 68 {"MIC2N", NULL, "Mic1 Bias"}, 69 {"Mic1 Bias", NULL, "Headset Mic 2"}, 70 71 {"MIC3P", NULL, "Mic3 Bias"}, 72 {"MIC3N", NULL, "Mic3 Bias"}, 73 {"Mic3 Bias", NULL, "Ext Mic 3"}, 74}; 75 76static int ttc_pm860x_init(struct snd_soc_pcm_runtime *rtd) 77{ 78 struct snd_soc_codec *codec = rtd->codec; 79 80 /* Headset jack detection */ 81 snd_soc_card_jack_new(rtd->card, "Headphone Jack", SND_JACK_HEADPHONE | 82 SND_JACK_BTN_0 | SND_JACK_BTN_1 | SND_JACK_BTN_2, 83 &hs_jack, hs_jack_pins, ARRAY_SIZE(hs_jack_pins)); 84 snd_soc_card_jack_new(rtd->card, "Microphone Jack", SND_JACK_MICROPHONE, 85 &mic_jack, mic_jack_pins, 86 ARRAY_SIZE(mic_jack_pins)); 87 88 /* headphone, microphone detection & headset short detection */ 89 pm860x_hs_jack_detect(codec, &hs_jack, SND_JACK_HEADPHONE, 90 SND_JACK_BTN_0, SND_JACK_BTN_1, SND_JACK_BTN_2); 91 pm860x_mic_jack_detect(codec, &hs_jack, SND_JACK_MICROPHONE); 92 93 return 0; 94} 95 96/* ttc/td-dkb digital audio interface glue - connects codec <--> CPU */ 97static struct snd_soc_dai_link ttc_pm860x_hifi_dai[] = { 98{ 99 .name = "88pm860x i2s", 100 .stream_name = "audio playback", 101 .codec_name = "88pm860x-codec", 102 .platform_name = "mmp-pcm-audio", 103 .cpu_dai_name = "pxa-ssp-dai.1", 104 .codec_dai_name = "88pm860x-i2s", 105 .dai_fmt = SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_NB_NF | 106 SND_SOC_DAIFMT_CBM_CFM, 107 .init = ttc_pm860x_init, 108}, 109}; 110 111/* ttc/td audio machine driver */ 112static struct snd_soc_card ttc_dkb_card = { 113 .name = "ttc-dkb-hifi", 114 .owner = THIS_MODULE, 115 .dai_link = ttc_pm860x_hifi_dai, 116 .num_links = ARRAY_SIZE(ttc_pm860x_hifi_dai), 117 118 .dapm_widgets = ttc_dapm_widgets, 119 .num_dapm_widgets = ARRAY_SIZE(ttc_dapm_widgets), 120 .dapm_routes = ttc_audio_map, 121 .num_dapm_routes = ARRAY_SIZE(ttc_audio_map), 122}; 123 124static int ttc_dkb_probe(struct platform_device *pdev) 125{ 126 struct snd_soc_card *card = &ttc_dkb_card; 127 int ret; 128 129 card->dev = &pdev->dev; 130 131 ret = devm_snd_soc_register_card(&pdev->dev, card); 132 if (ret) 133 dev_err(&pdev->dev, "snd_soc_register_card() failed: %d\n", 134 ret); 135 136 return ret; 137} 138 139static struct platform_driver ttc_dkb_driver = { 140 .driver = { 141 .name = "ttc-dkb-audio", 142 .pm = &snd_soc_pm_ops, 143 }, 144 .probe = ttc_dkb_probe, 145}; 146 147module_platform_driver(ttc_dkb_driver); 148 149/* Module information */ 150MODULE_AUTHOR("Qiao Zhou, <zhouqiao@marvell.com>"); 151MODULE_DESCRIPTION("ALSA SoC TTC DKB"); 152MODULE_LICENSE("GPL"); 153MODULE_ALIAS("platform:ttc-dkb-audio"); 154