]> xenbits.xensource.com Git - people/aperard/linux-chromebook.git/commitdiff
CHROMIUM: ALSA: hda/ca0132 - Add thorough codec init.
authorChee Kin Cheong <chee_kin@ctl.creative.com>
Wed, 19 Dec 2012 16:49:06 +0000 (08:49 -0800)
committerDylan Reid <dgreid@chromium.org>
Fri, 11 Jan 2013 00:46:27 +0000 (16:46 -0800)
During ca0132_init, check that the codec is ready and if not, reset
and re-initialize.

BUG=chrome-os-partner:14465
TEST=suspend/resume and play youtube.

Change-Id: I70a406042cfb8af80e9d0835d136be2df33f5b28
Signed-off-by: Dylan Reid <dgreid@chromium.org>
Reviewed-on: https://gerrit.chromium.org/gerrit/39981
Reviewed-by: Chih-Chung Chang <chihchung@chromium.org>
(cherry picked from commit 63ce7c56ac8a9dc1135140726f218d22232a5451)
Reviewed-on: https://gerrit.chromium.org/gerrit/41072

sound/pci/hda/patch_ca0132.c

index cec8ee24d6cfb9512c8b97dbcf39ef0a3baa3883..1fc82d308dec996458c8d6a0790211c504f11734 100644 (file)
@@ -3444,8 +3444,8 @@ static int stop_mic1(struct hda_codec *codec)
                                                 AC_VERB_GET_CONV, 0);
        if (oldval != 0)
                snd_hda_codec_write(codec, spec->adcs[0], 0,
-                               AC_VERB_SET_CHANNEL_STREAMID,
-                               0);
+                                   AC_VERB_SET_CHANNEL_STREAMID,
+                                   0);
        return oldval;
 }
 
@@ -4475,6 +4475,155 @@ static void ca0132_exit_chip(struct hda_codec *codec)
                dsp_reset(codec);
 }
 
