lkml.org 
[lkml]   [2021]   [Jul]   [26]   [last100]   RSS Feed
Views: [wrap][no wrap]   [headers]  [forward] 
 
Messages in this thread
    Patch in this message
    /
    From
    Subject[PATCH 13/27] ALSA: hda/cs8409: Dont disable I2C clock between consecutive accesses
    Date
    From: Lucas Tanure <tanureal@opensource.cirrus.com>

    Only disable I2C clock 25 ms after not being used

    Signed-off-by: Lucas Tanure <tanureal@opensource.cirrus.com>
    Signed-off-by: Vitaly Rodionov <vitalyr@opensource.cirrus.com>
    ---
    sound/pci/hda/patch_cs8409.c | 42 +++++++++++++++++++++++-------------
    sound/pci/hda/patch_cs8409.h | 4 ++++
    2 files changed, 31 insertions(+), 15 deletions(-)

    diff --git a/sound/pci/hda/patch_cs8409.c b/sound/pci/hda/patch_cs8409.c
    index 08205c19698c..335bcdc69106 100644
    --- a/sound/pci/hda/patch_cs8409.c
    +++ b/sound/pci/hda/patch_cs8409.c
    @@ -53,6 +53,7 @@ static struct cs8409_spec *cs8409_alloc_spec(struct hda_codec *codec)
    if (!spec)
    return NULL;
    codec->spec = spec;
    + spec->codec = codec;
    codec->power_save_node = 1;
    snd_hda_gen_spec_init(&spec->gen);

    @@ -72,21 +73,34 @@ static inline void cs8409_vendor_coef_set(struct hda_codec *codec, unsigned int
    snd_hda_codec_write(codec, CS8409_PIN_VENDOR_WIDGET, 0, AC_VERB_SET_PROC_COEF, coef);
    }

    -/**
    +/*
    + * cs8409_disable_i2c_clock - Worker that disable the I2C Clock after 25ms without use
    + */
    +static void cs8409_disable_i2c_clock(struct work_struct *work)
    +{
    + struct cs8409_spec *spec = container_of(work, struct cs8409_spec, i2c_clk_work.work);
    +
    + cs8409_vendor_coef_set(spec->codec, 0x0,
    + cs8409_vendor_coef_get(spec->codec, 0x0) & 0xfffffff7);
    + spec->i2c_clck_enabled = 0;
    +}
    +
    +/*
    * cs8409_enable_i2c_clock - Enable I2C clocks
    * @codec: the codec instance
    - * @enable: Enable or disable I2C clocks
    - *
    * Enable or Disable I2C clocks.
    */
    -static void cs8409_enable_i2c_clock(struct hda_codec *codec, unsigned int enable)
    +static void cs8409_enable_i2c_clock(struct hda_codec *codec)
    {
    - unsigned int retval;
    - unsigned int newval;
    + struct cs8409_spec *spec = codec->spec;
    +
    + cancel_delayed_work_sync(&spec->i2c_clk_work);

    - retval = cs8409_vendor_coef_get(codec, 0x0);
    - newval = (enable) ? (retval | 0x8) : (retval & 0xfffffff7);
    - cs8409_vendor_coef_set(codec, 0x0, newval);
    + if (!spec->i2c_clck_enabled) {
    + cs8409_vendor_coef_set(codec, 0x0, cs8409_vendor_coef_get(codec, 0x0) | 0x8);
    + spec->i2c_clck_enabled = 1;
    + }
    + queue_delayed_work(system_power_efficient_wq, &spec->i2c_clk_work, msecs_to_jiffies(25));
    }

    /**
    @@ -134,7 +148,7 @@ static int cs8409_i2c_read(struct hda_codec *codec, unsigned int i2c_address, un
    if (spec->cs42l42_suspended)
    return -EPERM;

    - cs8409_enable_i2c_clock(codec, 1);
    + cs8409_enable_i2c_clock(codec);
    cs8409_vendor_coef_set(codec, CS8409_I2C_ADDR, i2c_address);

    if (paged) {
    @@ -157,8 +171,6 @@ static int cs8409_i2c_read(struct hda_codec *codec, unsigned int i2c_address, un
    /* Register in bits 15-8 and the data in 7-0 */
    read_data = cs8409_vendor_coef_get(codec, CS8409_I2C_QREAD);

    - cs8409_enable_i2c_clock(codec, 0);
    -
    return read_data & 0x0ff;
    }

    @@ -182,7 +194,7 @@ static int cs8409_i2c_write(struct hda_codec *codec, unsigned int i2c_address, u
    if (spec->cs42l42_suspended)
    return -EPERM;

    - cs8409_enable_i2c_clock(codec, 1);
    + cs8409_enable_i2c_clock(codec);
    cs8409_vendor_coef_set(codec, CS8409_I2C_ADDR, i2c_address);

    if (paged) {
    @@ -203,8 +215,6 @@ static int cs8409_i2c_write(struct hda_codec *codec, unsigned int i2c_address, u
    return -EIO;
    }

    - cs8409_enable_i2c_clock(codec, 0);
    -
    return 0;
    }

    @@ -705,6 +715,8 @@ void cs8409_cs42l42_fixups(struct hda_codec *codec, const struct hda_fixup *fix,
    spec->cs42l42_mic_jack_in = 0;
    spec->cs42l42_suspended = 1;

    + INIT_DELAYED_WORK(&spec->i2c_clk_work, cs8409_disable_i2c_clock);
    +
    /* Basic initial sequence for specific hw configuration */
    snd_hda_sequence_write(codec, cs8409_cs42l42_init_verbs);

    diff --git a/sound/pci/hda/patch_cs8409.h b/sound/pci/hda/patch_cs8409.h
    index bf0e8a4cc4cc..542582c213d2 100644
    --- a/sound/pci/hda/patch_cs8409.h
    +++ b/sound/pci/hda/patch_cs8409.h
    @@ -11,6 +11,7 @@

    #include <linux/pci.h>
    #include <sound/tlv.h>
    +#include <linux/workqueue.h>
    #include <sound/hda_codec.h>
    #include "hda_local.h"
    #include "hda_auto_parser.h"
    @@ -267,6 +268,7 @@ struct cs8409_cir_param {

    struct cs8409_spec {
    struct hda_gen_spec gen;
    + struct hda_codec *codec;

    unsigned int gpio_mask;
    unsigned int gpio_dir;
    @@ -278,6 +280,8 @@ struct cs8409_spec {
    s8 vol[CS42L42_VOLUMES];

    struct mutex cs8409_i2c_mux;
    + unsigned int i2c_clck_enabled;
    + struct delayed_work i2c_clk_work;

    /* verb exec op override */
    int (*exec_verb)(struct hdac_device *dev, unsigned int cmd, unsigned int flags,
    --
    2.25.1
    \
     
     \ /
      Last update: 2021-07-26 20:03    [W:4.127 / U:0.504 seconds]
    ©2003-2020 Jasper Spaans|hosted at Digital Ocean and TransIP|Read the blog|Advertise on this site