Skip to content

Commit

Permalink
ALSA: hda - Register chmap obj as priv data instead of codec
Browse files Browse the repository at this point in the history
With this chmap object is added as private data and new ops are
added to access driver specific chmap.

Signed-off-by: Subhransu S. Prusty <subhransu.s.prusty@intel.com>
Signed-off-by: Vinod Koul <vinod.koul@intel.com>
Signed-off-by: Takashi Iwai <tiwai@suse.de>
  • Loading branch information
Subhransu S. Prusty authored and Takashi Iwai committed Mar 7, 2016
1 parent 67b90cb commit 9b3dc8a
Show file tree
Hide file tree
Showing 2 changed files with 65 additions and 34 deletions.
6 changes: 6 additions & 0 deletions include/sound/hda_chmap.h
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,12 @@ struct hdac_chmap_ops {

/* check that the user-given chmap is supported */
int (*chmap_validate)(int ca, int channels, unsigned char *chmap);

void (*get_chmap)(struct hdac_device *hdac, int pcm_idx,
unsigned char *chmap);
void (*set_chmap)(struct hdac_device *hdac, int pcm_idx,
unsigned char *chmap, int prepared);
bool (*is_pcm_attached)(struct hdac_device *hdac, int pcm_idx);
};

struct hdac_chmap {
Expand Down
93 changes: 59 additions & 34 deletions sound/pci/hda/patch_hdmi.c
Original file line number Diff line number Diff line change
Expand Up @@ -100,8 +100,6 @@ struct hdmi_spec_per_pin {
#endif
};

struct cea_channel_speaker_allocation;

/* operations used by generic code that can be overridden by patches */
struct hdmi_ops {
int (*pin_get_eld)(struct hda_codec *codec, hda_nid_t pin_nid,
Expand Down Expand Up @@ -2350,9 +2348,7 @@ static int hdmi_chmap_ctl_info(struct snd_kcontrol *kcontrol,
struct snd_ctl_elem_info *uinfo)
{
struct snd_pcm_chmap *info = snd_kcontrol_chip(kcontrol);
struct hda_codec *codec = info->private_data;
struct hdmi_spec *spec = codec->spec;
struct hdac_chmap *chmap = &spec->chmap;
struct hdac_chmap *chmap = info->private_data;

uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER;
uinfo->count = chmap->channels_max;
Expand Down Expand Up @@ -2389,13 +2385,49 @@ static void hdmi_cea_alloc_to_tlv_chmap(struct cea_channel_speaker_allocation *c
WARN_ON(count != channels);
}

static void hdmi_get_chmap(struct hdac_device *hdac, int pcm_idx,
unsigned char *chmap)
{
struct hda_codec *codec = container_of(hdac, struct hda_codec, core);
struct hdmi_spec *spec = codec->spec;
struct hdmi_spec_per_pin *per_pin = pcm_idx_to_pin(spec, pcm_idx);

/* chmap is already set to 0 in caller */
if (!per_pin)
return;

memcpy(chmap, per_pin->chmap, ARRAY_SIZE(per_pin->chmap));
}

static void hdmi_set_chmap(struct hdac_device *hdac, int pcm_idx,
unsigned char *chmap, int prepared)
{
struct hda_codec *codec = container_of(hdac, struct hda_codec, core);
struct hdmi_spec *spec = codec->spec;
struct hdmi_spec_per_pin *per_pin = pcm_idx_to_pin(spec, pcm_idx);

mutex_lock(&per_pin->lock);
per_pin->chmap_set = true;
memcpy(per_pin->chmap, chmap, ARRAY_SIZE(per_pin->chmap));
if (prepared)
hdmi_setup_audio_infoframe(codec, per_pin, per_pin->non_pcm);
mutex_unlock(&per_pin->lock);
}

static bool is_hdmi_pcm_attached(struct hdac_device *hdac, int pcm_idx)
{
struct hda_codec *codec = container_of(hdac, struct hda_codec, core);
struct hdmi_spec *spec = codec->spec;
struct hdmi_spec_per_pin *per_pin = pcm_idx_to_pin(spec, pcm_idx);

return per_pin ? true:false;
}

static int hdmi_chmap_ctl_tlv(struct snd_kcontrol *kcontrol, int op_flag,
unsigned int size, unsigned int __user *tlv)
{
struct snd_pcm_chmap *info = snd_kcontrol_chip(kcontrol);
struct hda_codec *codec = info->private_data;
struct hdmi_spec *spec = codec->spec;
struct hdac_chmap *chmap = &spec->chmap;
struct hdac_chmap *chmap = info->private_data;
unsigned int __user *dst;
int chs, count = 0;

Expand Down Expand Up @@ -2444,42 +2476,35 @@ static int hdmi_chmap_ctl_get(struct snd_kcontrol *kcontrol,
struct snd_ctl_elem_value *ucontrol)
{
struct snd_pcm_chmap *info = snd_kcontrol_chip(kcontrol);
struct hda_codec *codec = info->private_data;
struct hdmi_spec *spec = codec->spec;
struct hdac_chmap *chmap = &spec->chmap;
struct hdac_chmap *chmap = info->private_data;
int pcm_idx = kcontrol->private_value;
struct hdmi_spec_per_pin *per_pin = pcm_idx_to_pin(spec, pcm_idx);
unsigned char pcm_chmap[8];
int i;

if (!per_pin) {
for (i = 0; i < chmap->channels_max; i++)
ucontrol->value.integer.value[i] = 0;
return 0;
}
memset(pcm_chmap, 0, sizeof(pcm_chmap));
chmap->ops.get_chmap(chmap->hdac, pcm_idx, pcm_chmap);

for (i = 0; i < sizeof(chmap); i++)
ucontrol->value.integer.value[i] = pcm_chmap[i];

for (i = 0; i < ARRAY_SIZE(per_pin->chmap); i++)
ucontrol->value.integer.value[i] = per_pin->chmap[i];
return 0;
}

static int hdmi_chmap_ctl_put(struct snd_kcontrol *kcontrol,
struct snd_ctl_elem_value *ucontrol)
{
struct snd_pcm_chmap *info = snd_kcontrol_chip(kcontrol);
struct hda_codec *codec = info->private_data;
struct hdmi_spec *spec = codec->spec;
struct hdac_chmap *hchmap = &spec->chmap;
struct hdac_chmap *hchmap = info->private_data;
int pcm_idx = kcontrol->private_value;
struct hdmi_spec_per_pin *per_pin = pcm_idx_to_pin(spec, pcm_idx);
unsigned int ctl_idx;
struct snd_pcm_substream *substream;
unsigned char chmap[8];
unsigned char chmap[8], per_pin_chmap[8];
int i, err, ca, prepared = 0;

/* No monitor is connected in dyn_pcm_assign.
* It's invalid to setup the chmap
*/
if (!per_pin)
if (!hchmap->ops.is_pcm_attached(hchmap->hdac, pcm_idx))
return 0;

ctl_idx = snd_ctl_get_ioffidx(kcontrol, &ucontrol->id);
Expand All @@ -2499,7 +2524,9 @@ static int hdmi_chmap_ctl_put(struct snd_kcontrol *kcontrol,
memset(chmap, 0, sizeof(chmap));
for (i = 0; i < ARRAY_SIZE(chmap); i++)
chmap[i] = ucontrol->value.integer.value[i];
if (!memcmp(chmap, per_pin->chmap, sizeof(chmap)))

hchmap->ops.get_chmap(hchmap->hdac, pcm_idx, per_pin_chmap);
if (!memcmp(chmap, per_pin_chmap, sizeof(chmap)))
return 0;
ca = hdmi_manual_channel_allocation(ARRAY_SIZE(chmap), chmap);
if (ca < 0)
Expand All @@ -2509,12 +2536,8 @@ static int hdmi_chmap_ctl_put(struct snd_kcontrol *kcontrol,
if (err)
return err;
}
mutex_lock(&per_pin->lock);
per_pin->chmap_set = true;
memcpy(per_pin->chmap, chmap, sizeof(chmap));
if (prepared)
hdmi_setup_audio_infoframe(codec, per_pin, per_pin->non_pcm);
mutex_unlock(&per_pin->lock);

hchmap->ops.set_chmap(hchmap->hdac, pcm_idx, chmap, prepared);

return 0;
}
Expand Down Expand Up @@ -2672,7 +2695,7 @@ static int generic_hdmi_build_controls(struct hda_codec *codec)
if (err < 0)
return err;
/* override handlers */
chmap->private_data = codec;
chmap->private_data = &spec->chmap;
kctl = chmap->kctl;
for (i = 0; i < kctl->count; i++)
kctl->vd[i].access |= SNDRV_CTL_ELEM_ACCESS_WRITE;
Expand Down Expand Up @@ -2801,9 +2824,11 @@ static const struct hdmi_ops generic_standard_hdmi_ops = {
static const struct hdac_chmap_ops chmap_ops = {
.chmap_cea_alloc_validate_get_type = hdmi_chmap_cea_alloc_validate_get_type,
.cea_alloc_to_tlv_chmap = hdmi_cea_alloc_to_tlv_chmap,
.get_chmap = hdmi_get_chmap,
.set_chmap = hdmi_set_chmap,
.is_pcm_attached = is_hdmi_pcm_attached,
};


static void intel_haswell_fixup_connect_list(struct hda_codec *codec,
hda_nid_t nid)
{
Expand Down

0 comments on commit 9b3dc8a

Please sign in to comment.