Quellcodebibliothek Statistik Leitseite products/Sources/formale Sprachen/C/Linux/sound/hda/codecs/hdmi/   (Open Source Betriebssystem Version 6.17.9©)  Datei vom 24.10.2025 mit Größe 6 kB image not shown  

Quelle  eld.c   Sprache: C

 
// SPDX-License-Identifier: GPL-2.0-or-later
/*
 * Generic routines and proc interface for ELD(EDID Like Data) information
 *
 * Copyright(c) 2008 Intel Corporation.
 * Copyright (c) 2013 Anssi Hannula <anssi.hannula@iki.fi>
 *
 * Authors:
 *  Wu Fengguang <wfg@linux.intel.com>
 */


#include <linux/init.h>
#include <linux/slab.h>
#include <sound/core.h>
#include <sound/hda_chmap.h>
#include <sound/hda_codec.h>
#include "hda_local.h"

enum cea_edid_versions {
 CEA_EDID_VER_NONE = 0,
 CEA_EDID_VER_CEA861 = 1,
 CEA_EDID_VER_CEA861A = 2,
 CEA_EDID_VER_CEA861BCD = 3,
 CEA_EDID_VER_RESERVED = 4,
};

/*
 * The following two lists are shared between
 *  - HDMI audio InfoFrame (source to sink)
 *  - CEA E-EDID Extension (sink to source)
 */


static unsigned int hdmi_get_eld_data(struct hda_codec *codec, hda_nid_t nid,
     int byte_index)
{
 unsigned int val;

 val = snd_hda_codec_read(codec, nid, 0,
     AC_VERB_GET_HDMI_ELDD, byte_index);
#ifdef BE_PARANOID
 codec_info(codec, "HDMI: ELD data byte %d: 0x%x\n", byte_index, val);
#endif
 return val;
}

int snd_hdmi_get_eld_size(struct hda_codec *codec, hda_nid_t nid)
{
 return snd_hda_codec_read(codec, nid, 0, AC_VERB_GET_HDMI_DIP_SIZE,
       AC_DIPSIZE_ELD_BUF);
}

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 */
  codec_info(codec, "HDMI: ELD buf size is 0, force 128\n");
  size = 128;
 }
 if (size < ELD_FIXED_BYTES || size > ELD_MAX_SIZE) {
  codec_info(codec, "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)) {
   codec_info(codec, "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) {
   codec_dbg(codec, "HDMI: 0 ELD data\n");
   ret = -EINVAL;
   goto error;
  }
  buf[i] = val;
 }

 *eld_size = size;
error:
 return ret;
}

#ifdef CONFIG_SND_PROC_FS
void snd_hdmi_print_eld_info(struct hdmi_eld *eld,
        struct snd_info_buffer *buffer,
        hda_nid_t pin_nid, int dev_id, hda_nid_t cvt_nid)
{
 snd_iprintf(buffer, "monitor_present\t\t%d\n", eld->monitor_present);
 snd_iprintf(buffer, "eld_valid\t\t%d\n", eld->eld_valid);
 snd_iprintf(buffer, "codec_pin_nid\t\t0x%x\n", pin_nid);
 snd_iprintf(buffer, "codec_dev_id\t\t0x%x\n", dev_id);
 snd_iprintf(buffer, "codec_cvt_nid\t\t0x%x\n", cvt_nid);

 if (!eld->eld_valid)
  return;

 snd_print_eld_info(&eld->info, buffer);
}

void snd_hdmi_write_eld_info(struct hdmi_eld *eld,
        struct snd_info_buffer *buffer)
{
 struct snd_parsed_hdmi_eld *e = &eld->info;
 char line[64];
 char name[64];
 char *sname;
 long long val;
 unsigned int n;

