summaryrefslogtreecommitdiffstats
path: root/drivers/staging/intel_sst/intelmid_v2_control.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/staging/intel_sst/intelmid_v2_control.c')
-rw-r--r--drivers/staging/intel_sst/intelmid_v2_control.c1001
1 files changed, 1001 insertions, 0 deletions
diff --git a/drivers/staging/intel_sst/intelmid_v2_control.c b/drivers/staging/intel_sst/intelmid_v2_control.c
new file mode 100644
index 0000000..3a7de76
--- /dev/null
+++ b/drivers/staging/intel_sst/intelmid_v2_control.c
@@ -0,0 +1,1001 @@
+/*
+ * intelmid_v2_control.c - Intel Sound card driver for MID
+ *
+ * Copyright (C) 2008-10 Intel Corp
+ * Authors: Vinod Koul <vinod.koul@intel.com>
+ * Harsha Priya <priya.harsha@intel.com>
+ * KP Jeeja <jeeja.kp@intel.com>
+ * Dharageswari R <dharageswari.r@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 3
+ */
+
+#include <linux/pci.h>
+#include <linux/file.h>
+#include "intel_sst.h"
+#include "intelmid_snd_control.h"
+
+enum reg_v3 {
+ VAUDIOCNT = 0x51,
+ VOICEPORT1 = 0x100,
+ VOICEPORT2 = 0x101,
+ AUDIOPORT1 = 0x102,
+ AUDIOPORT2 = 0x103,
+ ADCSAMPLERATE = 0x104,
+ DMICCTRL1 = 0x105,
+ DMICCTRL2 = 0x106,
+ MICCTRL = 0x107,
+ MICSELVOL = 0x108,
+ LILSEL = 0x109,
+ LIRSEL = 0x10a,
+ VOICEVOL = 0x10b,
+ AUDIOLVOL = 0x10c,
+ AUDIORVOL = 0x10d,
+ LMUTE = 0x10e,
+ RMUTE = 0x10f,
+ POWERCTRL1 = 0x110,
+ POWERCTRL2 = 0x111,
+ DRVPOWERCTRL = 0x112,
+ VREFPLL = 0x113,
+ PCMBUFCTRL = 0x114,
+ SOFTMUTE = 0x115,
+ DTMFPATH = 0x116,
+ DTMFVOL = 0x117,
+ DTMFFREQ = 0x118,
+ DTMFHFREQ = 0x119,
+ DTMFLFREQ = 0x11a,
+ DTMFCTRL = 0x11b,
+ DTMFASON = 0x11c,
+ DTMFASOFF = 0x11d,
+ DTMFASINUM = 0x11e,
+ CLASSDVOL = 0x11f,
+ VOICEDACAVOL = 0x120,
+ AUDDACAVOL = 0x121,
+ LOMUTEVOL = 0x122,
+ HPLVOL = 0x123,
+ HPRVOL = 0x124,
+ MONOVOL = 0x125,
+ LINEOUTMIXVOL = 0x126,
+ EPMIXVOL = 0x127,
+ LINEOUTLSEL = 0x128,
+ LINEOUTRSEL = 0x129,
+ EPMIXOUTSEL = 0x12a,
+ HPLMIXSEL = 0x12b,
+ HPRMIXSEL = 0x12c,
+ LOANTIPOP = 0x12d,
+};
+
+/****
+ * nc_init_card - initilize the sound card
+ *
+ * This initilizes the audio paths to know values in case of this sound card
+ */
+static int nc_init_card(void)
+{
+ struct sc_reg_access sc_access[] = {
+ {VAUDIOCNT, 0x25, 0},
+ {VOICEPORT1, 0x00, 0},
+ {VOICEPORT2, 0x00, 0},
+ {AUDIOPORT1, 0x98, 0},
+ {AUDIOPORT2, 0x09, 0},
+ {AUDIOLVOL, 0x00, 0},
+ {AUDIORVOL, 0x00, 0},
+ {LMUTE, 0x03, 0},
+ {RMUTE, 0x03, 0},
+ {POWERCTRL1, 0x00, 0},
+ {POWERCTRL2, 0x00, 0},
+ {DRVPOWERCTRL, 0x00, 0},
+ {VREFPLL, 0x10, 0},
+ {HPLMIXSEL, 0xee, 0},
+ {HPRMIXSEL, 0xf6, 0},
+ {PCMBUFCTRL, 0x0, 0},
+ {VOICEVOL, 0x0e, 0},
+ {HPLVOL, 0x06, 0},
+ {HPRVOL, 0x06, 0},
+ {MICCTRL, 0x41, 0x00},
+ {ADCSAMPLERATE, 0x8B, 0x00},
+ {MICSELVOL, 0x5B, 0x00},
+ {LILSEL, 0x06, 0},
+ {LIRSEL, 0x46, 0},
+ {LOANTIPOP, 0x00, 0},
+ {DMICCTRL1, 0x40, 0},
+ };
+ snd_pmic_ops_nc.card_status = SND_CARD_INIT_DONE;
+ snd_pmic_ops_nc.master_mute = UNMUTE;
+ snd_pmic_ops_nc.mute_status = UNMUTE;
+ sst_sc_reg_access(sc_access, PMIC_WRITE, 26);
+ pr_debug("sst: init complete!!\n");
+ return 0;
+}
+
+static int nc_enable_audiodac(int value)
+{
+ struct sc_reg_access sc_access[3];
+ int mute_val = 0;
+
+ if (snd_pmic_ops_nc.mute_status == MUTE)
+ return 0;
+
+ if (((snd_pmic_ops_nc.output_dev_id == MONO_EARPIECE) ||
+ (snd_pmic_ops_nc.output_dev_id == INTERNAL_SPKR)) &&
+ (value == UNMUTE))
+ return 0;
+ if (value == UNMUTE) {
+ /* unmute the system, set the 7th bit to zero */
+ mute_val = 0x00;
+ } else {
+ /* MUTE:Set the seventh bit */
+ mute_val = 0x04;
+
+ }
+ sc_access[0].reg_addr = LMUTE;
+ sc_access[1].reg_addr = RMUTE;
+ sc_access[0].mask = sc_access[1].mask = MASK2;
+ sc_access[0].value = sc_access[1].value = mute_val;
+
+ if (snd_pmic_ops_nc.num_channel == 1)
+ sc_access[1].value = 0x04;
+ return sst_sc_reg_access(sc_access, PMIC_READ_MODIFY, 2);
+
+}
+
+static int nc_power_up_pb(unsigned int port)
+{
+ struct sc_reg_access sc_access[7];
+ int retval = 0;
+
+ if (snd_pmic_ops_nc.card_status == SND_CARD_UN_INIT)
+ retval = nc_init_card();
+ if (retval)
+ return retval;
+ if (port == 0xFF)
+ return 0;
+ nc_enable_audiodac(MUTE);
+ msleep(30);
+
+ pr_debug("sst: powering up pb....\n");
+
+ sc_access[0].reg_addr = VAUDIOCNT;
+ sc_access[0].value = 0x27;
+ sc_access[0].mask = 0x27;
+ sc_access[1].reg_addr = VREFPLL;
+ if (port == 0) {
+ sc_access[1].value = 0x3A;
+ sc_access[1].mask = 0x3A;
+ } else if (port == 1) {
+ sc_access[1].value = 0x35;
+ sc_access[1].mask = 0x35;
+ }
+ retval = sst_sc_reg_access(sc_access, PMIC_READ_MODIFY, 2);
+
+
+
+ sc_access[0].reg_addr = POWERCTRL1;
+ if (port == 0) {
+ sc_access[0].value = 0x40;
+ sc_access[0].mask = 0x40;
+ } else if (port == 1) {
+ sc_access[0].value = 0x01;
+ sc_access[0].mask = 0x01;
+ }
+ sc_access[1].reg_addr = POWERCTRL2;
+ sc_access[1].value = 0x0C;
+ sc_access[1].mask = 0x0C;
+
+ sc_access[2].reg_addr = DRVPOWERCTRL;
+ sc_access[2].value = 0x86;
+ sc_access[2].mask = 0x86;
+
+ sst_sc_reg_access(sc_access, PMIC_READ_MODIFY, 3);
+
+ msleep(30);
+
+ return nc_enable_audiodac(UNMUTE);
+
+}
+
+static int nc_power_up_cp(unsigned int port)
+{
+ struct sc_reg_access sc_access[5];
+ int retval = 0;
+
+
+ if (snd_pmic_ops_nc.card_status == SND_CARD_UN_INIT)
+ retval = nc_init_card();
+ if (retval)
+ return retval;
+
+
+ pr_debug("sst: powering up cp....\n");
+
+ if (port == 0xFF)
+ return 0;
+ sc_access[0].reg_addr = VAUDIOCNT;
+ sc_access[0].value = 0x27;
+ sc_access[0].mask = 0x27;
+ sc_access[1].reg_addr = VREFPLL;
+ if (port == 0) {
+ sc_access[1].value = 0x3E;
+ sc_access[1].mask = 0x3E;
+ } else if (port == 1) {
+ sc_access[1].value = 0x35;
+ sc_access[1].mask = 0x35;
+ }
+
+ retval = sst_sc_reg_access(sc_access, PMIC_READ_MODIFY, 2);
+
+
+ sc_access[0].reg_addr = POWERCTRL1;
+ if (port == 0) {
+ sc_access[0].value = 0xB4;
+ sc_access[0].mask = 0xB4;
+ } else if (port == 1) {
+ sc_access[0].value = 0xBF;
+ sc_access[0].mask = 0xBF;
+ }
+ sc_access[1].reg_addr = POWERCTRL2;
+ if (port == 0) {
+ sc_access[1].value = 0x0C;
+ sc_access[1].mask = 0x0C;
+ } else if (port == 1) {
+ sc_access[1].value = 0x02;
+ sc_access[1].mask = 0x02;
+ }
+
+ return sst_sc_reg_access(sc_access, PMIC_READ_MODIFY, 2);
+
+}
+
+static int nc_power_down(void)
+{
+ int retval = 0;
+ struct sc_reg_access sc_access[5];
+
+
+ if (snd_pmic_ops_nc.card_status == SND_CARD_UN_INIT)
+ retval = nc_init_card();
+ if (retval)
+ return retval;
+ nc_enable_audiodac(MUTE);
+
+
+ pr_debug("sst: powering dn nc_power_down ....\n");
+
+ msleep(30);
+
+ sc_access[0].reg_addr = DRVPOWERCTRL;
+ sc_access[0].value = 0x00;
+ sc_access[0].mask = 0x00;
+
+ sst_sc_reg_access(sc_access, PMIC_WRITE, 1);
+
+ sc_access[0].reg_addr = POWERCTRL1;
+ sc_access[0].value = 0x00;
+ sc_access[0].mask = 0x00;
+
+ sc_access[1].reg_addr = POWERCTRL2;
+ sc_access[1].value = 0x00;
+ sc_access[1].mask = 0x00;
+
+
+
+ sst_sc_reg_access(sc_access, PMIC_WRITE, 2);
+
+ msleep(30);
+ sc_access[0].reg_addr = VREFPLL;
+ sc_access[0].value = 0x10;
+ sc_access[0].mask = 0x10;
+
+ sc_access[1].reg_addr = VAUDIOCNT;
+ sc_access[1].value = 0x25;
+ sc_access[1].mask = 0x25;
+
+
+ retval = sst_sc_reg_access(sc_access, PMIC_WRITE, 2);
+
+ msleep(30);
+ return nc_enable_audiodac(UNMUTE);
+}
+
+static int nc_power_down_pb(void)
+{
+
+ int retval = 0;
+ struct sc_reg_access sc_access[5];
+
+ if (snd_pmic_ops_nc.card_status == SND_CARD_UN_INIT)
+ retval = nc_init_card();
+ if (retval)
+ return retval;
+
+ pr_debug("sst: powering dn pb....\n");
+
+ nc_enable_audiodac(MUTE);
+
+
+ msleep(30);
+
+
+ sc_access[0].reg_addr = DRVPOWERCTRL;
+ sc_access[0].value = 0x00;
+ sc_access[0].mask = 0x00;
+
+ sst_sc_reg_access(sc_access, PMIC_WRITE, 1);
+
+ msleep(30);
+
+ sc_access[0].reg_addr = POWERCTRL1;
+ sc_access[0].value = 0x00;
+ sc_access[0].mask = 0x41;
+
+ sc_access[1].reg_addr = POWERCTRL2;
+ sc_access[1].value = 0x00;
+ sc_access[1].mask = 0x0C;
+
+ sst_sc_reg_access(sc_access, PMIC_READ_MODIFY, 2);
+
+ msleep(30);
+
+ return nc_enable_audiodac(UNMUTE);
+
+
+}
+
+static int nc_power_down_cp(void)
+{
+ struct sc_reg_access sc_access[] = {
+ {POWERCTRL1, 0x00, 0xBE},
+ {POWERCTRL2, 0x00, 0x02},
+ };
+ int retval = 0;
+
+ if (snd_pmic_ops_nc.card_status == SND_CARD_UN_INIT)
+ retval = nc_init_card();
+ if (retval)
+ return retval;
+
+ pr_debug("sst: powering dn cp....\n");
+ return sst_sc_reg_access(sc_access, PMIC_READ_MODIFY, 1);
+}
+
+static int nc_set_pcm_voice_params(void)
+{
+ struct sc_reg_access sc_access[] = {
+ {0x100, 0xD5, 0},
+ {0x101, 0x08, 0},
+ {0x104, 0x03, 0},
+ {0x107, 0x10, 0},
+ {0x10B, 0x0E, 0},
+ {0x10E, 0x03, 0},
+ {0x10F, 0x03, 0},
+ {0x114, 0x13, 0},
+ {0x115, 0x00, 0},
+ {0x128, 0xFE, 0},
+ {0x129, 0xFE, 0},
+ {0x12A, 0xFE, 0},
+ {0x12B, 0xDE, 0},
+ {0x12C, 0xDE, 0},
+ };
+ int retval = 0;
+
+ if (snd_pmic_ops_nc.card_status == SND_CARD_UN_INIT)
+ retval = nc_init_card();
+ if (retval)
+ return retval;
+
+ sst_sc_reg_access(sc_access, PMIC_WRITE, 14);
+ pr_debug("sst: Voice parameters set successfully!!\n");
+ return 0;
+}
+
+
+static int nc_set_pcm_audio_params(int sfreq, int word_size, int num_channel)
+{
+ int config2 = 0;
+ struct sc_reg_access sc_access;
+ int retval = 0;
+
+ if (snd_pmic_ops_nc.card_status == SND_CARD_UN_INIT)
+ retval = nc_init_card();
+ if (retval)
+ return retval;
+
+ switch (sfreq) {
+ case 8000:
+ config2 = 0x00;
+ break;
+ case 11025:
+ config2 = 0x01;
+ break;
+ case 12000:
+ config2 = 0x02;
+ break;
+ case 16000:
+ config2 = 0x03;
+ break;
+ case 22050:
+ config2 = 0x04;
+ break;
+ case 24000:
+ config2 = 0x05;
+ break;
+ case 32000:
+ config2 = 0x07;
+ break;
+ case 44100:
+ config2 = 0x08;
+ break;
+ case 48000:
+ config2 = 0x09;
+ break;
+ }
+
+ snd_pmic_ops_nc.num_channel = num_channel;
+ if (snd_pmic_ops_nc.num_channel == 1) {
+
+ sc_access.value = 0x07;
+ sc_access.reg_addr = RMUTE;
+ pr_debug("sst: RIGHT_HP_MUTE value%d\n", sc_access.value);
+ sc_access.mask = MASK2;
+ sst_sc_reg_access(&sc_access, PMIC_READ_MODIFY, 1);
+ } else {
+ sc_access.value = 0x00;
+ sc_access.reg_addr = RMUTE;
+ pr_debug("sst: RIGHT_HP_MUTE value %d\n", sc_access.value);
+ sc_access.mask = MASK2;
+ sst_sc_reg_access(&sc_access, PMIC_READ_MODIFY, 1);
+
+
+ }
+
+ pr_debug("sst: word_size = %d\n", word_size);
+
+ if (word_size == 24) {
+ sc_access.reg_addr = AUDIOPORT2;
+ sc_access.value = config2 | 0x10;
+ sc_access.mask = 0x1F;
+ } else {
+ sc_access.value = config2;
+ sc_access.mask = 0x1F;
+ sc_access.reg_addr = AUDIOPORT2;
+ }
+ sst_sc_reg_access(&sc_access, PMIC_READ_MODIFY, 1);
+
+ pr_debug("sst: word_size = %d\n", word_size);
+ sc_access.reg_addr = AUDIOPORT1;
+ sc_access.mask = MASK5|MASK4|MASK1|MASK0;
+ if (word_size == 16)
+ sc_access.value = 0x98;
+ else if (word_size == 24)
+ sc_access.value = 0xAB;
+
+ return sst_sc_reg_access(&sc_access, PMIC_READ_MODIFY, 1);
+
+
+
+}
+
+static int nc_set_selected_output_dev(u8 value)
+{
+ struct sc_reg_access sc_access_HP[] = {
+ {LMUTE, 0x02, 0x06},
+ {RMUTE, 0x02, 0x06}
+ };
+ struct sc_reg_access sc_access_IS[] = {
+ {LMUTE, 0x04, 0x06},
+ {RMUTE, 0x04, 0x06}
+ };
+ int retval = 0;
+
+ snd_pmic_ops_nc.output_dev_id = value;
+ if (snd_pmic_ops_nc.card_status == SND_CARD_UN_INIT)
+ retval = nc_init_card();
+ if (retval)
+ return retval;
+ pr_debug("sst: nc set selected output:%d\n", value);
+ switch (value) {
+ case STEREO_HEADPHONE:
+ retval = sst_sc_reg_access(sc_access_HP, PMIC_WRITE, 2);
+ break;
+ case INTERNAL_SPKR:
+ retval = sst_sc_reg_access(sc_access_IS, PMIC_WRITE, 2);
+ break;
+ default:
+ pr_err("sst: rcvd illegal request: %d\n", value);
+ return -EINVAL;
+ }
+ return retval;
+}
+
+static int nc_audio_init(void)
+{
+ struct sc_reg_access sc_acces, sc_access[] = {
+ {0x100, 0x00, 0},
+ {0x101, 0x00, 0},
+ {0x104, 0x8B, 0},
+ {0x107, 0x11, 0},
+ {0x10B, 0x0E, 0},
+ {0x114, 0x00, 0},
+ {0x115, 0x00, 0},
+ {0x128, 0x00, 0},
+ {0x129, 0x00, 0},
+ {0x12A, 0x00, 0},
+ {0x12B, 0xee, 0},
+ {0x12C, 0xf6, 0},
+ };
+
+ sst_sc_reg_access(sc_access, PMIC_WRITE, 12);
+ pr_debug("sst: Audio Init successfully!!\n");
+
+ /*set output device */
+ nc_set_selected_output_dev(snd_pmic_ops_nc.output_dev_id);
+
+ if (snd_pmic_ops_nc.num_channel == 1) {
+ sc_acces.value = 0x07;
+ sc_acces.reg_addr = RMUTE;
+ pr_debug("sst: RIGHT_HP_MUTE value%d\n", sc_acces.value);
+ sc_acces.mask = MASK2;
+ sst_sc_reg_access(&sc_acces, PMIC_READ_MODIFY, 1);
+ } else {
+ sc_acces.value = 0x00;
+ sc_acces.reg_addr = RMUTE;
+ pr_debug("sst: RIGHT_HP_MUTE value%d\n", sc_acces.value);
+ sc_acces.mask = MASK2;
+ sst_sc_reg_access(&sc_acces, PMIC_READ_MODIFY, 1);
+ }
+
+ return 0;
+}
+
+static int nc_set_audio_port(int status)
+{
+ struct sc_reg_access sc_access[2] = {{0,},};
+ int retval = 0;
+
+ if (snd_pmic_ops_nc.card_status == SND_CARD_UN_INIT)
+ retval = nc_init_card();
+ if (retval)
+ return retval;
+
+ if (status == DEACTIVATE) {
+ /* Deactivate audio port-tristate and power */
+ sc_access[0].value = 0x00;
+ sc_access[0].mask = MASK4|MASK5;
+ sc_access[0].reg_addr = AUDIOPORT1;
+ return sst_sc_reg_access(sc_access, PMIC_READ_MODIFY, 1);
+ } else if (status == ACTIVATE) {
+ /* activate audio port */
+ nc_audio_init();
+ sc_access[0].value = 0x10;
+ sc_access[0].mask = MASK4|MASK5 ;
+ sc_access[0].reg_addr = AUDIOPORT1;
+ return sst_sc_reg_access(sc_access, PMIC_READ_MODIFY, 1);
+ } else
+ return -EINVAL;
+
+}
+
+static int nc_set_voice_port(int status)
+{
+ struct sc_reg_access sc_access[2] = {{0,},};
+ int retval = 0;
+
+ if (snd_pmic_ops_nc.card_status == SND_CARD_UN_INIT)
+ retval = nc_init_card();
+ if (retval)
+ return retval;
+
+ if (status == DEACTIVATE) {
+ /* Activate Voice port */
+ sc_access[0].value = 0x00;
+ sc_access[0].mask = MASK4;
+ sc_access[0].reg_addr = VOICEPORT1;
+ return sst_sc_reg_access(sc_access, PMIC_READ_MODIFY, 1);
+ } else if (status == ACTIVATE) {
+ /* Deactivate voice port */
+ nc_set_pcm_voice_params();
+ sc_access[0].value = 0x10;
+ sc_access[0].mask = MASK4;
+ sc_access[0].reg_addr = VOICEPORT1;
+ return sst_sc_reg_access(sc_access, PMIC_READ_MODIFY, 1);
+ } else
+ return -EINVAL;
+}
+
+static int nc_set_mute(int dev_id, u8 value)
+{
+ struct sc_reg_access sc_access[3];
+ u8 mute_val, cap_mute;
+ int retval = 0;
+
+ if (snd_pmic_ops_nc.card_status == SND_CARD_UN_INIT)
+ retval = nc_init_card();
+ if (retval)
+ return retval;
+
+ pr_debug("sst: set device id::%d, value %d\n", dev_id, value);
+
+ switch (dev_id) {
+ case PMIC_SND_MUTE_ALL:
+ pr_debug("sst: PMIC_SND_MUTE_ALL value %d\n", value);
+ snd_pmic_ops_nc.mute_status = value;
+ snd_pmic_ops_nc.master_mute = value;
+ if (value == UNMUTE) {
+ /* unmute the system, set the 7th bit to zero */
+ mute_val = cap_mute = 0x00;
+ } else {
+ /* MUTE:Set the seventh bit */
+ mute_val = 0x80;
+ cap_mute = 0x40;
+ }
+ sc_access[0].reg_addr = AUDIOLVOL;
+ sc_access[1].reg_addr = AUDIORVOL;
+ sc_access[0].mask = sc_access[1].mask = MASK7;
+ sc_access[0].value = sc_access[1].value = mute_val;
+ if (snd_pmic_ops_nc.num_channel == 1)
+ sc_access[1].value = 0x80;
+ if (!sst_sc_reg_access(sc_access, PMIC_READ_MODIFY, 2)) {
+ sc_access[0].reg_addr = 0x109;
+ sc_access[1].reg_addr = 0x10a;
+ sc_access[2].reg_addr = 0x105;
+ sc_access[0].mask = sc_access[1].mask =
+ sc_access[2].mask = MASK6;
+ sc_access[0].value = sc_access[1].value =
+ sc_access[2].value = cap_mute;
+
+ if ((snd_pmic_ops_nc.input_dev_id == AMIC) ||
+ (snd_pmic_ops_nc.input_dev_id == DMIC))
+ sc_access[1].value = 0x40;
+ if (snd_pmic_ops_nc.input_dev_id == HS_MIC)
+ sc_access[0].value = 0x40;
+ retval = sst_sc_reg_access(sc_access,
+ PMIC_READ_MODIFY, 3);
+ }
+ break;
+ case PMIC_SND_HP_MIC_MUTE:
+ pr_debug("sst: PMIC_SND_HPMIC_MUTE value %d\n", value);
+ if (value == UNMUTE) {
+ /* unmute the system, set the 6th bit to one */
+ sc_access[0].value = 0x00;
+ } else {
+ /* mute the system, reset the 6th bit to zero */
+ sc_access[0].value = 0x40;
+ }
+ sc_access[0].reg_addr = LIRSEL;
+ sc_access[0].mask = MASK6;
+ retval = sst_sc_reg_access(sc_access, PMIC_READ_MODIFY, 1);
+ break;
+ case PMIC_SND_AMIC_MUTE:
+ pr_debug("sst: PMIC_SND_AMIC_MUTE value %d\n", value);
+ if (value == UNMUTE) {
+ /* unmute the system, set the 6th bit to one */
+ sc_access[0].value = 0x00;
+ } else {
+ /* mute the system, reset the 6th bit to zero */
+ sc_access[0].value = 0x40;
+ }
+ sc_access[0].reg_addr = LILSEL;
+ sc_access[0].mask = MASK6;
+ retval = sst_sc_reg_access(sc_access, PMIC_READ_MODIFY, 1);
+ break;
+
+ case PMIC_SND_DMIC_MUTE:
+ pr_debug("sst: INPUT_MUTE_DMIC value%d\n", value);
+ if (value == UNMUTE) {
+ /* unmute the system, set the 6th bit to one */
+ sc_access[1].value = 0x00;
+ sc_access[0].value = 0x00;
+ } else {
+ /* mute the system, reset the 6th bit to zero */
+ sc_access[1].value = 0x40;
+ sc_access[0].value = 0x40;
+ }
+ sc_access[0].reg_addr = DMICCTRL1;
+ sc_access[0].mask = MASK6;
+ sc_access[1].reg_addr = LILSEL;
+ sc_access[1].mask = MASK6;
+ retval = sst_sc_reg_access(sc_access,
+ PMIC_READ_MODIFY, 2);
+ break;
+
+ case PMIC_SND_LEFT_HP_MUTE:
+ case PMIC_SND_RIGHT_HP_MUTE:
+ snd_pmic_ops_nc.mute_status = value;
+ if (value == UNMUTE)
+ sc_access[0].value = 0x0;
+ else
+ sc_access[0].value = 0x04;
+
+ if (dev_id == PMIC_SND_LEFT_HP_MUTE) {
+ sc_access[0].reg_addr = LMUTE;
+ pr_debug("sst: LEFT_HP_MUTE value %d\n",
+ sc_access[0].value);
+ } else {
+ if (snd_pmic_ops_nc.num_channel == 1)
+ sc_access[0].value = 0x04;
+ sc_access[0].reg_addr = RMUTE;
+ pr_debug("sst: RIGHT_HP_MUTE value %d\n",
+ sc_access[0].value);
+ }
+ sc_access[0].mask = MASK2;
+ retval = sst_sc_reg_access(sc_access, PMIC_READ_MODIFY, 1);
+ break;
+ case PMIC_SND_LEFT_SPEAKER_MUTE:
+ case PMIC_SND_RIGHT_SPEAKER_MUTE:
+ if (value == UNMUTE)
+ sc_access[0].value = 0x00;
+ else
+ sc_access[0].value = 0x03;
+ sc_access[0].reg_addr = LMUTE;
+ pr_debug("sst: SPEAKER_MUTE %d\n", sc_access[0].value);
+ sc_access[0].mask = MASK1;
+ retval = sst_sc_reg_access(sc_access, PMIC_READ_MODIFY, 1);
+ break;
+ default:
+ return -EINVAL;
+ }
+ return retval ;
+
+}
+
+static int nc_set_vol(int dev_id, int value)
+{
+ struct sc_reg_access sc_access[3];
+ int retval = 0, entries = 0;
+
+ if (snd_pmic_ops_nc.card_status == SND_CARD_UN_INIT)
+ retval = nc_init_card();
+ if (retval)
+ return retval;
+
+ pr_debug("sst: set volume:%d\n", dev_id);
+ switch (dev_id) {
+ case PMIC_SND_CAPTURE_VOL:
+ pr_debug("sst: PMIC_SND_CAPTURE_VOL:value::%d\n", value);
+ sc_access[0].value = sc_access[1].value =
+ sc_access[2].value = -value;
+ sc_access[0].mask = sc_access[1].mask = sc_access[2].mask =
+ (MASK0|MASK1|MASK2|MASK3|MASK4|MASK5);
+ sc_access[0].reg_addr = 0x10a;
+ sc_access[1].reg_addr = 0x109;
+ sc_access[2].reg_addr = 0x105;
+ entries = 3;
+ break;
+
+ case PMIC_SND_LEFT_PB_VOL:
+ pr_debug("sst: PMIC_SND_LEFT_HP_VOL %d\n", value);
+ sc_access[0].value = -value;
+ sc_access[0].reg_addr = AUDIOLVOL;
+ sc_access[0].mask =
+ (MASK0|MASK1|MASK2|MASK3|MASK4|MASK5|MASK6);
+ entries = 1;
+ break;
+
+ case PMIC_SND_RIGHT_PB_VOL:
+ pr_debug("sst: PMIC_SND_RIGHT_HP_VOL value %d\n", value);
+ if (snd_pmic_ops_nc.num_channel == 1) {
+ sc_access[0].value = 0x04;
+ sc_access[0].reg_addr = RMUTE;
+ sc_access[0].mask = MASK2;
+ } else {
+ sc_access[0].value = -value;
+ sc_access[0].reg_addr = AUDIORVOL;
+ sc_access[0].mask =
+ (MASK0|MASK1|MASK2|MASK3|MASK4|MASK5|MASK6);
+ entries = 1;
+ }
+ break;
+
+ default:
+ return -EINVAL;
+
+ }
+ return sst_sc_reg_access(sc_access, PMIC_READ_MODIFY, entries);
+}
+
+static int nc_set_selected_input_dev(u8 value)
+{
+ struct sc_reg_access sc_access[6];
+ u8 num_val;
+ int retval = 0;
+
+ if (snd_pmic_ops_nc.card_status == SND_CARD_UN_INIT)
+ retval = nc_init_card();
+ if (retval)
+ return retval;
+ snd_pmic_ops_nc.input_dev_id = value;
+
+ pr_debug("sst: nc set selected input:%d\n", value);
+
+ switch (value) {
+ case AMIC:
+ pr_debug("sst: Selecting AMIC\n");
+ sc_access[0].reg_addr = 0x107;
+ sc_access[0].value = 0x40;
+ sc_access[0].mask = MASK6|MASK4|MASK3|MASK1|MASK0;
+ sc_access[1].reg_addr = 0x10a;
+ sc_access[1].value = 0x40;
+ sc_access[1].mask = MASK6;
+ sc_access[2].reg_addr = 0x109;
+ sc_access[2].value = 0x00;
+ sc_access[2].mask = MASK6;
+ sc_access[3].reg_addr = 0x105;
+ sc_access[3].value = 0x40;
+ sc_access[3].mask = MASK6;
+ num_val = 4;
+ break;
+
+ case HS_MIC:
+ pr_debug("sst: Selecting HS_MIC\n");
+ sc_access[0].reg_addr = 0x107;
+ sc_access[0].mask = MASK6|MASK4|MASK3|MASK1|MASK0;
+ sc_access[0].value = 0x10;
+ sc_access[1].reg_addr = 0x109;
+ sc_access[1].mask = MASK6;
+ sc_access[1].value = 0x40;
+ sc_access[2].reg_addr = 0x10a;
+ sc_access[2].mask = MASK6;
+ sc_access[2].value = 0x00;
+ sc_access[3].reg_addr = 0x105;
+ sc_access[3].value = 0x40;
+ sc_access[3].mask = MASK6;
+ num_val = 4;
+ break;
+
+ case DMIC:
+ pr_debug("sst: DMIC\n");
+ sc_access[0].reg_addr = 0x107;
+ sc_access[0].mask = MASK6|MASK4|MASK3|MASK1|MASK0;
+ sc_access[0].value = 0x0B;
+ sc_access[1].reg_addr = 0x105;
+ sc_access[1].value = 0x80;
+ sc_access[1].mask = MASK7|MASK6;
+ sc_access[2].reg_addr = 0x10a;
+ sc_access[2].value = 0x40;
+ sc_access[2].mask = MASK6;
+ sc_access[3].reg_addr = 0x109;
+ sc_access[3].mask = MASK6;
+ sc_access[3].value = 0x40;
+ num_val = 4;
+ break;
+ default:
+ return -EINVAL;
+ }
+ return sst_sc_reg_access(sc_access, PMIC_READ_MODIFY, num_val);
+}
+
+static int nc_get_mute(int dev_id, u8 *value)
+{
+ int retval = 0, mask = 0;
+ struct sc_reg_access sc_access = {0,};
+
+ if (snd_pmic_ops_nc.card_status == SND_CARD_UN_INIT)
+ retval = nc_init_card();
+ if (retval)
+ return retval;
+
+ pr_debug("sst: get mute::%d\n", dev_id);
+
+ switch (dev_id) {
+ case PMIC_SND_AMIC_MUTE:
+ pr_debug("sst: PMIC_SND_INPUT_MUTE_MIC1\n");
+ sc_access.reg_addr = LILSEL;
+ mask = MASK6;
+ break;
+ case PMIC_SND_HP_MIC_MUTE:
+ pr_debug("sst: PMIC_SND_INPUT_MUTE_MIC2\n");
+ sc_access.reg_addr = LIRSEL;
+ mask = MASK6;
+ break;
+ case PMIC_SND_LEFT_HP_MUTE:
+ case PMIC_SND_RIGHT_HP_MUTE:
+ mask = MASK2;
+ pr_debug("sst: PMIC_SN_LEFT/RIGHT_HP_MUTE\n");
+ if (dev_id == PMIC_SND_RIGHT_HP_MUTE)
+ sc_access.reg_addr = RMUTE;
+ else
+ sc_access.reg_addr = LMUTE;
+ break;
+
+ case PMIC_SND_LEFT_SPEAKER_MUTE:
+ pr_debug("sst: PMIC_MONO_EARPIECE_MUTE\n");
+ sc_access.reg_addr = RMUTE;
+ mask = MASK1;
+ break;
+ case PMIC_SND_DMIC_MUTE:
+ pr_debug("sst: PMIC_SND_INPUT_MUTE_DMIC\n");
+ sc_access.reg_addr = 0x105;
+ mask = MASK6;
+ break;
+ default:
+ return -EINVAL;
+
+ }
+ retval = sst_sc_reg_access(&sc_access, PMIC_READ, 1);
+ pr_debug("sst: reg value = %d\n", sc_access.value);
+ if (retval)
+ return retval;
+ *value = (sc_access.value) & mask;
+ pr_debug("sst: masked value = %d\n", *value);
+ if (*value)
+ *value = 0;
+ else
+ *value = 1;
+ pr_debug("sst: value returned = 0x%x\n", *value);
+ return retval;
+}
+
+static int nc_get_vol(int dev_id, int *value)
+{
+ int retval = 0, mask = 0;
+ struct sc_reg_access sc_access = {0,};
+
+ if (snd_pmic_ops_nc.card_status == SND_CARD_UN_INIT)
+ retval = nc_init_card();
+ if (retval)
+ return retval;
+
+ switch (dev_id) {
+ case PMIC_SND_CAPTURE_VOL:
+ pr_debug("sst: PMIC_SND_INPUT_CAPTURE_VOL\n");
+ sc_access.reg_addr = LILSEL;
+ mask = (MASK0|MASK1|MASK2|MASK3|MASK4|MASK5);
+ break;
+
+ case PMIC_SND_RIGHT_PB_VOL:
+ pr_debug("sst: GET_VOLUME_PMIC_LEFT_HP_VOL\n");
+ sc_access.reg_addr = AUDIOLVOL;
+ mask = (MASK0|MASK1|MASK2|MASK3|MASK4|MASK5|MASK6);
+ break;
+
+ case PMIC_SND_LEFT_PB_VOL:
+ pr_debug("sst: GET_VOLUME_PMIC_RIGHT_HP_VOL\n");
+ sc_access.reg_addr = AUDIORVOL;
+ mask = (MASK0|MASK1|MASK2|MASK3|MASK4|MASK5|MASK6);
+ 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 = -((sc_access.value) & mask);
+ pr_debug("sst: get vol value returned = %d\n", *value);
+ return retval;
+}
+
+struct snd_pmic_ops snd_pmic_ops_nc = {
+ .set_input_dev = nc_set_selected_input_dev,
+ .set_output_dev = nc_set_selected_output_dev,
+ .set_mute = nc_set_mute,
+ .get_mute = nc_get_mute,
+ .set_vol = nc_set_vol,
+ .get_vol = nc_get_vol,
+ .init_card = nc_init_card,
+ .set_pcm_audio_params = nc_set_pcm_audio_params,
+ .set_pcm_voice_params = nc_set_pcm_voice_params,
+ .set_voice_port = nc_set_voice_port,
+ .set_audio_port = nc_set_audio_port,
+ .power_up_pmic_pb = nc_power_up_pb,
+ .power_up_pmic_cp = nc_power_up_cp,
+ .power_down_pmic_pb = nc_power_down_pb,
+ .power_down_pmic_cp = nc_power_down_cp,
+ .power_down_pmic = nc_power_down,
+};
OpenPOWER on IntegriCloud