diff options
author | Greg Kroah-Hartman <gregkh@suse.de> | 2010-10-28 09:44:56 -0700 |
---|---|---|
committer | Greg Kroah-Hartman <gregkh@suse.de> | 2010-10-28 09:44:56 -0700 |
commit | e4c5bf8e3dca827a1b3a6fac494eae8c74b7e1e7 (patch) | |
tree | ea51b391f7d74ca695dcb9f5e46eb02688a92ed9 /drivers/staging/intel_sst/intelmid_v2_control.c | |
parent | 81280572ca6f54009edfa4deee563e8678784218 (diff) | |
parent | a4ac0d847af9dd34d5953a5e264400326144b6b2 (diff) | |
download | op-kernel-dev-e4c5bf8e3dca827a1b3a6fac494eae8c74b7e1e7.zip op-kernel-dev-e4c5bf8e3dca827a1b3a6fac494eae8c74b7e1e7.tar.gz |
Merge 'staging-next' to Linus's tree
This merges the staging-next tree to Linus's tree and resolves
some conflicts that were present due to changes in other trees that were
affected by files here.
Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
Diffstat (limited to 'drivers/staging/intel_sst/intelmid_v2_control.c')
-rw-r--r-- | drivers/staging/intel_sst/intelmid_v2_control.c | 1001 |
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, +}; |