Merge branch 'topic/ice1724-quartet' into topic/hda
authorTakashi Iwai <tiwai@suse.de>
Tue, 1 Dec 2009 14:57:01 +0000 (15:57 +0100)
committerTakashi Iwai <tiwai@suse.de>
Tue, 1 Dec 2009 14:57:01 +0000 (15:57 +0100)
1  2 
sound/pci/ice1712/ice1712.c
sound/pci/ice1712/ice1724.c

@@@ -298,6 -298,16 +298,16 @@@ static void snd_ice1712_set_gpio_dir(st
        inb(ICEREG(ice, DATA)); /* dummy read for pci-posting */
  }
  
+ static unsigned int snd_ice1712_get_gpio_dir(struct snd_ice1712 *ice)
+ {
+       return snd_ice1712_read(ice, ICE1712_IREG_GPIO_DIRECTION);
+ }
+ static unsigned int snd_ice1712_get_gpio_mask(struct snd_ice1712 *ice)
+ {
+       return snd_ice1712_read(ice, ICE1712_IREG_GPIO_WRITE_MASK);
+ }
  static void snd_ice1712_set_gpio_mask(struct snd_ice1712 *ice, unsigned int data)
  {
        snd_ice1712_write(ice, ICE1712_IREG_GPIO_WRITE_MASK, data);
@@@ -2259,7 -2269,7 +2269,7 @@@ static int snd_ice1712_pro_peak_get(str
  }
  
  static struct snd_kcontrol_new snd_ice1712_mixer_pro_peak __devinitdata = {
 -      .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
 +      .iface = SNDRV_CTL_ELEM_IFACE_PCM,
        .name = "Multi Track Peak",
        .access = SNDRV_CTL_ELEM_ACCESS_READ | SNDRV_CTL_ELEM_ACCESS_VOLATILE,
        .info = snd_ice1712_pro_peak_info,
@@@ -2557,7 -2567,9 +2567,9 @@@ static int __devinit snd_ice1712_create
        mutex_init(&ice->i2c_mutex);
        mutex_init(&ice->open_mutex);
        ice->gpio.set_mask = snd_ice1712_set_gpio_mask;
+       ice->gpio.get_mask = snd_ice1712_get_gpio_mask;
        ice->gpio.set_dir = snd_ice1712_set_gpio_dir;
+       ice->gpio.get_dir = snd_ice1712_get_gpio_dir;
        ice->gpio.set_data = snd_ice1712_set_gpio_data;
        ice->gpio.get_data = snd_ice1712_get_gpio_data;
  
@@@ -53,6 -53,7 +53,7 @@@
  #include "phase.h"
  #include "wtm.h"
  #include "se.h"
+ #include "quartet.h"
  
  MODULE_AUTHOR("Jaroslav Kysela <perex@perex.cz>");
  MODULE_DESCRIPTION("VIA ICEnsemble ICE1724/1720 (Envy24HT/PT)");
@@@ -70,6 -71,7 +71,7 @@@ MODULE_SUPPORTED_DEVICE("{
               PHASE_DEVICE_DESC
               WTM_DEVICE_DESC
               SE_DEVICE_DESC
+              QTET_DEVICE_DESC
                "{VIA,VT1720},"
                "{VIA,VT1724},"
                "{ICEnsemble,Generic ICE1724},"
@@@ -104,6 -106,8 +106,8 @@@ static int PRO_RATE_LOCKED
  static int PRO_RATE_RESET = 1;
  static unsigned int PRO_RATE_DEFAULT = 44100;
  
+ static char *ext_clock_names[1] = { "IEC958 In" };
  /*
   *  Basic I/O
   */
@@@ -118,9 -122,12 +122,12 @@@ static inline int stdclock_is_spdif_mas
        return (inb(ICEMT1724(ice, RATE)) & VT1724_SPDIF_MASTER) ? 1 : 0;
  }
  
+ /*
+  * locking rate makes sense only for internal clock mode
+  */
  static inline int is_pro_rate_locked(struct snd_ice1712 *ice)
  {
-       return ice->is_spdif_master(ice) || PRO_RATE_LOCKED;
+       return (!ice->is_spdif_master(ice)) && PRO_RATE_LOCKED;
  }
  
  /*
@@@ -196,6 -203,12 +203,12 @@@ static void snd_vt1724_set_gpio_dir(str
        inw(ICEREG1724(ice, GPIO_DIRECTION)); /* dummy read for pci-posting */
  }
  
+ /* get gpio direction 0 = read, 1 = write */
+ static unsigned int snd_vt1724_get_gpio_dir(struct snd_ice1712 *ice)
+ {
+       return inl(ICEREG1724(ice, GPIO_DIRECTION));
+ }
  /* set the gpio mask (0 = writable) */
  static void snd_vt1724_set_gpio_mask(struct snd_ice1712 *ice, unsigned int data)
  {
        inw(ICEREG1724(ice, GPIO_WRITE_MASK)); /* dummy read for pci-posting */
  }
  
+ static unsigned int snd_vt1724_get_gpio_mask(struct snd_ice1712 *ice)
+ {
+       unsigned int mask;
+       if (!ice->vt1720)
+               mask = (unsigned int)inb(ICEREG1724(ice, GPIO_WRITE_MASK_22));
+       else
+               mask = 0;
+       mask = (mask << 16) | inw(ICEREG1724(ice, GPIO_WRITE_MASK));
+       return mask;
+ }
  static void snd_vt1724_set_gpio_data(struct snd_ice1712 *ice, unsigned int data)
  {
        outw(data, ICEREG1724(ice, GPIO_DATA));
@@@ -648,19 -672,25 +672,25 @@@ static int snd_vt1724_set_pro_rate(stru
            (inb(ICEMT1724(ice, DMA_PAUSE)) & DMA_PAUSES)) {
                /* running? we cannot change the rate now... */
                spin_unlock_irqrestore(&ice->reg_lock, flags);
 -              return -EBUSY;
 +              return ((rate == ice->cur_rate) && !force) ? 0 : -EBUSY;
        }
        if (!force && is_pro_rate_locked(ice)) {
+               /* comparing required and current rate - makes sense for
+                * internal clock only */
                spin_unlock_irqrestore(&ice->reg_lock, flags);
                return (rate == ice->cur_rate) ? 0 : -EBUSY;
        }
  
-       old_rate = ice->get_rate(ice);
-       if (force || (old_rate != rate))
-               ice->set_rate(ice, rate);
-       else if (rate == ice->cur_rate) {
-               spin_unlock_irqrestore(&ice->reg_lock, flags);
-               return 0;
+       if (force || !ice->is_spdif_master(ice)) {
+               /* force means the rate was switched by ucontrol, otherwise
+                * setting clock rate for internal clock mode */
+               old_rate = ice->get_rate(ice);
+               if (force || (old_rate != rate))
+                       ice->set_rate(ice, rate);
+               else if (rate == ice->cur_rate) {
+                       spin_unlock_irqrestore(&ice->reg_lock, flags);
+                       return 0;
+               }
        }
  
        ice->cur_rate = rate;
@@@ -1016,6 -1046,8 +1046,8 @@@ static int snd_vt1724_playback_pro_open
                                   VT1724_BUFFER_ALIGN);
        snd_pcm_hw_constraint_step(runtime, 0, SNDRV_PCM_HW_PARAM_BUFFER_BYTES,
                                   VT1724_BUFFER_ALIGN);
+       if (ice->pro_open)
+               ice->pro_open(ice, substream);
        return 0;
  }
  
@@@ -1034,6 -1066,8 +1066,8 @@@ static int snd_vt1724_capture_pro_open(
                                   VT1724_BUFFER_ALIGN);
        snd_pcm_hw_constraint_step(runtime, 0, SNDRV_PCM_HW_PARAM_BUFFER_BYTES,
                                   VT1724_BUFFER_ALIGN);
+       if (ice->pro_open)
+               ice->pro_open(ice, substream);
        return 0;
  }
  
