^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) * Copyright (c) by Jaroslav Kysela <perex@perex.cz>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4) * Routines for control of CS4235/4236B/4237B/4238B/4239 chips
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6) * Note:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7) * -----
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9) * Bugs:
^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) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14) * Indirect control registers (CS4236B+)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 15) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 16) * C0
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 17) * D8: WSS reset (all chips)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 18) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 19) * C1 (all chips except CS4236)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 20) * D7-D5: version
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 21) * D4-D0: chip id
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 22) * 11101 - CS4235
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 23) * 01011 - CS4236B
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 24) * 01000 - CS4237B
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 25) * 01001 - CS4238B
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 26) * 11110 - CS4239
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 27) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 28) * C2
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 29) * D7-D4: 3D Space (CS4235,CS4237B,CS4238B,CS4239)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 30) * D3-D0: 3D Center (CS4237B); 3D Volume (CS4238B)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 31) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 32) * C3
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 33) * D7: 3D Enable (CS4237B)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 34) * D6: 3D Mono Enable (CS4237B)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 35) * D5: 3D Serial Output (CS4237B,CS4238B)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 36) * D4: 3D Enable (CS4235,CS4238B,CS4239)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 37) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 38) * C4
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 39) * D7: consumer serial port enable (CS4237B,CS4238B)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 40) * D6: channels status block reset (CS4237B,CS4238B)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 41) * D5: user bit in sub-frame of digital audio data (CS4237B,CS4238B)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 42) * D4: validity bit in sub-frame of digital audio data (CS4237B,CS4238B)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 43) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 44) * C5 lower channel status (digital serial data description) (CS4237B,CS4238B)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 45) * D7-D6: first two bits of category code
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 46) * D5: lock
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 47) * D4-D3: pre-emphasis (0 = none, 1 = 50/15us)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 48) * D2: copy/copyright (0 = copy inhibited)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 49) * D1: 0 = digital audio / 1 = non-digital audio
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 50) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 51) * C6 upper channel status (digital serial data description) (CS4237B,CS4238B)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 52) * D7-D6: sample frequency (0 = 44.1kHz)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 53) * D5: generation status (0 = no indication, 1 = original/commercially precaptureed data)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 54) * D4-D0: category code (upper bits)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 55) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 56) * C7 reserved (must write 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 57) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 58) * C8 wavetable control
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 59) * D7: volume control interrupt enable (CS4235,CS4239)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 60) * D6: hardware volume control format (CS4235,CS4239)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 61) * D3: wavetable serial port enable (all chips)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 62) * D2: DSP serial port switch (all chips)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 63) * D1: disable MCLK (all chips)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 64) * D0: force BRESET low (all chips)
^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)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 68) #include <linux/io.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 69) #include <linux/delay.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 70) #include <linux/init.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 71) #include <linux/time.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 72) #include <linux/wait.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 73) #include <sound/core.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 74) #include <sound/wss.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 75) #include <sound/asoundef.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 76) #include <sound/initval.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 77) #include <sound/tlv.h>
^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) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 81) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 82)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 83) static const unsigned char snd_cs4236_ext_map[18] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 84) /* CS4236_LEFT_LINE */ 0xff,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 85) /* CS4236_RIGHT_LINE */ 0xff,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 86) /* CS4236_LEFT_MIC */ 0xdf,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 87) /* CS4236_RIGHT_MIC */ 0xdf,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 88) /* CS4236_LEFT_MIX_CTRL */ 0xe0 | 0x18,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 89) /* CS4236_RIGHT_MIX_CTRL */ 0xe0,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 90) /* CS4236_LEFT_FM */ 0xbf,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 91) /* CS4236_RIGHT_FM */ 0xbf,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 92) /* CS4236_LEFT_DSP */ 0xbf,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 93) /* CS4236_RIGHT_DSP */ 0xbf,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 94) /* CS4236_RIGHT_LOOPBACK */ 0xbf,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 95) /* CS4236_DAC_MUTE */ 0xe0,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 96) /* CS4236_ADC_RATE */ 0x01, /* 48kHz */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 97) /* CS4236_DAC_RATE */ 0x01, /* 48kHz */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 98) /* CS4236_LEFT_MASTER */ 0xbf,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 99) /* CS4236_RIGHT_MASTER */ 0xbf,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 100) /* CS4236_LEFT_WAVE */ 0xbf,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 101) /* CS4236_RIGHT_WAVE */ 0xbf
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 102) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 103)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 104) /*
^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) static void snd_cs4236_ctrl_out(struct snd_wss *chip,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 109) unsigned char reg, unsigned char val)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 110) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 111) outb(reg, chip->cport + 3);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 112) outb(chip->cimage[reg] = val, chip->cport + 4);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 113) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 114)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 115) static unsigned char snd_cs4236_ctrl_in(struct snd_wss *chip, unsigned char reg)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 116) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 117) outb(reg, chip->cport + 3);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 118) return inb(chip->cport + 4);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 119) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 120)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 121) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 122) * PCM
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 123) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 124)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 125) #define CLOCKS 8
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 126)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 127) static const struct snd_ratnum clocks[CLOCKS] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 128) { .num = 16934400, .den_min = 353, .den_max = 353, .den_step = 1 },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 129) { .num = 16934400, .den_min = 529, .den_max = 529, .den_step = 1 },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 130) { .num = 16934400, .den_min = 617, .den_max = 617, .den_step = 1 },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 131) { .num = 16934400, .den_min = 1058, .den_max = 1058, .den_step = 1 },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 132) { .num = 16934400, .den_min = 1764, .den_max = 1764, .den_step = 1 },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 133) { .num = 16934400, .den_min = 2117, .den_max = 2117, .den_step = 1 },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 134) { .num = 16934400, .den_min = 2558, .den_max = 2558, .den_step = 1 },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 135) { .num = 16934400/16, .den_min = 21, .den_max = 192, .den_step = 1 }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 136) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 137)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 138) static const struct snd_pcm_hw_constraint_ratnums hw_constraints_clocks = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 139) .nrats = CLOCKS,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 140) .rats = clocks,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 141) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 142)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 143) static int snd_cs4236_xrate(struct snd_pcm_runtime *runtime)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 144) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 145) return snd_pcm_hw_constraint_ratnums(runtime, 0, SNDRV_PCM_HW_PARAM_RATE,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 146) &hw_constraints_clocks);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 147) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 148)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 149) static unsigned char divisor_to_rate_register(unsigned int divisor)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 150) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 151) switch (divisor) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 152) case 353: return 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 153) case 529: return 2;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 154) case 617: return 3;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 155) case 1058: return 4;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 156) case 1764: return 5;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 157) case 2117: return 6;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 158) case 2558: return 7;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 159) default:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 160) if (divisor < 21 || divisor > 192) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 161) snd_BUG();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 162) return 192;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 163) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 164) return divisor;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 165) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 166) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 167)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 168) static void snd_cs4236_playback_format(struct snd_wss *chip,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 169) struct snd_pcm_hw_params *params,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 170) unsigned char pdfr)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 171) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 172) unsigned long flags;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 173) unsigned char rate = divisor_to_rate_register(params->rate_den);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 174)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 175) spin_lock_irqsave(&chip->reg_lock, flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 176) /* set fast playback format change and clean playback FIFO */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 177) snd_wss_out(chip, CS4231_ALT_FEATURE_1,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 178) chip->image[CS4231_ALT_FEATURE_1] | 0x10);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 179) snd_wss_out(chip, CS4231_PLAYBK_FORMAT, pdfr & 0xf0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 180) snd_wss_out(chip, CS4231_ALT_FEATURE_1,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 181) chip->image[CS4231_ALT_FEATURE_1] & ~0x10);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 182) snd_cs4236_ext_out(chip, CS4236_DAC_RATE, rate);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 183) spin_unlock_irqrestore(&chip->reg_lock, flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 184) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 185)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 186) static void snd_cs4236_capture_format(struct snd_wss *chip,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 187) struct snd_pcm_hw_params *params,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 188) unsigned char cdfr)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 189) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 190) unsigned long flags;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 191) unsigned char rate = divisor_to_rate_register(params->rate_den);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 192)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 193) spin_lock_irqsave(&chip->reg_lock, flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 194) /* set fast capture format change and clean capture FIFO */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 195) snd_wss_out(chip, CS4231_ALT_FEATURE_1,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 196) chip->image[CS4231_ALT_FEATURE_1] | 0x20);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 197) snd_wss_out(chip, CS4231_REC_FORMAT, cdfr & 0xf0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 198) snd_wss_out(chip, CS4231_ALT_FEATURE_1,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 199) chip->image[CS4231_ALT_FEATURE_1] & ~0x20);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 200) snd_cs4236_ext_out(chip, CS4236_ADC_RATE, rate);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 201) spin_unlock_irqrestore(&chip->reg_lock, flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 202) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 203)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 204) #ifdef CONFIG_PM
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 205)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 206) static void snd_cs4236_suspend(struct snd_wss *chip)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 207) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 208) int reg;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 209) unsigned long flags;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 210)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 211) spin_lock_irqsave(&chip->reg_lock, flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 212) for (reg = 0; reg < 32; reg++)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 213) chip->image[reg] = snd_wss_in(chip, reg);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 214) for (reg = 0; reg < 18; reg++)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 215) chip->eimage[reg] = snd_cs4236_ext_in(chip, CS4236_I23VAL(reg));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 216) for (reg = 2; reg < 9; reg++)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 217) chip->cimage[reg] = snd_cs4236_ctrl_in(chip, reg);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 218) spin_unlock_irqrestore(&chip->reg_lock, flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 219) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 220)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 221) static void snd_cs4236_resume(struct snd_wss *chip)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 222) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 223) int reg;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 224) unsigned long flags;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 225)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 226) snd_wss_mce_up(chip);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 227) spin_lock_irqsave(&chip->reg_lock, flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 228) for (reg = 0; reg < 32; reg++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 229) switch (reg) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 230) case CS4236_EXT_REG:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 231) case CS4231_VERSION:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 232) case 27: /* why? CS4235 - master left */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 233) case 29: /* why? CS4235 - master right */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 234) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 235) default:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 236) snd_wss_out(chip, reg, chip->image[reg]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 237) break;
^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) for (reg = 0; reg < 18; reg++)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 241) snd_cs4236_ext_out(chip, CS4236_I23VAL(reg), chip->eimage[reg]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 242) for (reg = 2; reg < 9; reg++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 243) switch (reg) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 244) case 7:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 245) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 246) default:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 247) snd_cs4236_ctrl_out(chip, reg, chip->cimage[reg]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 248) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 249) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 250) spin_unlock_irqrestore(&chip->reg_lock, flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 251) snd_wss_mce_down(chip);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 252) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 253)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 254) #endif /* CONFIG_PM */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 255) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 256) * This function does no fail if the chip is not CS4236B or compatible.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 257) * It just an equivalent to the snd_wss_create() then.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 258) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 259) int snd_cs4236_create(struct snd_card *card,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 260) unsigned long port,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 261) unsigned long cport,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 262) int irq, int dma1, int dma2,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 263) unsigned short hardware,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 264) unsigned short hwshare,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 265) struct snd_wss **rchip)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 266) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 267) struct snd_wss *chip;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 268) unsigned char ver1, ver2;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 269) unsigned int reg;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 270) int err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 271)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 272) *rchip = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 273) if (hardware == WSS_HW_DETECT)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 274) hardware = WSS_HW_DETECT3;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 275)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 276) err = snd_wss_create(card, port, cport,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 277) irq, dma1, dma2, hardware, hwshare, &chip);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 278) if (err < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 279) return err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 280)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 281) if ((chip->hardware & WSS_HW_CS4236B_MASK) == 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 282) snd_printd("chip is not CS4236+, hardware=0x%x\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 283) chip->hardware);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 284) *rchip = chip;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 285) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 286) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 287) #if 0
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 288) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 289) int idx;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 290) for (idx = 0; idx < 8; idx++)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 291) snd_printk(KERN_DEBUG "CD%i = 0x%x\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 292) idx, inb(chip->cport + idx));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 293) for (idx = 0; idx < 9; idx++)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 294) snd_printk(KERN_DEBUG "C%i = 0x%x\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 295) idx, snd_cs4236_ctrl_in(chip, idx));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 296) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 297) #endif
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 298) if (cport < 0x100 || cport == SNDRV_AUTO_PORT) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 299) snd_printk(KERN_ERR "please, specify control port "
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 300) "for CS4236+ chips\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 301) snd_device_free(card, chip);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 302) return -ENODEV;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 303) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 304) ver1 = snd_cs4236_ctrl_in(chip, 1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 305) ver2 = snd_cs4236_ext_in(chip, CS4236_VERSION);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 306) snd_printdd("CS4236: [0x%lx] C1 (version) = 0x%x, ext = 0x%x\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 307) cport, ver1, ver2);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 308) if (ver1 != ver2) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 309) snd_printk(KERN_ERR "CS4236+ chip detected, but "
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 310) "control port 0x%lx is not valid\n", cport);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 311) snd_device_free(card, chip);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 312) return -ENODEV;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 313) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 314) snd_cs4236_ctrl_out(chip, 0, 0x00);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 315) snd_cs4236_ctrl_out(chip, 2, 0xff);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 316) snd_cs4236_ctrl_out(chip, 3, 0x00);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 317) snd_cs4236_ctrl_out(chip, 4, 0x80);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 318) reg = ((IEC958_AES1_CON_PCM_CODER & 3) << 6) |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 319) IEC958_AES0_CON_EMPHASIS_NONE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 320) snd_cs4236_ctrl_out(chip, 5, reg);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 321) snd_cs4236_ctrl_out(chip, 6, IEC958_AES1_CON_PCM_CODER >> 2);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 322) snd_cs4236_ctrl_out(chip, 7, 0x00);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 323) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 324) * 0x8c for C8 is valid for Turtle Beach Malibu - the IEC-958
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 325) * output is working with this setup, other hardware should
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 326) * have different signal paths and this value should be
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 327) * selectable in the future
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 328) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 329) snd_cs4236_ctrl_out(chip, 8, 0x8c);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 330) chip->rate_constraint = snd_cs4236_xrate;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 331) chip->set_playback_format = snd_cs4236_playback_format;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 332) chip->set_capture_format = snd_cs4236_capture_format;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 333) #ifdef CONFIG_PM
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 334) chip->suspend = snd_cs4236_suspend;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 335) chip->resume = snd_cs4236_resume;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 336) #endif
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 337)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 338) /* initialize extended registers */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 339) for (reg = 0; reg < sizeof(snd_cs4236_ext_map); reg++)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 340) snd_cs4236_ext_out(chip, CS4236_I23VAL(reg),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 341) snd_cs4236_ext_map[reg]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 342)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 343) /* initialize compatible but more featured registers */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 344) snd_wss_out(chip, CS4231_LEFT_INPUT, 0x40);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 345) snd_wss_out(chip, CS4231_RIGHT_INPUT, 0x40);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 346) snd_wss_out(chip, CS4231_AUX1_LEFT_INPUT, 0xff);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 347) snd_wss_out(chip, CS4231_AUX1_RIGHT_INPUT, 0xff);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 348) snd_wss_out(chip, CS4231_AUX2_LEFT_INPUT, 0xdf);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 349) snd_wss_out(chip, CS4231_AUX2_RIGHT_INPUT, 0xdf);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 350) snd_wss_out(chip, CS4231_RIGHT_LINE_IN, 0xff);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 351) snd_wss_out(chip, CS4231_LEFT_LINE_IN, 0xff);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 352) snd_wss_out(chip, CS4231_RIGHT_LINE_IN, 0xff);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 353) switch (chip->hardware) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 354) case WSS_HW_CS4235:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 355) case WSS_HW_CS4239:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 356) snd_wss_out(chip, CS4235_LEFT_MASTER, 0xff);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 357) snd_wss_out(chip, CS4235_RIGHT_MASTER, 0xff);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 358) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 359) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 360)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 361) *rchip = chip;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 362) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 363) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 364)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 365) int snd_cs4236_pcm(struct snd_wss *chip, int device)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 366) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 367) int err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 368)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 369) err = snd_wss_pcm(chip, device);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 370) if (err < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 371) return err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 372) chip->pcm->info_flags &= ~SNDRV_PCM_INFO_JOINT_DUPLEX;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 373) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 374) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 375)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 376) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 377) * MIXER
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 378) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 379)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 380) #define CS4236_SINGLE(xname, xindex, reg, shift, mask, invert) \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 381) { .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = xname, .index = xindex, \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 382) .info = snd_cs4236_info_single, \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 383) .get = snd_cs4236_get_single, .put = snd_cs4236_put_single, \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 384) .private_value = reg | (shift << 8) | (mask << 16) | (invert << 24) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 385)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 386) #define CS4236_SINGLE_TLV(xname, xindex, reg, shift, mask, invert, xtlv) \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 387) { .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = xname, .index = xindex, \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 388) .access = SNDRV_CTL_ELEM_ACCESS_READWRITE | SNDRV_CTL_ELEM_ACCESS_TLV_READ, \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 389) .info = snd_cs4236_info_single, \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 390) .get = snd_cs4236_get_single, .put = snd_cs4236_put_single, \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 391) .private_value = reg | (shift << 8) | (mask << 16) | (invert << 24), \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 392) .tlv = { .p = (xtlv) } }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 393)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 394) static int snd_cs4236_info_single(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info *uinfo)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 395) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 396) int mask = (kcontrol->private_value >> 16) & 0xff;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 397)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 398) uinfo->type = mask == 1 ? SNDRV_CTL_ELEM_TYPE_BOOLEAN : SNDRV_CTL_ELEM_TYPE_INTEGER;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 399) uinfo->count = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 400) uinfo->value.integer.min = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 401) uinfo->value.integer.max = mask;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 402) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 403) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 404)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 405) static int snd_cs4236_get_single(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 406) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 407) struct snd_wss *chip = snd_kcontrol_chip(kcontrol);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 408) unsigned long flags;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 409) int reg = kcontrol->private_value & 0xff;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 410) int shift = (kcontrol->private_value >> 8) & 0xff;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 411) int mask = (kcontrol->private_value >> 16) & 0xff;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 412) int invert = (kcontrol->private_value >> 24) & 0xff;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 413)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 414) spin_lock_irqsave(&chip->reg_lock, flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 415) ucontrol->value.integer.value[0] = (chip->eimage[CS4236_REG(reg)] >> shift) & mask;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 416) spin_unlock_irqrestore(&chip->reg_lock, flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 417) if (invert)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 418) ucontrol->value.integer.value[0] = mask - ucontrol->value.integer.value[0];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 419) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 420) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 421)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 422) static int snd_cs4236_put_single(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 423) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 424) struct snd_wss *chip = snd_kcontrol_chip(kcontrol);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 425) unsigned long flags;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 426) int reg = kcontrol->private_value & 0xff;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 427) int shift = (kcontrol->private_value >> 8) & 0xff;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 428) int mask = (kcontrol->private_value >> 16) & 0xff;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 429) int invert = (kcontrol->private_value >> 24) & 0xff;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 430) int change;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 431) unsigned short val;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 432)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 433) val = (ucontrol->value.integer.value[0] & mask);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 434) if (invert)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 435) val = mask - val;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 436) val <<= shift;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 437) spin_lock_irqsave(&chip->reg_lock, flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 438) val = (chip->eimage[CS4236_REG(reg)] & ~(mask << shift)) | val;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 439) change = val != chip->eimage[CS4236_REG(reg)];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 440) snd_cs4236_ext_out(chip, reg, val);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 441) spin_unlock_irqrestore(&chip->reg_lock, flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 442) return change;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 443) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 444)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 445) #define CS4236_SINGLEC(xname, xindex, reg, shift, mask, invert) \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 446) { .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = xname, .index = xindex, \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 447) .info = snd_cs4236_info_single, \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 448) .get = snd_cs4236_get_singlec, .put = snd_cs4236_put_singlec, \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 449) .private_value = reg | (shift << 8) | (mask << 16) | (invert << 24) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 450)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 451) static int snd_cs4236_get_singlec(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 452) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 453) struct snd_wss *chip = snd_kcontrol_chip(kcontrol);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 454) unsigned long flags;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 455) int reg = kcontrol->private_value & 0xff;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 456) int shift = (kcontrol->private_value >> 8) & 0xff;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 457) int mask = (kcontrol->private_value >> 16) & 0xff;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 458) int invert = (kcontrol->private_value >> 24) & 0xff;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 459)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 460) spin_lock_irqsave(&chip->reg_lock, flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 461) ucontrol->value.integer.value[0] = (chip->cimage[reg] >> shift) & mask;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 462) spin_unlock_irqrestore(&chip->reg_lock, flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 463) if (invert)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 464) ucontrol->value.integer.value[0] = mask - ucontrol->value.integer.value[0];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 465) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 466) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 467)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 468) static int snd_cs4236_put_singlec(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 469) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 470) struct snd_wss *chip = snd_kcontrol_chip(kcontrol);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 471) unsigned long flags;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 472) int reg = kcontrol->private_value & 0xff;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 473) int shift = (kcontrol->private_value >> 8) & 0xff;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 474) int mask = (kcontrol->private_value >> 16) & 0xff;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 475) int invert = (kcontrol->private_value >> 24) & 0xff;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 476) int change;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 477) unsigned short val;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 478)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 479) val = (ucontrol->value.integer.value[0] & mask);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 480) if (invert)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 481) val = mask - val;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 482) val <<= shift;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 483) spin_lock_irqsave(&chip->reg_lock, flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 484) val = (chip->cimage[reg] & ~(mask << shift)) | val;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 485) change = val != chip->cimage[reg];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 486) snd_cs4236_ctrl_out(chip, reg, val);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 487) spin_unlock_irqrestore(&chip->reg_lock, flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 488) return change;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 489) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 490)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 491) #define CS4236_DOUBLE(xname, xindex, left_reg, right_reg, shift_left, shift_right, mask, invert) \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 492) { .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = xname, .index = xindex, \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 493) .info = snd_cs4236_info_double, \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 494) .get = snd_cs4236_get_double, .put = snd_cs4236_put_double, \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 495) .private_value = left_reg | (right_reg << 8) | (shift_left << 16) | (shift_right << 19) | (mask << 24) | (invert << 22) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 496)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 497) #define CS4236_DOUBLE_TLV(xname, xindex, left_reg, right_reg, shift_left, \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 498) shift_right, mask, invert, xtlv) \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 499) { .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = xname, .index = xindex, \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 500) .access = SNDRV_CTL_ELEM_ACCESS_READWRITE | SNDRV_CTL_ELEM_ACCESS_TLV_READ, \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 501) .info = snd_cs4236_info_double, \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 502) .get = snd_cs4236_get_double, .put = snd_cs4236_put_double, \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 503) .private_value = left_reg | (right_reg << 8) | (shift_left << 16) | \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 504) (shift_right << 19) | (mask << 24) | (invert << 22), \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 505) .tlv = { .p = (xtlv) } }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 506)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 507) static int snd_cs4236_info_double(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info *uinfo)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 508) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 509) int mask = (kcontrol->private_value >> 24) & 0xff;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 510)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 511) uinfo->type = mask == 1 ? SNDRV_CTL_ELEM_TYPE_BOOLEAN : SNDRV_CTL_ELEM_TYPE_INTEGER;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 512) uinfo->count = 2;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 513) uinfo->value.integer.min = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 514) uinfo->value.integer.max = mask;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 515) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 516) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 517)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 518) static int snd_cs4236_get_double(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 519) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 520) struct snd_wss *chip = snd_kcontrol_chip(kcontrol);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 521) unsigned long flags;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 522) int left_reg = kcontrol->private_value & 0xff;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 523) int right_reg = (kcontrol->private_value >> 8) & 0xff;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 524) int shift_left = (kcontrol->private_value >> 16) & 0x07;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 525) int shift_right = (kcontrol->private_value >> 19) & 0x07;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 526) int mask = (kcontrol->private_value >> 24) & 0xff;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 527) int invert = (kcontrol->private_value >> 22) & 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 528)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 529) spin_lock_irqsave(&chip->reg_lock, flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 530) ucontrol->value.integer.value[0] = (chip->eimage[CS4236_REG(left_reg)] >> shift_left) & mask;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 531) ucontrol->value.integer.value[1] = (chip->eimage[CS4236_REG(right_reg)] >> shift_right) & mask;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 532) spin_unlock_irqrestore(&chip->reg_lock, flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 533) if (invert) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 534) ucontrol->value.integer.value[0] = mask - ucontrol->value.integer.value[0];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 535) ucontrol->value.integer.value[1] = mask - ucontrol->value.integer.value[1];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 536) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 537) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 538) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 539)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 540) static int snd_cs4236_put_double(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 541) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 542) struct snd_wss *chip = snd_kcontrol_chip(kcontrol);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 543) unsigned long flags;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 544) int left_reg = kcontrol->private_value & 0xff;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 545) int right_reg = (kcontrol->private_value >> 8) & 0xff;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 546) int shift_left = (kcontrol->private_value >> 16) & 0x07;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 547) int shift_right = (kcontrol->private_value >> 19) & 0x07;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 548) int mask = (kcontrol->private_value >> 24) & 0xff;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 549) int invert = (kcontrol->private_value >> 22) & 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 550) int change;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 551) unsigned short val1, val2;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 552)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 553) val1 = ucontrol->value.integer.value[0] & mask;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 554) val2 = ucontrol->value.integer.value[1] & mask;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 555) if (invert) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 556) val1 = mask - val1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 557) val2 = mask - val2;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 558) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 559) val1 <<= shift_left;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 560) val2 <<= shift_right;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 561) spin_lock_irqsave(&chip->reg_lock, flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 562) if (left_reg != right_reg) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 563) val1 = (chip->eimage[CS4236_REG(left_reg)] & ~(mask << shift_left)) | val1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 564) val2 = (chip->eimage[CS4236_REG(right_reg)] & ~(mask << shift_right)) | val2;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 565) change = val1 != chip->eimage[CS4236_REG(left_reg)] || val2 != chip->eimage[CS4236_REG(right_reg)];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 566) snd_cs4236_ext_out(chip, left_reg, val1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 567) snd_cs4236_ext_out(chip, right_reg, val2);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 568) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 569) val1 = (chip->eimage[CS4236_REG(left_reg)] & ~((mask << shift_left) | (mask << shift_right))) | val1 | val2;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 570) change = val1 != chip->eimage[CS4236_REG(left_reg)];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 571) snd_cs4236_ext_out(chip, left_reg, val1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 572) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 573) spin_unlock_irqrestore(&chip->reg_lock, flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 574) return change;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 575) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 576)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 577) #define CS4236_DOUBLE1(xname, xindex, left_reg, right_reg, shift_left, \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 578) shift_right, mask, invert) \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 579) { .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = xname, .index = xindex, \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 580) .info = snd_cs4236_info_double, \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 581) .get = snd_cs4236_get_double1, .put = snd_cs4236_put_double1, \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 582) .private_value = left_reg | (right_reg << 8) | (shift_left << 16) | (shift_right << 19) | (mask << 24) | (invert << 22) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 583)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 584) #define CS4236_DOUBLE1_TLV(xname, xindex, left_reg, right_reg, shift_left, \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 585) shift_right, mask, invert, xtlv) \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 586) { .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = xname, .index = xindex, \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 587) .access = SNDRV_CTL_ELEM_ACCESS_READWRITE | SNDRV_CTL_ELEM_ACCESS_TLV_READ, \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 588) .info = snd_cs4236_info_double, \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 589) .get = snd_cs4236_get_double1, .put = snd_cs4236_put_double1, \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 590) .private_value = left_reg | (right_reg << 8) | (shift_left << 16) | \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 591) (shift_right << 19) | (mask << 24) | (invert << 22), \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 592) .tlv = { .p = (xtlv) } }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 593)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 594) static int snd_cs4236_get_double1(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 595) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 596) struct snd_wss *chip = snd_kcontrol_chip(kcontrol);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 597) unsigned long flags;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 598) int left_reg = kcontrol->private_value & 0xff;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 599) int right_reg = (kcontrol->private_value >> 8) & 0xff;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 600) int shift_left = (kcontrol->private_value >> 16) & 0x07;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 601) int shift_right = (kcontrol->private_value >> 19) & 0x07;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 602) int mask = (kcontrol->private_value >> 24) & 0xff;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 603) int invert = (kcontrol->private_value >> 22) & 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 604)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 605) spin_lock_irqsave(&chip->reg_lock, flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 606) ucontrol->value.integer.value[0] = (chip->image[left_reg] >> shift_left) & mask;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 607) ucontrol->value.integer.value[1] = (chip->eimage[CS4236_REG(right_reg)] >> shift_right) & mask;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 608) spin_unlock_irqrestore(&chip->reg_lock, flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 609) if (invert) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 610) ucontrol->value.integer.value[0] = mask - ucontrol->value.integer.value[0];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 611) ucontrol->value.integer.value[1] = mask - ucontrol->value.integer.value[1];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 612) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 613) return 0;
^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) static int snd_cs4236_put_double1(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 617) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 618) struct snd_wss *chip = snd_kcontrol_chip(kcontrol);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 619) unsigned long flags;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 620) int left_reg = kcontrol->private_value & 0xff;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 621) int right_reg = (kcontrol->private_value >> 8) & 0xff;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 622) int shift_left = (kcontrol->private_value >> 16) & 0x07;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 623) int shift_right = (kcontrol->private_value >> 19) & 0x07;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 624) int mask = (kcontrol->private_value >> 24) & 0xff;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 625) int invert = (kcontrol->private_value >> 22) & 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 626) int change;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 627) unsigned short val1, val2;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 628)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 629) val1 = ucontrol->value.integer.value[0] & mask;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 630) val2 = ucontrol->value.integer.value[1] & mask;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 631) if (invert) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 632) val1 = mask - val1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 633) val2 = mask - val2;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 634) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 635) val1 <<= shift_left;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 636) val2 <<= shift_right;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 637) spin_lock_irqsave(&chip->reg_lock, flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 638) val1 = (chip->image[left_reg] & ~(mask << shift_left)) | val1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 639) val2 = (chip->eimage[CS4236_REG(right_reg)] & ~(mask << shift_right)) | val2;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 640) change = val1 != chip->image[left_reg] || val2 != chip->eimage[CS4236_REG(right_reg)];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 641) snd_wss_out(chip, left_reg, val1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 642) snd_cs4236_ext_out(chip, right_reg, val2);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 643) spin_unlock_irqrestore(&chip->reg_lock, flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 644) return change;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 645) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 646)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 647) #define CS4236_MASTER_DIGITAL(xname, xindex, xtlv) \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 648) { .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = xname, .index = xindex, \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 649) .access = SNDRV_CTL_ELEM_ACCESS_READWRITE | SNDRV_CTL_ELEM_ACCESS_TLV_READ, \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 650) .info = snd_cs4236_info_double, \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 651) .get = snd_cs4236_get_master_digital, .put = snd_cs4236_put_master_digital, \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 652) .private_value = 71 << 24, \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 653) .tlv = { .p = (xtlv) } }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 654)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 655) static inline int snd_cs4236_mixer_master_digital_invert_volume(int vol)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 656) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 657) return (vol < 64) ? 63 - vol : 64 + (71 - vol);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 658) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 659)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 660) static int snd_cs4236_get_master_digital(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 661) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 662) struct snd_wss *chip = snd_kcontrol_chip(kcontrol);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 663) unsigned long flags;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 664)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 665) spin_lock_irqsave(&chip->reg_lock, flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 666) ucontrol->value.integer.value[0] = snd_cs4236_mixer_master_digital_invert_volume(chip->eimage[CS4236_REG(CS4236_LEFT_MASTER)] & 0x7f);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 667) ucontrol->value.integer.value[1] = snd_cs4236_mixer_master_digital_invert_volume(chip->eimage[CS4236_REG(CS4236_RIGHT_MASTER)] & 0x7f);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 668) spin_unlock_irqrestore(&chip->reg_lock, flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 669) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 670) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 671)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 672) static int snd_cs4236_put_master_digital(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 673) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 674) struct snd_wss *chip = snd_kcontrol_chip(kcontrol);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 675) unsigned long flags;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 676) int change;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 677) unsigned short val1, val2;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 678)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 679) val1 = snd_cs4236_mixer_master_digital_invert_volume(ucontrol->value.integer.value[0] & 0x7f);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 680) val2 = snd_cs4236_mixer_master_digital_invert_volume(ucontrol->value.integer.value[1] & 0x7f);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 681) spin_lock_irqsave(&chip->reg_lock, flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 682) val1 = (chip->eimage[CS4236_REG(CS4236_LEFT_MASTER)] & ~0x7f) | val1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 683) val2 = (chip->eimage[CS4236_REG(CS4236_RIGHT_MASTER)] & ~0x7f) | val2;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 684) change = val1 != chip->eimage[CS4236_REG(CS4236_LEFT_MASTER)] || val2 != chip->eimage[CS4236_REG(CS4236_RIGHT_MASTER)];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 685) snd_cs4236_ext_out(chip, CS4236_LEFT_MASTER, val1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 686) snd_cs4236_ext_out(chip, CS4236_RIGHT_MASTER, val2);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 687) spin_unlock_irqrestore(&chip->reg_lock, flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 688) return change;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 689) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 690)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 691) #define CS4235_OUTPUT_ACCU(xname, xindex, xtlv) \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 692) { .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = xname, .index = xindex, \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 693) .access = SNDRV_CTL_ELEM_ACCESS_READWRITE | SNDRV_CTL_ELEM_ACCESS_TLV_READ, \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 694) .info = snd_cs4236_info_double, \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 695) .get = snd_cs4235_get_output_accu, .put = snd_cs4235_put_output_accu, \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 696) .private_value = 3 << 24, \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 697) .tlv = { .p = (xtlv) } }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 698)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 699) static inline int snd_cs4235_mixer_output_accu_get_volume(int vol)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 700) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 701) switch ((vol >> 5) & 3) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 702) case 0: return 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 703) case 1: return 3;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 704) case 2: return 2;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 705) case 3: return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 706) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 707) return 3;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 708) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 709)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 710) static inline int snd_cs4235_mixer_output_accu_set_volume(int vol)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 711) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 712) switch (vol & 3) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 713) case 0: return 3 << 5;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 714) case 1: return 0 << 5;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 715) case 2: return 2 << 5;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 716) case 3: return 1 << 5;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 717) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 718) return 1 << 5;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 719) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 720)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 721) static int snd_cs4235_get_output_accu(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 722) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 723) struct snd_wss *chip = snd_kcontrol_chip(kcontrol);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 724) unsigned long flags;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 725)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 726) spin_lock_irqsave(&chip->reg_lock, flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 727) ucontrol->value.integer.value[0] = snd_cs4235_mixer_output_accu_get_volume(chip->image[CS4235_LEFT_MASTER]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 728) ucontrol->value.integer.value[1] = snd_cs4235_mixer_output_accu_get_volume(chip->image[CS4235_RIGHT_MASTER]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 729) spin_unlock_irqrestore(&chip->reg_lock, flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 730) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 731) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 732)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 733) static int snd_cs4235_put_output_accu(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 734) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 735) struct snd_wss *chip = snd_kcontrol_chip(kcontrol);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 736) unsigned long flags;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 737) int change;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 738) unsigned short val1, val2;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 739)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 740) val1 = snd_cs4235_mixer_output_accu_set_volume(ucontrol->value.integer.value[0]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 741) val2 = snd_cs4235_mixer_output_accu_set_volume(ucontrol->value.integer.value[1]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 742) spin_lock_irqsave(&chip->reg_lock, flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 743) val1 = (chip->image[CS4235_LEFT_MASTER] & ~(3 << 5)) | val1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 744) val2 = (chip->image[CS4235_RIGHT_MASTER] & ~(3 << 5)) | val2;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 745) change = val1 != chip->image[CS4235_LEFT_MASTER] || val2 != chip->image[CS4235_RIGHT_MASTER];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 746) snd_wss_out(chip, CS4235_LEFT_MASTER, val1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 747) snd_wss_out(chip, CS4235_RIGHT_MASTER, val2);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 748) spin_unlock_irqrestore(&chip->reg_lock, flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 749) return change;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 750) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 751)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 752) static const DECLARE_TLV_DB_SCALE(db_scale_7bit, -9450, 150, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 753) static const DECLARE_TLV_DB_SCALE(db_scale_6bit, -9450, 150, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 754) static const DECLARE_TLV_DB_SCALE(db_scale_6bit_12db_max, -8250, 150, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 755) static const DECLARE_TLV_DB_SCALE(db_scale_5bit_12db_max, -3450, 150, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 756) static const DECLARE_TLV_DB_SCALE(db_scale_5bit_22db_max, -2400, 150, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 757) static const DECLARE_TLV_DB_SCALE(db_scale_4bit, -4500, 300, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 758) static const DECLARE_TLV_DB_SCALE(db_scale_2bit, -1800, 600, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 759) static const DECLARE_TLV_DB_SCALE(db_scale_rec_gain, 0, 150, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 760)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 761) static const struct snd_kcontrol_new snd_cs4236_controls[] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 762)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 763) CS4236_DOUBLE("Master Digital Playback Switch", 0,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 764) CS4236_LEFT_MASTER, CS4236_RIGHT_MASTER, 7, 7, 1, 1),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 765) CS4236_DOUBLE("Master Digital Capture Switch", 0,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 766) CS4236_DAC_MUTE, CS4236_DAC_MUTE, 7, 6, 1, 1),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 767) CS4236_MASTER_DIGITAL("Master Digital Volume", 0, db_scale_7bit),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 768)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 769) CS4236_DOUBLE_TLV("Capture Boost Volume", 0,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 770) CS4236_LEFT_MIX_CTRL, CS4236_RIGHT_MIX_CTRL, 5, 5, 3, 1,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 771) db_scale_2bit),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 772)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 773) WSS_DOUBLE("PCM Playback Switch", 0,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 774) CS4231_LEFT_OUTPUT, CS4231_RIGHT_OUTPUT, 7, 7, 1, 1),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 775) WSS_DOUBLE_TLV("PCM Playback Volume", 0,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 776) CS4231_LEFT_OUTPUT, CS4231_RIGHT_OUTPUT, 0, 0, 63, 1,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 777) db_scale_6bit),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 778)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 779) CS4236_DOUBLE("DSP Playback Switch", 0,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 780) CS4236_LEFT_DSP, CS4236_RIGHT_DSP, 7, 7, 1, 1),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 781) CS4236_DOUBLE_TLV("DSP Playback Volume", 0,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 782) CS4236_LEFT_DSP, CS4236_RIGHT_DSP, 0, 0, 63, 1,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 783) db_scale_6bit),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 784)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 785) CS4236_DOUBLE("FM Playback Switch", 0,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 786) CS4236_LEFT_FM, CS4236_RIGHT_FM, 7, 7, 1, 1),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 787) CS4236_DOUBLE_TLV("FM Playback Volume", 0,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 788) CS4236_LEFT_FM, CS4236_RIGHT_FM, 0, 0, 63, 1,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 789) db_scale_6bit),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 790)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 791) CS4236_DOUBLE("Wavetable Playback Switch", 0,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 792) CS4236_LEFT_WAVE, CS4236_RIGHT_WAVE, 7, 7, 1, 1),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 793) CS4236_DOUBLE_TLV("Wavetable Playback Volume", 0,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 794) CS4236_LEFT_WAVE, CS4236_RIGHT_WAVE, 0, 0, 63, 1,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 795) db_scale_6bit_12db_max),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 796)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 797) WSS_DOUBLE("Synth Playback Switch", 0,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 798) CS4231_LEFT_LINE_IN, CS4231_RIGHT_LINE_IN, 7, 7, 1, 1),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 799) WSS_DOUBLE_TLV("Synth Volume", 0,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 800) CS4231_LEFT_LINE_IN, CS4231_RIGHT_LINE_IN, 0, 0, 31, 1,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 801) db_scale_5bit_12db_max),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 802) WSS_DOUBLE("Synth Capture Switch", 0,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 803) CS4231_LEFT_LINE_IN, CS4231_RIGHT_LINE_IN, 6, 6, 1, 1),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 804) WSS_DOUBLE("Synth Capture Bypass", 0,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 805) CS4231_LEFT_LINE_IN, CS4231_RIGHT_LINE_IN, 5, 5, 1, 1),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 806)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 807) CS4236_DOUBLE("Mic Playback Switch", 0,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 808) CS4236_LEFT_MIC, CS4236_RIGHT_MIC, 6, 6, 1, 1),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 809) CS4236_DOUBLE("Mic Capture Switch", 0,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 810) CS4236_LEFT_MIC, CS4236_RIGHT_MIC, 7, 7, 1, 1),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 811) CS4236_DOUBLE_TLV("Mic Volume", 0, CS4236_LEFT_MIC, CS4236_RIGHT_MIC,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 812) 0, 0, 31, 1, db_scale_5bit_22db_max),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 813) CS4236_DOUBLE("Mic Playback Boost (+20dB)", 0,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 814) CS4236_LEFT_MIC, CS4236_RIGHT_MIC, 5, 5, 1, 0),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 815)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 816) WSS_DOUBLE("Line Playback Switch", 0,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 817) CS4231_AUX1_LEFT_INPUT, CS4231_AUX1_RIGHT_INPUT, 7, 7, 1, 1),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 818) WSS_DOUBLE_TLV("Line Volume", 0,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 819) CS4231_AUX1_LEFT_INPUT, CS4231_AUX1_RIGHT_INPUT, 0, 0, 31, 1,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 820) db_scale_5bit_12db_max),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 821) WSS_DOUBLE("Line Capture Switch", 0,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 822) CS4231_AUX1_LEFT_INPUT, CS4231_AUX1_RIGHT_INPUT, 6, 6, 1, 1),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 823) WSS_DOUBLE("Line Capture Bypass", 0,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 824) CS4231_AUX1_LEFT_INPUT, CS4231_AUX1_RIGHT_INPUT, 5, 5, 1, 1),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 825)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 826) WSS_DOUBLE("CD Playback Switch", 0,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 827) CS4231_AUX2_LEFT_INPUT, CS4231_AUX2_RIGHT_INPUT, 7, 7, 1, 1),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 828) WSS_DOUBLE_TLV("CD Volume", 0,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 829) CS4231_AUX2_LEFT_INPUT, CS4231_AUX2_RIGHT_INPUT, 0, 0, 31, 1,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 830) db_scale_5bit_12db_max),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 831) WSS_DOUBLE("CD Capture Switch", 0,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 832) CS4231_AUX2_LEFT_INPUT, CS4231_AUX2_RIGHT_INPUT, 6, 6, 1, 1),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 833)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 834) CS4236_DOUBLE1("Mono Output Playback Switch", 0,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 835) CS4231_MONO_CTRL, CS4236_RIGHT_MIX_CTRL, 6, 7, 1, 1),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 836) CS4236_DOUBLE1("Beep Playback Switch", 0,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 837) CS4231_MONO_CTRL, CS4236_LEFT_MIX_CTRL, 7, 7, 1, 1),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 838) WSS_SINGLE_TLV("Beep Playback Volume", 0, CS4231_MONO_CTRL, 0, 15, 1,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 839) db_scale_4bit),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 840) WSS_SINGLE("Beep Bypass Playback Switch", 0, CS4231_MONO_CTRL, 5, 1, 0),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 841)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 842) WSS_DOUBLE_TLV("Capture Volume", 0, CS4231_LEFT_INPUT, CS4231_RIGHT_INPUT,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 843) 0, 0, 15, 0, db_scale_rec_gain),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 844) WSS_DOUBLE("Analog Loopback Capture Switch", 0,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 845) CS4231_LEFT_INPUT, CS4231_RIGHT_INPUT, 7, 7, 1, 0),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 846)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 847) WSS_SINGLE("Loopback Digital Playback Switch", 0, CS4231_LOOPBACK, 0, 1, 0),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 848) CS4236_DOUBLE1_TLV("Loopback Digital Playback Volume", 0,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 849) CS4231_LOOPBACK, CS4236_RIGHT_LOOPBACK, 2, 0, 63, 1,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 850) db_scale_6bit),
^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 DECLARE_TLV_DB_SCALE(db_scale_5bit_6db_max, -5600, 200, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 854) static const DECLARE_TLV_DB_SCALE(db_scale_2bit_16db_max, -2400, 800, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 855)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 856) static const struct snd_kcontrol_new snd_cs4235_controls[] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 857)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 858) WSS_DOUBLE("Master Playback Switch", 0,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 859) CS4235_LEFT_MASTER, CS4235_RIGHT_MASTER, 7, 7, 1, 1),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 860) WSS_DOUBLE_TLV("Master Playback Volume", 0,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 861) CS4235_LEFT_MASTER, CS4235_RIGHT_MASTER, 0, 0, 31, 1,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 862) db_scale_5bit_6db_max),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 863)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 864) CS4235_OUTPUT_ACCU("Playback Volume", 0, db_scale_2bit_16db_max),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 865)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 866) WSS_DOUBLE("Synth Playback Switch", 1,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 867) CS4231_LEFT_LINE_IN, CS4231_RIGHT_LINE_IN, 7, 7, 1, 1),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 868) WSS_DOUBLE("Synth Capture Switch", 1,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 869) CS4231_LEFT_LINE_IN, CS4231_RIGHT_LINE_IN, 6, 6, 1, 1),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 870) WSS_DOUBLE_TLV("Synth Volume", 1,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 871) CS4231_LEFT_LINE_IN, CS4231_RIGHT_LINE_IN, 0, 0, 31, 1,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 872) db_scale_5bit_12db_max),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 873)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 874) CS4236_DOUBLE_TLV("Capture Volume", 0,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 875) CS4236_LEFT_MIX_CTRL, CS4236_RIGHT_MIX_CTRL, 5, 5, 3, 1,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 876) db_scale_2bit),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 877)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 878) WSS_DOUBLE("PCM Playback Switch", 0,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 879) CS4231_LEFT_OUTPUT, CS4231_RIGHT_OUTPUT, 7, 7, 1, 1),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 880) WSS_DOUBLE("PCM Capture Switch", 0,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 881) CS4236_DAC_MUTE, CS4236_DAC_MUTE, 7, 6, 1, 1),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 882) WSS_DOUBLE_TLV("PCM Volume", 0,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 883) CS4231_LEFT_OUTPUT, CS4231_RIGHT_OUTPUT, 0, 0, 63, 1,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 884) db_scale_6bit),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 885)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 886) CS4236_DOUBLE("DSP Switch", 0, CS4236_LEFT_DSP, CS4236_RIGHT_DSP, 7, 7, 1, 1),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 887)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 888) CS4236_DOUBLE("FM Switch", 0, CS4236_LEFT_FM, CS4236_RIGHT_FM, 7, 7, 1, 1),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 889)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 890) CS4236_DOUBLE("Wavetable Switch", 0,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 891) CS4236_LEFT_WAVE, CS4236_RIGHT_WAVE, 7, 7, 1, 1),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 892)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 893) CS4236_DOUBLE("Mic Capture Switch", 0,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 894) CS4236_LEFT_MIC, CS4236_RIGHT_MIC, 7, 7, 1, 1),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 895) CS4236_DOUBLE("Mic Playback Switch", 0,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 896) CS4236_LEFT_MIC, CS4236_RIGHT_MIC, 6, 6, 1, 1),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 897) CS4236_SINGLE_TLV("Mic Volume", 0, CS4236_LEFT_MIC, 0, 31, 1,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 898) db_scale_5bit_22db_max),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 899) CS4236_SINGLE("Mic Boost (+20dB)", 0, CS4236_LEFT_MIC, 5, 1, 0),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 900)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 901) WSS_DOUBLE("Line Playback Switch", 0,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 902) CS4231_AUX1_LEFT_INPUT, CS4231_AUX1_RIGHT_INPUT, 7, 7, 1, 1),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 903) WSS_DOUBLE("Line Capture Switch", 0,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 904) CS4231_AUX1_LEFT_INPUT, CS4231_AUX1_RIGHT_INPUT, 6, 6, 1, 1),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 905) WSS_DOUBLE_TLV("Line Volume", 0,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 906) CS4231_AUX1_LEFT_INPUT, CS4231_AUX1_RIGHT_INPUT, 0, 0, 31, 1,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 907) db_scale_5bit_12db_max),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 908)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 909) WSS_DOUBLE("CD Playback Switch", 1,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 910) CS4231_AUX2_LEFT_INPUT, CS4231_AUX2_RIGHT_INPUT, 7, 7, 1, 1),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 911) WSS_DOUBLE("CD Capture Switch", 1,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 912) CS4231_AUX2_LEFT_INPUT, CS4231_AUX2_RIGHT_INPUT, 6, 6, 1, 1),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 913) WSS_DOUBLE_TLV("CD Volume", 1,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 914) CS4231_AUX2_LEFT_INPUT, CS4231_AUX2_RIGHT_INPUT, 0, 0, 31, 1,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 915) db_scale_5bit_12db_max),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 916)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 917) CS4236_DOUBLE1("Beep Playback Switch", 0,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 918) CS4231_MONO_CTRL, CS4236_LEFT_MIX_CTRL, 7, 7, 1, 1),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 919) WSS_SINGLE("Beep Playback Volume", 0, CS4231_MONO_CTRL, 0, 15, 1),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 920)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 921) WSS_DOUBLE("Analog Loopback Switch", 0,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 922) CS4231_LEFT_INPUT, CS4231_RIGHT_INPUT, 7, 7, 1, 0),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 923) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 924)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 925) #define CS4236_IEC958_ENABLE(xname, xindex) \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 926) { .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = xname, .index = xindex, \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 927) .info = snd_cs4236_info_single, \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 928) .get = snd_cs4236_get_iec958_switch, .put = snd_cs4236_put_iec958_switch, \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 929) .private_value = 1 << 16 }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 930)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 931) static int snd_cs4236_get_iec958_switch(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 932) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 933) struct snd_wss *chip = snd_kcontrol_chip(kcontrol);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 934) unsigned long flags;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 935)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 936) spin_lock_irqsave(&chip->reg_lock, flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 937) ucontrol->value.integer.value[0] = chip->image[CS4231_ALT_FEATURE_1] & 0x02 ? 1 : 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 938) #if 0
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 939) printk(KERN_DEBUG "get valid: ALT = 0x%x, C3 = 0x%x, C4 = 0x%x, "
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 940) "C5 = 0x%x, C6 = 0x%x, C8 = 0x%x\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 941) snd_wss_in(chip, CS4231_ALT_FEATURE_1),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 942) snd_cs4236_ctrl_in(chip, 3),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 943) snd_cs4236_ctrl_in(chip, 4),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 944) snd_cs4236_ctrl_in(chip, 5),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 945) snd_cs4236_ctrl_in(chip, 6),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 946) snd_cs4236_ctrl_in(chip, 8));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 947) #endif
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 948) spin_unlock_irqrestore(&chip->reg_lock, flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 949) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 950) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 951)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 952) static int snd_cs4236_put_iec958_switch(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 953) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 954) struct snd_wss *chip = snd_kcontrol_chip(kcontrol);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 955) unsigned long flags;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 956) int change;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 957) unsigned short enable, val;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 958)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 959) enable = ucontrol->value.integer.value[0] & 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 960)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 961) mutex_lock(&chip->mce_mutex);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 962) snd_wss_mce_up(chip);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 963) spin_lock_irqsave(&chip->reg_lock, flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 964) val = (chip->image[CS4231_ALT_FEATURE_1] & ~0x0e) | (0<<2) | (enable << 1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 965) change = val != chip->image[CS4231_ALT_FEATURE_1];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 966) snd_wss_out(chip, CS4231_ALT_FEATURE_1, val);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 967) val = snd_cs4236_ctrl_in(chip, 4) | 0xc0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 968) snd_cs4236_ctrl_out(chip, 4, val);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 969) udelay(100);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 970) val &= ~0x40;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 971) snd_cs4236_ctrl_out(chip, 4, val);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 972) spin_unlock_irqrestore(&chip->reg_lock, flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 973) snd_wss_mce_down(chip);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 974) mutex_unlock(&chip->mce_mutex);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 975)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 976) #if 0
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 977) printk(KERN_DEBUG "set valid: ALT = 0x%x, C3 = 0x%x, C4 = 0x%x, "
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 978) "C5 = 0x%x, C6 = 0x%x, C8 = 0x%x\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 979) snd_wss_in(chip, CS4231_ALT_FEATURE_1),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 980) snd_cs4236_ctrl_in(chip, 3),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 981) snd_cs4236_ctrl_in(chip, 4),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 982) snd_cs4236_ctrl_in(chip, 5),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 983) snd_cs4236_ctrl_in(chip, 6),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 984) snd_cs4236_ctrl_in(chip, 8));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 985) #endif
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 986) return change;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 987) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 988)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 989) static const struct snd_kcontrol_new snd_cs4236_iec958_controls[] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 990) CS4236_IEC958_ENABLE("IEC958 Output Enable", 0),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 991) CS4236_SINGLEC("IEC958 Output Validity", 0, 4, 4, 1, 0),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 992) CS4236_SINGLEC("IEC958 Output User", 0, 4, 5, 1, 0),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 993) CS4236_SINGLEC("IEC958 Output CSBR", 0, 4, 6, 1, 0),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 994) CS4236_SINGLEC("IEC958 Output Channel Status Low", 0, 5, 1, 127, 0),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 995) CS4236_SINGLEC("IEC958 Output Channel Status High", 0, 6, 0, 255, 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 996) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 997)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 998) static const struct snd_kcontrol_new snd_cs4236_3d_controls_cs4235[] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 999) CS4236_SINGLEC("3D Control - Switch", 0, 3, 4, 1, 0),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1000) CS4236_SINGLEC("3D Control - Space", 0, 2, 4, 15, 1)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1001) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1002)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1003) static const struct snd_kcontrol_new snd_cs4236_3d_controls_cs4237[] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1004) CS4236_SINGLEC("3D Control - Switch", 0, 3, 7, 1, 0),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1005) CS4236_SINGLEC("3D Control - Space", 0, 2, 4, 15, 1),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1006) CS4236_SINGLEC("3D Control - Center", 0, 2, 0, 15, 1),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1007) CS4236_SINGLEC("3D Control - Mono", 0, 3, 6, 1, 0),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1008) CS4236_SINGLEC("3D Control - IEC958", 0, 3, 5, 1, 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1009) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1010)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1011) static const struct snd_kcontrol_new snd_cs4236_3d_controls_cs4238[] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1012) CS4236_SINGLEC("3D Control - Switch", 0, 3, 4, 1, 0),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1013) CS4236_SINGLEC("3D Control - Space", 0, 2, 4, 15, 1),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1014) CS4236_SINGLEC("3D Control - Volume", 0, 2, 0, 15, 1),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1015) CS4236_SINGLEC("3D Control - IEC958", 0, 3, 5, 1, 0)
^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) int snd_cs4236_mixer(struct snd_wss *chip)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1019) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1020) struct snd_card *card;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1021) unsigned int idx, count;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1022) int err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1023) const struct snd_kcontrol_new *kcontrol;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1024)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1025) if (snd_BUG_ON(!chip || !chip->card))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1026) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1027) card = chip->card;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1028) strcpy(card->mixername, snd_wss_chip_id(chip));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1029)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1030) if (chip->hardware == WSS_HW_CS4235 ||
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1031) chip->hardware == WSS_HW_CS4239) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1032) for (idx = 0; idx < ARRAY_SIZE(snd_cs4235_controls); idx++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1033) if ((err = snd_ctl_add(card, snd_ctl_new1(&snd_cs4235_controls[idx], chip))) < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1034) return err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1035) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1036) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1037) for (idx = 0; idx < ARRAY_SIZE(snd_cs4236_controls); idx++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1038) if ((err = snd_ctl_add(card, snd_ctl_new1(&snd_cs4236_controls[idx], chip))) < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1039) return err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1040) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1041) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1042) switch (chip->hardware) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1043) case WSS_HW_CS4235:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1044) case WSS_HW_CS4239:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1045) count = ARRAY_SIZE(snd_cs4236_3d_controls_cs4235);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1046) kcontrol = snd_cs4236_3d_controls_cs4235;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1047) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1048) case WSS_HW_CS4237B:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1049) count = ARRAY_SIZE(snd_cs4236_3d_controls_cs4237);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1050) kcontrol = snd_cs4236_3d_controls_cs4237;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1051) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1052) case WSS_HW_CS4238B:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1053) count = ARRAY_SIZE(snd_cs4236_3d_controls_cs4238);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1054) kcontrol = snd_cs4236_3d_controls_cs4238;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1055) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1056) default:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1057) count = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1058) kcontrol = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1059) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1060) for (idx = 0; idx < count; idx++, kcontrol++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1061) if ((err = snd_ctl_add(card, snd_ctl_new1(kcontrol, chip))) < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1062) return err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1063) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1064) if (chip->hardware == WSS_HW_CS4237B ||
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1065) chip->hardware == WSS_HW_CS4238B) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1066) for (idx = 0; idx < ARRAY_SIZE(snd_cs4236_iec958_controls); idx++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1067) if ((err = snd_ctl_add(card, snd_ctl_new1(&snd_cs4236_iec958_controls[idx], chip))) < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1068) return err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1069) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1070) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1071) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1072) }