Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit d16be8ed authored by Pavel Hofman's avatar Pavel Hofman Committed by Takashi Iwai
Browse files

[ALSA] ice1724 - Improved the Juli rate setting



* moving most of clock-specific code to card-specific routines
* support for ESI Juli
* to-be-researched - monitoring of analog/digital inputs

Signed-off-by: default avatarPavel Hofman <dustin@seznam.cz>
Signed-off-by: default avatarTakashi Iwai <tiwai@suse.de>
parent ff73317e
Loading
Loading
Loading
Loading
+1 −0
Original line number Diff line number Diff line
@@ -697,6 +697,7 @@ config SND_ICE1724
	depends on SND
	select SND_MPU401_UART
	select SND_AC97_CODEC
	select SND_VMASTER
	help
	  Say Y here to include support for soundcards based on
	  ICE/VT1724/1720 (Envy24HT/PT) chips.
+9 −0
Original line number Diff line number Diff line
@@ -367,6 +367,15 @@ struct snd_ice1712 {

	/* other board-specific data */
	void *spec;

	/* VT172x specific */
	int pro_rate_default;
	int (*is_spdif_master)(struct snd_ice1712 *ice);
	unsigned int (*get_rate)(struct snd_ice1712 *ice);
	void (*set_rate)(struct snd_ice1712 *ice, unsigned int rate);
	unsigned char (*set_mclk)(struct snd_ice1712 *ice, unsigned int rate);
	void (*set_spdif_clock)(struct snd_ice1712 *ice);

};


+149 −164
Original line number Diff line number Diff line
@@ -106,15 +106,19 @@ static unsigned int PRO_RATE_DEFAULT = 44100;
 *  Basic I/O
 */
 
/*
 *  default rates, default clock routines
 */

/* check whether the clock mode is spdif-in */
static inline int is_spdif_master(struct snd_ice1712 *ice)
static inline int stdclock_is_spdif_master(struct snd_ice1712 *ice)
{
	return (inb(ICEMT1724(ice, RATE)) & VT1724_SPDIF_MASTER) ? 1 : 0;
}

static inline int is_pro_rate_locked(struct snd_ice1712 *ice)
{
	return is_spdif_master(ice) || PRO_RATE_LOCKED;
	return ice->is_spdif_master(ice) || PRO_RATE_LOCKED;
}

/*
@@ -391,49 +395,59 @@ static int snd_vt1724_pcm_trigger(struct snd_pcm_substream *substream, int cmd)
#define DMA_PAUSES	(VT1724_RDMA0_PAUSE|VT1724_PDMA0_PAUSE|VT1724_RDMA1_PAUSE|\
	VT1724_PDMA1_PAUSE|VT1724_PDMA2_PAUSE|VT1724_PDMA3_PAUSE|VT1724_PDMA4_PAUSE)

static int get_max_rate(struct snd_ice1712 *ice)
static const unsigned int stdclock_rate_list[16] = {
	48000, 24000, 12000, 9600, 32000, 16000, 8000, 96000, 44100,
	22050, 11025, 88200, 176400, 0, 192000, 64000
};

static unsigned int stdclock_get_rate(struct snd_ice1712 *ice)
{
	unsigned int rate;
	rate = stdclock_rate_list[inb(ICEMT1724(ice, RATE)) & 15];
	return rate;
}

static void stdclock_set_rate(struct snd_ice1712 *ice, unsigned int rate)
{
	int i;
	for (i = 0; i < ARRAY_SIZE(stdclock_rate_list); i++) {
		if (stdclock_rate_list[i] == rate) {
			outb(i, ICEMT1724(ice, RATE));
			return;
		}
	}
}

static unsigned char stdclock_set_mclk(struct snd_ice1712 *ice,
				       unsigned int rate)
{
	unsigned char val, old;
	/* check MT02 */
	if (ice->eeprom.data[ICE_EEP2_ACLINK] & VT1724_CFG_PRO_I2S) {
		if ((ice->eeprom.data[ICE_EEP2_I2S] & 0x08) && !ice->vt1720)
			return 192000;
		val = old = inb(ICEMT1724(ice, I2S_FORMAT));
		if (rate > 96000)
			val |= VT1724_MT_I2S_MCLK_128X; /* 128x MCLK */
		else
			return 96000;
	} else
		return 48000;
			val &= ~VT1724_MT_I2S_MCLK_128X; /* 256x MCLK */
		if (val != old) {
			outb(val, ICEMT1724(ice, I2S_FORMAT));
			/* master clock changed */
			return 1;
		}
	}
	/* no change in master clock */
	return 0;
}