@@@ -1294,7 -1328,7 +1328,7 @@@ static int __devinit snd_vt1724_pcm_spd
  
        snd_pcm_lib_preallocate_pages_for_all(pcm, SNDRV_DMA_TYPE_DEV,
                                              snd_dma_pci_data(ice->pci),
 -                                            64*1024, 64*1024);
 +                                            256*1024, 256*1024);
  
        ice->pcm = pcm;
  
@@@ -1408,7 -1442,7 +1442,7 @@@ static int __devinit snd_vt1724_pcm_ind
  
        snd_pcm_lib_preallocate_pages_for_all(pcm, SNDRV_DMA_TYPE_DEV,
                                              snd_dma_pci_data(ice->pci),
 -                                            64*1024, 64*1024);
 +                                            256*1024, 256*1024);
  
        ice->pcm_ds = pcm;
  
@@@ -1787,15 -1821,21 +1821,21 @@@ static int snd_vt1724_pro_internal_cloc
                                              struct snd_ctl_elem_info *uinfo)
  {
        struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol);
+       int hw_rates_count = ice->hw_rates->count;
        uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED;
        uinfo->count = 1;
-       uinfo->value.enumerated.items = ice->hw_rates->count + 1;
+       uinfo->value.enumerated.items = hw_rates_count + ice->ext_clock_count;
+       /* upper limit - keep at top */
        if (uinfo->value.enumerated.item >= uinfo->value.enumerated.items)
                uinfo->value.enumerated.item = uinfo->value.enumerated.items - 1;
