Back to home page

OSCL-LXR

 
 

    


0001 // SPDX-License-Identifier: GPL-2.0-only
0002 /*
0003  * Handles the Mitac mioa701 SoC system
0004  *
0005  * Copyright (C) 2008 Robert Jarzmik
0006  *
0007  * This is a little schema of the sound interconnections :
0008  *
0009  *    Sagem X200                 Wolfson WM9713
0010  *    +--------+             +-------------------+      Rear Speaker
0011  *    |        |             |                   |           /-+
0012  *    |        +--->----->---+MONOIN         SPKL+--->----+-+  |
0013  *    |  GSM   |             |                   |        | |  |
0014  *    |        +--->----->---+PCBEEP         SPKR+--->----+-+  |
0015  *    |  CHIP  |             |                   |           \-+
0016  *    |        +---<-----<---+MONO               |
0017  *    |        |             |                   |      Front Speaker
0018  *    +--------+             |                   |           /-+
0019  *                           |                HPL+--->----+-+  |
0020  *                           |                   |        | |  |
0021  *                           |               OUT3+--->----+-+  |
0022  *                           |                   |           \-+
0023  *                           |                   |
0024  *                           |                   |     Front Micro
0025  *                           |                   |         +
0026  *                           |               MIC1+-----<--+o+
0027  *                           |                   |         +
0028  *                           +-------------------+        ---
0029  */
0030 
0031 #include <linux/module.h>
0032 #include <linux/moduleparam.h>
0033 #include <linux/platform_device.h>
0034 
0035 #include <asm/mach-types.h>
0036 #include <linux/platform_data/asoc-pxa.h>
0037 
0038 #include <sound/core.h>
0039 #include <sound/pcm.h>
0040 #include <sound/soc.h>
0041 #include <sound/initval.h>
0042 #include <sound/ac97_codec.h>
0043 
0044 #include "../codecs/wm9713.h"
0045 
0046 #define AC97_GPIO_PULL      0x58
0047 
0048 /* Use GPIO8 for rear speaker amplifier */
0049 static int rear_amp_power(struct snd_soc_component *component, int power)
0050 {
0051     unsigned short reg;
0052 
0053     if (power) {
0054         reg = snd_soc_component_read(component, AC97_GPIO_CFG);
0055         snd_soc_component_write(component, AC97_GPIO_CFG, reg | 0x0100);
0056         reg = snd_soc_component_read(component, AC97_GPIO_PULL);
0057         snd_soc_component_write(component, AC97_GPIO_PULL, reg | (1<<15));
0058     } else {
0059         reg = snd_soc_component_read(component, AC97_GPIO_CFG);
0060         snd_soc_component_write(component, AC97_GPIO_CFG, reg & ~0x0100);
0061         reg = snd_soc_component_read(component, AC97_GPIO_PULL);
0062         snd_soc_component_write(component, AC97_GPIO_PULL, reg & ~(1<<15));
0063     }
0064 
0065     return 0;
0066 }
0067 
0068 static int rear_amp_event(struct snd_soc_dapm_widget *widget,
0069               struct snd_kcontrol *kctl, int event)
0070 {
0071     struct snd_soc_card *card = widget->dapm->card;
0072     struct snd_soc_pcm_runtime *rtd;
0073     struct snd_soc_component *component;
0074 
0075     rtd = snd_soc_get_pcm_runtime(card, &card->dai_link[0]);
0076     component = asoc_rtd_to_codec(rtd, 0)->component;
0077     return rear_amp_power(component, SND_SOC_DAPM_EVENT_ON(event));
0078 }
0079 
0080 /* mioa701 machine dapm widgets */
0081 static const struct snd_soc_dapm_widget mioa701_dapm_widgets[] = {
0082     SND_SOC_DAPM_SPK("Front Speaker", NULL),
0083     SND_SOC_DAPM_SPK("Rear Speaker", rear_amp_event),
0084     SND_SOC_DAPM_MIC("Headset", NULL),
0085     SND_SOC_DAPM_LINE("GSM Line Out", NULL),
0086     SND_SOC_DAPM_LINE("GSM Line In", NULL),
0087     SND_SOC_DAPM_MIC("Headset Mic", NULL),
0088     SND_SOC_DAPM_MIC("Front Mic", NULL),
0089 };
0090 
0091 static const struct snd_soc_dapm_route audio_map[] = {
0092     /* Call Mic */
0093     {"Mic Bias", NULL, "Front Mic"},
0094     {"MIC1", NULL, "Mic Bias"},
0095 
0096     /* Headset Mic */
0097     {"LINEL", NULL, "Headset Mic"},
0098     {"LINER", NULL, "Headset Mic"},
0099 
0100     /* GSM Module */
0101     {"MONOIN", NULL, "GSM Line Out"},
0102     {"PCBEEP", NULL, "GSM Line Out"},
0103     {"GSM Line In", NULL, "MONO"},
0104 
0105     /* headphone connected to HPL, HPR */
0106     {"Headset", NULL, "HPL"},
0107     {"Headset", NULL, "HPR"},
0108 
0109     /* front speaker connected to HPL, OUT3 */
0110     {"Front Speaker", NULL, "HPL"},
0111     {"Front Speaker", NULL, "OUT3"},
0112 
0113     /* rear speaker connected to SPKL, SPKR */
0114     {"Rear Speaker", NULL, "SPKL"},
0115     {"Rear Speaker", NULL, "SPKR"},
0116 };
0117 
0118 static int mioa701_wm9713_init(struct snd_soc_pcm_runtime *rtd)
0119 {
0120     struct snd_soc_component *component = asoc_rtd_to_codec(rtd, 0)->component;
0121 
0122     /* Prepare GPIO8 for rear speaker amplifier */
0123     snd_soc_component_update_bits(component, AC97_GPIO_CFG, 0x100, 0x100);
0124 
0125     /* Prepare MIC input */
0126     snd_soc_component_update_bits(component, AC97_3D_CONTROL, 0xc000, 0xc000);
0127 
0128     return 0;
0129 }
0130 
0131 static struct snd_soc_ops mioa701_ops;
0132 
0133 SND_SOC_DAILINK_DEFS(ac97,
0134     DAILINK_COMP_ARRAY(COMP_CPU("pxa2xx-ac97")),
0135     DAILINK_COMP_ARRAY(COMP_CODEC("wm9713-codec", "wm9713-hifi")),
0136     DAILINK_COMP_ARRAY(COMP_PLATFORM("pxa-pcm-audio")));
0137 
0138 SND_SOC_DAILINK_DEFS(ac97_aux,
0139     DAILINK_COMP_ARRAY(COMP_CPU("pxa2xx-ac97-aux")),
0140     DAILINK_COMP_ARRAY(COMP_CODEC("wm9713-codec", "wm9713-aux")),
0141     DAILINK_COMP_ARRAY(COMP_PLATFORM("pxa-pcm-audio")));
0142 
0143 static struct snd_soc_dai_link mioa701_dai[] = {
0144     {
0145         .name = "AC97",
0146         .stream_name = "AC97 HiFi",
0147         .init = mioa701_wm9713_init,
0148         .ops = &mioa701_ops,
0149         SND_SOC_DAILINK_REG(ac97),
0150     },
0151     {
0152         .name = "AC97 Aux",
0153         .stream_name = "AC97 Aux",
0154         .ops = &mioa701_ops,
0155         SND_SOC_DAILINK_REG(ac97_aux),
0156     },
0157 };
0158 
0159 static struct snd_soc_card mioa701 = {
0160     .name = "MioA701",
0161     .owner = THIS_MODULE,
0162     .dai_link = mioa701_dai,
0163     .num_links = ARRAY_SIZE(mioa701_dai),
0164 
0165     .dapm_widgets = mioa701_dapm_widgets,
0166     .num_dapm_widgets = ARRAY_SIZE(mioa701_dapm_widgets),
0167     .dapm_routes = audio_map,
0168     .num_dapm_routes = ARRAY_SIZE(audio_map),
0169 };
0170 
0171 static int mioa701_wm9713_probe(struct platform_device *pdev)
0172 {
0173     int rc;
0174 
0175     if (!machine_is_mioa701())
0176         return -ENODEV;
0177 
0178     mioa701.dev = &pdev->dev;
0179     rc = devm_snd_soc_register_card(&pdev->dev, &mioa701);
0180     if (!rc)
0181         dev_warn(&pdev->dev, "Be warned that incorrect mixers/muxes setup will "
0182              "lead to overheating and possible destruction of your device."
0183              " Do not use without a good knowledge of mio's board design!\n");
0184     return rc;
0185 }
0186 
0187 static struct platform_driver mioa701_wm9713_driver = {
0188     .probe      = mioa701_wm9713_probe,
0189     .driver     = {
0190         .name       = "mioa701-wm9713",
0191         .pm     = &snd_soc_pm_ops,
0192     },
0193 };
0194 
0195 module_platform_driver(mioa701_wm9713_driver);
0196 
0197 /* Module information */
0198 MODULE_AUTHOR("Robert Jarzmik (rjarzmik@free.fr)");
0199 MODULE_DESCRIPTION("ALSA SoC WM9713 MIO A701");
0200 MODULE_LICENSE("GPL");
0201 MODULE_ALIAS("platform:mioa701-wm9713");