diff options
Diffstat (limited to 'arch/arm/mach-msm/pmic.c')
-rw-r--r-- | arch/arm/mach-msm/pmic.c | 1095 |
1 files changed, 1095 insertions, 0 deletions
diff --git a/arch/arm/mach-msm/pmic.c b/arch/arm/mach-msm/pmic.c new file mode 100644 index 000000000000..3c481a6bc180 --- /dev/null +++ b/arch/arm/mach-msm/pmic.c @@ -0,0 +1,1095 @@ +/* Copyright (c) 2009, Code Aurora Forum. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * * Neither the name of Code Aurora Forum nor + * the names of its contributors may be used to endorse or promote + * products derived from this software without specific prior written + * permission. + * + * Alternatively, provided that this notice is retained in full, this software + * may be relicensed by the recipient under the terms of the GNU General Public + * License version 2 ("GPL") and only version 2, in which case the provisions of + * the GPL apply INSTEAD OF those given above. If the recipient relicenses the + * software under the GPL, then the identification text in the MODULE_LICENSE + * macro must be changed to reflect "GPLv2" instead of "Dual BSD/GPL". Once a + * recipient changes the license terms to the GPL, subsequent recipients shall + * not relicense under alternate licensing terms, including the BSD or dual + * BSD/GPL terms. In addition, the following license statement immediately + * below and between the words START and END shall also then apply when this + * software is relicensed under the GPL: + * + * START + * + * This program is free software; you can redistribute it and/or modify it under + * the terms of the GNU General Public License version 2 and only version 2 as + * published by the Free Software Foundation. + * + * 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., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + * END + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + */ +#include <linux/module.h> +#include <linux/init.h> +#include <linux/debugfs.h> +#include <linux/err.h> +#include <linux/uaccess.h> +#include <linux/mutex.h> + +#include <mach/pmic.h> + +#include "smd_rpcrouter.h" + +#define TRACE_PMIC 0 + +#if TRACE_PMIC +#define PMIC(x...) printk(KERN_INFO "[PMIC] " x) +#else +#define PMIC(x...) do {} while (0) +#endif + + +#define LIB_NULL_PROC 0 +#define LIB_RPC_GLUE_CODE_INFO_REMOTE_PROC 1 +#define LP_MODE_CONTROL_PROC 2 +#define VREG_SET_LEVEL_PROC 3 +#define VREG_PULL_DOWN_SWITCH_PROC 4 +#define SECURE_MPP_CONFIG_DIGITAL_OUTPUT_PROC 5 +#define SECURE_MPP_CONFIG_I_SINK_PROC 6 +#define RTC_START_PROC 7 +#define RTC_STOP_PROC 8 +#define RTC_GET_TIME_PROC 9 +#define RTC_ENABLE_ALARM_PROC 10 +#define RTC_DISABLE_ALARM_PROC 11 +#define RTC_GET_ALARM_TIME_PROC 12 +#define RTC_GET_ALARM_STATUS_PROC 13 +#define RTC_SET_TIME_ADJUST_PROC 14 +#define RTC_GET_TIME_ADJUST_PROC 15 +#define SET_LED_INTENSITY_PROC 16 +#define FLASH_LED_SET_CURRENT_PROC 17 +#define FLASH_LED_SET_MODE_PROC 18 +#define FLASH_LED_SET_POLARITY_PROC 19 +#define SPEAKER_CMD_PROC 20 +#define SET_SPEAKER_GAIN_PROC 21 +#define VIB_MOT_SET_VOLT_PROC 22 +#define VIB_MOT_SET_MODE_PROC 23 +#define VIB_MOT_SET_POLARITY_PROC 24 +#define VID_EN_PROC 25 +#define VID_IS_EN_PROC 26 +#define VID_LOAD_DETECT_EN_PROC 27 +#define MIC_EN_PROC 28 +#define MIC_IS_EN_PROC 29 +#define MIC_SET_VOLT_PROC 30 +#define MIC_GET_VOLT_PROC 31 +#define SPKR_EN_RIGHT_CHAN_PROC 32 +#define SPKR_IS_RIGHT_CHAN_EN_PROC 33 +#define SPKR_EN_LEFT_CHAN_PROC 34 +#define SPKR_IS_LEFT_CHAN_EN_PROC 35 +#define SET_SPKR_CONFIGURATION_PROC 36 +#define GET_SPKR_CONFIGURATION_PROC 37 +#define SPKR_GET_GAIN_PROC 38 +#define SPKR_IS_EN_PROC 39 +#define SPKR_EN_MUTE_PROC 40 +#define SPKR_IS_MUTE_EN_PROC 41 +#define SPKR_SET_DELAY_PROC 42 +#define SPKR_GET_DELAY_PROC 43 +#define SECURE_MPP_CONFIG_DIGITAL_INPUT_PROC 44 +#define SET_SPEAKER_DELAY_PROC 45 +#define SPEAKER_1K6_ZIN_ENABLE_PROC 46 +#define SPKR_SET_MUX_HPF_CORNER_FREQ_PROC 47 +#define SPKR_GET_MUX_HPF_CORNER_FREQ_PROC 48 +#define SPKR_IS_RIGHT_LEFT_CHAN_ADDED_PROC 49 +#define SPKR_EN_STEREO_PROC 50 +#define SPKR_IS_STEREO_EN_PROC 51 +#define SPKR_SELECT_USB_WITH_HPF_20HZ_PROC 52 +#define SPKR_IS_USB_WITH_HPF_20HZ_PROC 53 +#define SPKR_BYPASS_MUX_PROC 54 +#define SPKR_IS_MUX_BYPASSED_PROC 55 +#define SPKR_EN_HPF_PROC 56 +#define SPKR_IS_HPF_EN_PROC 57 +#define SPKR_EN_SINK_CURR_FROM_REF_VOLT_CIR_PROC 58 +#define SPKR_IS_SINK_CURR_FROM_REF_VOLT_CIR_EN_PROC 59 +#define SPKR_ADD_RIGHT_LEFT_CHAN_PROC 60 +#define SPKR_SET_GAIN_PROC 61 +#define SPKR_EN_PROC 62 +#define HSED_SET_PERIOD_PROC 63 +#define HSED_SET_HYSTERESIS_PROC 64 +#define HSED_SET_CURRENT_THRESHOLD_PROC 65 +#define HSED_ENABLE_PROC 66 + + +/* rpc related */ +#define PMIC_RPC_TIMEOUT (5*HZ) + +#define PMIC_PDEV_NAME "rs00010001:00000000" +#define PMIC_RPC_PROG 0x30000061 +#define PMIC_RPC_VER_1_1 0x00010001 +#define PMIC_RPC_VER_2_1 0x00020001 + +/* error bit flags defined by modem side */ +#define PM_ERR_FLAG__PAR1_OUT_OF_RANGE (0x0001) +#define PM_ERR_FLAG__PAR2_OUT_OF_RANGE (0x0002) +#define PM_ERR_FLAG__PAR3_OUT_OF_RANGE (0x0004) +#define PM_ERR_FLAG__PAR4_OUT_OF_RANGE (0x0008) +#define PM_ERR_FLAG__PAR5_OUT_OF_RANGE (0x0010) + +#define PM_ERR_FLAG__ALL_PARMS_OUT_OF_RANGE (0x001F) /* all 5 previous */ + +#define PM_ERR_FLAG__SBI_OPT_ERR (0x0080) +#define PM_ERR_FLAG__FEATURE_NOT_SUPPORTED (0x0100) + +#define PMIC_BUFF_SIZE 256 + +struct pmic_buf { + char *start; /* buffer start addr */ + char *end; /* buffer end addr */ + int size; /* buffer size */ + char *data; /* payload begin addr */ + int len; /* payload len */ +}; + +static DEFINE_MUTEX(pmic_mtx); + +struct pmic_ctrl { + int inited; + struct pmic_buf tbuf; + struct pmic_buf rbuf; + struct msm_rpc_endpoint *endpoint; +}; + +static struct pmic_ctrl pmic_ctrl = { + .inited = -1, +}; + +static int pmic_rpc_req_reply(struct pmic_buf *tbuf, + struct pmic_buf *rbuf, int proc); +static int pmic_rpc_set_only(uint data0, uint data1, uint data2, + uint data3, int num, int proc); +static int pmic_rpc_set_struct(int, uint, uint *data, uint size, int proc); +static int pmic_rpc_set_get(uint setdata, uint *getdata, int size, int proc); +static int pmic_rpc_get_only(uint *getdata, int size, int proc); + +static int pmic_buf_init(void) +{ + struct pmic_ctrl *pm = &pmic_ctrl; + + memset(&pmic_ctrl, 0, sizeof(pmic_ctrl)); + + pm->tbuf.start = kmalloc(PMIC_BUFF_SIZE, GFP_KERNEL); + if (pm->tbuf.start == NULL) { + printk(KERN_ERR "%s:%u\n", __func__, __LINE__); + return -ENOMEM; + } + + pm->tbuf.data = pm->tbuf.start; + pm->tbuf.size = PMIC_BUFF_SIZE; + pm->tbuf.end = pm->tbuf.start + PMIC_BUFF_SIZE; + pm->tbuf.len = 0; + + pm->rbuf.start = kmalloc(PMIC_BUFF_SIZE, GFP_KERNEL); + if (pm->rbuf.start == NULL) { + kfree(pm->tbuf.start); + printk(KERN_ERR "%s:%u\n", __func__, __LINE__); + return -ENOMEM; + } + pm->rbuf.data = pm->rbuf.start; + pm->rbuf.size = PMIC_BUFF_SIZE; + pm->rbuf.end = pm->rbuf.start + PMIC_BUFF_SIZE; + pm->rbuf.len = 0; + + pm->inited = 1; + + return 0; +} + +static inline void pmic_buf_reserve(struct pmic_buf *bp, int len) +{ + bp->data += len; +} + +static inline void pmic_buf_reset(struct pmic_buf *bp) +{ + bp->data = bp->start; + bp->len = 0; +} + +static int modem_to_linux_err(uint err) +{ + if (err == 0) + return 0; + + if (err & PM_ERR_FLAG__ALL_PARMS_OUT_OF_RANGE) + return -EINVAL; /* PM_ERR_FLAG__PAR[1..5]_OUT_OF_RANGE */ + + if (err & PM_ERR_FLAG__SBI_OPT_ERR) + return -EIO; + + if (err & PM_ERR_FLAG__FEATURE_NOT_SUPPORTED) + return -ENOSYS; + + return -EPERM; +} + +static int pmic_put_tx_data(struct pmic_buf *tp, uint datav) +{ + uint *lp; + + if ((tp->size - tp->len) < sizeof(datav)) { + printk(KERN_ERR "%s: OVERFLOW size=%d len=%d\n", + __func__, tp->size, tp->len); + return -1; + } + + lp = (uint *)tp->data; + *lp = cpu_to_be32(datav); + tp->data += sizeof(datav); + tp->len += sizeof(datav); + + return sizeof(datav); +} + +static int pmic_pull_rx_data(struct pmic_buf *rp, uint *datap) +{ + uint *lp; + + if (rp->len < sizeof(*datap)) { + printk(KERN_ERR "%s: UNDERRUN len=%d\n", __func__, rp->len); + return -1; + } + lp = (uint *)rp->data; + *datap = be32_to_cpu(*lp); + rp->data += sizeof(*datap); + rp->len -= sizeof(*datap); + + return sizeof(*datap); +} + + +/* + * + * +-------------------+ + * | PROC cmd layer | + * +-------------------+ + * | RPC layer | + * +-------------------+ + * + * 1) network byte order + * 2) RPC request header(40 bytes) and RPC reply header (24 bytes) + * 3) each transaction consists of a request and reply + * 3) PROC (comamnd) layer has its own sub-protocol defined + * 4) sub-protocol can be grouped to follwoing 7 cases: + * a) set one argument, no get + * b) set two argument, no get + * c) set three argument, no get + * d) set a struct, no get + * e) set a argument followed by a struct, no get + * f) set a argument, get a argument + * g) no set, get either a argument or a struct + */ + +/** + * pmic_rpc_req_reply() - send request and wait for reply + * @tbuf: buffer contains arguments + * @rbuf: buffer to be filled with arguments at reply + * @proc: command/request id + * + * This function send request to modem and wait until reply received + */ +static int pmic_rpc_req_reply(struct pmic_buf *tbuf, struct pmic_buf *rbuf, + int proc) +{ + struct pmic_ctrl *pm = &pmic_ctrl; + int ans, len; + + + if ((pm->endpoint == NULL) || IS_ERR(pm->endpoint)) { + pm->endpoint = msm_rpc_connect_compatible(PMIC_RPC_PROG, + PMIC_RPC_VER_2_1, 0); + if (IS_ERR(pm->endpoint)) { + pm->endpoint = msm_rpc_connect_compatible(PMIC_RPC_PROG, + PMIC_RPC_VER_1_1, 0); + } + + if (IS_ERR(pm->endpoint)) { + ans = PTR_ERR(pm->endpoint); + printk(KERN_ERR "%s: init rpc failed! ans = %d\n", + __func__, ans); + return ans; + } + } + + /* + * data is point to next available space at this moment, + * move it back to beginning of request header and increase + * the length + */ + tbuf->data = tbuf->start; + tbuf->len += sizeof(struct rpc_request_hdr); + + len = msm_rpc_call_reply(pm->endpoint, proc, + tbuf->data, tbuf->len, + rbuf->data, rbuf->size, + PMIC_RPC_TIMEOUT); + + if (len <= 0) { + printk(KERN_ERR "%s: rpc failed! len = %d\n", __func__, len); + pm->endpoint = NULL; /* re-connect later ? */ + return len; + } + + rbuf->len = len; + /* strip off rpc_reply_hdr */ + rbuf->data += sizeof(struct rpc_reply_hdr); + rbuf->len -= sizeof(struct rpc_reply_hdr); + + return rbuf->len; +} + +/** + * pmic_rpc_set_only() - set arguments and no get + * @data0: first argumrnt + * @data1: second argument + * @data2: third argument + * @data3: fourth argument + * @num: number of argument + * @proc: command/request id + * + * This function covers case a, b, and c + */ +static int pmic_rpc_set_only(uint data0, uint data1, uint data2, uint data3, + int num, int proc) +{ + struct pmic_ctrl *pm = &pmic_ctrl; + struct pmic_buf *tp; + struct pmic_buf *rp; + int stat; + + + if (mutex_lock_interruptible(&pmic_mtx)) + return -ERESTARTSYS; + + if (pm->inited <= 0) { + stat = pmic_buf_init(); + if (stat < 0) { + mutex_unlock(&pmic_mtx); + return stat; + } + } + + tp = &pm->tbuf; + rp = &pm->rbuf; + + pmic_buf_reset(tp); + pmic_buf_reserve(tp, sizeof(struct rpc_request_hdr)); + pmic_buf_reset(rp); + + if (num > 0) + pmic_put_tx_data(tp, data0); + + if (num > 1) + pmic_put_tx_data(tp, data1); + + if (num > 2) + pmic_put_tx_data(tp, data2); + + if (num > 3) + pmic_put_tx_data(tp, data3); + + stat = pmic_rpc_req_reply(tp, rp, proc); + if (stat < 0) { + mutex_unlock(&pmic_mtx); + return stat; + } + + pmic_pull_rx_data(rp, &stat); /* result from server */ + + mutex_unlock(&pmic_mtx); + + return modem_to_linux_err(stat); +} + +/** + * pmic_rpc_set_struct() - set the whole struct + * @xflag: indicates an extra argument + * @xdata: the extra argument + * @*data: starting address of struct + * @size: size of struct + * @proc: command/request id + * + * This fucntion covers case d and e + */ +static int pmic_rpc_set_struct(int xflag, uint xdata, uint *data, uint size, + int proc) +{ + struct pmic_ctrl *pm = &pmic_ctrl; + struct pmic_buf *tp; + struct pmic_buf *rp; + int i, stat, more_data; + + + if (mutex_lock_interruptible(&pmic_mtx)) + return -ERESTARTSYS; + + if (pm->inited <= 0) { + stat = pmic_buf_init(); + if (stat < 0) { + mutex_unlock(&pmic_mtx); + return stat; + } + } + + tp = &pm->tbuf; + rp = &pm->rbuf; + + pmic_buf_reset(tp); + pmic_buf_reserve(tp, sizeof(struct rpc_request_hdr)); + pmic_buf_reset(rp); + + if (xflag) + pmic_put_tx_data(tp, xdata); + + more_data = 1; /* tell server there have more data followed */ + pmic_put_tx_data(tp, more_data); + + size >>= 2; + for (i = 0; i < size; i++) { + pmic_put_tx_data(tp, *data); + data++; + } + + stat = pmic_rpc_req_reply(tp, rp, proc); + if (stat < 0) { + mutex_unlock(&pmic_mtx); + return stat; + } + + pmic_pull_rx_data(rp, &stat); /* result from server */ + + mutex_unlock(&pmic_mtx); + + return modem_to_linux_err(stat); +} + +/** + * pmic_rpc_set_get() - set one argument and get one argument + * @setdata: set argument + * @*getdata: memory to store argumnet + * @size: size of memory + * @proc: command/request id + * + * This function covers case f + */ +static int pmic_rpc_set_get(uint setdata, uint *getdata, int size, int proc) +{ + struct pmic_ctrl *pm = &pmic_ctrl; + struct pmic_buf *tp; + struct pmic_buf *rp; + unsigned int *lp; + int i, stat, more_data; + + + if (mutex_lock_interruptible(&pmic_mtx)) + return -ERESTARTSYS; + + if (pm->inited <= 0) { + stat = pmic_buf_init(); + if (stat < 0) { + mutex_unlock(&pmic_mtx); + return stat; + } + } + + tp = &pm->tbuf; + rp = &pm->rbuf; + + pmic_buf_reset(tp); + pmic_buf_reserve(tp, sizeof(struct rpc_request_hdr)); + pmic_buf_reset(rp); + + pmic_put_tx_data(tp, setdata); + + /* + * more_data = TRUE to ask server reply with requested datum + * otherwise, server will reply without datum + */ + more_data = (getdata != NULL); + pmic_put_tx_data(tp, more_data); + + stat = pmic_rpc_req_reply(tp, rp, proc); + if (stat < 0) { + mutex_unlock(&pmic_mtx); + return stat; + } + + pmic_pull_rx_data(rp, &stat); /* result from server */ + pmic_pull_rx_data(rp, &more_data); + + if (more_data) { /* more data followed */ + size >>= 2; + lp = getdata; + for (i = 0; i < size; i++) { + if (pmic_pull_rx_data(rp, lp++) < 0) + break; /* not supposed to happen */ + } + } + + mutex_unlock(&pmic_mtx); + + return modem_to_linux_err(stat); +} + +/** + * pmic_rpc_get_only() - get one or more than one arguments + * @*getdata: memory to store arguments + * @size: size of mmory + * @proc: command/request id + * + * This function covers case g + */ +static int pmic_rpc_get_only(uint *getdata, int size, int proc) +{ + struct pmic_ctrl *pm = &pmic_ctrl; + struct pmic_buf *tp; + struct pmic_buf *rp; + unsigned int *lp; + int i, stat, more_data; + + + if (mutex_lock_interruptible(&pmic_mtx)) + return -ERESTARTSYS; + + if (pm->inited <= 0) { + stat = pmic_buf_init(); + if (stat < 0) { + mutex_unlock(&pmic_mtx); + return stat; + } + } + + tp = &pm->tbuf; + rp = &pm->rbuf; + + pmic_buf_reset(tp); + pmic_buf_reserve(tp, sizeof(struct rpc_request_hdr)); + pmic_buf_reset(rp); + + /* + * more_data = TRUE to ask server reply with requested datum + * otherwise, server will reply without datum + */ + more_data = (getdata != NULL); + pmic_put_tx_data(tp, more_data); + + stat = pmic_rpc_req_reply(tp, rp, proc); + if (stat < 0) { + mutex_unlock(&pmic_mtx); + return stat; + } + + pmic_pull_rx_data(rp, &stat); /* result from server */ + pmic_pull_rx_data(rp, &more_data); + + if (more_data) { /* more data followed */ + size >>= 2; + lp = getdata; + for (i = 0; i < size; i++) { + if (pmic_pull_rx_data(rp, lp++) < 0) + break; /* not supposed to happen */ + } + } + + mutex_unlock(&pmic_mtx); + + return modem_to_linux_err(stat); +} + + +int pmic_lp_mode_control(enum switch_cmd cmd, enum vreg_lp_id id) +{ + return pmic_rpc_set_only(cmd, id, 0, 0, 2, LP_MODE_CONTROL_PROC); +} +EXPORT_SYMBOL(pmic_lp_mode_control); + +int pmic_vreg_set_level(enum vreg_id vreg, int level) +{ + return pmic_rpc_set_only(vreg, level, 0, 0, 2, VREG_SET_LEVEL_PROC); +} +EXPORT_SYMBOL(pmic_vreg_set_level); + +int pmic_vreg_pull_down_switch(enum switch_cmd cmd, enum vreg_pdown_id id) +{ + return pmic_rpc_set_only(cmd, id, 0, 0, 2, VREG_PULL_DOWN_SWITCH_PROC); +} +EXPORT_SYMBOL(pmic_vreg_pull_down_switch); + +int pmic_secure_mpp_control_digital_output(enum mpp_which which, + enum mpp_dlogic_level level, + enum mpp_dlogic_out_ctrl out) +{ + return pmic_rpc_set_only(which, level, out, 0, 3, + SECURE_MPP_CONFIG_DIGITAL_OUTPUT_PROC); +} +EXPORT_SYMBOL(pmic_secure_mpp_control_digital_output); + +int pmic_secure_mpp_config_i_sink(enum mpp_which which, + enum mpp_i_sink_level level, + enum mpp_i_sink_switch onoff) +{ + return pmic_rpc_set_only(which, level, onoff, 0, 3, + SECURE_MPP_CONFIG_I_SINK_PROC); +} +EXPORT_SYMBOL(pmic_secure_mpp_config_i_sink); + +int pmic_secure_mpp_config_digital_input(enum mpp_which which, + enum mpp_dlogic_level level, + enum mpp_dlogic_in_dbus dbus) +{ + return pmic_rpc_set_only(which, level, dbus, 0, 3, + SECURE_MPP_CONFIG_DIGITAL_INPUT_PROC); +} +EXPORT_SYMBOL(pmic_secure_mpp_config_digital_input); + +int pmic_rtc_start(struct rtc_time *time) +{ + return pmic_rpc_set_struct(0, 0, (uint *)time, sizeof(*time), + RTC_START_PROC); +} +EXPORT_SYMBOL(pmic_rtc_start); + +int pmic_rtc_stop(void) +{ + return pmic_rpc_set_only(0, 0, 0, 0, 0, RTC_STOP_PROC); +} +EXPORT_SYMBOL(pmic_rtc_stop); + +int pmic_rtc_get_time(struct rtc_time *time) +{ + return pmic_rpc_get_only((uint *)time, sizeof(*time), + RTC_GET_TIME_PROC); +} +EXPORT_SYMBOL(pmic_rtc_get_time); + +int pmic_rtc_enable_alarm(enum rtc_alarm alarm, + struct rtc_time *time) +{ + return pmic_rpc_set_struct(1, alarm, (uint *)time, sizeof(*time), + RTC_ENABLE_ALARM_PROC); +} +EXPORT_SYMBOL(pmic_rtc_enable_alarm); + +int pmic_rtc_disable_alarm(enum rtc_alarm alarm) +{ + return pmic_rpc_set_only(alarm, 0, 0, 0, 1, RTC_DISABLE_ALARM_PROC); +} +EXPORT_SYMBOL(pmic_rtc_disable_alarm); + +int pmic_rtc_get_alarm_time(enum rtc_alarm alarm, + struct rtc_time *time) +{ + return pmic_rpc_set_get(alarm, (uint *)time, sizeof(*time), + RTC_GET_ALARM_TIME_PROC); +} +EXPORT_SYMBOL(pmic_rtc_get_alarm_time); + +int pmic_rtc_get_alarm_status(uint *status) +{ + return pmic_rpc_get_only(status, sizeof(*status), + RTC_GET_ALARM_STATUS_PROC); +} +EXPORT_SYMBOL(pmic_rtc_get_alarm_status); + +int pmic_rtc_set_time_adjust(uint adjust) +{ + return pmic_rpc_set_only(adjust, 0, 0, 0, 1, + RTC_SET_TIME_ADJUST_PROC); +} +EXPORT_SYMBOL(pmic_rtc_set_time_adjust); + +int pmic_rtc_get_time_adjust(uint *adjust) +{ + return pmic_rpc_get_only(adjust, sizeof(*adjust), + RTC_GET_TIME_ADJUST_PROC); +} +EXPORT_SYMBOL(pmic_rtc_get_time_adjust); + +/* + * generic speaker + */ +int pmic_speaker_cmd(const enum spkr_cmd cmd) +{ + return pmic_rpc_set_only(cmd, 0, 0, 0, 1, SPEAKER_CMD_PROC); +} +EXPORT_SYMBOL(pmic_speaker_cmd); + +int pmic_set_spkr_configuration(struct spkr_config_mode *cfg) +{ + return pmic_rpc_set_struct(0, 0, (uint *)cfg, sizeof(*cfg), + SET_SPKR_CONFIGURATION_PROC); +} +EXPORT_SYMBOL(pmic_set_spkr_configuration); + +int pmic_get_spkr_configuration(struct spkr_config_mode *cfg) +{ + return pmic_rpc_get_only((uint *)cfg, sizeof(*cfg), + GET_SPKR_CONFIGURATION_PROC); +} +EXPORT_SYMBOL(pmic_get_spkr_configuration); + +int pmic_spkr_en_right_chan(uint enable) +{ + return pmic_rpc_set_only(enable, 0, 0, 0, 1, SPKR_EN_RIGHT_CHAN_PROC); +} +EXPORT_SYMBOL(pmic_spkr_en_right_chan); + +int pmic_spkr_is_right_chan_en(uint *enabled) +{ + return pmic_rpc_get_only(enabled, sizeof(*enabled), + SPKR_IS_RIGHT_CHAN_EN_PROC); +} +EXPORT_SYMBOL(pmic_spkr_is_right_chan_en); + +int pmic_spkr_en_left_chan(uint enable) +{ + return pmic_rpc_set_only(enable, 0, 0, 0, 1, SPKR_EN_LEFT_CHAN_PROC); +} +EXPORT_SYMBOL(pmic_spkr_en_left_chan); + +int pmic_spkr_is_left_chan_en(uint *enabled) +{ + return pmic_rpc_get_only(enabled, sizeof(*enabled), + SPKR_IS_LEFT_CHAN_EN_PROC); +} +EXPORT_SYMBOL(pmic_spkr_is_left_chan_en); + +int pmic_set_speaker_gain(enum spkr_gain gain) +{ + return pmic_rpc_set_only(gain, 0, 0, 0, 1, SET_SPEAKER_GAIN_PROC); +} +EXPORT_SYMBOL(pmic_set_speaker_gain); + +int pmic_set_speaker_delay(enum spkr_dly delay) +{ + return pmic_rpc_set_only(delay, 0, 0, 0, 1, SET_SPEAKER_DELAY_PROC); +} +EXPORT_SYMBOL(pmic_set_speaker_delay); + +int pmic_speaker_1k6_zin_enable(uint enable) +{ + return pmic_rpc_set_only(enable, 0, 0, 0, 1, + SPEAKER_1K6_ZIN_ENABLE_PROC); +} +EXPORT_SYMBOL(pmic_speaker_1k6_zin_enable); + +int pmic_spkr_set_mux_hpf_corner_freq(enum spkr_hpf_corner_freq freq) +{ + return pmic_rpc_set_only(freq, 0, 0, 0, 1, + SPKR_SET_MUX_HPF_CORNER_FREQ_PROC); +} +EXPORT_SYMBOL(pmic_spkr_set_mux_hpf_corner_freq); + +int pmic_spkr_get_mux_hpf_corner_freq(enum spkr_hpf_corner_freq *freq) +{ + return pmic_rpc_get_only(freq, sizeof(*freq), + SPKR_GET_MUX_HPF_CORNER_FREQ_PROC); +} +EXPORT_SYMBOL(pmic_spkr_get_mux_hpf_corner_freq); + +int pmic_spkr_select_usb_with_hpf_20hz(uint enable) +{ + return pmic_rpc_set_only(enable, 0, 0, 0, 1, + SPKR_SELECT_USB_WITH_HPF_20HZ_PROC); +} +EXPORT_SYMBOL(pmic_spkr_select_usb_with_hpf_20hz); + +int pmic_spkr_is_usb_with_hpf_20hz(uint *enabled) +{ + return pmic_rpc_get_only(enabled, sizeof(*enabled), + SPKR_IS_USB_WITH_HPF_20HZ_PROC); +} +EXPORT_SYMBOL(pmic_spkr_is_usb_with_hpf_20hz); + +int pmic_spkr_bypass_mux(uint enable) +{ + return pmic_rpc_set_only(enable, 0, 0, 0, 1, SPKR_BYPASS_MUX_PROC); +} +EXPORT_SYMBOL(pmic_spkr_bypass_mux); + +int pmic_spkr_is_mux_bypassed(uint *enabled) +{ + return pmic_rpc_get_only(enabled, sizeof(*enabled), + SPKR_IS_MUX_BYPASSED_PROC); +} +EXPORT_SYMBOL(pmic_spkr_is_mux_bypassed); + +int pmic_spkr_en_hpf(uint enable) +{ + return pmic_rpc_set_only(enable, 0, 0, 0, 1, SPKR_EN_HPF_PROC); +} +EXPORT_SYMBOL(pmic_spkr_en_hpf); + +int pmic_spkr_is_hpf_en(uint *enabled) +{ + return pmic_rpc_get_only(enabled, sizeof(*enabled), + SPKR_IS_HPF_EN_PROC); +} +EXPORT_SYMBOL(pmic_spkr_is_hpf_en); + +int pmic_spkr_en_sink_curr_from_ref_volt_cir(uint enable) +{ + return pmic_rpc_set_only(enable, 0, 0, 0, 1, + SPKR_EN_SINK_CURR_FROM_REF_VOLT_CIR_PROC); +} +EXPORT_SYMBOL(pmic_spkr_en_sink_curr_from_ref_volt_cir); + +int pmic_spkr_is_sink_curr_from_ref_volt_cir_en(uint *enabled) +{ + return pmic_rpc_get_only(enabled, sizeof(*enabled), + SPKR_IS_SINK_CURR_FROM_REF_VOLT_CIR_EN_PROC); +} +EXPORT_SYMBOL(pmic_spkr_is_sink_curr_from_ref_volt_cir_en); + +/* + * speaker indexed by left_right + */ +int pmic_spkr_en(enum spkr_left_right left_right, uint enable) +{ + return pmic_rpc_set_only(left_right, enable, 0, 0, 2, SPKR_EN_PROC); +} +EXPORT_SYMBOL(pmic_spkr_en); + +int pmic_spkr_is_en(enum spkr_left_right left_right, uint *enabled) +{ + return pmic_rpc_set_get(left_right, enabled, sizeof(*enabled), + SPKR_IS_EN_PROC); +} +EXPORT_SYMBOL(pmic_spkr_is_en); + +int pmic_spkr_set_gain(enum spkr_left_right left_right, enum spkr_gain gain) +{ + return pmic_rpc_set_only(left_right, gain, 0, 0, 2, SPKR_SET_GAIN_PROC); +} +EXPORT_SYMBOL(pmic_spkr_set_gain); + +int pmic_spkr_get_gain(enum spkr_left_right left_right, enum spkr_gain *gain) +{ + return pmic_rpc_set_get(left_right, gain, sizeof(*gain), + SPKR_GET_GAIN_PROC); +} +EXPORT_SYMBOL(pmic_spkr_get_gain); + +int pmic_spkr_set_delay(enum spkr_left_right left_right, enum spkr_dly delay) +{ + return pmic_rpc_set_only(left_right, delay, 0, 0, 2, + SPKR_SET_DELAY_PROC); +} +EXPORT_SYMBOL(pmic_spkr_set_delay); + +int pmic_spkr_get_delay(enum spkr_left_right left_right, enum spkr_dly *delay) +{ + return pmic_rpc_set_get(left_right, delay, sizeof(*delay), + SPKR_GET_DELAY_PROC); +} +EXPORT_SYMBOL(pmic_spkr_get_delay); + +int pmic_spkr_en_mute(enum spkr_left_right left_right, uint enabled) +{ + return pmic_rpc_set_only(left_right, enabled, 0, 0, 2, + SPKR_EN_MUTE_PROC); +} +EXPORT_SYMBOL(pmic_spkr_en_mute); + +int pmic_spkr_is_mute_en(enum spkr_left_right left_right, uint *enabled) +{ + return pmic_rpc_set_get(left_right, enabled, sizeof(*enabled), + SPKR_IS_MUTE_EN_PROC); +} +EXPORT_SYMBOL(pmic_spkr_is_mute_en); + +/* + * mic + */ +int pmic_mic_en(uint enable) +{ + return pmic_rpc_set_only(enable, 0, 0, 0, 1, MIC_EN_PROC); +} +EXPORT_SYMBOL(pmic_mic_en); + +int pmic_mic_is_en(uint *enabled) +{ + return pmic_rpc_get_only(enabled, sizeof(*enabled), MIC_IS_EN_PROC); +} +EXPORT_SYMBOL(pmic_mic_is_en); + +int pmic_mic_set_volt(enum mic_volt vol) +{ + return pmic_rpc_set_only(vol, 0, 0, 0, 1, MIC_SET_VOLT_PROC); +} +EXPORT_SYMBOL(pmic_mic_set_volt); + +int pmic_mic_get_volt(enum mic_volt *voltage) +{ + return pmic_rpc_get_only(voltage, sizeof(*voltage), MIC_GET_VOLT_PROC); +} +EXPORT_SYMBOL(pmic_mic_get_volt); + +int pmic_vib_mot_set_volt(uint vol) +{ + return pmic_rpc_set_only(vol, 0, 0, 0, 1, VIB_MOT_SET_VOLT_PROC); +} +EXPORT_SYMBOL(pmic_vib_mot_set_volt); + +int pmic_vib_mot_set_mode(enum pm_vib_mot_mode mode) +{ + return pmic_rpc_set_only(mode, 0, 0, 0, 1, VIB_MOT_SET_MODE_PROC); +} +EXPORT_SYMBOL(pmic_vib_mot_set_mode); + +int pmic_vib_mot_set_polarity(enum pm_vib_mot_pol pol) +{ + return pmic_rpc_set_only(pol, 0, 0, 0, 1, VIB_MOT_SET_POLARITY_PROC); +} +EXPORT_SYMBOL(pmic_vib_mot_set_polarity); + +int pmic_vid_en(uint enable) +{ + return pmic_rpc_set_only(enable, 0, 0, 0, 1, VID_EN_PROC); +} +EXPORT_SYMBOL(pmic_vid_en); + +int pmic_vid_is_en(uint *enabled) +{ + return pmic_rpc_get_only(enabled, sizeof(*enabled), VID_IS_EN_PROC); +} +EXPORT_SYMBOL(pmic_vid_is_en); + +int pmic_vid_load_detect_en(uint enable) +{ + return pmic_rpc_set_only(enable, 0, 0, 0, 1, VID_LOAD_DETECT_EN_PROC); +} +EXPORT_SYMBOL(pmic_vid_load_detect_en); + +int pmic_set_led_intensity(enum ledtype type, int level) +{ + return pmic_rpc_set_only(type, level, 0, 0, 2, SET_LED_INTENSITY_PROC); +} +EXPORT_SYMBOL(pmic_set_led_intensity); + +int pmic_flash_led_set_current(const uint16_t milliamps) +{ + return pmic_rpc_set_only(milliamps, 0, 0, 0, 1, + FLASH_LED_SET_CURRENT_PROC); +} +EXPORT_SYMBOL(pmic_flash_led_set_current); + +int pmic_flash_led_set_mode(enum flash_led_mode mode) +{ + return pmic_rpc_set_only((int)mode, 0, 0, 0, 1, + FLASH_LED_SET_MODE_PROC); +} +EXPORT_SYMBOL(pmic_flash_led_set_mode); + +int pmic_flash_led_set_polarity(enum flash_led_pol pol) +{ + return pmic_rpc_set_only((int)pol, 0, 0, 0, 1, + FLASH_LED_SET_POLARITY_PROC); +} +EXPORT_SYMBOL(pmic_flash_led_set_polarity); + +int pmic_spkr_add_right_left_chan(uint enable) +{ + return pmic_rpc_set_only(enable, 0, 0, 0, 1, + SPKR_ADD_RIGHT_LEFT_CHAN_PROC); +} +EXPORT_SYMBOL(pmic_spkr_add_right_left_chan); + +int pmic_spkr_is_right_left_chan_added(uint *enabled) +{ + return pmic_rpc_get_only(enabled, sizeof(*enabled), + SPKR_IS_RIGHT_LEFT_CHAN_ADDED_PROC); +} +EXPORT_SYMBOL(pmic_spkr_is_right_left_chan_added); + +int pmic_spkr_en_stereo(uint enable) +{ + return pmic_rpc_set_only(enable, 0, 0, 0, 1, SPKR_EN_STEREO_PROC); +} +EXPORT_SYMBOL(pmic_spkr_en_stereo); + +int pmic_spkr_is_stereo_en(uint *enabled) +{ + return pmic_rpc_get_only(enabled, sizeof(*enabled), + SPKR_IS_STEREO_EN_PROC); +} +EXPORT_SYMBOL(pmic_spkr_is_stereo_en); + +int pmic_hsed_set_period( + enum hsed_controller controller, + enum hsed_period_pre_div period_pre_div, + enum hsed_period_time period_time +) +{ + return pmic_rpc_set_only(controller, period_pre_div, period_time, 0, + 3, + HSED_SET_PERIOD_PROC); +} +EXPORT_SYMBOL(pmic_hsed_set_period); + +int pmic_hsed_set_hysteresis( + enum hsed_controller controller, + enum hsed_hyst_pre_div hyst_pre_div, + enum hsed_hyst_time hyst_time +) +{ + return pmic_rpc_set_only(controller, hyst_pre_div, hyst_time, 0, + 3, + HSED_SET_HYSTERESIS_PROC); +} +EXPORT_SYMBOL(pmic_hsed_set_hysteresis); + +int pmic_hsed_set_current_threshold( + enum hsed_controller controller, + enum hsed_switch switch_hsed, + uint32_t current_threshold +) +{ + return pmic_rpc_set_only(controller, switch_hsed, current_threshold, 0, + 3, + HSED_SET_CURRENT_THRESHOLD_PROC); +} +EXPORT_SYMBOL(pmic_hsed_set_current_threshold); + +int pmic_hsed_enable( + enum hsed_controller controller, + enum hsed_enable enable_hsed +) +{ + return pmic_rpc_set_only(controller, enable_hsed, 0, 0, + 2, + HSED_ENABLE_PROC); +} +EXPORT_SYMBOL(pmic_hsed_enable); |