-       if (uinfo->value.enumerated.item == uinfo->value.enumerated.items - 1)
-               strcpy(uinfo->value.enumerated.name, "IEC958 Input");
+       if (uinfo->value.enumerated.item >= hw_rates_count)
+               /* ext_clock items */
+               strcpy(uinfo->value.enumerated.name,
+                               ice->ext_clock_names[
+                               uinfo->value.enumerated.item - hw_rates_count]);
        else
+               /* int clock items */
                sprintf(uinfo->value.enumerated.name, "%d",
                        ice->hw_rates->list[uinfo->value.enumerated.item]);
        return 0;
@@@ -1809,7 -1849,8 +1849,8 @@@ static int snd_vt1724_pro_internal_cloc
  
        spin_lock_irq(&ice->reg_lock);
        if (ice->is_spdif_master(ice)) {
-               ucontrol->value.enumerated.item[0] = ice->hw_rates->count;
+               ucontrol->value.enumerated.item[0] = ice->hw_rates->count +
+                       ice->get_spdif_master_type(ice);
        } else {
                rate = ice->get_rate(ice);
                ucontrol->value.enumerated.item[0] = 0;
        return 0;
  }
  
+ static int stdclock_get_spdif_master_type(struct snd_ice1712 *ice)
+ {
+       /* standard external clock - only single type - SPDIF IN */
+       return 0;
+ }
  /* setting clock to external - SPDIF */
- static void stdclock_set_spdif_clock(struct snd_ice1712 *ice)
+ static int stdclock_set_spdif_clock(struct snd_ice1712 *ice, int type)
  {
        unsigned char oval;
        unsigned char i2s_oval;
        /* setting 256fs */
        i2s_oval = inb(ICEMT1724(ice, I2S_FORMAT));
        outb(i2s_oval & ~VT1724_MT_I2S_MCLK_128X, ICEMT1724(ice, I2S_FORMAT));
+       return 0;
  }
  
  static int snd_vt1724_pro_internal_clock_put(struct snd_kcontrol *kcontrol,
                                             struct snd_ctl_elem_value *ucontrol)
  {
        struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol);
        unsigned int old_rate, new_rate;
        unsigned int item = ucontrol->value.enumerated.item[0];
-       unsigned int spdif = ice->hw_rates->count;
+       unsigned int first_ext_clock = ice->hw_rates->count;
  
