^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1) // SPDX-License-Identifier: GPL-2.0-only
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3) * Apple Onboard Audio driver for Onyx codec
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5) * Copyright 2006 Johannes Berg <johannes@sipsolutions.net>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7) * This is a driver for the pcm3052 codec chip (codenamed Onyx)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8) * that is present in newer Apple hardware (with digital output).
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10) * The Onyx codec has the following connections (listed by the bit
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11) * to be used in aoa_codec.connected):
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12) * 0: analog output
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13) * 1: digital output
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14) * 2: line input
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 15) * 3: microphone input
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 16) * Note that even though I know of no machine that has for example
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 17) * the digital output connected but not the analog, I have handled
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 18) * all the different cases in the code so that this driver may serve
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 19) * as a good example of what to do.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 20) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 21) * NOTE: This driver assumes that there's at most one chip to be
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 22) * used with one alsa card, in form of creating all kinds
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 23) * of mixer elements without regard for their existence.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 24) * But snd-aoa assumes that there's at most one card, so
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 25) * this means you can only have one onyx on a system. This
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 26) * should probably be fixed by changing the assumption of
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 27) * having just a single card on a system, and making the
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 28) * 'card' pointer accessible to anyone who needs it instead
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 29) * of hiding it in the aoa_snd_* functions...
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 30) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 31) #include <linux/delay.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 32) #include <linux/module.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 33) #include <linux/slab.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 34) MODULE_AUTHOR("Johannes Berg <johannes@sipsolutions.net>");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 35) MODULE_LICENSE("GPL");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 36) MODULE_DESCRIPTION("pcm3052 (onyx) codec driver for snd-aoa");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 37)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 38) #include "onyx.h"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 39) #include "../aoa.h"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 40) #include "../soundbus/soundbus.h"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 41)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 42)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 43) #define PFX "snd-aoa-codec-onyx: "
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 44)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 45) struct onyx {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 46) /* cache registers 65 to 80, they are write-only! */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 47) u8 cache[16];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 48) struct i2c_client *i2c;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 49) struct aoa_codec codec;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 50) u32 initialised:1,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 51) spdif_locked:1,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 52) analog_locked:1,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 53) original_mute:2;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 54) int open_count;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 55) struct codec_info *codec_info;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 56)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 57) /* mutex serializes concurrent access to the device
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 58) * and this structure.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 59) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 60) struct mutex mutex;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 61) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 62) #define codec_to_onyx(c) container_of(c, struct onyx, codec)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 63)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 64) /* both return 0 if all ok, else on error */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 65) static int onyx_read_register(struct onyx *onyx, u8 reg, u8 *value)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 66) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 67) s32 v;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 68)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 69) if (reg != ONYX_REG_CONTROL) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 70) *value = onyx->cache[reg-FIRSTREGISTER];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 71) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 72) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 73) v = i2c_smbus_read_byte_data(onyx->i2c, reg);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 74) if (v < 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 75) *value = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 76) return -1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 77) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 78) *value = (u8)v;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 79) onyx->cache[ONYX_REG_CONTROL-FIRSTREGISTER] = *value;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 80) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 81) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 82)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 83) static int onyx_write_register(struct onyx *onyx, u8 reg, u8 value)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 84) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 85) int result;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 86)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 87) result = i2c_smbus_write_byte_data(onyx->i2c, reg, value);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 88) if (!result)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 89) onyx->cache[reg-FIRSTREGISTER] = value;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 90) return result;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 91) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 92)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 93) /* alsa stuff */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 94)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 95) static int onyx_dev_register(struct snd_device *dev)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 96) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 97) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 98) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 99)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 100) static const struct snd_device_ops ops = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 101) .dev_register = onyx_dev_register,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 102) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 103)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 104) /* this is necessary because most alsa mixer programs
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 105) * can't properly handle the negative range */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 106) #define VOLUME_RANGE_SHIFT 128
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 107)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 108) static int onyx_snd_vol_info(struct snd_kcontrol *kcontrol,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 109) struct snd_ctl_elem_info *uinfo)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 110) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 111) uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 112) uinfo->count = 2;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 113) uinfo->value.integer.min = -128 + VOLUME_RANGE_SHIFT;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 114) uinfo->value.integer.max = -1 + VOLUME_RANGE_SHIFT;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 115) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 116) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 117)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 118) static int onyx_snd_vol_get(struct snd_kcontrol *kcontrol,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 119) struct snd_ctl_elem_value *ucontrol)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 120) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 121) struct onyx *onyx = snd_kcontrol_chip(kcontrol);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 122) s8 l, r;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 123)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 124) mutex_lock(&onyx->mutex);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 125) onyx_read_register(onyx, ONYX_REG_DAC_ATTEN_LEFT, &l);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 126) onyx_read_register(onyx, ONYX_REG_DAC_ATTEN_RIGHT, &r);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 127) mutex_unlock(&onyx->mutex);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 128)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 129) ucontrol->value.integer.value[0] = l + VOLUME_RANGE_SHIFT;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 130) ucontrol->value.integer.value[1] = r + VOLUME_RANGE_SHIFT;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 131)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 132) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 133) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 134)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 135) static int onyx_snd_vol_put(struct snd_kcontrol *kcontrol,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 136) struct snd_ctl_elem_value *ucontrol)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 137) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 138) struct onyx *onyx = snd_kcontrol_chip(kcontrol);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 139) s8 l, r;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 140)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 141) if (ucontrol->value.integer.value[0] < -128 + VOLUME_RANGE_SHIFT ||
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 142) ucontrol->value.integer.value[0] > -1 + VOLUME_RANGE_SHIFT)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 143) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 144) if (ucontrol->value.integer.value[1] < -128 + VOLUME_RANGE_SHIFT ||
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 145) ucontrol->value.integer.value[1] > -1 + VOLUME_RANGE_SHIFT)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 146) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 147)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 148) mutex_lock(&onyx->mutex);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 149) onyx_read_register(onyx, ONYX_REG_DAC_ATTEN_LEFT, &l);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 150) onyx_read_register(onyx, ONYX_REG_DAC_ATTEN_RIGHT, &r);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 151)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 152) if (l + VOLUME_RANGE_SHIFT == ucontrol->value.integer.value[0] &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 153) r + VOLUME_RANGE_SHIFT == ucontrol->value.integer.value[1]) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 154) mutex_unlock(&onyx->mutex);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 155) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 156) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 157)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 158) onyx_write_register(onyx, ONYX_REG_DAC_ATTEN_LEFT,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 159) ucontrol->value.integer.value[0]
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 160) - VOLUME_RANGE_SHIFT);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 161) onyx_write_register(onyx, ONYX_REG_DAC_ATTEN_RIGHT,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 162) ucontrol->value.integer.value[1]
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 163) - VOLUME_RANGE_SHIFT);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 164) mutex_unlock(&onyx->mutex);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 165)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 166) return 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 167) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 168)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 169) static const struct snd_kcontrol_new volume_control = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 170) .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 171) .name = "Master Playback Volume",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 172) .access = SNDRV_CTL_ELEM_ACCESS_READWRITE,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 173) .info = onyx_snd_vol_info,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 174) .get = onyx_snd_vol_get,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 175) .put = onyx_snd_vol_put,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 176) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 177)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 178) /* like above, this is necessary because a lot
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 179) * of alsa mixer programs don't handle ranges
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 180) * that don't start at 0 properly.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 181) * even alsamixer is one of them... */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 182) #define INPUTGAIN_RANGE_SHIFT (-3)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 183)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 184) static int onyx_snd_inputgain_info(struct snd_kcontrol *kcontrol,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 185) struct snd_ctl_elem_info *uinfo)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 186) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 187) uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 188) uinfo->count = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 189) uinfo->value.integer.min = 3 + INPUTGAIN_RANGE_SHIFT;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 190) uinfo->value.integer.max = 28 + INPUTGAIN_RANGE_SHIFT;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 191) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 192) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 193)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 194) static int onyx_snd_inputgain_get(struct snd_kcontrol *kcontrol,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 195) struct snd_ctl_elem_value *ucontrol)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 196) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 197) struct onyx *onyx = snd_kcontrol_chip(kcontrol);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 198) u8 ig;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 199)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 200) mutex_lock(&onyx->mutex);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 201) onyx_read_register(onyx, ONYX_REG_ADC_CONTROL, &ig);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 202) mutex_unlock(&onyx->mutex);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 203)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 204) ucontrol->value.integer.value[0] =
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 205) (ig & ONYX_ADC_PGA_GAIN_MASK) + INPUTGAIN_RANGE_SHIFT;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 206)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 207) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 208) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 209)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 210) static int onyx_snd_inputgain_put(struct snd_kcontrol *kcontrol,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 211) struct snd_ctl_elem_value *ucontrol)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 212) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 213) struct onyx *onyx = snd_kcontrol_chip(kcontrol);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 214) u8 v, n;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 215)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 216) if (ucontrol->value.integer.value[0] < 3 + INPUTGAIN_RANGE_SHIFT ||
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 217) ucontrol->value.integer.value[0] > 28 + INPUTGAIN_RANGE_SHIFT)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 218) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 219) mutex_lock(&onyx->mutex);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 220) onyx_read_register(onyx, ONYX_REG_ADC_CONTROL, &v);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 221) n = v;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 222) n &= ~ONYX_ADC_PGA_GAIN_MASK;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 223) n |= (ucontrol->value.integer.value[0] - INPUTGAIN_RANGE_SHIFT)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 224) & ONYX_ADC_PGA_GAIN_MASK;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 225) onyx_write_register(onyx, ONYX_REG_ADC_CONTROL, n);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 226) mutex_unlock(&onyx->mutex);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 227)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 228) return n != v;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 229) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 230)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 231) static const struct snd_kcontrol_new inputgain_control = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 232) .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 233) .name = "Master Capture Volume",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 234) .access = SNDRV_CTL_ELEM_ACCESS_READWRITE,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 235) .info = onyx_snd_inputgain_info,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 236) .get = onyx_snd_inputgain_get,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 237) .put = onyx_snd_inputgain_put,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 238) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 239)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 240) static int onyx_snd_capture_source_info(struct snd_kcontrol *kcontrol,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 241) struct snd_ctl_elem_info *uinfo)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 242) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 243) static const char * const texts[] = { "Line-In", "Microphone" };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 244)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 245) return snd_ctl_enum_info(uinfo, 1, 2, texts);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 246) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 247)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 248) static int onyx_snd_capture_source_get(struct snd_kcontrol *kcontrol,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 249) struct snd_ctl_elem_value *ucontrol)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 250) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 251) struct onyx *onyx = snd_kcontrol_chip(kcontrol);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 252) s8 v;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 253)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 254) mutex_lock(&onyx->mutex);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 255) onyx_read_register(onyx, ONYX_REG_ADC_CONTROL, &v);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 256) mutex_unlock(&onyx->mutex);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 257)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 258) ucontrol->value.enumerated.item[0] = !!(v&ONYX_ADC_INPUT_MIC);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 259)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 260) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 261) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 262)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 263) static void onyx_set_capture_source(struct onyx *onyx, int mic)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 264) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 265) s8 v;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 266)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 267) mutex_lock(&onyx->mutex);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 268) onyx_read_register(onyx, ONYX_REG_ADC_CONTROL, &v);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 269) v &= ~ONYX_ADC_INPUT_MIC;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 270) if (mic)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 271) v |= ONYX_ADC_INPUT_MIC;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 272) onyx_write_register(onyx, ONYX_REG_ADC_CONTROL, v);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 273) mutex_unlock(&onyx->mutex);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 274) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 275)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 276) static int onyx_snd_capture_source_put(struct snd_kcontrol *kcontrol,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 277) struct snd_ctl_elem_value *ucontrol)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 278) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 279) if (ucontrol->value.enumerated.item[0] > 1)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 280) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 281) onyx_set_capture_source(snd_kcontrol_chip(kcontrol),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 282) ucontrol->value.enumerated.item[0]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 283) return 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 284) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 285)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 286) static const struct snd_kcontrol_new capture_source_control = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 287) .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 288) /* If we name this 'Input Source', it properly shows up in
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 289) * alsamixer as a selection, * but it's shown under the
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 290) * 'Playback' category.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 291) * If I name it 'Capture Source', it shows up in strange
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 292) * ways (two bools of which one can be selected at a
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 293) * time) but at least it's shown in the 'Capture'
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 294) * category.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 295) * I was told that this was due to backward compatibility,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 296) * but I don't understand then why the mangling is *not*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 297) * done when I name it "Input Source".....
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 298) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 299) .name = "Capture Source",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 300) .access = SNDRV_CTL_ELEM_ACCESS_READWRITE,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 301) .info = onyx_snd_capture_source_info,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 302) .get = onyx_snd_capture_source_get,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 303) .put = onyx_snd_capture_source_put,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 304) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 305)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 306) #define onyx_snd_mute_info snd_ctl_boolean_stereo_info
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 307)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 308) static int onyx_snd_mute_get(struct snd_kcontrol *kcontrol,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 309) struct snd_ctl_elem_value *ucontrol)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 310) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 311) struct onyx *onyx = snd_kcontrol_chip(kcontrol);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 312) u8 c;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 313)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 314) mutex_lock(&onyx->mutex);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 315) onyx_read_register(onyx, ONYX_REG_DAC_CONTROL, &c);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 316) mutex_unlock(&onyx->mutex);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 317)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 318) ucontrol->value.integer.value[0] = !(c & ONYX_MUTE_LEFT);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 319) ucontrol->value.integer.value[1] = !(c & ONYX_MUTE_RIGHT);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 320)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 321) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 322) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 323)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 324) static int onyx_snd_mute_put(struct snd_kcontrol *kcontrol,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 325) struct snd_ctl_elem_value *ucontrol)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 326) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 327) struct onyx *onyx = snd_kcontrol_chip(kcontrol);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 328) u8 v = 0, c = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 329) int err = -EBUSY;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 330)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 331) mutex_lock(&onyx->mutex);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 332) if (onyx->analog_locked)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 333) goto out_unlock;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 334)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 335) onyx_read_register(onyx, ONYX_REG_DAC_CONTROL, &v);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 336) c = v;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 337) c &= ~(ONYX_MUTE_RIGHT | ONYX_MUTE_LEFT);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 338) if (!ucontrol->value.integer.value[0])
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 339) c |= ONYX_MUTE_LEFT;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 340) if (!ucontrol->value.integer.value[1])
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 341) c |= ONYX_MUTE_RIGHT;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 342) err = onyx_write_register(onyx, ONYX_REG_DAC_CONTROL, c);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 343)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 344) out_unlock:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 345) mutex_unlock(&onyx->mutex);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 346)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 347) return !err ? (v != c) : err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 348) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 349)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 350) static const struct snd_kcontrol_new mute_control = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 351) .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 352) .name = "Master Playback Switch",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 353) .access = SNDRV_CTL_ELEM_ACCESS_READWRITE,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 354) .info = onyx_snd_mute_info,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 355) .get = onyx_snd_mute_get,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 356) .put = onyx_snd_mute_put,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 357) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 358)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 359)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 360) #define onyx_snd_single_bit_info snd_ctl_boolean_mono_info
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 361)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 362) #define FLAG_POLARITY_INVERT 1
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 363) #define FLAG_SPDIFLOCK 2
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 364)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 365) static int onyx_snd_single_bit_get(struct snd_kcontrol *kcontrol,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 366) struct snd_ctl_elem_value *ucontrol)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 367) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 368) struct onyx *onyx = snd_kcontrol_chip(kcontrol);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 369) u8 c;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 370) long int pv = kcontrol->private_value;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 371) u8 polarity = (pv >> 16) & FLAG_POLARITY_INVERT;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 372) u8 address = (pv >> 8) & 0xff;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 373) u8 mask = pv & 0xff;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 374)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 375) mutex_lock(&onyx->mutex);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 376) onyx_read_register(onyx, address, &c);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 377) mutex_unlock(&onyx->mutex);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 378)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 379) ucontrol->value.integer.value[0] = !!(c & mask) ^ polarity;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 380)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 381) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 382) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 383)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 384) static int onyx_snd_single_bit_put(struct snd_kcontrol *kcontrol,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 385) struct snd_ctl_elem_value *ucontrol)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 386) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 387) struct onyx *onyx = snd_kcontrol_chip(kcontrol);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 388) u8 v = 0, c = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 389) int err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 390) long int pv = kcontrol->private_value;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 391) u8 polarity = (pv >> 16) & FLAG_POLARITY_INVERT;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 392) u8 spdiflock = (pv >> 16) & FLAG_SPDIFLOCK;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 393) u8 address = (pv >> 8) & 0xff;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 394) u8 mask = pv & 0xff;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 395)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 396) mutex_lock(&onyx->mutex);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 397) if (spdiflock && onyx->spdif_locked) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 398) /* even if alsamixer doesn't care.. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 399) err = -EBUSY;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 400) goto out_unlock;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 401) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 402) onyx_read_register(onyx, address, &v);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 403) c = v;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 404) c &= ~(mask);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 405) if (!!ucontrol->value.integer.value[0] ^ polarity)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 406) c |= mask;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 407) err = onyx_write_register(onyx, address, c);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 408)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 409) out_unlock:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 410) mutex_unlock(&onyx->mutex);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 411)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 412) return !err ? (v != c) : err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 413) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 414)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 415) #define SINGLE_BIT(n, type, description, address, mask, flags) \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 416) static const struct snd_kcontrol_new n##_control = { \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 417) .iface = SNDRV_CTL_ELEM_IFACE_##type, \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 418) .name = description, \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 419) .access = SNDRV_CTL_ELEM_ACCESS_READWRITE, \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 420) .info = onyx_snd_single_bit_info, \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 421) .get = onyx_snd_single_bit_get, \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 422) .put = onyx_snd_single_bit_put, \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 423) .private_value = (flags << 16) | (address << 8) | mask \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 424) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 425)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 426) SINGLE_BIT(spdif,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 427) MIXER,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 428) SNDRV_CTL_NAME_IEC958("", PLAYBACK, SWITCH),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 429) ONYX_REG_DIG_INFO4,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 430) ONYX_SPDIF_ENABLE,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 431) FLAG_SPDIFLOCK);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 432) SINGLE_BIT(ovr1,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 433) MIXER,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 434) "Oversampling Rate",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 435) ONYX_REG_DAC_CONTROL,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 436) ONYX_OVR1,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 437) 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 438) SINGLE_BIT(flt0,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 439) MIXER,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 440) "Fast Digital Filter Rolloff",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 441) ONYX_REG_DAC_FILTER,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 442) ONYX_ROLLOFF_FAST,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 443) FLAG_POLARITY_INVERT);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 444) SINGLE_BIT(hpf,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 445) MIXER,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 446) "Highpass Filter",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 447) ONYX_REG_ADC_HPF_BYPASS,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 448) ONYX_HPF_DISABLE,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 449) FLAG_POLARITY_INVERT);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 450) SINGLE_BIT(dm12,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 451) MIXER,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 452) "Digital De-Emphasis",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 453) ONYX_REG_DAC_DEEMPH,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 454) ONYX_DIGDEEMPH_CTRL,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 455) 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 456)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 457) static int onyx_spdif_info(struct snd_kcontrol *kcontrol,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 458) struct snd_ctl_elem_info *uinfo)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 459) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 460) uinfo->type = SNDRV_CTL_ELEM_TYPE_IEC958;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 461) uinfo->count = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 462) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 463) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 464)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 465) static int onyx_spdif_mask_get(struct snd_kcontrol *kcontrol,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 466) struct snd_ctl_elem_value *ucontrol)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 467) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 468) /* datasheet page 30, all others are 0 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 469) ucontrol->value.iec958.status[0] = 0x3e;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 470) ucontrol->value.iec958.status[1] = 0xff;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 471)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 472) ucontrol->value.iec958.status[3] = 0x3f;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 473) ucontrol->value.iec958.status[4] = 0x0f;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 474)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 475) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 476) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 477)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 478) static const struct snd_kcontrol_new onyx_spdif_mask = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 479) .access = SNDRV_CTL_ELEM_ACCESS_READ,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 480) .iface = SNDRV_CTL_ELEM_IFACE_PCM,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 481) .name = SNDRV_CTL_NAME_IEC958("",PLAYBACK,CON_MASK),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 482) .info = onyx_spdif_info,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 483) .get = onyx_spdif_mask_get,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 484) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 485)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 486) static int onyx_spdif_get(struct snd_kcontrol *kcontrol,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 487) struct snd_ctl_elem_value *ucontrol)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 488) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 489) struct onyx *onyx = snd_kcontrol_chip(kcontrol);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 490) u8 v;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 491)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 492) mutex_lock(&onyx->mutex);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 493) onyx_read_register(onyx, ONYX_REG_DIG_INFO1, &v);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 494) ucontrol->value.iec958.status[0] = v & 0x3e;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 495)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 496) onyx_read_register(onyx, ONYX_REG_DIG_INFO2, &v);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 497) ucontrol->value.iec958.status[1] = v;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 498)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 499) onyx_read_register(onyx, ONYX_REG_DIG_INFO3, &v);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 500) ucontrol->value.iec958.status[3] = v & 0x3f;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 501)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 502) onyx_read_register(onyx, ONYX_REG_DIG_INFO4, &v);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 503) ucontrol->value.iec958.status[4] = v & 0x0f;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 504) mutex_unlock(&onyx->mutex);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 505)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 506) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 507) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 508)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 509) static int onyx_spdif_put(struct snd_kcontrol *kcontrol,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 510) struct snd_ctl_elem_value *ucontrol)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 511) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 512) struct onyx *onyx = snd_kcontrol_chip(kcontrol);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 513) u8 v;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 514)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 515) mutex_lock(&onyx->mutex);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 516) onyx_read_register(onyx, ONYX_REG_DIG_INFO1, &v);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 517) v = (v & ~0x3e) | (ucontrol->value.iec958.status[0] & 0x3e);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 518) onyx_write_register(onyx, ONYX_REG_DIG_INFO1, v);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 519)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 520) v = ucontrol->value.iec958.status[1];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 521) onyx_write_register(onyx, ONYX_REG_DIG_INFO2, v);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 522)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 523) onyx_read_register(onyx, ONYX_REG_DIG_INFO3, &v);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 524) v = (v & ~0x3f) | (ucontrol->value.iec958.status[3] & 0x3f);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 525) onyx_write_register(onyx, ONYX_REG_DIG_INFO3, v);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 526)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 527) onyx_read_register(onyx, ONYX_REG_DIG_INFO4, &v);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 528) v = (v & ~0x0f) | (ucontrol->value.iec958.status[4] & 0x0f);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 529) onyx_write_register(onyx, ONYX_REG_DIG_INFO4, v);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 530) mutex_unlock(&onyx->mutex);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 531)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 532) return 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 533) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 534)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 535) static const struct snd_kcontrol_new onyx_spdif_ctrl = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 536) .access = SNDRV_CTL_ELEM_ACCESS_READWRITE,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 537) .iface = SNDRV_CTL_ELEM_IFACE_PCM,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 538) .name = SNDRV_CTL_NAME_IEC958("",PLAYBACK,DEFAULT),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 539) .info = onyx_spdif_info,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 540) .get = onyx_spdif_get,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 541) .put = onyx_spdif_put,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 542) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 543)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 544) /* our registers */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 545)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 546) static const u8 register_map[] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 547) ONYX_REG_DAC_ATTEN_LEFT,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 548) ONYX_REG_DAC_ATTEN_RIGHT,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 549) ONYX_REG_CONTROL,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 550) ONYX_REG_DAC_CONTROL,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 551) ONYX_REG_DAC_DEEMPH,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 552) ONYX_REG_DAC_FILTER,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 553) ONYX_REG_DAC_OUTPHASE,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 554) ONYX_REG_ADC_CONTROL,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 555) ONYX_REG_ADC_HPF_BYPASS,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 556) ONYX_REG_DIG_INFO1,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 557) ONYX_REG_DIG_INFO2,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 558) ONYX_REG_DIG_INFO3,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 559) ONYX_REG_DIG_INFO4
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 560) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 561)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 562) static const u8 initial_values[ARRAY_SIZE(register_map)] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 563) 0x80, 0x80, /* muted */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 564) ONYX_MRST | ONYX_SRST, /* but handled specially! */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 565) ONYX_MUTE_LEFT | ONYX_MUTE_RIGHT,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 566) 0, /* no deemphasis */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 567) ONYX_DAC_FILTER_ALWAYS,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 568) ONYX_OUTPHASE_INVERTED,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 569) (-1 /*dB*/ + 8) & 0xF, /* line in selected, -1 dB gain*/
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 570) ONYX_ADC_HPF_ALWAYS,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 571) (1<<2), /* pcm audio */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 572) 2, /* category: pcm coder */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 573) 0, /* sampling frequency 44.1 kHz, clock accuracy level II */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 574) 1 /* 24 bit depth */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 575) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 576)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 577) /* reset registers of chip, either to initial or to previous values */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 578) static int onyx_register_init(struct onyx *onyx)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 579) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 580) int i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 581) u8 val;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 582) u8 regs[sizeof(initial_values)];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 583)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 584) if (!onyx->initialised) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 585) memcpy(regs, initial_values, sizeof(initial_values));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 586) if (onyx_read_register(onyx, ONYX_REG_CONTROL, &val))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 587) return -1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 588) val &= ~ONYX_SILICONVERSION;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 589) val |= initial_values[3];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 590) regs[3] = val;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 591) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 592) for (i=0; i<sizeof(register_map); i++)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 593) regs[i] = onyx->cache[register_map[i]-FIRSTREGISTER];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 594) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 595)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 596) for (i=0; i<sizeof(register_map); i++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 597) if (onyx_write_register(onyx, register_map[i], regs[i]))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 598) return -1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 599) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 600) onyx->initialised = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 601) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 602) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 603)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 604) static struct transfer_info onyx_transfers[] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 605) /* this is first so we can skip it if no input is present...
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 606) * No hardware exists with that, but it's here as an example
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 607) * of what to do :) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 608) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 609) /* analog input */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 610) .formats = SNDRV_PCM_FMTBIT_S8 |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 611) SNDRV_PCM_FMTBIT_S16_BE |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 612) SNDRV_PCM_FMTBIT_S24_BE,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 613) .rates = SNDRV_PCM_RATE_8000_96000,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 614) .transfer_in = 1,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 615) .must_be_clock_source = 0,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 616) .tag = 0,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 617) },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 618) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 619) /* if analog and digital are currently off, anything should go,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 620) * so this entry describes everything we can do... */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 621) .formats = SNDRV_PCM_FMTBIT_S8 |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 622) SNDRV_PCM_FMTBIT_S16_BE |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 623) SNDRV_PCM_FMTBIT_S24_BE
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 624) #ifdef SNDRV_PCM_FMTBIT_COMPRESSED_16BE
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 625) | SNDRV_PCM_FMTBIT_COMPRESSED_16BE
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 626) #endif
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 627) ,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 628) .rates = SNDRV_PCM_RATE_8000_96000,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 629) .tag = 0,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 630) },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 631) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 632) /* analog output */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 633) .formats = SNDRV_PCM_FMTBIT_S8 |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 634) SNDRV_PCM_FMTBIT_S16_BE |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 635) SNDRV_PCM_FMTBIT_S24_BE,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 636) .rates = SNDRV_PCM_RATE_8000_96000,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 637) .transfer_in = 0,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 638) .must_be_clock_source = 0,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 639) .tag = 1,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 640) },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 641) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 642) /* digital pcm output, also possible for analog out */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 643) .formats = SNDRV_PCM_FMTBIT_S8 |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 644) SNDRV_PCM_FMTBIT_S16_BE |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 645) SNDRV_PCM_FMTBIT_S24_BE,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 646) .rates = SNDRV_PCM_RATE_32000 |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 647) SNDRV_PCM_RATE_44100 |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 648) SNDRV_PCM_RATE_48000,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 649) .transfer_in = 0,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 650) .must_be_clock_source = 0,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 651) .tag = 2,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 652) },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 653) #ifdef SNDRV_PCM_FMTBIT_COMPRESSED_16BE
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 654) /* Once alsa gets supports for this kind of thing we can add it... */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 655) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 656) /* digital compressed output */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 657) .formats = SNDRV_PCM_FMTBIT_COMPRESSED_16BE,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 658) .rates = SNDRV_PCM_RATE_32000 |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 659) SNDRV_PCM_RATE_44100 |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 660) SNDRV_PCM_RATE_48000,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 661) .tag = 2,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 662) },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 663) #endif
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 664) {}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 665) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 666)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 667) static int onyx_usable(struct codec_info_item *cii,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 668) struct transfer_info *ti,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 669) struct transfer_info *out)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 670) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 671) u8 v;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 672) struct onyx *onyx = cii->codec_data;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 673) int spdif_enabled, analog_enabled;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 674)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 675) mutex_lock(&onyx->mutex);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 676) onyx_read_register(onyx, ONYX_REG_DIG_INFO4, &v);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 677) spdif_enabled = !!(v & ONYX_SPDIF_ENABLE);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 678) onyx_read_register(onyx, ONYX_REG_DAC_CONTROL, &v);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 679) analog_enabled =
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 680) (v & (ONYX_MUTE_RIGHT|ONYX_MUTE_LEFT))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 681) != (ONYX_MUTE_RIGHT|ONYX_MUTE_LEFT);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 682) mutex_unlock(&onyx->mutex);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 683)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 684) switch (ti->tag) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 685) case 0: return 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 686) case 1: return analog_enabled;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 687) case 2: return spdif_enabled;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 688) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 689) return 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 690) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 691)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 692) static int onyx_prepare(struct codec_info_item *cii,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 693) struct bus_info *bi,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 694) struct snd_pcm_substream *substream)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 695) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 696) u8 v;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 697) struct onyx *onyx = cii->codec_data;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 698) int err = -EBUSY;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 699)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 700) mutex_lock(&onyx->mutex);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 701)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 702) #ifdef SNDRV_PCM_FMTBIT_COMPRESSED_16BE
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 703) if (substream->runtime->format == SNDRV_PCM_FMTBIT_COMPRESSED_16BE) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 704) /* mute and lock analog output */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 705) onyx_read_register(onyx, ONYX_REG_DAC_CONTROL, &v);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 706) if (onyx_write_register(onyx,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 707) ONYX_REG_DAC_CONTROL,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 708) v | ONYX_MUTE_RIGHT | ONYX_MUTE_LEFT))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 709) goto out_unlock;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 710) onyx->analog_locked = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 711) err = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 712) goto out_unlock;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 713) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 714) #endif
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 715) switch (substream->runtime->rate) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 716) case 32000:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 717) case 44100:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 718) case 48000:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 719) /* these rates are ok for all outputs */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 720) /* FIXME: program spdif channel control bits here so that
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 721) * userspace doesn't have to if it only plays pcm! */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 722) err = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 723) goto out_unlock;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 724) default:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 725) /* got some rate that the digital output can't do,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 726) * so disable and lock it */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 727) onyx_read_register(cii->codec_data, ONYX_REG_DIG_INFO4, &v);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 728) if (onyx_write_register(onyx,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 729) ONYX_REG_DIG_INFO4,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 730) v & ~ONYX_SPDIF_ENABLE))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 731) goto out_unlock;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 732) onyx->spdif_locked = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 733) err = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 734) goto out_unlock;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 735) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 736)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 737) out_unlock:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 738) mutex_unlock(&onyx->mutex);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 739)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 740) return err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 741) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 742)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 743) static int onyx_open(struct codec_info_item *cii,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 744) struct snd_pcm_substream *substream)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 745) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 746) struct onyx *onyx = cii->codec_data;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 747)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 748) mutex_lock(&onyx->mutex);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 749) onyx->open_count++;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 750) mutex_unlock(&onyx->mutex);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 751)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 752) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 753) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 754)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 755) static int onyx_close(struct codec_info_item *cii,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 756) struct snd_pcm_substream *substream)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 757) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 758) struct onyx *onyx = cii->codec_data;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 759)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 760) mutex_lock(&onyx->mutex);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 761) onyx->open_count--;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 762) if (!onyx->open_count)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 763) onyx->spdif_locked = onyx->analog_locked = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 764) mutex_unlock(&onyx->mutex);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 765)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 766) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 767) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 768)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 769) static int onyx_switch_clock(struct codec_info_item *cii,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 770) enum clock_switch what)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 771) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 772) struct onyx *onyx = cii->codec_data;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 773)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 774) mutex_lock(&onyx->mutex);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 775) /* this *MUST* be more elaborate later... */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 776) switch (what) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 777) case CLOCK_SWITCH_PREPARE_SLAVE:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 778) onyx->codec.gpio->methods->all_amps_off(onyx->codec.gpio);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 779) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 780) case CLOCK_SWITCH_SLAVE:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 781) onyx->codec.gpio->methods->all_amps_restore(onyx->codec.gpio);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 782) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 783) default: /* silence warning */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 784) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 785) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 786) mutex_unlock(&onyx->mutex);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 787)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 788) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 789) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 790)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 791) #ifdef CONFIG_PM
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 792)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 793) static int onyx_suspend(struct codec_info_item *cii, pm_message_t state)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 794) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 795) struct onyx *onyx = cii->codec_data;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 796) u8 v;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 797) int err = -ENXIO;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 798)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 799) mutex_lock(&onyx->mutex);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 800) if (onyx_read_register(onyx, ONYX_REG_CONTROL, &v))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 801) goto out_unlock;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 802) onyx_write_register(onyx, ONYX_REG_CONTROL, v | ONYX_ADPSV | ONYX_DAPSV);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 803) /* Apple does a sleep here but the datasheet says to do it on resume */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 804) err = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 805) out_unlock:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 806) mutex_unlock(&onyx->mutex);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 807)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 808) return err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 809) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 810)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 811) static int onyx_resume(struct codec_info_item *cii)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 812) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 813) struct onyx *onyx = cii->codec_data;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 814) u8 v;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 815) int err = -ENXIO;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 816)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 817) mutex_lock(&onyx->mutex);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 818)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 819) /* reset codec */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 820) onyx->codec.gpio->methods->set_hw_reset(onyx->codec.gpio, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 821) msleep(1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 822) onyx->codec.gpio->methods->set_hw_reset(onyx->codec.gpio, 1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 823) msleep(1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 824) onyx->codec.gpio->methods->set_hw_reset(onyx->codec.gpio, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 825) msleep(1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 826)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 827) /* take codec out of suspend (if it still is after reset) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 828) if (onyx_read_register(onyx, ONYX_REG_CONTROL, &v))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 829) goto out_unlock;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 830) onyx_write_register(onyx, ONYX_REG_CONTROL, v & ~(ONYX_ADPSV | ONYX_DAPSV));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 831) /* FIXME: should divide by sample rate, but 8k is the lowest we go */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 832) msleep(2205000/8000);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 833) /* reset all values */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 834) onyx_register_init(onyx);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 835) err = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 836) out_unlock:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 837) mutex_unlock(&onyx->mutex);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 838)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 839) return err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 840) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 841)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 842) #endif /* CONFIG_PM */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 843)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 844) static struct codec_info onyx_codec_info = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 845) .transfers = onyx_transfers,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 846) .sysclock_factor = 256,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 847) .bus_factor = 64,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 848) .owner = THIS_MODULE,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 849) .usable = onyx_usable,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 850) .prepare = onyx_prepare,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 851) .open = onyx_open,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 852) .close = onyx_close,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 853) .switch_clock = onyx_switch_clock,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 854) #ifdef CONFIG_PM
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 855) .suspend = onyx_suspend,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 856) .resume = onyx_resume,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 857) #endif
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 858) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 859)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 860) static int onyx_init_codec(struct aoa_codec *codec)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 861) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 862) struct onyx *onyx = codec_to_onyx(codec);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 863) struct snd_kcontrol *ctl;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 864) struct codec_info *ci = &onyx_codec_info;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 865) u8 v;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 866) int err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 867)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 868) if (!onyx->codec.gpio || !onyx->codec.gpio->methods) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 869) printk(KERN_ERR PFX "gpios not assigned!!\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 870) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 871) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 872)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 873) onyx->codec.gpio->methods->set_hw_reset(onyx->codec.gpio, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 874) msleep(1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 875) onyx->codec.gpio->methods->set_hw_reset(onyx->codec.gpio, 1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 876) msleep(1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 877) onyx->codec.gpio->methods->set_hw_reset(onyx->codec.gpio, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 878) msleep(1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 879)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 880) if (onyx_register_init(onyx)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 881) printk(KERN_ERR PFX "failed to initialise onyx registers\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 882) return -ENODEV;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 883) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 884)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 885) if (aoa_snd_device_new(SNDRV_DEV_CODEC, onyx, &ops)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 886) printk(KERN_ERR PFX "failed to create onyx snd device!\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 887) return -ENODEV;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 888) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 889)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 890) /* nothing connected? what a joke! */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 891) if ((onyx->codec.connected & 0xF) == 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 892) return -ENOTCONN;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 893)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 894) /* if no inputs are present... */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 895) if ((onyx->codec.connected & 0xC) == 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 896) if (!onyx->codec_info)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 897) onyx->codec_info = kmalloc(sizeof(struct codec_info), GFP_KERNEL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 898) if (!onyx->codec_info)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 899) return -ENOMEM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 900) ci = onyx->codec_info;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 901) *ci = onyx_codec_info;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 902) ci->transfers++;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 903) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 904)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 905) /* if no outputs are present... */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 906) if ((onyx->codec.connected & 3) == 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 907) if (!onyx->codec_info)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 908) onyx->codec_info = kmalloc(sizeof(struct codec_info), GFP_KERNEL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 909) if (!onyx->codec_info)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 910) return -ENOMEM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 911) ci = onyx->codec_info;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 912) /* this is fine as there have to be inputs
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 913) * if we end up in this part of the code */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 914) *ci = onyx_codec_info;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 915) ci->transfers[1].formats = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 916) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 917)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 918) if (onyx->codec.soundbus_dev->attach_codec(onyx->codec.soundbus_dev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 919) aoa_get_card(),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 920) ci, onyx)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 921) printk(KERN_ERR PFX "error creating onyx pcm\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 922) return -ENODEV;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 923) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 924) #define ADDCTL(n) \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 925) do { \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 926) ctl = snd_ctl_new1(&n, onyx); \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 927) if (ctl) { \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 928) ctl->id.device = \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 929) onyx->codec.soundbus_dev->pcm->device; \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 930) err = aoa_snd_ctl_add(ctl); \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 931) if (err) \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 932) goto error; \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 933) } \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 934) } while (0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 935)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 936) if (onyx->codec.soundbus_dev->pcm) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 937) /* give the user appropriate controls
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 938) * depending on what inputs are connected */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 939) if ((onyx->codec.connected & 0xC) == 0xC)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 940) ADDCTL(capture_source_control);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 941) else if (onyx->codec.connected & 4)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 942) onyx_set_capture_source(onyx, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 943) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 944) onyx_set_capture_source(onyx, 1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 945) if (onyx->codec.connected & 0xC)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 946) ADDCTL(inputgain_control);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 947)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 948) /* depending on what output is connected,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 949) * give the user appropriate controls */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 950) if (onyx->codec.connected & 1) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 951) ADDCTL(volume_control);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 952) ADDCTL(mute_control);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 953) ADDCTL(ovr1_control);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 954) ADDCTL(flt0_control);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 955) ADDCTL(hpf_control);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 956) ADDCTL(dm12_control);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 957) /* spdif control defaults to off */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 958) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 959) if (onyx->codec.connected & 2) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 960) ADDCTL(onyx_spdif_mask);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 961) ADDCTL(onyx_spdif_ctrl);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 962) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 963) if ((onyx->codec.connected & 3) == 3)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 964) ADDCTL(spdif_control);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 965) /* if only S/PDIF is connected, enable it unconditionally */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 966) if ((onyx->codec.connected & 3) == 2) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 967) onyx_read_register(onyx, ONYX_REG_DIG_INFO4, &v);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 968) v |= ONYX_SPDIF_ENABLE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 969) onyx_write_register(onyx, ONYX_REG_DIG_INFO4, v);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 970) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 971) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 972) #undef ADDCTL
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 973) printk(KERN_INFO PFX "attached to onyx codec via i2c\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 974)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 975) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 976) error:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 977) onyx->codec.soundbus_dev->detach_codec(onyx->codec.soundbus_dev, onyx);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 978) snd_device_free(aoa_get_card(), onyx);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 979) return err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 980) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 981)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 982) static void onyx_exit_codec(struct aoa_codec *codec)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 983) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 984) struct onyx *onyx = codec_to_onyx(codec);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 985)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 986) if (!onyx->codec.soundbus_dev) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 987) printk(KERN_ERR PFX "onyx_exit_codec called without soundbus_dev!\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 988) return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 989) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 990) onyx->codec.soundbus_dev->detach_codec(onyx->codec.soundbus_dev, onyx);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 991) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 992)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 993) static int onyx_i2c_probe(struct i2c_client *client,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 994) const struct i2c_device_id *id)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 995) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 996) struct device_node *node = client->dev.of_node;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 997) struct onyx *onyx;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 998) u8 dummy;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 999)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1000) onyx = kzalloc(sizeof(struct onyx), GFP_KERNEL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1001)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1002) if (!onyx)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1003) return -ENOMEM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1004)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1005) mutex_init(&onyx->mutex);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1006) onyx->i2c = client;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1007) i2c_set_clientdata(client, onyx);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1008)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1009) /* we try to read from register ONYX_REG_CONTROL
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1010) * to check if the codec is present */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1011) if (onyx_read_register(onyx, ONYX_REG_CONTROL, &dummy) != 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1012) printk(KERN_ERR PFX "failed to read control register\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1013) goto fail;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1014) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1015)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1016) strlcpy(onyx->codec.name, "onyx", MAX_CODEC_NAME_LEN);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1017) onyx->codec.owner = THIS_MODULE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1018) onyx->codec.init = onyx_init_codec;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1019) onyx->codec.exit = onyx_exit_codec;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1020) onyx->codec.node = of_node_get(node);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1021)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1022) if (aoa_codec_register(&onyx->codec)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1023) goto fail;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1024) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1025) printk(KERN_DEBUG PFX "created and attached onyx instance\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1026) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1027) fail:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1028) kfree(onyx);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1029) return -ENODEV;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1030) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1031)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1032) static int onyx_i2c_remove(struct i2c_client *client)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1033) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1034) struct onyx *onyx = i2c_get_clientdata(client);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1035)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1036) aoa_codec_unregister(&onyx->codec);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1037) of_node_put(onyx->codec.node);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1038) kfree(onyx->codec_info);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1039) kfree(onyx);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1040) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1041) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1042)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1043) static const struct i2c_device_id onyx_i2c_id[] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1044) { "MAC,pcm3052", 0 },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1045) { }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1046) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1047) MODULE_DEVICE_TABLE(i2c,onyx_i2c_id);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1048)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1049) static struct i2c_driver onyx_driver = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1050) .driver = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1051) .name = "aoa_codec_onyx",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1052) },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1053) .probe = onyx_i2c_probe,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1054) .remove = onyx_i2c_remove,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1055) .id_table = onyx_i2c_id,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1056) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1057)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1058) module_i2c_driver(onyx_driver);