1 /* SPDX-License-Identifier: GPL-2.0 */ 2 /* 3 * HD-audio regmap helpers 4 */ 5 6 #ifndef __SOUND_HDA_REGMAP_H 7 #define __SOUND_HDA_REGMAP_H 8 9 #include <linux/regmap.h> 10 #include <sound/core.h> 11 #include <sound/hdaudio.h> 12 13 #define AC_AMP_FAKE_MUTE 0x10 /* fake mute bit set to amp verbs */ 14 15 int snd_hdac_regmap_init(struct hdac_device *codec); 16 void snd_hdac_regmap_exit(struct hdac_device *codec); 17 int snd_hdac_regmap_add_vendor_verb(struct hdac_device *codec, 18 unsigned int verb); 19 int snd_hdac_regmap_read_raw(struct hdac_device *codec, unsigned int reg, 20 unsigned int *val); 21 int snd_hdac_regmap_read_raw_uncached(struct hdac_device *codec, 22 unsigned int reg, unsigned int *val); 23 int snd_hdac_regmap_write_raw(struct hdac_device *codec, unsigned int reg, 24 unsigned int val); 25 int snd_hdac_regmap_update_raw(struct hdac_device *codec, unsigned int reg, 26 unsigned int mask, unsigned int val); 27 28 /** 29 * snd_hdac_regmap_encode_verb - encode the verb to a pseudo register 30 * @nid: widget NID 31 * @verb: codec verb 32 * 33 * Returns an encoded pseudo register. 34 */ 35 #define snd_hdac_regmap_encode_verb(nid, verb) \ 36 (((verb) << 8) | 0x80000 | ((unsigned int)(nid) << 20)) 37 38 /** 39 * snd_hdac_regmap_encode_amp - encode the AMP verb to a pseudo register 40 * @nid: widget NID 41 * @ch: channel (left = 0, right = 1) 42 * @dir: direction (#HDA_INPUT, #HDA_OUTPUT) 43 * @idx: input index value 44 * 45 * Returns an encoded pseudo register. 46 */ 47 #define snd_hdac_regmap_encode_amp(nid, ch, dir, idx) \ 48 (snd_hdac_regmap_encode_verb(nid, AC_VERB_GET_AMP_GAIN_MUTE) | \ 49 ((ch) ? AC_AMP_GET_RIGHT : AC_AMP_GET_LEFT) | \ 50 ((dir) == HDA_OUTPUT ? AC_AMP_GET_OUTPUT : AC_AMP_GET_INPUT) | \ 51 (idx)) 52 53 /** 54 * snd_hdac_regmap_encode_amp_stereo - encode a pseudo register for stereo AMPs 55 * @nid: widget NID 56 * @dir: direction (#HDA_INPUT, #HDA_OUTPUT) 57 * @idx: input index value 58 * 59 * Returns an encoded pseudo register. 60 */ 61 #define snd_hdac_regmap_encode_amp_stereo(nid, dir, idx) \ 62 (snd_hdac_regmap_encode_verb(nid, AC_VERB_GET_AMP_GAIN_MUTE) | \ 63 AC_AMP_SET_LEFT | AC_AMP_SET_RIGHT | /* both bits set! */ \ 64 ((dir) == HDA_OUTPUT ? AC_AMP_GET_OUTPUT : AC_AMP_GET_INPUT) | \ 65 (idx)) 66 67 /** 68 * snd_hdac_regmap_write - Write a verb with caching 69 * @nid: codec NID 70 * @reg: verb to write 71 * @val: value to write 72 * 73 * For writing an amp value, use snd_hdac_regmap_update_amp(). 74 */ 75 static inline int 76 snd_hdac_regmap_write(struct hdac_device *codec, hda_nid_t nid, 77 unsigned int verb, unsigned int val) 78 { 79 unsigned int cmd = snd_hdac_regmap_encode_verb(nid, verb); 80 81 return snd_hdac_regmap_write_raw(codec, cmd, val); 82 } 83 84 /** 85 * snd_hda_regmap_update - Update a verb value with caching 86 * @nid: codec NID 87 * @verb: verb to update 88 * @mask: bit mask to update 89 * @val: value to update 90 * 91 * For updating an amp value, use snd_hdac_regmap_update_amp(). 92 */ 93 static inline int 94 snd_hdac_regmap_update(struct hdac_device *codec, hda_nid_t nid, 95 unsigned int verb, unsigned int mask, 96 unsigned int val) 97 { 98 unsigned int cmd = snd_hdac_regmap_encode_verb(nid, verb); 99 100 return snd_hdac_regmap_update_raw(codec, cmd, mask, val); 101 } 102 103 /** 104 * snd_hda_regmap_read - Read a verb with caching 105 * @nid: codec NID 106 * @verb: verb to read 107 * @val: pointer to store the value 108 * 109 * For reading an amp value, use snd_hda_regmap_get_amp(). 110 */ 111 static inline int 112 snd_hdac_regmap_read(struct hdac_device *codec, hda_nid_t nid, 113 unsigned int verb, unsigned int *val) 114 { 115 unsigned int cmd = snd_hdac_regmap_encode_verb(nid, verb); 116 117 return snd_hdac_regmap_read_raw(codec, cmd, val); 118 } 119 120 /** 121 * snd_hdac_regmap_get_amp - Read AMP value 122 * @codec: HD-audio codec 123 * @nid: NID to read the AMP value 124 * @ch: channel (left=0 or right=1) 125 * @direction: #HDA_INPUT or #HDA_OUTPUT 126 * @index: the index value (only for input direction) 127 * @val: the pointer to store the value 128 * 129 * Read AMP value. The volume is between 0 to 0x7f, 0x80 = mute bit. 130 * Returns the value or a negative error. 131 */ 132 static inline int 133 snd_hdac_regmap_get_amp(struct hdac_device *codec, hda_nid_t nid, 134 int ch, int dir, int idx) 135 { 136 unsigned int cmd = snd_hdac_regmap_encode_amp(nid, ch, dir, idx); 137 int err, val; 138 139 err = snd_hdac_regmap_read_raw(codec, cmd, &val); 140 return err < 0 ? err : val; 141 } 142 143 /** 144 * snd_hdac_regmap_update_amp - update the AMP value 145 * @codec: HD-audio codec 146 * @nid: NID to read the AMP value 147 * @ch: channel (left=0 or right=1) 148 * @direction: #HDA_INPUT or #HDA_OUTPUT 149 * @idx: the index value (only for input direction) 150 * @mask: bit mask to set 151 * @val: the bits value to set 152 * 153 * Update the AMP value with a bit mask. 154 * Returns 0 if the value is unchanged, 1 if changed, or a negative error. 155 */ 156 static inline int 157 snd_hdac_regmap_update_amp(struct hdac_device *codec, hda_nid_t nid, 158 int ch, int dir, int idx, int mask, int val) 159 { 160 unsigned int cmd = snd_hdac_regmap_encode_amp(nid, ch, dir, idx); 161 162 return snd_hdac_regmap_update_raw(codec, cmd, mask, val); 163 } 164 165 /** 166 * snd_hdac_regmap_get_amp_stereo - Read stereo AMP values 167 * @codec: HD-audio codec 168 * @nid: NID to read the AMP value 169 * @ch: channel (left=0 or right=1) 170 * @direction: #HDA_INPUT or #HDA_OUTPUT 171 * @index: the index value (only for input direction) 172 * @val: the pointer to store the value 173 * 174 * Read stereo AMP values. The lower byte is left, the upper byte is right. 175 * Returns the value or a negative error. 176 */ 177 static inline int 178 snd_hdac_regmap_get_amp_stereo(struct hdac_device *codec, hda_nid_t nid, 179 int dir, int idx) 180 { 181 unsigned int cmd = snd_hdac_regmap_encode_amp_stereo(nid, dir, idx); 182 int err, val; 183 184 err = snd_hdac_regmap_read_raw(codec, cmd, &val); 185 return err < 0 ? err : val; 186 } 187 188 /** 189 * snd_hdac_regmap_update_amp_stereo - update the stereo AMP value 190 * @codec: HD-audio codec 191 * @nid: NID to read the AMP value 192 * @direction: #HDA_INPUT or #HDA_OUTPUT 193 * @idx: the index value (only for input direction) 194 * @mask: bit mask to set 195 * @val: the bits value to set 196 * 197 * Update the stereo AMP value with a bit mask. 198 * The lower byte is left, the upper byte is right. 199 * Returns 0 if the value is unchanged, 1 if changed, or a negative error. 200 */ 201 static inline int 202 snd_hdac_regmap_update_amp_stereo(struct hdac_device *codec, hda_nid_t nid, 203 int dir, int idx, int mask, int val) 204 { 205 unsigned int cmd = snd_hdac_regmap_encode_amp_stereo(nid, dir, idx); 206 207 return snd_hdac_regmap_update_raw(codec, cmd, mask, val); 208 } 209 210 /** 211 * snd_hdac_regmap_sync_node - sync the widget node attributes 212 * @codec: HD-audio codec 213 * @nid: NID to sync 214 */ 215 static inline void 216 snd_hdac_regmap_sync_node(struct hdac_device *codec, hda_nid_t nid) 217 { 218 regcache_mark_dirty(codec->regmap); 219 regcache_sync_region(codec->regmap, nid << 20, ((nid + 1) << 20) - 1); 220 } 221 222 #endif /* __SOUND_HDA_REGMAP_H */ 223