1/* 2 * linux/sound/soc/pxa/palm27x.c 3 * 4 * SoC Audio driver for Palm T|X, T5 and LifeDrive 5 * 6 * based on tosa.c 7 * 8 * Copyright (C) 2008 Marek Vasut <marek.vasut@gmail.com> 9 * 10 * This program is free software; you can redistribute it and/or modify 11 * it under the terms of the GNU General Public License version 2 as 12 * published by the Free Software Foundation. 13 * 14 */ 15 16#include <linux/module.h> 17#include <linux/moduleparam.h> 18#include <linux/device.h> 19#include <linux/gpio.h> 20 21#include <sound/core.h> 22#include <sound/pcm.h> 23#include <sound/soc.h> 24#include <sound/jack.h> 25 26#include <asm/mach-types.h> 27#include <mach/audio.h> 28#include <linux/platform_data/asoc-palm27x.h> 29 30#include "../codecs/wm9712.h" 31#include "pxa2xx-ac97.h" 32 33static struct snd_soc_jack hs_jack; 34 35/* Headphones jack detection DAPM pins */ 36static struct snd_soc_jack_pin hs_jack_pins[] = { 37 { 38 .pin = "Headphone Jack", 39 .mask = SND_JACK_HEADPHONE, 40 }, 41}; 42 43/* Headphones jack detection gpios */ 44static struct snd_soc_jack_gpio hs_jack_gpios[] = { 45 [0] = { 46 /* gpio is set on per-platform basis */ 47 .name = "hp-gpio", 48 .report = SND_JACK_HEADPHONE, 49 .debounce_time = 200, 50 }, 51}; 52 53/* Palm27x machine dapm widgets */ 54static const struct snd_soc_dapm_widget palm27x_dapm_widgets[] = { 55 SND_SOC_DAPM_HP("Headphone Jack", NULL), 56 SND_SOC_DAPM_SPK("Ext. Speaker", NULL), 57 SND_SOC_DAPM_MIC("Ext. Microphone", NULL), 58}; 59 60/* PalmTX audio map */ 61static const struct snd_soc_dapm_route audio_map[] = { 62 /* headphone connected to HPOUTL, HPOUTR */ 63 {"Headphone Jack", NULL, "HPOUTL"}, 64 {"Headphone Jack", NULL, "HPOUTR"}, 65 66 /* ext speaker connected to ROUT2, LOUT2 */ 67 {"Ext. Speaker", NULL, "LOUT2"}, 68 {"Ext. Speaker", NULL, "ROUT2"}, 69 70 /* mic connected to MIC1 */ 71 {"MIC1", NULL, "Ext. Microphone"}, 72}; 73 74static struct snd_soc_card palm27x_asoc; 75 76static int palm27x_ac97_init(struct snd_soc_pcm_runtime *rtd) 77{ 78 int err; 79 80 /* Jack detection API stuff */ 81 err = snd_soc_card_jack_new(rtd->card, "Headphone Jack", 82 SND_JACK_HEADPHONE, &hs_jack, hs_jack_pins, 83 ARRAY_SIZE(hs_jack_pins)); 84 if (err) 85 return err; 86 87 err = snd_soc_jack_add_gpios(&hs_jack, ARRAY_SIZE(hs_jack_gpios), 88 hs_jack_gpios); 89 90 return err; 91} 92 93static struct snd_soc_dai_link palm27x_dai[] = { 94{ 95 .name = "AC97 HiFi", 96 .stream_name = "AC97 HiFi", 97 .cpu_dai_name = "pxa2xx-ac97", 98 .codec_dai_name = "wm9712-hifi", 99 .codec_name = "wm9712-codec", 100 .platform_name = "pxa-pcm-audio", 101 .init = palm27x_ac97_init, 102}, 103{ 104 .name = "AC97 Aux", 105 .stream_name = "AC97 Aux", 106 .cpu_dai_name = "pxa2xx-ac97-aux", 107 .codec_dai_name = "wm9712-aux", 108 .codec_name = "wm9712-codec", 109 .platform_name = "pxa-pcm-audio", 110}, 111}; 112 113static struct snd_soc_card palm27x_asoc = { 114 .name = "Palm/PXA27x", 115 .owner = THIS_MODULE, 116 .dai_link = palm27x_dai, 117 .num_links = ARRAY_SIZE(palm27x_dai), 118 .dapm_widgets = palm27x_dapm_widgets, 119 .num_dapm_widgets = ARRAY_SIZE(palm27x_dapm_widgets), 120 .dapm_routes = audio_map, 121 .num_dapm_routes = ARRAY_SIZE(audio_map), 122 .fully_routed = true, 123}; 124 125static int palm27x_asoc_probe(struct platform_device *pdev) 126{ 127 int ret; 128 129 if (!(machine_is_palmtx() || machine_is_palmt5() || 130 machine_is_palmld() || machine_is_palmte2())) 131 return -ENODEV; 132 133 if (!pdev->dev.platform_data) { 134 dev_err(&pdev->dev, "please supply platform_data\n"); 135 return -ENODEV; 136 } 137 138 hs_jack_gpios[0].gpio = ((struct palm27x_asoc_info *) 139 (pdev->dev.platform_data))->jack_gpio; 140 141 palm27x_asoc.dev = &pdev->dev; 142 143 ret = snd_soc_register_card(&palm27x_asoc); 144 if (ret) 145 dev_err(&pdev->dev, "snd_soc_register_card() failed: %d\n", 146 ret); 147 return ret; 148} 149 150static int palm27x_asoc_remove(struct platform_device *pdev) 151{ 152 snd_soc_unregister_card(&palm27x_asoc); 153 return 0; 154} 155 156static struct platform_driver palm27x_wm9712_driver = { 157 .probe = palm27x_asoc_probe, 158 .remove = palm27x_asoc_remove, 159 .driver = { 160 .name = "palm27x-asoc", 161 .pm = &snd_soc_pm_ops, 162 }, 163}; 164 165module_platform_driver(palm27x_wm9712_driver); 166 167/* Module information */ 168MODULE_AUTHOR("Marek Vasut <marek.vasut@gmail.com>"); 169MODULE_DESCRIPTION("ALSA SoC Palm T|X, T5 and LifeDrive"); 170MODULE_LICENSE("GPL"); 171