Re: [Intel-gfx] [PATCH 4/4] ALSA: hda - Add display audio routing API for haswell

2013-06-17 Thread Wang, Xingchao

 -Original Message-
 From: Takashi Iwai [mailto:ti...@suse.de]
 Sent: Monday, June 17, 2013 5:04 PM
 To: Wang Xingchao
 Cc: daniel.vet...@ffwll.ch; alsa-de...@alsa-project.org;
 intel-gfx@lists.freedesktop.org; david.hennings...@canonical.com; Wang,
 Xingchao
 Subject: Re: [PATCH 4/4] ALSA: hda - Add display audio routing API for haswell
 
 At Fri, 14 Jun 2013 23:20:29 +0800,
 Wang Xingchao wrote:
 
  ALSA side use these apis to know display audio routing map in gfx
  side. And use the API to disable unused pin's audio output.
 
 Adding more and more such exported functions doesn't look scaling.
 Better to define an ops struct and export it.

Thanks Takashi, under discussion with Daniel in another thread, need 
improvement to make the API clean.
I will rework the patch when get some agreement.

Thanks
--xingchao
 
 
 Takashi
 
 
  Signed-off-by: Wang Xingchao xingchao.w...@linux.intel.com
  ---
   sound/pci/hda/hda_i915.c   | 83
 ++
   sound/pci/hda/hda_i915.h   |  4 +++
   sound/pci/hda/patch_hdmi.c | 20 +--
   3 files changed, 104 insertions(+), 3 deletions(-)
 
  diff --git a/sound/pci/hda/hda_i915.c b/sound/pci/hda/hda_i915.c index
  76c13d5..7ac446f 100644
  --- a/sound/pci/hda/hda_i915.c
  +++ b/sound/pci/hda/hda_i915.c
  @@ -22,9 +22,73 @@
   #include drm/i915_powerwell.h
   #include hda_i915.h
 
  +/* Haswell power well */
   static void (*get_power)(void);
   static void (*put_power)(void);
 
  +/* Haswell audio routing */
  +static int (*get_using_pipe)(int);
  +static int (*disable_unused_pipe)(int, int *); static int
  +(*restore_eld)(void);
  +
  +#define i915_pipe_name(p) ((p) + 'A')
  +
  +static int busy_pins[3] = {0, 0, 0};
  +
  +int hdmi_disable_unused_pipe(int pin_idx, int pipe_idx) {
  +   busy_pins[pin_idx] = 1;
  +   if (disable_unused_pipe)
  +   disable_unused_pipe(pipe_idx, busy_pins);
  +
  +   return 0;
  +}
  +EXPORT_SYMBOL(hdmi_disable_unused_pipe);
  +
  +void hdmi_restore_pineld(int pin_idx) {
  +   busy_pins[pin_idx] = 0;
  +   if (restore_eld)
  +   restore_eld();
  +}
  +EXPORT_SYMBOL(hdmi_restore_pineld);
  +
  +int hdmi_get_using_pipe(int pin_idx)
  +{
  +   int pipe = -1;
  +
  +   if (get_using_pipe)
  +   pipe = get_using_pipe(pin_idx);
  +
  +   if (pipe != -1)
  +   snd_printd(HDMI: pin %d get using pipe %c\n, pin_idx,
  +i915_pipe_name(pipe));
  +
  +   return pipe;
  +}
  +EXPORT_SYMBOL(hdmi_get_using_pipe);
  +
  +static int init_audio_routing(void)
  +{
  +   get_using_pipe = symbol_request(i915_using_pipe);
  +   if (!get_using_pipe)
  +   return -ENODEV;
  +
  +   disable_unused_pipe = symbol_request(i915_disable_pipe);
  +   if (!disable_unused_pipe) {
  +   get_using_pipe = NULL;
  +   return -ENODEV;
  +   }
  +
  +   restore_eld = symbol_request(i915_restore_pineld);
  +   if (!restore_eld) {
  +   restore_eld = NULL;
  +   get_using_pipe = NULL;
  +   return -ENODEV;
  +   }
  +
  +   return 0;
  +}
  +
   void hda_display_power(bool enable)
   {
  if (!get_power || !put_power)
  @@ -57,6 +121,10 @@ int hda_i915_init(void)
 
  snd_printd(HDA driver get symbol successfully from i915 module\n);
 
  +   err = init_audio_routing();
  +   if (err  0)
  +   snd_printd(HDA driver get audior routing APIs failed!\n);
  +
  return err;
   }
 
  @@ -71,5 +139,20 @@ int hda_i915_exit(void)
  put_power = NULL;
  }
 
  +   if (get_using_pipe) {
  +   symbol_put(get_using_pipe);
  +   get_using_pipe = NULL;
  +   }
  +
  +   if (disable_unused_pipe) {
  +   symbol_put(disable_unused_pipe);
  +   disable_unused_pipe = NULL;
  +   }
  +
  +   if (restore_eld) {
  +   symbol_put(restore_eld);
  +   restore_eld = NULL;
  +   }
  +
  return 0;
   }
  diff --git a/sound/pci/hda/hda_i915.h b/sound/pci/hda/hda_i915.h index
  5a63da2..52d6f09 100644
  --- a/sound/pci/hda/hda_i915.h
  +++ b/sound/pci/hda/hda_i915.h
  @@ -32,4 +32,8 @@ static inline int hda_i915_exit(void)  }  #endif
 
  +extern int hdmi_get_using_pipe(int pin_idx); extern int
  +hdmi_disable_unused_pipe(int pin_idx, int pipe_idx); extern void
  +hdmi_restore_pineld(int pin_idx);
  +
   #endif
  diff --git a/sound/pci/hda/patch_hdmi.c b/sound/pci/hda/patch_hdmi.c
  index d766f40..2a1e977 100644
  --- a/sound/pci/hda/patch_hdmi.c
  +++ b/sound/pci/hda/patch_hdmi.c
  @@ -39,6 +39,7 @@
   #include hda_codec.h
   #include hda_local.h
   #include hda_jack.h
  +#include hda_i915.h
 
   static bool static_hdmi_pcm;
   module_param(static_hdmi_pcm, bool, 0644); @@ -1131,6 +1132,7 @@
  static int hdmi_pcm_open(struct hda_pcm_stream *hinfo,
  struct hdmi_spec_per_pin *per_pin;
  struct hdmi_eld *eld;
  struct hdmi_spec_per_cvt *per_cvt = NULL;
  +   int pipe_idx;
 
  /* Validate hinfo */
  pin_idx = hinfo_to_pin_index(spec, hinfo); @@ -1139,12 +1141,21 @@
  static int 

[Intel-gfx] [PATCH 4/4] ALSA: hda - Add display audio routing API for haswell

2013-06-14 Thread Wang Xingchao
ALSA side use these apis to know display audio routing map
in gfx side. And use the API to disable unused pin's audio output.

Signed-off-by: Wang Xingchao xingchao.w...@linux.intel.com
---
 sound/pci/hda/hda_i915.c   | 83 ++
 sound/pci/hda/hda_i915.h   |  4 +++
 sound/pci/hda/patch_hdmi.c | 20 +--
 3 files changed, 104 insertions(+), 3 deletions(-)

diff --git a/sound/pci/hda/hda_i915.c b/sound/pci/hda/hda_i915.c
index 76c13d5..7ac446f 100644
--- a/sound/pci/hda/hda_i915.c
+++ b/sound/pci/hda/hda_i915.c
@@ -22,9 +22,73 @@
 #include drm/i915_powerwell.h
 #include hda_i915.h
 
+/* Haswell power well */
 static void (*get_power)(void);
 static void (*put_power)(void);
 
+/* Haswell audio routing */
+static int (*get_using_pipe)(int);
+static int (*disable_unused_pipe)(int, int *);
+static int (*restore_eld)(void);
+
+#define i915_pipe_name(p) ((p) + 'A')
+
+static int busy_pins[3] = {0, 0, 0};
+
+int hdmi_disable_unused_pipe(int pin_idx, int pipe_idx)
+{
+   busy_pins[pin_idx] = 1;
+   if (disable_unused_pipe)
+   disable_unused_pipe(pipe_idx, busy_pins);
+
+   return 0;
+}
+EXPORT_SYMBOL(hdmi_disable_unused_pipe);
+
+void hdmi_restore_pineld(int pin_idx)
+{
+   busy_pins[pin_idx] = 0;
+   if (restore_eld)
+   restore_eld();
+}
+EXPORT_SYMBOL(hdmi_restore_pineld);
+
+int hdmi_get_using_pipe(int pin_idx)
+{
+   int pipe = -1;
+
+   if (get_using_pipe)
+   pipe = get_using_pipe(pin_idx);
+
+   if (pipe != -1)
+   snd_printd(HDMI: pin %d get using pipe %c\n, pin_idx, 
i915_pipe_name(pipe));
+
+   return pipe;
+}
+EXPORT_SYMBOL(hdmi_get_using_pipe);
+
+static int init_audio_routing(void)
+{
+   get_using_pipe = symbol_request(i915_using_pipe);
+   if (!get_using_pipe)
+   return -ENODEV;
+
+   disable_unused_pipe = symbol_request(i915_disable_pipe);
+   if (!disable_unused_pipe) {
+   get_using_pipe = NULL;
+   return -ENODEV;
+   }
+
+   restore_eld = symbol_request(i915_restore_pineld);
+   if (!restore_eld) {
+   restore_eld = NULL;
+   get_using_pipe = NULL;
+   return -ENODEV;
+   }
+
+   return 0;
+}
+
 void hda_display_power(bool enable)
 {
if (!get_power || !put_power)
@@ -57,6 +121,10 @@ int hda_i915_init(void)
 
snd_printd(HDA driver get symbol successfully from i915 module\n);
 
+   err = init_audio_routing();
+   if (err  0)
+   snd_printd(HDA driver get audior routing APIs failed!\n);
+
return err;
 }
 
@@ -71,5 +139,20 @@ int hda_i915_exit(void)
put_power = NULL;
}
 
