ALSA: oxygen: merge HiFier driver into snd-oxygen
authorClemens Ladisch <clemens@ladisch.de>
Tue, 2 Nov 2010 16:08:37 +0000 (17:08 +0100)
committerTakashi Iwai <tiwai@suse.de>
Wed, 3 Nov 2010 07:19:11 +0000 (08:19 +0100)
The snd-hifier driver contains more duplicated code than model-specific
code, so it does not make sense for it to be a separate driver.
Handling the two-channel output restriction can be easily done in the
generic driver.

Signed-off-by: Clemens Ladisch <clemens@ladisch.de>
Signed-off-by: Takashi Iwai <tiwai@suse.de>
Documentation/sound/alsa/ALSA-Configuration.txt
sound/pci/Kconfig
sound/pci/oxygen/Makefile
sound/pci/oxygen/hifier.c [deleted file]
sound/pci/oxygen/oxygen.c

index d0eb696d32e8ade011a695a401fdfc51e42d7be5..f1a1787e71e5d8d9dbe436a6e19f79a77387d3c3 100644 (file)
@@ -974,13 +974,6 @@ Prior to version 0.9.0rc4 options had a 'snd_' prefix. This was removed.
 
     See hdspm.txt for details.
 
-  Module snd-hifier
-  -----------------
-
-    Module for the MediaTek/TempoTec HiFier Fantasia sound card.
-
-    This module supports autoprobe and multiple cards.
-
   Module snd-ice1712
   ------------------
 
@@ -1531,7 +1524,7 @@ Prior to version 0.9.0rc4 options had a 'snd_' prefix. This was removed.
   Module snd-oxygen
   -----------------
 
-    Module for sound cards based on the C-Media CMI8788 chip:
+    Module for sound cards based on the C-Media CMI8787/8788 chip:
     * Asound A-8788
     * AuzenTech X-Meridian
     * Bgears b-Enspirer
@@ -1540,6 +1533,7 @@ Prior to version 0.9.0rc4 options had a 'snd_' prefix. This was removed.
     * HT-Omega Claro halo (XT)
     * Razer Barracuda AC-1
     * Sondigo Inferno
+    * TempoTec HiFier Fantasia
 
     This module supports autoprobe and multiple cards.
 
index 12e34653b8a842ec5dd04778850438bec4b67aa7..dfe406de99351277af9583ac2c98e79844ee94dd 100644 (file)
@@ -209,7 +209,7 @@ config SND_OXYGEN_LIB
         tristate
 
 config SND_OXYGEN
-       tristate "C-Media 8788 (Oxygen)"
+       tristate "C-Media 8787, 8788 (Oxygen)"
        select SND_OXYGEN_LIB
        select SND_PCM
        select SND_MPU401_UART
@@ -224,6 +224,7 @@ config SND_OXYGEN
           * HT-Omega Claro halo (XT)
           * Razer Barracuda AC-1
           * Sondigo Inferno
+          * TempoTec/MediaTek HiFier Fantasia
 
          To compile this driver as a module, choose M here: the module
          will be called snd-oxygen.
@@ -578,18 +579,6 @@ config SND_HDSPM
          To compile this driver as a module, choose M here: the module
          will be called snd-hdspm.
 
-config SND_HIFIER
-       tristate "TempoTec HiFier Fantasia"
-       select SND_OXYGEN_LIB
-       select SND_PCM
-       select SND_MPU401_UART
-       help
-         Say Y here to include support for the MediaTek/TempoTec HiFier
-         Fantasia sound card.
-
-         To compile this driver as a module, choose M here: the module
-         will be called snd-hifier.
-
 config SND_ICE1712
        tristate "ICEnsemble ICE1712 (Envy24)"
        select SND_MPU401_UART
index acd8f15f7bff43226a534633adeb515c3ba1021b..bd67c0d7779cb488b741839c74cadd456f5fa2f8 100644 (file)
@@ -1,10 +1,8 @@
 snd-oxygen-lib-objs := oxygen_io.o oxygen_lib.o oxygen_mixer.o oxygen_pcm.o
-snd-hifier-objs := hifier.o
 snd-oxygen-objs := oxygen.o
 snd-virtuoso-objs := virtuoso.o xonar_lib.o \
        xonar_pcm179x.o xonar_cs43xx.o xonar_wm87x6.o xonar_hdmi.o
 
 obj-$(CONFIG_SND_OXYGEN_LIB) += snd-oxygen-lib.o
