summaryrefslogtreecommitdiffstats
path: root/sound/soc/intel/common/soc-intel-quirks.h
blob: a93987ab7f4d7a1e014d816d2d4592c9483cb641 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
/* SPDX-License-Identifier: GPL-2.0-only */
/*
 * soc-intel-quirks.h - prototypes for quirk autodetection
 *
 * Copyright (c) 2019, Intel Corporation.
 *
 */

#ifndef _SND_SOC_INTEL_QUIRKS_H
#define _SND_SOC_INTEL_QUIRKS_H

#if IS_ENABLED(CONFIG_X86)

#include <linux/dmi.h>
#include <asm/cpu_device_id.h>
#include <asm/intel-family.h>
#include <asm/iosf_mbi.h>

#define SOC_INTEL_IS_CPU(soc, type)				\
static inline bool soc_intel_is_##soc(void)			\
{								\
	static const struct x86_cpu_id soc##_cpu_ids[] = {	\
		X86_MATCH_INTEL_FAM6_MODEL(type, NULL),		\
		{}						\
	};							\
	const struct x86_cpu_id *id;				\
								\
	id = x86_match_cpu(soc##_cpu_ids);			\
	if (id)							\
		return true;					\
	return false;						\
}

SOC_INTEL_IS_CPU(byt, ATOM_SILVERMONT);
SOC_INTEL_IS_CPU(cht, ATOM_AIRMONT);
SOC_INTEL_IS_CPU(apl, ATOM_GOLDMONT);
SOC_INTEL_IS_CPU(glk, ATOM_GOLDMONT_PLUS);
SOC_INTEL_IS_CPU(cml, KABYLAKE_L);

static inline bool soc_intel_is_byt_cr(struct platform_device *pdev)
{
	/*
	 * List of systems which:
	 * 1. Use a non CR version of the Bay Trail SoC
	 * 2. Contain at least 6 interrupt resources so that the
	 *    platform_get_resource(pdev, IORESOURCE_IRQ, 5) check below
	 *    succeeds
	 * 3. Despite 1. and 2. still have their IPC IRQ at index 0 rather then 5
	 *
	 * This needs to be here so that it can be shared between the SST and
	 * SOF drivers. We rely on the compiler to optimize this out in files
	 * where soc_intel_is_byt_cr is not used.
	 */
	static const struct dmi_system_id force_bytcr_table[] = {
		{	/* Lenovo Yoga Tablet 2 series */
			.matches = {
				DMI_MATCH(DMI_SYS_VENDOR, "LENOVO"),
				DMI_MATCH(DMI_PRODUCT_FAMILY, "YOGATablet2"),
			},
		},
		{}
	};
	struct device *dev = &pdev->dev;
	int status = 0;

	if (!soc_intel_is_byt())
		return false;

	if (dmi_check_system(force_bytcr_table))
		return true;

	if (iosf_mbi_available()) {
		u32 bios_status;

		status = iosf_mbi_read(BT_MBI_UNIT_PMC, /* 0x04 PUNIT */
				       MBI_REG_READ, /* 0x10 */
				       0x006, /* BIOS_CONFIG */
				       &bios_status);

		if (status) {
			dev_err(dev, "could not read PUNIT BIOS_CONFIG\n");
		} else {
			/* bits 26:27 mirror PMIC options */
			bios_status = (bios_status >> 26) & 3;

			if (bios_status == 1 || bios_status == 3) {
				dev_info(dev, "Detected Baytrail-CR platform\n");
				return true;
			}

			dev_info(dev, "BYT-CR not detected\n");
		}
	} else {
		dev_info(dev, "IOSF_MBI not available, no BYT-CR detection\n");
	}

	if (!platform_get_resource(pdev, IORESOURCE_IRQ, 5)) {
		/*
		 * Some devices detected as BYT-T have only a single IRQ listed,
		 * causing platform_get_irq with index 5 to return -ENXIO.
		 * The correct IRQ in this case is at index 0, as on BYT-CR.
		 */
		dev_info(dev, "Falling back to Baytrail-CR platform\n");
		return true;
	}

	return false;
}

#else

static inline bool soc_intel_is_byt_cr(struct platform_device *pdev)
{
	return false;
}

static inline bool soc_intel_is_byt(void)
{
	return false;
}

static inline bool soc_intel_is_cht(void)
{
	return false;
}

static inline bool soc_intel_is_apl(void)
{
	return false;
}

static inline bool soc_intel_is_glk(void)
{
	return false;
}

static inline bool soc_intel_is_cml(void)
{
	return false;
}
#endif

 #endif /* _SND_SOC_INTEL_QUIRKS_H */