⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 hdspm.c

📁 底层驱动开发
💻 C
📖 第 1 页 / 共 5 页
字号:
	uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED;	uinfo->count = 1;	uinfo->value.enumerated.items = 2;	if (uinfo->value.enumerated.item >= uinfo->value.enumerated.items)		uinfo->value.enumerated.item =		    uinfo->value.enumerated.items - 1;	strcpy(uinfo->value.enumerated.name,	       texts[uinfo->value.enumerated.item]);	return 0;}static int snd_hdspm_get_input_select(snd_kcontrol_t * kcontrol,				      snd_ctl_elem_value_t * ucontrol){	hdspm_t *hdspm = snd_kcontrol_chip(kcontrol);	spin_lock_irq(&hdspm->lock);	ucontrol->value.enumerated.item[0] = hdspm_input_select(hdspm);	spin_unlock_irq(&hdspm->lock);	return 0;}static int snd_hdspm_put_input_select(snd_kcontrol_t * kcontrol,				      snd_ctl_elem_value_t * ucontrol){	hdspm_t *hdspm = snd_kcontrol_chip(kcontrol);	int change;	unsigned int val;	if (!snd_hdspm_use_is_exclusive(hdspm))		return -EBUSY;	val = ucontrol->value.integer.value[0] & 1;	spin_lock_irq(&hdspm->lock);	change = (int) val != hdspm_input_select(hdspm);	hdspm_set_input_select(hdspm, val);	spin_unlock_irq(&hdspm->lock);	return change;}/*           Simple Mixer  deprecated since to much faders ???  MIXER interface says output (source, destination, value)   where source > MAX_channels are playback channels    on MADICARD   - playback mixer matrix: [channelout+64] [output] [value]  - input(thru) mixer matrix: [channelin] [output] [value]  (better do 2 kontrols for seperation ?)*/#define HDSPM_MIXER(xname, xindex) \{ .iface = SNDRV_CTL_ELEM_IFACE_HWDEP, \  .name = xname, \  .index = xindex, \  .device = 0, \  .access = SNDRV_CTL_ELEM_ACCESS_READWRITE | \		 SNDRV_CTL_ELEM_ACCESS_VOLATILE, \  .info = snd_hdspm_info_mixer, \  .get = snd_hdspm_get_mixer, \  .put = snd_hdspm_put_mixer \}static int snd_hdspm_info_mixer(snd_kcontrol_t * kcontrol,				snd_ctl_elem_info_t * uinfo){	uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER;	uinfo->count = 3;	uinfo->value.integer.min = 0;	uinfo->value.integer.max = 65535;	uinfo->value.integer.step = 1;	return 0;}static int snd_hdspm_get_mixer(snd_kcontrol_t * kcontrol,			       snd_ctl_elem_value_t * ucontrol){	hdspm_t *hdspm = snd_kcontrol_chip(kcontrol);	int source;	int destination;	source = ucontrol->value.integer.value[0];	if (source < 0)		source = 0;	else if (source >= 2 * HDSPM_MAX_CHANNELS)		source = 2 * HDSPM_MAX_CHANNELS - 1;	destination = ucontrol->value.integer.value[1];	if (destination < 0)		destination = 0;	else if (destination >= HDSPM_MAX_CHANNELS)		destination = HDSPM_MAX_CHANNELS - 1;	spin_lock_irq(&hdspm->lock);	if (source >= HDSPM_MAX_CHANNELS)		ucontrol->value.integer.value[2] =		    hdspm_read_pb_gain(hdspm, destination,				       source - HDSPM_MAX_CHANNELS);	else		ucontrol->value.integer.value[2] =		    hdspm_read_in_gain(hdspm, destination, source);	spin_unlock_irq(&hdspm->lock);	return 0;}static int snd_hdspm_put_mixer(snd_kcontrol_t * kcontrol,			       snd_ctl_elem_value_t * ucontrol){	hdspm_t *hdspm = snd_kcontrol_chip(kcontrol);	int change;	int source;	int destination;	int gain;	if (!snd_hdspm_use_is_exclusive(hdspm))		return -EBUSY;	source = ucontrol->value.integer.value[0];	destination = ucontrol->value.integer.value[1];	if (source < 0 || source >= 2 * HDSPM_MAX_CHANNELS)		return -1;	if (destination < 0 || destination >= HDSPM_MAX_CHANNELS)		return -1;	gain = ucontrol->value.integer.value[2];	spin_lock_irq(&hdspm->lock);	if (source >= HDSPM_MAX_CHANNELS)		change = gain != hdspm_read_pb_gain(hdspm, destination,						    source -						    HDSPM_MAX_CHANNELS);	else		change =		    gain != hdspm_read_in_gain(hdspm, destination, source);	if (change) {		if (source >= HDSPM_MAX_CHANNELS)			hdspm_write_pb_gain(hdspm, destination,					    source - HDSPM_MAX_CHANNELS,					    gain);		else			hdspm_write_in_gain(hdspm, destination, source,					    gain);	}	spin_unlock_irq(&hdspm->lock);	return change;}/* The simple mixer control(s) provide gain control for the   basic 1:1 mappings of playback streams to output   streams. */#define HDSPM_PLAYBACK_MIXER \{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, \  .access = SNDRV_CTL_ELEM_ACCESS_READ | SNDRV_CTL_ELEM_ACCESS_WRITE | \		 SNDRV_CTL_ELEM_ACCESS_VOLATILE, \  .info = snd_hdspm_info_playback_mixer, \  .get = snd_hdspm_get_playback_mixer, \  .put = snd_hdspm_put_playback_mixer \}static int snd_hdspm_info_playback_mixer(snd_kcontrol_t * kcontrol,					 snd_ctl_elem_info_t * uinfo){	uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER;	uinfo->count = 1;	uinfo->value.integer.min = 0;	uinfo->value.integer.max = 65536;	uinfo->value.integer.step = 1;	return 0;}static int snd_hdspm_get_playback_mixer(snd_kcontrol_t * kcontrol,					snd_ctl_elem_value_t * ucontrol){	hdspm_t *hdspm = snd_kcontrol_chip(kcontrol);	int channel;	int mapped_channel;	channel = ucontrol->id.index - 1;	snd_assert(channel >= 0		   || channel < HDSPM_MAX_CHANNELS, return -EINVAL);	if ((mapped_channel = hdspm->channel_map[channel]) < 0)		return -EINVAL;	spin_lock_irq(&hdspm->lock);	ucontrol->value.integer.value[0] =	    hdspm_read_pb_gain(hdspm, mapped_channel, mapped_channel);	spin_unlock_irq(&hdspm->lock);	/*    snd_printdd("get pb mixer index %d, channel %d, mapped_channel %d, value %d\n",	   ucontrol->id.index,        channel, mapped_channel,  ucontrol->value.integer.value[0]); 	 */	return 0;}static int snd_hdspm_put_playback_mixer(snd_kcontrol_t * kcontrol,					snd_ctl_elem_value_t * ucontrol){	hdspm_t *hdspm = snd_kcontrol_chip(kcontrol);	int change;	int channel;	int mapped_channel;	int gain;	if (!snd_hdspm_use_is_exclusive(hdspm))		return -EBUSY;	channel = ucontrol->id.index - 1;	snd_assert(channel >= 0		   || channel < HDSPM_MAX_CHANNELS, return -EINVAL);	if ((mapped_channel = hdspm->channel_map[channel]) < 0)		return -EINVAL;	gain = ucontrol->value.integer.value[0];	spin_lock_irq(&hdspm->lock);	change =	    gain != hdspm_read_pb_gain(hdspm, mapped_channel,				       mapped_channel);	if (change)		hdspm_write_pb_gain(hdspm, mapped_channel, mapped_channel,				    gain);	spin_unlock_irq(&hdspm->lock);	return change;}#define HDSPM_WC_SYNC_CHECK(xname, xindex) \{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, \  .name = xname, \  .index = xindex, \  .access = SNDRV_CTL_ELEM_ACCESS_READ | SNDRV_CTL_ELEM_ACCESS_VOLATILE, \  .info = snd_hdspm_info_sync_check, \  .get = snd_hdspm_get_wc_sync_check \}static int snd_hdspm_info_sync_check(snd_kcontrol_t * kcontrol,				     snd_ctl_elem_info_t * uinfo){	static char *texts[] = { "No Lock", "Lock", "Sync" };	uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED;	uinfo->count = 1;	uinfo->value.enumerated.items = 3;	if (uinfo->value.enumerated.item >= uinfo->value.enumerated.items)		uinfo->value.enumerated.item =		    uinfo->value.enumerated.items - 1;	strcpy(uinfo->value.enumerated.name,	       texts[uinfo->value.enumerated.item]);	return 0;}static int hdspm_wc_sync_check(hdspm_t * hdspm){	int status2 = hdspm_read(hdspm, HDSPM_statusRegister2);	if (status2 & HDSPM_wcLock) {		if (status2 & HDSPM_wcSync)			return 2;		else			return 1;	}	return 0;}static int snd_hdspm_get_wc_sync_check(snd_kcontrol_t * kcontrol,				       snd_ctl_elem_value_t * ucontrol){	hdspm_t *hdspm = snd_kcontrol_chip(kcontrol);	ucontrol->value.enumerated.item[0] = hdspm_wc_sync_check(hdspm);	return 0;}#define HDSPM_MADI_SYNC_CHECK(xname, xindex) \{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, \  .name = xname, \  .index = xindex, \  .access = SNDRV_CTL_ELEM_ACCESS_READ | SNDRV_CTL_ELEM_ACCESS_VOLATILE, \  .info = snd_hdspm_info_sync_check, \  .get = snd_hdspm_get_madisync_sync_check \}static int hdspm_madisync_sync_check(hdspm_t * hdspm){	int status = hdspm_read(hdspm, HDSPM_statusRegister);	if (status & HDSPM_madiLock) {		if (status & HDSPM_madiSync)			return 2;		else			return 1;	}	return 0;}static int snd_hdspm_get_madisync_sync_check(snd_kcontrol_t * kcontrol,					     snd_ctl_elem_value_t *					     ucontrol){	hdspm_t *hdspm = snd_kcontrol_chip(kcontrol);	ucontrol->value.enumerated.item[0] =	    hdspm_madisync_sync_check(hdspm);	return 0;}static snd_kcontrol_new_t snd_hdspm_controls[] = {	HDSPM_MIXER("Mixer", 0),/* 'Sample Clock Source' complies with the alsa control naming scheme */	HDSPM_CLOCK_SOURCE("Sample Clock Source", 0),	HDSPM_SYSTEM_CLOCK_MODE("System Clock Mode", 0),	HDSPM_PREF_SYNC_REF("Preferred Sync Reference", 0),	HDSPM_AUTOSYNC_REF("AutoSync Reference", 0),	HDSPM_SYSTEM_SAMPLE_RATE("System Sample Rate", 0),/* 'External Rate' complies with the alsa control naming scheme */	HDSPM_AUTOSYNC_SAMPLE_RATE("External Rate", 0),	HDSPM_WC_SYNC_CHECK("Word Clock Lock Status", 0),	HDSPM_MADI_SYNC_CHECK("MADI Sync Lock Status", 0),	HDSPM_LINE_OUT("Line Out", 0),	HDSPM_TX_64("TX 64 channels mode", 0),	HDSPM_C_TMS("Clear Track Marker", 0),	HDSPM_SAFE_MODE("Safe Mode", 0),	HDSPM_INPUT_SELECT("Input Select", 0),};static snd_kcontrol_new_t snd_hdspm_playback_mixer = HDSPM_PLAYBACK_MIXER;static int hdspm_update_simple_mixer_controls(hdspm_t * hdspm){	int i;	for (i = hdspm->ds_channels; i < hdspm->ss_channels; ++i) {		if (hdspm->system_sample_rate > 48000) {			hdspm->playback_mixer_ctls[i]->vd[0].access =			    SNDRV_CTL_ELEM_ACCESS_INACTIVE |			    SNDRV_CTL_ELEM_ACCESS_READ |			    SNDRV_CTL_ELEM_ACCESS_VOLATILE;		} else {			hdspm->playback_mixer_ctls[i]->vd[0].access =			    SNDRV_CTL_ELEM_ACCESS_READWRITE |			    SNDRV_CTL_ELEM_ACCESS_VOLATILE;		}		snd_ctl_notify(hdspm->card, SNDRV_CTL_EVENT_MASK_VALUE |			       SNDRV_CTL_EVENT_MASK_INFO,			       &hdspm->playback_mixer_ctls[i]->id);	}	return 0;}static int snd_hdspm_create_controls(snd_card_t * card, hdspm_t * hdspm){	unsigned int idx, limit;	int err;	snd_kcontrol_t *kctl;	/* add control list first */	for (idx = 0; idx < ARRAY_SIZE(snd_hdspm_controls); idx++) {		if ((err =		     snd_ctl_add(card, kctl =				 snd_ctl_new1(&snd_hdspm_controls[idx],					      hdspm))) < 0) {			return err;		}	}	/* Channel playback mixer as default control 	   Note: the whole matrix would be 128*HDSPM_MIXER_CHANNELS Faders, thats to big for any alsamixer 	   they are accesible via special IOCTL on hwdep	   and the mixer 2dimensional mixer control */	snd_hdspm_playback_mixer.name = "Chn";	limit = HDSPM_MAX_CHANNELS;	/* The index values are one greater than the channel ID so that alsamixer	   will display them correctly. We want to use the index for fast lookup	   of the relevant channel, but if we use it at all, most ALSA software	   does the wrong thing with it ...	 */	for (idx = 0; idx < limit; ++idx) {		snd_hdspm_playback_mixer.index = idx + 1;		if ((err = snd_ctl_add(card,				       kctl =				       snd_ctl_new1				       (&snd_hdspm_playback_mixer,					hdspm)))) {			return err;		}		hdspm->playback_mixer_ctls[idx] = kctl;	}	return 0;}/*------------------------------------------------------------   /proc interface  ------------------------------------------------------------*/static voidsnd_hdspm_proc_read(snd_info_entry_t * entry, snd_info_buffer_t * buffer){	hdspm_t *hdspm = (hdspm_t *) entry->private_data;	unsigned int status;	unsigned int status2;	char *pref_sync_ref;	char *autosync_ref;	char *system_clock_mode;	char *clock_source;	char *insel;	char *syncref;	int x, x2;	status = hdspm_read(hdspm, HDSPM_statusRegister);	status2 = hdspm_read(hdspm, HDSPM_statusRegister2);	snd_iprintf(buffer, "%s (Card #%d) Rev.%x Status2first3bits: %x\n",		    hdspm->card_name, hdspm->card->number + 1,		    hdspm->firmware_rev,		    (status2 & HDSPM_version0) |		    (status2 & HDSPM_version1) | (status2 &						  HDSPM_version2));	snd_iprintf(buffer, "IRQ: %d Registers bus: 0x%lx VM: 0x%lx\n",		    hdspm->irq, hdspm->port, (unsigned long)hdspm->iobase);	snd_iprintf(buffer, "--- System ---\n");	snd_iprintf(buffer,		    "IRQ Pending: Audio=%d, MIDI0=%d, MIDI1=%d, IRQcount=%d\n",		    status & HDSPM_audioIRQPending,		    (status & HDSPM_midi0IRQPending) ? 1 : 0,		    (status & HDSPM_midi1IRQPending) ? 1 : 0,		    hdspm->irq_count);	snd_iprintf(buffer,		    "HW pointer: id = %d, rawptr = %d (%d->%d) estimated= %ld (bytes)\n",		    ((status & HDSPM_BufferID) ? 1 : 0),		    (status & HDSPM_BufferPositionMask),		    (status & HDSPM_BufferPositionMask) % (2 *							   (int)hdspm->							   period_bytes),		    ((status & HDSPM_BufferPositionMask) -		     64) % (2 * (int)hdspm->period_bytes),		    (long) hdspm_hw_pointer(hdspm) * 4);	snd_iprintf(buffer,		    "MIDI FIFO: Out1=0x%x, Out2=0x%x, In1=0x%x, In2=0x%x \n",		    hdspm_read(hdspm, HDSPM_midiStatusOut0) & 0xFF,		    hdspm_read(hdspm, HDSPM_midiStatusOut1) & 0xFF,		    hdspm_read(hdspm, HDSPM_midiStatusIn0) & 0xFF,		    h

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -