Loading asoc/codecs/ep92/ep92.c +148 −23 Original line number Diff line number Diff line // 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> Loading @@ -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 Loading Loading @@ -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; Loading Loading @@ -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)); } return 0; } Loading Loading @@ -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) { Loading Loading @@ -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; Loading @@ -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; /* if no IRQ is configured, always keep on polling */ if (ep92->irq == 0) ep92->poll_rem = EP92_POLL_RUNOUT_MSEC; mod_timer(&ep92->timer, jiffies + msecs_to_jiffies(poll_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); } Loading Loading @@ -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; Loading Loading @@ -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: Loading Loading @@ -1440,6 +1485,83 @@ static ssize_t ep92_sysfs_wta_cec_volume(struct device *dev, 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); Loading Loading @@ -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, Loading @@ -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, }; Loading Loading @@ -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) /* 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 */ Loading Loading @@ -1610,7 +1737,6 @@ 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); return ret; Loading @@ -1622,7 +1748,6 @@ static int ep92_i2c_remove(struct i2c_client *client) ep92 = i2c_get_clientdata(client); if (ep92) { if (ep92->irq == 0) del_timer(&ep92->timer); #if IS_ENABLED(CONFIG_DEBUG_FS) Loading Loading
asoc/codecs/ep92/ep92.c +148 −23 Original line number Diff line number Diff line // 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> Loading @@ -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 Loading Loading @@ -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; Loading Loading @@ -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)); } return 0; } Loading Loading @@ -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) { Loading Loading @@ -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; Loading @@ -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; /* if no IRQ is configured, always keep on polling */ if (ep92->irq == 0) ep92->poll_rem = EP92_POLL_RUNOUT_MSEC; mod_timer(&ep92->timer, jiffies + msecs_to_jiffies(poll_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); } Loading Loading @@ -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; Loading Loading @@ -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: Loading Loading @@ -1440,6 +1485,83 @@ static ssize_t ep92_sysfs_wta_cec_volume(struct device *dev, 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); Loading Loading @@ -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, Loading @@ -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, }; Loading Loading @@ -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) /* 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 */ Loading Loading @@ -1610,7 +1737,6 @@ 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); return ret; Loading @@ -1622,7 +1748,6 @@ static int ep92_i2c_remove(struct i2c_client *client) ep92 = i2c_get_clientdata(client); if (ep92) { if (ep92->irq == 0) del_timer(&ep92->timer); #if IS_ENABLED(CONFIG_DEBUG_FS) Loading