#ifndef __HDA_HDMI_LOCAL_H
#define __HDA_HDMI_LOCAL_H
#include <sound/core.h>
#include <sound/jack.h>
#include <sound/hdaudio.h>
#include <sound/hda_i915.h>
#include <sound/hda_chmap.h>
#include <sound/hda_codec.h>
#include "hda_local.h"
struct hdmi_spec_per_cvt {
hda_nid_t cvt_nid;
bool assigned;
bool silent_stream;
unsigned int channels_min;
unsigned int channels_max;
u32 rates;
u64 formats;
unsigned int maxbps;
};
#define HDA_MAX_CONNECTIONS 32
struct hdmi_spec_per_pin {
hda_nid_t pin_nid;
int dev_id;
int pin_nid_idx;
int num_mux_nids;
hda_nid_t mux_nids[HDA_MAX_CONNECTIONS];
int mux_idx;
hda_nid_t cvt_nid;
struct hda_codec *codec;
struct hdmi_eld sink_eld;
struct mutex lock;
struct delayed_work work;
struct hdmi_pcm *pcm;
int pcm_idx;
int prev_pcm_idx;
int repoll_count;
bool setup;
bool silent_stream;
int channels;
bool non_pcm;
bool chmap_set;
unsigned char chmap[8];
#ifdef CONFIG_SND_PROC_FS
struct snd_info_entry *proc_entry;
#endif
};
struct hdmi_ops {
int (*pin_get_eld)(struct hda_codec *codec, hda_nid_t pin_nid,
int dev_id, unsigned char *buf, int *eld_size);
void (*pin_setup_infoframe)(struct hda_codec *codec, hda_nid_t pin_nid,
int dev_id,
int ca, int active_channels, int conn_type);
int (*pin_hbr_setup)(struct hda_codec *codec, hda_nid_t pin_nid,
int dev_id, bool hbr);
int (*setup_stream)(struct hda_codec *codec, hda_nid_t cvt_nid,
hda_nid_t pin_nid, int dev_id, u32 stream_tag,
int format);
void (*pin_cvt_fixup)(struct hda_codec *codec,
struct hdmi_spec_per_pin *per_pin,
hda_nid_t cvt_nid);
void (*silent_stream)(struct hda_codec *codec,
struct hdmi_spec_per_pin *per_pin,
bool enable);
};
struct hdmi_pcm {
struct hda_pcm *pcm;
struct snd_jack *jack;
struct snd_kcontrol *eld_ctl;
};
enum {
SILENT_STREAM_OFF = 0,
SILENT_STREAM_KAE,
SILENT_STREAM_I915,
};
struct hdmi_spec {
struct hda_codec *codec;
int num_cvts;
struct snd_array cvts;
hda_nid_t cvt_nids[4];
int num_pins;
int num_nids;
int dev_num;
struct snd_array pins;
struct hdmi_pcm pcm_rec[8];
struct mutex pcm_lock;
struct mutex bind_lock;
unsigned long pcm_bitmap;
int pcm_used;
unsigned long pcm_in_use;
struct hdmi_eld temp_eld;
struct hdmi_ops ops;
bool dyn_pin_out;
bool static_pcm_mapping;
bool hdmi_intr_trig_ctrl;
bool nv_dp_workaround;
bool intel_hsw_fixup;
struct hda_multi_out multiout;
struct hda_pcm_stream pcm_playback;
bool use_acomp_notifier;
bool acomp_registered;
bool force_connect;
struct drm_audio_component_audio_ops drm_audio_ops;
int (*port2pin)(struct hda_codec *codec, int port);
struct hdac_chmap chmap;
hda_nid_t vendor_nid;
const int *port_map;
int port_num;
int silent_stream_type;
const struct snd_pcm_hw_constraint_list *hw_constraints_channels;
};
#ifdef CONFIG_SND_HDA_COMPONENT
static inline bool codec_has_acomp(struct hda_codec *codec)
{
struct hdmi_spec *spec = codec->spec;
return spec->use_acomp_notifier;
}
#else
#define codec_has_acomp(codec) false
#endif
struct hdmi_audio_infoframe {
u8 type;
u8 ver;
u8 len;
u8 checksum;
u8 CC02_CT47;
u8 SS01_SF24;
u8 CXT04;
u8 CA;
u8 LFEPBL01_LSV36_DM_INH7;
};
struct dp_audio_infoframe {
u8 type;
u8 len;
u8 ver;
u8 CC02_CT47;
u8 SS01_SF24;
u8 CXT04;
u8 CA;
u8 LFEPBL01_LSV36_DM_INH7;
};
union audio_infoframe {
struct hdmi_audio_infoframe hdmi;
struct dp_audio_infoframe dp;
DECLARE_FLEX_ARRAY(u8, bytes);
};
#ifdef LIMITED_RATE_FMT_SUPPORT
#define SUPPORTED_RATES SNDRV_PCM_RATE_48000
#define SUPPORTED_MAXBPS 16
#define SUPPORTED_FORMATS SNDRV_PCM_FMTBIT_S16_LE
#else
#define SUPPORTED_RATES \
(SNDRV_PCM_RATE_32000 | SNDRV_PCM_RATE_44100 | SNDRV_PCM_RATE_48000 |\
SNDRV_PCM_RATE_88200 | SNDRV_PCM_RATE_96000 | SNDRV_PCM_RATE_176400 |\
SNDRV_PCM_RATE_192000)
#define SUPPORTED_MAXBPS 24
#define SUPPORTED_FORMATS \
(SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S32_LE)
#endif
#define get_pin(spec, idx) \
((struct hdmi_spec_per_pin *)snd_array_elem(&spec->pins, idx))
#define get_cvt(spec, idx) \
((struct hdmi_spec_per_cvt *)snd_array_elem(&spec->cvts, idx))
#define get_hdmi_pcm(spec, idx) (&(spec)->pcm_rec[idx])
#define get_pcm_rec(spec, idx) (get_hdmi_pcm(spec, idx)->pcm)
int snd_hda_hdmi_generic_alloc(struct hda_codec *codec);
int snd_hda_hdmi_parse_codec(struct hda_codec *codec);
int snd_hda_hdmi_generic_probe(struct hda_codec *codec);
void snd_hda_hdmi_generic_remove(struct hda_codec *codec);
int snd_hda_hdmi_generic_build_pcms(struct hda_codec *codec);
int snd_hda_hdmi_generic_build_controls(struct hda_codec *codec);
int snd_hda_hdmi_generic_init(struct hda_codec *codec);
int snd_hda_hdmi_generic_suspend(struct hda_codec *codec);
int snd_hda_hdmi_generic_resume(struct hda_codec *codec);
void snd_hda_hdmi_generic_unsol_event(struct hda_codec *codec, unsigned int res);
int snd_hda_hdmi_pin_id_to_pin_index(struct hda_codec *codec,
hda_nid_t pin_nid, int dev_id);
#define pin_id_to_pin_index(codec, pin, dev) \
snd_hda_hdmi_pin_id_to_pin_index(codec, pin, dev)
int snd_hda_hdmi_generic_init_per_pins(struct hda_codec *codec);
void snd_hda_hdmi_generic_spec_free(struct hda_codec *codec);
int snd_hda_hdmi_setup_stream(struct hda_codec *codec,
hda_nid_t cvt_nid,
hda_nid_t pin_nid, int dev_id,
u32 stream_tag, int format);
int snd_hda_hdmi_generic_pcm_prepare(struct hda_pcm_stream *hinfo,
struct hda_codec *codec,
unsigned int stream_tag,
unsigned int format,
struct snd_pcm_substream *substream);
int snd_hda_hdmi_generic_pcm_cleanup(struct hda_pcm_stream *hinfo,
struct hda_codec *codec,
struct snd_pcm_substream *substream);
void snd_hda_hdmi_check_presence_and_report(struct hda_codec *codec,
hda_nid_t nid, int dev_id);
void snd_hda_hdmi_setup_audio_infoframe(struct hda_codec *codec,
struct hdmi_spec_per_pin *per_pin,
bool non_pcm);
void snd_hda_hdmi_setup_drm_audio_ops(struct hda_codec *codec,
const struct drm_audio_component_audio_ops *ops);
void snd_hda_hdmi_acomp_init(struct hda_codec *codec,
const struct drm_audio_component_audio_ops *ops,
int (*port2pin)(struct hda_codec *, int));
void snd_hda_hdmi_acomp_pin_eld_notify(void *audio_ptr, int port, int dev_id);
int snd_hda_hdmi_acomp_master_bind(struct device *dev,
struct drm_audio_component *acomp);
void snd_hda_hdmi_acomp_master_unbind(struct device *dev,
struct drm_audio_component *acomp);
int snd_hda_hdmi_simple_probe(struct hda_codec *codec,
hda_nid_t cvt_nid, hda_nid_t pin_nid);
void snd_hda_hdmi_simple_remove(struct hda_codec *codec);
int snd_hda_hdmi_simple_build_pcms(struct hda_codec *codec);
int snd_hda_hdmi_simple_build_controls(struct hda_codec *codec);
int snd_hda_hdmi_simple_init(struct hda_codec *codec);
void snd_hda_hdmi_simple_unsol_event(struct hda_codec *codec,
unsigned int res);
int snd_hda_hdmi_simple_pcm_open(struct hda_pcm_stream *hinfo,
struct hda_codec *codec,
struct snd_pcm_substream *substream);
#endif