+static int xdata_read(struct hda_codec *codec, u16 addr)
+{
+       struct ca0132_spec *spec = codec->spec;
+       int data;
+
+       mutex_lock(&spec->chipio_mutex);
+       snd_hda_codec_write(codec, WIDGET_CHIP_CTRL, 0,
+                           VENDOR_CHIPIO_8051_ADDRESS_LOW, addr & 0xFF);
+       snd_hda_codec_write(codec, WIDGET_CHIP_CTRL, 0,
+                           VENDOR_CHIPIO_8051_ADDRESS_HIGH,
+                           (addr >> 8) & 0xFF);
+       data = snd_hda_codec_read(codec, WIDGET_CHIP_CTRL, 0,
+                           VENDOR_CHIPIO_8051_DATA_READ, 0);
+       mutex_unlock(&spec->chipio_mutex);
+
+       return data;
+}
+
+static int xdata_write(struct hda_codec *codec, u16 addr, u8 value)
+{
+       struct ca0132_spec *spec = codec->spec;
+
+       mutex_lock(&spec->chipio_mutex);
+       snd_hda_codec_write(codec, WIDGET_CHIP_CTRL, 0,
+                           VENDOR_CHIPIO_8051_ADDRESS_LOW, addr & 0xFF);
+       snd_hda_codec_write(codec, WIDGET_CHIP_CTRL, 0,
+                           VENDOR_CHIPIO_8051_ADDRESS_HIGH,
+                           (addr >> 8) & 0xFF);
+       snd_hda_codec_write(codec, WIDGET_CHIP_CTRL, 0,
+                           VENDOR_CHIPIO_8051_DATA_WRITE, value);
+       mutex_unlock(&spec->chipio_mutex);
+
+       return 0;
+}
+
+static int idata_read(struct hda_codec *codec, u16 addr)
+{
+       struct ca0132_spec *spec = codec->spec;
+       int data;
+
+       mutex_lock(&spec->chipio_mutex);
+       snd_hda_codec_write(codec, WIDGET_CHIP_CTRL, 0,
+                           VENDOR_CHIPIO_8051_ADDRESS_LOW, addr & 0xFF);
+       snd_hda_codec_write(codec, WIDGET_CHIP_CTRL, 0,
+                           VENDOR_CHIPIO_8051_ADDRESS_HIGH,
+                           (addr >> 8) & 0xFF);
+       data = snd_hda_codec_read(codec, WIDGET_CHIP_CTRL, 0,
+                           0xF09, 0);
+       mutex_unlock(&spec->chipio_mutex);
+
+       return data;
+}
+
+static int idata_write(struct hda_codec *codec, u16 addr, u8 value)
+{
+       struct ca0132_spec *spec = codec->spec;
+
+       mutex_lock(&spec->chipio_mutex);
+       snd_hda_codec_write(codec, WIDGET_CHIP_CTRL, 0,
+                           VENDOR_CHIPIO_8051_ADDRESS_LOW, addr & 0xFF);
+       snd_hda_codec_write(codec, WIDGET_CHIP_CTRL, 0,
+                           VENDOR_CHIPIO_8051_ADDRESS_HIGH,
+                           (addr >> 8) & 0xFF);
+       snd_hda_codec_write(codec, WIDGET_CHIP_CTRL, 0,
+                           0x709, value);
+       mutex_unlock(&spec->chipio_mutex);
+
+       return 0;
+}
+
+static int pmu_read(struct hda_codec *codec, u8 addr)
+{
+       struct ca0132_spec *spec = codec->spec;
+       int data;
+
+       mutex_lock(&spec->chipio_mutex);
+       snd_hda_codec_write(codec, WIDGET_CHIP_CTRL, 0,
+                           VENDOR_CHIPIO_8051_ADDRESS_LOW, addr);
+       data = snd_hda_codec_read(codec, WIDGET_CHIP_CTRL, 0,
+                           VENDOR_CHIPIO_PLL_PMU_READ, 0);
+       mutex_unlock(&spec->chipio_mutex);
+
+       return data;
+}
+
+static int pmu_write(struct hda_codec *codec, u8 addr, u8 value)
+{
+       struct ca0132_spec *spec = codec->spec;
+
+       mutex_lock(&spec->chipio_mutex);
+       snd_hda_codec_write(codec, WIDGET_CHIP_CTRL, 0,
+                           VENDOR_CHIPIO_8051_ADDRESS_LOW, addr);
+       snd_hda_codec_write(codec, WIDGET_CHIP_CTRL, 0,
+                           VENDOR_CHIPIO_PLL_PMU_WRITE, value);
+       mutex_unlock(&spec->chipio_mutex);
+
+       return 0;
+}
+
+static int ca0132_init_codec(struct hda_codec *codec)
+{
+       u8 codecDevices[] = {
+               1, 2, 3, 6, 8, 10, 11
+       };
+       bool codec_ready = true;
+       int retryCount = 3;
+       int tryCount = 5;
+       int i;
+       int codecStateAddr = 0x18BE;
+       int addr;
+       int data;
+
+       do {
+               codec_ready = true;
+               for (i = 0; i < ARRAY_SIZE(codecDevices); i++) {
+                       addr = codecStateAddr + 13 * codecDevices[i] + 8;
+                       data = xdata_read(codec, addr);
+                       if ((data > 0) && (data & 0x4))
+                               codec_ready = false;
+               }
+
+               if (!codec_ready) {
+                       snd_hda_codec_write(codec, 1, 0,
+                                           AC_VERB_SET_POWER_STATE, 4);
+
+                       data = pmu_read(codec, 0xF);
+                       pmu_write(codec, 0xF, data & ~0x88);
+                       msleep(100);
+                       pmu_write(codec, 0xF, data | 0x88);
+                       msleep(100);
+                       xdata_write(codec, 0xB6, 0x1);
+                       xdata_write(codec, 0x1F07, 0xF9);
+                       xdata_write(codec, 0x1F08, 0x72);
+                       idata_write(codec, 0x7D, 0x40);
+
+                       do {
+                               data = xdata_read(codec, 0xB6);
+                               msleep(100);
+                       } while (data != 0 && --tryCount);
+
+                       snd_hda_codec_write(codec, 1, 0,
+                                           AC_VERB_SET_POWER_STATE, 0);
+                       msleep(500);
+               }
+       } while (!codec_ready && --retryCount);
+
+       return 0;
+}
+
 static int ca0132_init(struct hda_codec *codec)
 {
        struct ca0132_spec *spec = codec->spec;
@@ -4485,9 +4634,10 @@ static int ca0132_init(struct hda_codec *codec)
 
        snd_hda_power_up(codec);
 
+       snd_hda_sequence_write(codec, spec->base_init_verbs);
+       ca0132_init_codec(codec);
        ca0132_init_params(codec);
        ca0132_init_flags(codec);
-       snd_hda_sequence_write(codec, spec->base_init_verbs);
        ca0132_download_dsp(codec);
        ca0132_refresh_widget_caps(codec);
        ca0132_setup_defaults(codec);