]> pilppa.org Git - linux-2.6-omap-h63xx.git/blobdiff - sound/pci/ac97/ac97_codec.c
[ALSA] Fix pm_message_t in PXA2XX-AC97 driver
[linux-2.6-omap-h63xx.git] / sound / pci / ac97 / ac97_codec.c
index 6983eea226da2fa227a8f3b0df205bb68ba6d861..f221eba5c32f8baaca11219a54b42a3dca08f199 100644 (file)
@@ -112,6 +112,7 @@ static const ac97_codec_id_t snd_ac97_codec_ids[] = {
 { 0x414c4723, 0xffffffff, "ALC650F",           NULL,   NULL }, /* already patched */
 { 0x414c4720, 0xfffffff0, "ALC650",            patch_alc650,   NULL },
 { 0x414c4760, 0xfffffff0, "ALC655",            patch_alc655,   NULL },
+{ 0x414c4781, 0xffffffff, "ALC658D",           NULL,   NULL }, /* already patched */
 { 0x414c4780, 0xfffffff0, "ALC658",            patch_alc655,   NULL },
 { 0x414c4790, 0xfffffff0, "ALC850",            patch_alc850,   NULL },
 { 0x414c4730, 0xffffffff, "ALC101",            NULL,           NULL },
@@ -157,6 +158,7 @@ static const ac97_codec_id_t snd_ac97_codec_ids[] = {
 { 0x54524123, 0xffffffff, "TR28602",           NULL,           NULL }, // only guess --jk [TR28023 = eMicro EM28023 (new CT1297)]
 { 0x54584e20, 0xffffffff, "TLC320AD9xC",       NULL,           NULL },
 { 0x56494161, 0xffffffff, "VIA1612A",          NULL,           NULL }, // modified ICE1232 with S/PDIF
+{ 0x56494170, 0xffffffff, "VIA1617A",          patch_vt1617a,  NULL }, // modified VT1616 with S/PDIF
 { 0x57454301, 0xffffffff, "W83971D",           NULL,           NULL },
 { 0x574d4c00, 0xffffffff, "WM9701A",           NULL,           NULL },
 { 0x574d4C03, 0xffffffff, "WM9703,WM9707,WM9708,WM9717", patch_wolfson03, NULL},
@@ -1307,16 +1309,18 @@ static int snd_ac97_mixer_build(ac97_t * ac97)
        }
        
        /* build master tone controls */
-       if (snd_ac97_try_volume_mix(ac97, AC97_MASTER_TONE)) {
-               for (idx = 0; idx < 2; idx++) {
-                       if ((err = snd_ctl_add(card, kctl = snd_ac97_cnew(&snd_ac97_controls_tone[idx], ac97))) < 0)
-                               return err;
-                       if (ac97->id == AC97_ID_YMF753) {
-                               kctl->private_value &= ~(0xff << 16);
-                               kctl->private_value |= 7 << 16;
+       if (!(ac97->flags & AC97_HAS_NO_TONE)) {
+               if (snd_ac97_try_volume_mix(ac97, AC97_MASTER_TONE)) {
+                       for (idx = 0; idx < 2; idx++) {
+                               if ((err = snd_ctl_add(card, kctl = snd_ac97_cnew(&snd_ac97_controls_tone[idx], ac97))) < 0)
+                                       return err;
+                               if (ac97->id == AC97_ID_YMF753) {
+                                       kctl->private_value &= ~(0xff << 16);
+                                       kctl->private_value |= 7 << 16;
+                               }
                        }
+                       snd_ac97_write_cache(ac97, AC97_MASTER_TONE, 0x0f0f);
                }
-               snd_ac97_write_cache(ac97, AC97_MASTER_TONE, 0x0f0f);
        }
        
        /* build PC Speaker controls */
@@ -1339,11 +1343,13 @@ static int snd_ac97_mixer_build(ac97_t * ac97)
        }
        
        /* build MIC controls */
-       if (snd_ac97_try_volume_mix(ac97, AC97_MIC)) {
-               if ((err = snd_ac97_cmix_new(card, "Mic Playback", AC97_MIC, ac97)) < 0)
-                       return err;
-               if ((err = snd_ctl_add(card, snd_ac97_cnew(&snd_ac97_controls_mic_boost, ac97))) < 0)
-                       return err;
+       if (!(ac97->flags & AC97_HAS_NO_MIC)) {
+               if (snd_ac97_try_volume_mix(ac97, AC97_MIC)) {
+                       if ((err = snd_ac97_cmix_new(card, "Mic Playback", AC97_MIC, ac97)) < 0)
+                               return err;
+                       if ((err = snd_ctl_add(card, snd_ac97_cnew(&snd_ac97_controls_mic_boost, ac97))) < 0)
+                               return err;
+               }
        }
 
        /* build Line controls */
@@ -1402,12 +1408,14 @@ static int snd_ac97_mixer_build(ac97_t * ac97)
                }
                snd_ac97_write_cache(ac97, AC97_PCM, init_val);
        } else {
-               if (ac97->flags & AC97_HAS_NO_PCM_VOL)
-                       err = snd_ac97_cmute_new(card, "PCM Playback Switch", AC97_PCM, ac97);
-               else
-                       err = snd_ac97_cmix_new(card, "PCM Playback", AC97_PCM, ac97);
-               if (err < 0)
-                       return err;
+               if (!(ac97->flags & AC97_HAS_NO_STD_PCM)) {
+                       if (ac97->flags & AC97_HAS_NO_PCM_VOL)
+                               err = snd_ac97_cmute_new(card, "PCM Playback Switch", AC97_PCM, ac97);
+                       else
+                               err = snd_ac97_cmix_new(card, "PCM Playback", AC97_PCM, ac97);
+                       if (err < 0)
+                               return err;
+               }
        }
 
        /* build Capture controls */
@@ -1549,7 +1557,7 @@ static int snd_ac97_modem_build(snd_card_t * card, ac97_t * ac97)
 
        /* build modem switches */
        for (idx = 0; idx < ARRAY_SIZE(snd_ac97_controls_modem_switches); idx++)
-               if ((err = snd_ctl_add(card, snd_ac97_cnew(&snd_ac97_controls_modem_switches[idx], ac97))) < 0)
+               if ((err = snd_ctl_add(card, snd_ctl_new1(&snd_ac97_controls_modem_switches[idx], ac97))) < 0)
                        return err;
 
        /* build chip specific controls */
@@ -1789,7 +1797,7 @@ int snd_ac97_bus(snd_card_t *card, int num, ac97_bus_ops_t *ops,
 
        snd_assert(card != NULL, return -EINVAL);
        snd_assert(rbus != NULL, return -EINVAL);
-       bus = kcalloc(1, sizeof(*bus), GFP_KERNEL);
+       bus = kzalloc(sizeof(*bus), GFP_KERNEL);
        if (bus == NULL)
                return -ENOMEM;
        bus->card = card;
@@ -1807,6 +1815,39 @@ int snd_ac97_bus(snd_card_t *card, int num, ac97_bus_ops_t *ops,
        return 0;
 }
 
+/* stop no dev release warning */
+static void ac97_device_release(struct device * dev)
+{
+}
+
+/* register ac97 codec to bus */
+static int snd_ac97_dev_register(snd_device_t *device)
+{
+       ac97_t *ac97 = device->device_data;
+       int err;
+
+       ac97->dev.bus = &ac97_bus_type;
+       ac97->dev.parent = ac97->bus->card->dev;
+       ac97->dev.platform_data = ac97;
+       ac97->dev.release = ac97_device_release;
+       snprintf(ac97->dev.bus_id, BUS_ID_SIZE, "card%d-%d", ac97->bus->card->number, ac97->num);
+       if ((err = device_register(&ac97->dev)) < 0) {
+               snd_printk(KERN_ERR "Can't register ac97 bus\n");
+               ac97->dev.bus = NULL;
+               return err;
+       }
+       return 0;
+}
+
+/* unregister ac97 codec */
+static int snd_ac97_dev_unregister(snd_device_t *device)
+{
+       ac97_t *ac97 = device->device_data;
+       if (ac97->dev.bus)
+               device_unregister(&ac97->dev);
+       return snd_ac97_free(ac97);
+}
+
 /* build_ops to do nothing */
 static struct snd_ac97_build_ops null_build_ops;
 
@@ -1840,6 +1881,8 @@ int snd_ac97_mixer(ac97_bus_t *bus, ac97_template_t *template, ac97_t **rac97)
        const ac97_codec_id_t *pid;
        static snd_device_ops_t ops = {
                .dev_free =     snd_ac97_dev_free,
+               .dev_register = snd_ac97_dev_register,
+               .dev_unregister =       snd_ac97_dev_unregister,
        };
 
        snd_assert(rac97 != NULL, return -EINVAL);
@@ -1863,7 +1906,7 @@ int snd_ac97_mixer(ac97_bus_t *bus, ac97_template_t *template, ac97_t **rac97)
        }
 
        card = bus->card;
-       ac97 = kcalloc(1, sizeof(*ac97), GFP_KERNEL);
+       ac97 = kzalloc(sizeof(*ac97), GFP_KERNEL);
        if (ac97 == NULL)
                return -ENOMEM;
        ac97->private_data = template->private_data;
@@ -2539,8 +2582,6 @@ int snd_ac97_tune_hardware(ac97_t *ac97, struct ac97_quirk *quirk, const char *o
 {
        int result;
 
-       snd_assert(quirk, return -EINVAL);
-
        /* quirk overriden? */
        if (override && strcmp(override, "-1") && strcmp(override, "default")) {
                result = apply_quirk_str(ac97, override);
@@ -2549,6 +2590,9 @@ int snd_ac97_tune_hardware(ac97_t *ac97, struct ac97_quirk *quirk, const char *o
                return result;
        }
 
+       if (! quirk)
+               return -EINVAL;
+
        for (; quirk->subvendor; quirk++) {
                if (quirk->subvendor != ac97->subsystem_vendor)
                        continue;