14d75faa0STakashi Iwai /* 24d75faa0STakashi Iwai * HD-audio regmap helpers 34d75faa0STakashi Iwai */ 44d75faa0STakashi Iwai 54d75faa0STakashi Iwai #ifndef __SOUND_HDA_REGMAP_H 64d75faa0STakashi Iwai #define __SOUND_HDA_REGMAP_H 74d75faa0STakashi Iwai 84d75faa0STakashi Iwai #include <linux/regmap.h> 94d75faa0STakashi Iwai #include <sound/core.h> 104d75faa0STakashi Iwai #include <sound/hdaudio.h> 114d75faa0STakashi Iwai 124d75faa0STakashi Iwai int snd_hdac_regmap_init(struct hdac_device *codec); 134d75faa0STakashi Iwai void snd_hdac_regmap_exit(struct hdac_device *codec); 14*5e56bceaSTakashi Iwai int snd_hdac_regmap_add_vendor_verb(struct hdac_device *codec, 15*5e56bceaSTakashi Iwai unsigned int verb); 164d75faa0STakashi Iwai int snd_hdac_regmap_read_raw(struct hdac_device *codec, unsigned int reg, 174d75faa0STakashi Iwai unsigned int *val); 184d75faa0STakashi Iwai int snd_hdac_regmap_write_raw(struct hdac_device *codec, unsigned int reg, 194d75faa0STakashi Iwai unsigned int val); 204d75faa0STakashi Iwai int snd_hdac_regmap_update_raw(struct hdac_device *codec, unsigned int reg, 214d75faa0STakashi Iwai unsigned int mask, unsigned int val); 224d75faa0STakashi Iwai 234d75faa0STakashi Iwai /** 244d75faa0STakashi Iwai * snd_hdac_regmap_encode_verb - encode the verb to a pseudo register 254d75faa0STakashi Iwai * @nid: widget NID 264d75faa0STakashi Iwai * @verb: codec verb 274d75faa0STakashi Iwai * 284d75faa0STakashi Iwai * Returns an encoded pseudo register. 294d75faa0STakashi Iwai */ 304d75faa0STakashi Iwai #define snd_hdac_regmap_encode_verb(nid, verb) \ 314d75faa0STakashi Iwai (((verb) << 8) | 0x80000 | ((unsigned int)(nid) << 20)) 324d75faa0STakashi Iwai 334d75faa0STakashi Iwai /** 344d75faa0STakashi Iwai * snd_hdac_regmap_encode_amp - encode the AMP verb to a pseudo register 354d75faa0STakashi Iwai * @nid: widget NID 364d75faa0STakashi Iwai * @ch: channel (left = 0, right = 1) 374d75faa0STakashi Iwai * @dir: direction (#HDA_INPUT, #HDA_OUTPUT) 384d75faa0STakashi Iwai * @idx: input index value 394d75faa0STakashi Iwai * 404d75faa0STakashi Iwai * Returns an encoded pseudo register. 414d75faa0STakashi Iwai */ 424d75faa0STakashi Iwai #define snd_hdac_regmap_encode_amp(nid, ch, dir, idx) \ 434d75faa0STakashi Iwai (snd_hdac_regmap_encode_verb(nid, AC_VERB_GET_AMP_GAIN_MUTE) | \ 444d75faa0STakashi Iwai ((ch) ? AC_AMP_GET_RIGHT : AC_AMP_GET_LEFT) | \ 454d75faa0STakashi Iwai ((dir) == HDA_OUTPUT ? AC_AMP_GET_OUTPUT : AC_AMP_GET_INPUT) | \ 464d75faa0STakashi Iwai (idx)) 474d75faa0STakashi Iwai 484d75faa0STakashi Iwai /** 494d75faa0STakashi Iwai * snd_hdac_regmap_write - Write a verb with caching 504d75faa0STakashi Iwai * @nid: codec NID 514d75faa0STakashi Iwai * @reg: verb to write 524d75faa0STakashi Iwai * @val: value to write 534d75faa0STakashi Iwai * 544d75faa0STakashi Iwai * For writing an amp value, use snd_hda_regmap_amp_update(). 554d75faa0STakashi Iwai */ 564d75faa0STakashi Iwai static inline int 574d75faa0STakashi Iwai snd_hdac_regmap_write(struct hdac_device *codec, hda_nid_t nid, 584d75faa0STakashi Iwai unsigned int verb, unsigned int val) 594d75faa0STakashi Iwai { 604d75faa0STakashi Iwai unsigned int cmd = snd_hdac_regmap_encode_verb(nid, verb); 614d75faa0STakashi Iwai 624d75faa0STakashi Iwai return snd_hdac_regmap_write_raw(codec, cmd, val); 634d75faa0STakashi Iwai } 644d75faa0STakashi Iwai 654d75faa0STakashi Iwai /** 664d75faa0STakashi Iwai * snd_hda_regmap_update - Update a verb value with caching 674d75faa0STakashi Iwai * @nid: codec NID 684d75faa0STakashi Iwai * @verb: verb to update 694d75faa0STakashi Iwai * @mask: bit mask to update 704d75faa0STakashi Iwai * @val: value to update 714d75faa0STakashi Iwai * 724d75faa0STakashi Iwai * For updating an amp value, use snd_hda_regmap_amp_update(). 734d75faa0STakashi Iwai */ 744d75faa0STakashi Iwai static inline int 754d75faa0STakashi Iwai snd_hdac_regmap_update(struct hdac_device *codec, hda_nid_t nid, 764d75faa0STakashi Iwai unsigned int verb, unsigned int mask, 774d75faa0STakashi Iwai unsigned int val) 784d75faa0STakashi Iwai { 794d75faa0STakashi Iwai unsigned int cmd = snd_hdac_regmap_encode_verb(nid, verb); 804d75faa0STakashi Iwai 814d75faa0STakashi Iwai return snd_hdac_regmap_update_raw(codec, cmd, mask, val); 824d75faa0STakashi Iwai } 834d75faa0STakashi Iwai 844d75faa0STakashi Iwai /** 854d75faa0STakashi Iwai * snd_hda_regmap_read - Read a verb with caching 864d75faa0STakashi Iwai * @nid: codec NID 874d75faa0STakashi Iwai * @verb: verb to read 884d75faa0STakashi Iwai * @val: pointer to store the value 894d75faa0STakashi Iwai * 904d75faa0STakashi Iwai * For reading an amp value, use snd_hda_regmap_get_amp(). 914d75faa0STakashi Iwai */ 924d75faa0STakashi Iwai static inline int 934d75faa0STakashi Iwai snd_hdac_regmap_read(struct hdac_device *codec, hda_nid_t nid, 944d75faa0STakashi Iwai unsigned int verb, unsigned int *val) 954d75faa0STakashi Iwai { 964d75faa0STakashi Iwai unsigned int cmd = snd_hdac_regmap_encode_verb(nid, verb); 974d75faa0STakashi Iwai 984d75faa0STakashi Iwai return snd_hdac_regmap_read_raw(codec, cmd, val); 994d75faa0STakashi Iwai } 1004d75faa0STakashi Iwai 1014d75faa0STakashi Iwai /** 1024d75faa0STakashi Iwai * snd_hdac_regmap_get_amp - Read AMP value 1034d75faa0STakashi Iwai * @codec: HD-audio codec 1044d75faa0STakashi Iwai * @nid: NID to read the AMP value 1054d75faa0STakashi Iwai * @ch: channel (left=0 or right=1) 1064d75faa0STakashi Iwai * @direction: #HDA_INPUT or #HDA_OUTPUT 1074d75faa0STakashi Iwai * @index: the index value (only for input direction) 1084d75faa0STakashi Iwai * @val: the pointer to store the value 1094d75faa0STakashi Iwai * 1104d75faa0STakashi Iwai * Read AMP value. The volume is between 0 to 0x7f, 0x80 = mute bit. 1114d75faa0STakashi Iwai * Returns the value or a negative error. 1124d75faa0STakashi Iwai */ 1134d75faa0STakashi Iwai static inline int 1144d75faa0STakashi Iwai snd_hdac_regmap_get_amp(struct hdac_device *codec, hda_nid_t nid, 1154d75faa0STakashi Iwai int ch, int dir, int idx) 1164d75faa0STakashi Iwai { 1174d75faa0STakashi Iwai unsigned int cmd = snd_hdac_regmap_encode_amp(nid, ch, dir, idx); 1184d75faa0STakashi Iwai int err, val; 1194d75faa0STakashi Iwai 1204d75faa0STakashi Iwai err = snd_hdac_regmap_read_raw(codec, cmd, &val); 1214d75faa0STakashi Iwai return err < 0 ? err : val; 1224d75faa0STakashi Iwai } 1234d75faa0STakashi Iwai 1244d75faa0STakashi Iwai /** 1254d75faa0STakashi Iwai * snd_hdac_regmap_update_amp - update the AMP value 1264d75faa0STakashi Iwai * @codec: HD-audio codec 1274d75faa0STakashi Iwai * @nid: NID to read the AMP value 1284d75faa0STakashi Iwai * @ch: channel (left=0 or right=1) 1294d75faa0STakashi Iwai * @direction: #HDA_INPUT or #HDA_OUTPUT 1304d75faa0STakashi Iwai * @idx: the index value (only for input direction) 1314d75faa0STakashi Iwai * @mask: bit mask to set 1324d75faa0STakashi Iwai * @val: the bits value to set 1334d75faa0STakashi Iwai * 1344d75faa0STakashi Iwai * Update the AMP value with a bit mask. 1354d75faa0STakashi Iwai * Returns 0 if the value is unchanged, 1 if changed, or a negative error. 1364d75faa0STakashi Iwai */ 1374d75faa0STakashi Iwai static inline int 1384d75faa0STakashi Iwai snd_hdac_regmap_update_amp(struct hdac_device *codec, hda_nid_t nid, 1394d75faa0STakashi Iwai int ch, int dir, int idx, int mask, int val) 1404d75faa0STakashi Iwai { 1414d75faa0STakashi Iwai unsigned int cmd = snd_hdac_regmap_encode_amp(nid, ch, dir, idx); 1424d75faa0STakashi Iwai 1434d75faa0STakashi Iwai return snd_hdac_regmap_update_raw(codec, cmd, mask, val); 1444d75faa0STakashi Iwai } 1454d75faa0STakashi Iwai 1464d75faa0STakashi Iwai #endif /* __SOUND_HDA_REGMAP_H */ 147