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; }
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; if (!hdmi_eld_valid(codec, nid)) return -ENOENT; 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); codec->recv_dec_cap = 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); } } buf = kmalloc(size, GFP_KERNEL); if (!buf) return -ENOMEM; for (i = 0; i < size; i++) buf[i] = hdmi_get_eld_byte(codec, nid, i); ret = hdmi_update_eld(eld, buf, size); kfree(buf); return ret; }
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; if (!hdmi_eld_valid(codec, nid)) return -ENOENT; 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) { snd_printd("snd_hdmi_get_eld() lpcm_sad_ready= %d\n", (eld->lpcm_sad_ready?1:0)); hdmi_update_lpcm_sad_eld(codec, nid, eld, size); } buf = kmalloc(size, GFP_KERNEL); if (!buf) return -ENOMEM; for (i = 0; i < size; i++) buf[i] = hdmi_get_eld_byte(codec, nid, i); ret = hdmi_update_eld(eld, buf, size); kfree(buf); return ret; }
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; }