[ALSA] hda - Fix resume of auto-config mode with Realtek codecs
[safe/jmp/linux-2.6] / sound / pci / hda / hda_codec.h
index ef94c91..dcd390b 100644 (file)
 #include <sound/pcm.h>
 #include <sound/hwdep.h>
 
+#if defined(CONFIG_PM) || defined(CONFIG_SND_HDA_POWER_SAVE)
+#define SND_HDA_NEEDS_RESUME   /* resume control code is required */
+#endif
+
 /*
  * nodes
  */
@@ -73,12 +77,16 @@ enum {
 #define AC_VERB_GET_PIN_SENSE                  0x0f09
 #define AC_VERB_GET_BEEP_CONTROL               0x0f0a
 #define AC_VERB_GET_EAPD_BTLENABLE             0x0f0c
-#define AC_VERB_GET_DIGI_CONVERT               0x0f0d
+#define AC_VERB_GET_DIGI_CONVERT_1             0x0f0d
+#define AC_VERB_GET_DIGI_CONVERT_2             0x0f0e
 #define AC_VERB_GET_VOLUME_KNOB_CONTROL                0x0f0f
 /* f10-f1a: GPIO */
 #define AC_VERB_GET_GPIO_DATA                  0x0f15
 #define AC_VERB_GET_GPIO_MASK                  0x0f16
 #define AC_VERB_GET_GPIO_DIRECTION             0x0f17
+#define AC_VERB_GET_GPIO_WAKE_MASK             0x0f18
+#define AC_VERB_GET_GPIO_UNSOLICITED_RSP_MASK  0x0f19
+#define AC_VERB_GET_GPIO_STICKY_MASK           0x0f1a
 #define AC_VERB_GET_CONFIG_DEFAULT             0x0f1c
 /* f20: AFG/MFG */
 #define AC_VERB_GET_SUBSYSTEM_ID               0x0f20
@@ -106,6 +114,9 @@ enum {
 #define AC_VERB_SET_GPIO_DATA                  0x715
 #define AC_VERB_SET_GPIO_MASK                  0x716
 #define AC_VERB_SET_GPIO_DIRECTION             0x717
+#define AC_VERB_SET_GPIO_WAKE_MASK             0x718
+#define AC_VERB_SET_GPIO_UNSOLICITED_RSP_MASK  0x719
+#define AC_VERB_SET_GPIO_STICKY_MASK           0x71a
 #define AC_VERB_SET_CONFIG_DEFAULT_BYTES_0     0x71c
 #define AC_VERB_SET_CONFIG_DEFAULT_BYTES_1     0x71d
 #define AC_VERB_SET_CONFIG_DEFAULT_BYTES_2     0x71e
@@ -131,6 +142,7 @@ enum {
 #define AC_PAR_PROC_CAP                        0x10
 #define AC_PAR_GPIO_CAP                        0x11
 #define AC_PAR_AMP_OUT_CAP             0x12
+#define AC_PAR_VOL_KNB_CAP             0x13
 
 /*
  * AC_VERB_PARAMETERS results (32bit)
@@ -177,6 +189,27 @@ enum {
 #define AC_SUPFMT_FLOAT32              (1<<1)
 #define AC_SUPFMT_AC3                  (1<<2)
 
+/* GP I/O count */
+#define AC_GPIO_IO_COUNT               (0xff<<0)
+#define AC_GPIO_O_COUNT                        (0xff<<8)
+#define AC_GPIO_O_COUNT_SHIFT          8
+#define AC_GPIO_I_COUNT                        (0xff<<16)
+#define AC_GPIO_I_COUNT_SHIFT          16
+#define AC_GPIO_UNSOLICITED            (1<<30)
+#define AC_GPIO_WAKE                   (1<<31)
+
+/* Converter stream, channel */
+#define AC_CONV_CHANNEL                        (0xf<<0)
+#define AC_CONV_STREAM                 (0xf<<4)
+#define AC_CONV_STREAM_SHIFT           4
+
+/* Input converter SDI select */
+#define AC_SDI_SELECT                  (0xf<<0)
+
+/* Unsolicited response */
+#define AC_UNSOL_TAG                   (0x3f<<0)
+#define AC_UNSOL_ENABLED               (1<<7)
+
 /* Pin widget capabilies */
 #define AC_PINCAP_IMP_SENSE            (1<<0)  /* impedance sense capable */
 #define AC_PINCAP_TRIG_REQ             (1<<1)  /* trigger required */
@@ -185,6 +218,10 @@ enum {
 #define AC_PINCAP_OUT                  (1<<4)  /* output capable */
 #define AC_PINCAP_IN                   (1<<5)  /* input capable */
 #define AC_PINCAP_BALANCE              (1<<6)  /* balanced I/O capable */
+/* Note: This LR_SWAP pincap is defined in the Realtek ALC883 specification,
+ *       but is marked reserved in the Intel HDA specification.
+ */
+#define AC_PINCAP_LR_SWAP              (1<<7)  /* L/R swap */
 #define AC_PINCAP_VREF                 (0x37<<8)
 #define AC_PINCAP_VREF_SHIFT           8
 #define AC_PINCAP_EAPD                 (1<<16) /* EAPD capable */
@@ -218,6 +255,9 @@ enum {
 #define AC_PWRST_D3SUP                 (1<<3)
 
 /* Power state values */
+#define AC_PWRST_SETTING               (0xf<<0)
+#define AC_PWRST_ACTUAL                        (0xf<<4)
+#define AC_PWRST_ACTUAL_SHIFT          4
 #define AC_PWRST_D0                    0x00
 #define AC_PWRST_D1                    0x01
 #define AC_PWRST_D2                    0x02
@@ -226,10 +266,11 @@ enum {
 /* Processing capabilies */
 #define AC_PCAP_BENIGN                 (1<<0)
 #define AC_PCAP_NUM_COEF               (0xff<<8)
+#define AC_PCAP_NUM_COEF_SHIFT         8
 
 /* Volume knobs capabilities */
 #define AC_KNBCAP_NUM_STEPS            (0x7f<<0)
-#define AC_KNBCAP_DELTA                        (1<<8)
+#define AC_KNBCAP_DELTA                        (1<<7)
 
 /*
  * Control Parameters
@@ -262,6 +303,9 @@ enum {
 #define AC_DIG1_PROFESSIONAL           (1<<6)
 #define AC_DIG1_LEVEL                  (1<<7)
 
+/* DIGITAL2 bits */
+#define AC_DIG2_CC                     (0x7f<<0)
+
 /* Pin widget control - 8bit */
 #define AC_PINCTL_VREFEN               (0x7<<0)
 #define AC_PINCTL_VREF_HIZ             0       /* Hi-Z */
@@ -276,12 +320,22 @@ enum {
 /* Unsolicited response - 8bit */
 #define AC_USRSP_EN                    (1<<7)
 
+/* Pin sense - 32bit */
+#define AC_PINSENSE_IMPEDANCE_MASK     (0x7fffffff)
+#define AC_PINSENSE_PRESENCE           (1<<31)
+
+/* EAPD/BTL enable - 32bit */
+#define AC_EAPDBTL_BALANCED            (1<<0)
+#define AC_EAPDBTL_EAPD                        (1<<1)
+#define AC_EAPDBTL_LR_SWAP             (1<<2)
+
 /* configuration default - 32bit */
 #define AC_DEFCFG_SEQUENCE             (0xf<<0)
 #define AC_DEFCFG_DEF_ASSOC            (0xf<<4)
 #define AC_DEFCFG_ASSOC_SHIFT          4
 #define AC_DEFCFG_MISC                 (0xf<<8)
 #define AC_DEFCFG_MISC_SHIFT           8
+#define AC_DEFCFG_MISC_NO_PRESENCE     (1<<0)
 #define AC_DEFCFG_COLOR                        (0xf<<12)
 #define AC_DEFCFG_COLOR_SHIFT          12
 #define AC_DEFCFG_CONN_TYPE            (0xf<<16)
@@ -412,6 +466,10 @@ struct hda_bus_ops {
        unsigned int (*get_response)(struct hda_codec *codec);
        /* free the private data */
        void (*private_free)(struct hda_bus *);
+#ifdef CONFIG_SND_HDA_POWER_SAVE
+       /* notify power-up/down from codec to controller */
+       void (*pm_notify)(struct hda_codec *codec);
+#endif
 };
 
 /* template to pass to the bus constructor */
@@ -448,6 +506,9 @@ struct hda_bus {
        struct hda_bus_unsolicited *unsol;
 
        struct snd_info_entry *proc;
+
+       /* misc op flags */
+       unsigned int needs_damn_long_delay :1;
 };
 
 /*
@@ -462,6 +523,7 @@ struct hda_codec_preset {
        unsigned int subs;
        unsigned int subs_mask;
        unsigned int rev;
+       hda_nid_t afg, mfg;
        const char *name;
        int (*patch)(struct hda_codec *codec);
 };
@@ -473,10 +535,13 @@ struct hda_codec_ops {
        int (*init)(struct hda_codec *codec);
        void (*free)(struct hda_codec *codec);
        void (*unsol_event)(struct hda_codec *codec, unsigned int res);
-#ifdef CONFIG_PM
+#ifdef SND_HDA_NEEDS_RESUME
        int (*suspend)(struct hda_codec *codec, pm_message_t state);
        int (*resume)(struct hda_codec *codec);
 #endif
+#ifdef CONFIG_SND_HDA_POWER_SAVE
+       int (*check_power_status)(struct hda_codec *codec, hda_nid_t nid);
+#endif
 };
 
 /* record for amp information cache */
@@ -525,11 +590,21 @@ struct hda_pcm_stream {
        struct hda_pcm_ops ops;
 };
 
+/* PCM types */
+enum {
+       HDA_PCM_TYPE_AUDIO,
+       HDA_PCM_TYPE_SPDIF,
+       HDA_PCM_TYPE_HDMI,
+       HDA_PCM_TYPE_MODEM,
+       HDA_PCM_NTYPES
+};
+
 /* for PCM creation */
 struct hda_pcm {
        char *name;
        struct hda_pcm_stream stream[2];
-       unsigned int is_modem;  /* modem codec? */
+       unsigned int pcm_type;  /* HDA_PCM_TYPE_XXX */
+       int device;     /* assigned device number */
 };
 
 /* codec information */
@@ -552,11 +627,6 @@ struct hda_codec {
        /* set by patch */
        struct hda_codec_ops patch_ops;
 
-       /* resume phase - all controls should update even if
-        * the values are not changed
-        */
-       unsigned int in_resume;
-
        /* PCM to create, set by patch_ops.build_pcms callback */
        unsigned int num_pcms;
        struct hda_pcm *pcm_info;
@@ -578,6 +648,13 @@ struct hda_codec {
        unsigned int spdif_in_enable;   /* SPDIF input enable? */
 
        struct snd_hwdep *hwdep;        /* assigned hwdep device */
+
+#ifdef CONFIG_SND_HDA_POWER_SAVE
+       unsigned int power_on :1;       /* current (global) power-state */
+       unsigned int power_transition :1; /* power-state in transition */
+       int power_count;        /* current (global) power refcount */
+       struct delayed_work power_work; /* delayed task for powerdown */
+#endif
 };
 
 /* direction */
@@ -622,11 +699,16 @@ void snd_hda_sequence_write(struct hda_codec *codec,
 int snd_hda_queue_unsol_event(struct hda_bus *bus, u32 res, u32 res_ex);
 
 /* cached write */
+#ifdef SND_HDA_NEEDS_RESUME
 int snd_hda_codec_write_cache(struct hda_codec *codec, hda_nid_t nid,
                              int direct, unsigned int verb, unsigned int parm);
 void snd_hda_sequence_write_cache(struct hda_codec *codec,
                                  const struct hda_verb *seq);
 void snd_hda_codec_resume_cache(struct hda_codec *codec);
+#else
+#define snd_hda_codec_write_cache      snd_hda_codec_write
+#define snd_hda_sequence_write_cache   snd_hda_sequence_write
+#endif
 
 /*
  * Mixer
@@ -640,6 +722,7 @@ int snd_hda_build_pcms(struct hda_bus *bus);
 void snd_hda_codec_setup_stream(struct hda_codec *codec, hda_nid_t nid,
                                u32 stream_tag,
                                int channel_id, int format);
+void snd_hda_codec_cleanup_stream(struct hda_codec *codec, hda_nid_t nid);
 unsigned int snd_hda_calc_stream_format(unsigned int rate,
                                        unsigned int channels,
                                        unsigned int format,
@@ -662,4 +745,19 @@ int snd_hda_suspend(struct hda_bus *bus, pm_message_t state);
 int snd_hda_resume(struct hda_bus *bus);
 #endif
 
+/*
+ * power saving
+ */
+#ifdef CONFIG_SND_HDA_POWER_SAVE
+void snd_hda_power_up(struct hda_codec *codec);
+void snd_hda_power_down(struct hda_codec *codec);
+#define snd_hda_codec_needs_resume(codec) codec->power_count
+int snd_hda_codecs_inuse(struct hda_bus *bus);
+#else
+static inline void snd_hda_power_up(struct hda_codec *codec) {}
+static inline void snd_hda_power_down(struct hda_codec *codec) {}
+#define snd_hda_codec_needs_resume(codec) 1
+#define snd_hda_codecs_inuse(bus) 1
+#endif
+
 #endif /* __SOUND_HDA_CODEC_H */