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

xonar_lib.c (3289B)


      1// SPDX-License-Identifier: GPL-2.0-only
      2/*
      3 * helper functions for Asus Xonar cards
      4 *
      5 * Copyright (c) Clemens Ladisch <clemens@ladisch.de>
      6 */
      7
      8#include <linux/delay.h>
      9#include <sound/core.h>
     10#include <sound/control.h>
     11#include <sound/pcm.h>
     12#include <sound/pcm_params.h>
     13#include "xonar.h"
     14
     15
     16#define GPIO_CS53x1_M_MASK	0x000c
     17#define GPIO_CS53x1_M_SINGLE	0x0000
     18#define GPIO_CS53x1_M_DOUBLE	0x0004
     19#define GPIO_CS53x1_M_QUAD	0x0008
     20
     21
     22void xonar_enable_output(struct oxygen *chip)
     23{
     24	struct xonar_generic *data = chip->model_data;
     25
     26	oxygen_set_bits16(chip, OXYGEN_GPIO_CONTROL, data->output_enable_bit);
     27	msleep(data->anti_pop_delay);
     28	oxygen_set_bits16(chip, OXYGEN_GPIO_DATA, data->output_enable_bit);
     29}
     30
     31void xonar_disable_output(struct oxygen *chip)
     32{
     33	struct xonar_generic *data = chip->model_data;
     34
     35	oxygen_clear_bits16(chip, OXYGEN_GPIO_DATA, data->output_enable_bit);
     36}
     37
     38static void xonar_ext_power_gpio_changed(struct oxygen *chip)
     39{
     40	struct xonar_generic *data = chip->model_data;
     41	u8 has_power;
     42
     43	has_power = !!(oxygen_read8(chip, data->ext_power_reg)
     44		       & data->ext_power_bit);
     45	if (has_power != data->has_power) {
     46		data->has_power = has_power;
     47		if (has_power) {
     48			dev_notice(chip->card->dev, "power restored\n");
     49		} else {
     50			dev_crit(chip->card->dev,
     51				   "Hey! Don't unplug the power cable!\n");
     52			/* TODO: stop PCMs */
     53		}
     54	}
     55}
     56
     57void xonar_init_ext_power(struct oxygen *chip)
     58{
     59	struct xonar_generic *data = chip->model_data;
     60
     61	oxygen_set_bits8(chip, data->ext_power_int_reg,
     62			 data->ext_power_bit);
     63	chip->interrupt_mask |= OXYGEN_INT_GPIO;
     64	chip->model.gpio_changed = xonar_ext_power_gpio_changed;
     65	data->has_power = !!(oxygen_read8(chip, data->ext_power_reg)
     66			     & data->ext_power_bit);
     67}
     68
     69void xonar_init_cs53x1(struct oxygen *chip)
     70{
     71	oxygen_set_bits16(chip, OXYGEN_GPIO_CONTROL, GPIO_CS53x1_M_MASK);
     72	oxygen_write16_masked(chip, OXYGEN_GPIO_DATA,
     73			      GPIO_CS53x1_M_SINGLE, GPIO_CS53x1_M_MASK);
     74}
     75
     76void xonar_set_cs53x1_params(struct oxygen *chip,
     77			     struct snd_pcm_hw_params *params)
     78{
     79	unsigned int value;
     80
     81	if (params_rate(params) <= 54000)
     82		value = GPIO_CS53x1_M_SINGLE;
     83	else if (params_rate(params) <= 108000)
     84		value = GPIO_CS53x1_M_DOUBLE;
     85	else
     86		value = GPIO_CS53x1_M_QUAD;
     87	oxygen_write16_masked(chip, OXYGEN_GPIO_DATA,
     88			      value, GPIO_CS53x1_M_MASK);
     89}
     90
     91int xonar_gpio_bit_switch_get(struct snd_kcontrol *ctl,
     92			      struct snd_ctl_elem_value *value)
     93{
     94	struct oxygen *chip = ctl->private_data;
     95	u16 bit = ctl->private_value;
     96	bool invert = ctl->private_value & XONAR_GPIO_BIT_INVERT;
     97
     98	value->value.integer.value[0] =
     99		!!(oxygen_read16(chip, OXYGEN_GPIO_DATA) & bit) ^ invert;
    100	return 0;
    101}
    102
    103int xonar_gpio_bit_switch_put(struct snd_kcontrol *ctl,
    104			      struct snd_ctl_elem_value *value)
    105{
    106	struct oxygen *chip = ctl->private_data;
    107	u16 bit = ctl->private_value;
    108	bool invert = ctl->private_value & XONAR_GPIO_BIT_INVERT;
    109	u16 old_bits, new_bits;
    110	int changed;
    111
    112	spin_lock_irq(&chip->reg_lock);
    113	old_bits = oxygen_read16(chip, OXYGEN_GPIO_DATA);
    114	if (!!value->value.integer.value[0] ^ invert)
    115		new_bits = old_bits | bit;
    116	else
    117		new_bits = old_bits & ~bit;
    118	changed = new_bits != old_bits;
    119	if (changed)
    120		oxygen_write16(chip, OXYGEN_GPIO_DATA, new_bits);
    121	spin_unlock_irq(&chip->reg_lock);
    122	return changed;
    123}