Merge "asoc: codecs: No I2C activity when EP92 is inactive"
Šī revīzija ir iekļauta:

revīziju iesūtīja
Gerrit - the friendly Code Review server

revīzija
9197a2e94a
@@ -1,6 +1,6 @@
|
||||
// SPDX-License-Identifier: GPL-2.0-only
|
||||
/*
|
||||
* Copyright (c) 2018, The Linux Foundation. All rights reserved.
|
||||
* Copyright (c) 2018-2019, The Linux Foundation. All rights reserved.
|
||||
*/
|
||||
|
||||
#include <linux/init.h>
|
||||
@@ -25,6 +25,7 @@
|
||||
|
||||
#define EP92_POLL_INTERVAL_OFF_MSEC 200
|
||||
#define EP92_POLL_INTERVAL_ON_MSEC 20
|
||||
#define EP92_POLL_RUNOUT_MSEC 5000
|
||||
#define EP92_SYSFS_ENTRY_MAX_LEN 64
|
||||
#define EP92_HYST_CNT 5
|
||||
|
||||
@@ -68,6 +69,9 @@ struct ep92_pdata {
|
||||
struct timer_list timer;
|
||||
struct work_struct read_status_worker;
|
||||
int irq;
|
||||
int poll_trig;
|
||||
int poll_rem;
|
||||
int force_inactive;
|
||||
|
||||
int hyst_tx_plug;
|
||||
int hyst_link_on0;
|
||||
@@ -648,10 +652,8 @@ static int ep92_probe(struct snd_soc_component *component)
|
||||
ep92_init(component, ep92);
|
||||
|
||||
/* start polling when codec is registered */
|
||||
if (ep92->irq == 0) {
|
||||
mod_timer(&ep92->timer, jiffies +
|
||||
msecs_to_jiffies(EP92_POLL_INTERVAL_OFF_MSEC));
|
||||
}
|
||||
mod_timer(&ep92->timer, jiffies +
|
||||
msecs_to_jiffies(EP92_POLL_INTERVAL_OFF_MSEC));
|
||||
|
||||
return 0;
|
||||
}
|
||||
@@ -690,6 +692,9 @@ void ep92_read_status(struct work_struct *work)
|
||||
if (component == NULL)
|
||||
return;
|
||||
|
||||
if (ep92->force_inactive)
|
||||
return;
|
||||
|
||||
/* check ADO_CHF that is set when audio format has changed */
|
||||
val = snd_soc_component_read32(component, EP92_BI_GENERAL_INFO_1);
|
||||
if (val == 0xff) {
|
||||
@@ -724,6 +729,10 @@ static irqreturn_t ep92_irq(int irq, void *data)
|
||||
|
||||
dev_dbg(component->dev, "ep92_interrupt\n");
|
||||
|
||||
ep92->poll_trig = 1;
|
||||
mod_timer(&ep92->timer, jiffies +
|
||||
msecs_to_jiffies(EP92_POLL_INTERVAL_ON_MSEC));
|
||||
|
||||
schedule_work(&ep92->read_status_worker);
|
||||
|
||||
return IRQ_HANDLED;
|
||||
@@ -732,14 +741,45 @@ static irqreturn_t ep92_irq(int irq, void *data)
|
||||
void ep92_poll_status(struct timer_list *t)
|
||||
{
|
||||
struct ep92_pdata *ep92 = from_timer(ep92, t, timer);
|
||||
u32 poll_msec;
|
||||
struct snd_soc_component *component = ep92->component;
|
||||
|
||||
if ((ep92->gc.ctl & EP92_GC_POWER_MASK) == 0)
|
||||
poll_msec = EP92_POLL_INTERVAL_OFF_MSEC;
|
||||
else
|
||||
poll_msec = EP92_POLL_INTERVAL_ON_MSEC;
|
||||
if (ep92->force_inactive)
|
||||
return;
|
||||
|
||||
mod_timer(&ep92->timer, jiffies + msecs_to_jiffies(poll_msec));
|
||||
/* if no IRQ is configured, always keep on polling */
|
||||
if (ep92->irq == 0)
|
||||
ep92->poll_rem = EP92_POLL_RUNOUT_MSEC;
|
||||
|
||||
/* on interrupt, start polling for some time */
|
||||
if (ep92->poll_trig) {
|
||||
if (ep92->poll_rem == 0)
|
||||
dev_info(component->dev, "status checking activated\n");
|
||||
|
||||
ep92->poll_trig = 0;
|
||||
ep92->poll_rem = EP92_POLL_RUNOUT_MSEC;
|
||||
}
|
||||
|
||||
/*
|
||||
* If power_on == 0, poll only until poll_rem reaches zero and stop.
|
||||
* This allows to system to go to low power sleep mode.
|
||||
* Otherwise (power_on == 1) always re-arm timer to keep on polling.
|
||||
*/
|
||||
if ((ep92->gc.ctl & EP92_GC_POWER_MASK) == 0) {
|
||||
if (ep92->poll_rem) {
|
||||
mod_timer(&ep92->timer, jiffies +
|
||||
msecs_to_jiffies(EP92_POLL_INTERVAL_OFF_MSEC));
|
||||
if (ep92->poll_rem > EP92_POLL_INTERVAL_OFF_MSEC) {
|
||||
ep92->poll_rem -= EP92_POLL_INTERVAL_OFF_MSEC;
|
||||
} else {
|
||||
dev_info(component->dev, "status checking stopped\n");
|
||||
ep92->poll_rem = 0;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
ep92->poll_rem = EP92_POLL_RUNOUT_MSEC;
|
||||
mod_timer(&ep92->timer, jiffies +
|
||||
msecs_to_jiffies(EP92_POLL_INTERVAL_ON_MSEC));
|
||||
}
|
||||
|
||||
schedule_work(&ep92->read_status_worker);
|
||||
}
|
||||
@@ -1162,6 +1202,11 @@ static ssize_t ep92_sysfs_wta_power(struct device *dev,
|
||||
ep92->gc.ctl &= ~EP92_GC_POWER_MASK;
|
||||
ep92->gc.ctl |= (val << EP92_GC_POWER_SHIFT) & EP92_GC_POWER_MASK;
|
||||
|
||||
if (val == 1) {
|
||||
ep92->poll_trig = 1;
|
||||
mod_timer(&ep92->timer, jiffies +
|
||||
msecs_to_jiffies(EP92_POLL_INTERVAL_ON_MSEC));
|
||||
}
|
||||
rc = strnlen(buf, EP92_SYSFS_ENTRY_MAX_LEN);
|
||||
end:
|
||||
return rc;
|
||||
@@ -1321,12 +1366,12 @@ static ssize_t ep92_sysfs_wta_arc_enable(struct device *dev,
|
||||
}
|
||||
|
||||
reg = snd_soc_component_read32(ep92->component, EP92_GENERAL_CONTROL_0);
|
||||
reg &= ~EP92_GC_AUDIO_PATH_MASK;
|
||||
reg |= (val << EP92_GC_AUDIO_PATH_SHIFT) & EP92_GC_AUDIO_PATH_MASK;
|
||||
reg &= ~EP92_GC_ARC_EN_MASK;
|
||||
reg |= (val << EP92_GC_ARC_EN_SHIFT) & EP92_GC_ARC_EN_MASK;
|
||||
snd_soc_component_write(ep92->component, EP92_GENERAL_CONTROL_0, reg);
|
||||
ep92->gc.ctl &= ~EP92_GC_AUDIO_PATH_MASK;
|
||||
ep92->gc.ctl |= (val << EP92_GC_AUDIO_PATH_SHIFT) &
|
||||
EP92_GC_AUDIO_PATH_MASK;
|
||||
ep92->gc.ctl &= ~EP92_GC_ARC_EN_MASK;
|
||||
ep92->gc.ctl |= (val << EP92_GC_ARC_EN_SHIFT) &
|
||||
EP92_GC_ARC_EN_MASK;
|
||||
|
||||
rc = strnlen(buf, EP92_SYSFS_ENTRY_MAX_LEN);
|
||||
end:
|
||||
@@ -1440,6 +1485,83 @@ end:
|
||||
return rc;
|
||||
}
|
||||
|
||||
static ssize_t ep92_sysfs_rda_runout(struct device *dev,
|
||||
struct device_attribute *attr, char *buf)
|
||||
{
|
||||
ssize_t ret;
|
||||
int val;
|
||||
struct ep92_pdata *ep92 = dev_get_drvdata(dev);
|
||||
|
||||
if (!ep92 || !ep92->component) {
|
||||
dev_err(dev, "%s: device error\n", __func__);
|
||||
return -ENODEV;
|
||||
}
|
||||
|
||||
val = ep92->poll_rem;
|
||||
|
||||
ret = snprintf(buf, EP92_SYSFS_ENTRY_MAX_LEN, "%d\n", val);
|
||||
dev_dbg(dev, "%s: '%d'\n", __func__, val);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static ssize_t ep92_sysfs_rda_force_inactive(struct device *dev,
|
||||
struct device_attribute *attr, char *buf)
|
||||
{
|
||||
ssize_t ret;
|
||||
int val;
|
||||
struct ep92_pdata *ep92 = dev_get_drvdata(dev);
|
||||
|
||||
if (!ep92 || !ep92->component) {
|
||||
dev_err(dev, "%s: device error\n", __func__);
|
||||
return -ENODEV;
|
||||
}
|
||||
|
||||
val = ep92->force_inactive;
|
||||
|
||||
ret = snprintf(buf, EP92_SYSFS_ENTRY_MAX_LEN, "%d\n", val);
|
||||
dev_dbg(dev, "%s: '%d'\n", __func__, val);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static ssize_t ep92_sysfs_wta_force_inactive(struct device *dev,
|
||||
struct device_attribute *attr, const char *buf, size_t count)
|
||||
{
|
||||
int val, rc;
|
||||
struct ep92_pdata *ep92 = dev_get_drvdata(dev);
|
||||
|
||||
if (!ep92 || !ep92->component) {
|
||||
dev_err(dev, "%s: device error\n", __func__);
|
||||
return -ENODEV;
|
||||
}
|
||||
|
||||
rc = kstrtoint(buf, 10, &val);
|
||||
if (rc) {
|
||||
dev_err(dev, "%s: kstrtoint failed. rc=%d\n", __func__, rc);
|
||||
goto end;
|
||||
}
|
||||
if ((val < 0) || (val > 1)) {
|
||||
dev_err(dev, "%s: value out of range.\n", __func__);
|
||||
rc = -EINVAL;
|
||||
goto end;
|
||||
}
|
||||
|
||||
if (val == 0) {
|
||||
ep92->force_inactive = 0;
|
||||
ep92->poll_trig = 1;
|
||||
mod_timer(&ep92->timer, jiffies +
|
||||
msecs_to_jiffies(EP92_POLL_INTERVAL_ON_MSEC));
|
||||
} else {
|
||||
ep92->force_inactive = 1;
|
||||
ep92->poll_rem = 0;
|
||||
}
|
||||
|
||||
rc = strnlen(buf, EP92_SYSFS_ENTRY_MAX_LEN);
|
||||
end:
|
||||
return rc;
|
||||
}
|
||||
|
||||
static DEVICE_ATTR(chipid, 0444, ep92_sysfs_rda_chipid, NULL);
|
||||
static DEVICE_ATTR(version, 0444, ep92_sysfs_rda_version, NULL);
|
||||
static DEVICE_ATTR(audio_state, 0444, ep92_sysfs_rda_audio_state, NULL);
|
||||
@@ -1467,6 +1589,9 @@ static DEVICE_ATTR(cec_mute, 0644, ep92_sysfs_rda_cec_mute,
|
||||
ep92_sysfs_wta_cec_mute);
|
||||
static DEVICE_ATTR(cec_volume, 0644, ep92_sysfs_rda_cec_volume,
|
||||
ep92_sysfs_wta_cec_volume);
|
||||
static DEVICE_ATTR(runout, 0444, ep92_sysfs_rda_runout, NULL);
|
||||
static DEVICE_ATTR(force_inactive, 0644, ep92_sysfs_rda_force_inactive,
|
||||
ep92_sysfs_wta_force_inactive);
|
||||
|
||||
static struct attribute *ep92_fs_attrs[] = {
|
||||
&dev_attr_chipid.attr,
|
||||
@@ -1490,6 +1615,8 @@ static struct attribute *ep92_fs_attrs[] = {
|
||||
&dev_attr_arc_enable.attr,
|
||||
&dev_attr_cec_mute.attr,
|
||||
&dev_attr_cec_volume.attr,
|
||||
&dev_attr_runout.attr,
|
||||
&dev_attr_force_inactive.attr,
|
||||
NULL,
|
||||
};
|
||||
|
||||
@@ -1552,9 +1679,9 @@ static int ep92_i2c_probe(struct i2c_client *client,
|
||||
ep92->irq = 0;
|
||||
}
|
||||
}
|
||||
/* poll status if IRQ is not configured */
|
||||
if (ep92->irq == 0)
|
||||
timer_setup(&ep92->timer, ep92_poll_status, 0);
|
||||
/* prepare timer */
|
||||
timer_setup(&ep92->timer, ep92_poll_status, 0);
|
||||
ep92->poll_rem = EP92_POLL_RUNOUT_MSEC;
|
||||
|
||||
#if IS_ENABLED(CONFIG_DEBUG_FS)
|
||||
/* debugfs interface */
|
||||
@@ -1610,8 +1737,7 @@ static int ep92_i2c_probe(struct i2c_client *client,
|
||||
err_sysfs:
|
||||
snd_soc_unregister_component(&client->dev);
|
||||
err_reg:
|
||||
if (ep92->irq == 0)
|
||||
del_timer(&ep92->timer);
|
||||
del_timer(&ep92->timer);
|
||||
|
||||
return ret;
|
||||
}
|
||||
@@ -1622,8 +1748,7 @@ static int ep92_i2c_remove(struct i2c_client *client)
|
||||
|
||||
ep92 = i2c_get_clientdata(client);
|
||||
if (ep92) {
|
||||
if (ep92->irq == 0)
|
||||
del_timer(&ep92->timer);
|
||||
del_timer(&ep92->timer);
|
||||
|
||||
#if IS_ENABLED(CONFIG_DEBUG_FS)
|
||||
debugfs_remove_recursive(ep92->debugfs_dir);
|
||||
|
Atsaukties uz šo jaunā problēmā
Block a user