+   if (get_using_pipe) {
+   symbol_put(get_using_pipe);
+   get_using_pipe = NULL;
+   }
+
+   if (disable_unused_pipe) {
+   symbol_put(disable_unused_pipe);
+   disable_unused_pipe = NULL;
+   }
+
+   if (restore_eld) {
+   symbol_put(restore_eld);
+   restore_eld = NULL;
+   }
+
return 0;
 }
diff --git a/sound/pci/hda/hda_i915.h b/sound/pci/hda/hda_i915.h
index 5a63da2..52d6f09 100644
--- a/sound/pci/hda/hda_i915.h
+++ b/sound/pci/hda/hda_i915.h
@@ -32,4 +32,8 @@ static inline int hda_i915_exit(void)
 }
 #endif
 
+extern int hdmi_get_using_pipe(int pin_idx);
+extern int hdmi_disable_unused_pipe(int pin_idx, int pipe_idx);
+extern void hdmi_restore_pineld(int pin_idx);
+
 #endif
diff --git a/sound/pci/hda/patch_hdmi.c b/sound/pci/hda/patch_hdmi.c
index d766f40..2a1e977 100644
--- a/sound/pci/hda/patch_hdmi.c
+++ b/sound/pci/hda/patch_hdmi.c
@@ -39,6 +39,7 @@
 #include hda_codec.h
 #include hda_local.h
 #include hda_jack.h