static void snd_vt1724_set_pro_rate(struct snd_ice1712 *ice, unsigned int rate,
				    int force)
{
	unsigned long flags;
	unsigned char val, old;
	unsigned int i, mclk_change;
	unsigned char mclk_change;
	unsigned int i, old_rate;

	if (rate > get_max_rate(ice))
	if (rate > ice->hw_rates->list[ice->hw_rates->count - 1])
		return;

	switch (rate) {
	case 8000: val = 6; break;
	case 9600: val = 3; break;
	case 11025: val = 10; break;
	case 12000: val = 2; break;
	case 16000: val = 5; break;
	case 22050: val = 9; break;
	case 24000: val = 1; break;
	case 32000: val = 4; break;
	case 44100: val = 8; break;
	case 48000: val = 0; break;
	case 64000: val = 15; break;
	case 88200: val = 11; break;
	case 96000: val = 7; break;
	case 176400: val = 12; break;
	case 192000: val = 14; break;
	default:
		snd_BUG();
		val = 0;
		break;
	}

	spin_lock_irqsave(&ice->reg_lock, flags);
	if ((inb(ICEMT1724(ice, DMA_CONTROL)) & DMA_STARTS) ||
	    (inb(ICEMT1724(ice, DMA_PAUSE)) & DMA_PAUSES)) {
@@ -446,9 +460,9 @@ static void snd_vt1724_set_pro_rate(struct snd_ice1712 *ice, unsigned int rate,
		return;
	}

	old = inb(ICEMT1724(ice, RATE));
	if (force || old != val)
		outb(val, ICEMT1724(ice, RATE));
	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;
@@ -456,19 +470,9 @@ static void snd_vt1724_set_pro_rate(struct snd_ice1712 *ice, unsigned int rate,

	ice->cur_rate = rate;

	/* check MT02 */
	mclk_change = 0;
	if (ice->eeprom.data[ICE_EEP2_ACLINK] & VT1724_CFG_PRO_I2S) {
		val = old = inb(ICEMT1724(ice, I2S_FORMAT));
		if (rate > 96000)
			val |= VT1724_MT_I2S_MCLK_128X; /* 128x MCLK */
		else
			val &= ~VT1724_MT_I2S_MCLK_128X; /* 256x MCLK */
		if (val != old) {
			outb(val, ICEMT1724(ice, I2S_FORMAT));
			mclk_change = 1;
		}
	}
	/* setting master clock */
	mclk_change = ice->set_mclk(ice, rate);

	spin_unlock_irqrestore(&ice->reg_lock, flags);

	if (mclk_change && ice->gpio.i2s_mclk_changed)
@@ -727,12 +731,26 @@ static const struct snd_pcm_hardware snd_vt1724_2ch_stereo =
/*
 * set rate constraints
 */
static void set_std_hw_rates(struct snd_ice1712 *ice)
{
	if (ice->eeprom.data[ICE_EEP2_ACLINK] & VT1724_CFG_PRO_I2S) {
		/* I2S */
		/* VT1720 doesn't support more than 96kHz */
		if ((ice->eeprom.data[ICE_EEP2_I2S] & 0x08) && !ice->vt1720)
			ice->hw_rates = &hw_constraints_rates_192;
		else
			ice->hw_rates = &hw_constraints_rates_96;
	} else {
		/* ACLINK */
		ice->hw_rates = &hw_constraints_rates_48;
	}
}

static int set_rate_constraints(struct snd_ice1712 *ice,
				struct snd_pcm_substream *substream)
{
	struct snd_pcm_runtime *runtime = substream->runtime;
	if (ice->hw_rates) {
		/* hardware specific */

	runtime->hw.rate_min = ice->hw_rates->list[0];
	runtime->hw.rate_max = ice->hw_rates->list[ice->hw_rates->count - 1];
	runtime->hw.rates = SNDRV_PCM_RATE_KNOT;
@@ -740,31 +758,6 @@ static int set_rate_constraints(struct snd_ice1712 *ice,
					  SNDRV_PCM_HW_PARAM_RATE,
					  ice->hw_rates);
}
	if (ice->eeprom.data[ICE_EEP2_ACLINK] & VT1724_CFG_PRO_I2S) {
		/* I2S */
		/* VT1720 doesn't support more than 96kHz */
		if ((ice->eeprom.data[ICE_EEP2_I2S] & 0x08) && !ice->vt1720)
			return snd_pcm_hw_constraint_list(runtime, 0,
							  SNDRV_PCM_HW_PARAM_RATE,
							  &hw_constraints_rates_192);
		else {
			runtime->hw.rates = SNDRV_PCM_RATE_KNOT |
				SNDRV_PCM_RATE_8000_96000;
			runtime->hw.rate_max = 96000;
			return snd_pcm_hw_constraint_list(runtime, 0,
							  SNDRV_PCM_HW_PARAM_RATE,
							  &hw_constraints_rates_96);
		}
	} else if (ice->ac97) {
		/* ACLINK */
		runtime->hw.rate_max = 48000;
		runtime->hw.rates = SNDRV_PCM_RATE_KNOT | SNDRV_PCM_RATE_8000_48000;
		return snd_pcm_hw_constraint_list(runtime, 0,
						  SNDRV_PCM_HW_PARAM_RATE,
						  &hw_constraints_rates_48);
	}
	return 0;
}

/* multi-channel playback needs alignment 8x32bit regardless of the channels
 * actually used
@@ -824,7 +817,7 @@ static int snd_vt1724_playback_pro_close(struct snd_pcm_substream *substream)
	struct snd_ice1712 *ice = snd_pcm_substream_chip(substream);

	if (PRO_RATE_RESET)
		snd_vt1724_set_pro_rate(ice, PRO_RATE_DEFAULT, 0);
		snd_vt1724_set_pro_rate(ice, ice->pro_rate_default, 0);
	ice->playback_pro_substream = NULL;

	return 0;
@@ -835,7 +828,7 @@ static int snd_vt1724_capture_pro_close(struct snd_pcm_substream *substream)
	struct snd_ice1712 *ice = snd_pcm_substream_chip(substream);

	if (PRO_RATE_RESET)
		snd_vt1724_set_pro_rate(ice, PRO_RATE_DEFAULT, 0);
		snd_vt1724_set_pro_rate(ice, ice->pro_rate_default, 0);
	ice->capture_pro_substream = NULL;
	return 0;
}
@@ -980,7 +973,7 @@ static int snd_vt1724_playback_spdif_close(struct snd_pcm_substream *substream)
	struct snd_ice1712 *ice = snd_pcm_substream_chip(substream);

	if (PRO_RATE_RESET)
		snd_vt1724_set_pro_rate(ice, PRO_RATE_DEFAULT, 0);
		snd_vt1724_set_pro_rate(ice, ice->pro_rate_default, 0);
	ice->playback_con_substream = NULL;
	if (ice->spdif.ops.close)
		ice->spdif.ops.close(ice, substream);
@@ -1016,7 +1009,7 @@ static int snd_vt1724_capture_spdif_close(struct snd_pcm_substream *substream)
	struct snd_ice1712 *ice = snd_pcm_substream_chip(substream);

	if (PRO_RATE_RESET)
		snd_vt1724_set_pro_rate(ice, PRO_RATE_DEFAULT, 0);
		snd_vt1724_set_pro_rate(ice, ice->pro_rate_default, 0);
	ice->capture_con_substream = NULL;
	if (ice->spdif.ops.close)
		ice->spdif.ops.close(ice, substream);
@@ -1162,7 +1155,7 @@ static int snd_vt1724_playback_indep_close(struct snd_pcm_substream *substream)
	struct snd_ice1712 *ice = snd_pcm_substream_chip(substream);

	if (PRO_RATE_RESET)
		snd_vt1724_set_pro_rate(ice, PRO_RATE_DEFAULT, 0);
		snd_vt1724_set_pro_rate(ice, ice->pro_rate_default, 0);
	ice->playback_con_substream_ds[substream->number] = NULL;
	ice->pcm_reserved[substream->number] = NULL;

@@ -1580,50 +1573,18 @@ int snd_ice1712_gpio_put(struct snd_kcontrol *kcontrol,
static int snd_vt1724_pro_internal_clock_info(struct snd_kcontrol *kcontrol,
					      struct snd_ctl_elem_info *uinfo)
{
	static const char * const texts_1724[] = {
		"8000",		/* 0: 6 */
		"9600",		/* 1: 3 */
		"11025",	/* 2: 10 */
		"12000",	/* 3: 2 */
		"16000",	/* 4: 5 */
		"22050",	/* 5: 9 */
		"24000",	/* 6: 1 */
		"32000",	/* 7: 4 */
		"44100",	/* 8: 8 */
		"48000",	/* 9: 0 */
		"64000",	/* 10: 15 */
		"88200",	/* 11: 11 */
		"96000",	/* 12: 7 */
		"176400",	/* 13: 12 */
		"192000",	/* 14: 14 */
		"IEC958 Input",	/* 15: -- */
	};
	static const char * const texts_1720[] = {
		"8000",		/* 0: 6 */
		"9600",		/* 1: 3 */
		"11025",	/* 2: 10 */
		"12000",	/* 3: 2 */
		"16000",	/* 4: 5 */
		"22050",	/* 5: 9 */
		"24000",	/* 6: 1 */
		"32000",	/* 7: 4 */
		"44100",	/* 8: 8 */
		"48000",	/* 9: 0 */
		"64000",	/* 10: 15 */
		"88200",	/* 11: 11 */
		"96000",	/* 12: 7 */
		"IEC958 Input",	/* 13: -- */
	};
	struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol);

	uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED;
	uinfo->count = 1;
	uinfo->value.enumerated.items = ice->vt1720 ? 14 : 16;
	uinfo->value.enumerated.items = ice->hw_rates->count + 1;
	if (uinfo->value.enumerated.item >= uinfo->value.enumerated.items)
		uinfo->value.enumerated.item = uinfo->value.enumerated.items - 1;
	strcpy(uinfo->value.enumerated.name,
	       ice->vt1720 ? texts_1720[uinfo->value.enumerated.item] :
	       texts_1724[uinfo->value.enumerated.item]);
	if (uinfo->value.enumerated.item == uinfo->value.enumerated.items - 1)
		strcpy(uinfo->value.enumerated.name, "IEC958 Input");
	else
		sprintf(uinfo->value.enumerated.name, "%d",
			ice->hw_rates->list[uinfo->value.enumerated.item]);
	return 0;
}