-       if (item > spdif)
+       if (item >  first_ext_clock + ice->ext_clock_count - 1)
                return -EINVAL;
  
+       /* if rate = 0 => external clock */
        spin_lock_irq(&ice->reg_lock);
        if (ice->is_spdif_master(ice))
                old_rate = 0;
        else
                old_rate = ice->get_rate(ice);
-       if (item == spdif) {
-               /* switching to external clock via SPDIF */
-               ice->set_spdif_clock(ice);
+       if (item >= first_ext_clock) {
+               /* switching to external clock */
+               ice->set_spdif_clock(ice, item - first_ext_clock);
                new_rate = 0;
        } else {
                /* internal on-card clock */
        }
        spin_unlock_irq(&ice->reg_lock);
  
-       /* the first reset to the SPDIF master mode? */
+       /* the first switch to the ext. clock mode? */
        if (old_rate != new_rate && !new_rate) {
                /* notify akm chips as well */
                unsigned int i;
@@@ -2110,7 -2160,7 +2160,7 @@@ static int snd_vt1724_pro_peak_get(stru
  }
  
  static struct snd_kcontrol_new snd_vt1724_mixer_pro_peak __devinitdata = {
 -      .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
 +      .iface = SNDRV_CTL_ELEM_IFACE_PCM,
        .name = "Multi Track Peak",
        .access = SNDRV_CTL_ELEM_ACCESS_READ | SNDRV_CTL_ELEM_ACCESS_VOLATILE,
        .info = snd_vt1724_pro_peak_info,
@@@ -2136,6 -2186,7 +2186,7 @@@ static struct snd_ice1712_card_info *ca
        snd_vt1724_phase_cards,
        snd_vt1724_wtm_cards,
        snd_vt1724_se_cards,
+       snd_vt1724_qtet_cards,
        NULL,
  };
  
@@@ -2434,7 -2485,9 +2485,9 @@@ static int __devinit snd_vt1724_create(
        mutex_init(&ice->open_mutex);
        mutex_init(&ice->i2c_mutex);
        ice->gpio.set_mask = snd_vt1724_set_gpio_mask;
+       ice->gpio.get_mask = snd_vt1724_get_gpio_mask;
        ice->gpio.set_dir = snd_vt1724_set_gpio_dir;
+       ice->gpio.get_dir = snd_vt1724_get_gpio_dir;
        ice->gpio.set_data = snd_vt1724_set_gpio_data;
        ice->gpio.get_data = snd_vt1724_get_gpio_data;
        ice->card = card;
@@@ -2522,6 -2575,9 +2575,9 @@@ static int __devinit snd_vt1724_probe(s
                return err;
        }
  
+       /* field init before calling chip_init */
+       ice->ext_clock_count = 0;
        for (tbl = card_tables; *tbl; tbl++) {
                for (c = *tbl; c->subvendor; c++) {
                        if (c->subvendor == ice->eeprom.subvendor) {
@@@ -2560,6 -2616,13 +2616,13 @@@ __found
                ice->set_mclk = stdclock_set_mclk;
        if (!ice->set_spdif_clock)
                ice->set_spdif_clock = stdclock_set_spdif_clock;
+       if (!ice->get_spdif_master_type)
+               ice->get_spdif_master_type = stdclock_get_spdif_master_type;
+       if (!ice->ext_clock_names)
+               ice->ext_clock_names = ext_clock_names;
+       if (!ice->ext_clock_count)
+               ice->ext_clock_count = ARRAY_SIZE(ext_clock_names);
        if (!ice->hw_rates)
                set_std_hw_rates(ice);
  
@@@ -2719,7 -2782,7 +2782,7 @@@ static int snd_vt1724_resume(struct pci
  
        if (ice->pm_saved_is_spdif_master) {
                /* switching to external clock via SPDIF */
-               ice->set_spdif_clock(ice);
+               ice->set_spdif_clock(ice, 0);
        } else {
                /* internal on-card clock */
                snd_vt1724_set_pro_rate(ice, ice->pro_rate_default, 1);