mirror of
https://git.yoctoproject.org/poky
synced 2026-04-30 21:32:13 +02:00
2862 lines
72 KiB
Diff
2862 lines
72 KiB
Diff
From 14d8fbc882908c792b3640b3f2730990539d6645 Mon Sep 17 00:00:00 2001
|
|
From: R, Dharageswari <dharageswari.r@intel.com>
|
|
Date: Thu, 29 Apr 2010 20:27:36 +0530
|
|
Subject: [PATCH] ADR-Post-Beta-0.05.002.03-6/8-Moorestown Audio Drivers: SST sound card modules
|
|
|
|
This adds the support for vendor PMICs for widget control and configurations.
|
|
The Moorestown platform supports three different vendor implementation of PMIC.
|
|
The sound card, ie all analog components like DAC, ADC, mixer settings are
|
|
different for three vendors. This module implements these settings for each
|
|
of the vendor.
|
|
All PMIC vendors - NEC, Freescale and MAXIM are supported
|
|
|
|
Signed-off-by: Vinod Koul <vinod.koul@intel.com>
|
|
|
|
new file: sound/pci/sst/intelmid_snd_control.h
|
|
new file: sound/pci/sst/intelmid_v0_control.c
|
|
new file: sound/pci/sst/intelmid_v1_control.c
|
|
new file: sound/pci/sst/intelmid_v2_control.c
|
|
Patch-mainline: 2.6.35?
|
|
---
|
|
sound/pci/sst/intelmid_snd_control.h | 114 ++++
|
|
sound/pci/sst/intelmid_v0_control.c | 813 +++++++++++++++++++++++++++
|
|
sound/pci/sst/intelmid_v1_control.c | 846 ++++++++++++++++++++++++++++
|
|
sound/pci/sst/intelmid_v2_control.c | 1031 ++++++++++++++++++++++++++++++++++
|
|
4 files changed, 2804 insertions(+), 0 deletions(-)
|
|
create mode 100644 sound/pci/sst/intelmid_snd_control.h
|
|
create mode 100644 sound/pci/sst/intelmid_v0_control.c
|
|
create mode 100644 sound/pci/sst/intelmid_v1_control.c
|
|
create mode 100644 sound/pci/sst/intelmid_v2_control.c
|
|
|
|
diff --git a/sound/pci/sst/intelmid_snd_control.h b/sound/pci/sst/intelmid_snd_control.h
|
|
new file mode 100644
|
|
index 0000000..0cb9eb1
|
|
--- /dev/null
|
|
+++ b/sound/pci/sst/intelmid_snd_control.h
|
|
@@ -0,0 +1,114 @@
|
|
+#ifndef __INTELMID_SND_CTRL_H__
|
|
+#define __INTELMID_SND_CTRL_H__
|
|
+/*
|
|
+ * intelmid_snd_control.h - Intel Sound card driver for MID
|
|
+ *
|
|
+ * 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 defines all snd control functions
|
|
+ */
|
|
+
|
|
+/*
|
|
+Mask bits
|
|
+*/
|
|
+#define MASK0 0x01 /* 0000 0001 */
|
|
+#define MASK1 0x02 /* 0000 0010 */
|
|
+#define MASK2 0x04 /* 0000 0100 */
|
|
+#define MASK3 0x08 /* 0000 1000 */
|
|
+#define MASK4 0x10 /* 0001 0000 */
|
|
+#define MASK5 0x20 /* 0010 0000 */
|
|
+#define MASK6 0x40 /* 0100 0000 */
|
|
+#define MASK7 0x80 /* 1000 0000 */
|
|
+/*
|
|
+value bits
|
|
+*/
|
|
+#define VALUE0 0x01 /* 0000 0001 */
|
|
+#define VALUE1 0x02 /* 0000 0010 */
|
|
+#define VALUE2 0x04 /* 0000 0100 */
|
|
+#define VALUE3 0x08 /* 0000 1000 */
|
|
+#define VALUE4 0x10 /* 0001 0000 */
|
|
+#define VALUE5 0x20 /* 0010 0000 */
|
|
+#define VALUE6 0x40 /* 0100 0000 */
|
|
+#define VALUE7 0x80 /* 1000 0000 */
|
|
+
|
|
+#define MUTE 0 /* ALSA Passes 0 for mute */
|
|
+#define UNMUTE 1 /* ALSA Passes 1 for unmute */
|
|
+
|
|
+#define MAX_VOL_PMIC_VENDOR0 0x3f /* max vol in dB for stereo & voice DAC */
|
|
+#define MIN_VOL_PMIC_VENDOR0 0 /* min vol in dB for stereo & voice DAC */
|
|
+/* Head phone volume control */
|
|
+#define MAX_HP_VOL_PMIC_VENDOR1 6 /* max volume in dB for HP */
|
|
+#define MIN_HP_VOL_PMIC_VENDOR1 (-84) /* min volume in dB for HP */
|
|
+#define MAX_HP_VOL_INDX_PMIC_VENDOR1 40 /* Number of HP volume control values */
|
|
+
|
|
+/* Mono Earpiece Volume control */
|
|
+#define MAX_EP_VOL_PMIC_VENDOR1 0 /* max volume in dB for EP */
|
|
+#define MIN_EP_VOL_PMIC_VENDOR1 (-75) /* min volume in dB for EP */
|
|
+#define MAX_EP_VOL_INDX_PMIC_VENDOR1 32 /* Number of EP volume control values */
|
|
+
|
|
+int sst_sc_reg_access(struct sc_reg_access *sc_access,
|
|
+ int type, int num_val);
|
|
+extern struct snd_pmic_ops snd_pmic_ops_fs;
|
|
+extern struct snd_pmic_ops snd_pmic_ops_mx;
|
|
+extern struct snd_pmic_ops snd_pmic_ops_nc;
|
|
+
|
|
+/* device */
|
|
+enum SND_INPUT_DEVICE {
|
|
+ HS_MIC,
|
|
+ AMIC,
|
|
+ DMIC,
|
|
+ IN_UNDEFINED
|
|
+};
|
|
+
|
|
+enum SND_OUTPUT_DEVICE {
|
|
+ STEREO_HEADPHONE,
|
|
+ INTERNAL_SPKR,
|
|
+ OUT_UNDEFINED
|
|
+};
|
|
+
|
|
+enum SND_CARDS {
|
|
+ SND_FS = 0,
|
|
+ SND_MX,
|
|
+ SND_NC,
|
|
+};
|
|
+
|
|
+enum pmic_controls {
|
|
+ PMIC_SND_HP_MIC_MUTE = 0x0001,
|
|
+ PMIC_SND_AMIC_MUTE = 0x0002,
|
|
+ PMIC_SND_DMIC_MUTE = 0x0003,
|
|
+ PMIC_SND_CAPTURE_VOL = 0x0004,
|
|
+/* Output controls */
|
|
+ PMIC_SND_LEFT_PB_VOL = 0x0010,
|
|
+ PMIC_SND_RIGHT_PB_VOL = 0x0011,
|
|
+ PMIC_SND_LEFT_HP_MUTE = 0x0012,
|
|
+ PMIC_SND_RIGHT_HP_MUTE = 0x0013,
|
|
+ PMIC_SND_LEFT_SPEAKER_MUTE = 0x0014,
|
|
+ PMIC_SND_RIGHT_SPEAKER_MUTE = 0x0015,
|
|
+/* Other controls */
|
|
+ PMIC_SND_MUTE_ALL = 0x0020,
|
|
+ PMIC_MAX_CONTROLS = 0x0020,
|
|
+};
|
|
+
|
|
+#endif /* __INTELMID_SND_CTRL_H__ */
|
|
+
|
|
+
|
|
diff --git a/sound/pci/sst/intelmid_v0_control.c b/sound/pci/sst/intelmid_v0_control.c
|
|
new file mode 100644
|
|
index 0000000..3252fa5
|
|
--- /dev/null
|
|
+++ b/sound/pci/sst/intelmid_v0_control.c
|
|
@@ -0,0 +1,813 @@
|
|
+/*
|
|
+ * 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/cdev.h>
|
|
+#include <linux/pci.h>
|
|
+#include <linux/kernel.h>
|
|
+#include <linux/init.h>
|
|
+#include <linux/module.h>
|
|
+#include <linux/syscalls.h>
|
|
+#include <linux/file.h>
|
|
+#include <linux/fcntl.h>
|
|
+#include <linux/uaccess.h>
|
|
+#include <linux/interrupt.h>
|
|
+#include <linux/list.h>
|
|
+#include <linux/slab.h>
|
|
+#include <linux/mm.h>
|
|
+#include <linux/workqueue.h>
|
|
+#include <linux/pci.h>
|
|
+#include <linux/firmware.h>
|
|
+#include <sound/intel_lpe.h>
|
|
+#include <sound/intel_sst_ioctl.h>
|
|
+#include "intel_sst_fw_ipc.h"
|
|
+#include "intel_sst_common.h"
|
|
+#include "intelmid_snd_control.h"
|
|
+
|
|
+
|
|
+enum _reg_v1 {
|
|
+ VOICEPORT1 = 0x180,
|
|
+ VOICEPORT2 = 0x181,
|
|
+ AUDIOPORT1 = 0x182,
|
|
+ AUDIOPORT2 = 0x183,
|
|
+ MISCVOICECTRL = 0x184,
|
|
+ MISCAUDCTRL = 0x185,
|
|
+ DMICCTRL1 = 0x186,
|
|
+ DMICCTRL2 = 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;
|
|
+
|
|
+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, 0x00, 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, 0x06, 0x0},
|
|
+ {0x196, 0x7F, 0x0},
|
|
+ {0x197, 0x00, 0x0},
|
|
+ {0x198, 0x0B, 0x0},
|
|
+ {0x199, 0x00, 0x0},
|
|
+ {0x037, 0x3F, 0x0},
|
|
+ };
|
|
+
|
|
+ snd_pmic_ops_fs.card_status = SND_CARD_INIT_DONE;
|
|
+ return sst_sc_reg_access(sc_access, PMIC_WRITE, 27);
|
|
+}
|
|
+
|
|
+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 (PMIC_SND_MUTE_ALL == snd_pmic_ops_fs.mute_status )
|
|
+ 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);
|
|
+
|
|
+}
|
|
+int fs_power_up_pb(unsigned int port)
|
|
+{
|
|
+ struct sc_reg_access sc_access[] = {
|
|
+ {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, 2);
|
|
+
|
|
+ if (retval)
|
|
+ return retval;
|
|
+
|
|
+ return fs_enable_audiodac(UNMUTE);
|
|
+}
|
|
+
|
|
+int fs_power_up_cp(unsigned int port)
|
|
+{
|
|
+ struct sc_reg_access sc_access[] = {
|
|
+ {POWERCTRL2, 0x02, 0x02}, /*NOTE power up A ADC only as*/
|
|
+ /*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, 1);
|
|
+}
|
|
+
|
|
+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;
|
|
+ return fs_enable_audiodac(UNMUTE);
|
|
+}
|
|
+
|
|
+int fs_power_down(void)
|
|
+{
|
|
+ int retval = 0;
|
|
+
|
|
+ if (snd_pmic_ops_fs.card_status == SND_CARD_UN_INIT)
|
|
+ retval = fs_init_card();
|
|
+ if (retval)
|
|
+ return retval;
|
|
+ return retval;
|
|
+}
|
|
+
|
|
+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);
|
|
+}
|
|
+
|
|
+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, 0x6, 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);
|
|
+}
|
|
+
|
|
+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;
|
|
+}
|
|
+
|
|
+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;
|
|
+}
|
|
+
|
|
+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);
|
|
+
|
|
+ }
|
|
+ printk(KERN_DEBUG "SST DBG: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);
|
|
+
|
|
+}
|
|
+
|
|
+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, 0x10, MASK2|MASK4|MASK5|MASK6|MASK7},
|
|
+ {MICLICTRL3, 0x00, 0xE0},
|
|
+ };
|
|
+ struct sc_reg_access sc_access_hsmic[] = {
|
|
+ {MICCTRL, 0x40, 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:
|
|
+ printk(KERN_DEBUG "SST DBG:Selecting amic not supported in mono cfg\n");
|
|
+ return sst_sc_reg_access(sc_access_mic, PMIC_READ_MODIFY, 2);
|
|
+ break;
|
|
+
|
|
+ case HS_MIC:
|
|
+ printk(KERN_DEBUG "SST DBG:Selecting hsmic\n");
|
|
+ return sst_sc_reg_access(sc_access_hsmic,
|
|
+ PMIC_READ_MODIFY, 2);
|
|
+ break;
|
|
+
|
|
+ case DMIC:
|
|
+ printk(KERN_DEBUG "SST DBG:Selecting dmic\n");
|
|
+ return sst_sc_reg_access(sc_access_dmic, PMIC_READ_MODIFY, 2);
|
|
+ break;
|
|
+
|
|
+ default:
|
|
+ printk(KERN_ERR "SST ERR: +\
|
|
+ rcvd illegal request \n");
|
|
+ return -EINVAL;
|
|
+
|
|
+ }
|
|
+}
|
|
+
|
|
+int fs_set_selected_output_dev(u8 value)
|
|
+{
|
|
+ struct sc_reg_access sc_access_hp[] = {
|
|
+ {0x191, 0x11, 0x0},
|
|
+ {0x192, 0x0E, 0x0},
|
|
+ {0x195, 0x06, 0x0},
|
|
+ {0x196, 0x7E, 0x0},
|
|
+ };
|
|
+ struct sc_reg_access sc_access_is[] = {
|
|
+ {0x191, 0x17, 0xFF},
|
|
+ {0x192, 0x08, 0xFF},
|
|
+ {0x195, 0xC0, 0xFF},
|
|
+ {0x196, 0x12, 0x12},
|
|
+ };
|
|
+ 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:
|
|
+ printk(KERN_DEBUG "SST DBG:Selecting headphone \n");
|
|
+ return sst_sc_reg_access(sc_access_hp, PMIC_WRITE, 4);
|
|
+ break;
|
|
+
|
|
+ case INTERNAL_SPKR:
|
|
+ printk(KERN_DEBUG "SST DBG:Selecting internal spkr\n");
|
|
+ return sst_sc_reg_access(sc_access_is, PMIC_READ_MODIFY, 4);
|
|
+ break;
|
|
+
|
|
+ default:
|
|
+ printk(KERN_ERR "SST ERR: +\
|
|
+ rcvd illegal request \n");
|
|
+ return -EINVAL;
|
|
+
|
|
+ }
|
|
+}
|
|
+
|
|
+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;
|
|
+
|
|
+ snd_pmic_ops_fs.mute_status = dev_id;
|
|
+
|
|
+ printk(KERN_DEBUG "SST DBG: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;
|
|
+ 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;
|
|
+ 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;
|
|
+ break;
|
|
+
|
|
+ }
|
|
+ return sst_sc_reg_access(sc_access, PMIC_READ_MODIFY, reg_num);
|
|
+}
|
|
+
|
|
+int fs_set_vol(int dev_id, u8 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:
|
|
+ printk(KERN_DEBUG "SST DBG: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:
|
|
+ printk(KERN_DEBUG "SST DBG: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:
|
|
+ printk(KERN_DEBUG "SST DBG: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 = 0x3F - 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:
|
|
+ printk(KERN_ERR "SST ERR: +\
|
|
+ rcvd illegal request \n");
|
|
+ return -EINVAL;
|
|
+ }
|
|
+
|
|
+ return sst_sc_reg_access(sc_access, PMIC_READ_MODIFY, reg_num);
|
|
+}
|
|
+
|
|
+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;
|
|
+ case PMIC_SND_MUTE_ALL:
|
|
+ sc_access[0].reg_addr = AUD15;
|
|
+ sc_access[1].reg_addr = AUD16;
|
|
+ sc_access[2].reg_addr = AUD17;
|
|
+ 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;
|
|
+
|
|
+ retval = sst_sc_reg_access(sc_access, PMIC_READ, 6);
|
|
+ if (((sc_access[0].value & sc_access[0].mask) ==
|
|
+ sc_access[0].mask)
|
|
+ && ((sc_access[1].value & sc_access[1].mask) ==
|
|
+ sc_access[1].mask)
|
|
+ && ((sc_access[2].value & sc_access[2].mask) ==
|
|
+ sc_access[2].mask)
|
|
+ && ((sc_access[3].value & sc_access[3].mask) ==
|
|
+ sc_access[3].mask)
|
|
+ && ((sc_access[4].value & sc_access[4].mask) ==
|
|
+ sc_access[4].mask)
|
|
+ && ((sc_access[5].value & sc_access[5].mask) ==
|
|
+ sc_access[5].mask))
|
|
+ *value = MUTE;
|
|
+ else
|
|
+ *value = UNMUTE;
|
|
+ break;
|
|
+ default:
|
|
+ printk(KERN_ERR "SST ERR: +\
|
|
+ rcvd illegal request \n");
|
|
+ return -EINVAL;
|
|
+ }
|
|
+
|
|
+ return retval;
|
|
+}
|
|
+
|
|
+int fs_get_vol(int dev_id, u8 *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:
|
|
+ printk(KERN_DEBUG "SST DBG:PMIC_SND_CAPTURE_VOL\n");
|
|
+ sc_access.reg_addr = MICLICTRL1;
|
|
+ mask = (MASK5|MASK4|MASK3|MASK2|MASK1|MASK0);
|
|
+ break;
|
|
+ case PMIC_SND_LEFT_PB_VOL:
|
|
+ printk(KERN_DEBUG "SST DBG: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:
|
|
+ printk(KERN_DEBUG "SST DBG:PMIC_SND_LEFT_PB_VOL\n");
|
|
+ sc_access.reg_addr = AUD17;
|
|
+ mask = (MASK5|MASK4|MASK3|MASK2|MASK1|MASK0);
|
|
+ break;
|
|
+ default:
|
|
+ printk(KERN_ERR "SST ERR: +\
|
|
+ rcvd illegal request \n");
|
|
+ return -EINVAL;
|
|
+ }
|
|
+
|
|
+ retval = sst_sc_reg_access(&sc_access, PMIC_READ, 1);
|
|
+ printk(KERN_DEBUG "SST DBG:value read = 0x%x\n", sc_access.value);
|
|
+ *value = (sc_access.value) & mask;
|
|
+ printk(KERN_DEBUG "SST DBG: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,
|
|
+};
|
|
diff --git a/sound/pci/sst/intelmid_v1_control.c b/sound/pci/sst/intelmid_v1_control.c
|
|
new file mode 100644
|
|
index 0000000..740ffaf
|
|
--- /dev/null
|
|
+++ b/sound/pci/sst/intelmid_v1_control.c
|
|
@@ -0,0 +1,846 @@
|
|
+/*
|
|
+ * intel_sst_v1_control.c - Intel SST Driver for audio engine
|
|
+ *
|
|
+ * Copyright (C) 2008-10 Intel Corp
|
|
+ * 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 2
|
|
+ */
|
|
+
|
|
+#include <linux/cdev.h>
|
|
+#include <linux/pci.h>
|
|
+#include <linux/kernel.h>
|
|
+#include <linux/init.h>
|
|
+#include <linux/module.h>
|
|
+#include <linux/syscalls.h>
|
|
+#include <linux/file.h>
|
|
+#include <linux/fcntl.h>
|
|
+#include <linux/uaccess.h>
|
|
+#include <linux/interrupt.h>
|
|
+#include <linux/list.h>
|
|
+#include <linux/slab.h>
|
|
+#include <linux/mm.h>
|
|
+#include <linux/workqueue.h>
|
|
+#include <linux/pci.h>
|
|
+#include <linux/firmware.h>
|
|
+#include <sound/intel_lpe.h>
|
|
+#include <sound/intel_sst_ioctl.h>
|
|
+#include "intel_sst_fw_ipc.h"
|
|
+#include "intel_sst_common.h"
|
|
+#include "intelmid_snd_control.h"
|
|
+
|
|
+enum _reg_v2 {
|
|
+
|
|
+ MASTER_CLOCK_PRESCALAR = 0x205,
|
|
+ SET_MASTER_AND_LR_CLK1 = 0x20b,
|
|
+ SET_MASTER_AND_LR_CLK2 = 0x20c,
|
|
+ MASTER_MODE_AND_DATA_DELAY = 0x20d,
|
|
+ DIGITAL_INTERFACE_TO_DAI2 = 0x20e,
|
|
+ CLK_AND_FS1 = 0x208,
|
|
+ CLK_AND_FS2 = 0x209,
|
|
+ DAI2_TO_DAC_HP = 0x210,
|
|
+ HP_OP_SINGLE_ENDED = 0x224,
|
|
+ ENABLE_OPDEV_CTRL = 0x226,
|
|
+ ENABLE_DEV_AND_USE_XTAL = 0x227,
|
|
+
|
|
+ /* Max audio subsystem (PQ49) MAX 8921 */
|
|
+ AS_IP_MODE_CTL = 0xF9,
|
|
+ AS_LEFT_SPKR_VOL_CTL = 0xFA, /* Mono Earpiece volume control */
|
|
+ AS_RIGHT_SPKR_VOL_CTL = 0xFB,
|
|
+ AS_LEFT_HP_VOL_CTL = 0xFC,
|
|
+ AS_RIGHT_HP_VOL_CTL = 0xFD,
|
|
+ AS_OP_MIX_CTL = 0xFE,
|
|
+ AS_CONFIG = 0xFF,
|
|
+
|
|
+ /* Headphone volume control & mute registers */
|
|
+ VOL_CTRL_LT = 0x21c,
|
|
+ VOL_CTRL_RT = 0x21d,
|
|
+
|
|
+};
|
|
+
|
|
+int mx_init_card(void)
|
|
+{
|
|
+ struct sc_reg_access sc_access[] = {
|
|
+ {0x200, 0x80, 0x00},
|
|
+ {0x201, 0xC0, 0x00},
|
|
+ {0x202, 0x00, 0x00},
|
|
+ {0x203, 0x00, 0x00},
|
|
+ {0x204, 0x02, 0x00},
|
|
+ {0x205, 0x10, 0x00},
|
|
+ {0x206, 0x60, 0x00},
|
|
+ {0x207, 0x00, 0x00},
|
|
+ {0x208, 0x90, 0x00},
|
|
+ {0x209, 0x51, 0x00},
|
|
+ {0x20a, 0x00, 0x00},
|
|
+ {0x20b, 0x10, 0x00},
|
|
+ {0x20c, 0x00, 0x00},
|
|
+ {0x20d, 0x00, 0x00},
|
|
+ {0x20e, 0x11, 0x00},
|
|
+ {0x20f, 0x00, 0x00},
|
|
+ {0x210, 0x84, 0x00},
|
|
+ {0x211, 0xB3, 0x00},
|
|
+ {0x212, 0x00, 0x00},
|
|
+ {0x213, 0x00, 0x00},
|
|
+ {0x214, 0x41, 0x00},
|
|
+ {0x215, 0x00, 0x00},
|
|
+ {0x216, 0x00, 0x00},
|
|
+ {0x217, 0x00, 0x00},
|
|
+ {0x218, 0x03, 0x00},
|
|
+ {0x219, 0x03, 0x00},
|
|
+ {0x21a, 0x00, 0x00},
|
|
+ {0x21b, 0x00, 0x00},
|
|
+ {0x21c, 0x09, 0x00},
|
|
+ {0x21d, 0x09, 0x00},
|
|
+ {0x21e, 0x00, 0x00},
|
|
+ {0x21f, 0x00, 0x00},
|
|
+ {0x220, 0x54, 0x00},
|
|
+ {0x221, 0x54, 0x00},
|
|
+ {0x222, 0x50, 0x00},
|
|
+ {0x223, 0x00, 0x00},
|
|
+ {0x224, 0x04, 0x00},
|
|
+ {0x225, 0x80, 0x00},
|
|
+ {0x226, 0x0F, 0x00},
|
|
+ {0x227, 0x08, 0x00},
|
|
+ {0xf9, 0x40, 0x00},
|
|
+ {0xfa, 0x1f, 0x00},
|
|
+ {0xfb, 0x1f, 0x00},
|
|
+ {0xfc, 0x1f, 0x00},
|
|
+ {0xfd, 0x1f, 0x00},
|
|
+ {0xfe, 0x00, 0x00},
|
|
+ {0xff, 0x0c, 0x00},
|
|
+ };
|
|
+ snd_pmic_ops_mx.card_status = SND_CARD_INIT_DONE;
|
|
+ snd_pmic_ops_mx.num_channel = 2;
|
|
+ return sst_sc_reg_access(sc_access, PMIC_WRITE, 47);
|
|
+}
|
|
+
|
|
+
|
|
+
|
|
+int mx_enable_audiodac(int value)
|
|
+{
|
|
+ struct sc_reg_access sc_access[3];
|
|
+ int mute_val = 0;
|
|
+ int mute_val1 = 0;
|
|
+ u8 vol_value;
|
|
+
|
|
+ sc_access[0].reg_addr = AS_LEFT_HP_VOL_CTL;
|
|
+ sc_access[1].reg_addr = AS_RIGHT_HP_VOL_CTL;
|
|
+
|
|
+
|
|
+ if (value == UNMUTE) {
|
|
+
|
|
+ mute_val = 0x1f;
|
|
+ mute_val1 = 0x00;
|
|
+
|
|
+ } else {
|
|
+
|
|
+ mute_val = 0x00;
|
|
+ mute_val1 = 0x40;
|
|
+
|
|
+ }
|
|
+
|
|
+
|
|
+ sc_access[0].mask = sc_access[1].mask = MASK0|MASK1|MASK2|MASK3|MASK4;
|
|
+ sc_access[0].value = sc_access[1].value = mute_val;
|
|
+
|
|
+ sst_sc_reg_access(sc_access, PMIC_READ_MODIFY, 2);
|
|
+
|
|
+ sc_access[0].reg_addr = VOL_CTRL_LT;
|
|
+ sc_access[1].reg_addr = VOL_CTRL_RT;
|
|
+ sc_access[0].mask = sc_access[1].mask = MASK6;
|
|
+ sc_access[0].value = sc_access[1].value = mute_val1;
|
|
+ if ( snd_pmic_ops_mx.num_channel == 1)
|
|
+ sc_access[1].value = 0x40;
|
|
+
|
|
+ return sst_sc_reg_access(sc_access, PMIC_READ_MODIFY, 2);
|
|
+
|
|
+
|
|
+
|
|
+}
|
|
+int mx_power_up_pb(unsigned int port)
|
|
+{
|
|
+
|
|
+ int retval = 0;
|
|
+ struct sc_reg_access sc_access[3];
|
|
+
|
|
+
|
|
+
|
|
+ if (snd_pmic_ops_mx.card_status == SND_CARD_UN_INIT)
|
|
+ retval = mx_init_card();
|
|
+ if (retval)
|
|
+ return retval;
|
|
+
|
|
+
|
|
+
|
|
+ retval = mx_enable_audiodac(MUTE);
|
|
+
|
|
+ mdelay(10);
|
|
+
|
|
+ sc_access[0].reg_addr = AS_CONFIG;
|
|
+ sc_access[0].mask = MASK7;
|
|
+ sc_access[0].value = 0x80;
|
|
+
|
|
+ retval = sst_sc_reg_access(sc_access, PMIC_READ_MODIFY, 1);
|
|
+
|
|
+
|
|
+
|
|
+ sc_access[0].reg_addr = ENABLE_OPDEV_CTRL;
|
|
+ sc_access[0].mask = MASK3|MASK2;
|
|
+ sc_access[0].value = 0x0C;
|
|
+
|
|
+ retval = sst_sc_reg_access(sc_access, PMIC_READ_MODIFY, 1);
|
|
+ sc_access[0].reg_addr = ENABLE_DEV_AND_USE_XTAL;
|
|
+ sc_access[0].mask = MASK7|MASK3;
|
|
+ sc_access[0].value = 0x88;
|
|
+
|
|
+ retval = sst_sc_reg_access(sc_access, PMIC_READ_MODIFY, 1);
|
|
+
|
|
+
|
|
+
|
|
+ retval = mx_enable_audiodac(UNMUTE);
|
|
+
|
|
+ return retval;
|
|
+
|
|
+}
|
|
+
|
|
+int mx_power_up_cp(unsigned int port)
|
|
+{
|
|
+ struct sc_reg_access sc_access[] = {
|
|
+ {0x226, 0x03, MASK1|MASK0},
|
|
+ {0x227, 0x88, MASK7|MASK3},
|
|
+ };
|
|
+ int retval = 0;
|
|
+
|
|
+ if (snd_pmic_ops_mx.card_status == SND_CARD_UN_INIT)
|
|
+ retval = mx_init_card();
|
|
+ if (retval)
|
|
+ return retval;
|
|
+
|
|
+ return sst_sc_reg_access(sc_access, PMIC_READ_MODIFY, 2);
|
|
+}
|
|
+
|
|
+int mx_power_down_pb(void)
|
|
+{
|
|
+
|
|
+ struct sc_reg_access sc_access[3];
|
|
+ int retval = 0;
|
|
+
|
|
+
|
|
+
|
|
+ if (snd_pmic_ops_mx.card_status == SND_CARD_UN_INIT)
|
|
+ retval = mx_init_card();
|
|
+ if (retval)
|
|
+ return retval;
|
|
+
|
|
+ retval = mx_enable_audiodac(MUTE);
|
|
+
|
|
+
|
|
+ sc_access[0].reg_addr = ENABLE_OPDEV_CTRL;
|
|
+ sc_access[0].mask = MASK3|MASK2;
|
|
+ sc_access[0].value = 0x00;
|
|
+
|
|
+ retval = sst_sc_reg_access(sc_access, PMIC_READ_MODIFY, 1);
|
|
+
|
|
+
|
|
+ retval = mx_enable_audiodac(UNMUTE);
|
|
+
|
|
+ return retval;
|
|
+
|
|
+
|
|
+}
|
|
+
|
|
+int mx_power_down_cp(void)
|
|
+{
|
|
+ struct sc_reg_access sc_access[] = {
|
|
+ {0x226, 0x00, MASK1|MASK0},
|
|
+ };
|
|
+ int retval = 0;
|
|
+
|
|
+ if (snd_pmic_ops_mx.card_status == SND_CARD_UN_INIT)
|
|
+ retval = mx_init_card();
|
|
+ if (retval)
|
|
+ return retval;
|
|
+
|
|
+ return sst_sc_reg_access(sc_access, PMIC_READ_MODIFY, 1);
|
|
+
|
|
+}
|
|
+
|
|
+int mx_power_down(void)
|
|
+{
|
|
+ int retval = 0;
|
|
+ struct sc_reg_access sc_access[3];
|
|
+
|
|
+
|
|
+ if (snd_pmic_ops_mx.card_status == SND_CARD_UN_INIT)
|
|
+ retval = mx_init_card();
|
|
+ if (retval)
|
|
+ return retval;
|
|
+
|
|
+
|
|
+ retval = mx_enable_audiodac(MUTE);
|
|
+
|
|
+ sc_access[0].reg_addr = AS_CONFIG;
|
|
+ sc_access[0].mask = MASK7;
|
|
+ sc_access[0].value = 0x00;
|
|
+
|
|
+ retval = sst_sc_reg_access(sc_access, PMIC_READ_MODIFY, 1);
|
|
+
|
|
+ sc_access[0].reg_addr = ENABLE_DEV_AND_USE_XTAL;
|
|
+ sc_access[0].mask = MASK7;
|
|
+ sc_access[0].value = 0x00;
|
|
+
|
|
+ retval = sst_sc_reg_access(sc_access, PMIC_READ_MODIFY, 1);
|
|
+
|
|
+ retval = mx_enable_audiodac(UNMUTE);
|
|
+
|
|
+ return retval;
|
|
+
|
|
+
|
|
+}
|
|
+
|
|
+int mx_set_voice_port(int status)
|
|
+{
|
|
+ int retval = 0;
|
|
+
|
|
+ if (snd_pmic_ops_mx.card_status == SND_CARD_UN_INIT)
|
|
+ retval = mx_init_card();
|
|
+ if (retval)
|
|
+ return retval;
|
|
+
|
|
+ return retval;
|
|
+}
|
|
+
|
|
+int mx_set_audio_port(int status)
|
|
+{
|
|
+ int retval = 0;
|
|
+
|
|
+ if (snd_pmic_ops_mx.card_status == SND_CARD_UN_INIT)
|
|
+ retval = mx_init_card();
|
|
+ if (retval)
|
|
+ return retval;
|
|
+ return retval;
|
|
+}
|
|
+int mx_set_pcm_voice_params(void)
|
|
+{
|
|
+ int retval = 0;
|
|
+
|
|
+ if (snd_pmic_ops_mx.card_status == SND_CARD_UN_INIT)
|
|
+ retval = mx_init_card();
|
|
+ if (retval)
|
|
+ return retval;
|
|
+
|
|
+ return retval;
|
|
+}
|
|
+
|
|
+int mx_set_pcm_audio_params(int sfreq, int word_size , int num_channel)
|
|
+{
|
|
+ int config1 = 0, config2 = 0, filter = 0xB3;
|
|
+ struct sc_reg_access sc_access[5];
|
|
+ int retval = 0;
|
|
+
|
|
+ if (snd_pmic_ops_mx.card_status == SND_CARD_UN_INIT)
|
|
+ retval = mx_init_card();
|
|
+ if (retval)
|
|
+ return retval;
|
|
+
|
|
+
|
|
+ switch (sfreq) {
|
|
+ case 8000:
|
|
+ config1 = 0x10;
|
|
+ config2 = 0x00;
|
|
+ filter = 0x33;
|
|
+ break;
|
|
+ case 11025:
|
|
+ config1 = 0x16;
|
|
+ config2 = 0x0d;
|
|
+ break;
|
|
+ case 12000:
|
|
+ config1 = 0x18;
|
|
+ config2 = 0x00;
|
|
+ break;
|
|
+ case 16000:
|
|
+ config1 = 0x20;
|
|
+ config2 = 0x00;
|
|
+ break;
|
|
+ case 22050:
|
|
+ config1 = 0x2c;
|
|
+ config2 = 0x1a;
|
|
+ break;
|
|
+ case 24000:
|
|
+ config1 = 0x30;
|
|
+ config2 = 0x00;
|
|
+ break;
|
|
+ case 32000:
|
|
+ config1 = 0x40;
|
|
+ config2 = 0x00;
|
|
+ break;
|
|
+ case 44100:
|
|
+ config1 = 0x58;
|
|
+ config2 = 0x33;
|
|
+ break;
|
|
+ case 48000:
|
|
+ config1 = 0x60;
|
|
+ config2 = 0x00;
|
|
+ break;
|
|
+ }
|
|
+
|
|
+ snd_pmic_ops_mx.num_channel = num_channel;
|
|
+ /*mute the right channel if MONO*/
|
|
+ if(snd_pmic_ops_mx.num_channel == 1)
|
|
+ {
|
|
+
|
|
+ sc_access[0].reg_addr = VOL_CTRL_RT;
|
|
+ sc_access[0].value = 0x40;
|
|
+ sc_access[0].mask = MASK6;
|
|
+
|
|
+ sc_access[1].reg_addr = 0x224;
|
|
+ sc_access[1].value = 0x05;
|
|
+ sc_access[1].mask = MASK0|MASK1|MASK2;
|
|
+
|
|
+ sst_sc_reg_access(sc_access, PMIC_READ_MODIFY, 2);
|
|
+
|
|
+ }
|
|
+ else
|
|
+ {
|
|
+ sc_access[0].reg_addr = VOL_CTRL_RT;
|
|
+ sc_access[0].value = 0x00;
|
|
+ sc_access[0].mask = MASK6;
|
|
+
|
|
+ sc_access[1].reg_addr = 0x224;
|
|
+ sc_access[1].value = 0x04;
|
|
+ sc_access[1].mask = MASK0|MASK1|MASK2;
|
|
+
|
|
+ sst_sc_reg_access(sc_access, PMIC_READ_MODIFY, 2);
|
|
+
|
|
+ }
|
|
+ sc_access[0].reg_addr = 0x206;
|
|
+ sc_access[0].value = config1;
|
|
+ sc_access[1].reg_addr = 0x207;
|
|
+ sc_access[1].value = config2;
|
|
+
|
|
+ if (word_size == 16) {
|
|
+ sc_access[2].value = 0x51;
|
|
+ sc_access[3].value = 0x31;
|
|
+ }
|
|
+ else if (word_size == 24) {
|
|
+ sc_access[2].value =0x52;
|
|
+ sc_access[3].value = 0x92;
|
|
+
|
|
+ }
|
|
+
|
|
+ sc_access[2].reg_addr = 0x209;
|
|
+ sc_access[3].reg_addr = 0x20e;
|
|
+
|
|
+ sc_access[4].reg_addr = 0x211;
|
|
+ sc_access[4].value = filter;
|
|
+
|
|
+ sst_sc_reg_access(sc_access, PMIC_WRITE, 5);
|
|
+
|
|
+ return 0;
|
|
+}
|
|
+
|
|
+int mx_set_selected_output_dev(u8 dev_id)
|
|
+{
|
|
+ struct sc_reg_access sc_access[6];
|
|
+ int num_reg = 0;
|
|
+ int retval = 0;
|
|
+
|
|
+ if (snd_pmic_ops_mx.card_status == SND_CARD_UN_INIT)
|
|
+ retval = mx_init_card();
|
|
+ if (retval)
|
|
+ return retval;
|
|
+ printk(KERN_DEBUG "SST DBG:mx_set_selected_output_dev +\
|
|
+ dev_id:0x%x\n", dev_id);
|
|
+ switch (dev_id) {
|
|
+ case STEREO_HEADPHONE:
|
|
+ sc_access[0].reg_addr = 0x226;
|
|
+ sc_access[0].value = 0x0C;
|
|
+ sc_access[0].mask = 0x3F;
|
|
+
|
|
+ /*sc_access[3].reg_addr = 0xFA;
|
|
+ sc_access[3].value = 0x00;
|
|
+ sc_access[3].mask = MASK0|MASK1|MASK2|MASK3|MASK4|MASK5|MASK6|MASK7;
|
|
+
|
|
+ sc_access[5].reg_addr = 0xFB;
|
|
+ sc_access[5].value = 0x00;
|
|
+ sc_access[5].mask = MASK0|MASK1|MASK2|MASK3|MASK4|MASK5|MASK6|MASK7;
|
|
+
|
|
+
|
|
+ sc_access[1].reg_addr = 0xFC;
|
|
+ sc_access[1].value = 0x1F;
|
|
+ sc_access[1].mask = 0x1F;
|
|
+
|
|
+ sc_access[4].reg_addr = 0xFD;
|
|
+ sc_access[4].value = 0x1F;
|
|
+ sc_access[4].mask = 0x1F; */
|
|
+
|
|
+ sc_access[1].reg_addr = 0xFF;
|
|
+ sc_access[1].value = 0x0C;
|
|
+ sc_access[1].mask = MASK2|MASK3|MASK5|MASK6|MASK4;
|
|
+
|
|
+ num_reg = 2;
|
|
+ break;
|
|
+ case INTERNAL_SPKR:
|
|
+ sc_access[0].reg_addr = 0x226;
|
|
+ sc_access[0].value = 0x3F;
|
|
+ sc_access[0].mask = 0x3F;
|
|
+
|
|
+
|
|
+ /*sc_access[1].reg_addr = 0xFA;
|
|
+ sc_access[1].value = 0x1F;
|
|
+ sc_access[1].mask = 0x1F;
|
|
+
|
|
+ sc_access[2].reg_addr = 0xFB;
|
|
+ sc_access[2].value = 0x1F;
|
|
+ sc_access[2].mask = 0x1F;
|
|
+
|
|
+ sc_access[3].reg_addr = 0xFC;
|
|
+ sc_access[3].value = 0x00;
|
|
+ sc_access[3].mask = MASK0|MASK1|MASK2|MASK3|MASK4|MASK5|MASK6|MASK7;
|
|
+
|
|
+
|
|
+
|
|
+ sc_access[4].reg_addr = 0xFD;
|
|
+ sc_access[4].value = 0x00;
|
|
+ sc_access[4].mask = MASK0|MASK1|MASK2|MASK3|MASK4|MASK5|MASK6|MASK7; */
|
|
+
|
|
+ sc_access[1].reg_addr = 0xFF;
|
|
+ sc_access[1].value = 0x30;
|
|
+ sc_access[1].mask = MASK2|MASK3|MASK5|MASK6|MASK4;
|
|
+
|
|
+ num_reg = 2;
|
|
+ break;
|
|
+ }
|
|
+ return sst_sc_reg_access(sc_access, PMIC_READ_MODIFY, num_reg);
|
|
+}
|
|
+
|
|
+int mx_set_selected_input_dev(u8 dev_id)
|
|
+{
|
|
+ struct sc_reg_access sc_access[2];
|
|
+ int num_reg = 0;
|
|
+ int retval = 0;
|
|
+
|
|
+ if (snd_pmic_ops_mx.card_status == SND_CARD_UN_INIT)
|
|
+ retval = mx_init_card();
|
|
+ if (retval)
|
|
+ return retval;
|
|
+ snd_pmic_ops_mx.input_dev_id = dev_id;
|
|
+ printk(KERN_DEBUG "SST DBG:mx_set_selected_input_+\
|
|
+ dev dev_id:0x%x\n", dev_id);
|
|
+
|
|
+ switch (dev_id) {
|
|
+ case AMIC:
|
|
+ sc_access[0].reg_addr = 0x223;
|
|
+ sc_access[0].value = 0x00;
|
|
+ sc_access[0].mask = MASK7|MASK6|MASK5|MASK4|MASK0;
|
|
+ sc_access[1].reg_addr = 0x222;
|
|
+ sc_access[1].value = 0x50;
|
|
+ sc_access[1].mask = MASK7|MASK6|MASK5|MASK4;
|
|
+ num_reg = 2;
|
|
+ break;
|
|
+
|
|
+ case HS_MIC:
|
|
+ sc_access[0].reg_addr = 0x223;
|
|
+ sc_access[0].value = 0x00;
|
|
+ sc_access[0].mask = MASK7|MASK6|MASK5|MASK4|MASK0;
|
|
+ sc_access[1].reg_addr = 0x222;
|
|
+ sc_access[1].value = 0x70;
|
|
+ sc_access[1].mask = MASK7|MASK6|MASK5|MASK4;
|
|
+ num_reg = 2;
|
|
+ break;
|
|
+ case DMIC:
|
|
+ sc_access[1].reg_addr = 0x222;
|
|
+ sc_access[1].value = 0x00;
|
|
+ sc_access[1].mask = MASK7|MASK6|MASK5|MASK4|MASK0;
|
|
+ sc_access[0].reg_addr = 0x223;
|
|
+ sc_access[0].value = 0x20;
|
|
+ sc_access[0].mask = MASK7|MASK6|MASK5|MASK4|MASK0;
|
|
+ num_reg = 2;
|
|
+ break;
|
|
+ }
|
|
+ return sst_sc_reg_access(sc_access, PMIC_WRITE, num_reg);
|
|
+}
|
|
+
|
|
+int mx_set_mute(int dev_id, u8 value)
|
|
+{
|
|
+ struct sc_reg_access sc_access[5], sc_acces;
|
|
+ int num_reg = 0;
|
|
+ int retval = 0;
|
|
+
|
|
+ if (snd_pmic_ops_mx.card_status == SND_CARD_UN_INIT)
|
|
+ retval = mx_init_card();
|
|
+ if (retval)
|
|
+ return retval;
|
|
+
|
|
+
|
|
+
|
|
+ printk(KERN_DEBUG "SST DBG:mx_set_mute +\
|
|
+ dev_id:0x%x , value:%d \n", dev_id, value);
|
|
+
|
|
+ switch (dev_id) {
|
|
+ case PMIC_SND_DMIC_MUTE:
|
|
+ case PMIC_SND_AMIC_MUTE:
|
|
+ case PMIC_SND_HP_MIC_MUTE:
|
|
+ sc_access[0].reg_addr = 0x220;
|
|
+ sc_access[1].reg_addr = 0x221;
|
|
+ sc_access[2].reg_addr = 0x223;
|
|
+ if (value == MUTE) {
|
|
+ sc_access[0].value = 0x00;
|
|
+ sc_access[1].value = 0x00;
|
|
+ if (snd_pmic_ops_mx.input_dev_id == DMIC)
|
|
+ sc_access[2].value = 0x00;
|
|
+ else
|
|
+ sc_access[2].value = 0x20;
|
|
+ } else {
|
|
+ sc_access[0].value = 0x20;
|
|
+ sc_access[1].value = 0x20;
|
|
+ if (snd_pmic_ops_mx.input_dev_id == DMIC)
|
|
+ sc_access[2].value = 0x20;
|
|
+ else
|
|
+ sc_access[2].value = 0x00;
|
|
+ }
|
|
+ sc_access[0].mask = MASK5|MASK6;
|
|
+ sc_access[1].mask = MASK5|MASK6;
|
|
+ sc_access[2].mask = MASK5|MASK6;
|
|
+ num_reg = 3;
|
|
+ break;
|
|
+ case PMIC_SND_LEFT_SPEAKER_MUTE:
|
|
+ case PMIC_SND_LEFT_HP_MUTE:
|
|
+ sc_access[0].reg_addr = VOL_CTRL_LT;
|
|
+ if (value == MUTE)
|
|
+ sc_access[0].value = 0x40;
|
|
+ else
|
|
+ sc_access[0].value = 0x00;
|
|
+ sc_access[0].mask = MASK6;
|
|
+ num_reg = 1;
|
|
+ break;
|
|
+ case PMIC_SND_RIGHT_SPEAKER_MUTE:
|
|
+ case PMIC_SND_RIGHT_HP_MUTE:
|
|
+ sc_access[0].reg_addr = VOL_CTRL_RT;
|
|
+ if(snd_pmic_ops_mx.num_channel == 1)
|
|
+ value = MUTE;
|
|
+ if (value == MUTE)
|
|
+ sc_access[0].value = 0x40;
|
|
+ else
|
|
+ sc_access[0].value = 0x00;
|
|
+ sc_access[0].mask = MASK6;
|
|
+ num_reg = 1;
|
|
+ break;
|
|
+
|
|
+ case PMIC_SND_MUTE_ALL:
|
|
+ sc_access[0].reg_addr = VOL_CTRL_RT;
|
|
+ sc_access[1].reg_addr = VOL_CTRL_LT;
|
|
+ sc_access[2].reg_addr = 0x220;
|
|
+ sc_access[3].reg_addr = 0x221;
|
|
+ sc_access[4].reg_addr = 0x223;
|
|
+ if (value == MUTE) {
|
|
+ sc_access[0].value = sc_access[1].value = 0x40;
|
|
+ sc_access[2].value = 0x00;
|
|
+ sc_access[3].value = 0x00;
|
|
+ sc_acces.reg_addr = 0x222;
|
|
+ sc_acces.value = 0x00;
|
|
+ sc_acces.mask = MASK4|MASK5|MASK6|MASK7;
|
|
+ sst_sc_reg_access(&sc_acces, PMIC_READ_MODIFY, 1);
|
|
+ sc_access[4].value = 0x00;
|
|
+
|
|
+ } else {
|
|
+ sc_access[0].value = sc_access[1].value = 0x00;
|
|
+ sc_access[2].value = 0x20;
|
|
+ sc_access[3].value = 0x20;
|
|
+ sc_access[4].value = 0x20;
|
|
+ }
|
|
+ if(snd_pmic_ops_mx.num_channel == 1)
|
|
+ sc_access[0].value = 0x40;
|
|
+ sc_access[0].mask = sc_access[1].mask = MASK6;
|
|
+ sc_access[2].mask = MASK5|MASK6;
|
|
+ sc_access[3].mask = MASK5|MASK6|MASK2|MASK4;
|
|
+ sc_access[4].mask = MASK5|MASK6;
|
|
+ num_reg = 5;
|
|
+ break;
|
|
+ }
|
|
+
|
|
+ return sst_sc_reg_access(sc_access, PMIC_READ_MODIFY, num_reg);
|
|
+}
|
|
+
|
|
+int mx_set_vol(int dev_id, u8 value)
|
|
+{
|
|
+ struct sc_reg_access sc_access[2] = {{0},};
|
|
+ int num_reg = 0;
|
|
+ int retval = 0;
|
|
+
|
|
+ if (snd_pmic_ops_mx.card_status == SND_CARD_UN_INIT)
|
|
+ retval = mx_init_card();
|
|
+ if (retval)
|
|
+ return retval;
|
|
+
|
|
+ printk(KERN_DEBUG "SST DBG:mx_set_vol dev_id:0x%x , \
|
|
+ value:%d \n", dev_id, value);
|
|
+ switch (dev_id) {
|
|
+ case PMIC_SND_CAPTURE_VOL:
|
|
+ sc_access[0].reg_addr = 0x220;
|
|
+ sc_access[1].reg_addr = 0x221;
|
|
+ sc_access[0].value = sc_access[1].value = -value;
|
|
+ sc_access[0].mask = sc_access[1].mask =
|
|
+ (MASK0|MASK1|MASK2|MASK3|MASK4);
|
|
+ num_reg = 2;
|
|
+ break;
|
|
+ case PMIC_SND_LEFT_PB_VOL:
|
|
+ sc_access[0].value = -value;
|
|
+ sc_access[0].reg_addr = VOL_CTRL_LT;
|
|
+ sc_access[0].mask = (MASK0|MASK1|MASK2|MASK3|MASK4|MASK5);
|
|
+ num_reg = 1;
|
|
+ break;
|
|
+ case PMIC_SND_RIGHT_PB_VOL:
|
|
+ sc_access[0].value = -value;
|
|
+ sc_access[0].reg_addr = VOL_CTRL_RT;
|
|
+ sc_access[0].mask = (MASK0|MASK1|MASK2|MASK3|MASK4|MASK5);
|
|
+ if(snd_pmic_ops_mx.num_channel == 1) {
|
|
+ sc_access[0].value = 0x40;
|
|
+ sc_access[0].mask = MASK6;
|
|
+ sc_access[0].reg_addr = VOL_CTRL_RT;
|
|
+ }
|
|
+ num_reg = 1;
|
|
+ break;
|
|
+ }
|
|
+ return sst_sc_reg_access(sc_access, PMIC_READ_MODIFY, num_reg);
|
|
+}
|
|
+
|
|
+int mx_get_mute(int dev_id, u8 *value)
|
|
+{
|
|
+ struct sc_reg_access sc_access[4] = {{0},};
|
|
+ int retval = 0, num_reg = 0, mask = 0;
|
|
+
|
|
+ if (snd_pmic_ops_mx.card_status == SND_CARD_UN_INIT)
|
|
+ retval = mx_init_card();
|
|
+ if (retval)
|
|
+ return retval;
|
|
+
|
|
+ switch (dev_id) {
|
|
+ case PMIC_SND_DMIC_MUTE:
|
|
+ case PMIC_SND_AMIC_MUTE:
|
|
+ case PMIC_SND_HP_MIC_MUTE:
|
|
+ sc_access[0].reg_addr = 0x220;
|
|
+ mask = MASK5|MASK6;
|
|
+ num_reg = 1;
|
|
+ retval = sst_sc_reg_access(sc_access, PMIC_READ, num_reg);
|
|
+ if (retval)
|
|
+ return retval;
|
|
+ *value = sc_access[0].value & mask;
|
|
+ if (*value)
|
|
+ *value = UNMUTE;
|
|
+ else
|
|
+ *value = MUTE;
|
|
+ return retval;
|
|
+
|
|
+ case PMIC_SND_LEFT_HP_MUTE:
|
|
+ case PMIC_SND_LEFT_SPEAKER_MUTE:
|
|
+ sc_access[0].reg_addr = VOL_CTRL_LT;
|
|
+ num_reg = 1;
|
|
+ mask = MASK6;
|
|
+ break;
|
|
+ case PMIC_SND_RIGHT_HP_MUTE:
|
|
+ case PMIC_SND_RIGHT_SPEAKER_MUTE:
|
|
+ sc_access[0].reg_addr = VOL_CTRL_RT;
|
|
+ num_reg = 1;
|
|
+ mask = MASK6;
|
|
+ break;
|
|
+ case PMIC_SND_MUTE_ALL:
|
|
+ sc_access[0].reg_addr = VOL_CTRL_RT;
|
|
+ sc_access[1].reg_addr = VOL_CTRL_LT;
|
|
+ sc_access[2].reg_addr = 0x220;
|
|
+ sc_access[3].reg_addr = 0x221;
|
|
+ num_reg = 4;
|
|
+ retval = sst_sc_reg_access(sc_access, PMIC_READ, num_reg);
|
|
+ if (((sc_access[0].value & MASK6) == MASK6) &&
|
|
+ ((sc_access[1].value & MASK6) == MASK6) &&
|
|
+ ((sc_access[2].value & (MASK5|MASK6)) == 0) &&
|
|
+ ((sc_access[3].value & (MASK5|MASK6)) == 0))
|
|
+ *value = MUTE;
|
|
+ else
|
|
+ *value = UNMUTE;
|
|
+ break;
|
|
+ }
|
|
+ retval = sst_sc_reg_access(sc_access, PMIC_READ, num_reg);
|
|
+ if (retval)
|
|
+ return retval;
|
|
+ *value = sc_access[0].value & mask;
|
|
+ if (*value)
|
|
+ *value = MUTE;
|
|
+ else
|
|
+ *value = UNMUTE;
|
|
+ return retval;
|
|
+}
|
|
+
|
|
+int mx_get_vol(int dev_id, u8 *value)
|
|
+{
|
|
+ struct sc_reg_access sc_access = {0,};
|
|
+ int retval = 0, mask = 0, num_reg = 0;
|
|
+
|
|
+ if (snd_pmic_ops_mx.card_status == SND_CARD_UN_INIT)
|
|
+ retval = mx_init_card();
|
|
+ if (retval)
|
|
+ return retval;
|
|
+
|
|
+ switch (dev_id) {
|
|
+ case PMIC_SND_CAPTURE_VOL:
|
|
+ sc_access.reg_addr = 0x220;
|
|
+ mask = MASK0|MASK1|MASK2|MASK3|MASK4|MASK5;
|
|
+ num_reg = 1;
|
|
+ break;
|
|
+ case PMIC_SND_LEFT_PB_VOL:
|
|
+ sc_access.reg_addr = VOL_CTRL_LT;
|
|
+ mask = MASK0|MASK1|MASK2|MASK3|MASK4|MASK5;
|
|
+ num_reg = 1;
|
|
+ break;
|
|
+ case PMIC_SND_RIGHT_PB_VOL:
|
|
+ sc_access.reg_addr = VOL_CTRL_RT;
|
|
+ mask = MASK0|MASK1|MASK2|MASK3|MASK4|MASK5;
|
|
+ num_reg = 1;
|
|
+ break;
|
|
+ }
|
|
+ retval = sst_sc_reg_access(&sc_access, PMIC_READ, num_reg);
|
|
+ if (retval)
|
|
+ return retval;
|
|
+ *value = -(sc_access.value & mask);
|
|
+ printk(KERN_DEBUG "SST DBG:value extracted 0x%x\n", *value);
|
|
+ return retval;
|
|
+}
|
|
+
|
|
+struct snd_pmic_ops snd_pmic_ops_mx = {
|
|
+ .set_input_dev = mx_set_selected_input_dev,
|
|
+ .set_output_dev = mx_set_selected_output_dev,
|
|
+ .set_mute = mx_set_mute,
|
|
+ .get_mute = mx_get_mute,
|
|
+ .set_vol = mx_set_vol,
|
|
+ .get_vol = mx_get_vol,
|
|
+ .init_card = mx_init_card,
|
|
+ .set_pcm_audio_params = mx_set_pcm_audio_params,
|
|
+ .set_pcm_voice_params = mx_set_pcm_voice_params,
|
|
+ .set_voice_port = mx_set_voice_port,
|
|
+ .set_audio_port = mx_set_audio_port,
|
|
+ .power_up_pmic_pb = mx_power_up_pb,
|
|
+ .power_up_pmic_cp = mx_power_up_cp,
|
|
+ .power_down_pmic_pb = mx_power_down_pb,
|
|
+ .power_down_pmic_cp = mx_power_down_cp,
|
|
+ .power_down_pmic = mx_power_down,
|
|
+};
|
|
+
|
|
diff --git a/sound/pci/sst/intelmid_v2_control.c b/sound/pci/sst/intelmid_v2_control.c
|
|
new file mode 100644
|
|
index 0000000..d42b564
|
|
--- /dev/null
|
|
+++ b/sound/pci/sst/intelmid_v2_control.c
|
|
@@ -0,0 +1,1031 @@
|
|
+/*
|
|
+ * 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/cdev.h>
|
|
+#include <linux/pci.h>
|
|
+#include <linux/kernel.h>
|
|
+#include <linux/delay.h>
|
|
+#include <linux/init.h>
|
|
+#include <linux/module.h>
|
|
+#include <linux/syscalls.h>
|
|
+#include <linux/file.h>
|
|
+#include <linux/fcntl.h>
|
|
+#include <linux/uaccess.h>
|
|
+#include <linux/interrupt.h>
|
|
+#include <linux/list.h>
|
|
+#include <linux/slab.h>
|
|
+#include <linux/mm.h>
|
|
+#include <linux/workqueue.h>
|
|
+#include <linux/pci.h>
|
|
+#include <linux/firmware.h>
|
|
+#include <sound/intel_lpe.h>
|
|
+#include <sound/intel_sst_ioctl.h>
|
|
+#include "intel_sst_fw_ipc.h"
|
|
+#include "intel_sst_common.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,
|
|
+};
|
|
+
|
|
+
|
|
+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, 0x0e, 0},
|
|
+ {AUDIORVOL, 0x0e, 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, 0x11, 0x00},
|
|
+ {ADCSAMPLERATE, 0x8B, 0x00},
|
|
+ {MICSELVOL, 0x5B, 0x00},
|
|
+ {LILSEL, 0x46, 0},
|
|
+ {LIRSEL, 0x06, 0},
|
|
+ {LOANTIPOP, 0x00, 0},
|
|
+ };
|
|
+ snd_pmic_ops_nc.card_status = SND_CARD_INIT_DONE;
|
|
+ sst_sc_reg_access(sc_access, PMIC_WRITE, 25);
|
|
+ snd_pmic_ops_nc.mute_status = 1;
|
|
+ printk(KERN_DEBUG "SST DBG:init complete!!\n");
|
|
+ return 0;
|
|
+}
|
|
+
|
|
+int nc_enable_audiodac(int value)
|
|
+{
|
|
+ struct sc_reg_access sc_access[3];
|
|
+ int mute_val = 0;
|
|
+
|
|
+ printk(KERN_DEBUG "SST DBG:+\
|
|
+ PMIC_SND_INPUT_MUTE_: value::%d\n", snd_pmic_ops_nc.mute_status );
|
|
+ if (snd_pmic_ops_nc.mute_status == MUTE)
|
|
+ return 0;
|
|
+
|
|
+ if ((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);
|
|
+
|
|
+}
|
|
+
|
|
+
|
|
+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);
|
|
+ mdelay(30);
|
|
+
|
|
+ printk(KERN_DEBUG "SST DBG: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);
|
|
+
|
|
+ mdelay(30);
|
|
+
|
|
+ return nc_enable_audiodac(UNMUTE);
|
|
+
|
|
+}
|
|
+
|
|
+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;
|
|
+
|
|
+
|
|
+ printk(KERN_DEBUG "SST DBG: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);
|
|
+
|
|
+}
|
|
+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);
|
|
+
|
|
+
|
|
+ printk(KERN_DEBUG "SST DBG:powering dn nc_power_down ....\n");
|
|
+
|
|
+
|
|
+
|
|
+ mdelay(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);
|
|
+
|
|
+ mdelay(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);
|
|
+
|
|
+ mdelay(30);
|
|
+ return nc_enable_audiodac(UNMUTE);
|
|
+}
|
|
+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;
|
|
+
|
|
+ printk(KERN_DEBUG "SST DBG:powering dn pb....\n");
|
|
+
|
|
+ nc_enable_audiodac(MUTE);
|
|
+
|
|
+
|
|
+ mdelay(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);
|
|
+
|
|
+ mdelay(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);
|
|
+
|
|
+ mdelay(30);
|
|
+
|
|
+ return nc_enable_audiodac(UNMUTE);
|
|
+
|
|
+
|
|
+}
|
|
+
|
|
+int nc_power_down_cp(void)
|
|
+{
|
|
+ struct sc_reg_access sc_access[] = {
|
|
+ {POWERCTRL1, 0x00, 0xBF},
|
|
+ {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;
|
|
+
|
|
+ printk(KERN_DEBUG "SST DBG:powering dn cp....\n");
|
|
+ return sst_sc_reg_access(sc_access, PMIC_READ_MODIFY, 1);
|
|
+}
|
|
+
|
|
+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);
|
|
+ printk(KERN_DEBUG "SST DBG:Voice parameters set successfully!!\n");
|
|
+ return 0;
|
|
+}
|
|
+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},
|
|
+ {0x10E, 0x03, 0},
|
|
+ {0x10F, 0x03, 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, 14);
|
|
+ printk(KERN_DEBUG "SST DBG:Audio Init successfully!!\n");
|
|
+ if(snd_pmic_ops_nc.num_channel == 1) {
|
|
+ sc_acces.value = 0x07;
|
|
+ sc_acces.reg_addr = RMUTE;
|
|
+ printk(KERN_DEBUG "SST DBG:PMIC_SND_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;
|
|
+ printk(KERN_DEBUG "SST DBG:PMIC_SND_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;
|
|
+}
|
|
+
|
|
+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;
|
|
+ printk(KERN_DEBUG "SST DBG:PMIC_SND_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;
|
|
+ printk(KERN_DEBUG "SST DBG:PMIC_SND_RIGHT_HP_MUTE:: value::%d\n",
|
|
+ sc_access.value);
|
|
+ sc_access.mask = MASK2;
|
|
+ sst_sc_reg_access(&sc_access, PMIC_READ_MODIFY, 1);
|
|
+
|
|
+
|
|
+ }
|
|
+
|
|
+ printk(KERN_DEBUG "SST DBG: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);
|
|
+
|
|
+ printk(KERN_DEBUG "SST DBG: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);
|
|
+
|
|
+
|
|
+
|
|
+}
|
|
+
|
|
+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;
|
|
+
|
|
+}
|
|
+
|
|
+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;
|
|
+}
|
|
+int nc_set_selected_output_dev(u8 value)
|
|
+{
|
|
+ struct sc_reg_access sc_acces, 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;
|
|
+ printk(KERN_DEBUG "SST DBG:nc set selected output:%d \n", value);
|
|
+ switch (value) {
|
|
+ case STEREO_HEADPHONE:
|
|
+ retval = sst_sc_reg_access(sc_access_HP, PMIC_WRITE, 2);
|
|
+ if(snd_pmic_ops_nc.num_channel == 1) {
|
|
+ sc_acces.value = 0x07;
|
|
+ sc_acces.reg_addr = RMUTE;
|
|
+ printk(KERN_DEBUG "SST DBG:PMIC_SND_RIGHT_HP_MUTE:: value::%d\n",
|
|
+ sc_acces.value);
|
|
+ sc_acces.mask = MASK2;
|
|
+ retval = sst_sc_reg_access(&sc_acces, PMIC_READ_MODIFY, 1);
|
|
+ }
|
|
+ break;
|
|
+ case INTERNAL_SPKR:
|
|
+ return sst_sc_reg_access(sc_access_IS, PMIC_WRITE, 2);
|
|
+ default:
|
|
+ printk(KERN_ERR "SST ERR: +\
|
|
+ rcvd illegal request: %d \n", value);
|
|
+ return -EINVAL;
|
|
+ }
|
|
+ return retval;
|
|
+}
|
|
+
|
|
+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;
|
|
+
|
|
+ printk(KERN_DEBUG "SST DBG:set device id::%d, +\
|
|
+ value %d\n", dev_id, value);
|
|
+
|
|
+ switch (dev_id) {
|
|
+ case PMIC_SND_MUTE_ALL:
|
|
+ printk(KERN_DEBUG "SST DBG:+\
|
|
+ PMIC_SND_MUTE_ALL: value::%d \n", value);
|
|
+ snd_pmic_ops_nc.mute_status = 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;
|
|
+ return sst_sc_reg_access(sc_access,
|
|
+ PMIC_READ_MODIFY, 3);
|
|
+ }
|
|
+ break;
|
|
+ case PMIC_SND_HP_MIC_MUTE:
|
|
+ printk(KERN_DEBUG "SST DBG:+\
|
|
+ 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;
|
|
+ break;
|
|
+ case PMIC_SND_AMIC_MUTE:
|
|
+ printk(KERN_DEBUG "SST DBG:+\
|
|
+ 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;
|
|
+ break;
|
|
+
|
|
+ case PMIC_SND_DMIC_MUTE:
|
|
+ printk(KERN_DEBUG "SST DBG:+\
|
|
+ PMIC_SND_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;
|
|
+ return 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;
|
|
+ printk(KERN_DEBUG "SST DBG:PMIC_SND_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;
|
|
+ printk(KERN_DEBUG "SST DBG:PMIC_SND_RIGHT_HP_MUTE:: value::%d\n",
|
|
+ sc_access[0].value);
|
|
+ }
|
|
+ sc_access[0].mask = MASK2;
|
|
+ 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;
|
|
+ printk(KERN_DEBUG "SST DBG:+\
|
|
+ PMIC_SND_SPEAKER_MUTE %d\n", sc_access[0].value);
|
|
+ sc_access[0].mask = MASK1;
|
|
+ break;
|
|
+ default:
|
|
+ printk(KERN_ERR "SST ERR: +\
|
|
+ Invalid Device_id \n");
|
|
+ return -EINVAL;
|
|
+ }
|
|
+ return sst_sc_reg_access(sc_access, PMIC_READ_MODIFY, 1);
|
|
+
|
|
+}
|
|
+
|
|
+int nc_set_vol(int dev_id, u8 value)
|
|
+{
|
|
+ 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;
|
|
+
|
|
+ printk(KERN_DEBUG "SST DBG:set volume:%d\n", dev_id);
|
|
+ switch (dev_id) {
|
|
+ case PMIC_SND_CAPTURE_VOL:
|
|
+ printk(KERN_DEBUG "SST DBG:PMIC_SND_CAPTURE_VOL:: +\
|
|
+ value::%d \n", value);
|
|
+ sc_access.value = -value;
|
|
+ sc_access.reg_addr = LILSEL;
|
|
+ sc_access.mask = MASK0|MASK1|MASK2|MASK3|MASK4|MASK5;
|
|
+ break;
|
|
+
|
|
+ case PMIC_SND_LEFT_PB_VOL:
|
|
+ printk(KERN_DEBUG "SST DBG:+\
|
|
+ PMIC_SND_LEFT_HP_VOL:%d \n", value);
|
|
+ sc_access.value = -value;
|
|
+ sc_access.reg_addr = AUDIOLVOL;
|
|
+ sc_access.mask = (MASK0|MASK1|MASK2|MASK3|MASK4|MASK5|MASK6);
|
|
+ break;
|
|
+
|
|
+ case PMIC_SND_RIGHT_PB_VOL:
|
|
+ printk(KERN_DEBUG "SST DBG:PMIC_SND_RIGHT_HP_VOL: +\
|
|
+ value::%d\n", value);
|
|
+ if(snd_pmic_ops_nc.num_channel == 1) {
|
|
+ sc_access.value = 0x04;
|
|
+ sc_access.reg_addr = RMUTE;
|
|
+ sc_access.mask = MASK2;
|
|
+ } else {
|
|
+ sc_access.value = -value;
|
|
+ sc_access.reg_addr = AUDIORVOL;
|
|
+ sc_access.mask = (MASK0|MASK1|MASK2|MASK3|MASK4|MASK5|MASK6);
|
|
+ }
|
|
+ break;
|
|
+
|
|
+ default:
|
|
+ printk(KERN_ERR "SST ERR: +\
|
|
+ Invalid Device_id \n");
|
|
+ return -EINVAL;
|
|
+
|
|
+ }
|
|
+ /* sst_sc_read_modify(®_adrs, &difference, 1);*/
|
|
+ return sst_sc_reg_access(&sc_access, PMIC_READ_MODIFY, 1);
|
|
+}
|
|
+
|
|
+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;
|
|
+
|
|
+ printk(KERN_DEBUG "SST DBG:nc set selected input:%d \n", value);
|
|
+
|
|
+ switch (value) {
|
|
+ case AMIC:
|
|
+ printk(KERN_DEBUG "SST DBG: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;
|
|
+ num_val = 3;
|
|
+ break;
|
|
+
|
|
+ case HS_MIC:
|
|
+ printk(KERN_DEBUG "SST DBG:+\
|
|
+ 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;
|
|
+ num_val = 3;
|
|
+ break;
|
|
+
|
|
+ case DMIC:
|
|
+ printk(KERN_DEBUG "SST DBG: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;
|
|
+ num_val = 3;
|
|
+ break;
|
|
+ default:
|
|
+ printk(KERN_ERR "SST ERR:+\
|
|
+ rcvd illegal request: %d \n", value);
|
|
+ return -EINVAL;
|
|
+ }
|
|
+ return sst_sc_reg_access(sc_access, PMIC_READ_MODIFY, num_val);
|
|
+}
|
|
+
|
|
+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;
|
|
+
|
|
+ printk(KERN_DEBUG "SST DBG:get mute::%d\n", dev_id);
|
|
+
|
|
+ switch (dev_id) {
|
|
+ case PMIC_SND_MUTE_ALL:
|
|
+ printk(KERN_DEBUG "SST DBG:PMIC_SND_INPUT_MASTER_MUTE: +\
|
|
+ value::%d\n", *value);
|
|
+ sc_access.reg_addr = AUDIOLVOL;
|
|
+ sc_access.mask = MASK7;
|
|
+ break;
|
|
+ case PMIC_SND_AMIC_MUTE:
|
|
+ printk(KERN_DEBUG "SST DBG:PMIC_SND_INPUT_MUTE_MIC1\n");
|
|
+ sc_access.reg_addr = LILSEL;
|
|
+ mask = MASK6;
|
|
+ break;
|
|
+ case PMIC_SND_HP_MIC_MUTE:
|
|
+ printk(KERN_DEBUG "SST DBG: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;
|
|
+ printk(KERN_DEBUG "SST DBG: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:
|
|
+ printk(KERN_DEBUG "SST DBG:PMIC_MONO_EARPIECE_MUTE\n");
|
|
+ sc_access.reg_addr = RMUTE;
|
|
+ mask = MASK1;
|
|
+ break;
|
|
+ case PMIC_SND_DMIC_MUTE:
|
|
+ printk(KERN_DEBUG "SST DBG:PMIC_SND_INPUT_MUTE_DMIC\n");
|
|
+ sc_access.reg_addr = 0x105;
|
|
+ mask = MASK6;
|
|
+ break;
|
|
+ default:
|
|
+ printk(KERN_ERR "SST ERR: +\
|
|
+ Invalid Device_id \n");
|
|
+ return -EINVAL;
|
|
+
|
|
+ }
|
|
+ retval = sst_sc_reg_access(&sc_access, PMIC_READ, 1);
|
|
+ printk(KERN_DEBUG "SST DBG:reg value = %d\n", sc_access.value);
|
|
+ if (retval)
|
|
+ return retval;
|
|
+ *value = (sc_access.value) & mask;
|
|
+ printk(KERN_DEBUG "SST DBG:masked value = %d\n", *value);
|
|
+ if (*value)
|
|
+ *value = 0;
|
|
+ else
|
|
+ *value = 1;
|
|
+ printk(KERN_DEBUG "SST DBG:value returned = 0x%x\n", *value);
|
|
+ return retval;
|
|
+}
|
|
+
|
|
+int nc_get_vol(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;
|
|
+
|
|
+ switch (dev_id) {
|
|
+ case PMIC_SND_CAPTURE_VOL:
|
|
+ printk(KERN_DEBUG "SST DBG: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:
|
|
+ printk(KERN_DEBUG "SST DBG: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:
|
|
+ printk(KERN_DEBUG "SST DBG:GET_VOLUME_PMIC_RIGHT_HP_VOL\n");
|
|
+ sc_access.reg_addr = AUDIORVOL;
|
|
+ mask = (MASK0|MASK1|MASK2|MASK3|MASK4|MASK5|MASK6);
|
|
+ break;
|
|
+
|
|
+ default:
|
|
+ printk(KERN_ERR "SST ERR: +\
|
|
+ Invalid Device_id = %d \n", dev_id);
|
|
+ return -EINVAL;
|
|
+
|
|
+ }
|
|
+ retval = sst_sc_reg_access(&sc_access, PMIC_READ, 1);
|
|
+ printk(KERN_DEBUG "SST DBG:value read = 0x%x\n", sc_access.value);
|
|
+ *value = (sc_access.value) & mask;
|
|
+ *value = -*value;
|
|
+ printk(KERN_DEBUG "SST DBG:value returned = 0x%x\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,
|
|
+};
|
|
--
|
|
1.6.2.2
|
|
|