cachepc-linux

Fork of AMDESE/linux with modifications for CachePC side-channel attack
git clone https://git.sinitax.com/sinitax/cachepc-linux
Log | Files | Refs | README | LICENSE | sfeed.txt

hdac_regmap.c (15565B)


      1// SPDX-License-Identifier: GPL-2.0-only
      2/*
      3 * Regmap support for HD-audio verbs
      4 *
      5 * A virtual register is translated to one or more hda verbs for write,
      6 * vice versa for read.
      7 *
      8 * A few limitations:
      9 * - Provided for not all verbs but only subset standard non-volatile verbs.
     10 * - For reading, only AC_VERB_GET_* variants can be used.
     11 * - For writing, mapped to the *corresponding* AC_VERB_SET_* variants,
     12 *   so can't handle asymmetric verbs for read and write
     13 */
     14
     15#include <linux/slab.h>
     16#include <linux/device.h>
     17#include <linux/regmap.h>
     18#include <linux/export.h>
     19#include <linux/pm.h>
     20#include <linux/pm_runtime.h>
     21#include <sound/core.h>
     22#include <sound/hdaudio.h>
     23#include <sound/hda_regmap.h>
     24#include "local.h"
     25
     26static int codec_pm_lock(struct hdac_device *codec)
     27{
     28	return snd_hdac_keep_power_up(codec);
     29}
     30
     31static void codec_pm_unlock(struct hdac_device *codec, int lock)
     32{
     33	if (lock == 1)
     34		snd_hdac_power_down_pm(codec);
     35}
     36
     37#define get_verb(reg)	(((reg) >> 8) & 0xfff)
     38
     39static bool hda_volatile_reg(struct device *dev, unsigned int reg)
     40{
     41	struct hdac_device *codec = dev_to_hdac_dev(dev);
     42	unsigned int verb = get_verb(reg);
     43
     44	switch (verb) {
     45	case AC_VERB_GET_PROC_COEF:
     46		return !codec->cache_coef;
     47	case AC_VERB_GET_COEF_INDEX:
     48	case AC_VERB_GET_PROC_STATE:
     49	case AC_VERB_GET_POWER_STATE:
     50	case AC_VERB_GET_PIN_SENSE:
     51	case AC_VERB_GET_HDMI_DIP_SIZE:
     52	case AC_VERB_GET_HDMI_ELDD:
     53	case AC_VERB_GET_HDMI_DIP_INDEX:
     54	case AC_VERB_GET_HDMI_DIP_DATA:
     55	case AC_VERB_GET_HDMI_DIP_XMIT:
     56	case AC_VERB_GET_HDMI_CP_CTRL:
     57	case AC_VERB_GET_HDMI_CHAN_SLOT:
     58	case AC_VERB_GET_DEVICE_SEL:
     59	case AC_VERB_GET_DEVICE_LIST:	/* read-only volatile */
     60		return true;
     61	}
     62
     63	return false;
     64}
     65
     66static bool hda_writeable_reg(struct device *dev, unsigned int reg)
     67{
     68	struct hdac_device *codec = dev_to_hdac_dev(dev);
     69	unsigned int verb = get_verb(reg);
     70	const unsigned int *v;
     71	int i;
     72
     73	snd_array_for_each(&codec->vendor_verbs, i, v) {
     74		if (verb == *v)
     75			return true;
     76	}
     77
     78	if (codec->caps_overwriting)
     79		return true;
     80
     81	switch (verb & 0xf00) {
     82	case AC_VERB_GET_STREAM_FORMAT:
     83	case AC_VERB_GET_AMP_GAIN_MUTE:
     84		return true;
     85	case AC_VERB_GET_PROC_COEF:
     86		return codec->cache_coef;
     87	case 0xf00:
     88		break;
     89	default:
     90		return false;
     91	}
     92
     93	switch (verb) {
     94	case AC_VERB_GET_CONNECT_SEL:
     95	case AC_VERB_GET_SDI_SELECT:
     96	case AC_VERB_GET_PIN_WIDGET_CONTROL:
     97	case AC_VERB_GET_UNSOLICITED_RESPONSE: /* only as SET_UNSOLICITED_ENABLE */
     98	case AC_VERB_GET_BEEP_CONTROL:
     99	case AC_VERB_GET_EAPD_BTLENABLE:
    100	case AC_VERB_GET_DIGI_CONVERT_1:
    101	case AC_VERB_GET_DIGI_CONVERT_2: /* only for beep control */
    102	case AC_VERB_GET_VOLUME_KNOB_CONTROL:
    103	case AC_VERB_GET_GPIO_MASK:
    104	case AC_VERB_GET_GPIO_DIRECTION:
    105	case AC_VERB_GET_GPIO_DATA: /* not for volatile read */
    106	case AC_VERB_GET_GPIO_WAKE_MASK:
    107	case AC_VERB_GET_GPIO_UNSOLICITED_RSP_MASK:
    108	case AC_VERB_GET_GPIO_STICKY_MASK:
    109		return true;
    110	}
    111
    112	return false;
    113}
    114
    115static bool hda_readable_reg(struct device *dev, unsigned int reg)
    116{
    117	struct hdac_device *codec = dev_to_hdac_dev(dev);
    118	unsigned int verb = get_verb(reg);
    119
    120	if (codec->caps_overwriting)
    121		return true;
    122
    123	switch (verb) {
    124	case AC_VERB_PARAMETERS:
    125	case AC_VERB_GET_CONNECT_LIST:
    126	case AC_VERB_GET_SUBSYSTEM_ID:
    127		return true;
    128	/* below are basically writable, but disabled for reducing unnecessary
    129	 * writes at sync
    130	 */
    131	case AC_VERB_GET_CONFIG_DEFAULT: /* usually just read */
    132	case AC_VERB_GET_CONV: /* managed in PCM code */
    133	case AC_VERB_GET_CVT_CHAN_COUNT: /* managed in HDMI CA code */
    134		return true;
    135	}
    136
    137	return hda_writeable_reg(dev, reg);
    138}
    139
    140/*
    141 * Stereo amp pseudo register:
    142 * for making easier to handle the stereo volume control, we provide a
    143 * fake register to deal both left and right channels by a single
    144 * (pseudo) register access.  A verb consisting of SET_AMP_GAIN with
    145 * *both* SET_LEFT and SET_RIGHT bits takes a 16bit value, the lower 8bit
    146 * for the left and the upper 8bit for the right channel.
    147 */
    148static bool is_stereo_amp_verb(unsigned int reg)
    149{
    150	if (((reg >> 8) & 0x700) != AC_VERB_SET_AMP_GAIN_MUTE)
    151		return false;
    152	return (reg & (AC_AMP_SET_LEFT | AC_AMP_SET_RIGHT)) ==
    153		(AC_AMP_SET_LEFT | AC_AMP_SET_RIGHT);
    154}
    155
    156/* read a pseudo stereo amp register (16bit left+right) */
    157static int hda_reg_read_stereo_amp(struct hdac_device *codec,
    158				   unsigned int reg, unsigned int *val)
    159{
    160	unsigned int left, right;
    161	int err;
    162
    163	reg &= ~(AC_AMP_SET_LEFT | AC_AMP_SET_RIGHT);
    164	err = snd_hdac_exec_verb(codec, reg | AC_AMP_GET_LEFT, 0, &left);
    165	if (err < 0)
    166		return err;
    167	err = snd_hdac_exec_verb(codec, reg | AC_AMP_GET_RIGHT, 0, &right);
    168	if (err < 0)
    169		return err;
    170	*val = left | (right << 8);
    171	return 0;
    172}
    173
    174/* write a pseudo stereo amp register (16bit left+right) */
    175static int hda_reg_write_stereo_amp(struct hdac_device *codec,
    176				    unsigned int reg, unsigned int val)
    177{
    178	int err;
    179	unsigned int verb, left, right;
    180
    181	verb = AC_VERB_SET_AMP_GAIN_MUTE << 8;
    182	if (reg & AC_AMP_GET_OUTPUT)
    183		verb |= AC_AMP_SET_OUTPUT;
    184	else
    185		verb |= AC_AMP_SET_INPUT | ((reg & 0xf) << 8);
    186	reg = (reg & ~0xfffff) | verb;
    187
    188	left = val & 0xff;
    189	right = (val >> 8) & 0xff;
    190	if (left == right) {
    191		reg |= AC_AMP_SET_LEFT | AC_AMP_SET_RIGHT;
    192		return snd_hdac_exec_verb(codec, reg | left, 0, NULL);
    193	}
    194
    195	err = snd_hdac_exec_verb(codec, reg | AC_AMP_SET_LEFT | left, 0, NULL);
    196	if (err < 0)
    197		return err;
    198	err = snd_hdac_exec_verb(codec, reg | AC_AMP_SET_RIGHT | right, 0, NULL);
    199	if (err < 0)
    200		return err;
    201	return 0;
    202}
    203
    204/* read a pseudo coef register (16bit) */
    205static int hda_reg_read_coef(struct hdac_device *codec, unsigned int reg,
    206			     unsigned int *val)
    207{
    208	unsigned int verb;
    209	int err;
    210
    211	if (!codec->cache_coef)
    212		return -EINVAL;
    213	/* LSB 8bit = coef index */
    214	verb = (reg & ~0xfff00) | (AC_VERB_SET_COEF_INDEX << 8);
    215	err = snd_hdac_exec_verb(codec, verb, 0, NULL);
    216	if (err < 0)
    217		return err;
    218	verb = (reg & ~0xfffff) | (AC_VERB_GET_COEF_INDEX << 8);
    219	return snd_hdac_exec_verb(codec, verb, 0, val);
    220}
    221
    222/* write a pseudo coef register (16bit) */
    223static int hda_reg_write_coef(struct hdac_device *codec, unsigned int reg,
    224			      unsigned int val)
    225{
    226	unsigned int verb;
    227	int err;
    228
    229	if (!codec->cache_coef)
    230		return -EINVAL;
    231	/* LSB 8bit = coef index */
    232	verb = (reg & ~0xfff00) | (AC_VERB_SET_COEF_INDEX << 8);
    233	err = snd_hdac_exec_verb(codec, verb, 0, NULL);
    234	if (err < 0)
    235		return err;
    236	verb = (reg & ~0xfffff) | (AC_VERB_GET_COEF_INDEX << 8) |
    237		(val & 0xffff);
    238	return snd_hdac_exec_verb(codec, verb, 0, NULL);
    239}
    240
    241static int hda_reg_read(void *context, unsigned int reg, unsigned int *val)
    242{
    243	struct hdac_device *codec = context;
    244	int verb = get_verb(reg);
    245	int err;
    246	int pm_lock = 0;
    247
    248	if (verb != AC_VERB_GET_POWER_STATE) {
    249		pm_lock = codec_pm_lock(codec);
    250		if (pm_lock < 0)
    251			return -EAGAIN;
    252	}
    253	reg |= (codec->addr << 28);
    254	if (is_stereo_amp_verb(reg)) {
    255		err = hda_reg_read_stereo_amp(codec, reg, val);
    256		goto out;
    257	}
    258	if (verb == AC_VERB_GET_PROC_COEF) {
    259		err = hda_reg_read_coef(codec, reg, val);
    260		goto out;
    261	}
    262	if ((verb & 0x700) == AC_VERB_SET_AMP_GAIN_MUTE)
    263		reg &= ~AC_AMP_FAKE_MUTE;
    264
    265	err = snd_hdac_exec_verb(codec, reg, 0, val);
    266	if (err < 0)
    267		goto out;
    268	/* special handling for asymmetric reads */
    269	if (verb == AC_VERB_GET_POWER_STATE) {
    270		if (*val & AC_PWRST_ERROR)
    271			*val = -1;
    272		else /* take only the actual state */
    273			*val = (*val >> 4) & 0x0f;
    274	}
    275 out:
    276	codec_pm_unlock(codec, pm_lock);
    277	return err;
    278}
    279
    280static int hda_reg_write(void *context, unsigned int reg, unsigned int val)
    281{
    282	struct hdac_device *codec = context;
    283	unsigned int verb;
    284	int i, bytes, err;
    285	int pm_lock = 0;
    286
    287	if (codec->caps_overwriting)
    288		return 0;
    289
    290	reg &= ~0x00080000U; /* drop GET bit */
    291	reg |= (codec->addr << 28);
    292	verb = get_verb(reg);
    293
    294	if (verb != AC_VERB_SET_POWER_STATE) {
    295		pm_lock = codec_pm_lock(codec);
    296		if (pm_lock < 0)
    297			return codec->lazy_cache ? 0 : -EAGAIN;
    298	}
    299
    300	if (is_stereo_amp_verb(reg)) {
    301		err = hda_reg_write_stereo_amp(codec, reg, val);
    302		goto out;
    303	}
    304
    305	if (verb == AC_VERB_SET_PROC_COEF) {
    306		err = hda_reg_write_coef(codec, reg, val);
    307		goto out;
    308	}
    309
    310	switch (verb & 0xf00) {
    311	case AC_VERB_SET_AMP_GAIN_MUTE:
    312		if ((reg & AC_AMP_FAKE_MUTE) && (val & AC_AMP_MUTE))
    313			val = 0;
    314		verb = AC_VERB_SET_AMP_GAIN_MUTE;
    315		if (reg & AC_AMP_GET_LEFT)
    316			verb |= AC_AMP_SET_LEFT >> 8;
    317		else
    318			verb |= AC_AMP_SET_RIGHT >> 8;
    319		if (reg & AC_AMP_GET_OUTPUT) {
    320			verb |= AC_AMP_SET_OUTPUT >> 8;
    321		} else {
    322			verb |= AC_AMP_SET_INPUT >> 8;
    323			verb |= reg & 0xf;
    324		}
    325		break;
    326	}
    327
    328	switch (verb) {
    329	case AC_VERB_SET_DIGI_CONVERT_1:
    330		bytes = 2;
    331		break;
    332	case AC_VERB_SET_CONFIG_DEFAULT_BYTES_0:
    333		bytes = 4;
    334		break;
    335	default:
    336		bytes = 1;
    337		break;
    338	}
    339
    340	for (i = 0; i < bytes; i++) {
    341		reg &= ~0xfffff;
    342		reg |= (verb + i) << 8 | ((val >> (8 * i)) & 0xff);
    343		err = snd_hdac_exec_verb(codec, reg, 0, NULL);
    344		if (err < 0)
    345			goto out;
    346	}
    347
    348 out:
    349	codec_pm_unlock(codec, pm_lock);
    350	return err;
    351}
    352
    353static const struct regmap_config hda_regmap_cfg = {
    354	.name = "hdaudio",
    355	.reg_bits = 32,
    356	.val_bits = 32,
    357	.max_register = 0xfffffff,
    358	.writeable_reg = hda_writeable_reg,
    359	.readable_reg = hda_readable_reg,
    360	.volatile_reg = hda_volatile_reg,
    361	.cache_type = REGCACHE_RBTREE,
    362	.reg_read = hda_reg_read,
    363	.reg_write = hda_reg_write,
    364	.use_single_read = true,
    365	.use_single_write = true,
    366	.disable_locking = true,
    367};
    368
    369/**
    370 * snd_hdac_regmap_init - Initialize regmap for HDA register accesses
    371 * @codec: the codec object
    372 *
    373 * Returns zero for success or a negative error code.
    374 */
    375int snd_hdac_regmap_init(struct hdac_device *codec)
    376{
    377	struct regmap *regmap;
    378
    379	regmap = regmap_init(&codec->dev, NULL, codec, &hda_regmap_cfg);
    380	if (IS_ERR(regmap))
    381		return PTR_ERR(regmap);
    382	codec->regmap = regmap;
    383	snd_array_init(&codec->vendor_verbs, sizeof(unsigned int), 8);
    384	return 0;
    385}
    386EXPORT_SYMBOL_GPL(snd_hdac_regmap_init);
    387
    388/**
    389 * snd_hdac_regmap_exit - Release the regmap from HDA codec
    390 * @codec: the codec object
    391 */
    392void snd_hdac_regmap_exit(struct hdac_device *codec)
    393{
    394	if (codec->regmap) {
    395		regmap_exit(codec->regmap);
    396		codec->regmap = NULL;
    397		snd_array_free(&codec->vendor_verbs);
    398	}
    399}
    400EXPORT_SYMBOL_GPL(snd_hdac_regmap_exit);
    401
    402/**
    403 * snd_hdac_regmap_add_vendor_verb - add a vendor-specific verb to regmap
    404 * @codec: the codec object
    405 * @verb: verb to allow accessing via regmap
    406 *
    407 * Returns zero for success or a negative error code.
    408 */
    409int snd_hdac_regmap_add_vendor_verb(struct hdac_device *codec,
    410				    unsigned int verb)
    411{
    412	unsigned int *p = snd_array_new(&codec->vendor_verbs);
    413
    414	if (!p)
    415		return -ENOMEM;
    416	*p = verb | 0x800; /* set GET bit */
    417	return 0;
    418}
    419EXPORT_SYMBOL_GPL(snd_hdac_regmap_add_vendor_verb);
    420
    421/*
    422 * helper functions
    423 */
    424
    425/* write a pseudo-register value (w/o power sequence) */
    426static int reg_raw_write(struct hdac_device *codec, unsigned int reg,
    427			 unsigned int val)
    428{
    429	int err;
    430
    431	mutex_lock(&codec->regmap_lock);
    432	if (!codec->regmap)
    433		err = hda_reg_write(codec, reg, val);
    434	else
    435		err = regmap_write(codec->regmap, reg, val);
    436	mutex_unlock(&codec->regmap_lock);
    437	return err;
    438}
    439
    440/* a helper macro to call @func_call; retry with power-up if failed */
    441#define CALL_RAW_FUNC(codec, func_call)				\
    442	({							\
    443		int _err = func_call;				\
    444		if (_err == -EAGAIN) {				\
    445			_err = snd_hdac_power_up_pm(codec);	\
    446			if (_err >= 0)				\
    447				_err = func_call;		\
    448			snd_hdac_power_down_pm(codec);		\
    449		}						\
    450		_err;})
    451
    452/**
    453 * snd_hdac_regmap_write_raw - write a pseudo register with power mgmt
    454 * @codec: the codec object
    455 * @reg: pseudo register
    456 * @val: value to write
    457 *
    458 * Returns zero if successful or a negative error code.
    459 */
    460int snd_hdac_regmap_write_raw(struct hdac_device *codec, unsigned int reg,
    461			      unsigned int val)
    462{
    463	return CALL_RAW_FUNC(codec, reg_raw_write(codec, reg, val));
    464}
    465EXPORT_SYMBOL_GPL(snd_hdac_regmap_write_raw);
    466
    467static int reg_raw_read(struct hdac_device *codec, unsigned int reg,
    468			unsigned int *val, bool uncached)
    469{
    470	int err;
    471
    472	mutex_lock(&codec->regmap_lock);
    473	if (uncached || !codec->regmap)
    474		err = hda_reg_read(codec, reg, val);
    475	else
    476		err = regmap_read(codec->regmap, reg, val);
    477	mutex_unlock(&codec->regmap_lock);
    478	return err;
    479}
    480
    481static int __snd_hdac_regmap_read_raw(struct hdac_device *codec,
    482				      unsigned int reg, unsigned int *val,
    483				      bool uncached)
    484{
    485	return CALL_RAW_FUNC(codec, reg_raw_read(codec, reg, val, uncached));
    486}
    487
    488/**
    489 * snd_hdac_regmap_read_raw - read a pseudo register with power mgmt
    490 * @codec: the codec object
    491 * @reg: pseudo register
    492 * @val: pointer to store the read value
    493 *
    494 * Returns zero if successful or a negative error code.
    495 */
    496int snd_hdac_regmap_read_raw(struct hdac_device *codec, unsigned int reg,
    497			     unsigned int *val)
    498{
    499	return __snd_hdac_regmap_read_raw(codec, reg, val, false);
    500}
    501EXPORT_SYMBOL_GPL(snd_hdac_regmap_read_raw);
    502
    503/* Works like snd_hdac_regmap_read_raw(), but this doesn't read from the
    504 * cache but always via hda verbs.
    505 */
    506int snd_hdac_regmap_read_raw_uncached(struct hdac_device *codec,
    507				      unsigned int reg, unsigned int *val)
    508{
    509	return __snd_hdac_regmap_read_raw(codec, reg, val, true);
    510}
    511
    512static int reg_raw_update(struct hdac_device *codec, unsigned int reg,
    513			  unsigned int mask, unsigned int val)
    514{
    515	unsigned int orig;
    516	bool change;
    517	int err;
    518
    519	mutex_lock(&codec->regmap_lock);
    520	if (codec->regmap) {
    521		err = regmap_update_bits_check(codec->regmap, reg, mask, val,
    522					       &change);
    523		if (!err)
    524			err = change ? 1 : 0;
    525	} else {
    526		err = hda_reg_read(codec, reg, &orig);
    527		if (!err) {
    528			val &= mask;
    529			val |= orig & ~mask;
    530			if (val != orig) {
    531				err = hda_reg_write(codec, reg, val);
    532				if (!err)
    533					err = 1;
    534			}
    535		}
    536	}
    537	mutex_unlock(&codec->regmap_lock);
    538	return err;
    539}
    540
    541/**
    542 * snd_hdac_regmap_update_raw - update a pseudo register with power mgmt
    543 * @codec: the codec object
    544 * @reg: pseudo register
    545 * @mask: bit mask to update
    546 * @val: value to update
    547 *
    548 * Returns zero if successful or a negative error code.
    549 */
    550int snd_hdac_regmap_update_raw(struct hdac_device *codec, unsigned int reg,
    551			       unsigned int mask, unsigned int val)
    552{
    553	return CALL_RAW_FUNC(codec, reg_raw_update(codec, reg, mask, val));
    554}
    555EXPORT_SYMBOL_GPL(snd_hdac_regmap_update_raw);
    556
    557static int reg_raw_update_once(struct hdac_device *codec, unsigned int reg,
    558			       unsigned int mask, unsigned int val)
    559{
    560	unsigned int orig;
    561	int err;
    562
    563	if (!codec->regmap)
    564		return reg_raw_update(codec, reg, mask, val);
    565
    566	mutex_lock(&codec->regmap_lock);
    567	regcache_cache_only(codec->regmap, true);
    568	err = regmap_read(codec->regmap, reg, &orig);
    569	regcache_cache_only(codec->regmap, false);
    570	if (err < 0)
    571		err = regmap_update_bits(codec->regmap, reg, mask, val);
    572	mutex_unlock(&codec->regmap_lock);
    573	return err;
    574}
    575
    576/**
    577 * snd_hdac_regmap_update_raw_once - initialize the register value only once
    578 * @codec: the codec object
    579 * @reg: pseudo register
    580 * @mask: bit mask to update
    581 * @val: value to update
    582 *
    583 * Performs the update of the register bits only once when the register
    584 * hasn't been initialized yet.  Used in HD-audio legacy driver.
    585 * Returns zero if successful or a negative error code
    586 */
    587int snd_hdac_regmap_update_raw_once(struct hdac_device *codec, unsigned int reg,
    588				    unsigned int mask, unsigned int val)
    589{
    590	return CALL_RAW_FUNC(codec, reg_raw_update_once(codec, reg, mask, val));
    591}
    592EXPORT_SYMBOL_GPL(snd_hdac_regmap_update_raw_once);
    593
    594/**
    595 * snd_hdac_regmap_sync - sync out the cached values for PM resume
    596 * @codec: the codec object
    597 */
    598void snd_hdac_regmap_sync(struct hdac_device *codec)
    599{
    600	if (codec->regmap) {
    601		mutex_lock(&codec->regmap_lock);
    602		regcache_sync(codec->regmap);
    603		mutex_unlock(&codec->regmap_lock);
    604	}
    605}
    606EXPORT_SYMBOL_GPL(snd_hdac_regmap_sync);