-obj-$(CONFIG_SND_HIFIER) += snd-hifier.o
 obj-$(CONFIG_SND_OXYGEN) += snd-oxygen.o
 obj-$(CONFIG_SND_VIRTUOSO) += snd-virtuoso.o
diff --git a/sound/pci/oxygen/hifier.c b/sound/pci/oxygen/hifier.c
deleted file mode 100644 (file)
index 5a87d68..0000000
+++ /dev/null
@@ -1,239 +0,0 @@
-/*
- * C-Media CMI8788 driver for the MediaTek/TempoTec HiFier Fantasia
- *
- * Copyright (c) Clemens Ladisch <clemens@ladisch.de>
- *
- *
- *  This driver is free software; you can redistribute it and/or modify
- *  it under the terms of the GNU General Public License, version 2.
- *
- *  This driver is distributed in the hope that it will be useful,
- *  but WITHOUT ANY WARRANTY; without even the implied warranty of
- *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- *  GNU General Public License for more details.
- *
- *  You should have received a copy of the GNU General Public License
- *  along with this driver; if not, write to the Free Software
- *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA
- */
-
-/*
- * CMI8788:
- *
- * SPI 0 -> AK4396
- */
-
-#include <linux/delay.h>
-#include <linux/pci.h>
-#include <sound/control.h>
-#include <sound/core.h>
-#include <sound/initval.h>
-#include <sound/pcm.h>
-#include <sound/tlv.h>
-#include "oxygen.h"
-#include "ak4396.h"
-
-MODULE_AUTHOR("Clemens Ladisch <clemens@ladisch.de>");
-MODULE_DESCRIPTION("TempoTec HiFier driver");
-MODULE_LICENSE("GPL v2");
-
-static int index[SNDRV_CARDS] = SNDRV_DEFAULT_IDX;
-static char *id[SNDRV_CARDS] = SNDRV_DEFAULT_STR;
-static int enable[SNDRV_CARDS] = SNDRV_DEFAULT_ENABLE_PNP;
-
-module_param_array(index, int, NULL, 0444);
-MODULE_PARM_DESC(index, "card index");
-module_param_array(id, charp, NULL, 0444);
-MODULE_PARM_DESC(id, "ID string");
-module_param_array(enable, bool, NULL, 0444);
-MODULE_PARM_DESC(enable, "enable card");
-
-static DEFINE_PCI_DEVICE_TABLE(hifier_ids) = {
-       { OXYGEN_PCI_SUBID(0x14c3, 0x1710) },
-       { OXYGEN_PCI_SUBID(0x14c3, 0x1711) },
-       { OXYGEN_PCI_SUBID_BROKEN_EEPROM },
-       { }
-};
-MODULE_DEVICE_TABLE(pci, hifier_ids);
-
-struct hifier_data {
-       u8 ak4396_regs[5];
-};
-
-static void ak4396_write(struct oxygen *chip, u8 reg, u8 value)
-{
-       struct hifier_data *data = chip->model_data;
-
-       oxygen_write_spi(chip, OXYGEN_SPI_TRIGGER  |
-                        OXYGEN_SPI_DATA_LENGTH_2 |
-                        OXYGEN_SPI_CLOCK_160 |
-                        (0 << OXYGEN_SPI_CODEC_SHIFT) |
-                        OXYGEN_SPI_CEN_LATCH_CLOCK_HI,
-                        AK4396_WRITE | (reg << 8) | value);
-       data->ak4396_regs[reg] = value;
-}
-
-static void ak4396_write_cached(struct oxygen *chip, u8 reg, u8 value)
-{
-       struct hifier_data *data = chip->model_data;
-
-       if (value != data->ak4396_regs[reg])
-               ak4396_write(chip, reg, value);
-}
-
-static void hifier_registers_init(struct oxygen *chip)
-{
-       struct hifier_data *data = chip->model_data;
-
-       ak4396_write(chip, AK4396_CONTROL_1, AK4396_DIF_24_MSB | AK4396_RSTN);
-       ak4396_write(chip, AK4396_CONTROL_2,
-                    data->ak4396_regs[AK4396_CONTROL_2]);
-       ak4396_write(chip, AK4396_CONTROL_3, AK4396_PCM);
-       ak4396_write(chip, AK4396_LCH_ATT, chip->dac_volume[0]);
-       ak4396_write(chip, AK4396_RCH_ATT, chip->dac_volume[1]);
-}
-
-static void hifier_init(struct oxygen *chip)
-{
-       struct hifier_data *data = chip->model_data;
-
-       data->ak4396_regs[AK4396_CONTROL_2] =
-               AK4396_SMUTE | AK4396_DEM_OFF | AK4396_DFS_NORMAL;
-       hifier_registers_init(chip);
-
-       snd_component_add(chip->card, "AK4396");
-       snd_component_add(chip->card, "CS5340");
-}
-
-static void hifier_cleanup(struct oxygen *chip)
-{
-}
-
-static void hifier_resume(struct oxygen *chip)
-{
-       hifier_registers_init(chip);
-}
-
-static void set_ak4396_params(struct oxygen *chip,
-                              struct snd_pcm_hw_params *params)
-{
-       struct hifier_data *data = chip->model_data;
-       u8 value;
-
-       value = data->ak4396_regs[AK4396_CONTROL_2] & ~AK4396_DFS_MASK;
-       if (params_rate(params) <= 54000)
-               value |= AK4396_DFS_NORMAL;
-       else if (params_rate(params) <= 108000)
-               value |= AK4396_DFS_DOUBLE;
-       else
-               value |= AK4396_DFS_QUAD;
-
-       msleep(1); /* wait for the new MCLK to become stable */
-
-       if (value != data->ak4396_regs[AK4396_CONTROL_2]) {
-               ak4396_write(chip, AK4396_CONTROL_1,
-                            AK4396_DIF_24_MSB);
-               ak4396_write(chip, AK4396_CONTROL_2, value);
-               ak4396_write(chip, AK4396_CONTROL_1,
-                            AK4396_DIF_24_MSB | AK4396_RSTN);
-       }
-}
-
-static void update_ak4396_volume(struct oxygen *chip)
-{
-       ak4396_write_cached(chip, AK4396_LCH_ATT, chip->dac_volume[0]);
-       ak4396_write_cached(chip, AK4396_RCH_ATT, chip->dac_volume[1]);
-}
-
-static void update_ak4396_mute(struct oxygen *chip)
-{
-       struct hifier_data *data = chip->model_data;
-       u8 value;
-
-       value = data->ak4396_regs[AK4396_CONTROL_2] & ~AK4396_SMUTE;
-       if (chip->dac_mute)
-               value |= AK4396_SMUTE;
-       ak4396_write_cached(chip, AK4396_CONTROL_2, value);
-}
-
-static void set_cs5340_params(struct oxygen *chip,
-                             struct snd_pcm_hw_params *params)
-{
-}
-
-static const DECLARE_TLV_DB_LINEAR(ak4396_db_scale, TLV_DB_GAIN_MUTE, 0);
-
-static const struct oxygen_model model_hifier = {
-       .shortname = "C-Media CMI8787",
-       .longname = "C-Media Oxygen HD Audio",
-       .chip = "CMI8788",
-       .init = hifier_init,
-       .cleanup = hifier_cleanup,
-       .resume = hifier_resume,
-       .get_i2s_mclk = oxygen_default_i2s_mclk,
-       .set_dac_params = set_ak4396_params,
-       .set_adc_params = set_cs5340_params,
-       .update_dac_volume = update_ak4396_volume,
-       .update_dac_mute = update_ak4396_mute,
-       .dac_tlv = ak4396_db_scale,
-       .model_data_size = sizeof(struct hifier_data),
-       .device_config = PLAYBACK_0_TO_I2S |
-                        PLAYBACK_1_TO_SPDIF |
-                        CAPTURE_0_FROM_I2S_1,
-       .dac_channels = 2,
-       .dac_volume_min = 0,
-       .dac_volume_max = 255,
-       .function_flags = OXYGEN_FUNCTION_SPI,
-       .dac_i2s_format = OXYGEN_I2S_FORMAT_LJUST,
-       .adc_i2s_format = OXYGEN_I2S_FORMAT_LJUST,
-};
-
-static int __devinit get_hifier_model(struct oxygen *chip,
-                                     const struct pci_device_id *id)
-{
-       chip->model = model_hifier;
-       return 0;
-}
-
-static int __devinit hifier_probe(struct pci_dev *pci,
-                                 const struct pci_device_id *pci_id)
-{
-       static int dev;
-       int err;
-
-       if (dev >= SNDRV_CARDS)
-               return -ENODEV;
-       if (!enable[dev]) {
-               ++dev;
-               return -ENOENT;
-       }
-       err = oxygen_pci_probe(pci, index[dev], id[dev], THIS_MODULE,
-                              hifier_ids, get_hifier_model);
-       if (err >= 0)
-               ++dev;
-       return err;
-}
-
-static struct pci_driver hifier_driver = {
-       .name = "CMI8787HiFier",
-       .id_table = hifier_ids,
-       .probe = hifier_probe,
-       .remove = __devexit_p(oxygen_pci_remove),
-#ifdef CONFIG_PM
-       .suspend = oxygen_pci_suspend,
-       .resume = oxygen_pci_resume,
-#endif
-};
-
-static int __init alsa_card_hifier_init(void)
-{
-       return pci_register_driver(&hifier_driver);
-}
-
-static void __exit alsa_card_hifier_exit(void)
-{
-       pci_unregister_driver(&hifier_driver);
-}
-
-module_init(alsa_card_hifier_init)
-module_exit(alsa_card_hifier_exit)
index 98a8eb3c92f76a614bba10332d519f5fd0e2b26d..5e258b26f044f084d3e51110d2d7478033cf8fe5 100644 (file)
@@ -70,6 +70,7 @@ enum {
        MODEL_MERIDIAN,         /* AuzenTech X-Meridian */
        MODEL_CLARO,            /* HT-Omega Claro */
        MODEL_CLARO_HALO,       /* HT-Omega Claro halo */
+       MODEL_HIFIER,           /* TempoTec HiFier Fantasia */
 };
 
 static DEFINE_PCI_DEVICE_TABLE(oxygen_ids) = {
@@ -81,6 +82,8 @@ static DEFINE_PCI_DEVICE_TABLE(oxygen_ids) = {
        { OXYGEN_PCI_SUBID(0x13f6, 0x8788), .driver_data = MODEL_CMEDIA_REF },
        { OXYGEN_PCI_SUBID(0x13f6, 0xffff), .driver_data = MODEL_CMEDIA_REF },
        { OXYGEN_PCI_SUBID(0x147a, 0xa017), .driver_data = MODEL_CMEDIA_REF },
+       { OXYGEN_PCI_SUBID(0x14c3, 0x1710), .driver_data = MODEL_HIFIER },
+       { OXYGEN_PCI_SUBID(0x14c3, 0x1711), .driver_data = MODEL_HIFIER },
        { OXYGEN_PCI_SUBID(0x1a58, 0x0910), .driver_data = MODEL_CMEDIA_REF },
        { OXYGEN_PCI_SUBID(0x415a, 0x5431), .driver_data = MODEL_MERIDIAN },
        { OXYGEN_PCI_SUBID(0x7284, 0x9761), .driver_data = MODEL_CLARO },
@@ -98,6 +101,7 @@ MODULE_DEVICE_TABLE(pci, oxygen_ids);
 #define GPIO_CLARO_HP          0x0100
 
 struct generic_data {
+       unsigned int dacs;
        u8 ak4396_regs[4][5];
        u16 wm8785_regs[3];
 };
@@ -148,7 +152,7 @@ static void ak4396_registers_init(struct oxygen *chip)
        struct generic_data *data = chip->model_data;
        unsigned int i;
 
-       for (i = 0; i < 4; ++i) {
+       for (i = 0; i < data->dacs; ++i) {
                ak4396_write(chip, i, AK4396_CONTROL_1,
                             AK4396_DIF_24_MSB | AK4396_RSTN);
                ak4396_write(chip, i, AK4396_CONTROL_2,
@@ -166,6 +170,7 @@ static void ak4396_init(struct oxygen *chip)
 {
        struct generic_data *data = chip->model_data;
 
+       data->dacs = chip->model.dac_channels / 2;
        data->ak4396_regs[0][AK4396_CONTROL_2] =
                AK4396_SMUTE | AK4396_DEM_OFF | AK4396_DFS_NORMAL;
        ak4396_registers_init(chip);
@@ -232,6 +237,12 @@ static void claro_halo_init(struct oxygen *chip)
        claro_enable_hp(chip);
 }
 
+static void hifier_init(struct oxygen *chip)
+{
+       ak4396_init(chip);
+       snd_component_add(chip->card, "CS5340");
+}
+
 static void generic_cleanup(struct oxygen *chip)
 {
 }
@@ -268,6 +279,11 @@ static void claro_resume(struct oxygen *chip)
        claro_enable_hp(chip);
 }
 
+static void stereo_resume(struct oxygen *chip)
+{
+       ak4396_registers_init(chip);
+}
+
 static void set_ak4396_params(struct oxygen *chip,
                              struct snd_pcm_hw_params *params)
 {
@@ -286,7 +302,7 @@ static void set_ak4396_params(struct oxygen *chip,
        msleep(1); /* wait for the new MCLK to become stable */
 
        if (value != data->ak4396_regs[0][AK4396_CONTROL_2]) {
-               for (i = 0; i < 4; ++i) {
+               for (i = 0; i < data->dacs; ++i) {
                        ak4396_write(chip, i, AK4396_CONTROL_1,
                                     AK4396_DIF_24_MSB);
                        ak4396_write(chip, i, AK4396_CONTROL_2, value);
@@ -298,9 +314,10 @@ static void set_ak4396_params(struct oxygen *chip,
 
 static void update_ak4396_volume(struct oxygen *chip)
 {
+       struct generic_data *data = chip->model_data;
        unsigned int i;
 
-       for (i = 0; i < 4; ++i) {
+       for (i = 0; i < data->dacs; ++i) {
                ak4396_write_cached(chip, i, AK4396_LCH_ATT,
                                    chip->dac_volume[i * 2]);
                ak4396_write_cached(chip, i, AK4396_RCH_ATT,
@@ -317,7 +334,7 @@ static void update_ak4396_mute(struct oxygen *chip)
        value = data->ak4396_regs[0][AK4396_CONTROL_2] & ~AK4396_SMUTE;
        if (chip->dac_mute)
                value |= AK4396_SMUTE;
-       for (i = 0; i < 4; ++i)
+       for (i = 0; i < data->dacs; ++i)
                ak4396_write_cached(chip, i, AK4396_CONTROL_2, value);
 }
 
@@ -356,6 +373,10 @@ static void set_ak5385_params(struct oxygen *chip,
                              value, GPIO_AK5385_DFS_MASK);
 }
 
+static void set_no_params(struct oxygen *chip, struct snd_pcm_hw_params *params)
+{
+}
+
 static int rolloff_info(struct snd_kcontrol *ctl,
                        struct snd_ctl_elem_info *info)
 {
@@ -400,7 +421,7 @@ static int rolloff_put(struct snd_kcontrol *ctl,
                reg &= ~AK4396_SLOW;
        changed = reg != data->ak4396_regs[0][AK4396_CONTROL_2];
        if (changed) {
-               for (i = 0; i < 4; ++i)
+               for (i = 0; i < data->dacs; ++i)
                        ak4396_write(chip, i, AK4396_CONTROL_2, reg);
        }
        mutex_unlock(&chip->mutex);
@@ -550,6 +571,18 @@ static int __devinit get_oxygen_model(struct oxygen *chip,
                                            CAPTURE_0_FROM_I2S_2 |
                                            CAPTURE_1_FROM_SPDIF;
                break;
+       case MODEL_HIFIER:
+               chip->model.shortname = "C-Media CMI8787";
+               chip->model.chip = "CMI8787";
+               chip->model.init = hifier_init;
+               chip->model.resume = stereo_resume;
+               chip->model.mixer_init = generic_mixer_init;
+               chip->model.set_adc_params = set_no_params;
+               chip->model.device_config = PLAYBACK_0_TO_I2S |
+                                           PLAYBACK_1_TO_SPDIF |
+                                           CAPTURE_0_FROM_I2S_1;
+               chip->model.dac_channels = 2;
+               break;
        }
        if (id->driver_data == MODEL_MERIDIAN ||
            id->driver_data == MODEL_CLARO_HALO) {