1457c8996SThomas Gleixner // SPDX-License-Identifier: GPL-2.0-only
24d75faa0STakashi Iwai /*
34d75faa0STakashi Iwai * Regmap support for HD-audio verbs
44d75faa0STakashi Iwai *
54d75faa0STakashi Iwai * A virtual register is translated to one or more hda verbs for write,
64d75faa0STakashi Iwai * vice versa for read.
74d75faa0STakashi Iwai *
84d75faa0STakashi Iwai * A few limitations:
94d75faa0STakashi Iwai * - Provided for not all verbs but only subset standard non-volatile verbs.
104d75faa0STakashi Iwai * - For reading, only AC_VERB_GET_* variants can be used.
114d75faa0STakashi Iwai * - For writing, mapped to the *corresponding* AC_VERB_SET_* variants,
124d75faa0STakashi Iwai * so can't handle asymmetric verbs for read and write
134d75faa0STakashi Iwai */
144d75faa0STakashi Iwai
154d75faa0STakashi Iwai #include <linux/slab.h>
164d75faa0STakashi Iwai #include <linux/device.h>
174d75faa0STakashi Iwai #include <linux/regmap.h>
184d75faa0STakashi Iwai #include <linux/export.h>
194d75faa0STakashi Iwai #include <linux/pm.h>
204d75faa0STakashi Iwai #include <sound/core.h>
214d75faa0STakashi Iwai #include <sound/hdaudio.h>
224d75faa0STakashi Iwai #include <sound/hda_regmap.h>
23ddf7cb83STakashi Iwai #include "local.h"
244d75faa0STakashi Iwai
codec_pm_lock(struct hdac_device * codec)25fc4f000bSTakashi Iwai static int codec_pm_lock(struct hdac_device *codec)
26fc4f000bSTakashi Iwai {
27fc4f000bSTakashi Iwai return snd_hdac_keep_power_up(codec);
28fc4f000bSTakashi Iwai }
29fc4f000bSTakashi Iwai
codec_pm_unlock(struct hdac_device * codec,int lock)30fc4f000bSTakashi Iwai static void codec_pm_unlock(struct hdac_device *codec, int lock)
31fc4f000bSTakashi Iwai {
32fc4f000bSTakashi Iwai if (lock == 1)
33fc4f000bSTakashi Iwai snd_hdac_power_down_pm(codec);
34fc4f000bSTakashi Iwai }
354d75faa0STakashi Iwai
364d75faa0STakashi Iwai #define get_verb(reg) (((reg) >> 8) & 0xfff)
374d75faa0STakashi Iwai
hda_volatile_reg(struct device * dev,unsigned int reg)384d75faa0STakashi Iwai static bool hda_volatile_reg(struct device *dev, unsigned int reg)
394d75faa0STakashi Iwai {
4040ba66a7STakashi Iwai struct hdac_device *codec = dev_to_hdac_dev(dev);
414d75faa0STakashi Iwai unsigned int verb = get_verb(reg);
424d75faa0STakashi Iwai
434d75faa0STakashi Iwai switch (verb) {
444d75faa0STakashi Iwai case AC_VERB_GET_PROC_COEF:
4540ba66a7STakashi Iwai return !codec->cache_coef;
464d75faa0STakashi Iwai case AC_VERB_GET_COEF_INDEX:
474d75faa0STakashi Iwai case AC_VERB_GET_PROC_STATE:
484d75faa0STakashi Iwai case AC_VERB_GET_POWER_STATE:
494d75faa0STakashi Iwai case AC_VERB_GET_PIN_SENSE:
504d75faa0STakashi Iwai case AC_VERB_GET_HDMI_DIP_SIZE:
514d75faa0STakashi Iwai case AC_VERB_GET_HDMI_ELDD:
524d75faa0STakashi Iwai case AC_VERB_GET_HDMI_DIP_INDEX:
534d75faa0STakashi Iwai case AC_VERB_GET_HDMI_DIP_DATA:
544d75faa0STakashi Iwai case AC_VERB_GET_HDMI_DIP_XMIT:
554d75faa0STakashi Iwai case AC_VERB_GET_HDMI_CP_CTRL:
564d75faa0STakashi Iwai case AC_VERB_GET_HDMI_CHAN_SLOT:
574d75faa0STakashi Iwai case AC_VERB_GET_DEVICE_SEL:
584d75faa0STakashi Iwai case AC_VERB_GET_DEVICE_LIST: /* read-only volatile */
594d75faa0STakashi Iwai return true;
604d75faa0STakashi Iwai }
614d75faa0STakashi Iwai
624d75faa0STakashi Iwai return false;
634d75faa0STakashi Iwai }
644d75faa0STakashi Iwai
hda_writeable_reg(struct device * dev,unsigned int reg)654d75faa0STakashi Iwai static bool hda_writeable_reg(struct device *dev, unsigned int reg)
664d75faa0STakashi Iwai {
67faa75f8aSTakashi Iwai struct hdac_device *codec = dev_to_hdac_dev(dev);
684d75faa0STakashi Iwai unsigned int verb = get_verb(reg);
69a9c2dfc8STakashi Iwai const unsigned int *v;
705e56bceaSTakashi Iwai int i;
715e56bceaSTakashi Iwai
72a9c2dfc8STakashi Iwai snd_array_for_each(&codec->vendor_verbs, i, v) {
735e56bceaSTakashi Iwai if (verb == *v)
745e56bceaSTakashi Iwai return true;
755e56bceaSTakashi Iwai }
764d75faa0STakashi Iwai
77faa75f8aSTakashi Iwai if (codec->caps_overwriting)
78faa75f8aSTakashi Iwai return true;
79faa75f8aSTakashi Iwai
804d75faa0STakashi Iwai switch (verb & 0xf00) {
814d75faa0STakashi Iwai case AC_VERB_GET_STREAM_FORMAT:
824d75faa0STakashi Iwai case AC_VERB_GET_AMP_GAIN_MUTE:
834d75faa0STakashi Iwai return true;
8440ba66a7STakashi Iwai case AC_VERB_GET_PROC_COEF:
8540ba66a7STakashi Iwai return codec->cache_coef;
864d75faa0STakashi Iwai case 0xf00:
874d75faa0STakashi Iwai break;
884d75faa0STakashi Iwai default:
894d75faa0STakashi Iwai return false;
904d75faa0STakashi Iwai }
914d75faa0STakashi Iwai
924d75faa0STakashi Iwai switch (verb) {
934d75faa0STakashi Iwai case AC_VERB_GET_CONNECT_SEL:
944d75faa0STakashi Iwai case AC_VERB_GET_SDI_SELECT:
954d75faa0STakashi Iwai case AC_VERB_GET_PIN_WIDGET_CONTROL:
964d75faa0STakashi Iwai case AC_VERB_GET_UNSOLICITED_RESPONSE: /* only as SET_UNSOLICITED_ENABLE */
974d75faa0STakashi Iwai case AC_VERB_GET_BEEP_CONTROL:
984d75faa0STakashi Iwai case AC_VERB_GET_EAPD_BTLENABLE:
994d75faa0STakashi Iwai case AC_VERB_GET_DIGI_CONVERT_1:
1004d75faa0STakashi Iwai case AC_VERB_GET_DIGI_CONVERT_2: /* only for beep control */
1014d75faa0STakashi Iwai case AC_VERB_GET_VOLUME_KNOB_CONTROL:
1024d75faa0STakashi Iwai case AC_VERB_GET_GPIO_MASK:
1034d75faa0STakashi Iwai case AC_VERB_GET_GPIO_DIRECTION:
1044d75faa0STakashi Iwai case AC_VERB_GET_GPIO_DATA: /* not for volatile read */
1054d75faa0STakashi Iwai case AC_VERB_GET_GPIO_WAKE_MASK:
1064d75faa0STakashi Iwai case AC_VERB_GET_GPIO_UNSOLICITED_RSP_MASK:
1074d75faa0STakashi Iwai case AC_VERB_GET_GPIO_STICKY_MASK:
1084d75faa0STakashi Iwai return true;
1094d75faa0STakashi Iwai }
1104d75faa0STakashi Iwai
1114d75faa0STakashi Iwai return false;
1124d75faa0STakashi Iwai }
1134d75faa0STakashi Iwai
hda_readable_reg(struct device * dev,unsigned int reg)1144d75faa0STakashi Iwai static bool hda_readable_reg(struct device *dev, unsigned int reg)
1154d75faa0STakashi Iwai {
116faa75f8aSTakashi Iwai struct hdac_device *codec = dev_to_hdac_dev(dev);
1174d75faa0STakashi Iwai unsigned int verb = get_verb(reg);
1184d75faa0STakashi Iwai
119faa75f8aSTakashi Iwai if (codec->caps_overwriting)
120faa75f8aSTakashi Iwai return true;
121faa75f8aSTakashi Iwai
1224d75faa0STakashi Iwai switch (verb) {
1234d75faa0STakashi Iwai case AC_VERB_PARAMETERS:
1244d75faa0STakashi Iwai case AC_VERB_GET_CONNECT_LIST:
1254d75faa0STakashi Iwai case AC_VERB_GET_SUBSYSTEM_ID:
1264d75faa0STakashi Iwai return true;
1278bc174e9STakashi Iwai /* below are basically writable, but disabled for reducing unnecessary
1288bc174e9STakashi Iwai * writes at sync
1298bc174e9STakashi Iwai */
1308bc174e9STakashi Iwai case AC_VERB_GET_CONFIG_DEFAULT: /* usually just read */
1318bc174e9STakashi Iwai case AC_VERB_GET_CONV: /* managed in PCM code */
1328bc174e9STakashi Iwai case AC_VERB_GET_CVT_CHAN_COUNT: /* managed in HDMI CA code */
1338bc174e9STakashi Iwai return true;
1344d75faa0STakashi Iwai }
1354d75faa0STakashi Iwai
1364d75faa0STakashi Iwai return hda_writeable_reg(dev, reg);
1374d75faa0STakashi Iwai }
1384d75faa0STakashi Iwai
139d313e0a8STakashi Iwai /*
140d313e0a8STakashi Iwai * Stereo amp pseudo register:
141d313e0a8STakashi Iwai * for making easier to handle the stereo volume control, we provide a
142d313e0a8STakashi Iwai * fake register to deal both left and right channels by a single
143d313e0a8STakashi Iwai * (pseudo) register access. A verb consisting of SET_AMP_GAIN with
144d313e0a8STakashi Iwai * *both* SET_LEFT and SET_RIGHT bits takes a 16bit value, the lower 8bit
145d313e0a8STakashi Iwai * for the left and the upper 8bit for the right channel.
146d313e0a8STakashi Iwai */
is_stereo_amp_verb(unsigned int reg)147d313e0a8STakashi Iwai static bool is_stereo_amp_verb(unsigned int reg)
148d313e0a8STakashi Iwai {
149d313e0a8STakashi Iwai if (((reg >> 8) & 0x700) != AC_VERB_SET_AMP_GAIN_MUTE)
150d313e0a8STakashi Iwai return false;
151d313e0a8STakashi Iwai return (reg & (AC_AMP_SET_LEFT | AC_AMP_SET_RIGHT)) ==
152d313e0a8STakashi Iwai (AC_AMP_SET_LEFT | AC_AMP_SET_RIGHT);
153d313e0a8STakashi Iwai }
154d313e0a8STakashi Iwai
155d313e0a8STakashi Iwai /* read a pseudo stereo amp register (16bit left+right) */
hda_reg_read_stereo_amp(struct hdac_device * codec,unsigned int reg,unsigned int * val)156d313e0a8STakashi Iwai static int hda_reg_read_stereo_amp(struct hdac_device *codec,
157d313e0a8STakashi Iwai unsigned int reg, unsigned int *val)
158d313e0a8STakashi Iwai {
159d313e0a8STakashi Iwai unsigned int left, right;
160d313e0a8STakashi Iwai int err;
161d313e0a8STakashi Iwai
162d313e0a8STakashi Iwai reg &= ~(AC_AMP_SET_LEFT | AC_AMP_SET_RIGHT);
163d313e0a8STakashi Iwai err = snd_hdac_exec_verb(codec, reg | AC_AMP_GET_LEFT, 0, &left);
164d313e0a8STakashi Iwai if (err < 0)
165d313e0a8STakashi Iwai return err;
166d313e0a8STakashi Iwai err = snd_hdac_exec_verb(codec, reg | AC_AMP_GET_RIGHT, 0, &right);
167d313e0a8STakashi Iwai if (err < 0)
168d313e0a8STakashi Iwai return err;
169d313e0a8STakashi Iwai *val = left | (right << 8);
170d313e0a8STakashi Iwai return 0;
171d313e0a8STakashi Iwai }
172d313e0a8STakashi Iwai
173d313e0a8STakashi Iwai /* write a pseudo stereo amp register (16bit left+right) */
hda_reg_write_stereo_amp(struct hdac_device * codec,unsigned int reg,unsigned int val)174d313e0a8STakashi Iwai static int hda_reg_write_stereo_amp(struct hdac_device *codec,
175d313e0a8STakashi Iwai unsigned int reg, unsigned int val)
176d313e0a8STakashi Iwai {
177d313e0a8STakashi Iwai int err;
178d313e0a8STakashi Iwai unsigned int verb, left, right;
179d313e0a8STakashi Iwai
180d313e0a8STakashi Iwai verb = AC_VERB_SET_AMP_GAIN_MUTE << 8;
181d313e0a8STakashi Iwai if (reg & AC_AMP_GET_OUTPUT)
182d313e0a8STakashi Iwai verb |= AC_AMP_SET_OUTPUT;
183d313e0a8STakashi Iwai else
184d313e0a8STakashi Iwai verb |= AC_AMP_SET_INPUT | ((reg & 0xf) << 8);
185d313e0a8STakashi Iwai reg = (reg & ~0xfffff) | verb;
186d313e0a8STakashi Iwai
187d313e0a8STakashi Iwai left = val & 0xff;
188d313e0a8STakashi Iwai right = (val >> 8) & 0xff;
189d313e0a8STakashi Iwai if (left == right) {
190d313e0a8STakashi Iwai reg |= AC_AMP_SET_LEFT | AC_AMP_SET_RIGHT;
191d313e0a8STakashi Iwai return snd_hdac_exec_verb(codec, reg | left, 0, NULL);
192d313e0a8STakashi Iwai }
193d313e0a8STakashi Iwai
194d313e0a8STakashi Iwai err = snd_hdac_exec_verb(codec, reg | AC_AMP_SET_LEFT | left, 0, NULL);
195d313e0a8STakashi Iwai if (err < 0)
196d313e0a8STakashi Iwai return err;
197d313e0a8STakashi Iwai err = snd_hdac_exec_verb(codec, reg | AC_AMP_SET_RIGHT | right, 0, NULL);
198d313e0a8STakashi Iwai if (err < 0)
199d313e0a8STakashi Iwai return err;
200d313e0a8STakashi Iwai return 0;
201d313e0a8STakashi Iwai }
202d313e0a8STakashi Iwai
20340ba66a7STakashi Iwai /* read a pseudo coef register (16bit) */
hda_reg_read_coef(struct hdac_device * codec,unsigned int reg,unsigned int * val)20440ba66a7STakashi Iwai static int hda_reg_read_coef(struct hdac_device *codec, unsigned int reg,
20540ba66a7STakashi Iwai unsigned int *val)
20640ba66a7STakashi Iwai {
20740ba66a7STakashi Iwai unsigned int verb;
20840ba66a7STakashi Iwai int err;
20940ba66a7STakashi Iwai
21040ba66a7STakashi Iwai if (!codec->cache_coef)
21140ba66a7STakashi Iwai return -EINVAL;
21240ba66a7STakashi Iwai /* LSB 8bit = coef index */
21340ba66a7STakashi Iwai verb = (reg & ~0xfff00) | (AC_VERB_SET_COEF_INDEX << 8);
21440ba66a7STakashi Iwai err = snd_hdac_exec_verb(codec, verb, 0, NULL);
21540ba66a7STakashi Iwai if (err < 0)
21640ba66a7STakashi Iwai return err;
21740ba66a7STakashi Iwai verb = (reg & ~0xfffff) | (AC_VERB_GET_COEF_INDEX << 8);
21840ba66a7STakashi Iwai return snd_hdac_exec_verb(codec, verb, 0, val);
21940ba66a7STakashi Iwai }
22040ba66a7STakashi Iwai
22140ba66a7STakashi Iwai /* write a pseudo coef register (16bit) */
hda_reg_write_coef(struct hdac_device * codec,unsigned int reg,unsigned int val)22240ba66a7STakashi Iwai static int hda_reg_write_coef(struct hdac_device *codec, unsigned int reg,
22340ba66a7STakashi Iwai unsigned int val)
22440ba66a7STakashi Iwai {
22540ba66a7STakashi Iwai unsigned int verb;
22640ba66a7STakashi Iwai int err;
22740ba66a7STakashi Iwai
22840ba66a7STakashi Iwai if (!codec->cache_coef)
22940ba66a7STakashi Iwai return -EINVAL;
23040ba66a7STakashi Iwai /* LSB 8bit = coef index */
23140ba66a7STakashi Iwai verb = (reg & ~0xfff00) | (AC_VERB_SET_COEF_INDEX << 8);
23240ba66a7STakashi Iwai err = snd_hdac_exec_verb(codec, verb, 0, NULL);
23340ba66a7STakashi Iwai if (err < 0)
23440ba66a7STakashi Iwai return err;
23540ba66a7STakashi Iwai verb = (reg & ~0xfffff) | (AC_VERB_GET_COEF_INDEX << 8) |
23640ba66a7STakashi Iwai (val & 0xffff);
23740ba66a7STakashi Iwai return snd_hdac_exec_verb(codec, verb, 0, NULL);
23840ba66a7STakashi Iwai }
23940ba66a7STakashi Iwai
hda_reg_read(void * context,unsigned int reg,unsigned int * val)2404d75faa0STakashi Iwai static int hda_reg_read(void *context, unsigned int reg, unsigned int *val)
2414d75faa0STakashi Iwai {
2424d75faa0STakashi Iwai struct hdac_device *codec = context;
24340ba66a7STakashi Iwai int verb = get_verb(reg);
24433f81940STakashi Iwai int err;
245fc4f000bSTakashi Iwai int pm_lock = 0;
2464d75faa0STakashi Iwai
247fc4f000bSTakashi Iwai if (verb != AC_VERB_GET_POWER_STATE) {
248fc4f000bSTakashi Iwai pm_lock = codec_pm_lock(codec);
249fc4f000bSTakashi Iwai if (pm_lock < 0)
2504d75faa0STakashi Iwai return -EAGAIN;
251fc4f000bSTakashi Iwai }
2524d75faa0STakashi Iwai reg |= (codec->addr << 28);
253fc4f000bSTakashi Iwai if (is_stereo_amp_verb(reg)) {
254fc4f000bSTakashi Iwai err = hda_reg_read_stereo_amp(codec, reg, val);
255fc4f000bSTakashi Iwai goto out;
256fc4f000bSTakashi Iwai }
257fc4f000bSTakashi Iwai if (verb == AC_VERB_GET_PROC_COEF) {
258fc4f000bSTakashi Iwai err = hda_reg_read_coef(codec, reg, val);
259fc4f000bSTakashi Iwai goto out;
260fc4f000bSTakashi Iwai }
261a686ec4cSTakashi Iwai if ((verb & 0x700) == AC_VERB_SET_AMP_GAIN_MUTE)
262a686ec4cSTakashi Iwai reg &= ~AC_AMP_FAKE_MUTE;
263a686ec4cSTakashi Iwai
26433f81940STakashi Iwai err = snd_hdac_exec_verb(codec, reg, 0, val);
26533f81940STakashi Iwai if (err < 0)
266fc4f000bSTakashi Iwai goto out;
26733f81940STakashi Iwai /* special handling for asymmetric reads */
26840ba66a7STakashi Iwai if (verb == AC_VERB_GET_POWER_STATE) {
26933f81940STakashi Iwai if (*val & AC_PWRST_ERROR)
27033f81940STakashi Iwai *val = -1;
27133f81940STakashi Iwai else /* take only the actual state */
27233f81940STakashi Iwai *val = (*val >> 4) & 0x0f;
27333f81940STakashi Iwai }
274fc4f000bSTakashi Iwai out:
275fc4f000bSTakashi Iwai codec_pm_unlock(codec, pm_lock);
276fc4f000bSTakashi Iwai return err;
2774d75faa0STakashi Iwai }
2784d75faa0STakashi Iwai
hda_reg_write(void * context,unsigned int reg,unsigned int val)2794d75faa0STakashi Iwai static int hda_reg_write(void *context, unsigned int reg, unsigned int val)
2804d75faa0STakashi Iwai {
2814d75faa0STakashi Iwai struct hdac_device *codec = context;
2824d75faa0STakashi Iwai unsigned int verb;
2834d75faa0STakashi Iwai int i, bytes, err;
284fc4f000bSTakashi Iwai int pm_lock = 0;
2854d75faa0STakashi Iwai
28698a226edSTakashi Iwai if (codec->caps_overwriting)
28798a226edSTakashi Iwai return 0;
28898a226edSTakashi Iwai
2894d75faa0STakashi Iwai reg &= ~0x00080000U; /* drop GET bit */
2904d75faa0STakashi Iwai reg |= (codec->addr << 28);
2919efe2731STakashi Iwai verb = get_verb(reg);
2929efe2731STakashi Iwai
293fc4f000bSTakashi Iwai if (verb != AC_VERB_SET_POWER_STATE) {
294fc4f000bSTakashi Iwai pm_lock = codec_pm_lock(codec);
295fc4f000bSTakashi Iwai if (pm_lock < 0)
2969efe2731STakashi Iwai return codec->lazy_cache ? 0 : -EAGAIN;
297fc4f000bSTakashi Iwai }
2984d75faa0STakashi Iwai
299fc4f000bSTakashi Iwai if (is_stereo_amp_verb(reg)) {
300fc4f000bSTakashi Iwai err = hda_reg_write_stereo_amp(codec, reg, val);
301fc4f000bSTakashi Iwai goto out;
302fc4f000bSTakashi Iwai }
303d313e0a8STakashi Iwai
304fc4f000bSTakashi Iwai if (verb == AC_VERB_SET_PROC_COEF) {
305fc4f000bSTakashi Iwai err = hda_reg_write_coef(codec, reg, val);
306fc4f000bSTakashi Iwai goto out;
307fc4f000bSTakashi Iwai }
30840ba66a7STakashi Iwai
3094d75faa0STakashi Iwai switch (verb & 0xf00) {
3104d75faa0STakashi Iwai case AC_VERB_SET_AMP_GAIN_MUTE:
311a686ec4cSTakashi Iwai if ((reg & AC_AMP_FAKE_MUTE) && (val & AC_AMP_MUTE))
312a686ec4cSTakashi Iwai val = 0;
3134d75faa0STakashi Iwai verb = AC_VERB_SET_AMP_GAIN_MUTE;
3144d75faa0STakashi Iwai if (reg & AC_AMP_GET_LEFT)
3154d75faa0STakashi Iwai verb |= AC_AMP_SET_LEFT >> 8;
3164d75faa0STakashi Iwai else
3174d75faa0STakashi Iwai verb |= AC_AMP_SET_RIGHT >> 8;
3184d75faa0STakashi Iwai if (reg & AC_AMP_GET_OUTPUT) {
3194d75faa0STakashi Iwai verb |= AC_AMP_SET_OUTPUT >> 8;
3204d75faa0STakashi Iwai } else {
3214d75faa0STakashi Iwai verb |= AC_AMP_SET_INPUT >> 8;
3224d75faa0STakashi Iwai verb |= reg & 0xf;
3234d75faa0STakashi Iwai }
3244d75faa0STakashi Iwai break;
3254d75faa0STakashi Iwai }
3264d75faa0STakashi Iwai
3274d75faa0STakashi Iwai switch (verb) {
3284d75faa0STakashi Iwai case AC_VERB_SET_DIGI_CONVERT_1:
3294d75faa0STakashi Iwai bytes = 2;
3304d75faa0STakashi Iwai break;
3314d75faa0STakashi Iwai case AC_VERB_SET_CONFIG_DEFAULT_BYTES_0:
3324d75faa0STakashi Iwai bytes = 4;
3334d75faa0STakashi Iwai break;
3344d75faa0STakashi Iwai default:
3354d75faa0STakashi Iwai bytes = 1;
3364d75faa0STakashi Iwai break;
3374d75faa0STakashi Iwai }
3384d75faa0STakashi Iwai
3394d75faa0STakashi Iwai for (i = 0; i < bytes; i++) {
3404d75faa0STakashi Iwai reg &= ~0xfffff;
3414d75faa0STakashi Iwai reg |= (verb + i) << 8 | ((val >> (8 * i)) & 0xff);
3424d75faa0STakashi Iwai err = snd_hdac_exec_verb(codec, reg, 0, NULL);
3434d75faa0STakashi Iwai if (err < 0)
344fc4f000bSTakashi Iwai goto out;
3454d75faa0STakashi Iwai }
3464d75faa0STakashi Iwai
347fc4f000bSTakashi Iwai out:
348fc4f000bSTakashi Iwai codec_pm_unlock(codec, pm_lock);
349fc4f000bSTakashi Iwai return err;
3504d75faa0STakashi Iwai }
3514d75faa0STakashi Iwai
3524d75faa0STakashi Iwai static const struct regmap_config hda_regmap_cfg = {
3534d75faa0STakashi Iwai .name = "hdaudio",
3544d75faa0STakashi Iwai .reg_bits = 32,
3554d75faa0STakashi Iwai .val_bits = 32,
3564d75faa0STakashi Iwai .max_register = 0xfffffff,
3574d75faa0STakashi Iwai .writeable_reg = hda_writeable_reg,
3584d75faa0STakashi Iwai .readable_reg = hda_readable_reg,
3594d75faa0STakashi Iwai .volatile_reg = hda_volatile_reg,
36015253079SMark Brown .cache_type = REGCACHE_MAPLE,
3614d75faa0STakashi Iwai .reg_read = hda_reg_read,
3624d75faa0STakashi Iwai .reg_write = hda_reg_write,
3631c96a2f6SDavid Frey .use_single_read = true,
3641c96a2f6SDavid Frey .use_single_write = true,
3651a462be5STakashi Iwai .disable_locking = true,
3664d75faa0STakashi Iwai };
3674d75faa0STakashi Iwai
36878dd5e21STakashi Iwai /**
36978dd5e21STakashi Iwai * snd_hdac_regmap_init - Initialize regmap for HDA register accesses
37078dd5e21STakashi Iwai * @codec: the codec object
37178dd5e21STakashi Iwai *
37278dd5e21STakashi Iwai * Returns zero for success or a negative error code.
37378dd5e21STakashi Iwai */
snd_hdac_regmap_init(struct hdac_device * codec)3744d75faa0STakashi Iwai int snd_hdac_regmap_init(struct hdac_device *codec)
3754d75faa0STakashi Iwai {
3764d75faa0STakashi Iwai struct regmap *regmap;
3774d75faa0STakashi Iwai
3784d75faa0STakashi Iwai regmap = regmap_init(&codec->dev, NULL, codec, &hda_regmap_cfg);
3794d75faa0STakashi Iwai if (IS_ERR(regmap))
3804d75faa0STakashi Iwai return PTR_ERR(regmap);
3814d75faa0STakashi Iwai codec->regmap = regmap;
3825e56bceaSTakashi Iwai snd_array_init(&codec->vendor_verbs, sizeof(unsigned int), 8);
3834d75faa0STakashi Iwai return 0;
3844d75faa0STakashi Iwai }
3854d75faa0STakashi Iwai EXPORT_SYMBOL_GPL(snd_hdac_regmap_init);
3864d75faa0STakashi Iwai
38778dd5e21STakashi Iwai /**
3883531ba21SPierre-Louis Bossart * snd_hdac_regmap_exit - Release the regmap from HDA codec
38978dd5e21STakashi Iwai * @codec: the codec object
39078dd5e21STakashi Iwai */
snd_hdac_regmap_exit(struct hdac_device * codec)3914d75faa0STakashi Iwai void snd_hdac_regmap_exit(struct hdac_device *codec)
3924d75faa0STakashi Iwai {
3934d75faa0STakashi Iwai if (codec->regmap) {
3944d75faa0STakashi Iwai regmap_exit(codec->regmap);
3954d75faa0STakashi Iwai codec->regmap = NULL;
3965e56bceaSTakashi Iwai snd_array_free(&codec->vendor_verbs);
3974d75faa0STakashi Iwai }
3984d75faa0STakashi Iwai }
3994d75faa0STakashi Iwai EXPORT_SYMBOL_GPL(snd_hdac_regmap_exit);
4004d75faa0STakashi Iwai
4015e56bceaSTakashi Iwai /**
4025e56bceaSTakashi Iwai * snd_hdac_regmap_add_vendor_verb - add a vendor-specific verb to regmap
4035e56bceaSTakashi Iwai * @codec: the codec object
4045e56bceaSTakashi Iwai * @verb: verb to allow accessing via regmap
4055e56bceaSTakashi Iwai *
4065e56bceaSTakashi Iwai * Returns zero for success or a negative error code.
4075e56bceaSTakashi Iwai */
snd_hdac_regmap_add_vendor_verb(struct hdac_device * codec,unsigned int verb)4085e56bceaSTakashi Iwai int snd_hdac_regmap_add_vendor_verb(struct hdac_device *codec,
4095e56bceaSTakashi Iwai unsigned int verb)
4105e56bceaSTakashi Iwai {
4115e56bceaSTakashi Iwai unsigned int *p = snd_array_new(&codec->vendor_verbs);
4125e56bceaSTakashi Iwai
4135e56bceaSTakashi Iwai if (!p)
4145e56bceaSTakashi Iwai return -ENOMEM;
415d6eb9e3eSMengdong Lin *p = verb | 0x800; /* set GET bit */
4165e56bceaSTakashi Iwai return 0;
4175e56bceaSTakashi Iwai }
4185e56bceaSTakashi Iwai EXPORT_SYMBOL_GPL(snd_hdac_regmap_add_vendor_verb);
4195e56bceaSTakashi Iwai
4204d75faa0STakashi Iwai /*
4214d75faa0STakashi Iwai * helper functions
4224d75faa0STakashi Iwai */
4234d75faa0STakashi Iwai
4244d75faa0STakashi Iwai /* write a pseudo-register value (w/o power sequence) */
reg_raw_write(struct hdac_device * codec,unsigned int reg,unsigned int val)4254d75faa0STakashi Iwai static int reg_raw_write(struct hdac_device *codec, unsigned int reg,
4264d75faa0STakashi Iwai unsigned int val)
4274d75faa0STakashi Iwai {
4281a462be5STakashi Iwai int err;
4291a462be5STakashi Iwai
4301a462be5STakashi Iwai mutex_lock(&codec->regmap_lock);
4314d75faa0STakashi Iwai if (!codec->regmap)
4321a462be5STakashi Iwai err = hda_reg_write(codec, reg, val);
4334d75faa0STakashi Iwai else
4341a462be5STakashi Iwai err = regmap_write(codec->regmap, reg, val);
4351a462be5STakashi Iwai mutex_unlock(&codec->regmap_lock);
4361a462be5STakashi Iwai return err;
4374d75faa0STakashi Iwai }
4384d75faa0STakashi Iwai
4391a462be5STakashi Iwai /* a helper macro to call @func_call; retry with power-up if failed */
4401a462be5STakashi Iwai #define CALL_RAW_FUNC(codec, func_call) \
4411a462be5STakashi Iwai ({ \
4421a462be5STakashi Iwai int _err = func_call; \
4431a462be5STakashi Iwai if (_err == -EAGAIN) { \
4441a462be5STakashi Iwai _err = snd_hdac_power_up_pm(codec); \
4451a462be5STakashi Iwai if (_err >= 0) \
4461a462be5STakashi Iwai _err = func_call; \
4471a462be5STakashi Iwai snd_hdac_power_down_pm(codec); \
4481a462be5STakashi Iwai } \
4491a462be5STakashi Iwai _err;})
4501a462be5STakashi Iwai
4514d75faa0STakashi Iwai /**
4524d75faa0STakashi Iwai * snd_hdac_regmap_write_raw - write a pseudo register with power mgmt
4534d75faa0STakashi Iwai * @codec: the codec object
4544d75faa0STakashi Iwai * @reg: pseudo register
4554d75faa0STakashi Iwai * @val: value to write
4564d75faa0STakashi Iwai *
4574d75faa0STakashi Iwai * Returns zero if successful or a negative error code.
4584d75faa0STakashi Iwai */
snd_hdac_regmap_write_raw(struct hdac_device * codec,unsigned int reg,unsigned int val)4594d75faa0STakashi Iwai int snd_hdac_regmap_write_raw(struct hdac_device *codec, unsigned int reg,
4604d75faa0STakashi Iwai unsigned int val)
4614d75faa0STakashi Iwai {
4621a462be5STakashi Iwai return CALL_RAW_FUNC(codec, reg_raw_write(codec, reg, val));
4634d75faa0STakashi Iwai }
4644d75faa0STakashi Iwai EXPORT_SYMBOL_GPL(snd_hdac_regmap_write_raw);
4654d75faa0STakashi Iwai
reg_raw_read(struct hdac_device * codec,unsigned int reg,unsigned int * val,bool uncached)4664d75faa0STakashi Iwai static int reg_raw_read(struct hdac_device *codec, unsigned int reg,
4673194ed49STakashi Iwai unsigned int *val, bool uncached)
4684d75faa0STakashi Iwai {
4691a462be5STakashi Iwai int err;
4701a462be5STakashi Iwai
4711a462be5STakashi Iwai mutex_lock(&codec->regmap_lock);
4723194ed49STakashi Iwai if (uncached || !codec->regmap)
4731a462be5STakashi Iwai err = hda_reg_read(codec, reg, val);
4744d75faa0STakashi Iwai else
4751a462be5STakashi Iwai err = regmap_read(codec->regmap, reg, val);
4761a462be5STakashi Iwai mutex_unlock(&codec->regmap_lock);
4771a462be5STakashi Iwai return err;
4784d75faa0STakashi Iwai }
4794d75faa0STakashi Iwai
__snd_hdac_regmap_read_raw(struct hdac_device * codec,unsigned int reg,unsigned int * val,bool uncached)4803194ed49STakashi Iwai static int __snd_hdac_regmap_read_raw(struct hdac_device *codec,
4813194ed49STakashi Iwai unsigned int reg, unsigned int *val,
4823194ed49STakashi Iwai bool uncached)
4833194ed49STakashi Iwai {
4841a462be5STakashi Iwai return CALL_RAW_FUNC(codec, reg_raw_read(codec, reg, val, uncached));
4853194ed49STakashi Iwai }
4863194ed49STakashi Iwai
4874d75faa0STakashi Iwai /**
4884d75faa0STakashi Iwai * snd_hdac_regmap_read_raw - read a pseudo register with power mgmt
4894d75faa0STakashi Iwai * @codec: the codec object
4904d75faa0STakashi Iwai * @reg: pseudo register
4914d75faa0STakashi Iwai * @val: pointer to store the read value
4924d75faa0STakashi Iwai *
4934d75faa0STakashi Iwai * Returns zero if successful or a negative error code.
4944d75faa0STakashi Iwai */
snd_hdac_regmap_read_raw(struct hdac_device * codec,unsigned int reg,unsigned int * val)4954d75faa0STakashi Iwai int snd_hdac_regmap_read_raw(struct hdac_device *codec, unsigned int reg,
4964d75faa0STakashi Iwai unsigned int *val)
4974d75faa0STakashi Iwai {
4983194ed49STakashi Iwai return __snd_hdac_regmap_read_raw(codec, reg, val, false);
4994d75faa0STakashi Iwai }
5004d75faa0STakashi Iwai EXPORT_SYMBOL_GPL(snd_hdac_regmap_read_raw);
5014d75faa0STakashi Iwai
5023194ed49STakashi Iwai /* Works like snd_hdac_regmap_read_raw(), but this doesn't read from the
5033194ed49STakashi Iwai * cache but always via hda verbs.
5043194ed49STakashi Iwai */
snd_hdac_regmap_read_raw_uncached(struct hdac_device * codec,unsigned int reg,unsigned int * val)5053194ed49STakashi Iwai int snd_hdac_regmap_read_raw_uncached(struct hdac_device *codec,
5063194ed49STakashi Iwai unsigned int reg, unsigned int *val)
5073194ed49STakashi Iwai {
5083194ed49STakashi Iwai return __snd_hdac_regmap_read_raw(codec, reg, val, true);
5093194ed49STakashi Iwai }
5103194ed49STakashi Iwai
reg_raw_update(struct hdac_device * codec,unsigned int reg,unsigned int mask,unsigned int val)5111a462be5STakashi Iwai static int reg_raw_update(struct hdac_device *codec, unsigned int reg,
5121a462be5STakashi Iwai unsigned int mask, unsigned int val)
5131a462be5STakashi Iwai {
5141a462be5STakashi Iwai unsigned int orig;
5151a462be5STakashi Iwai bool change;
5161a462be5STakashi Iwai int err;
5171a462be5STakashi Iwai
5181a462be5STakashi Iwai mutex_lock(&codec->regmap_lock);
5191a462be5STakashi Iwai if (codec->regmap) {
5201a462be5STakashi Iwai err = regmap_update_bits_check(codec->regmap, reg, mask, val,
5211a462be5STakashi Iwai &change);
5221a462be5STakashi Iwai if (!err)
5231a462be5STakashi Iwai err = change ? 1 : 0;
5241a462be5STakashi Iwai } else {
5251a462be5STakashi Iwai err = hda_reg_read(codec, reg, &orig);
5261a462be5STakashi Iwai if (!err) {
5271a462be5STakashi Iwai val &= mask;
5281a462be5STakashi Iwai val |= orig & ~mask;
5291a462be5STakashi Iwai if (val != orig) {
5301a462be5STakashi Iwai err = hda_reg_write(codec, reg, val);
5311a462be5STakashi Iwai if (!err)
5321a462be5STakashi Iwai err = 1;
5331a462be5STakashi Iwai }
5341a462be5STakashi Iwai }
5351a462be5STakashi Iwai }
5361a462be5STakashi Iwai mutex_unlock(&codec->regmap_lock);
5371a462be5STakashi Iwai return err;
5381a462be5STakashi Iwai }
5391a462be5STakashi Iwai
5404d75faa0STakashi Iwai /**
5414d75faa0STakashi Iwai * snd_hdac_regmap_update_raw - update a pseudo register with power mgmt
5424d75faa0STakashi Iwai * @codec: the codec object
5434d75faa0STakashi Iwai * @reg: pseudo register
5441a0986c1STakashi Iwai * @mask: bit mask to update
5454d75faa0STakashi Iwai * @val: value to update
5464d75faa0STakashi Iwai *
5474d75faa0STakashi Iwai * Returns zero if successful or a negative error code.
5484d75faa0STakashi Iwai */
snd_hdac_regmap_update_raw(struct hdac_device * codec,unsigned int reg,unsigned int mask,unsigned int val)5494d75faa0STakashi Iwai int snd_hdac_regmap_update_raw(struct hdac_device *codec, unsigned int reg,
5504d75faa0STakashi Iwai unsigned int mask, unsigned int val)
5514d75faa0STakashi Iwai {
5521a462be5STakashi Iwai return CALL_RAW_FUNC(codec, reg_raw_update(codec, reg, mask, val));
5531a462be5STakashi Iwai }
5541a462be5STakashi Iwai EXPORT_SYMBOL_GPL(snd_hdac_regmap_update_raw);
5551a462be5STakashi Iwai
reg_raw_update_once(struct hdac_device * codec,unsigned int reg,unsigned int mask,unsigned int val)5561a462be5STakashi Iwai static int reg_raw_update_once(struct hdac_device *codec, unsigned int reg,
5571a462be5STakashi Iwai unsigned int mask, unsigned int val)
5581a462be5STakashi Iwai {
559*99aae705SMark Brown int err = 0;
5604d75faa0STakashi Iwai
5611a462be5STakashi Iwai if (!codec->regmap)
5621a462be5STakashi Iwai return reg_raw_update(codec, reg, mask, val);
5631a462be5STakashi Iwai
5641a462be5STakashi Iwai mutex_lock(&codec->regmap_lock);
565*99aae705SMark Brown /* Discard any updates to already initialised registers. */
566*99aae705SMark Brown if (!regcache_reg_cached(codec->regmap, reg))
5671a462be5STakashi Iwai err = regmap_update_bits(codec->regmap, reg, mask, val);
5681a462be5STakashi Iwai mutex_unlock(&codec->regmap_lock);
5694d75faa0STakashi Iwai return err;
5704d75faa0STakashi Iwai }
5711a462be5STakashi Iwai
5721a462be5STakashi Iwai /**
5731a462be5STakashi Iwai * snd_hdac_regmap_update_raw_once - initialize the register value only once
5741a462be5STakashi Iwai * @codec: the codec object
5751a462be5STakashi Iwai * @reg: pseudo register
5761a462be5STakashi Iwai * @mask: bit mask to update
5771a462be5STakashi Iwai * @val: value to update
5781a462be5STakashi Iwai *
5791a462be5STakashi Iwai * Performs the update of the register bits only once when the register
5801a462be5STakashi Iwai * hasn't been initialized yet. Used in HD-audio legacy driver.
5811a462be5STakashi Iwai * Returns zero if successful or a negative error code
5821a462be5STakashi Iwai */
snd_hdac_regmap_update_raw_once(struct hdac_device * codec,unsigned int reg,unsigned int mask,unsigned int val)5831a462be5STakashi Iwai int snd_hdac_regmap_update_raw_once(struct hdac_device *codec, unsigned int reg,
5841a462be5STakashi Iwai unsigned int mask, unsigned int val)
5851a462be5STakashi Iwai {
5861a462be5STakashi Iwai return CALL_RAW_FUNC(codec, reg_raw_update_once(codec, reg, mask, val));
5871a462be5STakashi Iwai }
5881a462be5STakashi Iwai EXPORT_SYMBOL_GPL(snd_hdac_regmap_update_raw_once);
5891a462be5STakashi Iwai
5901a462be5STakashi Iwai /**
5911a462be5STakashi Iwai * snd_hdac_regmap_sync - sync out the cached values for PM resume
5921a462be5STakashi Iwai * @codec: the codec object
5931a462be5STakashi Iwai */
snd_hdac_regmap_sync(struct hdac_device * codec)5941a462be5STakashi Iwai void snd_hdac_regmap_sync(struct hdac_device *codec)
5951a462be5STakashi Iwai {
5961a462be5STakashi Iwai mutex_lock(&codec->regmap_lock);
5971f4a08feSTuo Li if (codec->regmap)
5981a462be5STakashi Iwai regcache_sync(codec->regmap);
5991a462be5STakashi Iwai mutex_unlock(&codec->regmap_lock);
6001a462be5STakashi Iwai }
6011a462be5STakashi Iwai EXPORT_SYMBOL_GPL(snd_hdac_regmap_sync);
602