2 * skl-nhlt.c - Intel SKL Platform NHLT parsing
4 * Copyright (C) 2015 Intel Corp
5 * Author: Sanjiv Kumar <sanjiv.kumar@intel.com>
6 * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
8 * This program is free software; you can redistribute it and/or modify
9 * it under the terms of the GNU General Public License as published by
10 * the Free Software Foundation; version 2 of the License.
12 * This program is distributed in the hope that it will be useful, but
13 * WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 * General Public License for more details.
17 * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
22 /* Unique identification for getting NHLT blobs */
23 static u8 OSC_UUID
[16] = {0x6E, 0x88, 0x9F, 0xA6, 0xEB, 0x6C, 0x94, 0x45,
24 0xA4, 0x1F, 0x7B, 0x5D, 0xCE, 0x24, 0xC5, 0x53};
26 #define DSDT_NHLT_PATH "\\_SB.PCI0.HDAS"
28 void *skl_nhlt_init(struct device
*dev
)
31 union acpi_object
*obj
;
32 struct nhlt_resource_desc
*nhlt_ptr
= NULL
;
34 if (ACPI_FAILURE(acpi_get_handle(NULL
, DSDT_NHLT_PATH
, &handle
))) {
35 dev_err(dev
, "Requested NHLT device not found\n");
39 obj
= acpi_evaluate_dsm(handle
, OSC_UUID
, 1, 1, NULL
);
40 if (obj
&& obj
->type
== ACPI_TYPE_BUFFER
) {
41 nhlt_ptr
= (struct nhlt_resource_desc
*)obj
->buffer
.pointer
;
43 return memremap(nhlt_ptr
->min_addr
, nhlt_ptr
->length
,
47 dev_err(dev
, "device specific method to extract NHLT blob failed\n");
51 void skl_nhlt_free(void *addr
)
56 static struct nhlt_specific_cfg
*skl_get_specific_cfg(
57 struct device
*dev
, struct nhlt_fmt
*fmt
,
58 u8 no_ch
, u32 rate
, u16 bps
, u8 linktype
)
60 struct nhlt_specific_cfg
*sp_config
;
62 struct nhlt_fmt_cfg
*fmt_config
= fmt
->fmt_config
;
65 dev_dbg(dev
, "Format count =%d\n", fmt
->fmt_count
);
67 for (i
= 0; i
< fmt
->fmt_count
; i
++) {
68 wfmt
= &fmt_config
->fmt_ext
.fmt
;
69 dev_dbg(dev
, "ch=%d fmt=%d s_rate=%d\n", wfmt
->channels
,
70 wfmt
->bits_per_sample
, wfmt
->samples_per_sec
);
71 if (wfmt
->channels
== no_ch
&& wfmt
->bits_per_sample
== bps
) {
73 * if link type is dmic ignore rate check as the blob is
74 * generic for all rates
76 sp_config
= &fmt_config
->config
;
77 if (linktype
== NHLT_LINK_DMIC
)
80 if (wfmt
->samples_per_sec
== rate
)
84 fmt_config
= (struct nhlt_fmt_cfg
*)(fmt_config
->config
.caps
+
85 fmt_config
->config
.size
);
91 static void dump_config(struct device
*dev
, u32 instance_id
, u8 linktype
,
92 u8 s_fmt
, u8 num_channels
, u32 s_rate
, u8 dirn
, u16 bps
)
94 dev_dbg(dev
, "Input configuration\n");
95 dev_dbg(dev
, "ch=%d fmt=%d s_rate=%d\n", num_channels
, s_fmt
, s_rate
);
96 dev_dbg(dev
, "vbus_id=%d link_type=%d\n", instance_id
, linktype
);
97 dev_dbg(dev
, "bits_per_sample=%d\n", bps
);
100 static bool skl_check_ep_match(struct device
*dev
, struct nhlt_endpoint
*epnt
,
101 u32 instance_id
, u8 link_type
, u8 dirn
)
103 dev_dbg(dev
, "vbus_id=%d link_type=%d dir=%d\n",
104 epnt
->virtual_bus_id
, epnt
->linktype
, epnt
->direction
);
106 if ((epnt
->virtual_bus_id
== instance_id
) &&
107 (epnt
->linktype
== link_type
) &&
108 (epnt
->direction
== dirn
))
114 struct nhlt_specific_cfg
115 *skl_get_ep_blob(struct skl
*skl
, u32 instance
, u8 link_type
,
116 u8 s_fmt
, u8 num_ch
, u32 s_rate
, u8 dirn
)
118 struct nhlt_fmt
*fmt
;
119 struct nhlt_endpoint
*epnt
;
120 struct hdac_bus
*bus
= ebus_to_hbus(&skl
->ebus
);
121 struct device
*dev
= bus
->dev
;
122 struct nhlt_specific_cfg
*sp_config
;
123 struct nhlt_acpi_table
*nhlt
= (struct nhlt_acpi_table
*)skl
->nhlt
;
124 u16 bps
= (s_fmt
== 16) ? 16 : 32;
127 dump_config(dev
, instance
, link_type
, s_fmt
, num_ch
, s_rate
, dirn
, bps
);
129 epnt
= (struct nhlt_endpoint
*)nhlt
->desc
;
131 dev_dbg(dev
, "endpoint count =%d\n", nhlt
->endpoint_count
);
133 for (j
= 0; j
< nhlt
->endpoint_count
; j
++) {
134 if (skl_check_ep_match(dev
, epnt
, instance
, link_type
, dirn
)) {
135 fmt
= (struct nhlt_fmt
*)(epnt
->config
.caps
+
137 sp_config
= skl_get_specific_cfg(dev
, fmt
, num_ch
,
138 s_rate
, bps
, link_type
);
143 epnt
= (struct nhlt_endpoint
*)((u8
*)epnt
+ epnt
->length
);