ASoC: msm: critical tasha fixes

tasha fixes pulled in by the below change id.

I4ca4a554c0a83d4053301ca5dd2afb8b09fa5194
I2cb4447b36fef111ed1f9b8991b3882b8d57f6a7
I80ee0dedac8fa81ce54a0e61c839a97b9b45d36b

Change-Id: I258d5bb48a25f13e0c0f348a8f6a7bf1b38922d0
Signed-off-by: Santosh Mardi <gsantosh@codeaurora.org>
This commit is contained in:
Santosh Mardi 2016-03-18 16:24:48 +05:30
parent 3d9b219cf4
commit 6203e5d262
7 changed files with 251 additions and 30 deletions

View File

@ -1,4 +1,4 @@
/* Copyright (c) 2015, The Linux Foundation. All rights reserved.
/* Copyright (c) 2015-2016, The Linux Foundation. All rights reserved.
*
* 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
@ -476,6 +476,15 @@ int swr_bulk_write(struct swr_device *dev, u8 dev_num, void *reg,
return -EINVAL;
master = dev->master;
if (dev->group_id) {
if (master->gr_sid != dev_num) {
if (!master->gr_sid)
master->gr_sid = dev_num;
else
return 0;
}
dev_num = dev->group_id;
}
if (master->bulk_write)
return master->bulk_write(master, dev_num, reg, buf, len);
@ -499,6 +508,16 @@ int swr_write(struct swr_device *dev, u8 dev_num, u16 reg_addr,
struct swr_master *master = dev->master;
if (!master)
return -EINVAL;
if (dev->group_id) {
if (master->gr_sid != dev_num) {
if (!master->gr_sid)
master->gr_sid = dev_num;
else
return 0;
}
dev_num = dev->group_id;
}
return master->write(master, dev_num, reg_addr, buf);
}
EXPORT_SYMBOL(swr_write);
@ -588,6 +607,31 @@ int swr_reset_device(struct swr_device *swr_dev)
}
EXPORT_SYMBOL(swr_reset_device);
/**
* swr_set_device_group - Assign group id to the slave devices
* @swr_dev: pointer to soundwire slave device
* @id: group id to be assigned to slave device
* Context: can sleep
*
* This API will be called either from soundwire master or slave
* device to assign group id.
*/
int swr_set_device_group(struct swr_device *swr_dev, u8 id)
{
struct swr_master *master;
if (!swr_dev)
return -EINVAL;
swr_dev->group_id = id;
master = swr_dev->master;
if (!id && master)
master->gr_sid = 0;
return 0;
}
EXPORT_SYMBOL(swr_set_device_group);
static int swr_drv_probe(struct device *dev)
{
const struct swr_driver *sdrv = to_swr_driver(dev->driver);

View File

@ -1,4 +1,4 @@
/* Copyright (c) 2015, The Linux Foundation. All rights reserved.
/* Copyright (c) 2015-2016, The Linux Foundation. All rights reserved.
*
* 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
@ -30,7 +30,7 @@
#include "swr-wcd-ctrl.h"
#define SWR_BROADCAST_CMD_ID 0x0F
#define SWR_AUTO_SUSPEND_DELAY 3 /* delay in sec */
#define SWR_AUTO_SUSPEND_DELAY 3 /* delay in sec */
#define SWR_DEV_ID_MASK 0xFFFFFFFF
#define SWR_REG_VAL_PACK(data, dev, id, reg) \
((reg) | ((id) << 16) | ((dev) << 20) | ((data) << 24))
@ -162,7 +162,7 @@ enum {
#define SWR_MSTR_MAX_REG_ADDR 0x1740
#define SWR_MSTR_START_REG_ADDR 0x00
#define SWR_MSTR_MAX_BUF_LEN 20
#define SWR_MSTR_MAX_BUF_LEN 32
#define BYTES_PER_LINE 12
#define SWR_MSTR_RD_BUF_LEN 8
#define SWR_MSTR_WR_BUF_LEN 32
@ -391,6 +391,7 @@ static int swrm_get_port_config(struct swr_master *master)
static int swrm_get_master_port(u8 *mstr_port_id, u8 slv_port_id)
{
int i;
for (i = 0; i < SWR_MSTR_PORT_LEN; i++) {
if (mstr_ports[i] == slv_port_id) {
*mstr_port_id = i;
@ -480,6 +481,7 @@ static int swrm_read(struct swr_master *master, u8 dev_num, u16 reg_addr,
dev_err(&master->dev, "%s: swrm is NULL\n", __func__);
return -EINVAL;
}
if (dev_num)
ret = swrm_cmd_fifo_rd_cmd(swrm, &val, dev_num, 0, reg_addr,
len);
@ -503,10 +505,12 @@ static int swrm_write(struct swr_master *master, u8 dev_num, u16 reg_addr,
dev_err(&master->dev, "%s: swrm is NULL\n", __func__);
return -EINVAL;
}
if (dev_num)
ret = swrm_cmd_fifo_wr_cmd(swrm, reg_val, dev_num, 0, reg_addr);
else
ret = swrm->write(swrm->handle, reg_addr, reg_val);
pm_runtime_mark_last_busy(&swrm->pdev->dev);
return ret;
@ -612,7 +616,14 @@ static void swrm_apply_port_config(struct swr_master *master)
int len = 0;
int mask = (SWRM_MCP_FRAME_CTRL_BANK_ROW_CTRL_BMSK |
SWRM_MCP_FRAME_CTRL_BANK_COL_CTRL_BMSK);
SWRM_MCP_FRAME_CTRL_BANK_COL_CTRL_BMSK |
SWRM_MCP_FRAME_CTRL_BANK_SSP_PERIOD_BMSK);
if (!swrm) {
pr_err("%s: Invalid handle to swr controller\n",
__func__);
return;
}
bank = get_inactive_bank_num(swrm);
dev_dbg(swrm->dev, "%s: enter bank: %d master_ports: %d\n",
@ -622,7 +633,8 @@ static void swrm_apply_port_config(struct swr_master *master)
value = swrm->read(swrm->handle, SWRM_MCP_FRAME_CTRL_BANK_ADDR(bank));
value &= (~mask);
value |= ((0 << SWRM_MCP_FRAME_CTRL_BANK_ROW_CTRL_SHFT) |
(7 << SWRM_MCP_FRAME_CTRL_BANK_COL_CTRL_SHFT));
(7 << SWRM_MCP_FRAME_CTRL_BANK_COL_CTRL_SHFT) |
(0 << SWRM_MCP_FRAME_CTRL_BANK_SSP_PERIOD_SHFT));
swrm->write(swrm->handle, SWRM_MCP_FRAME_CTRL_BANK_ADDR(bank), value);
dev_dbg(swrm->dev, "%s: regaddr: 0x%x, value: 0x%x\n", __func__,
SWRM_MCP_FRAME_CTRL_BANK_ADDR(bank), value);
@ -707,9 +719,10 @@ static int swrm_connect_port(struct swr_master *master,
if (!portinfo)
return -EINVAL;
if (swrm == NULL) {
dev_err(&master->dev, "%s: invalid soundwire master pointer",
__func__);
if (!swrm) {
dev_err(&master->dev,
"%s: Invalid handle to swr controller\n",
__func__);
return -EINVAL;
}
@ -750,7 +763,13 @@ static int swrm_connect_port(struct swr_master *master,
swrm_get_port_config(master);
swr_port_response(master, portinfo->tid);
swrm_apply_port_config(master);
if (swrm->num_rx_chs > 1) {
swrm->num_cfg_devs += 1;
if (swrm->num_rx_chs == swrm->num_cfg_devs)
swrm_apply_port_config(master);
} else {
swrm_apply_port_config(master);
}
mutex_unlock(&swrm->mlock);
return 0;
@ -777,6 +796,13 @@ static int swrm_disconnect_port(struct swr_master *master,
u32 val[SWRM_MAX_PORT_REG];
int len = 0;
if (!swrm) {
dev_err(&master->dev,
"%s: Invalid handle to swr controller\n",
__func__);
return -EINVAL;
}
if (!portinfo) {
dev_err(&master->dev, "%s: portinfo is NULL\n", __func__);
return -EINVAL;
@ -831,6 +857,8 @@ static int swrm_disconnect_port(struct swr_master *master,
master->num_port -= portinfo->num_port;
swr_port_response(master, portinfo->tid);
if (swrm->num_rx_chs > 1)
swrm->num_cfg_devs -= 1;
mutex_unlock(&swrm->mlock);
dev_dbg(&master->dev, "%s: master active ports: %d\n",
@ -919,7 +947,7 @@ static irqreturn_t swr_mstr_interrupt(int irq, void *dev)
}
break;
case SWRM_INTERRUPT_STATUS_MASTER_CLASH_DET:
dev_err(swrm->dev, "SWR bus clash detected\n");
dev_err_ratelimited(swrm->dev, "SWR bus clash detected\n");
break;
case SWRM_INTERRUPT_STATUS_RD_FIFO_OVERFLOW:
dev_dbg(swrm->dev, "SWR read FIFO overflow\n");
@ -932,9 +960,9 @@ static irqreturn_t swr_mstr_interrupt(int irq, void *dev)
break;
case SWRM_INTERRUPT_STATUS_CMD_ERROR:
value = swrm->read(swrm->handle, SWRM_CMD_FIFO_STATUS);
dev_err(swrm->dev,
"SWR CMD error, CMD fifo status 0x%x, flushing fifo\n",
value);
dev_err_ratelimited(swrm->dev,
"SWR CMD error, fifo status 0x%x, flushing fifo\n",
value);
swrm->write(swrm->handle, SWRM_CMD_FIFO_CMD, 0x1);
break;
case SWRM_INTERRUPT_STATUS_DOUT_PORT_COLLISION:
@ -959,7 +987,7 @@ static irqreturn_t swr_mstr_interrupt(int irq, void *dev)
case SWRM_INTERRUPT_STATUS_CLK_STOP_FINISHED:
break;
default:
dev_err(swrm->dev, "SWR unkown interrupt\n");
dev_err_ratelimited(swrm->dev, "SWR unknown interrupt\n");
ret = IRQ_NONE;
break;
}
@ -987,15 +1015,19 @@ static int swrm_get_logical_dev_num(struct swr_master *mstr, u64 dev_id,
int ret = -EINVAL;
struct swr_mstr_ctrl *swrm = swr_get_ctrl_data(mstr);
if (!swrm) {
pr_err("%s: Invalid handle to swr controller\n",
__func__);
return ret;
}
pm_runtime_get_sync(&swrm->pdev->dev);
for (i = 1; i < (mstr->num_dev + 1); i++) {
id = ((u64)(swrm->read(swrm->handle,
SWRM_ENUMERATOR_SLAVE_DEV_ID_2(i))) << 32);
id |= swrm->read(swrm->handle,
SWRM_ENUMERATOR_SLAVE_DEV_ID_1(i));
id = id & SWR_DEV_ID_MASK;
if (id == dev_id) {
if ((id & SWR_DEV_ID_MASK) == dev_id) {
if (swrm_get_device_status(swrm, i) == 0x01) {
*dev_num = i;
ret = 0;
@ -1019,6 +1051,7 @@ static int swrm_master_init(struct swr_mstr_ctrl *swrm)
u32 val;
u8 row_ctrl = SWR_MAX_ROW;
u8 col_ctrl = SWR_MIN_COL;
u8 ssp_period = 1;
u8 retry_cmd_num = 3;
u32 reg[SWRM_MAX_INIT_REG];
u32 value[SWRM_MAX_INIT_REG];
@ -1026,7 +1059,8 @@ static int swrm_master_init(struct swr_mstr_ctrl *swrm)
/* Clear Rows and Cols */
val = ((row_ctrl << SWRM_MCP_FRAME_CTRL_BANK_ROW_CTRL_SHFT) |
(col_ctrl << SWRM_MCP_FRAME_CTRL_BANK_COL_CTRL_SHFT));
(col_ctrl << SWRM_MCP_FRAME_CTRL_BANK_COL_CTRL_SHFT) |
(ssp_period << SWRM_MCP_FRAME_CTRL_BANK_SSP_PERIOD_SHFT));
reg[len] = SWRM_MCP_FRAME_CTRL_BANK_ADDR(0);
value[len++] = val;
@ -1055,11 +1089,12 @@ static int swrm_master_init(struct swr_mstr_ctrl *swrm)
reg[len] = SWRM_COMP_CFG_ADDR;
value[len++] = 0x02;
reg[len] = SWRM_MCP_BUS_CTRL_ADDR;
value[len++] = 0x02;
reg[len] = SWRM_COMP_CFG_ADDR;
value[len++] = 0x03;
reg[len] = SWRM_INTERRUPT_CLEAR;
value[len++] = 0x08;
swrm->bulk_write(swrm->handle, reg, value, len);
return ret;
@ -1146,6 +1181,7 @@ static int swrm_probe(struct platform_device *pdev)
swrm->rcmd_id = 0;
swrm->wcmd_id = 0;
swrm->slave_status = 0;
swrm->num_rx_chs = 0;
swrm->state = SWR_MSTR_RESUME;
init_completion(&swrm->reset);
init_completion(&swrm->broadcast);
@ -1241,6 +1277,7 @@ static int swrm_remove(struct platform_device *pdev)
pm_runtime_set_suspended(&pdev->dev);
swr_unregister_master(&swrm->master);
mutex_destroy(&swrm->mlock);
mutex_destroy(&swrm->reslock);
kfree(swrm);
return 0;
}
@ -1335,12 +1372,13 @@ exit:
static int swrm_runtime_idle(struct device *dev)
{
if (pm_runtime_autosuspend_expiration(dev)) {
if (pm_runtime_autosuspend_expiration(dev)) {
pm_runtime_autosuspend(dev);
return -EAGAIN;
}
return 0;
}
#endif /* CONFIG_PM_RUNTIME */
static int swrm_device_down(struct device *dev)
@ -1420,12 +1458,16 @@ int swrm_wcd_notify(struct platform_device *pdev, u32 id, void *data)
case SWR_DEVICE_UP:
dev_dbg(swrm->dev, "%s: swr master up called\n", __func__);
mutex_lock(&swrm->mlock);
mutex_lock(&swrm->reslock);
if ((swrm->state == SWR_MSTR_RESUME) ||
(swrm->state == SWR_MSTR_UP)) {
dev_dbg(swrm->dev, "%s: SWR master is already UP: %d\n",
__func__, swrm->state);
} else {
pm_runtime_mark_last_busy(&pdev->dev);
mutex_unlock(&swrm->reslock);
pm_runtime_get_sync(&pdev->dev);
mutex_lock(&swrm->reslock);
list_for_each_entry(swr_dev, &mstr->devices, dev_list) {
ret = swr_reset_device(swr_dev);
if (ret) {
@ -1438,8 +1480,40 @@ int swrm_wcd_notify(struct platform_device *pdev, u32 id, void *data)
pm_runtime_mark_last_busy(&pdev->dev);
pm_runtime_put_autosuspend(&pdev->dev);
}
mutex_unlock(&swrm->reslock);
mutex_unlock(&swrm->mlock);
break;
case SWR_SET_NUM_RX_CH:
if (!data) {
dev_err(swrm->dev, "%s: data is NULL\n", __func__);
ret = -EINVAL;
} else {
mutex_lock(&swrm->mlock);
swrm->num_rx_chs = *(int *)data;
if (swrm->num_rx_chs > 1) {
list_for_each_entry(swr_dev, &mstr->devices,
dev_list) {
ret = swr_set_device_group(swr_dev,
SWR_BROADCAST);
if (ret)
dev_err(swrm->dev,
"%s: set num ch failed\n",
__func__);
}
} else {
list_for_each_entry(swr_dev, &mstr->devices,
dev_list) {
ret = swr_set_device_group(swr_dev,
SWR_GROUP_NONE);
if (ret)
dev_err(swrm->dev,
"%s: set num ch failed\n",
__func__);
}
}
mutex_unlock(&swrm->mlock);
}
break;
default:
dev_err(swrm->dev, "%s: swr master unknown id %d\n",
__func__, id);

View File

@ -90,10 +90,12 @@ struct swr_mstr_ctrl {
int irq;
int num_enum_slaves;
int slave_status;
struct list_head mport_list;
struct swr_mstr_port *mstr_port;
struct list_head mport_list;
int state;
struct platform_device *pdev;
int num_rx_chs;
u8 num_cfg_devs;
};
#endif /* _SWR_WCD_CTRL_H */

View File

@ -136,8 +136,12 @@
#define SWRM_ENUMERATOR_SLAVE_DEV_ID_2(m) (SWRM_BASE_ADDRESS+0x534+0x8*m)
#define SWRM_MCP_FRAME_CTRL_BANK_ADDR(m) (SWRM_BASE_ADDRESS+0x101C+0x40*m)
#define SWRM_MCP_FRAME_CTRL_BANK_RMSK 0x000007ff
#define SWRM_MCP_FRAME_CTRL_BANK_RMSK 0x00ff07ff
#define SWRM_MCP_FRAME_CTRL_BANK_SHFT 0
#define SWRM_MCP_FRAME_CTRL_BANK_SSP_PERIOD_BMSK 0xff0000
#define SWRM_MCP_FRAME_CTRL_BANK_SSP_PERIOD_SHFT 16
#define SWRM_MCP_FRAME_CTRL_BANK_PHASE_BMSK 0xf800
#define SWRM_MCP_FRAME_CTRL_BANK_PHASE_SHFT 11
#define SWRM_MCP_FRAME_CTRL_BANK_CLK_DIV_VALUE_BMSK 0x700
#define SWRM_MCP_FRAME_CTRL_BANK_CLK_DIV_VALUE_SHFT 8
#define SWRM_MCP_FRAME_CTRL_BANK_ROW_CTRL_BMSK 0xF8

View File

@ -29,6 +29,14 @@ extern struct bus_type soundwire_type;
*/
#define SWR_MAX_MSTR_PORT_NUM (SWR_MAX_DEV_NUM * SWR_MAX_DEV_PORT_NUM)
/* Indicates soundwire devices group information */
enum {
SWR_GROUP_NONE = 0,
SWR_GROUP_12 = 12,
SWR_GROUP_13 = 13,
SWR_BROADCAST = 15,
};
/*
* struct swr_port_info - represent soundwire frame shape
* @dev_id: logical device number of the soundwire slave device
@ -112,6 +120,7 @@ struct swr_reg {
* @last_tid: size of table port_txn (can't grow beyond 256 since
* tid is 8 bits)
* @num_port: number of active ports on soundwire master
* @gr_sid: slave id used by the group for write operations
* @connect_port: callback for configuration of soundwire port(s)
* @disconnect_port: callback for disable of soundwire port(s)
* @read: callback for soundwire slave register read
@ -131,6 +140,7 @@ struct swr_master {
u8 last_tid;
u8 num_port;
u8 num_dev;
u8 gr_sid;
int (*connect_port)(struct swr_master *mstr, struct swr_params *txn);
int (*disconnect_port)(struct swr_master *mstr, struct swr_params *txn);
int (*read)(struct swr_master *mstr, u8 dev_num, u16 reg_addr,
@ -159,6 +169,7 @@ static inline struct swr_master *to_swr_master(struct device *dev)
* @dev: driver model representation of the device
* @addr: represents "ea-addr" which is unique-id of soundwire slave
* device
* @group_id: group id supported by the slave device
*/
struct swr_device {
char name[SOUNDWIRE_NAME_SIZE];
@ -168,6 +179,7 @@ struct swr_device {
u8 dev_num;
struct device dev;
unsigned long addr;
u8 group_id;
};
static inline struct swr_device *to_swr_device(struct device *dev)
@ -270,6 +282,8 @@ extern int swr_connect_port(struct swr_device *dev, u8 *port_id, u8 num_port,
extern int swr_disconnect_port(struct swr_device *dev,
u8 *port_id, u8 num_port);
extern int swr_set_device_group(struct swr_device *swr_dev, u8 id);
extern int swr_driver_register(struct swr_driver *drv);
extern void swr_driver_unregister(struct swr_driver *drv);

View File

@ -4584,6 +4584,11 @@ static int tasha_codec_enable_swr(struct snd_soc_dapm_widget *w,
if ((strnstr(w->name, "INT8_", sizeof("RX INT8_"))) &&
tasha->rx_8_count)
tasha->rx_8_count--;
ch_cnt = tasha->rx_7_count + tasha->rx_8_count;
for (i = 0; i < tasha->nr; i++)
swrm_wcd_notify(tasha->swr_ctrl_data[i].swr_pdev,
SWR_SET_NUM_RX_CH, &ch_cnt);
break;
}
@ -5475,30 +5480,56 @@ static const struct soc_enum cf_dec8_enum =
static const struct soc_enum cf_int0_1_enum =
SOC_ENUM_SINGLE(WCD9335_CDC_RX0_RX_PATH_CFG2, 0, 4, rx_cf_text);
static SOC_ENUM_SINGLE_DECL(cf_int0_2_enum, WCD9335_CDC_RX0_RX_PATH_MIX_CFG, 2,
rx_cf_text);
static const struct soc_enum cf_int1_1_enum =
SOC_ENUM_SINGLE(WCD9335_CDC_RX1_RX_PATH_CFG2, 0, 4, rx_cf_text);
static SOC_ENUM_SINGLE_DECL(cf_int1_2_enum, WCD9335_CDC_RX1_RX_PATH_MIX_CFG, 2,
rx_cf_text);
static const struct soc_enum cf_int2_1_enum =
SOC_ENUM_SINGLE(WCD9335_CDC_RX2_RX_PATH_CFG2, 0, 4, rx_cf_text);
static SOC_ENUM_SINGLE_DECL(cf_int2_2_enum, WCD9335_CDC_RX2_RX_PATH_MIX_CFG, 2,
rx_cf_text);
static const struct soc_enum cf_int3_1_enum =
SOC_ENUM_SINGLE(WCD9335_CDC_RX3_RX_PATH_CFG2, 0, 4, rx_cf_text);
static SOC_ENUM_SINGLE_DECL(cf_int3_2_enum, WCD9335_CDC_RX3_RX_PATH_MIX_CFG, 2,
rx_cf_text);
static const struct soc_enum cf_int4_1_enum =
SOC_ENUM_SINGLE(WCD9335_CDC_RX4_RX_PATH_CFG2, 0, 4, rx_cf_text);
static SOC_ENUM_SINGLE_DECL(cf_int4_2_enum, WCD9335_CDC_RX4_RX_PATH_MIX_CFG, 2,
rx_cf_text);
static const struct soc_enum cf_int5_1_enum =
SOC_ENUM_SINGLE(WCD9335_CDC_RX5_RX_PATH_CFG2, 0, 4, rx_cf_text);
static SOC_ENUM_SINGLE_DECL(cf_int5_2_enum, WCD9335_CDC_RX5_RX_PATH_MIX_CFG, 2,
rx_cf_text);
static const struct soc_enum cf_int6_1_enum =
SOC_ENUM_SINGLE(WCD9335_CDC_RX6_RX_PATH_CFG2, 0, 4, rx_cf_text);
static SOC_ENUM_SINGLE_DECL(cf_int6_2_enum, WCD9335_CDC_RX6_RX_PATH_MIX_CFG, 2,
rx_cf_text);
static const struct soc_enum cf_int7_1_enum =
SOC_ENUM_SINGLE(WCD9335_CDC_RX7_RX_PATH_CFG2, 0, 4, rx_cf_text);
static SOC_ENUM_SINGLE_DECL(cf_int7_2_enum, WCD9335_CDC_RX7_RX_PATH_MIX_CFG, 2,
rx_cf_text);
static const struct soc_enum cf_int8_1_enum =
SOC_ENUM_SINGLE(WCD9335_CDC_RX8_RX_PATH_CFG2, 0, 4, rx_cf_text);
static SOC_ENUM_SINGLE_DECL(cf_int8_2_enum, WCD9335_CDC_RX8_RX_PATH_MIX_CFG, 2,
rx_cf_text);
static const struct snd_soc_dapm_route audio_map[] = {
/* MAD */
@ -7518,14 +7549,23 @@ static const struct snd_kcontrol_new tasha_snd_controls[] = {
SOC_ENUM("TX8 HPF cut off", cf_dec8_enum),
SOC_ENUM("RX INT0_1 HPF cut off", cf_int0_1_enum),
SOC_ENUM("RX INT0_2 HPF cut off", cf_int0_2_enum),
SOC_ENUM("RX INT1_1 HPF cut off", cf_int1_1_enum),
SOC_ENUM("RX INT1_2 HPF cut off", cf_int1_2_enum),
SOC_ENUM("RX INT2_1 HPF cut off", cf_int2_1_enum),
SOC_ENUM("RX INT2_2 HPF cut off", cf_int2_2_enum),
SOC_ENUM("RX INT3_1 HPF cut off", cf_int3_1_enum),
SOC_ENUM("RX INT3_2 HPF cut off", cf_int3_2_enum),
SOC_ENUM("RX INT4_1 HPF cut off", cf_int4_1_enum),
SOC_ENUM("RX INT4_2 HPF cut off", cf_int4_2_enum),
SOC_ENUM("RX INT5_1 HPF cut off", cf_int5_1_enum),
SOC_ENUM("RX INT5_2 HPF cut off", cf_int5_2_enum),
SOC_ENUM("RX INT6_1 HPF cut off", cf_int6_1_enum),
SOC_ENUM("RX INT6_2 HPF cut off", cf_int6_2_enum),
SOC_ENUM("RX INT7_1 HPF cut off", cf_int7_1_enum),
SOC_ENUM("RX INT7_2 HPF cut off", cf_int7_2_enum),
SOC_ENUM("RX INT8_1 HPF cut off", cf_int8_1_enum),
SOC_ENUM("RX INT8_2 HPF cut off", cf_int8_2_enum),
SOC_SINGLE_EXT("IIR0 Enable Band1", IIR0, BAND1, 1, 0,
tasha_get_iir_enable_audio_mixer, tasha_put_iir_enable_audio_mixer),
@ -12160,9 +12200,33 @@ static int tasha_codec_remove(struct snd_soc_codec *codec)
return 0;
}
static int tasha_codec_suspend(struct snd_soc_codec *codec)
{
struct tasha_priv *tasha = snd_soc_codec_get_drvdata(codec);
struct wcd9xxx_pdata *pdata = dev_get_platdata(codec->dev->parent);
pr_debug("%s:suspend of tasha codec\n", __func__);
wcd9xxx_disable_static_supplies_to_optimum(tasha->wcd9xxx, pdata);
return 0;
}
static int tasha_codec_resume(struct snd_soc_codec *codec)
{
struct tasha_priv *tasha = snd_soc_codec_get_drvdata(codec);
struct wcd9xxx_pdata *pdata = dev_get_platdata(codec->dev->parent);
pr_debug("%s:resume of tasha codec\n", __func__);
wcd9xxx_enable_static_supplies_to_optimum(tasha->wcd9xxx, pdata);
return 0;
}
static struct snd_soc_codec_driver soc_codec_dev_tasha = {
.probe = tasha_codec_probe,
.remove = tasha_codec_remove,
.suspend = tasha_codec_suspend,
.resume = tasha_codec_resume,
.controls = tasha_snd_controls,
.num_controls = ARRAY_SIZE(tasha_snd_controls),
.dapm_widgets = tasha_dapm_widgets,

View File

@ -431,7 +431,7 @@ static const struct reg_default wsa881x_vi_txfe_en[] = {
static const struct reg_default wsa881x_vi_txfe_en_2_0[] = {
{WSA881X_SPKR_PROT_FE_VSENSE_VCM, 0x85},
{WSA881X_SPKR_PROT_ATEST2, 0x0A},
{WSA881X_SPKR_PROT_FE_GAIN, 0xCF},
{WSA881X_SPKR_PROT_FE_GAIN, 0x47},
};
static int wsa881x_boost_ctrl(struct snd_soc_codec *codec, bool enable)
@ -460,14 +460,26 @@ static int wsa881x_visense_txfe_ctrl(struct snd_soc_codec *codec, bool enable,
__func__, enable, isense1_gain, isense2_gain, vsense_gain);
if (enable) {
if (WSA881X_IS_2_0(wsa881x->version))
if (WSA881X_IS_2_0(wsa881x->version)) {
regmap_multi_reg_write(wsa881x->regmap,
wsa881x_vi_txfe_en_2_0,
ARRAY_SIZE(wsa881x_vi_txfe_en_2_0));
else
if (!wsa881x->comp_enable) {
if (((snd_soc_read(codec, WSA881X_SPKR_DRV_GAIN)
& 0xF0) >> 4) < G_15DB)
snd_soc_update_bits(codec,
WSA881X_SPKR_PROT_FE_GAIN,
0xF8, 0xC8);
else
snd_soc_update_bits(codec,
WSA881X_SPKR_PROT_FE_GAIN,
0xF8, 0x40);
}
} else {
regmap_multi_reg_write(wsa881x->regmap,
wsa881x_vi_txfe_en,
ARRAY_SIZE(wsa881x_vi_txfe_en));
}
} else {
snd_soc_update_bits(codec, WSA881X_SPKR_PROT_FE_VSENSE_VCM,
0x08, 0x08);
@ -919,9 +931,12 @@ static void wsa881x_init(struct snd_soc_codec *codec)
snd_soc_update_bits(codec, WSA881X_CDC_RST_CTL, 0x01, 0x01);
if (WSA881X_IS_2_0(wsa881x->version)) {
snd_soc_update_bits(codec, WSA881X_CLOCK_CONFIG, 0x10, 0x10);
snd_soc_update_bits(codec, WSA881X_SPKR_OCP_CTL, 0x02, 0x02);
snd_soc_update_bits(codec, WSA881X_SPKR_MISC_CTL1, 0xC0, 0x80);
snd_soc_update_bits(codec, WSA881X_SPKR_MISC_CTL1, 0x06, 0x06);
snd_soc_update_bits(codec, WSA881X_SPKR_PA_INT, 0xF0, 0x20);
snd_soc_update_bits(codec, WSA881X_SPKR_BIAS_INT, 0xFF, 0x00);
snd_soc_update_bits(codec, WSA881X_SPKR_PA_INT, 0xF0, 0x40);
snd_soc_update_bits(codec, WSA881X_SPKR_PA_INT, 0x0E, 0x0E);
snd_soc_update_bits(codec, WSA881X_BOOST_LOOP_STABILITY,
0x03, 0x03);
@ -932,8 +947,12 @@ static void wsa881x_init(struct snd_soc_codec *codec)
0x0C, 0x04);
snd_soc_update_bits(codec, WSA881X_BOOST_SLOPE_COMP_ISENSE_FB,
0x03, 0x00);
if (snd_soc_read(codec, WSA881X_OTP_REG_0))
snd_soc_update_bits(codec, WSA881X_BOOST_PRESET_OUT1,
0xF0, 0x70);
snd_soc_update_bits(codec, WSA881X_BOOST_PRESET_OUT2,
0xF0, 0x30);
snd_soc_update_bits(codec, WSA881X_SPKR_DRV_EN, 0x08, 0x08);
snd_soc_update_bits(codec, WSA881X_BOOST_PS_CTL, 0x80, 0x00);
snd_soc_update_bits(codec, WSA881X_BOOST_CURRENT_LIMIT,
0x0F, 0x08);
snd_soc_update_bits(codec, WSA881X_SPKR_OCP_CTL, 0x30, 0x30);