^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1) // SPDX-License-Identifier: GPL-2.0-or-later
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3) * PMac Tumbler/Snapper lowlevel functions
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5) * Copyright (c) by Takashi Iwai <tiwai@suse.de>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7) * Rene Rebe <rene.rebe@gmx.net>:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8) * * update from shadow registers on wakeup and headphone plug
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9) * * automatically toggle DRC on headphone plug
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13) #include <linux/init.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14) #include <linux/delay.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 15) #include <linux/i2c.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 16) #include <linux/kmod.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 17) #include <linux/slab.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 18) #include <linux/interrupt.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 19) #include <linux/string.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 20) #include <linux/of_irq.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 21) #include <linux/io.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 22) #include <sound/core.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 23) #include <asm/irq.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 24) #include <asm/machdep.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 25) #include <asm/pmac_feature.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 26) #include "pmac.h"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 27) #include "tumbler_volume.h"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 28)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 29) #undef DEBUG
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 30)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 31) #ifdef DEBUG
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 32) #define DBG(fmt...) printk(KERN_DEBUG fmt)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 33) #else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 34) #define DBG(fmt...)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 35) #endif
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 36)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 37) #define IS_G4DA (of_machine_is_compatible("PowerMac3,4"))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 38)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 39) /* i2c address for tumbler */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 40) #define TAS_I2C_ADDR 0x34
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 41)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 42) /* registers */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 43) #define TAS_REG_MCS 0x01 /* main control */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 44) #define TAS_REG_DRC 0x02
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 45) #define TAS_REG_VOL 0x04
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 46) #define TAS_REG_TREBLE 0x05
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 47) #define TAS_REG_BASS 0x06
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 48) #define TAS_REG_INPUT1 0x07
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 49) #define TAS_REG_INPUT2 0x08
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 50)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 51) /* tas3001c */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 52) #define TAS_REG_PCM TAS_REG_INPUT1
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 53)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 54) /* tas3004 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 55) #define TAS_REG_LMIX TAS_REG_INPUT1
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 56) #define TAS_REG_RMIX TAS_REG_INPUT2
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 57) #define TAS_REG_MCS2 0x43 /* main control 2 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 58) #define TAS_REG_ACS 0x40 /* analog control */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 59)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 60) /* mono volumes for tas3001c/tas3004 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 61) enum {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 62) VOL_IDX_PCM_MONO, /* tas3001c only */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 63) VOL_IDX_BASS, VOL_IDX_TREBLE,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 64) VOL_IDX_LAST_MONO
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 65) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 66)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 67) /* stereo volumes for tas3004 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 68) enum {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 69) VOL_IDX_PCM, VOL_IDX_PCM2, VOL_IDX_ADC,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 70) VOL_IDX_LAST_MIX
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 71) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 72)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 73) struct pmac_gpio {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 74) unsigned int addr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 75) u8 active_val;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 76) u8 inactive_val;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 77) u8 active_state;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 78) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 79)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 80) struct pmac_tumbler {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 81) struct pmac_keywest i2c;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 82) struct pmac_gpio audio_reset;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 83) struct pmac_gpio amp_mute;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 84) struct pmac_gpio line_mute;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 85) struct pmac_gpio line_detect;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 86) struct pmac_gpio hp_mute;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 87) struct pmac_gpio hp_detect;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 88) int headphone_irq;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 89) int lineout_irq;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 90) unsigned int save_master_vol[2];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 91) unsigned int master_vol[2];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 92) unsigned int save_master_switch[2];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 93) unsigned int master_switch[2];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 94) unsigned int mono_vol[VOL_IDX_LAST_MONO];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 95) unsigned int mix_vol[VOL_IDX_LAST_MIX][2]; /* stereo volumes for tas3004 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 96) int drc_range;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 97) int drc_enable;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 98) int capture_source;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 99) int anded_reset;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 100) int auto_mute_notify;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 101) int reset_on_sleep;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 102) u8 acs;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 103) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 104)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 105)
^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)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 109) static int send_init_client(struct pmac_keywest *i2c, const unsigned int *regs)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 110) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 111) while (*regs > 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 112) int err, count = 10;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 113) do {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 114) err = i2c_smbus_write_byte_data(i2c->client,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 115) regs[0], regs[1]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 116) if (err >= 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 117) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 118) DBG("(W) i2c error %d\n", err);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 119) mdelay(10);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 120) } while (count--);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 121) if (err < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 122) return -ENXIO;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 123) regs += 2;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 124) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 125) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 126) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 127)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 128)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 129) static int tumbler_init_client(struct pmac_keywest *i2c)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 130) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 131) static const unsigned int regs[] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 132) /* normal operation, SCLK=64fps, i2s output, i2s input, 16bit width */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 133) TAS_REG_MCS, (1<<6)|(2<<4)|(2<<2)|0,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 134) 0, /* terminator */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 135) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 136) DBG("(I) tumbler init client\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 137) return send_init_client(i2c, regs);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 138) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 139)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 140) static int snapper_init_client(struct pmac_keywest *i2c)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 141) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 142) static const unsigned int regs[] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 143) /* normal operation, SCLK=64fps, i2s output, 16bit width */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 144) TAS_REG_MCS, (1<<6)|(2<<4)|0,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 145) /* normal operation, all-pass mode */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 146) TAS_REG_MCS2, (1<<1),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 147) /* normal output, no deemphasis, A input, power-up, line-in */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 148) TAS_REG_ACS, 0,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 149) 0, /* terminator */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 150) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 151) DBG("(I) snapper init client\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 152) return send_init_client(i2c, regs);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 153) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 154)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 155) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 156) * gpio access
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 157) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 158) #define do_gpio_write(gp, val) \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 159) pmac_call_feature(PMAC_FTR_WRITE_GPIO, NULL, (gp)->addr, val)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 160) #define do_gpio_read(gp) \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 161) pmac_call_feature(PMAC_FTR_READ_GPIO, NULL, (gp)->addr, 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 162) #define tumbler_gpio_free(gp) /* NOP */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 163)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 164) static void write_audio_gpio(struct pmac_gpio *gp, int active)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 165) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 166) if (! gp->addr)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 167) return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 168) active = active ? gp->active_val : gp->inactive_val;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 169) do_gpio_write(gp, active);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 170) DBG("(I) gpio %x write %d\n", gp->addr, active);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 171) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 172)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 173) static int check_audio_gpio(struct pmac_gpio *gp)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 174) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 175) int ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 176)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 177) if (! gp->addr)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 178) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 179)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 180) ret = do_gpio_read(gp);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 181)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 182) return (ret & 0x1) == (gp->active_val & 0x1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 183) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 184)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 185) static int read_audio_gpio(struct pmac_gpio *gp)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 186) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 187) int ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 188) if (! gp->addr)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 189) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 190) ret = do_gpio_read(gp);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 191) ret = (ret & 0x02) !=0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 192) return ret == gp->active_state;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 193) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 194)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 195) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 196) * update master volume
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 197) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 198) static int tumbler_set_master_volume(struct pmac_tumbler *mix)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 199) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 200) unsigned char block[6];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 201) unsigned int left_vol, right_vol;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 202)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 203) if (! mix->i2c.client)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 204) return -ENODEV;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 205)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 206) if (! mix->master_switch[0])
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 207) left_vol = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 208) else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 209) left_vol = mix->master_vol[0];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 210) if (left_vol >= ARRAY_SIZE(master_volume_table))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 211) left_vol = ARRAY_SIZE(master_volume_table) - 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 212) left_vol = master_volume_table[left_vol];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 213) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 214) if (! mix->master_switch[1])
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 215) right_vol = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 216) else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 217) right_vol = mix->master_vol[1];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 218) if (right_vol >= ARRAY_SIZE(master_volume_table))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 219) right_vol = ARRAY_SIZE(master_volume_table) - 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 220) right_vol = master_volume_table[right_vol];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 221) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 222)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 223) block[0] = (left_vol >> 16) & 0xff;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 224) block[1] = (left_vol >> 8) & 0xff;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 225) block[2] = (left_vol >> 0) & 0xff;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 226)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 227) block[3] = (right_vol >> 16) & 0xff;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 228) block[4] = (right_vol >> 8) & 0xff;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 229) block[5] = (right_vol >> 0) & 0xff;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 230)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 231) if (i2c_smbus_write_i2c_block_data(mix->i2c.client, TAS_REG_VOL, 6,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 232) block) < 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 233) snd_printk(KERN_ERR "failed to set volume \n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 234) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 235) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 236) DBG("(I) succeeded to set volume (%u, %u)\n", left_vol, right_vol);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 237) return 0;
^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)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 241) /* output volume */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 242) static int tumbler_info_master_volume(struct snd_kcontrol *kcontrol,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 243) struct snd_ctl_elem_info *uinfo)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 244) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 245) uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 246) uinfo->count = 2;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 247) uinfo->value.integer.min = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 248) uinfo->value.integer.max = ARRAY_SIZE(master_volume_table) - 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 249) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 250) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 251)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 252) static int tumbler_get_master_volume(struct snd_kcontrol *kcontrol,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 253) struct snd_ctl_elem_value *ucontrol)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 254) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 255) struct snd_pmac *chip = snd_kcontrol_chip(kcontrol);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 256) struct pmac_tumbler *mix = chip->mixer_data;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 257)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 258) ucontrol->value.integer.value[0] = mix->master_vol[0];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 259) ucontrol->value.integer.value[1] = mix->master_vol[1];
^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 int tumbler_put_master_volume(struct snd_kcontrol *kcontrol,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 264) struct snd_ctl_elem_value *ucontrol)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 265) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 266) struct snd_pmac *chip = snd_kcontrol_chip(kcontrol);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 267) struct pmac_tumbler *mix = chip->mixer_data;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 268) unsigned int vol[2];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 269) int change;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 270)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 271) vol[0] = ucontrol->value.integer.value[0];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 272) vol[1] = ucontrol->value.integer.value[1];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 273) if (vol[0] >= ARRAY_SIZE(master_volume_table) ||
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 274) vol[1] >= ARRAY_SIZE(master_volume_table))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 275) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 276) change = mix->master_vol[0] != vol[0] ||
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 277) mix->master_vol[1] != vol[1];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 278) if (change) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 279) mix->master_vol[0] = vol[0];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 280) mix->master_vol[1] = vol[1];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 281) tumbler_set_master_volume(mix);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 282) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 283) return change;
^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) /* output switch */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 287) static int tumbler_get_master_switch(struct snd_kcontrol *kcontrol,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 288) struct snd_ctl_elem_value *ucontrol)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 289) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 290) struct snd_pmac *chip = snd_kcontrol_chip(kcontrol);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 291) struct pmac_tumbler *mix = chip->mixer_data;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 292)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 293) ucontrol->value.integer.value[0] = mix->master_switch[0];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 294) ucontrol->value.integer.value[1] = mix->master_switch[1];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 295) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 296) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 297)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 298) static int tumbler_put_master_switch(struct snd_kcontrol *kcontrol,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 299) struct snd_ctl_elem_value *ucontrol)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 300) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 301) struct snd_pmac *chip = snd_kcontrol_chip(kcontrol);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 302) struct pmac_tumbler *mix = chip->mixer_data;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 303) int change;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 304)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 305) change = mix->master_switch[0] != ucontrol->value.integer.value[0] ||
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 306) mix->master_switch[1] != ucontrol->value.integer.value[1];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 307) if (change) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 308) mix->master_switch[0] = !!ucontrol->value.integer.value[0];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 309) mix->master_switch[1] = !!ucontrol->value.integer.value[1];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 310) tumbler_set_master_volume(mix);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 311) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 312) return change;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 313) }
^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) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 317) * TAS3001c dynamic range compression
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 318) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 319)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 320) #define TAS3001_DRC_MAX 0x5f
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 321)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 322) static int tumbler_set_drc(struct pmac_tumbler *mix)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 323) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 324) unsigned char val[2];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 325)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 326) if (! mix->i2c.client)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 327) return -ENODEV;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 328)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 329) if (mix->drc_enable) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 330) val[0] = 0xc1; /* enable, 3:1 compression */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 331) if (mix->drc_range > TAS3001_DRC_MAX)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 332) val[1] = 0xf0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 333) else if (mix->drc_range < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 334) val[1] = 0x91;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 335) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 336) val[1] = mix->drc_range + 0x91;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 337) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 338) val[0] = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 339) val[1] = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 340) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 341)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 342) if (i2c_smbus_write_i2c_block_data(mix->i2c.client, TAS_REG_DRC,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 343) 2, val) < 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 344) snd_printk(KERN_ERR "failed to set DRC\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 345) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 346) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 347) DBG("(I) succeeded to set DRC (%u, %u)\n", val[0], val[1]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 348) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 349) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 350)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 351) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 352) * TAS3004
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 353) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 354)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 355) #define TAS3004_DRC_MAX 0xef
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 356)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 357) static int snapper_set_drc(struct pmac_tumbler *mix)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 358) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 359) unsigned char val[6];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 360)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 361) if (! mix->i2c.client)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 362) return -ENODEV;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 363)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 364) if (mix->drc_enable)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 365) val[0] = 0x50; /* 3:1 above threshold */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 366) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 367) val[0] = 0x51; /* disabled */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 368) val[1] = 0x02; /* 1:1 below threshold */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 369) if (mix->drc_range > 0xef)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 370) val[2] = 0xef;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 371) else if (mix->drc_range < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 372) val[2] = 0x00;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 373) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 374) val[2] = mix->drc_range;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 375) val[3] = 0xb0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 376) val[4] = 0x60;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 377) val[5] = 0xa0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 378)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 379) if (i2c_smbus_write_i2c_block_data(mix->i2c.client, TAS_REG_DRC,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 380) 6, val) < 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 381) snd_printk(KERN_ERR "failed to set DRC\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 382) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 383) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 384) DBG("(I) succeeded to set DRC (%u, %u)\n", val[0], val[1]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 385) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 386) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 387)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 388) static int tumbler_info_drc_value(struct snd_kcontrol *kcontrol,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 389) struct snd_ctl_elem_info *uinfo)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 390) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 391) struct snd_pmac *chip = snd_kcontrol_chip(kcontrol);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 392) uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 393) uinfo->count = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 394) uinfo->value.integer.min = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 395) uinfo->value.integer.max =
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 396) chip->model == PMAC_TUMBLER ? TAS3001_DRC_MAX : TAS3004_DRC_MAX;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 397) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 398) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 399)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 400) static int tumbler_get_drc_value(struct snd_kcontrol *kcontrol,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 401) struct snd_ctl_elem_value *ucontrol)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 402) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 403) struct snd_pmac *chip = snd_kcontrol_chip(kcontrol);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 404) struct pmac_tumbler *mix;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 405) if (! (mix = chip->mixer_data))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 406) return -ENODEV;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 407) ucontrol->value.integer.value[0] = mix->drc_range;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 408) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 409) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 410)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 411) static int tumbler_put_drc_value(struct snd_kcontrol *kcontrol,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 412) struct snd_ctl_elem_value *ucontrol)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 413) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 414) struct snd_pmac *chip = snd_kcontrol_chip(kcontrol);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 415) struct pmac_tumbler *mix;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 416) unsigned int val;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 417) int change;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 418)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 419) if (! (mix = chip->mixer_data))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 420) return -ENODEV;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 421) val = ucontrol->value.integer.value[0];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 422) if (chip->model == PMAC_TUMBLER) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 423) if (val > TAS3001_DRC_MAX)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 424) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 425) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 426) if (val > TAS3004_DRC_MAX)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 427) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 428) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 429) change = mix->drc_range != val;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 430) if (change) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 431) mix->drc_range = val;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 432) if (chip->model == PMAC_TUMBLER)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 433) tumbler_set_drc(mix);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 434) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 435) snapper_set_drc(mix);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 436) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 437) return change;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 438) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 439)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 440) static int tumbler_get_drc_switch(struct snd_kcontrol *kcontrol,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 441) struct snd_ctl_elem_value *ucontrol)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 442) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 443) struct snd_pmac *chip = snd_kcontrol_chip(kcontrol);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 444) struct pmac_tumbler *mix;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 445) if (! (mix = chip->mixer_data))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 446) return -ENODEV;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 447) ucontrol->value.integer.value[0] = mix->drc_enable;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 448) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 449) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 450)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 451) static int tumbler_put_drc_switch(struct snd_kcontrol *kcontrol,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 452) struct snd_ctl_elem_value *ucontrol)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 453) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 454) struct snd_pmac *chip = snd_kcontrol_chip(kcontrol);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 455) struct pmac_tumbler *mix;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 456) int change;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 457)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 458) if (! (mix = chip->mixer_data))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 459) return -ENODEV;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 460) change = mix->drc_enable != ucontrol->value.integer.value[0];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 461) if (change) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 462) mix->drc_enable = !!ucontrol->value.integer.value[0];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 463) if (chip->model == PMAC_TUMBLER)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 464) tumbler_set_drc(mix);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 465) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 466) snapper_set_drc(mix);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 467) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 468) return change;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 469) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 470)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 471)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 472) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 473) * mono volumes
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 474) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 475)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 476) struct tumbler_mono_vol {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 477) int index;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 478) int reg;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 479) int bytes;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 480) unsigned int max;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 481) const unsigned int *table;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 482) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 483)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 484) static int tumbler_set_mono_volume(struct pmac_tumbler *mix,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 485) const struct tumbler_mono_vol *info)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 486) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 487) unsigned char block[4];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 488) unsigned int vol;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 489) int i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 490)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 491) if (! mix->i2c.client)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 492) return -ENODEV;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 493)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 494) vol = mix->mono_vol[info->index];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 495) if (vol >= info->max)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 496) vol = info->max - 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 497) vol = info->table[vol];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 498) for (i = 0; i < info->bytes; i++)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 499) block[i] = (vol >> ((info->bytes - i - 1) * 8)) & 0xff;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 500) if (i2c_smbus_write_i2c_block_data(mix->i2c.client, info->reg,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 501) info->bytes, block) < 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 502) snd_printk(KERN_ERR "failed to set mono volume %d\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 503) info->index);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 504) return -EINVAL;
^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 tumbler_info_mono(struct snd_kcontrol *kcontrol,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 510) struct snd_ctl_elem_info *uinfo)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 511) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 512) struct tumbler_mono_vol *info = (struct tumbler_mono_vol *)kcontrol->private_value;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 513)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 514) uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 515) uinfo->count = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 516) uinfo->value.integer.min = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 517) uinfo->value.integer.max = info->max - 1;
^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)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 521) static int tumbler_get_mono(struct snd_kcontrol *kcontrol,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 522) struct snd_ctl_elem_value *ucontrol)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 523) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 524) struct tumbler_mono_vol *info = (struct tumbler_mono_vol *)kcontrol->private_value;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 525) struct snd_pmac *chip = snd_kcontrol_chip(kcontrol);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 526) struct pmac_tumbler *mix;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 527) if (! (mix = chip->mixer_data))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 528) return -ENODEV;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 529) ucontrol->value.integer.value[0] = mix->mono_vol[info->index];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 530) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 531) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 532)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 533) static int tumbler_put_mono(struct snd_kcontrol *kcontrol,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 534) struct snd_ctl_elem_value *ucontrol)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 535) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 536) struct tumbler_mono_vol *info = (struct tumbler_mono_vol *)kcontrol->private_value;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 537) struct snd_pmac *chip = snd_kcontrol_chip(kcontrol);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 538) struct pmac_tumbler *mix;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 539) unsigned int vol;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 540) int change;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 541)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 542) if (! (mix = chip->mixer_data))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 543) return -ENODEV;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 544) vol = ucontrol->value.integer.value[0];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 545) if (vol >= info->max)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 546) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 547) change = mix->mono_vol[info->index] != vol;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 548) if (change) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 549) mix->mono_vol[info->index] = vol;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 550) tumbler_set_mono_volume(mix, info);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 551) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 552) return change;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 553) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 554)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 555) /* TAS3001c mono volumes */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 556) static const struct tumbler_mono_vol tumbler_pcm_vol_info = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 557) .index = VOL_IDX_PCM_MONO,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 558) .reg = TAS_REG_PCM,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 559) .bytes = 3,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 560) .max = ARRAY_SIZE(mixer_volume_table),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 561) .table = mixer_volume_table,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 562) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 563)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 564) static const struct tumbler_mono_vol tumbler_bass_vol_info = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 565) .index = VOL_IDX_BASS,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 566) .reg = TAS_REG_BASS,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 567) .bytes = 1,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 568) .max = ARRAY_SIZE(bass_volume_table),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 569) .table = bass_volume_table,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 570) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 571)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 572) static const struct tumbler_mono_vol tumbler_treble_vol_info = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 573) .index = VOL_IDX_TREBLE,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 574) .reg = TAS_REG_TREBLE,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 575) .bytes = 1,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 576) .max = ARRAY_SIZE(treble_volume_table),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 577) .table = treble_volume_table,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 578) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 579)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 580) /* TAS3004 mono volumes */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 581) static const struct tumbler_mono_vol snapper_bass_vol_info = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 582) .index = VOL_IDX_BASS,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 583) .reg = TAS_REG_BASS,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 584) .bytes = 1,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 585) .max = ARRAY_SIZE(snapper_bass_volume_table),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 586) .table = snapper_bass_volume_table,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 587) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 588)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 589) static const struct tumbler_mono_vol snapper_treble_vol_info = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 590) .index = VOL_IDX_TREBLE,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 591) .reg = TAS_REG_TREBLE,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 592) .bytes = 1,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 593) .max = ARRAY_SIZE(snapper_treble_volume_table),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 594) .table = snapper_treble_volume_table,
^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)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 598) #define DEFINE_MONO(xname,type) { \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 599) .iface = SNDRV_CTL_ELEM_IFACE_MIXER,\
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 600) .name = xname, \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 601) .info = tumbler_info_mono, \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 602) .get = tumbler_get_mono, \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 603) .put = tumbler_put_mono, \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 604) .private_value = (unsigned long)(&tumbler_##type##_vol_info), \
^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) #define DEFINE_SNAPPER_MONO(xname,type) { \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 608) .iface = SNDRV_CTL_ELEM_IFACE_MIXER,\
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 609) .name = xname, \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 610) .info = tumbler_info_mono, \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 611) .get = tumbler_get_mono, \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 612) .put = tumbler_put_mono, \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 613) .private_value = (unsigned long)(&snapper_##type##_vol_info), \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 614) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 615)
^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) * snapper mixer volumes
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 619) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 620)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 621) static int snapper_set_mix_vol1(struct pmac_tumbler *mix, int idx, int ch, int reg)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 622) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 623) int i, j, vol;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 624) unsigned char block[9];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 625)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 626) vol = mix->mix_vol[idx][ch];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 627) if (vol >= ARRAY_SIZE(mixer_volume_table)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 628) vol = ARRAY_SIZE(mixer_volume_table) - 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 629) mix->mix_vol[idx][ch] = vol;
^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) for (i = 0; i < 3; i++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 633) vol = mix->mix_vol[i][ch];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 634) vol = mixer_volume_table[vol];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 635) for (j = 0; j < 3; j++)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 636) block[i * 3 + j] = (vol >> ((2 - j) * 8)) & 0xff;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 637) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 638) if (i2c_smbus_write_i2c_block_data(mix->i2c.client, reg,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 639) 9, block) < 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 640) snd_printk(KERN_ERR "failed to set mono volume %d\n", reg);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 641) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 642) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 643) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 644) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 645)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 646) static int snapper_set_mix_vol(struct pmac_tumbler *mix, int idx)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 647) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 648) if (! mix->i2c.client)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 649) return -ENODEV;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 650) if (snapper_set_mix_vol1(mix, idx, 0, TAS_REG_LMIX) < 0 ||
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 651) snapper_set_mix_vol1(mix, idx, 1, TAS_REG_RMIX) < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 652) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 653) return 0;
^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) static int snapper_info_mix(struct snd_kcontrol *kcontrol,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 657) struct snd_ctl_elem_info *uinfo)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 658) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 659) uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 660) uinfo->count = 2;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 661) uinfo->value.integer.min = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 662) uinfo->value.integer.max = ARRAY_SIZE(mixer_volume_table) - 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 663) return 0;
^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) static int snapper_get_mix(struct snd_kcontrol *kcontrol,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 667) struct snd_ctl_elem_value *ucontrol)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 668) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 669) int idx = (int)kcontrol->private_value;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 670) struct snd_pmac *chip = snd_kcontrol_chip(kcontrol);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 671) struct pmac_tumbler *mix;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 672) if (! (mix = chip->mixer_data))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 673) return -ENODEV;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 674) ucontrol->value.integer.value[0] = mix->mix_vol[idx][0];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 675) ucontrol->value.integer.value[1] = mix->mix_vol[idx][1];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 676) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 677) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 678)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 679) static int snapper_put_mix(struct snd_kcontrol *kcontrol,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 680) struct snd_ctl_elem_value *ucontrol)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 681) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 682) int idx = (int)kcontrol->private_value;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 683) struct snd_pmac *chip = snd_kcontrol_chip(kcontrol);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 684) struct pmac_tumbler *mix;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 685) unsigned int vol[2];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 686) int change;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 687)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 688) if (! (mix = chip->mixer_data))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 689) return -ENODEV;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 690) vol[0] = ucontrol->value.integer.value[0];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 691) vol[1] = ucontrol->value.integer.value[1];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 692) if (vol[0] >= ARRAY_SIZE(mixer_volume_table) ||
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 693) vol[1] >= ARRAY_SIZE(mixer_volume_table))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 694) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 695) change = mix->mix_vol[idx][0] != vol[0] ||
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 696) mix->mix_vol[idx][1] != vol[1];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 697) if (change) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 698) mix->mix_vol[idx][0] = vol[0];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 699) mix->mix_vol[idx][1] = vol[1];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 700) snapper_set_mix_vol(mix, idx);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 701) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 702) return change;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 703) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 704)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 705)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 706) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 707) * mute switches. FIXME: Turn that into software mute when both outputs are muted
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 708) * to avoid codec reset on ibook M7
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 709) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 710)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 711) enum { TUMBLER_MUTE_HP, TUMBLER_MUTE_AMP, TUMBLER_MUTE_LINE };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 712)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 713) static int tumbler_get_mute_switch(struct snd_kcontrol *kcontrol,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 714) struct snd_ctl_elem_value *ucontrol)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 715) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 716) struct snd_pmac *chip = snd_kcontrol_chip(kcontrol);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 717) struct pmac_tumbler *mix;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 718) struct pmac_gpio *gp;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 719) if (! (mix = chip->mixer_data))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 720) return -ENODEV;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 721) switch(kcontrol->private_value) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 722) case TUMBLER_MUTE_HP:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 723) gp = &mix->hp_mute; break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 724) case TUMBLER_MUTE_AMP:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 725) gp = &mix->amp_mute; break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 726) case TUMBLER_MUTE_LINE:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 727) gp = &mix->line_mute; break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 728) default:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 729) gp = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 730) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 731) if (gp == NULL)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 732) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 733) ucontrol->value.integer.value[0] = !check_audio_gpio(gp);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 734) return 0;
^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) static int tumbler_put_mute_switch(struct snd_kcontrol *kcontrol,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 738) struct snd_ctl_elem_value *ucontrol)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 739) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 740) struct snd_pmac *chip = snd_kcontrol_chip(kcontrol);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 741) struct pmac_tumbler *mix;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 742) struct pmac_gpio *gp;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 743) int val;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 744) #ifdef PMAC_SUPPORT_AUTOMUTE
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 745) if (chip->update_automute && chip->auto_mute)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 746) return 0; /* don't touch in the auto-mute mode */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 747) #endif
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 748) if (! (mix = chip->mixer_data))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 749) return -ENODEV;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 750) switch(kcontrol->private_value) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 751) case TUMBLER_MUTE_HP:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 752) gp = &mix->hp_mute; break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 753) case TUMBLER_MUTE_AMP:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 754) gp = &mix->amp_mute; break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 755) case TUMBLER_MUTE_LINE:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 756) gp = &mix->line_mute; break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 757) default:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 758) gp = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 759) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 760) if (gp == NULL)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 761) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 762) val = ! check_audio_gpio(gp);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 763) if (val != ucontrol->value.integer.value[0]) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 764) write_audio_gpio(gp, ! ucontrol->value.integer.value[0]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 765) return 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 766) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 767) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 768) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 769)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 770) static int snapper_set_capture_source(struct pmac_tumbler *mix)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 771) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 772) if (! mix->i2c.client)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 773) return -ENODEV;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 774) if (mix->capture_source)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 775) mix->acs |= 2;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 776) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 777) mix->acs &= ~2;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 778) return i2c_smbus_write_byte_data(mix->i2c.client, TAS_REG_ACS, mix->acs);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 779) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 780)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 781) static int snapper_info_capture_source(struct snd_kcontrol *kcontrol,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 782) struct snd_ctl_elem_info *uinfo)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 783) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 784) static const char * const texts[2] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 785) "Line", "Mic"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 786) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 787)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 788) return snd_ctl_enum_info(uinfo, 1, 2, texts);
^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) static int snapper_get_capture_source(struct snd_kcontrol *kcontrol,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 792) struct snd_ctl_elem_value *ucontrol)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 793) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 794) struct snd_pmac *chip = snd_kcontrol_chip(kcontrol);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 795) struct pmac_tumbler *mix = chip->mixer_data;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 796)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 797) ucontrol->value.enumerated.item[0] = mix->capture_source;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 798) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 799) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 800)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 801) static int snapper_put_capture_source(struct snd_kcontrol *kcontrol,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 802) struct snd_ctl_elem_value *ucontrol)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 803) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 804) struct snd_pmac *chip = snd_kcontrol_chip(kcontrol);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 805) struct pmac_tumbler *mix = chip->mixer_data;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 806) int change;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 807)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 808) change = ucontrol->value.enumerated.item[0] != mix->capture_source;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 809) if (change) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 810) mix->capture_source = !!ucontrol->value.enumerated.item[0];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 811) snapper_set_capture_source(mix);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 812) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 813) return change;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 814) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 815)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 816) #define DEFINE_SNAPPER_MIX(xname,idx,ofs) { \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 817) .iface = SNDRV_CTL_ELEM_IFACE_MIXER,\
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 818) .name = xname, \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 819) .info = snapper_info_mix, \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 820) .get = snapper_get_mix, \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 821) .put = snapper_put_mix, \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 822) .index = idx,\
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 823) .private_value = ofs, \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 824) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 825)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 826)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 827) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 828) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 829) static const struct snd_kcontrol_new tumbler_mixers[] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 830) { .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 831) .name = "Master Playback Volume",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 832) .info = tumbler_info_master_volume,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 833) .get = tumbler_get_master_volume,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 834) .put = tumbler_put_master_volume
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 835) },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 836) { .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 837) .name = "Master Playback Switch",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 838) .info = snd_pmac_boolean_stereo_info,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 839) .get = tumbler_get_master_switch,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 840) .put = tumbler_put_master_switch
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 841) },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 842) DEFINE_MONO("Tone Control - Bass", bass),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 843) DEFINE_MONO("Tone Control - Treble", treble),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 844) DEFINE_MONO("PCM Playback Volume", pcm),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 845) { .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 846) .name = "DRC Range",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 847) .info = tumbler_info_drc_value,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 848) .get = tumbler_get_drc_value,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 849) .put = tumbler_put_drc_value
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 850) },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 851) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 852)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 853) static const struct snd_kcontrol_new snapper_mixers[] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 854) { .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 855) .name = "Master Playback Volume",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 856) .info = tumbler_info_master_volume,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 857) .get = tumbler_get_master_volume,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 858) .put = tumbler_put_master_volume
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 859) },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 860) { .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 861) .name = "Master Playback Switch",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 862) .info = snd_pmac_boolean_stereo_info,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 863) .get = tumbler_get_master_switch,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 864) .put = tumbler_put_master_switch
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 865) },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 866) DEFINE_SNAPPER_MIX("PCM Playback Volume", 0, VOL_IDX_PCM),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 867) /* Alternative PCM is assigned to Mic analog loopback on iBook G4 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 868) DEFINE_SNAPPER_MIX("Mic Playback Volume", 0, VOL_IDX_PCM2),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 869) DEFINE_SNAPPER_MIX("Monitor Mix Volume", 0, VOL_IDX_ADC),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 870) DEFINE_SNAPPER_MONO("Tone Control - Bass", bass),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 871) DEFINE_SNAPPER_MONO("Tone Control - Treble", treble),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 872) { .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 873) .name = "DRC Range",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 874) .info = tumbler_info_drc_value,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 875) .get = tumbler_get_drc_value,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 876) .put = tumbler_put_drc_value
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 877) },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 878) { .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 879) .name = "Input Source", /* FIXME: "Capture Source" doesn't work properly */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 880) .info = snapper_info_capture_source,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 881) .get = snapper_get_capture_source,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 882) .put = snapper_put_capture_source
^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)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 886) static const struct snd_kcontrol_new tumbler_hp_sw = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 887) .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 888) .name = "Headphone Playback Switch",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 889) .info = snd_pmac_boolean_mono_info,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 890) .get = tumbler_get_mute_switch,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 891) .put = tumbler_put_mute_switch,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 892) .private_value = TUMBLER_MUTE_HP,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 893) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 894) static const struct snd_kcontrol_new tumbler_speaker_sw = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 895) .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 896) .name = "Speaker Playback Switch",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 897) .info = snd_pmac_boolean_mono_info,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 898) .get = tumbler_get_mute_switch,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 899) .put = tumbler_put_mute_switch,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 900) .private_value = TUMBLER_MUTE_AMP,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 901) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 902) static const struct snd_kcontrol_new tumbler_lineout_sw = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 903) .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 904) .name = "Line Out Playback Switch",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 905) .info = snd_pmac_boolean_mono_info,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 906) .get = tumbler_get_mute_switch,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 907) .put = tumbler_put_mute_switch,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 908) .private_value = TUMBLER_MUTE_LINE,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 909) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 910) static const struct snd_kcontrol_new tumbler_drc_sw = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 911) .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 912) .name = "DRC Switch",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 913) .info = snd_pmac_boolean_mono_info,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 914) .get = tumbler_get_drc_switch,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 915) .put = tumbler_put_drc_switch
^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)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 919) #ifdef PMAC_SUPPORT_AUTOMUTE
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 920) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 921) * auto-mute stuffs
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 922) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 923) static int tumbler_detect_headphone(struct snd_pmac *chip)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 924) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 925) struct pmac_tumbler *mix = chip->mixer_data;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 926) int detect = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 927)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 928) if (mix->hp_detect.addr)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 929) detect |= read_audio_gpio(&mix->hp_detect);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 930) return detect;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 931) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 932)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 933) static int tumbler_detect_lineout(struct snd_pmac *chip)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 934) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 935) struct pmac_tumbler *mix = chip->mixer_data;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 936) int detect = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 937)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 938) if (mix->line_detect.addr)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 939) detect |= read_audio_gpio(&mix->line_detect);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 940) return detect;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 941) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 942)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 943) static void check_mute(struct snd_pmac *chip, struct pmac_gpio *gp, int val, int do_notify,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 944) struct snd_kcontrol *sw)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 945) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 946) if (check_audio_gpio(gp) != val) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 947) write_audio_gpio(gp, val);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 948) if (do_notify)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 949) snd_ctl_notify(chip->card, SNDRV_CTL_EVENT_MASK_VALUE,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 950) &sw->id);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 951) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 952) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 953)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 954) static struct work_struct device_change;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 955) static struct snd_pmac *device_change_chip;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 956)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 957) static void device_change_handler(struct work_struct *work)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 958) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 959) struct snd_pmac *chip = device_change_chip;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 960) struct pmac_tumbler *mix;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 961) int headphone, lineout;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 962)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 963) if (!chip)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 964) return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 965)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 966) mix = chip->mixer_data;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 967) if (snd_BUG_ON(!mix))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 968) return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 969)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 970) headphone = tumbler_detect_headphone(chip);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 971) lineout = tumbler_detect_lineout(chip);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 972)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 973) DBG("headphone: %d, lineout: %d\n", headphone, lineout);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 974)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 975) if (headphone || lineout) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 976) /* unmute headphone/lineout & mute speaker */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 977) if (headphone)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 978) check_mute(chip, &mix->hp_mute, 0, mix->auto_mute_notify,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 979) chip->master_sw_ctl);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 980) if (lineout && mix->line_mute.addr != 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 981) check_mute(chip, &mix->line_mute, 0, mix->auto_mute_notify,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 982) chip->lineout_sw_ctl);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 983) if (mix->anded_reset)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 984) msleep(10);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 985) check_mute(chip, &mix->amp_mute, !IS_G4DA, mix->auto_mute_notify,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 986) chip->speaker_sw_ctl);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 987) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 988) /* unmute speaker, mute others */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 989) check_mute(chip, &mix->amp_mute, 0, mix->auto_mute_notify,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 990) chip->speaker_sw_ctl);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 991) if (mix->anded_reset)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 992) msleep(10);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 993) check_mute(chip, &mix->hp_mute, 1, mix->auto_mute_notify,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 994) chip->master_sw_ctl);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 995) if (mix->line_mute.addr != 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 996) check_mute(chip, &mix->line_mute, 1, mix->auto_mute_notify,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 997) chip->lineout_sw_ctl);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 998) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 999) if (mix->auto_mute_notify)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1000) snd_ctl_notify(chip->card, SNDRV_CTL_EVENT_MASK_VALUE,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1001) &chip->hp_detect_ctl->id);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1002)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1003) #ifdef CONFIG_SND_POWERMAC_AUTO_DRC
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1004) mix->drc_enable = ! (headphone || lineout);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1005) if (mix->auto_mute_notify)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1006) snd_ctl_notify(chip->card, SNDRV_CTL_EVENT_MASK_VALUE,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1007) &chip->drc_sw_ctl->id);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1008) if (chip->model == PMAC_TUMBLER)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1009) tumbler_set_drc(mix);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1010) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1011) snapper_set_drc(mix);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1012) #endif
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1013)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1014) /* reset the master volume so the correct amplification is applied */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1015) tumbler_set_master_volume(mix);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1016) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1017)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1018) static void tumbler_update_automute(struct snd_pmac *chip, int do_notify)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1019) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1020) if (chip->auto_mute) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1021) struct pmac_tumbler *mix;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1022) mix = chip->mixer_data;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1023) if (snd_BUG_ON(!mix))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1024) return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1025) mix->auto_mute_notify = do_notify;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1026) schedule_work(&device_change);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1027) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1028) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1029) #endif /* PMAC_SUPPORT_AUTOMUTE */
^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) /* interrupt - headphone plug changed */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1033) static irqreturn_t headphone_intr(int irq, void *devid)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1034) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1035) struct snd_pmac *chip = devid;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1036) if (chip->update_automute && chip->initialized) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1037) chip->update_automute(chip, 1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1038) return IRQ_HANDLED;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1039) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1040) return IRQ_NONE;
^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) /* look for audio-gpio device */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1044) static struct device_node *find_audio_device(const char *name)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1045) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1046) struct device_node *gpiop;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1047) struct device_node *np;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1048)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1049) gpiop = of_find_node_by_name(NULL, "gpio");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1050) if (! gpiop)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1051) return NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1052)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1053) for (np = of_get_next_child(gpiop, NULL); np;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1054) np = of_get_next_child(gpiop, np)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1055) const char *property = of_get_property(np, "audio-gpio", NULL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1056) if (property && strcmp(property, name) == 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1057) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1058) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1059) of_node_put(gpiop);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1060) return np;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1061) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1062)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1063) /* look for audio-gpio device */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1064) static struct device_node *find_compatible_audio_device(const char *name)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1065) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1066) struct device_node *gpiop;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1067) struct device_node *np;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1068)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1069) gpiop = of_find_node_by_name(NULL, "gpio");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1070) if (!gpiop)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1071) return NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1072)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1073) for (np = of_get_next_child(gpiop, NULL); np;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1074) np = of_get_next_child(gpiop, np)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1075) if (of_device_is_compatible(np, name))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1076) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1077) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1078) of_node_put(gpiop);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1079) return np;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1080) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1081)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1082) /* find an audio device and get its address */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1083) static long tumbler_find_device(const char *device, const char *platform,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1084) struct pmac_gpio *gp, int is_compatible)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1085) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1086) struct device_node *node;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1087) const u32 *base;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1088) u32 addr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1089) long ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1090)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1091) if (is_compatible)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1092) node = find_compatible_audio_device(device);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1093) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1094) node = find_audio_device(device);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1095) if (! node) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1096) DBG("(W) cannot find audio device %s !\n", device);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1097) snd_printdd("cannot find device %s\n", device);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1098) return -ENODEV;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1099) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1100)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1101) base = of_get_property(node, "AAPL,address", NULL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1102) if (! base) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1103) base = of_get_property(node, "reg", NULL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1104) if (!base) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1105) DBG("(E) cannot find address for device %s !\n", device);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1106) snd_printd("cannot find address for device %s\n", device);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1107) of_node_put(node);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1108) return -ENODEV;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1109) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1110) addr = *base;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1111) if (addr < 0x50)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1112) addr += 0x50;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1113) } else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1114) addr = *base;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1115)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1116) gp->addr = addr & 0x0000ffff;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1117) /* Try to find the active state, default to 0 ! */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1118) base = of_get_property(node, "audio-gpio-active-state", NULL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1119) if (base) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1120) gp->active_state = *base;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1121) gp->active_val = (*base) ? 0x5 : 0x4;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1122) gp->inactive_val = (*base) ? 0x4 : 0x5;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1123) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1124) const u32 *prop = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1125) gp->active_state = IS_G4DA
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1126) && !strncmp(device, "keywest-gpio1", 13);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1127) gp->active_val = 0x4;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1128) gp->inactive_val = 0x5;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1129) /* Here are some crude hacks to extract the GPIO polarity and
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1130) * open collector informations out of the do-platform script
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1131) * as we don't yet have an interpreter for these things
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1132) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1133) if (platform)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1134) prop = of_get_property(node, platform, NULL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1135) if (prop) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1136) if (prop[3] == 0x9 && prop[4] == 0x9) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1137) gp->active_val = 0xd;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1138) gp->inactive_val = 0xc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1139) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1140) if (prop[3] == 0x1 && prop[4] == 0x1) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1141) gp->active_val = 0x5;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1142) gp->inactive_val = 0x4;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1143) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1144) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1145) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1146)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1147) DBG("(I) GPIO device %s found, offset: %x, active state: %d !\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1148) device, gp->addr, gp->active_state);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1149)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1150) ret = irq_of_parse_and_map(node, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1151) of_node_put(node);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1152) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1153) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1154)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1155) /* reset audio */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1156) static void tumbler_reset_audio(struct snd_pmac *chip)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1157) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1158) struct pmac_tumbler *mix = chip->mixer_data;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1159)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1160) if (mix->anded_reset) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1161) DBG("(I) codec anded reset !\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1162) write_audio_gpio(&mix->hp_mute, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1163) write_audio_gpio(&mix->amp_mute, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1164) msleep(200);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1165) write_audio_gpio(&mix->hp_mute, 1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1166) write_audio_gpio(&mix->amp_mute, 1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1167) msleep(100);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1168) write_audio_gpio(&mix->hp_mute, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1169) write_audio_gpio(&mix->amp_mute, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1170) msleep(100);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1171) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1172) DBG("(I) codec normal reset !\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1173)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1174) write_audio_gpio(&mix->audio_reset, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1175) msleep(200);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1176) write_audio_gpio(&mix->audio_reset, 1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1177) msleep(100);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1178) write_audio_gpio(&mix->audio_reset, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1179) msleep(100);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1180) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1181) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1182)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1183) #ifdef CONFIG_PM
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1184) /* suspend mixer */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1185) static void tumbler_suspend(struct snd_pmac *chip)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1186) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1187) struct pmac_tumbler *mix = chip->mixer_data;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1188)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1189) if (mix->headphone_irq >= 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1190) disable_irq(mix->headphone_irq);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1191) if (mix->lineout_irq >= 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1192) disable_irq(mix->lineout_irq);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1193) mix->save_master_switch[0] = mix->master_switch[0];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1194) mix->save_master_switch[1] = mix->master_switch[1];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1195) mix->save_master_vol[0] = mix->master_vol[0];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1196) mix->save_master_vol[1] = mix->master_vol[1];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1197) mix->master_switch[0] = mix->master_switch[1] = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1198) tumbler_set_master_volume(mix);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1199) if (!mix->anded_reset) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1200) write_audio_gpio(&mix->amp_mute, 1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1201) write_audio_gpio(&mix->hp_mute, 1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1202) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1203) if (chip->model == PMAC_SNAPPER) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1204) mix->acs |= 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1205) i2c_smbus_write_byte_data(mix->i2c.client, TAS_REG_ACS, mix->acs);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1206) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1207) if (mix->anded_reset) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1208) write_audio_gpio(&mix->amp_mute, 1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1209) write_audio_gpio(&mix->hp_mute, 1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1210) } else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1211) write_audio_gpio(&mix->audio_reset, 1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1212) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1213)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1214) /* resume mixer */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1215) static void tumbler_resume(struct snd_pmac *chip)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1216) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1217) struct pmac_tumbler *mix = chip->mixer_data;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1218)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1219) mix->acs &= ~1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1220) mix->master_switch[0] = mix->save_master_switch[0];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1221) mix->master_switch[1] = mix->save_master_switch[1];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1222) mix->master_vol[0] = mix->save_master_vol[0];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1223) mix->master_vol[1] = mix->save_master_vol[1];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1224) tumbler_reset_audio(chip);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1225) if (mix->i2c.client && mix->i2c.init_client) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1226) if (mix->i2c.init_client(&mix->i2c) < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1227) printk(KERN_ERR "tumbler_init_client error\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1228) } else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1229) printk(KERN_ERR "tumbler: i2c is not initialized\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1230) if (chip->model == PMAC_TUMBLER) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1231) tumbler_set_mono_volume(mix, &tumbler_pcm_vol_info);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1232) tumbler_set_mono_volume(mix, &tumbler_bass_vol_info);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1233) tumbler_set_mono_volume(mix, &tumbler_treble_vol_info);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1234) tumbler_set_drc(mix);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1235) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1236) snapper_set_mix_vol(mix, VOL_IDX_PCM);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1237) snapper_set_mix_vol(mix, VOL_IDX_PCM2);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1238) snapper_set_mix_vol(mix, VOL_IDX_ADC);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1239) tumbler_set_mono_volume(mix, &snapper_bass_vol_info);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1240) tumbler_set_mono_volume(mix, &snapper_treble_vol_info);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1241) snapper_set_drc(mix);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1242) snapper_set_capture_source(mix);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1243) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1244) tumbler_set_master_volume(mix);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1245) if (chip->update_automute)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1246) chip->update_automute(chip, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1247) if (mix->headphone_irq >= 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1248) unsigned char val;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1249)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1250) enable_irq(mix->headphone_irq);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1251) /* activate headphone status interrupts */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1252) val = do_gpio_read(&mix->hp_detect);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1253) do_gpio_write(&mix->hp_detect, val | 0x80);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1254) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1255) if (mix->lineout_irq >= 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1256) enable_irq(mix->lineout_irq);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1257) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1258) #endif
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1259)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1260) /* initialize tumbler */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1261) static int tumbler_init(struct snd_pmac *chip)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1262) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1263) int irq;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1264) struct pmac_tumbler *mix = chip->mixer_data;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1265)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1266) if (tumbler_find_device("audio-hw-reset",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1267) "platform-do-hw-reset",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1268) &mix->audio_reset, 0) < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1269) tumbler_find_device("hw-reset",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1270) "platform-do-hw-reset",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1271) &mix->audio_reset, 1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1272) if (tumbler_find_device("amp-mute",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1273) "platform-do-amp-mute",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1274) &mix->amp_mute, 0) < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1275) tumbler_find_device("amp-mute",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1276) "platform-do-amp-mute",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1277) &mix->amp_mute, 1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1278) if (tumbler_find_device("headphone-mute",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1279) "platform-do-headphone-mute",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1280) &mix->hp_mute, 0) < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1281) tumbler_find_device("headphone-mute",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1282) "platform-do-headphone-mute",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1283) &mix->hp_mute, 1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1284) if (tumbler_find_device("line-output-mute",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1285) "platform-do-lineout-mute",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1286) &mix->line_mute, 0) < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1287) tumbler_find_device("line-output-mute",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1288) "platform-do-lineout-mute",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1289) &mix->line_mute, 1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1290) irq = tumbler_find_device("headphone-detect",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1291) NULL, &mix->hp_detect, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1292) if (irq <= 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1293) irq = tumbler_find_device("headphone-detect",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1294) NULL, &mix->hp_detect, 1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1295) if (irq <= 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1296) irq = tumbler_find_device("keywest-gpio15",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1297) NULL, &mix->hp_detect, 1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1298) mix->headphone_irq = irq;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1299) irq = tumbler_find_device("line-output-detect",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1300) NULL, &mix->line_detect, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1301) if (irq <= 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1302) irq = tumbler_find_device("line-output-detect",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1303) NULL, &mix->line_detect, 1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1304) if (IS_G4DA && irq <= 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1305) irq = tumbler_find_device("keywest-gpio16",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1306) NULL, &mix->line_detect, 1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1307) mix->lineout_irq = irq;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1308)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1309) tumbler_reset_audio(chip);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1310)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1311) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1312) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1313)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1314) static void tumbler_cleanup(struct snd_pmac *chip)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1315) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1316) struct pmac_tumbler *mix = chip->mixer_data;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1317) if (! mix)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1318) return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1319)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1320) if (mix->headphone_irq >= 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1321) free_irq(mix->headphone_irq, chip);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1322) if (mix->lineout_irq >= 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1323) free_irq(mix->lineout_irq, chip);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1324) tumbler_gpio_free(&mix->audio_reset);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1325) tumbler_gpio_free(&mix->amp_mute);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1326) tumbler_gpio_free(&mix->hp_mute);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1327) tumbler_gpio_free(&mix->hp_detect);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1328) snd_pmac_keywest_cleanup(&mix->i2c);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1329) kfree(mix);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1330) chip->mixer_data = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1331) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1332)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1333) /* exported */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1334) int snd_pmac_tumbler_init(struct snd_pmac *chip)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1335) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1336) int i, err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1337) struct pmac_tumbler *mix;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1338) const u32 *paddr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1339) struct device_node *tas_node, *np;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1340) char *chipname;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1341)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1342) request_module("i2c-powermac");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1343)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1344) mix = kzalloc(sizeof(*mix), GFP_KERNEL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1345) if (! mix)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1346) return -ENOMEM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1347) mix->headphone_irq = -1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1348)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1349) chip->mixer_data = mix;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1350) chip->mixer_free = tumbler_cleanup;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1351) mix->anded_reset = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1352) mix->reset_on_sleep = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1353)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1354) for_each_child_of_node(chip->node, np) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1355) if (of_node_name_eq(np, "sound")) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1356) if (of_get_property(np, "has-anded-reset", NULL))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1357) mix->anded_reset = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1358) if (of_get_property(np, "layout-id", NULL))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1359) mix->reset_on_sleep = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1360) of_node_put(np);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1361) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1362) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1363) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1364) if ((err = tumbler_init(chip)) < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1365) return err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1366)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1367) /* set up TAS */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1368) tas_node = of_find_node_by_name(NULL, "deq");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1369) if (tas_node == NULL)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1370) tas_node = of_find_node_by_name(NULL, "codec");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1371) if (tas_node == NULL)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1372) return -ENODEV;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1373)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1374) paddr = of_get_property(tas_node, "i2c-address", NULL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1375) if (paddr == NULL)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1376) paddr = of_get_property(tas_node, "reg", NULL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1377) if (paddr)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1378) mix->i2c.addr = (*paddr) >> 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1379) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1380) mix->i2c.addr = TAS_I2C_ADDR;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1381) of_node_put(tas_node);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1382)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1383) DBG("(I) TAS i2c address is: %x\n", mix->i2c.addr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1384)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1385) if (chip->model == PMAC_TUMBLER) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1386) mix->i2c.init_client = tumbler_init_client;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1387) mix->i2c.name = "TAS3001c";
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1388) chipname = "Tumbler";
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1389) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1390) mix->i2c.init_client = snapper_init_client;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1391) mix->i2c.name = "TAS3004";
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1392) chipname = "Snapper";
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1393) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1394)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1395) if ((err = snd_pmac_keywest_init(&mix->i2c)) < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1396) return err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1397)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1398) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1399) * build mixers
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1400) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1401) sprintf(chip->card->mixername, "PowerMac %s", chipname);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1402)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1403) if (chip->model == PMAC_TUMBLER) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1404) for (i = 0; i < ARRAY_SIZE(tumbler_mixers); i++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1405) if ((err = snd_ctl_add(chip->card, snd_ctl_new1(&tumbler_mixers[i], chip))) < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1406) return err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1407) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1408) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1409) for (i = 0; i < ARRAY_SIZE(snapper_mixers); i++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1410) if ((err = snd_ctl_add(chip->card, snd_ctl_new1(&snapper_mixers[i], chip))) < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1411) return err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1412) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1413) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1414) chip->master_sw_ctl = snd_ctl_new1(&tumbler_hp_sw, chip);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1415) if ((err = snd_ctl_add(chip->card, chip->master_sw_ctl)) < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1416) return err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1417) chip->speaker_sw_ctl = snd_ctl_new1(&tumbler_speaker_sw, chip);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1418) if ((err = snd_ctl_add(chip->card, chip->speaker_sw_ctl)) < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1419) return err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1420) if (mix->line_mute.addr != 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1421) chip->lineout_sw_ctl = snd_ctl_new1(&tumbler_lineout_sw, chip);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1422) if ((err = snd_ctl_add(chip->card, chip->lineout_sw_ctl)) < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1423) return err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1424) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1425) chip->drc_sw_ctl = snd_ctl_new1(&tumbler_drc_sw, chip);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1426) if ((err = snd_ctl_add(chip->card, chip->drc_sw_ctl)) < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1427) return err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1428)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1429) /* set initial DRC range to 60% */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1430) if (chip->model == PMAC_TUMBLER)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1431) mix->drc_range = (TAS3001_DRC_MAX * 6) / 10;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1432) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1433) mix->drc_range = (TAS3004_DRC_MAX * 6) / 10;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1434) mix->drc_enable = 1; /* will be changed later if AUTO_DRC is set */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1435) if (chip->model == PMAC_TUMBLER)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1436) tumbler_set_drc(mix);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1437) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1438) snapper_set_drc(mix);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1439)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1440) #ifdef CONFIG_PM
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1441) chip->suspend = tumbler_suspend;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1442) chip->resume = tumbler_resume;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1443) #endif
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1444)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1445) INIT_WORK(&device_change, device_change_handler);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1446) device_change_chip = chip;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1447)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1448) #ifdef PMAC_SUPPORT_AUTOMUTE
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1449) if ((mix->headphone_irq >=0 || mix->lineout_irq >= 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1450) && (err = snd_pmac_add_automute(chip)) < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1451) return err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1452) chip->detect_headphone = tumbler_detect_headphone;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1453) chip->update_automute = tumbler_update_automute;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1454) tumbler_update_automute(chip, 0); /* update the status only */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1455)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1456) /* activate headphone status interrupts */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1457) if (mix->headphone_irq >= 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1458) unsigned char val;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1459) if ((err = request_irq(mix->headphone_irq, headphone_intr, 0,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1460) "Sound Headphone Detection", chip)) < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1461) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1462) /* activate headphone status interrupts */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1463) val = do_gpio_read(&mix->hp_detect);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1464) do_gpio_write(&mix->hp_detect, val | 0x80);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1465) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1466) if (mix->lineout_irq >= 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1467) unsigned char val;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1468) if ((err = request_irq(mix->lineout_irq, headphone_intr, 0,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1469) "Sound Lineout Detection", chip)) < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1470) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1471) /* activate headphone status interrupts */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1472) val = do_gpio_read(&mix->line_detect);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1473) do_gpio_write(&mix->line_detect, val | 0x80);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1474) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1475) #endif
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1476)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1477) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1478) }