@@ -1631,68 +1592,79 @@ static int snd_vt1724_pro_internal_clock_get(struct snd_kcontrol *kcontrol,
					     struct snd_ctl_elem_value *ucontrol)
{
	struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol);
	static const unsigned char xlate[16] = {
		9, 6, 3, 1, 7, 4, 0, 12, 8, 5, 2, 11, 13, 255, 14, 10
	};
	unsigned char val;
	unsigned int i, rate;
	
	spin_lock_irq(&ice->reg_lock);
	if (is_spdif_master(ice)) {
		ucontrol->value.enumerated.item[0] = ice->vt1720 ? 13 : 15;
	if (ice->is_spdif_master(ice)) {
		ucontrol->value.enumerated.item[0] = ice->hw_rates->count;
	} else {
		val = xlate[inb(ICEMT1724(ice, RATE)) & 15];
		if (val == 255) {
			snd_BUG();
			val = 0;
		rate = ice->get_rate(ice);
		ucontrol->value.enumerated.item[0] = 0;
		for (i = 0; i < ice->hw_rates->count; i++) {
			if (ice->hw_rates->list[i] == rate) {
				ucontrol->value.enumerated.item[0] = i;
				break;
			}
		}
		ucontrol->value.enumerated.item[0] = val;
	}
	spin_unlock_irq(&ice->reg_lock);
	return 0;
}

static int snd_vt1724_pro_internal_clock_put(struct snd_kcontrol *kcontrol,
					     struct snd_ctl_elem_value *ucontrol)
/* setting clock to external - SPDIF */
static void stdclock_set_spdif_clock(struct snd_ice1712 *ice)
{
	struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol);
	unsigned char oval;
	int rate;
	int change = 0;
	int spdif = ice->vt1720 ? 13 : 15;

	spin_lock_irq(&ice->reg_lock);
	oval = inb(ICEMT1724(ice, RATE));
	if (ucontrol->value.enumerated.item[0] == spdif) {
	unsigned char i2s_oval;
	oval = inb(ICEMT1724(ice, RATE));
	outb(oval | VT1724_SPDIF_MASTER, ICEMT1724(ice, RATE));
	/* setting 256fs */
	i2s_oval = inb(ICEMT1724(ice, I2S_FORMAT));
		outb(i2s_oval & ~VT1724_MT_I2S_MCLK_128X,
		     ICEMT1724(ice, I2S_FORMAT));
	outb(i2s_oval & ~VT1724_MT_I2S_MCLK_128X, ICEMT1724(ice, I2S_FORMAT));
}

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;

	if (item > spdif)
		return -EINVAL;

	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);
		new_rate = 0;
	} else {
		rate = rates[ucontrol->value.integer.value[0] % 15];
		if (rate <= get_max_rate(ice)) {
			PRO_RATE_DEFAULT = rate;
		/* internal on-card clock */
		new_rate = ice->hw_rates->list[item];
		ice->pro_rate_default = new_rate;
		spin_unlock_irq(&ice->reg_lock);
			snd_vt1724_set_pro_rate(ice, PRO_RATE_DEFAULT, 1);
		snd_vt1724_set_pro_rate(ice, ice->pro_rate_default, 1);
		spin_lock_irq(&ice->reg_lock);
	}
	}
	change = inb(ICEMT1724(ice, RATE)) != oval;
	spin_unlock_irq(&ice->reg_lock);

	if ((oval & VT1724_SPDIF_MASTER) !=
	    (inb(ICEMT1724(ice, RATE)) & VT1724_SPDIF_MASTER)) {
	/* the first reset to the SPDIF master mode? */
	if (old_rate != new_rate && !new_rate) {
		/* notify akm chips as well */
		if (is_spdif_master(ice)) {
		unsigned int i;
		if (ice->gpio.set_pro_rate)
			ice->gpio.set_pro_rate(ice, 0);
		for (i = 0; i < ice->akm_codecs; i++) {
			if (ice->akm[i].ops.set_rate_val)
				ice->akm[i].ops.set_rate_val(&ice->akm[i], 0);
		}
	}
	}
	return change;
	return old_rate != new_rate;
}

static struct snd_kcontrol_new snd_vt1724_pro_internal_clock __devinitdata = {
@@ -2343,6 +2315,19 @@ static int __devinit snd_vt1724_probe(struct pci_dev *pci,
        * was called so in ice1712 driver, and vt1724 driver is derived from
        * ice1712 driver.
        */
	ice->pro_rate_default = PRO_RATE_DEFAULT;
	if (!ice->is_spdif_master)
		ice->is_spdif_master = stdclock_is_spdif_master;
	if (!ice->get_rate)
		ice->get_rate = stdclock_get_rate;
	if (!ice->set_rate)
		ice->set_rate = stdclock_set_rate;
	if (!ice->set_mclk)
		ice->set_mclk = stdclock_set_mclk;
	if (!ice->set_spdif_clock)
		ice->set_spdif_clock = stdclock_set_spdif_clock;
	if (!ice->hw_rates)
		set_std_hw_rates(ice);

	if ((err = snd_vt1724_pcm_profi(ice, pcm_dev++)) < 0) {
		snd_card_free(card);
+440 −31

File changed.

Preview size limit exceeded, changes collapsed.