+#include hda_i915.h
 
 static bool static_hdmi_pcm;
 module_param(static_hdmi_pcm, bool, 0644);
@@ -1131,6 +1132,7 @@ static int hdmi_pcm_open(struct hda_pcm_stream *hinfo,
struct hdmi_spec_per_pin *per_pin;
struct hdmi_eld *eld;
struct hdmi_spec_per_cvt *per_cvt = NULL;
+   int pipe_idx;
 
/* Validate hinfo */
pin_idx = hinfo_to_pin_index(spec, hinfo);
@@ -1139,12 +1141,21 @@ static int hdmi_pcm_open(struct hda_pcm_stream *hinfo,
per_pin = get_pin(spec, pin_idx);
eld = per_pin-sink_eld;
 
+   if (codec-vendor_id == 0x80862807) {
+   hsw_verify_cvt_D0(spec, codec);
+
+   pipe_idx = hdmi_get_using_pipe(pin_idx);
+   if (pipe_idx  0)
+   snd_printdd(HDMI: Pin %d has no valid pipe in use\n, 
pin_idx);
+   else {
+   hdmi_disable_unused_pipe(pin_idx, pipe_idx);
+   msleep(10);
+   }
+   }
+
if (!eld-monitor_present || !eld-eld_valid)
return -EIO;
 
-   if (codec-vendor_id == 0x80862807)
-   hsw_verify_cvt_D0(spec, codec);
-   
/* Dynamically assign converter to