1/* 2 * Handles the Mitac mioa701 SoC system 3 * 4 * Copyright (C) 2008 Robert Jarzmik 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 in version 2 of the License. 9 * 10 * This program is distributed in the hope that it will be useful, 11 * but WITHOUT ANY WARRANTY; without even the implied warranty of 12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 * GNU General Public License for more details. 14 * 15 * You should have received a copy of the GNU General Public License 16 * along with this program; if not, write to the Free Software 17 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 18 * 19 * This is a little schema of the sound interconnections : 20 * 21 * Sagem X200 Wolfson WM9713 22 * +--------+ +-------------------+ Rear Speaker 23 * | | | | /-+ 24 * | +--->----->---+MONOIN SPKL+--->----+-+ | 25 * | GSM | | | | | | 26 * | +--->----->---+PCBEEP SPKR+--->----+-+ | 27 * | CHIP | | | \-+ 28 * | +---<-----<---+MONO | 29 * | | | | Front Speaker 30 * +--------+ | | /-+ 31 * | HPL+--->----+-+ | 32 * | | | | | 33 * | OUT3+--->----+-+ | 34 * | | \-+ 35 * | | 36 * | | Front Micro 37 * | | + 38 * | MIC1+-----<--+o+ 39 * | | + 40 * +-------------------+ --- 41 */ 42 43#include <linux/module.h> 44#include <linux/moduleparam.h> 45#include <linux/platform_device.h> 46 47#include <asm/mach-types.h> 48#include <mach/audio.h> 49 50#include <sound/core.h> 51#include <sound/pcm.h> 52#include <sound/soc.h> 53#include <sound/initval.h> 54#include <sound/ac97_codec.h> 55 56#include "pxa2xx-ac97.h" 57#include "../codecs/wm9713.h" 58 59#define AC97_GPIO_PULL 0x58 60 61/* Use GPIO8 for rear speaker amplifier */ 62static int rear_amp_power(struct snd_soc_codec *codec, int power) 63{ 64 unsigned short reg; 65 66 if (power) { 67 reg = snd_soc_read(codec, AC97_GPIO_CFG); 68 snd_soc_write(codec, AC97_GPIO_CFG, reg | 0x0100); 69 reg = snd_soc_read(codec, AC97_GPIO_PULL); 70 snd_soc_write(codec, AC97_GPIO_PULL, reg | (1<<15)); 71 } else { 72 reg = snd_soc_read(codec, AC97_GPIO_CFG); 73 snd_soc_write(codec, AC97_GPIO_CFG, reg & ~0x0100); 74 reg = snd_soc_read(codec, AC97_GPIO_PULL); 75 snd_soc_write(codec, AC97_GPIO_PULL, reg & ~(1<<15)); 76 } 77 78 return 0; 79} 80 81static int rear_amp_event(struct snd_soc_dapm_widget *widget, 82 struct snd_kcontrol *kctl, int event) 83{ 84 struct snd_soc_codec *codec = widget->dapm->card->rtd[0].codec; 85 86 return rear_amp_power(codec, SND_SOC_DAPM_EVENT_ON(event)); 87} 88 89/* mioa701 machine dapm widgets */ 90static const struct snd_soc_dapm_widget mioa701_dapm_widgets[] = { 91 SND_SOC_DAPM_SPK("Front Speaker", NULL), 92 SND_SOC_DAPM_SPK("Rear Speaker", rear_amp_event), 93 SND_SOC_DAPM_MIC("Headset", NULL), 94 SND_SOC_DAPM_LINE("GSM Line Out", NULL), 95 SND_SOC_DAPM_LINE("GSM Line In", NULL), 96 SND_SOC_DAPM_MIC("Headset Mic", NULL), 97 SND_SOC_DAPM_MIC("Front Mic", NULL), 98}; 99 100static const struct snd_soc_dapm_route audio_map[] = { 101 /* Call Mic */ 102 {"Mic Bias", NULL, "Front Mic"}, 103 {"MIC1", NULL, "Mic Bias"}, 104 105 /* Headset Mic */ 106 {"LINEL", NULL, "Headset Mic"}, 107 {"LINER", NULL, "Headset Mic"}, 108 109 /* GSM Module */ 110 {"MONOIN", NULL, "GSM Line Out"}, 111 {"PCBEEP", NULL, "GSM Line Out"}, 112 {"GSM Line In", NULL, "MONO"}, 113 114 /* headphone connected to HPL, HPR */ 115 {"Headset", NULL, "HPL"}, 116 {"Headset", NULL, "HPR"}, 117 118 /* front speaker connected to HPL, OUT3 */ 119 {"Front Speaker", NULL, "HPL"}, 120 {"Front Speaker", NULL, "OUT3"}, 121 122 /* rear speaker connected to SPKL, SPKR */ 123 {"Rear Speaker", NULL, "SPKL"}, 124 {"Rear Speaker", NULL, "SPKR"}, 125}; 126 127static int mioa701_wm9713_init(struct snd_soc_pcm_runtime *rtd) 128{ 129 struct snd_soc_codec *codec = rtd->codec; 130 131 /* Prepare GPIO8 for rear speaker amplifier */ 132 snd_soc_update_bits(codec, AC97_GPIO_CFG, 0x100, 0x100); 133 134 /* Prepare MIC input */ 135 snd_soc_update_bits(codec, AC97_3D_CONTROL, 0xc000, 0xc000); 136 137 return 0; 138} 139 140static struct snd_soc_ops mioa701_ops; 141 142static struct snd_soc_dai_link mioa701_dai[] = { 143 { 144 .name = "AC97", 145 .stream_name = "AC97 HiFi", 146 .cpu_dai_name = "pxa2xx-ac97", 147 .codec_dai_name = "wm9713-hifi", 148 .codec_name = "wm9713-codec", 149 .init = mioa701_wm9713_init, 150 .platform_name = "pxa-pcm-audio", 151 .ops = &mioa701_ops, 152 }, 153 { 154 .name = "AC97 Aux", 155 .stream_name = "AC97 Aux", 156 .cpu_dai_name = "pxa2xx-ac97-aux", 157 .codec_dai_name ="wm9713-aux", 158 .codec_name = "wm9713-codec", 159 .platform_name = "pxa-pcm-audio", 160 .ops = &mioa701_ops, 161 }, 162}; 163 164static struct snd_soc_card mioa701 = { 165 .name = "MioA701", 166 .owner = THIS_MODULE, 167 .dai_link = mioa701_dai, 168 .num_links = ARRAY_SIZE(mioa701_dai), 169 170 .dapm_widgets = mioa701_dapm_widgets, 171 .num_dapm_widgets = ARRAY_SIZE(mioa701_dapm_widgets), 172 .dapm_routes = audio_map, 173 .num_dapm_routes = ARRAY_SIZE(audio_map), 174}; 175 176static int mioa701_wm9713_probe(struct platform_device *pdev) 177{ 178 int rc; 179 180 if (!machine_is_mioa701()) 181 return -ENODEV; 182 183 mioa701.dev = &pdev->dev; 184 rc = snd_soc_register_card(&mioa701); 185 if (!rc) 186 dev_warn(&pdev->dev, "Be warned that incorrect mixers/muxes setup will" 187 "lead to overheating and possible destruction of your device." 188 " Do not use without a good knowledge of mio's board design!\n"); 189 return rc; 190} 191 192static int mioa701_wm9713_remove(struct platform_device *pdev) 193{ 194 struct snd_soc_card *card = platform_get_drvdata(pdev); 195 196 snd_soc_unregister_card(card); 197 return 0; 198} 199 200static struct platform_driver mioa701_wm9713_driver = { 201 .probe = mioa701_wm9713_probe, 202 .remove = mioa701_wm9713_remove, 203 .driver = { 204 .name = "mioa701-wm9713", 205 .pm = &snd_soc_pm_ops, 206 }, 207}; 208 209module_platform_driver(mioa701_wm9713_driver); 210 211/* Module information */ 212MODULE_AUTHOR("Robert Jarzmik (rjarzmik@free.fr)"); 213MODULE_DESCRIPTION("ALSA SoC WM9713 MIO A701"); 214MODULE_LICENSE("GPL"); 215