linux/sound/hda/intel-nhlt.c
<<
>>
Prefs
   1// SPDX-License-Identifier: GPL-2.0-only
   2// Copyright (c) 2015-2019 Intel Corporation
   3
   4#include <linux/acpi.h>
   5#include <sound/intel-nhlt.h>
   6
   7struct nhlt_acpi_table *intel_nhlt_init(struct device *dev)
   8{
   9        struct nhlt_acpi_table *nhlt;
  10        acpi_status status;
  11
  12        status = acpi_get_table(ACPI_SIG_NHLT, 0,
  13                                (struct acpi_table_header **)&nhlt);
  14        if (ACPI_FAILURE(status)) {
  15                dev_warn(dev, "NHLT table not found\n");
  16                return NULL;
  17        }
  18
  19        return nhlt;
  20}
  21EXPORT_SYMBOL_GPL(intel_nhlt_init);
  22
  23void intel_nhlt_free(struct nhlt_acpi_table *nhlt)
  24{
  25        acpi_put_table((struct acpi_table_header *)nhlt);
  26}
  27EXPORT_SYMBOL_GPL(intel_nhlt_free);
  28
  29int intel_nhlt_get_dmic_geo(struct device *dev, struct nhlt_acpi_table *nhlt)
  30{
  31        struct nhlt_endpoint *epnt;
  32        struct nhlt_dmic_array_config *cfg;
  33        struct nhlt_vendor_dmic_array_config *cfg_vendor;
  34        struct nhlt_fmt *fmt_configs;
  35        unsigned int dmic_geo = 0;
  36        u16 max_ch = 0;
  37        u8 i, j;
  38
  39        if (!nhlt)
  40                return 0;
  41
  42        if (nhlt->header.length <= sizeof(struct acpi_table_header)) {
  43                dev_warn(dev, "Invalid DMIC description table\n");
  44                return 0;
  45        }
  46
  47        for (j = 0, epnt = nhlt->desc; j < nhlt->endpoint_count; j++,
  48             epnt = (struct nhlt_endpoint *)((u8 *)epnt + epnt->length)) {
  49
  50                if (epnt->linktype != NHLT_LINK_DMIC)
  51                        continue;
  52
  53                cfg = (struct nhlt_dmic_array_config  *)(epnt->config.caps);
  54                fmt_configs = (struct nhlt_fmt *)(epnt->config.caps + epnt->config.size);
  55
  56                /* find max number of channels based on format_configuration */
  57                if (fmt_configs->fmt_count) {
  58                        dev_dbg(dev, "%s: found %d format definitions\n",
  59                                __func__, fmt_configs->fmt_count);
  60
  61                        for (i = 0; i < fmt_configs->fmt_count; i++) {
  62                                struct wav_fmt_ext *fmt_ext;
  63
  64                                fmt_ext = &fmt_configs->fmt_config[i].fmt_ext;
  65
  66                                if (fmt_ext->fmt.channels > max_ch)
  67                                        max_ch = fmt_ext->fmt.channels;
  68                        }
  69                        dev_dbg(dev, "%s: max channels found %d\n", __func__, max_ch);
  70                } else {
  71                        dev_dbg(dev, "%s: No format information found\n", __func__);
  72                }
  73
  74                if (cfg->device_config.config_type != NHLT_CONFIG_TYPE_MIC_ARRAY) {
  75                        dmic_geo = max_ch;
  76                } else {
  77                        switch (cfg->array_type) {
  78                        case NHLT_MIC_ARRAY_2CH_SMALL:
  79                        case NHLT_MIC_ARRAY_2CH_BIG:
  80                                dmic_geo = MIC_ARRAY_2CH;
  81                                break;
  82
  83                        case NHLT_MIC_ARRAY_4CH_1ST_GEOM:
  84                        case NHLT_MIC_ARRAY_4CH_L_SHAPED:
  85                        case NHLT_MIC_ARRAY_4CH_2ND_GEOM:
  86                                dmic_geo = MIC_ARRAY_4CH;
  87                                break;
  88                        case NHLT_MIC_ARRAY_VENDOR_DEFINED:
  89                                cfg_vendor = (struct nhlt_vendor_dmic_array_config *)cfg;
  90                                dmic_geo = cfg_vendor->nb_mics;
  91                                break;
  92                        default:
  93                                dev_warn(dev, "%s: undefined DMIC array_type 0x%0x\n",
  94                                         __func__, cfg->array_type);
  95                        }
  96
  97                        if (dmic_geo > 0) {
  98                                dev_dbg(dev, "%s: Array with %d dmics\n", __func__, dmic_geo);
  99                        }
 100                        if (max_ch > dmic_geo) {
 101                                dev_dbg(dev, "%s: max channels %d exceed dmic number %d\n",
 102                                        __func__, max_ch, dmic_geo);
 103                        }
 104                }
 105        }
 106
 107        dev_dbg(dev, "%s: dmic number %d max_ch %d\n",
 108                __func__, dmic_geo, max_ch);
 109
 110        return dmic_geo;
 111}
 112EXPORT_SYMBOL_GPL(intel_nhlt_get_dmic_geo);
 113