>From 757f86c2a501377cc92a51cbbc5b6a6769e658c6 Mon Sep 17 00:00:00 2001 From: Vinod Koul <[email protected]> Date: Wed, 17 Nov 2010 20:00:53 +0530 Subject: [PATCH 1/4] sst: fix audio power optimization of codec
The audio codecs were not powered down when the stream is no longer in use This patch ensure that whenever audio stream is not active the codecs are completely powered off Signed-off-by: Vinod Koul <[email protected]> --- include/sound/intel_sst.h | 4 +- sound/pci/sst/intel_sst_drv_interface.c | 10 +- sound/pci/sst/intelmid_msic_control.c | 273 +++++++++++++++++++++---------- sound/pci/sst/intelmid_v0_control.c | 4 +- sound/pci/sst/intelmid_v1_control.c | 4 +- sound/pci/sst/intelmid_v2_control.c | 4 +- 6 files changed, 200 insertions(+), 99 deletions(-) diff --git a/include/sound/intel_sst.h b/include/sound/intel_sst.h index e6e5191..a8f7941 100644 --- a/include/sound/intel_sst.h +++ b/include/sound/intel_sst.h @@ -103,8 +103,8 @@ struct snd_pmic_ops { int (*power_up_pmic_pb) (unsigned int port); int (*power_up_pmic_cp) (unsigned int port); - int (*power_down_pmic_pb) (void); - int (*power_down_pmic_cp) (void); + int (*power_down_pmic_pb) (unsigned int device); + int (*power_down_pmic_cp) (unsigned int device); int (*power_down_pmic) (void); }; diff --git a/sound/pci/sst/intel_sst_drv_interface.c b/sound/pci/sst/intel_sst_drv_interface.c index 8926fc1..2a9c232 100644 --- a/sound/pci/sst/intel_sst_drv_interface.c +++ b/sound/pci/sst/intel_sst_drv_interface.c @@ -102,21 +102,23 @@ void free_stream_context(unsigned int str_id) if (!sst_validate_strid(str_id)) { /* str_id is valid, so stream is alloacted */ stream = &sst_drv_ctx->streams[str_id]; + if (sst_free_stream(str_id)) + sst_clean_stream(&sst_drv_ctx->streams[str_id]); if (stream->ops == STREAM_OPS_PLAYBACK || stream->ops == STREAM_OPS_PLAYBACK_DRM) { sst_drv_ctx->pb_streams--; if (sst_drv_ctx->pb_streams == 0) - sst_drv_ctx->scard_ops->power_down_pmic_pb(); + sst_drv_ctx->scard_ops->power_down_pmic_pb( + stream->device); } else if (stream->ops == STREAM_OPS_CAPTURE) { sst_drv_ctx->cp_streams--; if (sst_drv_ctx->cp_streams == 0) - sst_drv_ctx->scard_ops->power_down_pmic_cp(); + sst_drv_ctx->scard_ops->power_down_pmic_cp( + stream->device); } if (sst_drv_ctx->pb_streams == 0 && sst_drv_ctx->cp_streams == 0) sst_drv_ctx->scard_ops->power_down_pmic(); - if (sst_free_stream(str_id)) - sst_clean_stream(&sst_drv_ctx->streams[str_id]); } } diff --git a/sound/pci/sst/intelmid_msic_control.c b/sound/pci/sst/intelmid_msic_control.c index 8b48746..37524bb 100644 --- a/sound/pci/sst/intelmid_msic_control.c +++ b/sound/pci/sst/intelmid_msic_control.c @@ -61,17 +61,17 @@ static int msic_init_card(void) {0x27B, 0x01, 0}, {0x27C, 0x0a, 0}, /* Set vol HSLRVOLCTRL, IHFVOL */ - {0x259, 0x04, 0}, - {0x25A, 0x04, 0}, - {0x25B, 0x04, 0}, - {0x25C, 0x04, 0}, + {0x259, 0x08, 0}, + {0x25A, 0x08, 0}, + {0x25B, 0x08, 0}, + {0x25C, 0x08, 0}, /* HSEPRXCTRL Enable the headset left and right FIR filters */ {0x250, 0x30, 0}, /* HSMIXER */ {0x256, 0x11, 0}, /* amic configuration */ - {0x249, 0x09, 0x0}, - {0x24A, 0x09, 0x0}, + {0x249, 0x01, 0x0}, + {0x24A, 0x01, 0x0}, /* unmask ocaudio/accdet interrupts */ {0x1d, 0x00, 0x00}, {0x1e, 0x00, 0x00}, @@ -88,79 +88,84 @@ static int msic_init_card(void) static int msic_power_up_pb(unsigned int device) { - struct sc_reg_access sc_access1[] = { + struct sc_reg_access vaud[] = { /* turn on the audio power supplies */ - {0x0DB, 0x05, 0}, + {0x0DB, 0x07, 0}, + }; + struct sc_reg_access pll[] = { + /* turn on PLL */ + {0x240, 0x20, 0}, + }; + struct sc_reg_access vhs[] = { /* VHSP */ {0x0DC, 0xFF, 0}, /* VHSN */ {0x0DD, 0x3F, 0}, - /* turn on PLL */ - {0x240, 0x21, 0}, }; - struct sc_reg_access sc_access2[] = { + struct sc_reg_access hsdac[] = { /* disable driver */ {0x25D, 0x0, 0x43}, /* DAC CONFIG ; both HP, LP on */ {0x257, 0x03, 0x03}, }; - struct sc_reg_access sc_access3[] = { + struct sc_reg_access hs_filter[] = { /* HSEPRXCTRL Enable the headset left and right FIR filters */ {0x250, 0x30, 0}, /* HSMIXER */ {0x256, 0x11, 0}, }; - struct sc_reg_access sc_access4[] = { + struct sc_reg_access hs_enable[] = { /* enable driver */ {0x25D, 0x3, 0x3}, + {0x26C, 0x0, 0x2}, /* unmute the headset */ { 0x259, 0x80, 0x80}, { 0x25A, 0x80, 0x80}, }; - struct sc_reg_access sc_access_vihf[] = { + struct sc_reg_access vihf[] = { /* VIHF ON */ - {0x0C9, 0x2D, 0x00}, + {0x0C9, 0x27, 0x00}, }; - struct sc_reg_access sc_access22[] = { + struct sc_reg_access ihf_filter[] = { /* disable driver */ {0x25D, 0x00, 0x0C}, /*Filer DAC enable*/ {0x251, 0x03, 0x03}, {0x257, 0x0C, 0x0C}, }; - struct sc_reg_access sc_access32[] = { + struct sc_reg_access ihf_en[] = { /*enable drv*/ {0x25D, 0x0C, 0x0c}, }; - struct sc_reg_access sc_access42[] = { + struct sc_reg_access ihf_unmute[] = { /*unmute headset*/ {0x25B, 0x80, 0x80}, {0x25C, 0x80, 0x80}, }; - struct sc_reg_access sc_access23[] = { + struct sc_reg_access epdac[] = { /* disable driver */ {0x25D, 0x0, 0x43}, /* DAC CONFIG ; both HP, LP on */ {0x257, 0x03, 0x03}, }; - struct sc_reg_access sc_access43[] = { + struct sc_reg_access ep_enable[] = { /* enable driver */ {0x25D, 0x40, 0x40}, /* unmute the headset */ { 0x259, 0x80, 0x80}, { 0x25A, 0x80, 0x80}, }; - struct sc_reg_access sc_access_vib[] = { + struct sc_reg_access vib1_en[] = { /* enable driver, ADC */ {0x25D, 0x10, 0x10}, {0x264, 0x02, 0x02}, }; - struct sc_reg_access sc_access_hap[] = { + struct sc_reg_access vib2_en[] = { /* enable driver, ADC */ {0x25D, 0x20, 0x20}, {0x26A, 0x02, 0x02}, }; - struct sc_reg_access sc_access_pcm2[] = { + struct sc_reg_access pcm2_en[] = { /* enable pcm 2 */ {0x27C, 0x1, 0x1}, }; @@ -173,89 +178,84 @@ static int msic_power_up_pb(unsigned int device) } pr_debug("sst: powering up pb.... Device %d\n", device); - sst_sc_reg_access(sc_access1, PMIC_WRITE, 4); + sst_sc_reg_access(vaud, PMIC_WRITE, 1); + msleep(1); + sst_sc_reg_access(pll, PMIC_WRITE, 1); + msleep(1); switch (device) { case SND_SST_DEVICE_HEADSET: if (snd_msic_ops.output_dev_id == STEREO_HEADPHONE) { - sst_sc_reg_access(sc_access2, PMIC_READ_MODIFY, 2); - sst_sc_reg_access(sc_access3, PMIC_WRITE, 2); - sst_sc_reg_access(sc_access4, PMIC_READ_MODIFY, 3); + sst_sc_reg_access(vhs, PMIC_WRITE, 2); + sst_sc_reg_access(hsdac, PMIC_READ_MODIFY, 2); + sst_sc_reg_access(hs_filter, PMIC_WRITE, 2); + sst_sc_reg_access(hs_enable, PMIC_READ_MODIFY, 4); } else { - sst_sc_reg_access(sc_access23, PMIC_READ_MODIFY, 2); - sst_sc_reg_access(sc_access3, PMIC_WRITE, 2); - sst_sc_reg_access(sc_access43, PMIC_READ_MODIFY, 3); + sst_sc_reg_access(epdac, PMIC_READ_MODIFY, 2); + sst_sc_reg_access(hs_filter, PMIC_WRITE, 2); + sst_sc_reg_access(ep_enable, PMIC_READ_MODIFY, 3); } snd_msic_ops.pb_on = 1; break; case SND_SST_DEVICE_IHF: - sst_sc_reg_access(sc_access_vihf, PMIC_WRITE, 1); - sst_sc_reg_access(sc_access22, PMIC_READ_MODIFY, 3); - sst_sc_reg_access(sc_access32, PMIC_READ_MODIFY, 1); - sst_sc_reg_access(sc_access42, PMIC_READ_MODIFY, 2); + sst_sc_reg_access(vihf, PMIC_WRITE, 1); + sst_sc_reg_access(ihf_filter, PMIC_READ_MODIFY, 3); + sst_sc_reg_access(ihf_en, PMIC_READ_MODIFY, 1); + sst_sc_reg_access(ihf_unmute, PMIC_READ_MODIFY, 2); break; case SND_SST_DEVICE_VIBRA: - sst_sc_reg_access(sc_access_vib, PMIC_READ_MODIFY, 2); + sst_sc_reg_access(vib1_en, PMIC_READ_MODIFY, 2); break; case SND_SST_DEVICE_HAPTIC: - sst_sc_reg_access(sc_access_hap, PMIC_READ_MODIFY, 2); + sst_sc_reg_access(vib2_en, PMIC_READ_MODIFY, 2); break; default: pr_warn("sst: Wrong Device %d, selected %d\n", device, snd_msic_ops.output_dev_id); } - return sst_sc_reg_access(sc_access_pcm2, PMIC_READ_MODIFY, 1); + return sst_sc_reg_access(pcm2_en, PMIC_READ_MODIFY, 1); } static int msic_power_up_cp(unsigned int device) { - struct sc_reg_access sc_access[] = { + struct sc_reg_access vaud[] = { /* turn on the audio power supplies */ - {0x0DB, 0x05, 0}, - /* VHSP */ - {0x0DC, 0xFF, 0}, - /* VHSN */ - {0x0DD, 0x3F, 0}, + {0x0DB, 0x07, 0}, + }; + struct sc_reg_access pll[] = { /* turn on PLL */ - {0x240, 0x21, 0}, - - /* Turn on DMIC supply */ - {0x247, 0xA0, 0x0}, - {0x240, 0x21, 0x0}, - {0x24C, 0x10, 0x0}, - + {0x240, 0x20, 0}, + }; + struct sc_reg_access dmic_bias[] = { + /* Turn on AMIC supply */ + {0x247, 0xA0, 0xA0}, + }; + struct sc_reg_access dmic[] = { /* mic demux enable */ - {0x245, 0x3F, 0x0}, - {0x246, 0x7, 0x0}, + {0x245, 0x3F, 0x3F}, + {0x246, 0x07, 0x07}, }; - struct sc_reg_access sc_access_amic[] = { - /* turn on the audio power supplies */ - {0x0DB, 0x05, 0}, - /* VHSP */ - {0x0DC, 0xFF, 0}, - /* VHSN */ - {0x0DD, 0x3F, 0}, - /* turn on PLL */ - {0x240, 0x21, 0}, - /*ADC EN*/ - {0x248, 0x05, 0x0}, - {0x24C, 0x76, 0x0}, - /*MIC EN*/ - {0x249, 0x09, 0x0}, - {0x24A, 0x09, 0x0}, + struct sc_reg_access amic_bias[] = { /* Turn on AMIC supply */ - {0x247, 0xFC, 0x0}, + {0x247, 0xFC, 0xFC}, + }; + struct sc_reg_access amic[] = { + /*MIC EN*/ + {0x249, 0x01, 0x01}, + {0x24A, 0x01, 0x01}, + /*ADC EN*/ + {0x248, 0x05, 0x0F}, }; - struct sc_reg_access sc_access2[] = { + struct sc_reg_access pcm2[] = { /* enable pcm 2 */ {0x27C, 0x1, 0x1}, }; - struct sc_reg_access sc_access3[] = { + struct sc_reg_access tx_on[] = { /*wait for mic to stabalize before turning on audio channels*/ {0x24F, 0x3C, 0x0}, }; @@ -268,42 +268,141 @@ static int msic_power_up_cp(unsigned int device) } pr_debug("sst: powering up cp....%d\n", snd_msic_ops.input_dev_id); - sst_sc_reg_access(sc_access2, PMIC_READ_MODIFY, 1); + sst_sc_reg_access(vaud, PMIC_WRITE, 1); + msleep(500);/*FIXME need optimzed value here*/ + sst_sc_reg_access(pll, PMIC_WRITE, 1); + msleep(1); snd_msic_ops.cap_on = 1; - if (snd_msic_ops.input_dev_id == AMIC) - sst_sc_reg_access(sc_access_amic, PMIC_WRITE, 9); - else - sst_sc_reg_access(sc_access, PMIC_WRITE, 9); - return sst_sc_reg_access(sc_access3, PMIC_WRITE, 1); - + if (snd_msic_ops.input_dev_id == AMIC) { + sst_sc_reg_access(amic_bias, PMIC_READ_MODIFY, 1); + msleep(1); + sst_sc_reg_access(amic, PMIC_READ_MODIFY, 3); + } else { + sst_sc_reg_access(dmic_bias, PMIC_READ_MODIFY, 1); + msleep(1); + sst_sc_reg_access(dmic, PMIC_READ_MODIFY, 2); + } + msleep(1); + sst_sc_reg_access(tx_on, PMIC_WRITE, 1); + return sst_sc_reg_access(pcm2, PMIC_READ_MODIFY, 1); } static int msic_power_down(void) { - int retval = 0; + struct sc_reg_access power_dn[] = { + /* VHSP */ + {0x0DC, 0xC4, 0}, + /* VHSN */ + {0x0DD, 0x04, 0}, + /* VIHF */ + {0x0C9, 0x24, 0}, + }; + struct sc_reg_access pll[] = { + /* turn off PLL*/ + {0x240, 0x00, 0x0}, + }; + struct sc_reg_access vaud[] = { + /* turn off VAUD*/ + {0x0DB, 0x04, 0}, + }; pr_debug("sst: powering dn msic\n"); snd_msic_ops.pb_on = 0; snd_msic_ops.cap_on = 0; - return retval; + sst_sc_reg_access(power_dn, PMIC_WRITE, 3); + msleep(1); + sst_sc_reg_access(pll, PMIC_WRITE, 1); + msleep(1); + sst_sc_reg_access(vaud, PMIC_WRITE, 1); + return 0; } -static int msic_power_down_pb(void) +static int msic_power_down_pb(unsigned int device) { - int retval = 0; + struct sc_reg_access drv_enable[] = { + {0x25D, 0x00, 0x00}, + }; + struct sc_reg_access hs_mute[] = { + {0x259, 0x80, 0x80}, + {0x25A, 0x80, 0x80}, + {0x26C, 0x02, 0x02}, + }; + struct sc_reg_access hs_off[] = { + {0x257, 0x00, 0x03}, + {0x250, 0x00, 0x30}, + }; + struct sc_reg_access ihf_mute[] = { + {0x25B, 0x80, 0x80}, + {0x25C, 0x80, 0x80}, + }; + struct sc_reg_access ihf_off[] = { + {0x257, 0x00, 0x0C}, + {0x251, 0x00, 0x03}, + }; + struct sc_reg_access vib1_off[] = { + {0x264, 0x00, 0x82}, + }; + struct sc_reg_access vib2_off[] = { + {0x26A, 0x00, 0x82}, + }; - pr_debug("sst: powering dn pb....\n"); - snd_msic_ops.pb_on = 0; - return retval; + pr_debug("sst: powering dn pb for device %d\n", device); + switch (device) { + case SND_SST_DEVICE_HEADSET: + snd_msic_ops.pb_on = 0; + sst_sc_reg_access(hs_mute, PMIC_READ_MODIFY, 3); + drv_enable[0].mask = 0x43; + sst_sc_reg_access(drv_enable, PMIC_READ_MODIFY, 1); + sst_sc_reg_access(hs_off, PMIC_READ_MODIFY, 2); + break; + + case SND_SST_DEVICE_IHF: + sst_sc_reg_access(ihf_mute, PMIC_READ_MODIFY, 2); + drv_enable[0].mask = 0x0C; + sst_sc_reg_access(drv_enable, PMIC_READ_MODIFY, 1); + sst_sc_reg_access(ihf_off, PMIC_READ_MODIFY, 2); + break; + + case SND_SST_DEVICE_VIBRA: + sst_sc_reg_access(vib1_off, PMIC_READ_MODIFY, 2); + drv_enable[0].mask = 0x10; + sst_sc_reg_access(drv_enable, PMIC_READ_MODIFY, 1); + break; + + case SND_SST_DEVICE_HAPTIC: + sst_sc_reg_access(vib2_off, PMIC_READ_MODIFY, 2); + drv_enable[0].mask = 0x20; + sst_sc_reg_access(drv_enable, PMIC_READ_MODIFY, 1); + break; + } + return 0; } -static int msic_power_down_cp(void) +static int msic_power_down_cp(unsigned int device) { - int retval = 0; + struct sc_reg_access dmic[] = { + {0x247, 0x00, 0xA0}, + {0x245, 0x00, 0x38}, + {0x246, 0x00, 0x07}, + }; + struct sc_reg_access amic[] = { + {0x248, 0x00, 0x05}, + {0x249, 0x00, 0x01}, + {0x24A, 0x00, 0x01}, + {0x247, 0x00, 0xA3}, + }; + struct sc_reg_access tx_off[] = { + {0x24F, 0x00, 0x3C}, + }; pr_debug("sst: powering dn cp....\n"); snd_msic_ops.cap_on = 0; - return retval; + sst_sc_reg_access(tx_off, PMIC_READ_MODIFY, 1); + if (snd_msic_ops.input_dev_id == DMIC) + sst_sc_reg_access(dmic, PMIC_READ_MODIFY, 3); + else + sst_sc_reg_access(amic, PMIC_READ_MODIFY, 4); + return 0; } static int msic_set_selected_output_dev(u8 value) diff --git a/sound/pci/sst/intelmid_v0_control.c b/sound/pci/sst/intelmid_v0_control.c index 85265d3..00241fa 100644 --- a/sound/pci/sst/intelmid_v0_control.c +++ b/sound/pci/sst/intelmid_v0_control.c @@ -155,7 +155,7 @@ static int fs_power_up_pb(unsigned int port) return fs_enable_audiodac(UNMUTE); } -static int fs_power_down_pb(void) +static int fs_power_down_pb(unsigned int device) { struct sc_reg_access sc_access[] = { {POWERCTRL1, 0x00, 0xC6}, @@ -193,7 +193,7 @@ static int fs_power_up_cp(unsigned int port) return sst_sc_reg_access(sc_access, PMIC_READ_MODIFY, 2); } -static int fs_power_down_cp(void) +static int fs_power_down_cp(unsigned int device) { struct sc_reg_access sc_access[] = { {POWERCTRL2, 0x00, 0x03}, diff --git a/sound/pci/sst/intelmid_v1_control.c b/sound/pci/sst/intelmid_v1_control.c index a8c7629..959b218 100644 --- a/sound/pci/sst/intelmid_v1_control.c +++ b/sound/pci/sst/intelmid_v1_control.c @@ -322,7 +322,7 @@ static int mx_power_up_pb(unsigned int port) return mx_enable_audiodac(UNMUTE); } -static int mx_power_down_pb(void) +static int mx_power_down_pb(unsigned int device) { struct sc_reg_access sc_access[3]; int retval = 0; @@ -371,7 +371,7 @@ static int mx_power_up_cp(unsigned int port) return sst_sc_reg_access(sc_access, PMIC_READ_MODIFY, 2); } -static int mx_power_down_cp(void) +static int mx_power_down_cp(unsigned int device) { struct sc_reg_access sc_access[] = { {ENABLE_OPDEV_CTRL, 0x00, MASK1|MASK0}, diff --git a/sound/pci/sst/intelmid_v2_control.c b/sound/pci/sst/intelmid_v2_control.c index 8462ce1..3aede20 100644 --- a/sound/pci/sst/intelmid_v2_control.c +++ b/sound/pci/sst/intelmid_v2_control.c @@ -313,7 +313,7 @@ static int nc_power_down(void) return nc_enable_audiodac(UNMUTE); } -static int nc_power_down_pb(void) +static int nc_power_down_pb(unsigned int device) { int retval = 0; @@ -357,7 +357,7 @@ static int nc_power_down_pb(void) } -static int nc_power_down_cp(void) +static int nc_power_down_cp(unsigned int device) { struct sc_reg_access sc_access[] = { {POWERCTRL1, 0x00, 0xBE}, -- 1.7.2.3
0001-sst-fix-audio-power-optimzation-of-codec.patch
Description: 0001-sst-fix-audio-power-optimzation-of-codec.patch
_______________________________________________ MeeGo-kernel mailing list [email protected] http://lists.meego.com/listinfo/meego-kernel
