^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 tas 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) * Open questions:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8) * - How to distinguish between 3004 and versions?
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10) * FIXMEs:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11) * - This codec driver doesn't honour the 'connected'
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12) * property of the aoa_codec struct, hence if
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13) * it is used in machines where not everything is
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14) * connected it will display wrong mixer elements.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 15) * - Driver assumes that the microphone is always
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 16) * monaureal and connected to the right channel of
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 17) * the input. This should also be a codec-dependent
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 18) * flag, maybe the codec should have 3 different
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 19) * bits for the three different possibilities how
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 20) * it can be hooked up...
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 21) * But as long as I don't see any hardware hooked
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 22) * up that way...
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 23) * - As Apple notes in their code, the tas3004 seems
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 24) * to delay the right channel by one sample. You can
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 25) * see this when for example recording stereo in
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 26) * audacity, or recording the tas output via cable
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 27) * on another machine (use a sinus generator or so).
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 28) * I tried programming the BiQuads but couldn't
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 29) * make the delay work, maybe someone can read the
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 30) * datasheet and fix it. The relevant Apple comment
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 31) * is in AppleTAS3004Audio.cpp lines 1637 ff. Note
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 32) * that their comment describing how they program
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 33) * the filters sucks...
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 34) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 35) * Other things:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 36) * - this should actually register *two* aoa_codec
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 37) * structs since it has two inputs. Then it must
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 38) * use the prepare callback to forbid running the
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 39) * secondary output on a different clock.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 40) * Also, whatever bus knows how to do this must
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 41) * provide two soundbus_dev devices and the fabric
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 42) * must be able to link them correctly.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 43) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 44) * I don't even know if Apple ever uses the second
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 45) * port on the tas3004 though, I don't think their
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 46) * i2s controllers can even do it. OTOH, they all
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 47) * derive the clocks from common clocks, so it
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 48) * might just be possible. The framework allows the
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 49) * codec to refine the transfer_info items in the
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 50) * usable callback, so we can simply remove the
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 51) * rates the second instance is not using when it
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 52) * actually is in use.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 53) * Maybe we'll need to make the sound busses have
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 54) * a 'clock group id' value so the codec can
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 55) * determine if the two outputs can be driven at
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 56) * the same time. But that is likely overkill, up
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 57) * to the fabric to not link them up incorrectly,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 58) * and up to the hardware designer to not wire
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 59) * them up in some weird unusable way.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 60) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 61) #include <stddef.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 62) #include <linux/i2c.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 63) #include <asm/pmac_low_i2c.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 64) #include <asm/prom.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 65) #include <linux/delay.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 66) #include <linux/module.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 67) #include <linux/mutex.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 68) #include <linux/slab.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 69)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 70) MODULE_AUTHOR("Johannes Berg <johannes@sipsolutions.net>");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 71) MODULE_LICENSE("GPL");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 72) MODULE_DESCRIPTION("tas codec driver for snd-aoa");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 73)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 74) #include "tas.h"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 75) #include "tas-gain-table.h"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 76) #include "tas-basstreble.h"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 77) #include "../aoa.h"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 78) #include "../soundbus/soundbus.h"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 79)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 80) #define PFX "snd-aoa-codec-tas: "
^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) struct tas {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 84) struct aoa_codec codec;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 85) struct i2c_client *i2c;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 86) u32 mute_l:1, mute_r:1 ,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 87) controls_created:1 ,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 88) drc_enabled:1,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 89) hw_enabled:1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 90) u8 cached_volume_l, cached_volume_r;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 91) u8 mixer_l[3], mixer_r[3];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 92) u8 bass, treble;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 93) u8 acr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 94) int drc_range;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 95) /* protects hardware access against concurrency from
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 96) * userspace when hitting controls and during
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 97) * codec init/suspend/resume */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 98) struct mutex mtx;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 99) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 100)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 101) static int tas_reset_init(struct tas *tas);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 102)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 103) static struct tas *codec_to_tas(struct aoa_codec *codec)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 104) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 105) return container_of(codec, struct tas, codec);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 106) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 107)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 108) static inline int tas_write_reg(struct tas *tas, u8 reg, u8 len, u8 *data)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 109) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 110) if (len == 1)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 111) return i2c_smbus_write_byte_data(tas->i2c, reg, *data);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 112) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 113) return i2c_smbus_write_i2c_block_data(tas->i2c, reg, len, data);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 114) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 115)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 116) static void tas3004_set_drc(struct tas *tas)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 117) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 118) unsigned char val[6];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 119)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 120) if (tas->drc_enabled)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 121) val[0] = 0x50; /* 3:1 above threshold */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 122) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 123) val[0] = 0x51; /* disabled */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 124) val[1] = 0x02; /* 1:1 below threshold */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 125) if (tas->drc_range > 0xef)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 126) val[2] = 0xef;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 127) else if (tas->drc_range < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 128) val[2] = 0x00;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 129) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 130) val[2] = tas->drc_range;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 131) val[3] = 0xb0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 132) val[4] = 0x60;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 133) val[5] = 0xa0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 134)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 135) tas_write_reg(tas, TAS_REG_DRC, 6, val);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 136) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 137)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 138) static void tas_set_treble(struct tas *tas)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 139) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 140) u8 tmp;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 141)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 142) tmp = tas3004_treble(tas->treble);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 143) tas_write_reg(tas, TAS_REG_TREBLE, 1, &tmp);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 144) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 145)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 146) static void tas_set_bass(struct tas *tas)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 147) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 148) u8 tmp;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 149)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 150) tmp = tas3004_bass(tas->bass);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 151) tas_write_reg(tas, TAS_REG_BASS, 1, &tmp);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 152) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 153)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 154) static void tas_set_volume(struct tas *tas)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 155) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 156) u8 block[6];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 157) int tmp;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 158) u8 left, right;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 159)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 160) left = tas->cached_volume_l;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 161) right = tas->cached_volume_r;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 162)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 163) if (left > 177) left = 177;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 164) if (right > 177) right = 177;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 165)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 166) if (tas->mute_l) left = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 167) if (tas->mute_r) right = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 168)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 169) /* analysing the volume and mixer tables shows
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 170) * that they are similar enough when we shift
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 171) * the mixer table down by 4 bits. The error
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 172) * is miniscule, in just one item the error
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 173) * is 1, at a value of 0x07f17b (mixer table
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 174) * value is 0x07f17a) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 175) tmp = tas_gaintable[left];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 176) block[0] = tmp>>20;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 177) block[1] = tmp>>12;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 178) block[2] = tmp>>4;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 179) tmp = tas_gaintable[right];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 180) block[3] = tmp>>20;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 181) block[4] = tmp>>12;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 182) block[5] = tmp>>4;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 183) tas_write_reg(tas, TAS_REG_VOL, 6, block);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 184) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 185)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 186) static void tas_set_mixer(struct tas *tas)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 187) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 188) u8 block[9];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 189) int tmp, i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 190) u8 val;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 191)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 192) for (i=0;i<3;i++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 193) val = tas->mixer_l[i];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 194) if (val > 177) val = 177;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 195) tmp = tas_gaintable[val];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 196) block[3*i+0] = tmp>>16;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 197) block[3*i+1] = tmp>>8;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 198) block[3*i+2] = tmp;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 199) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 200) tas_write_reg(tas, TAS_REG_LMIX, 9, block);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 201)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 202) for (i=0;i<3;i++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 203) val = tas->mixer_r[i];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 204) if (val > 177) val = 177;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 205) tmp = tas_gaintable[val];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 206) block[3*i+0] = tmp>>16;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 207) block[3*i+1] = tmp>>8;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 208) block[3*i+2] = tmp;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 209) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 210) tas_write_reg(tas, TAS_REG_RMIX, 9, block);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 211) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 212)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 213) /* alsa stuff */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 214)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 215) static int tas_dev_register(struct snd_device *dev)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 216) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 217) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 218) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 219)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 220) static const struct snd_device_ops ops = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 221) .dev_register = tas_dev_register,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 222) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 223)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 224) static int tas_snd_vol_info(struct snd_kcontrol *kcontrol,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 225) struct snd_ctl_elem_info *uinfo)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 226) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 227) uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 228) uinfo->count = 2;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 229) uinfo->value.integer.min = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 230) uinfo->value.integer.max = 177;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 231) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 232) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 233)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 234) static int tas_snd_vol_get(struct snd_kcontrol *kcontrol,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 235) struct snd_ctl_elem_value *ucontrol)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 236) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 237) struct tas *tas = snd_kcontrol_chip(kcontrol);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 238)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 239) mutex_lock(&tas->mtx);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 240) ucontrol->value.integer.value[0] = tas->cached_volume_l;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 241) ucontrol->value.integer.value[1] = tas->cached_volume_r;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 242) mutex_unlock(&tas->mtx);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 243) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 244) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 245)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 246) static int tas_snd_vol_put(struct snd_kcontrol *kcontrol,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 247) struct snd_ctl_elem_value *ucontrol)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 248) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 249) struct tas *tas = snd_kcontrol_chip(kcontrol);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 250)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 251) if (ucontrol->value.integer.value[0] < 0 ||
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 252) ucontrol->value.integer.value[0] > 177)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 253) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 254) if (ucontrol->value.integer.value[1] < 0 ||
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 255) ucontrol->value.integer.value[1] > 177)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 256) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 257)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 258) mutex_lock(&tas->mtx);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 259) if (tas->cached_volume_l == ucontrol->value.integer.value[0]
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 260) && tas->cached_volume_r == ucontrol->value.integer.value[1]) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 261) mutex_unlock(&tas->mtx);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 262) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 263) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 264)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 265) tas->cached_volume_l = ucontrol->value.integer.value[0];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 266) tas->cached_volume_r = ucontrol->value.integer.value[1];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 267) if (tas->hw_enabled)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 268) tas_set_volume(tas);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 269) mutex_unlock(&tas->mtx);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 270) return 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 271) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 272)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 273) static const struct snd_kcontrol_new volume_control = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 274) .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 275) .name = "Master Playback Volume",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 276) .access = SNDRV_CTL_ELEM_ACCESS_READWRITE,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 277) .info = tas_snd_vol_info,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 278) .get = tas_snd_vol_get,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 279) .put = tas_snd_vol_put,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 280) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 281)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 282) #define tas_snd_mute_info snd_ctl_boolean_stereo_info
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 283)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 284) static int tas_snd_mute_get(struct snd_kcontrol *kcontrol,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 285) struct snd_ctl_elem_value *ucontrol)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 286) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 287) struct tas *tas = snd_kcontrol_chip(kcontrol);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 288)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 289) mutex_lock(&tas->mtx);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 290) ucontrol->value.integer.value[0] = !tas->mute_l;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 291) ucontrol->value.integer.value[1] = !tas->mute_r;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 292) mutex_unlock(&tas->mtx);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 293) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 294) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 295)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 296) static int tas_snd_mute_put(struct snd_kcontrol *kcontrol,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 297) struct snd_ctl_elem_value *ucontrol)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 298) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 299) struct tas *tas = snd_kcontrol_chip(kcontrol);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 300)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 301) mutex_lock(&tas->mtx);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 302) if (tas->mute_l == !ucontrol->value.integer.value[0]
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 303) && tas->mute_r == !ucontrol->value.integer.value[1]) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 304) mutex_unlock(&tas->mtx);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 305) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 306) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 307)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 308) tas->mute_l = !ucontrol->value.integer.value[0];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 309) tas->mute_r = !ucontrol->value.integer.value[1];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 310) if (tas->hw_enabled)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 311) tas_set_volume(tas);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 312) mutex_unlock(&tas->mtx);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 313) return 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 314) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 315)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 316) static const struct snd_kcontrol_new mute_control = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 317) .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 318) .name = "Master Playback Switch",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 319) .access = SNDRV_CTL_ELEM_ACCESS_READWRITE,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 320) .info = tas_snd_mute_info,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 321) .get = tas_snd_mute_get,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 322) .put = tas_snd_mute_put,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 323) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 324)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 325) static int tas_snd_mixer_info(struct snd_kcontrol *kcontrol,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 326) struct snd_ctl_elem_info *uinfo)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 327) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 328) uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 329) uinfo->count = 2;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 330) uinfo->value.integer.min = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 331) uinfo->value.integer.max = 177;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 332) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 333) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 334)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 335) static int tas_snd_mixer_get(struct snd_kcontrol *kcontrol,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 336) struct snd_ctl_elem_value *ucontrol)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 337) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 338) struct tas *tas = snd_kcontrol_chip(kcontrol);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 339) int idx = kcontrol->private_value;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 340)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 341) mutex_lock(&tas->mtx);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 342) ucontrol->value.integer.value[0] = tas->mixer_l[idx];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 343) ucontrol->value.integer.value[1] = tas->mixer_r[idx];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 344) mutex_unlock(&tas->mtx);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 345)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 346) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 347) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 348)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 349) static int tas_snd_mixer_put(struct snd_kcontrol *kcontrol,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 350) struct snd_ctl_elem_value *ucontrol)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 351) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 352) struct tas *tas = snd_kcontrol_chip(kcontrol);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 353) int idx = kcontrol->private_value;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 354)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 355) mutex_lock(&tas->mtx);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 356) if (tas->mixer_l[idx] == ucontrol->value.integer.value[0]
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 357) && tas->mixer_r[idx] == ucontrol->value.integer.value[1]) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 358) mutex_unlock(&tas->mtx);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 359) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 360) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 361)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 362) tas->mixer_l[idx] = ucontrol->value.integer.value[0];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 363) tas->mixer_r[idx] = ucontrol->value.integer.value[1];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 364)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 365) if (tas->hw_enabled)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 366) tas_set_mixer(tas);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 367) mutex_unlock(&tas->mtx);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 368) return 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 369) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 370)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 371) #define MIXER_CONTROL(n,descr,idx) \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 372) static const struct snd_kcontrol_new n##_control = { \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 373) .iface = SNDRV_CTL_ELEM_IFACE_MIXER, \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 374) .name = descr " Playback Volume", \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 375) .access = SNDRV_CTL_ELEM_ACCESS_READWRITE, \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 376) .info = tas_snd_mixer_info, \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 377) .get = tas_snd_mixer_get, \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 378) .put = tas_snd_mixer_put, \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 379) .private_value = idx, \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 380) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 381)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 382) MIXER_CONTROL(pcm1, "PCM", 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 383) MIXER_CONTROL(monitor, "Monitor", 2);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 384)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 385) static int tas_snd_drc_range_info(struct snd_kcontrol *kcontrol,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 386) struct snd_ctl_elem_info *uinfo)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 387) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 388) uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 389) uinfo->count = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 390) uinfo->value.integer.min = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 391) uinfo->value.integer.max = TAS3004_DRC_MAX;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 392) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 393) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 394)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 395) static int tas_snd_drc_range_get(struct snd_kcontrol *kcontrol,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 396) struct snd_ctl_elem_value *ucontrol)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 397) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 398) struct tas *tas = snd_kcontrol_chip(kcontrol);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 399)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 400) mutex_lock(&tas->mtx);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 401) ucontrol->value.integer.value[0] = tas->drc_range;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 402) mutex_unlock(&tas->mtx);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 403) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 404) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 405)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 406) static int tas_snd_drc_range_put(struct snd_kcontrol *kcontrol,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 407) struct snd_ctl_elem_value *ucontrol)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 408) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 409) struct tas *tas = snd_kcontrol_chip(kcontrol);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 410)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 411) if (ucontrol->value.integer.value[0] < 0 ||
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 412) ucontrol->value.integer.value[0] > TAS3004_DRC_MAX)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 413) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 414)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 415) mutex_lock(&tas->mtx);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 416) if (tas->drc_range == ucontrol->value.integer.value[0]) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 417) mutex_unlock(&tas->mtx);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 418) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 419) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 420)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 421) tas->drc_range = ucontrol->value.integer.value[0];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 422) if (tas->hw_enabled)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 423) tas3004_set_drc(tas);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 424) mutex_unlock(&tas->mtx);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 425) return 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 426) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 427)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 428) static const struct snd_kcontrol_new drc_range_control = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 429) .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 430) .name = "DRC Range",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 431) .access = SNDRV_CTL_ELEM_ACCESS_READWRITE,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 432) .info = tas_snd_drc_range_info,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 433) .get = tas_snd_drc_range_get,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 434) .put = tas_snd_drc_range_put,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 435) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 436)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 437) #define tas_snd_drc_switch_info snd_ctl_boolean_mono_info
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 438)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 439) static int tas_snd_drc_switch_get(struct snd_kcontrol *kcontrol,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 440) struct snd_ctl_elem_value *ucontrol)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 441) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 442) struct tas *tas = snd_kcontrol_chip(kcontrol);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 443)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 444) mutex_lock(&tas->mtx);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 445) ucontrol->value.integer.value[0] = tas->drc_enabled;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 446) mutex_unlock(&tas->mtx);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 447) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 448) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 449)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 450) static int tas_snd_drc_switch_put(struct snd_kcontrol *kcontrol,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 451) struct snd_ctl_elem_value *ucontrol)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 452) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 453) struct tas *tas = snd_kcontrol_chip(kcontrol);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 454)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 455) mutex_lock(&tas->mtx);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 456) if (tas->drc_enabled == ucontrol->value.integer.value[0]) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 457) mutex_unlock(&tas->mtx);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 458) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 459) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 460)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 461) tas->drc_enabled = !!ucontrol->value.integer.value[0];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 462) if (tas->hw_enabled)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 463) tas3004_set_drc(tas);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 464) mutex_unlock(&tas->mtx);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 465) return 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 466) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 467)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 468) static const struct snd_kcontrol_new drc_switch_control = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 469) .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 470) .name = "DRC Range Switch",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 471) .access = SNDRV_CTL_ELEM_ACCESS_READWRITE,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 472) .info = tas_snd_drc_switch_info,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 473) .get = tas_snd_drc_switch_get,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 474) .put = tas_snd_drc_switch_put,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 475) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 476)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 477) static int tas_snd_capture_source_info(struct snd_kcontrol *kcontrol,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 478) struct snd_ctl_elem_info *uinfo)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 479) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 480) static const char * const texts[] = { "Line-In", "Microphone" };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 481)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 482) return snd_ctl_enum_info(uinfo, 1, 2, texts);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 483) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 484)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 485) static int tas_snd_capture_source_get(struct snd_kcontrol *kcontrol,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 486) struct snd_ctl_elem_value *ucontrol)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 487) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 488) struct tas *tas = snd_kcontrol_chip(kcontrol);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 489)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 490) mutex_lock(&tas->mtx);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 491) ucontrol->value.enumerated.item[0] = !!(tas->acr & TAS_ACR_INPUT_B);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 492) mutex_unlock(&tas->mtx);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 493) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 494) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 495)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 496) static int tas_snd_capture_source_put(struct snd_kcontrol *kcontrol,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 497) struct snd_ctl_elem_value *ucontrol)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 498) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 499) struct tas *tas = snd_kcontrol_chip(kcontrol);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 500) int oldacr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 501)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 502) if (ucontrol->value.enumerated.item[0] > 1)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 503) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 504) mutex_lock(&tas->mtx);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 505) oldacr = tas->acr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 506)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 507) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 508) * Despite what the data sheet says in one place, the
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 509) * TAS_ACR_B_MONAUREAL bit forces mono output even when
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 510) * input A (line in) is selected.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 511) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 512) tas->acr &= ~(TAS_ACR_INPUT_B | TAS_ACR_B_MONAUREAL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 513) if (ucontrol->value.enumerated.item[0])
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 514) tas->acr |= TAS_ACR_INPUT_B | TAS_ACR_B_MONAUREAL |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 515) TAS_ACR_B_MON_SEL_RIGHT;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 516) if (oldacr == tas->acr) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 517) mutex_unlock(&tas->mtx);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 518) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 519) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 520) if (tas->hw_enabled)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 521) tas_write_reg(tas, TAS_REG_ACR, 1, &tas->acr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 522) mutex_unlock(&tas->mtx);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 523) return 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 524) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 525)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 526) static const struct snd_kcontrol_new capture_source_control = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 527) .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 528) /* If we name this 'Input Source', it properly shows up in
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 529) * alsamixer as a selection, * but it's shown under the
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 530) * 'Playback' category.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 531) * If I name it 'Capture Source', it shows up in strange
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 532) * ways (two bools of which one can be selected at a
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 533) * time) but at least it's shown in the 'Capture'
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 534) * category.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 535) * I was told that this was due to backward compatibility,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 536) * but I don't understand then why the mangling is *not*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 537) * done when I name it "Input Source".....
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 538) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 539) .name = "Capture Source",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 540) .access = SNDRV_CTL_ELEM_ACCESS_READWRITE,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 541) .info = tas_snd_capture_source_info,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 542) .get = tas_snd_capture_source_get,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 543) .put = tas_snd_capture_source_put,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 544) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 545)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 546) static int tas_snd_treble_info(struct snd_kcontrol *kcontrol,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 547) struct snd_ctl_elem_info *uinfo)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 548) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 549) uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 550) uinfo->count = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 551) uinfo->value.integer.min = TAS3004_TREBLE_MIN;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 552) uinfo->value.integer.max = TAS3004_TREBLE_MAX;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 553) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 554) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 555)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 556) static int tas_snd_treble_get(struct snd_kcontrol *kcontrol,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 557) struct snd_ctl_elem_value *ucontrol)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 558) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 559) struct tas *tas = snd_kcontrol_chip(kcontrol);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 560)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 561) mutex_lock(&tas->mtx);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 562) ucontrol->value.integer.value[0] = tas->treble;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 563) mutex_unlock(&tas->mtx);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 564) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 565) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 566)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 567) static int tas_snd_treble_put(struct snd_kcontrol *kcontrol,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 568) struct snd_ctl_elem_value *ucontrol)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 569) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 570) struct tas *tas = snd_kcontrol_chip(kcontrol);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 571)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 572) if (ucontrol->value.integer.value[0] < TAS3004_TREBLE_MIN ||
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 573) ucontrol->value.integer.value[0] > TAS3004_TREBLE_MAX)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 574) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 575) mutex_lock(&tas->mtx);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 576) if (tas->treble == ucontrol->value.integer.value[0]) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 577) mutex_unlock(&tas->mtx);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 578) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 579) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 580)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 581) tas->treble = ucontrol->value.integer.value[0];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 582) if (tas->hw_enabled)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 583) tas_set_treble(tas);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 584) mutex_unlock(&tas->mtx);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 585) return 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 586) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 587)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 588) static const struct snd_kcontrol_new treble_control = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 589) .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 590) .name = "Treble",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 591) .access = SNDRV_CTL_ELEM_ACCESS_READWRITE,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 592) .info = tas_snd_treble_info,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 593) .get = tas_snd_treble_get,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 594) .put = tas_snd_treble_put,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 595) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 596)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 597) static int tas_snd_bass_info(struct snd_kcontrol *kcontrol,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 598) struct snd_ctl_elem_info *uinfo)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 599) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 600) uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 601) uinfo->count = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 602) uinfo->value.integer.min = TAS3004_BASS_MIN;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 603) uinfo->value.integer.max = TAS3004_BASS_MAX;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 604) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 605) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 606)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 607) static int tas_snd_bass_get(struct snd_kcontrol *kcontrol,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 608) struct snd_ctl_elem_value *ucontrol)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 609) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 610) struct tas *tas = snd_kcontrol_chip(kcontrol);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 611)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 612) mutex_lock(&tas->mtx);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 613) ucontrol->value.integer.value[0] = tas->bass;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 614) mutex_unlock(&tas->mtx);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 615) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 616) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 617)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 618) static int tas_snd_bass_put(struct snd_kcontrol *kcontrol,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 619) struct snd_ctl_elem_value *ucontrol)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 620) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 621) struct tas *tas = snd_kcontrol_chip(kcontrol);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 622)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 623) if (ucontrol->value.integer.value[0] < TAS3004_BASS_MIN ||
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 624) ucontrol->value.integer.value[0] > TAS3004_BASS_MAX)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 625) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 626) mutex_lock(&tas->mtx);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 627) if (tas->bass == ucontrol->value.integer.value[0]) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 628) mutex_unlock(&tas->mtx);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 629) return 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) tas->bass = ucontrol->value.integer.value[0];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 633) if (tas->hw_enabled)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 634) tas_set_bass(tas);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 635) mutex_unlock(&tas->mtx);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 636) return 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 637) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 638)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 639) static const struct snd_kcontrol_new bass_control = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 640) .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 641) .name = "Bass",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 642) .access = SNDRV_CTL_ELEM_ACCESS_READWRITE,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 643) .info = tas_snd_bass_info,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 644) .get = tas_snd_bass_get,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 645) .put = tas_snd_bass_put,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 646) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 647)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 648) static struct transfer_info tas_transfers[] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 649) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 650) /* input */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 651) .formats = SNDRV_PCM_FMTBIT_S16_BE | SNDRV_PCM_FMTBIT_S24_BE,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 652) .rates = SNDRV_PCM_RATE_32000 | SNDRV_PCM_RATE_44100 | SNDRV_PCM_RATE_48000,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 653) .transfer_in = 1,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 654) },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 655) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 656) /* output */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 657) .formats = SNDRV_PCM_FMTBIT_S16_BE | SNDRV_PCM_FMTBIT_S24_BE,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 658) .rates = SNDRV_PCM_RATE_32000 | SNDRV_PCM_RATE_44100 | SNDRV_PCM_RATE_48000,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 659) .transfer_in = 0,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 660) },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 661) {}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 662) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 663)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 664) static int tas_usable(struct codec_info_item *cii,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 665) struct transfer_info *ti,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 666) struct transfer_info *out)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 667) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 668) return 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 669) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 670)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 671) static int tas_reset_init(struct tas *tas)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 672) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 673) u8 tmp;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 674)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 675) tas->codec.gpio->methods->all_amps_off(tas->codec.gpio);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 676) msleep(5);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 677) tas->codec.gpio->methods->set_hw_reset(tas->codec.gpio, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 678) msleep(5);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 679) tas->codec.gpio->methods->set_hw_reset(tas->codec.gpio, 1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 680) msleep(20);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 681) tas->codec.gpio->methods->set_hw_reset(tas->codec.gpio, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 682) msleep(10);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 683) tas->codec.gpio->methods->all_amps_restore(tas->codec.gpio);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 684)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 685) tmp = TAS_MCS_SCLK64 | TAS_MCS_SPORT_MODE_I2S | TAS_MCS_SPORT_WL_24BIT;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 686) if (tas_write_reg(tas, TAS_REG_MCS, 1, &tmp))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 687) goto outerr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 688)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 689) tas->acr |= TAS_ACR_ANALOG_PDOWN;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 690) if (tas_write_reg(tas, TAS_REG_ACR, 1, &tas->acr))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 691) goto outerr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 692)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 693) tmp = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 694) if (tas_write_reg(tas, TAS_REG_MCS2, 1, &tmp))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 695) goto outerr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 696)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 697) tas3004_set_drc(tas);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 698)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 699) /* Set treble & bass to 0dB */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 700) tas->treble = TAS3004_TREBLE_ZERO;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 701) tas->bass = TAS3004_BASS_ZERO;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 702) tas_set_treble(tas);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 703) tas_set_bass(tas);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 704)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 705) tas->acr &= ~TAS_ACR_ANALOG_PDOWN;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 706) if (tas_write_reg(tas, TAS_REG_ACR, 1, &tas->acr))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 707) goto outerr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 708)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 709) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 710) outerr:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 711) return -ENODEV;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 712) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 713)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 714) static int tas_switch_clock(struct codec_info_item *cii, enum clock_switch clock)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 715) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 716) struct tas *tas = cii->codec_data;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 717)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 718) switch(clock) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 719) case CLOCK_SWITCH_PREPARE_SLAVE:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 720) /* Clocks are going away, mute mute mute */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 721) tas->codec.gpio->methods->all_amps_off(tas->codec.gpio);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 722) tas->hw_enabled = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 723) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 724) case CLOCK_SWITCH_SLAVE:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 725) /* Clocks are back, re-init the codec */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 726) mutex_lock(&tas->mtx);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 727) tas_reset_init(tas);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 728) tas_set_volume(tas);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 729) tas_set_mixer(tas);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 730) tas->hw_enabled = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 731) tas->codec.gpio->methods->all_amps_restore(tas->codec.gpio);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 732) mutex_unlock(&tas->mtx);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 733) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 734) default:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 735) /* doesn't happen as of now */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 736) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 737) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 738) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 739) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 740)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 741) #ifdef CONFIG_PM
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 742) /* we are controlled via i2c and assume that is always up
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 743) * If that wasn't the case, we'd have to suspend once
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 744) * our i2c device is suspended, and then take note of that! */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 745) static int tas_suspend(struct tas *tas)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 746) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 747) mutex_lock(&tas->mtx);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 748) tas->hw_enabled = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 749) tas->acr |= TAS_ACR_ANALOG_PDOWN;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 750) tas_write_reg(tas, TAS_REG_ACR, 1, &tas->acr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 751) mutex_unlock(&tas->mtx);
^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 tas_resume(struct tas *tas)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 756) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 757) /* reset codec */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 758) mutex_lock(&tas->mtx);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 759) tas_reset_init(tas);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 760) tas_set_volume(tas);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 761) tas_set_mixer(tas);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 762) tas->hw_enabled = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 763) mutex_unlock(&tas->mtx);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 764) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 765) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 766)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 767) static int _tas_suspend(struct codec_info_item *cii, pm_message_t state)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 768) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 769) return tas_suspend(cii->codec_data);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 770) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 771)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 772) static int _tas_resume(struct codec_info_item *cii)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 773) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 774) return tas_resume(cii->codec_data);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 775) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 776) #else /* CONFIG_PM */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 777) #define _tas_suspend NULL
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 778) #define _tas_resume NULL
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 779) #endif /* CONFIG_PM */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 780)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 781) static struct codec_info tas_codec_info = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 782) .transfers = tas_transfers,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 783) /* in theory, we can drive it at 512 too...
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 784) * but so far the framework doesn't allow
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 785) * for that and I don't see much point in it. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 786) .sysclock_factor = 256,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 787) /* same here, could be 32 for just one 16 bit format */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 788) .bus_factor = 64,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 789) .owner = THIS_MODULE,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 790) .usable = tas_usable,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 791) .switch_clock = tas_switch_clock,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 792) .suspend = _tas_suspend,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 793) .resume = _tas_resume,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 794) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 795)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 796) static int tas_init_codec(struct aoa_codec *codec)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 797) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 798) struct tas *tas = codec_to_tas(codec);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 799) int err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 800)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 801) if (!tas->codec.gpio || !tas->codec.gpio->methods) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 802) printk(KERN_ERR PFX "gpios not assigned!!\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 803) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 804) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 805)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 806) mutex_lock(&tas->mtx);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 807) if (tas_reset_init(tas)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 808) printk(KERN_ERR PFX "tas failed to initialise\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 809) mutex_unlock(&tas->mtx);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 810) return -ENXIO;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 811) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 812) tas->hw_enabled = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 813) mutex_unlock(&tas->mtx);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 814)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 815) if (tas->codec.soundbus_dev->attach_codec(tas->codec.soundbus_dev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 816) aoa_get_card(),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 817) &tas_codec_info, tas)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 818) printk(KERN_ERR PFX "error attaching tas to soundbus\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 819) return -ENODEV;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 820) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 821)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 822) if (aoa_snd_device_new(SNDRV_DEV_CODEC, tas, &ops)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 823) printk(KERN_ERR PFX "failed to create tas snd device!\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 824) return -ENODEV;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 825) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 826) err = aoa_snd_ctl_add(snd_ctl_new1(&volume_control, tas));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 827) if (err)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 828) goto error;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 829)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 830) err = aoa_snd_ctl_add(snd_ctl_new1(&mute_control, tas));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 831) if (err)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 832) goto error;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 833)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 834) err = aoa_snd_ctl_add(snd_ctl_new1(&pcm1_control, tas));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 835) if (err)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 836) goto error;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 837)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 838) err = aoa_snd_ctl_add(snd_ctl_new1(&monitor_control, tas));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 839) if (err)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 840) goto error;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 841)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 842) err = aoa_snd_ctl_add(snd_ctl_new1(&capture_source_control, tas));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 843) if (err)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 844) goto error;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 845)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 846) err = aoa_snd_ctl_add(snd_ctl_new1(&drc_range_control, tas));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 847) if (err)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 848) goto error;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 849)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 850) err = aoa_snd_ctl_add(snd_ctl_new1(&drc_switch_control, tas));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 851) if (err)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 852) goto error;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 853)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 854) err = aoa_snd_ctl_add(snd_ctl_new1(&treble_control, tas));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 855) if (err)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 856) goto error;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 857)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 858) err = aoa_snd_ctl_add(snd_ctl_new1(&bass_control, tas));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 859) if (err)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 860) goto error;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 861)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 862) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 863) error:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 864) tas->codec.soundbus_dev->detach_codec(tas->codec.soundbus_dev, tas);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 865) snd_device_free(aoa_get_card(), tas);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 866) return err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 867) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 868)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 869) static void tas_exit_codec(struct aoa_codec *codec)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 870) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 871) struct tas *tas = codec_to_tas(codec);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 872)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 873) if (!tas->codec.soundbus_dev)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 874) return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 875) tas->codec.soundbus_dev->detach_codec(tas->codec.soundbus_dev, tas);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 876) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 877)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 878)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 879) static int tas_i2c_probe(struct i2c_client *client,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 880) const struct i2c_device_id *id)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 881) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 882) struct device_node *node = client->dev.of_node;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 883) struct tas *tas;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 884)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 885) tas = kzalloc(sizeof(struct tas), GFP_KERNEL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 886)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 887) if (!tas)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 888) return -ENOMEM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 889)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 890) mutex_init(&tas->mtx);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 891) tas->i2c = client;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 892) i2c_set_clientdata(client, tas);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 893)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 894) /* seems that half is a saner default */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 895) tas->drc_range = TAS3004_DRC_MAX / 2;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 896)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 897) strlcpy(tas->codec.name, "tas", MAX_CODEC_NAME_LEN);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 898) tas->codec.owner = THIS_MODULE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 899) tas->codec.init = tas_init_codec;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 900) tas->codec.exit = tas_exit_codec;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 901) tas->codec.node = of_node_get(node);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 902)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 903) if (aoa_codec_register(&tas->codec)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 904) goto fail;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 905) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 906) printk(KERN_DEBUG
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 907) "snd-aoa-codec-tas: tas found, addr 0x%02x on %pOF\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 908) (unsigned int)client->addr, node);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 909) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 910) fail:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 911) mutex_destroy(&tas->mtx);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 912) kfree(tas);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 913) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 914) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 915)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 916) static int tas_i2c_remove(struct i2c_client *client)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 917) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 918) struct tas *tas = i2c_get_clientdata(client);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 919) u8 tmp = TAS_ACR_ANALOG_PDOWN;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 920)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 921) aoa_codec_unregister(&tas->codec);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 922) of_node_put(tas->codec.node);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 923)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 924) /* power down codec chip */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 925) tas_write_reg(tas, TAS_REG_ACR, 1, &tmp);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 926)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 927) mutex_destroy(&tas->mtx);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 928) kfree(tas);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 929) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 930) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 931)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 932) static const struct i2c_device_id tas_i2c_id[] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 933) { "MAC,tas3004", 0 },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 934) { }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 935) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 936) MODULE_DEVICE_TABLE(i2c,tas_i2c_id);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 937)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 938) static struct i2c_driver tas_driver = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 939) .driver = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 940) .name = "aoa_codec_tas",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 941) },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 942) .probe = tas_i2c_probe,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 943) .remove = tas_i2c_remove,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 944) .id_table = tas_i2c_id,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 945) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 946)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 947) module_i2c_driver(tas_driver);