示例#1
0
int snd_hdmi_get_eld(struct hda_codec *codec, hda_nid_t nid,
		     unsigned char *buf, int *eld_size)
{
	int i;
	int ret = 0;
	int size;

	/*
	 * ELD size is initialized to zero in caller function. If no errors and
	 * ELD is valid, actual eld_size is assigned.
	 */

	size = snd_hdmi_get_eld_size(codec, nid);
	if (size == 0) {
		/* wfg: workaround for ASUS P5E-VM HDMI board */
		snd_printd(KERN_INFO "HDMI: ELD buf size is 0, force 128\n");
		size = 128;
	}
	if (size < ELD_FIXED_BYTES || size > ELD_MAX_SIZE) {
		snd_printd(KERN_INFO "HDMI: invalid ELD buf size %d\n", size);
		return -ERANGE;
	}


	/* set ELD buffer */
	for (i = 0; i < size; i++) {
		unsigned int val = hdmi_get_eld_data(codec, nid, i);
		/*
		 * Graphics driver might be writing to ELD buffer right now.
		 * Just abort. The caller will repoll after a while.
		 */
		if (!(val & AC_ELDD_ELD_VALID)) {
			snd_printd(KERN_INFO
				  "HDMI: invalid ELD data byte %d\n", i);
			ret = -EINVAL;
			goto error;
		}
		val &= AC_ELDD_ELD_DATA;
		/*
		 * The first byte cannot be zero. This can happen on some DVI
		 * connections. Some Intel chips may also need some 250ms delay
		 * to return non-zero ELD data, even when the graphics driver
		 * correctly writes ELD content before setting ELD_valid bit.
		 */
		if (!val && !i) {
			snd_printdd(KERN_INFO "HDMI: 0 ELD data\n");
			ret = -EINVAL;
			goto error;
		}
		buf[i] = val;
	}

	*eld_size = size;

error:
	return ret;
}
示例#2
0
int snd_hdmi_get_eld(struct hdmi_eld *eld,
		     struct hda_codec *codec, hda_nid_t nid)
{
	int i;
	int ret;
	int size;
	unsigned char *buf;

	size = snd_hdmi_get_eld_size(codec, nid);
	if (size == 0) {
		/* wfg: workaround for ASUS P5E-VM HDMI board */
		snd_printd(KERN_INFO "HDMI: ELD buf size is 0, force 128\n");
		size = 128;
	}
	if (size < ELD_FIXED_BYTES || size > PAGE_SIZE) {
		snd_printd(KERN_INFO "HDMI: invalid ELD buf size %d\n", size);
		return -ERANGE;
	}

	if (!eld->lpcm_sad_ready)
		hdmi_update_lpcm_sad_eld(codec, nid, eld, size);

	buf = kmalloc(size, GFP_KERNEL);
	if (!buf)
		return -ENOMEM;

	for (i = 0; i < size; i++) {
		unsigned int val = hdmi_get_eld_data(codec, nid, i);
		if (!(val & AC_ELDD_ELD_VALID)) {
			if (!i) {
				snd_printd(KERN_INFO
					   "HDMI: invalid ELD data\n");
				ret = -EINVAL;
				goto error;
			}
			snd_printd(KERN_INFO
				  "HDMI: invalid ELD data byte %d\n", i);
			val = 0;
		} else
			val &= AC_ELDD_ELD_DATA;
		buf[i] = val;
	}

	ret = hdmi_update_eld(eld, buf, size);
	codec->ac3dec_capable = false;
	for (i = 0; i < eld->sad_count; i++) {
		if (eld->sad[i].format == AUDIO_CODING_TYPE_AC3)
			codec->ac3dec_capable = true;
	}

error:
	kfree(buf);
	return ret;
}
示例#3
0
static unsigned char hdmi_get_eld_byte(struct hda_codec *codec, hda_nid_t nid,
					int byte_index)
{
	unsigned int val;

	val = hdmi_get_eld_data(codec, nid, byte_index);

	if ((val & AC_ELDD_ELD_VALID) == 0) {
		snd_printd(KERN_INFO "HDMI: invalid ELD data byte %d\n",
								byte_index);
		val = 0;
	}

	return val & AC_ELDD_ELD_DATA;
}
int snd_hdmi_get_eld(struct hdmi_eld *eld,
		     struct hda_codec *codec, hda_nid_t nid)
{
	int i;
	int ret = 0;
	int size;
	unsigned char *buf;

	/*
	 * ELD size is initialized to zero in caller function. If no errors and
	 * ELD is valid, actual eld_size is assigned in hdmi_update_eld()
	 */

	size = snd_hdmi_get_eld_size(codec, nid);
	if (size == 0) {
		/* wfg: workaround for ASUS P5E-VM HDMI board */
		snd_printd(KERN_INFO "HDMI: ELD buf size is 0, force 128\n");
		size = 128;
	}
	if (size < ELD_FIXED_BYTES || size > ELD_MAX_SIZE) {
		snd_printd(KERN_INFO "HDMI: invalid ELD buf size %d\n", size);
		return -ERANGE;
	}

	if (!eld->lpcm_sad_ready)
		hdmi_update_lpcm_sad_eld(codec, nid, eld, size);

	/* set ELD buffer */
	buf = eld->eld_buffer;

	codec->recv_dec_cap = 0;
	codec->max_pcm_channels = 0;
	for (i = 0; i < eld->sad_count; i++) {
		if (eld->sad[i].format == AUDIO_CODING_TYPE_AC3) {
			codec->recv_dec_cap |= (1 << AUDIO_CODING_TYPE_AC3);
		} else if (eld->sad[i].format == AUDIO_CODING_TYPE_DTS) {
			codec->recv_dec_cap |= (1 << AUDIO_CODING_TYPE_DTS);
		} else if (eld->sad[i].format == AUDIO_CODING_TYPE_EAC3) {
			codec->recv_dec_cap |= (1 << AUDIO_CODING_TYPE_EAC3);
		} else if (eld->sad[i].format == AUDIO_CODING_TYPE_LPCM) {
			codec->max_pcm_channels =
				eld->sad[i].channels > codec->max_pcm_channels ?
				eld->sad[i].channels : codec->max_pcm_channels;
		}
	}

	for (i = 0; i < size; i++) {
		unsigned int val = hdmi_get_eld_data(codec, nid, i);
		/*
		 * Graphics driver might be writing to ELD buffer right now.
		 * Just abort. The caller will repoll after a while.
		 */
		if (!(val & AC_ELDD_ELD_VALID)) {
			snd_printd(KERN_INFO
				  "HDMI: invalid ELD data byte %d\n", i);
			ret = -EINVAL;
			goto error;
		}
		val &= AC_ELDD_ELD_DATA;
		/*
		 * The first byte cannot be zero. This can happen on some DVI
		 * connections. Some Intel chips may also need some 250ms delay
		 * to return non-zero ELD data, even when the graphics driver
		 * correctly writes ELD content before setting ELD_valid bit.
		 */
		if (!val && !i) {
			snd_printdd(KERN_INFO "HDMI: 0 ELD data\n");
			ret = -EINVAL;
			goto error;
		}
		buf[i] = val;
	}

	ret = hdmi_update_eld(eld, buf, size);

error:
	return ret;
}