mirror of
https://github.com/team-infusion-developers/android_kernel_samsung_msm8976.git
synced 2024-11-01 02:21:16 +00:00
ASoC: msm: update machine and codec driver for proper ioremap checks
ioremapped address is directly accessed without a proper NULL check. This causes the NULL pointer dereference leading to target crash. Crosscheck for the address returned by the ioremap api. Change-Id: I343a11e1dd6b4f30d2e8b2c1d10d382d3cacf3cd Signed-off-by: Aviral Gupta <aviralg@codeaurora.org>
This commit is contained in:
parent
792ce78d67
commit
2bd2fdeeb2
3 changed files with 108 additions and 24 deletions
|
@ -59,6 +59,7 @@
|
|||
#define TOMBAK_CORE_1_SPMI_ADDR 0xf100
|
||||
|
||||
#define CODEC_DT_MAX_PROP_SIZE 40
|
||||
#define MSM8X16_DIGITAL_CODEC_REG_SIZE 0x400
|
||||
#define MAX_ON_DEMAND_SUPPLY_NAME_LENGTH 64
|
||||
#define TOMBAK_MCLK_CLK_9P6MHZ 9600000
|
||||
|
||||
|
@ -207,10 +208,11 @@ static int get_spmi_msm8x16_wcd_device_info(u16 *reg,
|
|||
return rtn;
|
||||
}
|
||||
|
||||
static int msm8x16_wcd_ahb_write_device(u16 reg, u8 *value, u32 bytes)
|
||||
static int msm8x16_wcd_ahb_write_device(struct msm8x16_wcd *msm8x16_wcd,
|
||||
u16 reg, u8 *value, u32 bytes)
|
||||
{
|
||||
u32 temp = ((u32)(*value)) & 0x000000FF;
|
||||
u32 offset = (((u32)(reg)) ^ 0x00000200) & 0x00000FFF;
|
||||
u16 offset = (reg ^ 0x0200) & 0x0FFF;
|
||||
bool q6_state = false;
|
||||
|
||||
q6_state = q6core_is_adsp_ready();
|
||||
|
@ -220,14 +222,15 @@ static int msm8x16_wcd_ahb_write_device(u16 reg, u8 *value, u32 bytes)
|
|||
} else
|
||||
pr_debug("%s: DSP is ready %d\n", __func__, q6_state);
|
||||
|
||||
iowrite32(temp, ioremap(MSM8X16_DIGITAL_CODEC_BASE_ADDR + offset, 4));
|
||||
iowrite32(temp, msm8x16_wcd->dig_base + offset);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int msm8x16_wcd_ahb_read_device(u16 reg, u32 bytes, u8 *value)
|
||||
static int msm8x16_wcd_ahb_read_device(struct msm8x16_wcd *msm8x16_wcd,
|
||||
u16 reg, u32 bytes, u8 *value)
|
||||
{
|
||||
u32 temp;
|
||||
u32 offset = (((u32)(reg)) ^ 0x00000200) & 0x00000FFF;
|
||||
u16 offset = (reg ^ 0x0200) & 0x0FFF;
|
||||
bool q6_state = false;
|
||||
|
||||
q6_state = q6core_is_adsp_ready();
|
||||
|
@ -237,8 +240,7 @@ static int msm8x16_wcd_ahb_read_device(u16 reg, u32 bytes, u8 *value)
|
|||
} else
|
||||
pr_debug("%s: DSP is ready %d\n", __func__, q6_state);
|
||||
|
||||
temp = ioread32(ioremap(MSM8X16_DIGITAL_CODEC_BASE_ADDR +
|
||||
offset, 4));
|
||||
temp = ioread32(msm8x16_wcd->dig_base + offset);
|
||||
*value = (u8)temp;
|
||||
return 0;
|
||||
}
|
||||
|
@ -343,12 +345,13 @@ static int __msm8x16_wcd_reg_read(struct snd_soc_codec *codec,
|
|||
pr_debug("%s: MCLK not enabled\n", __func__);
|
||||
atomic_set(&pdata->dis_work_mclk, true);
|
||||
schedule_delayed_work(&pdata->enable_mclk_work, 50);
|
||||
ret = msm8x16_wcd_ahb_read_device(reg, 1, &temp);
|
||||
ret = msm8x16_wcd_ahb_read_device(
|
||||
msm8x16_wcd, reg, 1, &temp);
|
||||
mutex_unlock(&pdata->cdc_mclk_mutex);
|
||||
mutex_unlock(&msm8x16_wcd->io_lock);
|
||||
return temp;
|
||||
}
|
||||
ret = msm8x16_wcd_ahb_read_device(reg, 1, &temp);
|
||||
ret = msm8x16_wcd_ahb_read_device(msm8x16_wcd, reg, 1, &temp);
|
||||
}
|
||||
mutex_unlock(&msm8x16_wcd->io_lock);
|
||||
|
||||
|
@ -392,12 +395,13 @@ static int __msm8x16_wcd_reg_write(struct snd_soc_codec *codec,
|
|||
}
|
||||
atomic_set(&pdata->dis_work_mclk, true);
|
||||
schedule_delayed_work(&pdata->enable_mclk_work, 50);
|
||||
ret = msm8x16_wcd_ahb_write_device(reg, &val, 1);
|
||||
ret = msm8x16_wcd_ahb_write_device(
|
||||
msm8x16_wcd, reg, &val, 1);
|
||||
mutex_unlock(&pdata->cdc_mclk_mutex);
|
||||
mutex_unlock(&msm8x16_wcd->io_lock);
|
||||
return ret;
|
||||
}
|
||||
ret = msm8x16_wcd_ahb_write_device(reg, &val, 1);
|
||||
ret = msm8x16_wcd_ahb_write_device(msm8x16_wcd, reg, &val, 1);
|
||||
}
|
||||
mutex_unlock(&msm8x16_wcd->io_lock);
|
||||
|
||||
|
@ -2932,6 +2936,13 @@ static int msm8x16_wcd_codec_probe(struct snd_soc_codec *codec)
|
|||
|
||||
/* codec resmgr module init */
|
||||
msm8x16_wcd = codec->control_data;
|
||||
msm8x16_wcd->dig_base = ioremap(MSM8X16_DIGITAL_CODEC_BASE_ADDR,
|
||||
MSM8X16_DIGITAL_CODEC_REG_SIZE);
|
||||
if (msm8x16_wcd->dig_base == NULL) {
|
||||
dev_err(codec->dev, "%s ioremap failed", __func__);
|
||||
kfree(msm8x16_wcd_priv);
|
||||
return -ENOMEM;
|
||||
}
|
||||
msm8x16_wcd_bringup(codec);
|
||||
msm8x16_wcd_codec_init_reg(codec);
|
||||
msm8x16_wcd_update_reg_defaults(codec);
|
||||
|
@ -2957,6 +2968,8 @@ static int msm8x16_wcd_codec_probe(struct snd_soc_codec *codec)
|
|||
if (!modem_state_notifier) {
|
||||
dev_err(codec->dev, "Failed to register modem state notifier\n"
|
||||
);
|
||||
iounmap(msm8x16_wcd->dig_base);
|
||||
kfree(msm8x16_wcd_priv);
|
||||
registered_codec = NULL;
|
||||
return -ENOMEM;
|
||||
}
|
||||
|
@ -2965,10 +2978,14 @@ static int msm8x16_wcd_codec_probe(struct snd_soc_codec *codec)
|
|||
|
||||
static int msm8x16_wcd_codec_remove(struct snd_soc_codec *codec)
|
||||
{
|
||||
struct msm8x16_wcd_priv *msm8x16_wcd = snd_soc_codec_get_drvdata(codec);
|
||||
struct msm8x16_wcd_priv *msm8x16_wcd_priv =
|
||||
snd_soc_codec_get_drvdata(codec);
|
||||
struct msm8x16_wcd *msm8x16_wcd;
|
||||
|
||||
msm8x16_wcd->on_demand_list[ON_DEMAND_MICBIAS].supply = NULL;
|
||||
atomic_set(&msm8x16_wcd->on_demand_list[ON_DEMAND_MICBIAS].ref, 0);
|
||||
msm8x16_wcd = codec->control_data;
|
||||
msm8x16_wcd_priv->on_demand_list[ON_DEMAND_MICBIAS].supply = NULL;
|
||||
atomic_set(&msm8x16_wcd_priv->on_demand_list[ON_DEMAND_MICBIAS].ref, 0);
|
||||
iounmap(msm8x16_wcd->dig_base);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
@ -3118,15 +3135,59 @@ static void msm8x16_wcd_disable_supplies(struct msm8x16_wcd *msm8x16,
|
|||
|
||||
static int msm8x16_wcd_clk_init(void)
|
||||
{
|
||||
void __iomem *vaddr = NULL;
|
||||
|
||||
/* Div-2 */
|
||||
iowrite32(0x3, ioremap(MSM8X16_TOMBAK_LPASS_DIGCODEC_CFG_RCGR, 4));
|
||||
iowrite32(0x0, ioremap(MSM8X16_TOMBAK_LPASS_DIGCODEC_M, 4));
|
||||
iowrite32(0x0, ioremap(MSM8X16_TOMBAK_LPASS_DIGCODEC_N, 4));
|
||||
iowrite32(0x0, ioremap(MSM8X16_TOMBAK_LPASS_DIGCODEC_D, 4));
|
||||
vaddr = ioremap(MSM8X16_TOMBAK_LPASS_DIGCODEC_CFG_RCGR, 4);
|
||||
if (vaddr == NULL) {
|
||||
pr_err("%s: ioremap failed for %x\n",
|
||||
__func__, MSM8X16_TOMBAK_LPASS_DIGCODEC_CFG_RCGR);
|
||||
return -ENOMEM;
|
||||
}
|
||||
iowrite32(0x3, vaddr);
|
||||
iounmap(vaddr);
|
||||
vaddr = ioremap(MSM8X16_TOMBAK_LPASS_DIGCODEC_M, 4);
|
||||
if (vaddr == NULL) {
|
||||
pr_err("%s: ioremap failed for %x\n",
|
||||
__func__, MSM8X16_TOMBAK_LPASS_DIGCODEC_M);
|
||||
return -ENOMEM;
|
||||
}
|
||||
iowrite32(0x0, vaddr);
|
||||
iounmap(vaddr);
|
||||
vaddr = ioremap(MSM8X16_TOMBAK_LPASS_DIGCODEC_N, 4);
|
||||
if (vaddr == NULL) {
|
||||
pr_err("%s: ioremap failed for %x\n",
|
||||
__func__, MSM8X16_TOMBAK_LPASS_DIGCODEC_N);
|
||||
return -ENOMEM;
|
||||
}
|
||||
iowrite32(0x0, vaddr);
|
||||
iounmap(vaddr);
|
||||
vaddr = ioremap(MSM8X16_TOMBAK_LPASS_DIGCODEC_D, 4);
|
||||
if (vaddr == NULL) {
|
||||
pr_err("%s: ioremap failed for %x\n",
|
||||
__func__, MSM8X16_TOMBAK_LPASS_DIGCODEC_D);
|
||||
return -ENOMEM;
|
||||
}
|
||||
iowrite32(0x0, vaddr);
|
||||
iounmap(vaddr);
|
||||
/* Digital codec clock enable */
|
||||
iowrite32(0x1, ioremap(MSM8X16_TOMBAK_LPASS_DIGCODEC_CBCR, 4));
|
||||
vaddr = ioremap(MSM8X16_TOMBAK_LPASS_DIGCODEC_CBCR, 4);
|
||||
if (vaddr == NULL) {
|
||||
pr_err("%s: ioremap failed for %x\n",
|
||||
__func__, MSM8X16_TOMBAK_LPASS_DIGCODEC_CBCR);
|
||||
return -ENOMEM;
|
||||
}
|
||||
iowrite32(0x1, vaddr);
|
||||
iounmap(vaddr);
|
||||
/* Set the update bit to make the settings go through */
|
||||
iowrite32(0x1, ioremap(MSM8X16_TOMBAK_LPASS_DIGCODEC_CMD_RCGR, 4));
|
||||
vaddr = ioremap(MSM8X16_TOMBAK_LPASS_DIGCODEC_CMD_RCGR, 4);
|
||||
if (vaddr == NULL) {
|
||||
pr_err("%s: ioremap failed for %x\n",
|
||||
__func__, MSM8X16_TOMBAK_LPASS_DIGCODEC_CMD_RCGR);
|
||||
return -ENOMEM;
|
||||
}
|
||||
iowrite32(0x1, vaddr);
|
||||
iounmap(vaddr);
|
||||
usleep_range(100, 200);
|
||||
return 0;
|
||||
}
|
||||
|
|
|
@ -160,6 +160,7 @@ struct msm8x16_wcd {
|
|||
|
||||
int num_irqs;
|
||||
u32 mclk_rate;
|
||||
char __iomem *dig_base;
|
||||
};
|
||||
|
||||
extern int msm8x16_wcd_mclk_enable(struct snd_soc_codec *codec, int mclk_enable,
|
||||
|
|
|
@ -387,6 +387,7 @@ static int msm_mi2s_snd_startup(struct snd_pcm_substream *substream)
|
|||
struct msm8916_asoc_mach_data *pdata = snd_soc_card_get_drvdata(card);
|
||||
int ret = 0;
|
||||
int val = 0;
|
||||
void __iomem *vaddr = NULL;
|
||||
|
||||
pr_debug("%s(): substream = %s stream = %d\n", __func__,
|
||||
substream->name, substream->stream);
|
||||
|
@ -396,12 +397,33 @@ static int msm_mi2s_snd_startup(struct snd_pcm_substream *substream)
|
|||
* slave select to invalid state, for machine mode this
|
||||
* should move to HW, I do not like to do it here
|
||||
*/
|
||||
val = ioread32(ioremap(LPASS_CSR_GP_IO_MUX_SPKR_CTL , 4));
|
||||
vaddr = ioremap(LPASS_CSR_GP_IO_MUX_SPKR_CTL , 4);
|
||||
if (!vaddr) {
|
||||
pr_err("%s ioremap failure for addr %x",
|
||||
__func__, LPASS_CSR_GP_IO_MUX_SPKR_CTL);
|
||||
return -ENOMEM;
|
||||
}
|
||||
val = ioread32(vaddr);
|
||||
val = val | 0x00030300;
|
||||
iowrite32(val, ioremap(LPASS_CSR_GP_IO_MUX_SPKR_CTL , 4));
|
||||
val = ioread32(ioremap(LPASS_CSR_GP_IO_MUX_MIC_CTL , 4));
|
||||
iowrite32(val, vaddr);
|
||||
iounmap(vaddr);
|
||||
vaddr = ioremap(LPASS_CSR_GP_IO_MUX_MIC_CTL , 4);
|
||||
if (!vaddr) {
|
||||
pr_err("%s ioremap failure for addr %x",
|
||||
__func__, LPASS_CSR_GP_IO_MUX_MIC_CTL);
|
||||
return -ENOMEM;
|
||||
}
|
||||
val = ioread32(vaddr);
|
||||
iounmap(vaddr);
|
||||
val = val | 0x00200000;
|
||||
iowrite32(val, ioremap(LPASS_CSR_GP_IO_MUX_MIC_CTL , 4));
|
||||
vaddr = ioremap(LPASS_CSR_GP_IO_MUX_MIC_CTL , 4);
|
||||
if (!vaddr) {
|
||||
pr_err("%s ioremap failure for addr %x",
|
||||
__func__, LPASS_CSR_GP_IO_MUX_MIC_CTL);
|
||||
return -ENOMEM;
|
||||
}
|
||||
iowrite32(val, vaddr);
|
||||
iounmap(vaddr);
|
||||
}
|
||||
ret = msm8x16_enable_codec_ext_clk(codec, 1, true);
|
||||
if (ret < 0) {
|
||||
|
|
Loading…
Reference in a new issue