summaryrefslogtreecommitdiffstats
path: root/include/sound/hda_regmap.h
blob: 95651d26437d47c4fe8407d6215c361de36996ce (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
144
145
/*
 * HD-audio regmap helpers
 */

#ifndef __SOUND_HDA_REGMAP_H
#define __SOUND_HDA_REGMAP_H

#include <linux/regmap.h>
#include <sound/core.h>
#include <sound/hdaudio.h>

int snd_hdac_regmap_init(struct hdac_device *codec);
void snd_hdac_regmap_exit(struct hdac_device *codec);

int snd_hdac_regmap_read_raw(struct hdac_device *codec, unsigned int reg,
			     unsigned int *val);
int snd_hdac_regmap_write_raw(struct hdac_device *codec, unsigned int reg,
			      unsigned int val);
int snd_hdac_regmap_update_raw(struct hdac_device *codec, unsigned int reg,
			       unsigned int mask, unsigned int val);

/**
 * snd_hdac_regmap_encode_verb - encode the verb to a pseudo register
 * @nid: widget NID
 * @verb: codec verb
 *
 * Returns an encoded pseudo register.
 */
#define snd_hdac_regmap_encode_verb(nid, verb)		\
	(((verb) << 8) | 0x80000 | ((unsigned int)(nid) << 20))

/**
 * snd_hdac_regmap_encode_amp - encode the AMP verb to a pseudo register
 * @nid: widget NID
 * @ch: channel (left = 0, right = 1)
 * @dir: direction (#HDA_INPUT, #HDA_OUTPUT)
 * @idx: input index value
 *
 * Returns an encoded pseudo register.
 */
#define snd_hdac_regmap_encode_amp(nid, ch, dir, idx)			\
	(snd_hdac_regmap_encode_verb(nid, AC_VERB_GET_AMP_GAIN_MUTE) |	\
	 ((ch) ? AC_AMP_GET_RIGHT : AC_AMP_GET_LEFT) |			\
	 ((dir) == HDA_OUTPUT ? AC_AMP_GET_OUTPUT : AC_AMP_GET_INPUT) | \
	 (idx))

/**
 * snd_hdac_regmap_write - Write a verb with caching
 * @nid: codec NID
 * @reg: verb to write
 * @val: value to write
 *
 * For writing an amp value, use snd_hda_regmap_amp_update().
 */
static inline int
snd_hdac_regmap_write(struct hdac_device *codec, hda_nid_t nid,
		      unsigned int verb, unsigned int val)
{
	unsigned int cmd = snd_hdac_regmap_encode_verb(nid, verb);

	return snd_hdac_regmap_write_raw(codec, cmd, val);
}

/**
 * snd_hda_regmap_update - Update a verb value with caching
 * @nid: codec NID
 * @verb: verb to update
 * @mask: bit mask to update
 * @val: value to update
 *
 * For updating an amp value, use snd_hda_regmap_amp_update().
 */
static inline int
snd_hdac_regmap_update(struct hdac_device *codec, hda_nid_t nid,
		       unsigned int verb, unsigned int mask,
		       unsigned int val)
{
	unsigned int cmd = snd_hdac_regmap_encode_verb(nid, verb);

	return snd_hdac_regmap_update_raw(codec, cmd, mask, val);
}

/**
 * snd_hda_regmap_read - Read a verb with caching
 * @nid: codec NID
 * @verb: verb to read
 * @val: pointer to store the value
 *
 * For reading an amp value, use snd_hda_regmap_get_amp().
 */
static inline int
snd_hdac_regmap_read(struct hdac_device *codec, hda_nid_t nid,
		     unsigned int verb, unsigned int *val)
{
	unsigned int cmd = snd_hdac_regmap_encode_verb(nid, verb);

	return snd_hdac_regmap_read_raw(codec, cmd, val);
}

/**
 * snd_hdac_regmap_get_amp - Read AMP value
 * @codec: HD-audio codec
 * @nid: NID to read the AMP value
 * @ch: channel (left=0 or right=1)
 * @direction: #HDA_INPUT or #HDA_OUTPUT
 * @index: the index value (only for input direction)
 * @val: the pointer to store the value
 *
 * Read AMP value.  The volume is between 0 to 0x7f, 0x80 = mute bit.
 * Returns the value or a negative error.
 */
static inline int
snd_hdac_regmap_get_amp(struct hdac_device *codec, hda_nid_t nid,
			int ch, int dir, int idx)
{
	unsigned int cmd = snd_hdac_regmap_encode_amp(nid, ch, dir, idx);
	int err, val;

	err = snd_hdac_regmap_read_raw(codec, cmd, &val);
	return err < 0 ? err : val;
}

/**
 * snd_hdac_regmap_update_amp - update the AMP value
 * @codec: HD-audio codec
 * @nid: NID to read the AMP value
 * @ch: channel (left=0 or right=1)
 * @direction: #HDA_INPUT or #HDA_OUTPUT
 * @idx: the index value (only for input direction)
 * @mask: bit mask to set
 * @val: the bits value to set
 *
 * Update the AMP value with a bit mask.
 * Returns 0 if the value is unchanged, 1 if changed, or a negative error.
 */
static inline int
snd_hdac_regmap_update_amp(struct hdac_device *codec, hda_nid_t nid,
			   int ch, int dir, int idx, int mask, int val)
{
	unsigned int cmd = snd_hdac_regmap_encode_amp(nid, ch, dir, idx);

	return snd_hdac_regmap_update_raw(codec, cmd, mask, val);
}

#endif /* __SOUND_HDA_REGMAP_H */
OpenPOWER on IntegriCloud