 while (!snd_info_get_line(buffer, line, sizeof(line))) {
  if (sscanf(line, "%s %llx", name, &val) != 2)
   continue;
  /*
 * We don't allow modification to these fields:
 *  monitor_name manufacture_id product_id
 *  eld_version edid_version
 */

  if (!strcmp(name, "monitor_present"))
   eld->monitor_present = val;
  else if (!strcmp(name, "eld_valid"))
   eld->eld_valid = val;
  else if (!strcmp(name, "connection_type"))
   e->conn_type = val;
  else if (!strcmp(name, "port_id"))
   e->port_id = val;
  else if (!strcmp(name, "support_hdcp"))
   e->support_hdcp = val;
  else if (!strcmp(name, "support_ai"))
   e->support_ai = val;
  else if (!strcmp(name, "audio_sync_delay"))
   e->aud_synch_delay = val;
  else if (!strcmp(name, "speakers"))
   e->spk_alloc = val;
  else if (!strcmp(name, "sad_count"))
   e->sad_count = val;
  else if (!strncmp(name, "sad", 3)) {
   sname = name + 4;
   n = name[3] - '0';
   if (name[4] >= '0' && name[4] <= '9') {
    sname++;
    n = 10 * n + name[4] - '0';
   }
   if (n >= ELD_MAX_SAD)
    continue;
   if (!strcmp(sname, "_coding_type"))
    e->sad[n].format = val;
   else if (!strcmp(sname, "_channels"))
    e->sad[n].channels = val;
   else if (!strcmp(sname, "_rates"))
    e->sad[n].rates = val;
   else if (!strcmp(sname, "_bits"))
    e->sad[n].sample_bits = val;
   else if (!strcmp(sname, "_max_bitrate"))
    e->sad[n].max_bitrate = val;
   else if (!strcmp(sname, "_profile"))
    e->sad[n].profile = val;
   if (n >= e->sad_count)
    e->sad_count = n + 1;
  }
 }
}
#endif /* CONFIG_SND_PROC_FS */

/* update PCM info based on ELD */
void snd_hdmi_eld_update_pcm_info(struct snd_parsed_hdmi_eld *e,
         struct hda_pcm_stream *hinfo)
{
 u32 rates;
 u64 formats;
 unsigned int maxbps;
 unsigned int channels_max;
 int i;

 /* assume basic audio support (the basic audio flag is not in ELD;
 * however, all audio capable sinks are required to support basic
 * audio) */

 rates = SNDRV_PCM_RATE_32000 | SNDRV_PCM_RATE_44100 |
  SNDRV_PCM_RATE_48000;
 formats = SNDRV_PCM_FMTBIT_S16_LE;
 maxbps = 16;
 channels_max = 2;
 for (i = 0; i < e->sad_count; i++) {
  struct snd_cea_sad *a = &e->sad[i];
  rates |= a->rates;
  if (a->channels > channels_max)
   channels_max = a->channels;
  if (a->format == AUDIO_CODING_TYPE_LPCM) {
   if (a->sample_bits & ELD_PCM_BITS_20) {
    formats |= SNDRV_PCM_FMTBIT_S32_LE;
    if (maxbps < 20)
     maxbps = 20;
   }
   if (a->sample_bits & ELD_PCM_BITS_24) {
    formats |= SNDRV_PCM_FMTBIT_S32_LE;
    if (maxbps < 24)
     maxbps = 24;
   }
  }
 }

 /* restrict the parameters by the values the codec provides */
 hinfo->rates &= rates;
 hinfo->formats &= formats;
 hinfo->maxbps = min(hinfo->maxbps, maxbps);
 hinfo->channels_max = min(hinfo->channels_max, channels_max);
}

Messung V0.5
C=95 H=91 G=92

¤ Dauer der Verarbeitung: 0.27 Sekunden  (vorverarbeitet)  ¤

*© Formatika GbR, Deutschland






Wurzel

Suchen

Beweissystem der NASA

Beweissystem Isabelle

NIST Cobol Testsuite

Cephes Mathematical Library

Wiener Entwicklungsmethode

Haftungshinweis

Die Informationen auf dieser Webseite wurden nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit, noch Qualität der bereit gestellten Informationen zugesichert.

Bemerkung:

Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.