summaryrefslogtreecommitdiffstats
path: root/drivers/staging/intel_sst/intelmid_v0_control.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/staging/intel_sst/intelmid_v0_control.c')
-rw-r--r--drivers/staging/intel_sst/intelmid_v0_control.c771
1 files changed, 771 insertions, 0 deletions
diff --git a/drivers/staging/intel_sst/intelmid_v0_control.c b/drivers/staging/intel_sst/intelmid_v0_control.c
new file mode 100644
index 0000000..f586d62
--- /dev/null
+++ b/drivers/staging/intel_sst/intelmid_v0_control.c
@@ -0,0 +1,771 @@
+/*
+ * intel_sst_v0_control.c - Intel SST Driver for audio engine
+ *
+ * Copyright (C) 2008-10 Intel Corporation
+ * Authors: Vinod Koul <vinod.koul@intel.com>
+ * Harsha Priya <priya.harsha@intel.com>
+ * Dharageswari R <dharageswari.r@intel.com>
+ * KP Jeeja <jeeja.kp@intel.com>
+ * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; version 2 of the License.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
+ *
+ * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ *
+ * This file contains the control operations of vendor 1
+ */
+
+#include <linux/pci.h>
+#include <linux/file.h>
+#include "intel_sst.h"
+#include "intelmid_snd_control.h"
+
+
+enum _reg_v1 {
+ VOICEPORT1 = 0x180,
+ VOICEPORT2 = 0x181,
+ AUDIOPORT1 = 0x182,
+ AUDIOPORT2 = 0x183,
+ MISCVOICECTRL = 0x184,
+ MISCAUDCTRL = 0x185,
+ DMICCTRL1 = 0x186,
+ AUDIOBIAS = 0x187,
+ MICCTRL = 0x188,
+ MICLICTRL1 = 0x189,
+ MICLICTRL2 = 0x18A,
+ MICLICTRL3 = 0x18B,
+ VOICEDACCTRL1 = 0x18C,
+ STEREOADCCTRL = 0x18D,
+ AUD15 = 0x18E,
+ AUD16 = 0x18F,
+ AUD17 = 0x190,
+ AUD18 = 0x191,
+ RMIXOUTSEL = 0x192,
+ ANALOGLBR = 0x193,
+ ANALOGLBL = 0x194,
+ POWERCTRL1 = 0x195,
+ POWERCTRL2 = 0x196,
+ HEADSETDETECTINT = 0x197,
+ HEADSETDETECTINTMASK = 0x198,
+ TRIMENABLE = 0x199,
+};
+
+int rev_id = 0x20;
+
+/****
+ * fs_init_card - initialize the sound card
+ *
+ * This initilizes the audio paths to know values in case of this sound card
+ */
+static int fs_init_card(void)
+{
+ struct sc_reg_access sc_access[] = {
+ {0x180, 0x00, 0x0},
+ {0x181, 0x00, 0x0},
+ {0x182, 0xF8, 0x0},
+ {0x183, 0x08, 0x0},
+ {0x184, 0x00, 0x0},
+ {0x185, 0x40, 0x0},
+ {0x186, 0x06, 0x0},
+ {0x187, 0x80, 0x0},
+ {0x188, 0x40, 0x0},
+ {0x189, 0x39, 0x0},
+ {0x18a, 0x39, 0x0},
+ {0x18b, 0x1F, 0x0},
+ {0x18c, 0x00, 0x0},
+ {0x18d, 0x00, 0x0},
+ {0x18e, 0x39, 0x0},
+ {0x18f, 0x39, 0x0},
+ {0x190, 0x39, 0x0},
+ {0x191, 0x11, 0x0},
+ {0x192, 0x0E, 0x0},
+ {0x193, 0x00, 0x0},
+ {0x194, 0x00, 0x0},
+ {0x195, 0x00, 0x0},
+ {0x196, 0x7C, 0x0},
+ {0x197, 0x00, 0x0},
+ {0x198, 0x0B, 0x0},
+ {0x199, 0x00, 0x0},
+ {0x037, 0x3F, 0x0},
+ };
+
+ snd_pmic_ops_fs.card_status = SND_CARD_INIT_DONE;
+ snd_pmic_ops_fs.master_mute = UNMUTE;
+ snd_pmic_ops_fs.mute_status = UNMUTE;
+ snd_pmic_ops_fs.num_channel = 2;
+ return sst_sc_reg_access(sc_access, PMIC_WRITE, 27);
+}
+
+static int fs_enable_audiodac(int value)
+{
+ struct sc_reg_access sc_access[3];
+ sc_access[0].reg_addr = AUD16;
+ sc_access[1].reg_addr = AUD17;
+ sc_access[2].reg_addr = AUD15;
+ sc_access[0].mask = sc_access[1].mask = sc_access[2].mask = MASK7;
+
+ if (snd_pmic_ops_fs.mute_status == MUTE)
+ return 0;
+ if (value == MUTE) {
+ sc_access[0].value = sc_access[1].value =
+ sc_access[2].value = 0x80;
+
+ } else {
+ sc_access[0].value = sc_access[1].value =
+ sc_access[2].value = 0x0;
+ }
+ if (snd_pmic_ops_fs.num_channel == 1)
+ sc_access[1].value = sc_access[2].value = 0x80;
+ return sst_sc_reg_access(sc_access, PMIC_READ_MODIFY, 3);
+
+}
+
+static int fs_power_up_pb(unsigned int port)
+{
+ struct sc_reg_access sc_access[] = {
+ {AUDIOBIAS, 0x00, MASK7},
+ {POWERCTRL1, 0xC6, 0xC6},
+ {POWERCTRL2, 0x30, 0x30},
+
+ };
+ int retval = 0;
+
+ if (snd_pmic_ops_fs.card_status == SND_CARD_UN_INIT)
+ retval = fs_init_card();
+ if (retval)
+ return retval;
+ retval = fs_enable_audiodac(MUTE);
+ retval = sst_sc_reg_access(sc_access, PMIC_READ_MODIFY, 3);
+
+ if (retval)
+ return retval;
+
+ pr_debug("sst: in fs power up pb\n");
+ return fs_enable_audiodac(UNMUTE);
+}
+
+static int fs_power_down_pb(void)
+{
+ struct sc_reg_access sc_access[] = {
+ {POWERCTRL1, 0x00, 0xC6},
+ {POWERCTRL2, 0x00, 0x30},
+ };
+ int retval = 0;
+
+ if (snd_pmic_ops_fs.card_status == SND_CARD_UN_INIT)
+ retval = fs_init_card();
+ if (retval)
+ return retval;
+ retval = fs_enable_audiodac(MUTE);
+ retval = sst_sc_reg_access(sc_access, PMIC_READ_MODIFY, 2);
+
+ if (retval)
+ return retval;
+
+ pr_debug("sst: in fsl power down pb\n");
+ return fs_enable_audiodac(UNMUTE);
+}
+
+static int fs_power_up_cp(unsigned int port)
+{
+ struct sc_reg_access sc_access[] = {
+ {POWERCTRL2, 0x32, 0x32}, /*NOTE power up A ADC only as*/
+ {AUDIOBIAS, 0x00, MASK7},
+ /*as turning on V ADC causes noise*/
+ };
+ int retval = 0;
+
+ if (snd_pmic_ops_fs.card_status == SND_CARD_UN_INIT)
+ retval = fs_init_card();
+ if (retval)
+ return retval;
+ return sst_sc_reg_access(sc_access, PMIC_READ_MODIFY, 2);
+}
+
+static int fs_power_down_cp(void)
+{
+ struct sc_reg_access sc_access[] = {
+ {POWERCTRL2, 0x00, 0x03},
+ };
+ int retval = 0;
+
+ if (snd_pmic_ops_fs.card_status == SND_CARD_UN_INIT)
+ retval = fs_init_card();
+ if (retval)
+ return retval;
+ return sst_sc_reg_access(sc_access, PMIC_READ_MODIFY, 1);
+}
+
+static int fs_power_down(void)
+{
+ int retval = 0;
+ struct sc_reg_access sc_access[] = {
+ {AUDIOBIAS, MASK7, MASK7},
+ };
+
+ if (snd_pmic_ops_fs.card_status == SND_CARD_UN_INIT)
+ retval = fs_init_card();
+ if (retval)
+ return retval;
+ return sst_sc_reg_access(sc_access, PMIC_READ_MODIFY, 1);
+}
+
+static int fs_set_pcm_voice_params(void)
+{
+ struct sc_reg_access sc_access[] = {
+ {0x180, 0xA0, 0},
+ {0x181, 0x04, 0},
+ {0x182, 0x0, 0},
+ {0x183, 0x0, 0},
+ {0x184, 0x18, 0},
+ {0x185, 0x40, 0},
+ {0x186, 0x06, 0},
+ {0x187, 0x0, 0},
+ {0x188, 0x10, 0},
+ {0x189, 0x39, 0},
+ {0x18a, 0x39, 0},
+ {0x18b, 0x02, 0},
+ {0x18c, 0x0, 0},
+ {0x18d, 0x0, 0},
+ {0x18e, 0x39, 0},
+ {0x18f, 0x0, 0},
+ {0x190, 0x0, 0},
+ {0x191, 0x20, 0},
+ {0x192, 0x20, 0},
+ {0x193, 0x0, 0},
+ {0x194, 0x0, 0},
+ {0x195, 0x06, 0},
+ {0x196, 0x25, 0},
+ {0x197, 0x0, 0},
+ {0x198, 0xF, 0},
+ {0x199, 0x0, 0},
+ };
+ int retval = 0;
+
+ if (snd_pmic_ops_fs.card_status == SND_CARD_UN_INIT)
+ retval = fs_init_card();
+ if (retval)
+ return retval;
+ return sst_sc_reg_access(sc_access, PMIC_WRITE, 26);
+}
+
+static int fs_set_audio_port(int status)
+{
+ struct sc_reg_access sc_access[2];
+ int retval = 0;
+
+ if (snd_pmic_ops_fs.card_status == SND_CARD_UN_INIT)
+ retval = fs_init_card();
+ if (retval)
+ return retval;
+ if (status == DEACTIVATE) {
+ /* Deactivate audio port-tristate and power */
+ sc_access[0].value = 0x00;
+ sc_access[0].mask = MASK6|MASK7;
+ sc_access[0].reg_addr = AUDIOPORT1;
+ sc_access[1].value = 0x00;
+ sc_access[1].mask = MASK4|MASK5;
+ sc_access[1].reg_addr = POWERCTRL2;
+ return sst_sc_reg_access(sc_access, PMIC_READ_MODIFY, 2);
+ } else if (status == ACTIVATE) {
+ /* activate audio port */
+ sc_access[0].value = 0xC0;
+ sc_access[0].mask = MASK6|MASK7;
+ sc_access[0].reg_addr = AUDIOPORT1;
+ sc_access[1].value = 0x30;
+ sc_access[1].mask = MASK4|MASK5;
+ sc_access[1].reg_addr = POWERCTRL2;
+ return sst_sc_reg_access(sc_access, PMIC_READ_MODIFY, 2);
+ } else
+ return -EINVAL;
+}
+
+static int fs_set_voice_port(int status)
+{
+ struct sc_reg_access sc_access[2];
+ int retval = 0;
+
+ if (snd_pmic_ops_fs.card_status == SND_CARD_UN_INIT)
+ retval = fs_init_card();
+ if (retval)
+ return retval;
+ if (status == DEACTIVATE) {
+ /* Deactivate audio port-tristate and power */
+ sc_access[0].value = 0x00;
+ sc_access[0].mask = MASK6|MASK7;
+ sc_access[0].reg_addr = VOICEPORT1;
+ sc_access[1].value = 0x00;
+ sc_access[1].mask = MASK0|MASK1;
+ sc_access[1].reg_addr = POWERCTRL2;
+ return sst_sc_reg_access(sc_access, PMIC_READ_MODIFY, 2);
+ } else if (status == ACTIVATE) {
+ /* activate audio port */
+ sc_access[0].value = 0xC0;
+ sc_access[0].mask = MASK6|MASK7;
+ sc_access[0].reg_addr = VOICEPORT1;
+ sc_access[1].value = 0x03;
+ sc_access[1].mask = MASK0|MASK1;
+ sc_access[1].reg_addr = POWERCTRL2;
+ return sst_sc_reg_access(sc_access, PMIC_READ_MODIFY, 2);
+ } else
+ return -EINVAL;
+}
+
+static int fs_set_pcm_audio_params(int sfreq, int word_size, int num_channel)
+{
+ u8 config1 = 0;
+ struct sc_reg_access sc_access[4];
+ int retval = 0, num_value = 0;
+
+ if (snd_pmic_ops_fs.card_status == SND_CARD_UN_INIT)
+ retval = fs_init_card();
+ if (retval)
+ return retval;
+ switch (sfreq) {
+ case 8000:
+ config1 = 0x00;
+ break;
+ case 11025:
+ config1 = 0x01;
+ break;
+ case 12000:
+ config1 = 0x02;
+ break;
+ case 16000:
+ config1 = 0x03;
+ break;
+ case 22050:
+ config1 = 0x04;
+ break;
+ case 24000:
+ config1 = 0x05;
+ break;
+ case 26000:
+ config1 = 0x06;
+ break;
+ case 32000:
+ config1 = 0x07;
+ break;
+ case 44100:
+ config1 = 0x08;
+ break;
+ case 48000:
+ config1 = 0x09;
+ break;
+ }
+ snd_pmic_ops_fs.num_channel = num_channel;
+ if (snd_pmic_ops_fs.num_channel == 1) {
+ sc_access[0].reg_addr = AUD17;
+ sc_access[1].reg_addr = AUD15;
+ sc_access[0].mask = sc_access[1].mask = MASK7;
+ sc_access[0].value = sc_access[1].value = 0x80;
+ sst_sc_reg_access(sc_access, PMIC_READ_MODIFY, 2);
+
+ } else {
+ sc_access[0].reg_addr = AUD17;
+ sc_access[1].reg_addr = AUD15;
+ sc_access[0].mask = sc_access[1].mask = MASK7;
+ sc_access[0].value = sc_access[1].value = 0x00;
+ sst_sc_reg_access(sc_access, PMIC_READ_MODIFY, 2);
+
+ }
+ pr_debug("sst: sfreq:%d,Register value = %x\n", sfreq, config1);
+
+ if (word_size == 24) {
+ sc_access[0].reg_addr = AUDIOPORT1;
+ sc_access[0].mask = MASK0|MASK1|MASK2|MASK3;
+ sc_access[0].value = 0xFB;
+
+
+ sc_access[1].reg_addr = AUDIOPORT2;
+ sc_access[1].value = config1 | 0x10;
+ sc_access[1].mask = MASK0 | MASK1 | MASK2 | MASK3
+ | MASK4 | MASK5 | MASK6;
+
+ sc_access[2].reg_addr = MISCAUDCTRL;
+ sc_access[2].value = 0x02;
+ sc_access[2].mask = 0x02;
+
+ num_value = 3 ;
+
+ } else {
+
+ sc_access[0].reg_addr = AUDIOPORT2;
+ sc_access[0].value = config1;
+ sc_access[0].mask = MASK0|MASK1|MASK2|MASK3;
+
+ sc_access[1].reg_addr = MISCAUDCTRL;
+ sc_access[1].value = 0x00;
+ sc_access[1].mask = 0x02;
+ num_value = 2;
+ }
+ return sst_sc_reg_access(sc_access, PMIC_READ_MODIFY, num_value);
+
+}
+
+static int fs_set_selected_input_dev(u8 value)
+{
+ struct sc_reg_access sc_access_dmic[] = {
+ {MICCTRL, 0x81, 0xf7},
+ {MICLICTRL3, 0x00, 0xE0},
+ };
+ struct sc_reg_access sc_access_mic[] = {
+ {MICCTRL, 0x40, MASK2|MASK4|MASK5|MASK6|MASK7},
+ {MICLICTRL3, 0x00, 0xE0},
+ };
+ struct sc_reg_access sc_access_hsmic[] = {
+ {MICCTRL, 0x10, MASK2|MASK4|MASK5|MASK6|MASK7},
+ {MICLICTRL3, 0x00, 0xE0},
+ };
+
+ int retval = 0;
+
+ if (snd_pmic_ops_fs.card_status == SND_CARD_UN_INIT)
+ retval = fs_init_card();
+ if (retval)
+ return retval;
+
+ switch (value) {
+ case AMIC:
+ pr_debug("sst: Selecting amic not supported in mono cfg\n");
+ return sst_sc_reg_access(sc_access_mic, PMIC_READ_MODIFY, 2);
+ break;
+
+ case HS_MIC:
+ pr_debug("sst: Selecting hsmic\n");
+ return sst_sc_reg_access(sc_access_hsmic,
+ PMIC_READ_MODIFY, 2);
+ break;
+
+ case DMIC:
+ pr_debug("sst: Selecting dmic\n");
+ return sst_sc_reg_access(sc_access_dmic, PMIC_READ_MODIFY, 2);
+ break;
+
+ default:
+ return -EINVAL;
+
+ }
+}
+
+static int fs_set_selected_output_dev(u8 value)
+{
+ struct sc_reg_access sc_access_hp[] = {
+ {0x191, 0x11, 0x0},
+ {0x192, 0x0E, 0x0},
+ };
+ struct sc_reg_access sc_access_is[] = {
+ {0x191, 0x17, 0xFF},
+ {0x192, 0x08, 0xFF},
+ };
+ int retval = 0;
+
+ if (snd_pmic_ops_fs.card_status == SND_CARD_UN_INIT)
+ retval = fs_init_card();
+ if (retval)
+ return retval;
+
+ switch (value) {
+ case STEREO_HEADPHONE:
+ pr_debug("SST DBG:Selecting headphone\n");
+ return sst_sc_reg_access(sc_access_hp, PMIC_WRITE, 2);
+ break;
+ case MONO_EARPIECE:
+ case INTERNAL_SPKR:
+ pr_debug("SST DBG:Selecting internal spkr\n");
+ return sst_sc_reg_access(sc_access_is, PMIC_READ_MODIFY, 2);
+ break;
+
+ default:
+ return -EINVAL;
+
+ }
+}
+
+static int fs_set_mute(int dev_id, u8 value)
+{
+ struct sc_reg_access sc_access[6] = {{0,},};
+ int reg_num = 0;
+ int retval = 0;
+
+ if (snd_pmic_ops_fs.card_status == SND_CARD_UN_INIT)
+ retval = fs_init_card();
+ if (retval)
+ return retval;
+
+
+ pr_debug("sst: dev_id:0x%x value:0x%x\n", dev_id, value);
+ switch (dev_id) {
+ case PMIC_SND_DMIC_MUTE:
+ sc_access[0].reg_addr = MICCTRL;
+ sc_access[1].reg_addr = MICLICTRL1;
+ sc_access[2].reg_addr = MICLICTRL2;
+ sc_access[0].mask = MASK5;
+ sc_access[1].mask = sc_access[2].mask = MASK6;
+ if (value == MUTE) {
+ sc_access[0].value = 0x20;
+ sc_access[2].value = sc_access[1].value = 0x40;
+ } else
+ sc_access[0].value = sc_access[1].value
+ = sc_access[2].value = 0x0;
+ reg_num = 3;
+ break;
+ case PMIC_SND_HP_MIC_MUTE:
+ case PMIC_SND_AMIC_MUTE:
+ sc_access[0].reg_addr = MICLICTRL1;
+ sc_access[1].reg_addr = MICLICTRL2;
+ sc_access[0].mask = sc_access[1].mask = MASK6;
+ if (value == MUTE)
+ sc_access[0].value = sc_access[1].value = 0x40;
+ else
+ sc_access[0].value = sc_access[1].value = 0x0;
+ reg_num = 2;
+ break;
+ case PMIC_SND_LEFT_SPEAKER_MUTE:
+ case PMIC_SND_LEFT_HP_MUTE:
+ sc_access[0].reg_addr = AUD16;
+ sc_access[1].reg_addr = AUD15;
+
+ sc_access[0].mask = sc_access[1].mask = MASK7;
+ if (value == MUTE)
+ sc_access[0].value = sc_access[1].value = 0x80;
+ else
+ sc_access[0].value = sc_access[1].value = 0x0;
+ reg_num = 2;
+ snd_pmic_ops_fs.mute_status = value;
+ break;
+ case PMIC_SND_RIGHT_HP_MUTE:
+ case PMIC_SND_RIGHT_SPEAKER_MUTE:
+ sc_access[0].reg_addr = AUD17;
+ sc_access[1].reg_addr = AUD15;
+ sc_access[0].mask = sc_access[1].mask = MASK7;
+ if (value == MUTE)
+ sc_access[0].value = sc_access[1].value = 0x80;
+ else
+ sc_access[0].value = sc_access[1].value = 0x0;
+ snd_pmic_ops_fs.mute_status = value;
+ if (snd_pmic_ops_fs.num_channel == 1)
+ sc_access[0].value = sc_access[1].value = 0x80;
+ reg_num = 2;
+ break;
+ case PMIC_SND_MUTE_ALL:
+ sc_access[0].reg_addr = AUD16;
+ sc_access[1].reg_addr = AUD17;
+ sc_access[2].reg_addr = AUD15;
+ sc_access[3].reg_addr = MICCTRL;
+ sc_access[4].reg_addr = MICLICTRL1;
+ sc_access[5].reg_addr = MICLICTRL2;
+ sc_access[0].mask = sc_access[1].mask =
+ sc_access[2].mask = MASK7;
+ sc_access[3].mask = MASK5;
+ sc_access[4].mask = sc_access[5].mask = MASK6;
+
+ if (value == MUTE) {
+ sc_access[0].value =
+ sc_access[1].value = sc_access[2].value = 0x80;
+ sc_access[3].value = 0x20;
+ sc_access[4].value = sc_access[5].value = 0x40;
+
+ } else {
+ sc_access[0].value = sc_access[1].value =
+ sc_access[2].value = sc_access[3].value =
+ sc_access[4].value = sc_access[5].value = 0x0;
+ }
+ if (snd_pmic_ops_fs.num_channel == 1)
+ sc_access[1].value = sc_access[2].value = 0x80;
+ reg_num = 6;
+ snd_pmic_ops_fs.mute_status = value;
+ snd_pmic_ops_fs.master_mute = value;
+ break;
+
+ }
+ return sst_sc_reg_access(sc_access, PMIC_READ_MODIFY, reg_num);
+}
+
+static int fs_set_vol(int dev_id, int value)
+{
+ struct sc_reg_access sc_acces, sc_access[4] = {{0},};
+ int reg_num = 0;
+ int retval = 0;
+
+ if (snd_pmic_ops_fs.card_status == SND_CARD_UN_INIT)
+ retval = fs_init_card();
+ if (retval)
+ return retval;
+
+ switch (dev_id) {
+ case PMIC_SND_LEFT_PB_VOL:
+ pr_debug("sst: PMIC_SND_LEFT_PB_VOL:%d\n", value);
+ sc_access[0].value = sc_access[1].value = value;
+ sc_access[0].reg_addr = AUD16;
+ sc_access[1].reg_addr = AUD15;
+ sc_access[0].mask = sc_access[1].mask =
+ (MASK0|MASK1|MASK2|MASK3|MASK4|MASK5);
+ reg_num = 2;
+ break;
+
+ case PMIC_SND_RIGHT_PB_VOL:
+ pr_debug("sst: PMIC_SND_RIGHT_PB_VOL:%d\n", value);
+ sc_access[0].value = sc_access[1].value = value;
+ sc_access[0].reg_addr = AUD17;
+ sc_access[1].reg_addr = AUD15;
+ sc_access[0].mask = sc_access[1].mask =
+ (MASK0|MASK1|MASK2|MASK3|MASK4|MASK5);
+ if (snd_pmic_ops_fs.num_channel == 1) {
+ sc_access[0].value = sc_access[1].value = 0x80;
+ sc_access[0].mask = sc_access[1].mask = MASK7;
+ }
+ reg_num = 2;
+ break;
+ case PMIC_SND_CAPTURE_VOL:
+ pr_debug("sst: PMIC_SND_CAPTURE_VOL:%d\n", value);
+ sc_access[0].reg_addr = MICLICTRL1;
+ sc_access[1].reg_addr = MICLICTRL2;
+ sc_access[2].reg_addr = DMICCTRL1;
+ sc_access[2].value = value;
+ sc_access[0].value = sc_access[1].value = value;
+ sc_acces.reg_addr = MICLICTRL3;
+ sc_acces.value = value;
+ sc_acces.mask = (MASK0|MASK1|MASK2|MASK3|MASK5|MASK6|MASK7);
+ retval = sst_sc_reg_access(&sc_acces, PMIC_READ_MODIFY, 1);
+ sc_access[0].mask = sc_access[1].mask =
+ sc_access[2].mask = (MASK0|MASK1|MASK2|MASK3|MASK4|MASK5);
+ reg_num = 3;
+ break;
+
+ default:
+ return -EINVAL;
+ }
+
+ return sst_sc_reg_access(sc_access, PMIC_READ_MODIFY, reg_num);
+}
+
+static int fs_get_mute(int dev_id, u8 *value)
+{
+ struct sc_reg_access sc_access[6] = {{0,},};
+
+ int retval = 0, temp_value = 0, mask = 0;
+
+ if (snd_pmic_ops_fs.card_status == SND_CARD_UN_INIT)
+ retval = fs_init_card();
+ if (retval)
+ return retval;
+
+ switch (dev_id) {
+
+ case PMIC_SND_AMIC_MUTE:
+ case PMIC_SND_HP_MIC_MUTE:
+ sc_access[0].reg_addr = MICLICTRL1;
+ mask = MASK6;
+ retval = sst_sc_reg_access(sc_access, PMIC_READ, 1);
+ if (sc_access[0].value & mask)
+ *value = MUTE;
+ else
+ *value = UNMUTE;
+ break;
+ case PMIC_SND_DMIC_MUTE:
+ sc_access[0].reg_addr = MICCTRL;
+ mask = MASK5;
+ retval = sst_sc_reg_access(sc_access, PMIC_READ, 1);
+ temp_value = (sc_access[0].value & mask);
+ if (temp_value == 0)
+ *value = UNMUTE;
+ else
+ *value = MUTE;
+ break;
+
+ case PMIC_SND_LEFT_HP_MUTE:
+ case PMIC_SND_LEFT_SPEAKER_MUTE:
+ sc_access[0].reg_addr = AUD16;
+ mask = MASK7;
+ retval = sst_sc_reg_access(sc_access, PMIC_READ, 1);
+ temp_value = sc_access[0].value & mask;
+ if (temp_value == 0)
+ *value = UNMUTE;
+ else
+ *value = MUTE;
+ break;
+ case PMIC_SND_RIGHT_HP_MUTE:
+ case PMIC_SND_RIGHT_SPEAKER_MUTE:
+ sc_access[0].reg_addr = AUD17;
+ mask = MASK7;
+ retval = sst_sc_reg_access(sc_access, PMIC_READ, 1);
+ temp_value = sc_access[0].value & mask;
+ if (temp_value == 0)
+ *value = UNMUTE;
+ else
+ *value = MUTE;
+ break;
+ default:
+ return -EINVAL;
+ }
+
+ return retval;
+}
+
+static int fs_get_vol(int dev_id, int *value)
+{
+ struct sc_reg_access sc_access = {0,};
+ int retval = 0, mask = 0;
+
+ if (snd_pmic_ops_fs.card_status == SND_CARD_UN_INIT)
+ retval = fs_init_card();
+ if (retval)
+ return retval;
+
+ switch (dev_id) {
+ case PMIC_SND_CAPTURE_VOL:
+ pr_debug("sst: PMIC_SND_CAPTURE_VOL\n");
+ sc_access.reg_addr = MICLICTRL1;
+ mask = (MASK5|MASK4|MASK3|MASK2|MASK1|MASK0);
+ break;
+ case PMIC_SND_LEFT_PB_VOL:
+ pr_debug("sst: PMIC_SND_LEFT_PB_VOL\n");
+ sc_access.reg_addr = AUD16;
+ mask = (MASK5|MASK4|MASK3|MASK2|MASK1|MASK0);
+ break;
+ case PMIC_SND_RIGHT_PB_VOL:
+ pr_debug("sst: PMIC_SND_RT_PB_VOL\n");
+ sc_access.reg_addr = AUD17;
+ mask = (MASK5|MASK4|MASK3|MASK2|MASK1|MASK0);
+ break;
+ default:
+ return -EINVAL;
+ }
+
+ retval = sst_sc_reg_access(&sc_access, PMIC_READ, 1);
+ pr_debug("sst: value read = 0x%x\n", sc_access.value);
+ *value = (int) (sc_access.value & mask);
+ pr_debug("sst: value returned = 0x%x\n", *value);
+ return retval;
+}
+
+struct snd_pmic_ops snd_pmic_ops_fs = {
+ .set_input_dev = fs_set_selected_input_dev,
+ .set_output_dev = fs_set_selected_output_dev,
+ .set_mute = fs_set_mute,
+ .get_mute = fs_get_mute,
+ .set_vol = fs_set_vol,
+ .get_vol = fs_get_vol,
+ .init_card = fs_init_card,
+ .set_pcm_audio_params = fs_set_pcm_audio_params,
+ .set_pcm_voice_params = fs_set_pcm_voice_params,
+ .set_voice_port = fs_set_voice_port,
+ .set_audio_port = fs_set_audio_port,
+ .power_up_pmic_pb = fs_power_up_pb,
+ .power_up_pmic_cp = fs_power_up_cp,
+ .power_down_pmic_pb = fs_power_down_pb,
+ .power_down_pmic_cp = fs_power_down_cp,
+ .power_down_pmic = fs_power_down,
+};
OpenPOWER on IntegriCloud