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