diff options
Diffstat (limited to 'include/sound/hda_codec.h')
| -rw-r--r-- | include/sound/hda_codec.h | 112 |
1 files changed, 72 insertions, 40 deletions
diff --git a/include/sound/hda_codec.h b/include/sound/hda_codec.h index 82d9daa17851..5d9f0ef228af 100644 --- a/include/sound/hda_codec.h +++ b/include/sound/hda_codec.h @@ -18,9 +18,6 @@ #include <sound/hda_verbs.h> #include <sound/hda_regmap.h> -#define IS_BXT(pci) ((pci)->vendor == 0x8086 && (pci)->device == 0x5a98) -#define IS_CFL(pci) ((pci)->vendor == 0x8086 && (pci)->device == 0xa348) - /* * Structures */ @@ -30,6 +27,7 @@ struct hda_beep; struct hda_codec; struct hda_pcm; struct hda_pcm_stream; +struct hda_codec_ops; /* * codec bus @@ -59,6 +57,9 @@ struct hda_bus { unsigned int no_response_fallback:1; /* don't fallback at RIRB error */ unsigned int bus_probing :1; /* during probing process */ unsigned int keep_power:1; /* keep power up for notification */ + unsigned int jackpoll_in_suspend:1; /* keep jack polling during + * runtime suspend + */ int primary_dig_out_type; /* primary digital out PCM type */ unsigned int mixer_assigned; /* codec addr for mixer name */ @@ -69,28 +70,31 @@ struct hda_bus { /* * codec preset - * - * Known codecs have the patch to build and set up the controls/PCMs - * better than the generic parser. */ -typedef int (*hda_codec_patch_t)(struct hda_codec *); - + #define HDA_CODEC_ID_SKIP_PROBE 0x00000001 #define HDA_CODEC_ID_GENERIC_HDMI 0x00000101 #define HDA_CODEC_ID_GENERIC 0x00000201 -#define HDA_CODEC_REV_ENTRY(_vid, _rev, _name, _patch) \ +#define HDA_CODEC_ID_REV_MODEL(_vid, _rev, _name, _model) \ { .vendor_id = (_vid), .rev_id = (_rev), .name = (_name), \ - .api_version = HDA_DEV_LEGACY, \ - .driver_data = (unsigned long)(_patch) } -#define HDA_CODEC_ENTRY(_vid, _name, _patch) \ - HDA_CODEC_REV_ENTRY(_vid, 0, _name, _patch) + .api_version = HDA_DEV_LEGACY, .driver_data = (_model) } +#define HDA_CODEC_ID_MODEL(_vid, _name, _model) \ + HDA_CODEC_ID_REV_MODEL(_vid, 0, _name, _model) +#define HDA_CODEC_ID_REV(_vid, _rev, _name) \ + HDA_CODEC_ID_REV_MODEL(_vid, _rev, _name, 0) +#define HDA_CODEC_ID(_vid, _name) \ + HDA_CODEC_ID_REV(_vid, 0, _name) struct hda_codec_driver { struct hdac_driver core; const struct hda_device_id *id; + const struct hda_codec_ops *ops; }; +#define hda_codec_to_driver(codec) \ + container_of((codec)->core.dev.driver, struct hda_codec_driver, core.driver) + int __hda_codec_driver_register(struct hda_codec_driver *drv, const char *name, struct module *owner); #define hda_codec_driver_register(drv) \ @@ -100,20 +104,19 @@ void hda_codec_driver_unregister(struct hda_codec_driver *drv); module_driver(drv, hda_codec_driver_register, \ hda_codec_driver_unregister) -/* ops set by the preset patch */ +/* ops for hda codec driver */ struct hda_codec_ops { + int (*probe)(struct hda_codec *codec, const struct hda_device_id *id); + void (*remove)(struct hda_codec *codec); int (*build_controls)(struct hda_codec *codec); int (*build_pcms)(struct hda_codec *codec); int (*init)(struct hda_codec *codec); - void (*free)(struct hda_codec *codec); void (*unsol_event)(struct hda_codec *codec, unsigned int res); void (*set_power_state)(struct hda_codec *codec, hda_nid_t fg, unsigned int power_state); -#ifdef CONFIG_PM int (*suspend)(struct hda_codec *codec); int (*resume)(struct hda_codec *codec); int (*check_power_status)(struct hda_codec *codec, hda_nid_t nid); -#endif void (*stream_pm)(struct hda_codec *codec, hda_nid_t nid, bool on); }; @@ -141,6 +144,7 @@ struct hda_pcm_stream { hda_nid_t nid; /* default NID to query rates/formats/bps, or set up */ u32 rates; /* supported rates */ u64 formats; /* supported formats (SNDRV_PCM_FMTBIT_) */ + u32 subformats; /* for S32_LE format, SNDRV_PCM_SUBFMTBIT_* */ unsigned int maxbps; /* supported max. bit per sample */ const struct snd_pcm_chmap_elem *chmap; /* chmap to override */ struct hda_pcm_ops ops; @@ -182,10 +186,7 @@ struct hda_codec { const struct hda_device_id *preset; const char *modelname; /* model name for preset */ - /* set by patch */ - struct hda_codec_ops patch_ops; - - /* PCM to create, set by patch_ops.build_pcms callback */ + /* PCM to create, set by hda_codec_ops.build_pcms callback */ struct list_head pcm_list_head; refcount_t pcm_ref; wait_queue_head_t remove_sleep; @@ -196,6 +197,7 @@ struct hda_codec { /* beep device */ struct hda_beep *beep; unsigned int beep_mode; + bool beep_just_power_on; /* widget capabilities cache */ u32 *wcaps; @@ -228,7 +230,6 @@ struct hda_codec { /* misc flags */ unsigned int configured:1; /* codec was configured */ unsigned int in_freeing:1; /* being released */ - unsigned int registered:1; /* codec was registered */ unsigned int display_power_control:1; /* needs display power */ unsigned int spdif_status_reset :1; /* needs to toggle SPDIF for each * status change @@ -256,13 +257,12 @@ struct hda_codec { unsigned int link_down_at_suspend:1; /* link down at runtime suspend */ unsigned int relaxed_resume:1; /* don't resume forcibly for jack */ unsigned int forced_resume:1; /* forced resume for jack */ - unsigned int mst_no_extra_pcms:1; /* no backup PCMs for DP-MST */ + unsigned int no_stream_clean_at_suspend:1; /* do not clean streams at suspend */ + unsigned int ctl_dev_id:1; /* old control element id build behaviour */ -#ifdef CONFIG_PM unsigned long power_on_acct; unsigned long power_off_acct; unsigned long power_jiffies; -#endif /* filter the requested power state per nid */ unsigned int (*power_filter)(struct hda_codec *codec, hda_nid_t nid, @@ -291,8 +291,6 @@ struct hda_codec { #define dev_to_hda_codec(_dev) container_of(_dev, struct hda_codec, core.dev) #define hda_codec_dev(_dev) (&(_dev)->core.dev) -#define hdac_to_hda_priv(_hdac) \ - container_of(_hdac, struct hdac_hda_priv, codec.core) #define hdac_to_hda_codec(_hdac) container_of(_hdac, struct hda_codec, core) #define list_for_each_codec(c, bus) \ @@ -306,12 +304,19 @@ struct hda_codec { /* * constructors */ +__printf(3, 4) struct hda_codec * +snd_hda_codec_device_init(struct hda_bus *bus, unsigned int codec_addr, + const char *fmt, ...); int snd_hda_codec_new(struct hda_bus *bus, struct snd_card *card, unsigned int codec_addr, struct hda_codec **codecp); int snd_hda_codec_device_new(struct hda_bus *bus, struct snd_card *card, - unsigned int codec_addr, struct hda_codec *codec); + unsigned int codec_addr, struct hda_codec *codec, + bool snddev_managed); int snd_hda_codec_configure(struct hda_codec *codec); int snd_hda_codec_update_widgets(struct hda_codec *codec); +void snd_hda_codec_register(struct hda_codec *codec); +void snd_hda_codec_unregister(struct hda_codec *codec); +void snd_hda_codec_cleanup_for_unbind(struct hda_codec *codec); /* * low level functions @@ -355,8 +360,8 @@ int snd_hda_override_conn_list(struct hda_codec *codec, hda_nid_t nid, int nums, int snd_hda_get_conn_index(struct hda_codec *codec, hda_nid_t mux, hda_nid_t nid, int recursive); unsigned int snd_hda_get_num_devices(struct hda_codec *codec, hda_nid_t nid); -int snd_hda_get_devices(struct hda_codec *codec, hda_nid_t nid, - u8 *dev_list, int max_devices); +unsigned int snd_hda_get_devices(struct hda_codec *codec, hda_nid_t nid, + u8 *dev_list, unsigned int max_devices); int snd_hda_get_dev_select(struct hda_codec *codec, hda_nid_t nid); int snd_hda_set_dev_select(struct hda_codec *codec, hda_nid_t nid, int dev_id); @@ -443,8 +448,8 @@ void __snd_hda_codec_cleanup_stream(struct hda_codec *codec, hda_nid_t nid, #define snd_hda_codec_cleanup_stream(codec, nid) \ __snd_hda_codec_cleanup_stream(codec, nid, 0) -#define snd_hda_query_supported_pcm(codec, nid, ratesp, fmtsp, bpsp) \ - snd_hdac_query_supported_pcm(&(codec)->core, nid, ratesp, fmtsp, bpsp) +#define snd_hda_query_supported_pcm(codec, nid, ratesp, fmtsp, subfmtp, bpsp) \ + snd_hdac_query_supported_pcm(&(codec)->core, nid, ratesp, fmtsp, subfmtp, bpsp) #define snd_hda_is_supported_format(codec, nid, fmt) \ snd_hdac_is_supported_format(&(codec)->core, nid, fmt) @@ -475,10 +480,10 @@ extern const struct dev_pm_ops hda_codec_driver_pm; static inline int hda_call_check_power_status(struct hda_codec *codec, hda_nid_t nid) { -#ifdef CONFIG_PM - if (codec->patch_ops.check_power_status) - return codec->patch_ops.check_power_status(codec, nid); -#endif + struct hda_codec_driver *driver = hda_codec_to_driver(codec); + + if (driver->ops && driver->ops->check_power_status) + return driver->ops->check_power_status(codec, nid); return 0; } @@ -489,18 +494,45 @@ int hda_call_check_power_status(struct hda_codec *codec, hda_nid_t nid) #define snd_hda_power_up_pm(codec) snd_hdac_power_up_pm(&(codec)->core) #define snd_hda_power_down(codec) snd_hdac_power_down(&(codec)->core) #define snd_hda_power_down_pm(codec) snd_hdac_power_down_pm(&(codec)->core) -#ifdef CONFIG_PM +void snd_hda_codec_set_power_save(struct hda_codec *codec, int delay); void snd_hda_set_power_save(struct hda_bus *bus, int delay); void snd_hda_update_power_acct(struct hda_codec *codec); -#else -static inline void snd_hda_set_power_save(struct hda_bus *bus, int delay) {} -#endif static inline bool hda_codec_need_resume(struct hda_codec *codec) { return !codec->relaxed_resume && codec->jacktbl.used; } +/* + * PM with auto-cleanup: call like CLASS(snd_hda_power, pm)(codec) + * If the error handling is needed, refer pm.err. + */ +struct __hda_power_obj { + struct hda_codec *codec; + int err; +}; + +static inline struct __hda_power_obj __snd_hda_power_up(struct hda_codec *codec) +{ + struct __hda_power_obj T = { .codec = codec }; + T.err = snd_hda_power_up(codec); + return T; +} + +static inline struct __hda_power_obj __snd_hda_power_up_pm(struct hda_codec *codec) +{ + struct __hda_power_obj T = { .codec = codec }; + T.err = snd_hda_power_up_pm(codec); + return T; +} + +DEFINE_CLASS(snd_hda_power, struct __hda_power_obj, + snd_hda_power_down((_T).codec), __snd_hda_power_up(codec), + struct hda_codec *codec) +DEFINE_CLASS(snd_hda_power_pm, struct __hda_power_obj, + snd_hda_power_down_pm((_T).codec), __snd_hda_power_up_pm(codec), + struct hda_codec *codec) + #ifdef CONFIG_SND_HDA_PATCH_LOADER /* * patch firmware |
